MHEG5  18.9.0
MHEG5 Documentation
mh5listgroup.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2004 Ocean Blue Software Ltd
4  * Copyright © 2000 Koninklijke Philips Electronics N.V
5  *
6  * This file is part of a DTVKit Software Component
7  * You are permitted to copy, modify or distribute this file subject to the terms
8  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
9  *
10  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
11  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
12  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * If you or your organisation is not a member of DTVKit then you have access
15  * to this source code outside of the terms of the licence agreement
16  * and you are expected to delete this and any associated files immediately.
17  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
18  *******************************************************************************/
34 /*---includes for this file--------------------------------------------------*/
35 #include "mh5profile.h"
36 #include "mh5listgroup.h"
37 #include "mh5object.h" /* for actions */
38 #include "mh5gate.h"
39 #include "mh5variable.h" /* for actions */
40 #include "mh5memory.h" /* for constructor/destructor */
41 #include "mh5queue.h" /* Events */
42 #include "mh5debug.h"
43 #include "mh5final.h"
44 #include "mh5bitmap.h"
45 #include "mh5video.h"
46 #include "mh5rectangle.h"
47 #include "mh5hypertext.h"
48 #include "mh5entryfield.h"
49 #include "mh5slider.h"
50 #include "mh5dynamiclineart.h"
51 #ifndef MHEG5PROFILE_UK1_06
52 #include "mh5button.h"
53 #include "mh5hotspot.h"
54 #include "mh5pushbutton.h"
55 #include "mh5switchbutton.h"
56 #include "mh5rtgraphics.h"
57 #endif
58 
59 #include "mh5application.h"
60 #include "mh5scene.h"
61 
62 #ifdef MH5PRINTOUT
63 #include <string.h>
64 #endif
65 
66 /*---constant definitions for this file--------------------------------------*/
67 
68 
69 /*---local typedef structs for this file-------------------------------------*/
70 
71 /*---local (static) variable declarations for this file----------------------*/
72 
73 /*---local function definitions----------------------------------------------*/
74 
75 /*---global function definitions---------------------------------------------*/
76 
77 static void MHEG5listGroupDeselect(MHEG5ListGroup *listGroup, MHEG5Int itemIndex);
78 static void MHEG5listGroupUpdate(MHEG5ListGroup *listGroup);
79 
80 
86 /*
87  Debug
88  */
89 #ifdef MH5PRINTOUT
90 #include <string.h>
91 #include "mh5group.h"
92 
93 
94 static void MHEG5listGroupItemsPrint(MHEG5ListGroup *grp, MHEG5ItemList *item, char *out)
95 {
96  MHEG5indent(out);
97  MHEG_PRINT(out, "(");
98  MHEG5stringPrint(grp->tokenGroup.ingredient.root.grp->groupName, out);
99  MHEG_PRINT(out, " ");
100  MHEG5intPrint(item->id, out);
101  MHEG_PRINT(out, ") ");
102  MHEG5boolPrint(item->itemSelectionStatus, out);
103  MHEG5newLine(out);
104  if (item->next)
105  {
106  MHEG5listGroupItemsPrint(grp, item->next, out);
107  }
108 }
109 
110 static void MHEG5listGroupPositionsPrint(MHEG5PosList *pos, char *out)
111 {
112  MHEG5indent(out);
113  MHEG_PRINT(out, "(");
114  MHEG5intPrint(pos->position.x, out);
115  MHEG_PRINT(out, " ");
116  MHEG5intPrint(pos->position.y, out);
117  MHEG_PRINT(out, ")");
118  MHEG5newLine(out);
119  if (pos->next)
120  MHEG5listGroupPositionsPrint(pos->next, out);
121 }
122 
123 void MHEG5listGroupPrint(MHEG5ListGroup *listGroup, char *out)
124 {
125  MHEG5tokenGroupPrint(&listGroup->tokenGroup, out);
126 
127  if (listGroup->originalPositions)
128  {
129  MHEG5indent(out);
130  MHEG_PRINT(out, ":OriginalPositions");
131  MHEG5newLine(out);
132  MHEG5incIndent();
133  MHEG5listGroupPositionsPrint(listGroup->originalPositions, out);
134  MHEG5decIndent();
135  }
136  if (listGroup->wrapAround)
137  {
138  MHEG5indent(out);
139  MHEG_PRINT(out, ":WrapAround TRUE");
140  MHEG5newLine(out);
141  }
142  if (listGroup->multipleSelection)
143  {
144  MHEG5indent(out);
145  MHEG_PRINT(out, ":MultipleSelection TRUE");
146  MHEG5newLine(out);
147  }
148  if (listGroup->positions)
149  {
150  MHEG5indent(out);
151  MHEG_PRINT(out, "// :Positions");
152  MHEG5newLine(out);
153  MHEG5incIndent();
154  MHEG5listGroupPositionsPrint(listGroup->positions, out);
155  MHEG5decIndent();
156  }
157  if (listGroup->firstItem != 1)
158  {
159  MHEG5indent(out);
160  MHEG_PRINT(out, "// FirstItem:\t");
161  MHEG5intPrint(listGroup->firstItem, out);
162  MHEG5newLine(out);
163  }
164  if (listGroup->positionCount)
165  {
166  MHEG5indent(out);
167  MHEG_PRINT(out, "// PositionCount:\t");
168  MHEG5intPrint(listGroup->positionCount, out);
169  MHEG5newLine(out);
170  }
171  if (listGroup->itemCount)
172  {
173  MHEG5indent(out);
174  MHEG_PRINT(out, "// ItemCount:\t");
175  MHEG5intPrint(listGroup->itemCount, out);
176  MHEG5newLine(out);
177  }
178  if (listGroup->itemList)
179  {
180  MHEG5indent(out);
181  MHEG_PRINT(out, "// :Items");
182  MHEG5newLine(out);
183  MHEG5incIndent();
184  MHEG5listGroupItemsPrint(listGroup, listGroup->itemList, out);
185  MHEG5decIndent();
186  }
187 }
188 
189 #endif
190 
191 
192 
199 static void MHEG5listGroupInitInternal(MHEG5ListGroup *listGroup)
200 {
201  MHEG5PosList **copy, *position, *newItem;
202 
203  assert(listGroup);
204 
205  assert(listGroup->itemList == 0);
206  listGroup->firstItem = 1;
207 
208  listGroup->positions = 0;
209  position = listGroup->originalPositions;
210  copy = &listGroup->positions;
211  while (position)
212  {
213  newItem = MHEG5getMem(sizeof(MHEG5PosList)); /* FreeMem in Destruct */
214  if (!newItem)
215  {
216  /* Out of memory */
217  return;
218  }
219  newItem->position.x = position->position.x;
220  newItem->position.y = position->position.y;
221  newItem->next = 0;
222  *copy = newItem;
223  copy = &newItem->next;
224  position = position->next;
225  }
226 
227  listGroup->firstItemVisible = MHEG5FALSE;
228  listGroup->lastItemVisible = MHEG5FALSE;
229 }
230 
239 {
240  MHEG5PosList *lastPos;
241 
242  assert(listGroup);
243 
244  MHEG5tokenGroupFree(&listGroup->tokenGroup);
245 
246  while (listGroup->originalPositions)
247  {
248  lastPos = listGroup->originalPositions;
249  listGroup->originalPositions = listGroup->originalPositions->next;
250  MHEG5freeMem(lastPos);
251  }
252  while (listGroup->positions)
253  {
254  lastPos = listGroup->positions;
255  listGroup->positions = listGroup->positions->next;
256  MHEG5freeMem(lastPos);
257  }
258 }
259 
268 {
269  MHEG5PosList *position, *newItem;
270 
271  INFO_PRINT(("Adding position (%d, %d) to ListGroup id=%d\n", x, y, ((MHEG5Root *)listGroup)->id));
272 
273  assert(listGroup);
274  newItem = MHEG5getMem(sizeof(MHEG5PosList)); /* FreeMem in Destruct */
275  if (!newItem)
276  {
277  /* Out of memory */
278  return;
279  }
280  newItem->position.x = x;
281  newItem->position.y = y;
282  newItem->next = 0;
283  position = listGroup->originalPositions;
284  listGroup->positionCount++;
285  if (!position)
286  {
287  listGroup->originalPositions = newItem;
288  }
289  else
290  {
291  while (position->next)
292  {
293  position = position->next;
294  }
295  position->next = newItem;
296  }
297 }
298 
305 {
306  MHEG5TokenSlot *token_ptr;
307  U32BIT token_num;
308  MHEG5ItemList *item;
309  MHEG5ItemList *newItem;
310  MHEG5ItemList *lastItem;
311  MHEG5Bool alreadyPresent;
312 
313  assert(listGroup);
314 
315  INFO_PRINT(("Prepare ListGroup id=%d\n", ((MHEG5Root *) listGroup)->id));
316 
317  /* Execute the following sequence of actions: */
319  {
320  return;
321  }
322 
323  assert(listGroup->itemList == 0);
324 
325  MHEG5listGroupInitInternal(listGroup);
326 
327  /* 1. Apply the Preparation behaviour as inherited from the base class. */
328  MHEG5tokenGroupPrepare(&listGroup->tokenGroup);
329 
330  /* 2. Add each reference listed in the token_ptr attribute to the
331  * ItemList in the order they are listed in the token_ptr
332  * attribute. If a Visible is referenced more than once in the
333  * token_ptr, it is added only at its first occurrence in the
334  * ItemList. Null ObjectReferences are not added to ItemList.
335  */
336  token_ptr = listGroup->tokenGroup.tokens_ptr + 1;
337  token_num = listGroup->tokenGroup.tokens_num - 1;
338  lastItem = 0;
339  while (token_num)
340  {
341  item = listGroup->itemList;
342  alreadyPresent = MHEG5FALSE;
343 
344  /* Check for NULL reference */
345  if ((token_ptr->groupid.ptr.name == NULL) || (token_ptr->id == 0))
346  {
347  alreadyPresent = MHEG5TRUE;
348  }
349 
350  /* Check whether item is already in the list */
351  while (item)
352  {
353  if ((item->id == token_ptr->id) &&
354  ((item->groupRef.ptr.group == token_ptr->groupid.ptr.group) ||
355  MHEG5sameGroups(item->groupRef, token_ptr->groupid)))
356  {
357  alreadyPresent = MHEG5TRUE;
358  break;
359  }
360  item = item->next;
361  }
362 
363  if (!alreadyPresent)
364  {
365  /* Add item to the list */
366  newItem = MHEG5getMem(sizeof(MHEG5ItemList)); /* FreeMem in Destruct */
367  if (!newItem)
368  {
369  /* Out of memory */
370  break;
371  }
372  newItem->groupRef = token_ptr->groupid;
373  newItem->id = token_ptr->id;
374  newItem->itemSelectionStatus = MHEG5FALSE;
375  newItem->next = 0;
376  if (lastItem)
377  {
378  /* Add to the tail of the list */
379  lastItem->next = newItem;
380  }
381  else
382  {
383  /* List is empty - add to the head */
384  listGroup->itemList = newItem;
385  }
386  lastItem = newItem;
387  listGroup->itemCount++;
388  }
389  token_ptr++;
390  token_num--;
391  }
392 
393  if (listGroup->itemCount > 0)
394  {
395  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5TAILITEMS, listGroup->itemCount - listGroup->firstItem + 1 );
396  }
397 }
398 
405 {
406  MHEG5ItemList *lastItem;
407 
408  while (listGroup->itemList)
409  {
410  lastItem = listGroup->itemList;
411  listGroup->itemList = listGroup->itemList->next;
412  MHEG5freeMem(lastItem);
413  }
414 
415  MHEG5tokenGroupDestruct(&listGroup->tokenGroup);
416 }
417 
424 {
425  assert(listGroup);
426 
427  /* Execute the following sequence of actions: */
428  if (!listGroup->tokenGroup.ingredient.root.runningStatus)
429  {
430  /* 1. Apply the Activation behaviour as inherited from the Presentable
431  * class.
432  */
433 
435  {
436  MHEG5listGroupPrepare( listGroup );
437  }
438  /* Could call the base class activation behaviour, but */
439  MHEG5ingredientActivate(&listGroup->tokenGroup.ingredient); /*<- does nothing, so don't bother */
440 
441  /* 2. Generate a TokenMovedTo event with the value of the TokenPosition
442  * attribute as associated data.
443  */
445 
446  /* 3. Set the RunningStatus to True. */
448 
449  /* 4. Apply the Updatebehaviour. */
450  MHEG5listGroupUpdate(listGroup);
451 
452  /* 5. Generate an IsRunningevent. */
453  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5ISRUNNING, 0);
454  }
455 }
456 
463 {
464  MHEG5ItemList *item;
465  MHEG5Root *visible;
466 
467  /* NOTE: This class is different that all others. Step 1 occurs before
468  * checking that the RunningStatus is True.
469  */
470 
471  /* Execute the following sequence of actions: */
472  /* 1. Apply the Deactivation behaviour to all Visibles referenced in the
473  * ItemList.
474  */
475  item = listGroup->itemList;
476  while (item)
477  {
478  visible = MHEG5findObject(item->groupRef, item->id);
479  if (visible)
480  {
481  MHEG5finalDeactivate(visible);
483  }
484  item = item->next;
485  }
486 
487  /* 2. Apply the Deactivation behaviour as defined in the base class. */
489 }
490 
498 static void MHEG5listGroupUpdateItemVisibleIndices(MHEG5ListGroup *listGroup)
499 {
500  MHEG5ItemList *item;
501  MHEG5Int itemPos, firstItem;
502 
503  assert(listGroup);
504 
505  firstItem = listGroup->firstItem - 1; /* Index from 0 */
506  if (listGroup->wrapAround)
507  {
508  firstItem %= listGroup->itemCount;
509  }
510 
511  /* Find out which items are visible and set the visibleIndex for them */
512  itemPos = 0;
513  item = listGroup->itemList;
514  while (item)
515  {
516  if ((itemPos >= firstItem) &&
517  (itemPos < firstItem + listGroup->positionCount))
518  {
519  /* This item is visible in the normal view */
520  item->visibleIndex = itemPos - firstItem;
521  }
522  else if (((listGroup->wrapAround) &&
523  (listGroup->positionCount >= listGroup->itemCount)) ||
524  ((listGroup->wrapAround) &&
525  (itemPos < firstItem) &&
526  (firstItem + listGroup->positionCount > listGroup->itemCount) &&
527  (itemPos < (firstItem + listGroup->positionCount) % listGroup->itemCount)))
528  {
529  /* Wrapped items are visible */
530  item->visibleIndex = itemPos - firstItem + listGroup->itemCount;
531  }
532  else
533  {
534  /* Item is not visible */
535  item->visibleIndex = -1;
536  }
537  itemPos++;
538  item = item->next;
539  }
540 }
541 
548 static void MHEG5listGroupDeactivateNotPresentedVisibles(MHEG5ListGroup *listGroup)
549 {
550  MHEG5ItemList *item;
551  MHEG5Root *visible;
552 
553  assert(listGroup);
554 
555  item = listGroup->itemList;
556  while (item)
557  {
558  if (item->visibleIndex < 0) /* Will not be presented */
559  {
560  visible = MHEG5findObject(item->groupRef, item->id);
561  if (visible)
562  {
563  INFO_PRINT((" Item id=%d not visible\n", ((MHEG5Root *)visible)->id));
564  MHEG5finalDeactivate(visible);
566  }
567  }
568  item = item->next;
569  }
570 }
571 
578 static void MHEG5listGroupPreparePresentedVisibles(MHEG5ListGroup *listGroup)
579 {
580  MHEG5ItemList *item;
581  MHEG5Root *visible;
582  MHEG5PosList *pos;
583 
584  assert(listGroup);
585 
586  item = listGroup->itemList;
587  while (item)
588  {
589  if (item->visibleIndex >= 0)
590  {
591  /* Will be presented */
592  visible = MHEG5findObject(item->groupRef, item->id);
593  if (visible)
594  {
595  MHEG5Int i;
596 
597  INFO_PRINT((" Item id=%d visible\n", ((MHEG5Root *)visible)->id));
598  if (!visible->availabilityStatus)
599  {
600  switch (visible->clazz)
601  {
602  case MHEG5BITMAP:
603  MHEG5bitmapPrepare((MHEG5Bitmap *) visible);
604  break;
605  case MHEG5TEXT:
606  MHEG5textPrepare((MHEG5Text *) visible);
607  break;
608  case MHEG5LINEART:
609  MHEG5lineartPrepare((MHEG5Lineart *) visible);
610  break;
611  case MHEG5DYNAMICLINEART:
613  break;
614  case MHEG5RECTANGLE:
616  break;
617  case MHEG5VIDEO:
618  MHEG5videoPrepare((MHEG5Video *) visible);
619  break;
620  case MHEG5ENTRYFIELD:
622  break;
623  case MHEG5HYPERTEXT:
625  break;
626  case MHEG5SLIDER:
627  MHEG5sliderPrepare((MHEG5Slider *)visible);
628  break;
629 
630  #ifndef MHEG5PROFILE_UK1_06
631  case MHEG5HOTSPOT:
632  MHEG5hotspotPrepare((MHEG5Hotspot *)visible);
633  break;
634  case MHEG5PUSHBUTTON:
636  break;
637  case MHEG5SWITCHBUTTON:
639  break;
640  case MHEG5RTGRAPHICS:
642  break;
643  case MHEG5PALETTE:
644  MHEG5palettePrepare((MHEG5Palette *)visible);
645  break;
646  case MHEG5CURSORSHAPE:
648  break;
649  #endif
651  case MHEG5SCENE:
652  case MHEG5APPLICATION:
653  case MHEG5LINK:
655  case MHEG5REMOTEPROGRAM:
662  case MHEG5STREAM:
663  case MHEG5AUDIO:
664  case MHEG5FONT:
665  case MHEG5TOKENGROUP:
666  case MHEG5LISTGROUP:
667  default:
668  ERROR_PRINT(("ListGroup: item not visible %d\n", visible->clazz));
669  return;
670  }
671  }
672  pos = listGroup->positions;
673 
674  for (i = 0; i < item->visibleIndex && pos; i++)
675  {
676  pos = pos->next;
677  assert(pos);
678  }
679 
680  if (pos)
681  {
682  INFO_PRINT(("Setting position of item id=%d to (%d, %d)\n", visible->id, pos->position.x, pos->position.y));
683  MHEG5visibleSetPosition((MHEG5Visible *)visible, pos->position.x, pos->position.y);
684  }
685  }
686  }
687  item = item->next;
688  }
689 }
690 
697 static void MHEG5listGroupActivatePresentedVisibles(MHEG5ListGroup *listGroup)
698 {
699  MHEG5ItemList *item;
700  MHEG5Root *visible;
701 
702  assert(listGroup);
703 
704  item = listGroup->itemList;
705  while (item)
706  {
707  if (item->visibleIndex >= 0) /* Will be presented */
708  {
709  visible = MHEG5findObject(item->groupRef, item->id);
710  if (visible)
711  {
712  MHEG5finalActivate(visible);
713  }
714  if (item == listGroup->itemList && !listGroup->firstItemVisible)
715  {
716  listGroup->firstItemVisible = MHEG5TRUE;
718  }
719  if (!item->next && !listGroup->lastItemVisible)
720  {
721  listGroup->lastItemVisible = MHEG5TRUE;
723  }
724  }
725  else
726  {
727  if (item == listGroup->itemList && listGroup->firstItemVisible)
728  {
729  listGroup->firstItemVisible = MHEG5FALSE;
731  }
732  if (!item->next && listGroup->lastItemVisible)
733  {
734  listGroup->lastItemVisible = MHEG5FALSE;
736  }
737  }
738 
739  item = item->next;
740  }
741 }
742 
748 static void MHEG5listGroupUpdate(MHEG5ListGroup *listGroup)
749 {
750  INFO_PRINT(("INFO: ListGroup update id=%d\n", ((MHEG5Root *)listGroup)->id));
751 
752  assert(listGroup);
753 
754  if (!listGroup)
755  {
756  return;
757  }
758 
759  /* If the RunningStatus of the ListGroup is True then execute the following
760  * sequence of actions:
761  */
762  if (!((MHEG5Root *)listGroup)->runningStatus)
763  {
764  DEBUG_PRINT(("WARNING: MHEG5listGroupUpdate - listgroup id=%d not running\n", ((MHEG5Root *)listGroup)->id));
765  return;
766  }
767 
768  /* Update the display index that each visible in the list holds */
769  MHEG5listGroupUpdateItemVisibleIndices(listGroup);
770 
771  /* 1. For each item that will not be presented in a cell, if the item is
772  * active then apply the Deactivation behaviour to it and set its
773  * position to its OriginalPosition attribute.
774  */
775  MHEG5listGroupDeactivateNotPresentedVisibles(listGroup);
776 
777  /* 2. For each item, if it is to be presented at a cell, apply the
778  * Preparation behaviour to it and then set its
779  * Position(internal attribute) to the position defined for that cell.
780  */
781  MHEG5listGroupPreparePresentedVisibles(listGroup);
782 
783  /* 3. For each item that will be presented in a cell, if the item is
784  * inactive, apply the Activation behaviour to it.
785  */
786  MHEG5listGroupActivatePresentedVisibles(listGroup);
787 }
788 
797 static void MHEG5listGroupAddItem(MHEG5ListGroup *listGroup, MHEG5Int idx, MH5GroupRef grpRef, MHEG5Int id)
798 {
799  MHEG5ItemList *item, *newItem;
800  MHEG5Int i;
801  MH5GroupPtr gptr;
802  INFO_PRINT(("Adding item ( %d, %d ) to ListGroup id=%d\n", grpRef.len, id, ((MHEG5Root *)listGroup)->id));
803 
804  /* Execute the following sequence of actions: */
805 
806  /* 1. If the Visible referenced by the Item parameter is already in the ItemList, ignore this behaviour. */
807  item = listGroup->itemList;
808  while (item)
809  {
810  if ((item->id == id) &&
811  ((item->groupRef.ptr.group == grpRef.ptr.group) ||
812  MHEG5sameGroups(item->groupRef, grpRef)))
813  {
814  DEBUG_PRINT(("MHEG5listGroupAddItem: Item already in ListGroup\n"));
815  return;
816  }
817  item = item->next;
818  }
819 
820  /* 2. If Index is less than 1 or greater than the current length of
821  * ItemList + 1, ignore this behaviour.
822  */
823  if ((idx < 1) || (idx > listGroup->itemCount + 1))
824  {
825  DEBUG_PRINT(("MHEG5listGroupAddItem: Index out of range\n"));
826  return;
827  }
828 
829  i = 0;
830  gptr = listGroup->tokenGroup.ingredient.root.grp;
831  if ( !MHEG5sameGroup(gptr,grpRef) )
832  {
833  if (gptr->root.clazz == MHEG5SCENE)
834  {
836  }
837  else
838  {
840  }
841  if ( !MHEG5sameGroup(gptr,grpRef) )
842  {
843  i = grpRef.len;
844  }
845  }
846 
847  /* 3. Add the Item reference at position Index in the ItemList. (The item
848  * previously at position Index in the ItemList -if any- will now have index
849  * Index+1 and, similarly, every item of index greater than Index will now
850  * have an index incremented by one.)
851  */
852  newItem = MHEG5getMem(sizeof(MHEG5ItemList) + i); /* FreeMem in Destruct */
853  if (!newItem)
854  {
855  TRACE(TERROR,("Out of memory"))
856  }
857  else
858  {
859  if (i == 0)
860  {
861  newItem->groupRef.len = 0;
862  newItem->groupRef.ptr.group = gptr;
863  }
864  else
865  {
866  newItem->groupRef.len = i;
867  newItem->groupRef.ptr.name = (MHEG5Byte*)(newItem + 1);
868  memcpy(newItem->groupRef.ptr.name,grpRef.ptr.name,i);
869  }
870  newItem->id = id;
871  newItem->itemSelectionStatus = MHEG5FALSE;
872  newItem->next = 0;
873 
874  listGroup->itemCount++;
875 
876  if (idx==1)
877  {
878  newItem->next=listGroup->itemList;
879  listGroup->itemList=newItem;
880  }
881  else
882  {
883  item=listGroup->itemList;
884  i=2;
885  while (item && (i<idx))
886  {
887  item=item->next;
888  i++;
889  }
890 
891  /* Really can assert that item != NULL, because 'idx' <= listGroup->itemCount+1,
892  * however no harm in checking anyway */
893  assert( item != NULL );
894  if (!item)
895  {
896  return;
897  }
898 
899  newItem->next=item->next;
900  item->next=newItem;
901  }
902 
903  /* Increment the index of first item if necessary */
904  if ((idx <= listGroup->firstItem) && (listGroup->firstItem < listGroup->itemCount))
905  {
906  listGroup->firstItem++;
907 
908  /* FirstItem has been incremented. */
909  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5HEADITEMS, listGroup->firstItem - 1 );
910  }
911  else
912  {
913  /* FirstItem remains the same, but itemCount has incremented */
914  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5TAILITEMS, listGroup->itemCount - listGroup->firstItem + 1 );
915  }
916 
917  /* 4. Apply the Update behaviour. */
918  MHEG5listGroupUpdate(listGroup);
919  }
920 }
921 
929 static void MHEG5listGroupDelItem(MHEG5ListGroup *listGroup, MH5GroupRef grpRef, MHEG5Int id)
930 {
931  MHEG5ItemList *item, *prevItem = 0;
932  MHEG5Int idx = 0;
933  MHEG5Root *visible;
934 
935  INFO_PRINT(("Deleting item ( %ld ) from ListGroup %d\n", id, ((MHEG5Root *)listGroup)->id));
936 
937  /* Execute the following sequence of actions: */
938  item = listGroup->itemList;
939  while (item)
940  {
941  idx++;
942 
943  /* 1. If the Visible referenced by the Item parameter is not in the
944  * ItemList, ignore this action.
945  */
946  if ((item->id == id) &&
947  ((item->groupRef.ptr.group == grpRef.ptr.group) ||
948  MHEG5sameGroups(item->groupRef, grpRef)))
949  {
950  INFO_PRINT((" Found it!\n"));
951 
952  /* 2. Remove the reference indicated by the Item parameter from the
953  * ItemList. (The item index of the following items in ItemList will
954  * decrement by one.)
955  */
956  if (!prevItem)
957  {
958  listGroup->itemList = listGroup->itemList->next;
959  }
960  else
961  {
962  prevItem->next = item->next;
963  }
964 
965  /* Find the visible referenced by this item */
966  visible = MHEG5findObject(item->groupRef, item->id);
967 
968  /* Destruct the reference to the visible */
969  MHEG5freeMem(item);
970 
971  listGroup->itemCount--;
972 
973  /* 3. Set the position of the referenced Visible to its
974  * OriginalPosition.
975  */
976  if (visible)
977  {
979  }
980 
981  /* 4. If the index of the deleted Item was less than or equal to
982  * FirstItem and FirstItem is strictly greater than one, then
983  * decrease FirstItem internal attribute by one.
984  */
985  if ((idx <= listGroup->firstItem) && (listGroup->firstItem > 1))
986  {
987  listGroup->firstItem--;
988 
989  /* FirstItem has been decremented */
990  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5HEADITEMS, listGroup->firstItem - 1 );
991  }
992  else
993  {
994  /* FirstItem remains the same, ItemCount has been decremented */
995  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5TAILITEMS, listGroup->itemCount - listGroup->firstItem + 1 );
996  }
997 
998  /* 5. Apply the Update behaviour. */
999  MHEG5listGroupUpdate(listGroup);
1000  return;
1001  }
1002  prevItem = item;
1003  item = item->next;
1004  }
1005 }
1006 
1013 static void MHEG5listGroupSelect(MHEG5ListGroup *listGroup, MHEG5Int itemIndex)
1014 {
1015  MHEG5ItemList *item;
1016  MHEG5Int i;
1017 
1018  item = listGroup->itemList;
1019  for (i = 1; (i < itemIndex) && (item != NULL); i++)
1020  {
1021  item = item->next;
1022  }
1023 
1024  if (item == NULL)
1025  {
1026  return;
1027  }
1028 
1029  /* Execute the following sequence of actions: */
1030 
1031  /* 1. If ItemSelectionStatus of item with index ItemIndex is True, ignore this behaviour. */
1032  if (item->itemSelectionStatus)
1033  {
1034  return;
1035  }
1036 
1037  /* 2. If MultipleSelection is False, apply Deselect(Index) internal
1038  * behaviour for any item with index Index, for which the
1039  * ItemSelectionStatus is True.
1040  */
1041  if (!listGroup->multipleSelection)
1042  {
1043  MHEG5ItemList *item2;
1044  MHEG5Int idx;
1045 
1046  item2 = listGroup->itemList;
1047  idx = 0;
1048  while (item2)
1049  {
1050  idx++;
1051  if (item2->itemSelectionStatus)
1052  {
1053  MHEG5listGroupDeselect(listGroup, idx);
1054  }
1055  item2 = item2->next;
1056  }
1057  }
1058 
1059  /* 3. Set the ItemSelectionStatus of the item with index ItemIndex to True. */
1061 
1062  /* 4. Generate an ItemSelected event with ItemIndex as associated data. */
1063  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5ITEMSELECTED, itemIndex );
1064 }
1065 
1072 static void MHEG5listGroupDeselect(MHEG5ListGroup *listGroup, MHEG5Int itemIndex)
1073 {
1074  MHEG5ItemList *item;
1075  MHEG5Int i;
1076 
1077  item = listGroup->itemList;
1078  for (i = 1; (i < itemIndex) && (item != NULL); i++)
1079  {
1080  item = item->next;
1081  }
1082 
1083  if (item == NULL)
1084  {
1085  return;
1086  }
1087 
1088  /* Execute the following sequence of actions: */
1089 
1090  /* 1. If ItemSelectionStatus of item with index ItemIndex is False, ignore this behaviour. */
1091  if (!item->itemSelectionStatus)
1092  {
1093  return;
1094  }
1095 
1096  /* 2. Set the ItemSelectionStatus of the item with the index ItemIndex to False. */
1098 
1099  /* 3. Generate an ItemDeselected event with ItemIndex as associated data. */
1100  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5ITEMDESELECTED, itemIndex );
1101 }
1102 
1109 static MHEG5Int MHEG5listGroupAdjustindex(MHEG5ListGroup *listGroup, MHEG5Int idx)
1110 {
1111  assert(listGroup);
1112  if (!listGroup)
1113  {
1114  return 0;
1115  }
1116 
1117  /* Set the Adjusted parameter to the value of the Index parameter normalised
1118  * to the length of the ItemList, by applying the following logic:
1119  */
1120  /* If the length of ItemListis zero then set Adjustedto 1. */
1121  if (!listGroup->itemCount)
1122  {
1123  return 1;
1124  }
1125 
1126  /* Otherwise, if Index is greater than the length of ItemList, set Adjusted
1127  * to:
1128  * (( Index-1) MODULO Length of ItemList) + 1
1129  */
1130  if (idx > listGroup->itemCount)
1131  {
1132  return ((idx - 1) % listGroup->itemCount) + 1;
1133  }
1134 
1135  /* Otherwise, if Index is less than 1, set Adjusted to:
1136  * Length of ItemList - ((- Index) MODULO Length of ItemList)
1137  */
1138  if (idx < 1)
1139  {
1140  return listGroup->itemCount - ((-idx) % listGroup->itemCount);
1141  }
1142 
1143  /* Otherwise, set Adjustedto Index, unmodified. */
1144  return idx;
1145 }
1146 
1147 /*
1148  Actions
1149  */
1157 {
1158  MHEG5GList *thirdParam = 0;
1159  MHEG5Int itemIndex;
1160  MH5GroupRef gref;
1161  MHEG5Int id;
1162 
1163  assert(target);
1164 
1165  if (target->clazz != MHEG5LISTGROUP)
1166  {
1167  return MHEG5ERR_WRONGTARGET;
1168  }
1169  if (!params)
1170  {
1172  }
1173  thirdParam = MHEG5resolveGenericInteger(params, &itemIndex);
1174  if (!thirdParam)
1175  {
1177  }
1178  MHEG5resolveGenericORefProper(thirdParam, &gref, &id);
1179  if ((id == 0) || (gref.ptr.group == 0))
1180  {
1182  }
1183 
1184  /* Apply the Additem(ItemIndex, VisibleReference) internal behaviour to add
1185  * the reference to the visible, as indicated by the VisibleReference
1186  * parameter at the position indicated by the ItemIndex parameter.
1187  */
1188  MHEG5listGroupAddItem((MHEG5ListGroup *)target, itemIndex, gref, id);
1189 
1190  return MHEG5ERR_NOERROR;
1191 }
1192 
1200 {
1201  MH5GroupRef gref;
1202  MHEG5Int id;
1203 
1204  assert(target);
1205 
1206  if (target->clazz != MHEG5LISTGROUP)
1207  {
1208  return MHEG5ERR_WRONGTARGET;
1209  }
1210  if (!params)
1211  {
1213  }
1214 
1215  MHEG5resolveGenericORefProper(params, &gref, &id);
1216  if ((id == 0) || (gref.ptr.group == 0))
1217  {
1219  }
1220 
1221  /* Apply the Delitem(VisibleReference) internal behaviour to delete the
1222  * reference to the visible, as indicated by the VisibleReference parameter
1223  * from the ItemList attribute, if it occurs in it.
1224  */
1225  MHEG5listGroupDelItem((MHEG5ListGroup *)target, gref, id);
1226 
1227  return MHEG5ERR_NOERROR;
1228 }
1229 
1230 /* mh5variable.h is included at the top of this file and yet the ST compiler still does not
1231  * know about the function MHEG5objRefValueDestruct unless its definition is placed here
1232  * ??? - beats me!
1233  */
1235 
1243 {
1244  MHEG5GList *thirdParam = 0;
1245  MHEG5Root *visible;
1246  MHEG5Int itemIndex;
1247  MHEG5Int idx;
1248  MHEG5ItemList *item;
1249  MHEG5ListGroup *listGroup;
1250  MHEG5ObjectRefVariable *oRef;
1251  MHEG5Int i;
1252 
1253  assert(target);
1254 
1255  if (target->clazz != MHEG5LISTGROUP)
1256  {
1257  return MHEG5ERR_WRONGTARGET;
1258  }
1259  if (!params)
1260  {
1262  }
1263  thirdParam = MHEG5resolveGenericInteger(params, &itemIndex);
1264  if (!thirdParam)
1265  {
1267  }
1268  MHEG5resolveORef(thirdParam, &visible);
1269  if (!visible)
1270  {
1272  }
1273  if (visible->clazz != MHEG5OBJECTREFVARIABLE)
1274  {
1275  return MHEG5ERR_WRONGPARAM;
1276  }
1277  listGroup = (MHEG5ListGroup *)target;
1278 
1279  /* Using a local variable Index: */
1280  if (!listGroup->wrapAround)
1281  {
1282  /* If WrapAround is False, if ItemIndex is in the range
1283  * [1, length of ItemList] then set Index to ItemIndex, otherwise
1284  * ignore this action.
1285  */
1286  if ((itemIndex >= 1) && (itemIndex <= listGroup->itemCount))
1287  {
1288  idx = itemIndex;
1289  }
1290  else
1291  {
1292  return MHEG5ERR_NOERROR;
1293  }
1294  }
1295  else
1296  {
1297  /* If WrapAround is True, apply the AdjustIndex(ItemIndex,Index)
1298  * behaviour.
1299  */
1300  idx = MHEG5listGroupAdjustindex(listGroup, itemIndex);
1301  }
1302 
1303  /* Find the item in the item list */
1304  item = listGroup->itemList;
1305  for (i = 1; (i < idx) && (item != NULL); i++)
1306  {
1307  item = item->next;
1308  }
1309 
1310  /* Return the reference included in the ItemList attribute with the index
1311  * specified by the Index parameter in the ObjectRefVariable referenced by
1312  * ItemRefVar.
1313  */
1314  oRef = (MHEG5ObjectRefVariable *)visible;
1315  if (item)
1316  {
1317  MHEG5objRefStoreValue( oRef, item->groupRef, item->id );
1318  }
1319  else
1320  {
1321  /* this could only get here if internal error with the linked list of items */
1322  TRACE(TERROR, ("itemIndex=%d wr=%d", itemIndex, listGroup->wrapAround))
1323  assert(0);
1324  }
1325  return MHEG5ERR_NOERROR;
1326 }
1327 
1335 {
1336  MHEG5GList *thirdParam = 0;
1337  MHEG5Root *visible;
1338  MHEG5Int idx, first;
1339  MHEG5ItemList *item;
1340  MHEG5ListGroup *listGroup;
1341  MHEG5ObjectRefVariable *oRef;
1342 
1343  if (target->clazz != MHEG5LISTGROUP)
1344  {
1345  return MHEG5ERR_WRONGTARGET;
1346  }
1347  if (!params)
1348  {
1350  }
1351  thirdParam = MHEG5resolveGenericInteger(params, &idx);
1352  if (!thirdParam)
1353  {
1355  }
1356  MHEG5resolveORef(thirdParam, &visible);
1357  if (!visible)
1358  {
1360  }
1361  if (visible->clazz != MHEG5OBJECTREFVARIABLE)
1362  {
1363  return MHEG5ERR_WRONGPARAM;
1364  }
1365  listGroup = (MHEG5ListGroup *)target;
1366 
1367  /* Return the reference of the visible presented at the cell indicated by
1368  * the CellIndex parameter in the ObjectRefVariable referenced by
1369  * ItemRefVar. If the CellIndex specifies an index smaller than or equal to
1370  * 1 return the reference of the visible presented at the first cell. If the
1371  * CellIndex specifies an index greater than or equal to the number of
1372  * cells, return the reference of the visible presented in the last cell. If
1373  * no visible is presented at the indicated cell, return NULL.
1374  */
1375  if (idx < 1)
1376  {
1377  idx = 1;
1378  }
1379  if (idx > listGroup->positionCount)
1380  {
1381  idx = listGroup->positionCount;
1382  }
1383 
1384  if (listGroup->wrapAround)
1385  {
1386  if (idx > listGroup->itemCount)
1387  {
1388  /* Cell index is greater than the number of items in this list.
1389  * Nothing will be displayed in this cell.
1390  */
1391  first = 0;
1392  }
1393  else
1394  {
1395  first = MHEG5listGroupAdjustindex(listGroup, listGroup->firstItem + idx - 1);
1396  }
1397  }
1398  else
1399  {
1400  first = listGroup->firstItem + idx - 1;
1401  if (first > listGroup->itemCount)
1402  {
1403  first = 0;
1404  }
1405  }
1406 
1407  if (first > 0)
1408  {
1409  first--;
1410  item = listGroup->itemList;
1411  while ((first) && (item))
1412  {
1413  item = item->next;
1414  first--;
1415  }
1416  }
1417  else
1418  {
1419  item = NULL;
1420  }
1421  oRef = (MHEG5ObjectRefVariable *)visible;
1422  if (item)
1423  {
1424  MHEG5objRefStoreValue( oRef, item->groupRef, item->id );
1425  }
1426  else
1427  {
1428  MH5GroupRef gref;
1429  gref.len = 0;
1430  gref.ptr.group = NULL;
1431  MHEG5objRefStoreValue( oRef, gref, 0 );
1432  }
1433  return MHEG5ERR_NOERROR;
1434 }
1435 
1443 {
1444  MHEG5GList *thirdParam = 0;
1445  MHEG5Root *visible;
1446  MHEG5Int itemIndex;
1447  MHEG5Int idx;
1448  MHEG5ItemList *item;
1449  MHEG5ListGroup *listGroup;
1450  MHEG5BooleanVariable *oRef;
1451  int i;
1452 
1453  assert(target);
1454 
1455  if (target->clazz != MHEG5LISTGROUP)
1456  {
1457  return MHEG5ERR_WRONGTARGET;
1458  }
1459  if (!params)
1460  {
1462  }
1463  thirdParam = MHEG5resolveGenericInteger(params, &itemIndex);
1464  if (!thirdParam)
1465  {
1467  }
1468  MHEG5resolveORef(thirdParam, &visible);
1469  if (!visible)
1470  {
1472  }
1473  if (visible->clazz != MHEG5BOOLEANVARIABLE)
1474  {
1475  return MHEG5ERR_WRONGPARAM;
1476  }
1477  listGroup = (MHEG5ListGroup *)target;
1478 
1479  /* Using a local variable Index: */
1480  if (!listGroup->wrapAround)
1481  {
1482  /* If WrapAround is False, if ItemIndex is in the range
1483  * [1, length of ItemList] then set Index to ItemIndex, otherwise
1484  * ignore this action.
1485  */
1486  if ((itemIndex >= 1) && (itemIndex <= listGroup->itemCount))
1487  {
1488  idx = itemIndex;
1489  }
1490  else
1491  {
1492  return MHEG5ERR_NOERROR;
1493  }
1494  }
1495  else
1496  {
1497  /* If WrapAround is True, apply the AdjustIndex(ItemIndex,Index)
1498  * behaviour.
1499  */
1500  idx = MHEG5listGroupAdjustindex(listGroup, itemIndex);
1501  }
1502 
1503  /* Find the item in the item list */
1504  item = listGroup->itemList;
1505  for (i = 1; (i < idx) && (item != NULL); i++)
1506  {
1507  item = item->next;
1508  }
1509 
1510  oRef = (MHEG5BooleanVariable *)visible;
1511  if (item)
1512  {
1513  /* Return the value of the ItemSelectionStatus attribute of the item in
1514  * the ItemList with index Index in the BooleanVariable referenced by
1515  * ItemStatusVar
1516  */
1517  oRef->value = item->itemSelectionStatus;
1518  }
1519  else
1520  {
1521  oRef->value = MHEG5FALSE;
1522  }
1523 
1524  return MHEG5ERR_NOERROR;
1525 }
1526 
1534 {
1535  MHEG5Int itemIndex;
1536  MHEG5Int idx;
1537  MHEG5ListGroup *listGroup;
1538 
1539  assert(target);
1540 
1541  if (target->clazz != MHEG5LISTGROUP)
1542  {
1543  return MHEG5ERR_WRONGTARGET;
1544  }
1545  if (!params)
1546  {
1548  }
1549  MHEG5resolveGenericInteger(params, &itemIndex);
1550  listGroup = (MHEG5ListGroup *)target;
1551 
1552  /* Using a local variable Index: */
1553  if (!listGroup->wrapAround)
1554  {
1555  /* If WrapAround is False, if ItemIndex is in the range
1556  * [1, length of ItemList] then set Index to ItemIndex, otherwise ignore
1557  * this action.
1558  */
1559  if ((itemIndex >= 1) && (itemIndex <= listGroup->itemCount))
1560  {
1561  idx = itemIndex;
1562  }
1563  else
1564  {
1565  return MHEG5ERR_NOERROR;
1566  }
1567  }
1568  else
1569  {
1570  /* If WrapAround is True, apply the AdjustIndex(ItemIndex,Index)
1571  * behaviour.
1572  */
1573  idx = MHEG5listGroupAdjustindex(listGroup, itemIndex);
1574  }
1575 
1576  /* Apply the Select(Index) internal behaviour. */
1577  MHEG5listGroupSelect(listGroup, idx);
1578 
1579  return MHEG5ERR_NOERROR;
1580 }
1581 
1589 {
1590  MHEG5Int itemIndex;
1591  MHEG5Int idx;
1592  MHEG5ListGroup *listGroup;
1593 
1594  assert(target);
1595 
1596  if (target->clazz != MHEG5LISTGROUP)
1597  {
1598  return MHEG5ERR_WRONGTARGET;
1599  }
1600  if (!params)
1601  {
1603  }
1604  MHEG5resolveGenericInteger(params, &itemIndex);
1605  listGroup = (MHEG5ListGroup *)target;
1606 
1607  /* Using a local variable Index: */
1608  if (!listGroup->wrapAround)
1609  {
1610  /* If WrapAround is False, if ItemIndex is in the range
1611  * [1, length of ItemList] then set Index to ItemIndex, otherwise ignore
1612  * this action.
1613  */
1614  if ((itemIndex >= 1) && (itemIndex <= listGroup->itemCount))
1615  {
1616  idx = itemIndex;
1617  }
1618  else
1619  {
1620  return MHEG5ERR_NOERROR;
1621  }
1622  }
1623  else
1624  {
1625  /* If WrapAround is True, apply the AdjustIndex(ItemIndex,Index)
1626  * behaviour.
1627  */
1628  idx = MHEG5listGroupAdjustindex(listGroup, itemIndex);
1629  }
1630 
1631  /* Apply the Deselect(Index) internal behaviour. */
1632  MHEG5listGroupDeselect(listGroup, idx);
1633 
1634  return MHEG5ERR_NOERROR;
1635 }
1636 
1644 {
1645  MHEG5Int itemIndex;
1646  MHEG5Int idx;
1647  MHEG5Int i;
1648  MHEG5ItemList *item;
1649  MHEG5ListGroup *listGroup;
1650 
1651  assert(target);
1652 
1653  if (target->clazz != MHEG5LISTGROUP)
1654  {
1655  return MHEG5ERR_WRONGTARGET;
1656  }
1657  if (!params)
1658  {
1660  }
1661  MHEG5resolveGenericInteger(params, &itemIndex);
1662  listGroup = (MHEG5ListGroup *)target;
1663 
1664  /* Using a local variable Index: */
1665  if (!listGroup->wrapAround)
1666  {
1667  /* If WrapAround is False, if ItemIndex is in the range
1668  * [1, length of ItemList] then set Index to ItemIndex, otherwise ignore
1669  * this action.
1670  */
1671  if ((itemIndex >= 1) && (itemIndex <= listGroup->itemCount))
1672  {
1673  idx = itemIndex;
1674  }
1675  else
1676  {
1677  return MHEG5ERR_NOERROR;
1678  }
1679  }
1680  else
1681  {
1682  /* If WrapAround is True, apply the AdjustIndex(ItemIndex,Index)
1683  * behaviour.
1684  */
1685  idx = MHEG5listGroupAdjustindex(listGroup, itemIndex);
1686  }
1687 
1688  /* Find the item in the item list */
1689  item = listGroup->itemList;
1690  if (item == 0)
1691  {
1692  return MHEG5ERR_NOERROR;
1693  }
1694  for (i = 1; i < idx; i++)
1695  {
1696  item = item->next;
1697  if (item == 0)
1698  {
1699  return MHEG5ERR_NOERROR;
1700  }
1701  }
1702 
1703  /* If the ItemSelectionStatus of the item indicated by Index is True, apply
1704  * the Deselect(Index) internal behaviour, otherwise apply the Select(Index)
1705  * internal behaviour.
1706  */
1707  if (item->itemSelectionStatus)
1708  {
1709  MHEG5listGroupDeselect(listGroup, idx);
1710  }
1711  else
1712  {
1713  MHEG5listGroupSelect(listGroup, idx);
1714  }
1715 
1716  return MHEG5ERR_NOERROR;
1717 }
1718 
1726 {
1727  MHEG5Int itemsToScroll = 0, newIndex;
1728  MHEG5ListGroup *listGroup;
1729  MHEG5Int oldFirstItem;
1730 
1731  assert(target);
1732 
1733  if (target->clazz != MHEG5LISTGROUP)
1734  {
1735  return MHEG5ERR_WRONGTARGET;
1736  }
1737  if (!params)
1738  {
1740  }
1741  MHEG5resolveGenericInteger(params, &itemsToScroll);
1742 
1743  listGroup = (MHEG5ListGroup *)target;
1744  newIndex = listGroup->firstItem + itemsToScroll;
1745  oldFirstItem = listGroup->firstItem;
1746 
1747  if (!listGroup->wrapAround)
1748  {
1749  /* If WrapAround is False, if FirstItem+ItemsToScroll is in the range
1750  * [1, length of ItemList] then set FirstItem to
1751  * FirstItem+ItemsToScroll, otherwise ignore this action.
1752  */
1753  if ((newIndex >= 1) && (newIndex <= listGroup->itemCount))
1754  {
1755  listGroup->firstItem = newIndex;
1756  }
1757  else
1758  {
1759  return MHEG5ERR_NOERROR;
1760  }
1761  }
1762  else
1763  {
1764  /* If WrapAround is True, apply the
1765  * AdjustIndex(FirstItem+ItemsToScroll,FirstItem) behaviour.
1766  */
1767  listGroup->firstItem = MHEG5listGroupAdjustindex(listGroup, newIndex);
1768  }
1769 
1770  if (oldFirstItem != listGroup->firstItem)
1771  {
1772  /* FirstItem has changed */
1773  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5HEADITEMS, listGroup->firstItem - 1 );
1774  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5TAILITEMS, listGroup->itemCount - listGroup->firstItem + 1 );
1775  }
1776 
1777  /* Apply the Update behaviour. */
1778  MHEG5listGroupUpdate(listGroup);
1779 
1780  return MHEG5ERR_NOERROR;
1781 }
1782 
1790 {
1791  MHEG5Int newFirstItem;
1792  MHEG5ListGroup *listGroup;
1793  MHEG5Int oldFirstItem;
1794 
1795  assert(target);
1796 
1797  if (target->clazz != MHEG5LISTGROUP)
1798  {
1799  return MHEG5ERR_WRONGTARGET;
1800  }
1801  if (!params)
1802  {
1804  }
1805  MHEG5resolveGenericInteger(params, &newFirstItem);
1806 
1807  listGroup = (MHEG5ListGroup *)target;
1808  oldFirstItem = listGroup->firstItem;
1809 
1810  if (!listGroup->wrapAround)
1811  {
1812  /* If WrapAround is False, if NewFirstItem is in the range
1813  * [1, length of ItemList] then set FirstItem to NewFirstItem, otherwise
1814  * ignore this action.
1815  */
1816  if ((newFirstItem >= 1) && (newFirstItem <= listGroup->itemCount))
1817  {
1818  listGroup->firstItem = newFirstItem;
1819  }
1820  else
1821  {
1822  return MHEG5ERR_NOERROR;
1823  }
1824  }
1825  else
1826  {
1827  /* If WrapAround is True, apply the AdjustIndex(NewFirstItem,FirstItem)
1828  * behaviour.
1829  */
1830  listGroup->firstItem = MHEG5listGroupAdjustindex(listGroup, newFirstItem);
1831  }
1832 
1833  if (oldFirstItem != listGroup->firstItem)
1834  {
1835  /* FirstItem has changed */
1836  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5HEADITEMS, listGroup->firstItem - 1);
1837  MHEG5sendSync((MHEG5Root *)listGroup, MHEG5TAILITEMS, listGroup->itemCount - listGroup->firstItem + 1);
1838  }
1839 
1840  /* Apply the Update behaviour. */
1841  MHEG5listGroupUpdate(listGroup);
1842 
1843  return MHEG5ERR_NOERROR;
1844 }
1845 
1853 {
1854  MHEG5Root *object = 0;
1855  MHEG5ListGroup *listGroup;
1856  MHEG5IntegerVariable *oRef;
1857 
1858  assert(target);
1859 
1860  if (target->clazz != MHEG5LISTGROUP)
1861  {
1862  return MHEG5ERR_WRONGTARGET;
1863  }
1864  if (!params)
1865  {
1867  }
1868  MHEG5resolveORef(params, &object);
1869  if (!object)
1870  {
1872  }
1873  if (object->clazz != MHEG5INTEGERVARIABLE)
1874  {
1875  return MHEG5ERR_WRONGPARAM;
1876  }
1877 
1878  listGroup = (MHEG5ListGroup *)target;
1879 
1880  /* Return the current value of the FirstItem attribute in the
1881  * IntegerVariable referenced by FirstItemVar.
1882  */
1883  oRef = (MHEG5IntegerVariable *)object;
1884  oRef->value = listGroup->firstItem;
1885 
1886  return MHEG5ERR_NOERROR;
1887 }
1888 
1896 {
1897  MHEG5Root *object = 0;
1898  MHEG5ListGroup *listGroup;
1899  MHEG5IntegerVariable *oRef;
1900 
1901  assert(target);
1902 
1903  if (target->clazz != MHEG5LISTGROUP)
1904  {
1905  return MHEG5ERR_WRONGTARGET;
1906  }
1907  if (!params)
1908  {
1910  }
1911  MHEG5resolveORef(params, &object);
1912  if (!object)
1913  {
1915  }
1916  if (object->clazz != MHEG5INTEGERVARIABLE)
1917  {
1918  return MHEG5ERR_WRONGPARAM;
1919  }
1920 
1921  listGroup = (MHEG5ListGroup *)target;
1922 
1923  /* Return the number of items in the ItemList in the IntegerVariable
1924  * referenced by SizeVar.
1925  */
1926  oRef = (MHEG5IntegerVariable *)object;
1927  oRef->value = listGroup->itemCount;
1928 
1929  return MHEG5ERR_NOERROR;
1930 }
1931 
1939 {
1940  MHEG5GList *thirdParam = 0;
1941  MHEG5GList *fourthParam = 0;
1942  MHEG5ListGroup *listGroup;
1943  MHEG5Int idx, newXPosition, newYPosition;
1944  MHEG5Int counter;
1945  MHEG5PosList *position;
1946 
1947  assert(target);
1948 
1949  if (target->clazz != MHEG5LISTGROUP)
1950  {
1951  return MHEG5ERR_WRONGTARGET;
1952  }
1953  if (!params)
1954  {
1956  }
1957  thirdParam = MHEG5resolveGenericInteger(params, &idx);
1958  if (!thirdParam)
1960  fourthParam = MHEG5resolveGenericInteger(thirdParam, &newXPosition);
1961  if (!fourthParam)
1963  MHEG5resolveGenericInteger(fourthParam, &newYPosition);
1964 
1965  listGroup = (MHEG5ListGroup *)target;
1966 
1967  position = listGroup->positions;
1968  for (counter = 1; counter < idx; ++counter)
1969  {
1970  if (position->next)
1971  {
1972  position = position->next;
1973  }
1974  }
1975  position->position.x = newXPosition;
1976  position->position.y = newYPosition;
1977 
1978  /* Apply the Update behaviour. */
1979  MHEG5listGroupUpdate(listGroup);
1980 
1981  return MHEG5ERR_NOERROR;
1982 }
1983 
MHEG5Bool availabilityStatus
Definition: mh5root.h:52
MHEG5ErrorCode MHEG5getCellItem(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup GetCellItem elementary action.
Implement the MHEG5 Button Class Description Defines functionality associated with the rendering and ...
MHEG5Int itemCount
Definition: mh5listgroup.h:80
Implement the MHEG5 Hypertext Class. The HyperText class is a subclass of the Text class...
Distributor for Prepare, Destruct, Activate, Deactivate and Clone calls. Distribute the +Prepare +Des...
MHEG5ItemList * itemList
Definition: mh5listgroup.h:75
MHEG5Bool MHEG5sameGroup(MH5GroupPtr gptr, MH5GroupRef gref)
Compares group ptr with group ref to see whether they both reference the same group. The first is pointer to group, the second can be a relative group name and will be converted to absolute prior to the comparison, so two different references that resolve to reference the same group name produces a True return value.
Definition: mh5gate.c:517
MHEG5ErrorCode MHEG5addItem(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup AddItem elementary action.
MHEG5TokenGroup tokenGroup
Definition: mh5listgroup.h:66
Implementation of the RTGraphics class Description Defines the attributes and behaviour of non-persis...
void MHEG5finalActivate(MHEG5Root *item)
Definition: mh5final.c:260
Implement the MHEG5 Dynamiclineart Class Defines means to dynamically draw vectorial graphical object...
MHEG5ErrorCode MHEG5setFirstItem(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup SetFirstItem elementary action.
MHEG5IntPair position
Definition: mh5listgroup.h:46
MHEG5ErrorCode MHEG5toggleItem(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup ToggleItem elementary action.
void MHEG5cursorShapePrepare(MHEG5CursorShape *cursorShape)
Apply the preparation behaviour of the cursorshape class Apply the preparation behaviour of the curso...
MHEG5Bool lastItemVisible
Definition: mh5listgroup.h:82
#define INFO_PRINT(x)
Definition: mh5debug.h:69
void MHEG5finalDeactivate(MHEG5Root *item)
Definition: mh5final.c:354
Implementation of the Video class Description Defines the attributes and behaviour of an elementary v...
MHEG5Root * MHEG5findObject(MH5GroupRef gid, MHEG5Int id)
Definition: mh5object.c:65
struct sMHEG5Group * MH5GroupPtr
Definition: mh5base.h:95
MHEG5GList * MHEG5resolveGenericInteger(MHEG5GList *params, MHEG5Int *value)
Definition: mh5object.c:510
MHEG5ErrorCode MHEG5getFirstItem(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup GetFirstItem elementary action.
MHEG5ErrorCode MHEG5deselectItem(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup DeselectItem elementary action.
#define MHEG5getMem
Definition: glue_memory.h:93
Implement the MHEG5 Hotspot Class. Defines invisible unlabelled rectangular areas on the screen that ...
MHEG5Final clazz
Definition: mh5root.h:55
union sMH5GroupRef::@5 ptr
void MHEG5objRefStoreValue(MHEG5ObjectRefVariable *objRef, MH5GroupRef ref, MHEG5Int id)
Definition: mh5variable.c:503
Implementation of the Group class Description Defines the structure and behaviour of objects used as ...
void MHEG5ingredientActivate(MHEG5Ingredient *ingredient)
Implementation of Activate behaviour Inherrited from Root class.
void MHEG5listGroupDestruct(MHEG5ListGroup *listGroup)
Implementation of the ListGroup Destruction behaviour.
Definition: mh5listgroup.c:404
void MHEG5tokenGroupPrepare(MHEG5TokenGroup *tokenGroup)
MHEG5Bool multipleSelection
Definition: mh5listgroup.h:71
MHEG5Int tokens_num
Definition: mh5tokengroup.h:65
Implement the MHEG5 Slider Class. Slider Class. Defines the behaviour of sliders. Base class: Visible...
void MHEG5textPrepare(MHEG5Text *text)
Apply the preparation behaviour of the text class Apply the preparation behaviour of the text class...
Definition: mh5text.c:293
MH5GroupPtr grp
Definition: mh5root.h:57
Implement the MHEG5 Variable Class 21 Variable Class Defines a variable within the context of a Group...
void MHEG5listGroupFree(MHEG5ListGroup *listGroup)
Free off all memory associated with the specified object, including any exchanged attributes and inte...
Definition: mh5listgroup.c:238
MHEG5ErrorCode MHEG5delItem(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup DelItem elementary action.
MHEG5Bool wrapAround
Definition: mh5listgroup.h:70
long MHEG5Int
Definition: mh5base.h:73
void MHEG5listGroupAddPosition(MHEG5ListGroup *listGroup, MHEG5Int x, MHEG5Int y)
Adds a new cell position to the ListGroup.
Definition: mh5listgroup.c:267
Implement the MHEG5 ListGroup Class Defines the location of list elements on the screen and theire in...
MHEG5Bool MHEG5sameGroups(MH5GroupRef gref1, MH5GroupRef gref2)
Compares two group ID strings to see whether they both reference the same group. Relative group ID st...
Definition: mh5gate.c:533
#define MHEG5freeMem
Definition: glue_memory.h:94
void MHEG5dynamicLineartPrepare(MHEG5DynamicLineart *dynamicLineart)
Apply the preparation behaviour of the dynamiclineart class Apply the preparation behaviour of the dy...
void MHEG5tokenGroupDestruct(MHEG5TokenGroup *tokenGroup)
void MHEG5listGroupActivate(MHEG5ListGroup *listGroup)
Implementation of the ListGroup Activation behaviour.
Definition: mh5listgroup.c:423
MHEG5PosList * positions
Definition: mh5listgroup.h:74
void MHEG5videoPrepare(MHEG5Video *video)
Apply the preparation behaviour of the video class As this class has no own preparation behaviour thi...
Definition: mh5video.c:125
void MHEG5listGroupDeactivate(MHEG5ListGroup *listGroup)
Implementation of the ListGroup Deactivation behaviour.
Definition: mh5listgroup.c:462
This file defines the profile for the MHEG engine.
void MHEG5hotspotPrepare(MHEG5Hotspot *hotspot)
Definition: mh5hotspot.c:89
void MHEG5tokenGroupDeactivate(MHEG5TokenGroup *tokenGroup)
MHEG5Int x
Definition: mh5base.h:78
void MHEG5sliderPrepare(MHEG5Slider *slider)
Apply the preparation behaviour of the slider class Apply the preparation behaviour of the slider cla...
Definition: mh5slider.c:235
Implement Functions to support Service Gateways. Functions for standarizing several GroupIDs like +DS...
struct sMHEG5PosList * next
Definition: mh5listgroup.h:47
short MHEG5Bool
Definition: mh5base.h:71
Implement the MHEG5 Rectangle Class Rectangle Class Defines a data structure that deals with rectangl...
void MHEG5rtgraphicsPrepare(MHEG5RTGraphics *rtgraphics)
Apply the preparation behaviour of the RTGraphics class As this class has no own preparation behaviou...
MHEG5ErrorCode
Definition: mh5base.h:222
MHEG5ErrorCode MHEG5getListSize(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup GetListSize elementary action.
unsigned char MHEG5Byte
Definition: mh5base.h:74
void MHEG5visibleSetPosition(MHEG5Visible *visible, MHEG5Int x, MHEG5Int y)
This procedure sets the position of the target visible object to the given values.
Definition: mh5visible.c:415
MHEG5TokenSlot * tokens_ptr
Definition: mh5tokengroup.h:66
Event handling. Implementation of a combined queue for events and actions. This is the eventsystem wh...
MHEG5Bool itemSelectionStatus
Definition: mh5listgroup.h:56
Module Description: Implement the MHEG5 Bitmap Class. 32 Bitmap Class Defines the behaviour of a two-...
#define MHEG5TRUE
Definition: mh5base.h:49
Implement functions to retrieve MHEG5objects by GroupID and ID.
void MHEG5palettePrepare(MHEG5Palette *palette)
Definition: mh5palette.c:84
Implementation of the MHEG5 Application Class Defines a set of Ingredient objects, which are shared within an application scope. Base class: Group Subclasses: None Status: Concrete class.
Implementation of the MHEG5 Scene Class Scene Class Defines a set of Ingredient objects to be activat...
Mheg5 logging and debug printing.
MHEG5ErrorCode MHEG5scrollItems(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup ScrollItems elementary action.
MHEG5Ingredient ingredient
Definition: mh5tokengroup.h:61
MHEG5Int len
Definition: mh5base.h:99
MHEG5ErrorCode MHEG5setCellPosition(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup SetCellPosition elementary action.
MHEG5Bool runningStatus
Definition: mh5root.h:51
void MHEG5rectanglePrepare(MHEG5Rectangle *rectangle)
Definition: mh5rectangle.c:120
MHEG5Byte * name
Definition: mh5base.h:102
Implement the MHEG5 PushButton Class. Defines labelled, largely rectangular areas on the screen...
void MHEG5visibleResetPosition(MHEG5Visible *visible)
Reset the position of the visible back to its original values (as stored in originalPosition).
Definition: mh5visible.c:400
MHEG5String groupName
Definition: mh5group.h:53
MHEG5Root root
Definition: mh5group.h:50
MHEG5Int positionCount
Definition: mh5listgroup.h:79
void MHEG5listGroupPrepare(MHEG5ListGroup *listGroup)
Implementation of the ListGroup Preparation behaviour.
Definition: mh5listgroup.c:304
MHEG5Int visibleIndex
Definition: mh5listgroup.h:57
redirection include
MHEG5Int id
Definition: mh5root.h:48
MH5GroupRef groupRef
Definition: mh5listgroup.h:55
void MHEG5switchbuttonPrepare(MHEG5Switchbutton *switchbutton)
Apply the preparation behaviour of the switchbutton class Apply the preparation behaviour of the swit...
void MHEG5objRefValueDestruct(MHEG5ObjectRefVariable *objRef)
void MHEG5pushbuttonPrepare(MHEG5Pushbutton *pushbutton)
MHEG5Bool firstItemVisible
Definition: mh5listgroup.h:81
#define ERROR_PRINT(x)
Definition: mh5debug.h:76
MHEG5Scene * MHEG5getCurrentScene(void)
<Function description>="">
Definition: mh5scene.c:207
MH5GroupRef groupid
Definition: mh5tokengroup.h:52
MHEG5ErrorCode MHEG5selectItem(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup SelectItem elementary action.
MH5GroupPtr group
Definition: mh5base.h:103
Implement the MHEG5 SwitchButton Class. Defines the behaviour of pressable buttons. Base class: PushButton. Subclasses: None. Status: Concrete class.
void MHEG5tokenGroupFree(MHEG5TokenGroup *tokenGroup)
Free off all memory associated with the specified object, including any exchanged attributes and inte...
void MHEG5hypertextPrepare(MHEG5Hypertext *hypertext)
Definition: mh5hypertext.c:262
MHEG5ErrorCode MHEG5getItemStatus(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup GetItemStatus elementary action.
MHEG5GList * MHEG5resolveORef(MHEG5GList *params, MHEG5Root **object)
Definition: mh5object.c:126
void MHEG5lineartPrepare(MHEG5Lineart *lineart)
Definition: mh5lineart.c:215
void MHEG5bitmapPrepare(MHEG5Bitmap *bitmap)
Apply the preparation behaviour of the bitmap class. As this class has no own preparation behaviour t...
Definition: mh5bitmap.c:146
MHEG5TokenManager tokenManager
Definition: mh5tokengroup.h:62
struct sMHEG5ItemList * next
Definition: mh5listgroup.h:58
MHEG5PosList * originalPositions
Definition: mh5listgroup.h:69
MHEG5Int y
Definition: mh5base.h:79
#define MHEG5FALSE
Definition: mh5base.h:48
MHEG5ErrorCode MHEG5getListItem(MHEG5Root *target, MHEG5GList *params)
Implementation of the ListGroup GetListItem elementary action.
uint32_t U32BIT
Definition: techtype.h:86
MHEG5Int firstItem
Definition: mh5listgroup.h:76
void MHEG5sendSync(MHEG5Root *source, MHEG5EventType event, MHEG5Int data)
Store an event in the synchronous event queue.
Definition: mh5queue.c:1651
MHEG5GList * MHEG5resolveGenericORefProper(MHEG5GList *params, MH5GroupRef *pgroupRef, MHEG5Int *id)
Resolve a generic object reference, returning the object reference. The reference can be direct or in...
Definition: mh5object.c:177
Implement the MHEG5 EntryField Class. Defines an interaction widget used by the final user to edit an...
MHEG5Application * MHEG5getCurrentApplication(void)
<Function description>="">
#define DEBUG_PRINT(x)
Definition: mh5debug.h:70
void MHEG5entryfieldPrepare(MHEG5Entryfield *entryfield)
Apply the preparation behaviour of the entryfield class Apply the preparation behaviour of the entryf...
#define TRACE(t, x)
Definition: glue_debug.h:118