MHEG5  18.9.0
MHEG5 Documentation
mh5text.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  *******************************************************************************/
31 /*---includes for this file--------------------------------------------------*/
32 #include "mh5text.h"
33 #include "mh5entryfield.h"
34 #include "mh5object.h" /* for actions */
35 #include "mh5variable.h" /* for actions */
36 #include "mh5display.h" /* for actions */
37 #include "mh5memory.h" /* for constructor/destructor */
38 #include "mh5application.h" /* Default Colour */
39 #include "mh5profile.h"
40 #include "mh5debug.h"
41 #include <stdlib.h>
42 #include <string.h>
43 #include "mh5drawtext.h"
44 #include "mg_api.h"
45 
46 #define UNICODE_BOM_LITTLE_ENDIAN 0xFFFE
47 #define UNICODE_BOM_BIG_ENDIAN 0xFEFF
48 
49 /*
50  Debug
51  */
52 #ifdef MH5PRINTOUT
53 
60 void MHEG5textPrint(MHEG5Text *text, char *out)
61 {
62  /* Base Class */
63  MHEG5visiblePrint(&text->visible, out);
64 
65  /* Exchanged Attributes */
67  {
68  MHEG5indent(out);
69  MHEG_PRINT(out, ":OrigFont ");
70  MHEG5fontBodyPrint(text->originalFont, out);
71  MHEG5newLine(out);
72  }
73 
74  if (text->originalFontAttributes.len)
75  {
76  MHEG5indent(out);
77  MHEG_PRINT(out, ":FontAttributes ");
78  MHEG5stringPrint(text->originalFontAttributes, out);
79  MHEG5newLine(out);
80  }
81 
82 /*
83  if (text->originalTextColour.direct)
84  {
85  MHEG5indent(out);
86  MHEG_PRINT(out,":OriginalTextColour ");
87  MHEG5colourPrint(text->originalTextColour,out);
88  MHEG5newLine(out);
89  }
90 
91  if (text->originalBackgroundColour.direct)
92  {
93  MHEG5indent(out);
94  MHEG_PRINT(out,":OriginalBackgroundColour ");
95  MHEG5colourPrint(text->originalBackgroundColour,out);
96  MHEG5newLine(out);
97  }
98  */
99  if (text->characterSet)
100  {
101  MHEG5indent(out);
102  MHEG_PRINT(out, ":CharacterSet ");
103  MHEG5intPrint(text->characterSet, out);
104  MHEG5newLine(out);
105  }
106 
108  {
109  MHEG5indent(out);
110  MHEG_PRINT(out, ":HJustification ");
111  switch (text->horizontalJustification)
112  {
113  case HJUSTIFICATION_END: MHEG_PRINT(out, "end"); break;
114  case HJUSTIFICATION_CENTRE: MHEG_PRINT(out, "centre"); break;
115  case HJUSTIFICATION_JUSTIFIED: MHEG_PRINT(out, "justified"); break;
116  default:;
117  }
118  MHEG5newLine(out);
119  }
120 
122  {
123  MHEG5indent(out);
124  MHEG_PRINT(out, ":VJustification ");
125  switch (text->verticalJustification)
126  {
127  case VJUSTIFICATION_END: MHEG_PRINT(out, "end"); break;
128  case VJUSTIFICATION_CENTRE: MHEG_PRINT(out, "centre"); break;
129  case VJUSTIFICATION_JUSTIFIED: MHEG_PRINT(out, "justified"); break;
130  default:;
131  }
132  MHEG5newLine(out);
133  }
134 
135  if (text->verticalLineOrientation)
136  {
137  MHEG5indent(out);
138  MHEG_PRINT(out, ":LineOrientation vertical");
139  MHEG5newLine(out);
140  }
141 
142  if (text->startCorner != 0)
143  {
144  MHEG5indent(out);
145  MHEG_PRINT(out, ":StartCorner ");
146  switch (text->startCorner)
147  {
148  case 1: MHEG_PRINT(out, "upper-right"); break;
149  case 2: MHEG_PRINT(out, "lower-left"); break;
150  case 3: MHEG_PRINT(out, "lower-right"); break;
151  default:;
152  }
153  MHEG5newLine(out);
154  }
155 
157  {
158  MHEG5indent(out);
159  MHEG_PRINT(out, ":TextColour ");
160  MHEG5colourPrint(text->originalTextColour, out);
161  MHEG5newLine(out);
162  }
163 
165  {
166  MHEG5indent(out);
167  MHEG_PRINT(out, ":BackgroundColour ");
168  MHEG5colourPrint(text->originalBackgroundColour, out);
169  MHEG5newLine(out);
170  }
171 
172  if (text->textWrapping)
173  {
174  MHEG5indent(out);
175  MHEG_PRINT(out, ":TextWrapping TRUE");
176  MHEG5newLine(out);
177  }
178 }
179 
180 #endif
181 
182 /*
183  Constructor
184  */
191 {
192  assert(text);
193 
194  MHEG5visibleInit(&text->visible);
195 }
196 
205 {
206  assert(text);
207 
208  MHEG5visibleFree(&text->visible);
209 
210  if (text->originalFont.referenced)
211  {
212  if (text->originalFont.ref.referenced.grp.len != 0)
213  {
215  }
216  }
217  else
218  {
220  }
224 
226 }
227 
233 {
234  MHEG5Text *destination;
235 
236  assert(source);
237  destination = (MHEG5Text *)MHEG5getMem( sizeof(MHEG5Text));
238  if (destination != NULL)
239  {
240  memset( destination, 0, sizeof(MHEG5Text));
241  destination->visible.ingredient.root.clazz = MHEG5TEXT;
242 
243  MHEG5visibleClone(&destination->visible, &source->visible);
244 
245  destination->originalFont.referenced = source->originalFont.referenced;
246  if (source->originalFont.referenced)
247  {
248  if (source->originalFont.ref.referenced.grp.len != 0)
249  {
250  MHEG5String name;
251  name.len = source->originalFont.ref.referenced.grp.len;
252  name.data = source->originalFont.ref.referenced.grp.ptr.name;
253  name = MHEG5stringCopy(name);
254  destination->originalFont.ref.referenced.grp.len = name.len;
255  destination->originalFont.ref.referenced.grp.ptr.name = name.data;
256  }
257  else
258  {
259  destination->originalFont.ref.referenced.grp.len = 0;
260  destination->originalFont.ref.referenced.grp.ptr.group = source->originalFont.ref.referenced.grp.ptr.group;
261  }
262  destination->originalFont.ref.referenced.id = source->originalFont.ref.referenced.id;
263  }
264  else
265  {
267  }
269  MHEG5genericCopy(&destination->originalTextColour, &source->originalTextColour);
271  destination->characterSet = source->characterSet;
272  destination->horizontalJustification = source->horizontalJustification;
273  destination->verticalJustification = source->verticalJustification;
274  destination->verticalLineOrientation = source->verticalLineOrientation;
275  destination->startCorner = source->startCorner;
276  destination->textWrapping = source->textWrapping;
277  }
278  return destination;
279 }
280 
281 /*
282  Internal behaviours
283  */
294 {
295  assert(text);
296  text->font.referenced = text->originalFont.referenced;
297  if (text->font.referenced)
298  {
299  if (text->originalFont.ref.referenced.grp.len != 0)
300  {
301  text->font.ref.referenced.grp = text->originalFont.ref.referenced.grp;
302  }
303  else
304  {
305  text->font.ref.referenced.grp.len = 0;
306  text->font.ref.referenced.grp.ptr.group = text->originalFont.ref.referenced.grp.ptr.group;
307  }
308  text->font.ref.referenced.id = text->originalFont.ref.referenced.id;
309  }
310  else
311  {
313  }
314 
318 
320 }
321 
331 {
332  assert(text);
334  {
335  MHEG5textPrepare( text );
336  }
338 }
339 
349 {
350  assert(text);
351  if (text->visible.graphic_data != NULL)
352  {
354  text->visible.graphic_data = NULL;
355  }
357 }
358 
366 {
367  assert(text);
369  if (text->font.referenced)
370  {
371  if (text->font.ref.referenced.grp.len != 0)
372  {
374  }
375  }
376  else
377  {
379  }
380 
384 }
385 
387 {
388  if (((MHEG5Root *)text)->clazz == MHEG5ENTRYFIELD)
389  {
391  }
392  else if (((MHEG5Root *)text)->clazz == MHEG5HYPERTEXT)
393  {
395  }
396  else
397  {
398  MHEG5drawText( text );
399  }
401 }
402 
403 /*
404  Actions
405  */
406 
422 {
423  MHEG5Root *tVar = 0;
424 
425  assert(target);
426 
427  if ((target->clazz != MHEG5TEXT) &&
428  (target->clazz != MHEG5HYPERTEXT) &&
429  (target->clazz != MHEG5ENTRYFIELD))
430  return MHEG5ERR_WRONGTARGET;
431 
432  if (!params)
434  MHEG5resolveORef(params, &tVar);
435  if (!tVar)
437  if (!tVar->runningStatus)
439 
440  /* What should happen if content is included, but TextContentVar is a
441  * ContentRefVariable or content is referenced but TextContentVar is an
442  * OctetStringVariable? Current implementation returns MHEG5ERR_WRONGPARAM.
443  */
444  if (((MHEG5Ingredient *) target)->content.referenced)
445  {
446  if (tVar->clazz != MHEG5CONTENTREFVARIABLE)
447  return MHEG5ERR_WRONGPARAM;
448  MHEG5stringDestruct(&((MHEG5ContentVariable *) tVar)->contentData);
449  ((MHEG5ContentVariable *) tVar)->contentData = MHEG5stringCopy(((MHEG5Ingredient *) target)->content.ref.referenced.reference);
450  }
451  else
452  {
453  if (tVar->clazz != MHEG5OCTETSTRINGVARIABLE)
454  return MHEG5ERR_WRONGPARAM;
455  MHEG5stringDestruct(&((MHEG5OctetStringVariable *) tVar)->value);
456  ((MHEG5OctetStringVariable *) tVar)->value = MHEG5stringCopy(((MHEG5Ingredient *) target)->content.ref.included);
457  }
458  return MHEG5ERR_NOERROR;
459 }
460 
471 {
472  MHEG5Root *tVar = 0;
473 
474  assert(target);
475 
476  if ((target->clazz != MHEG5TEXT) && (target->clazz != MHEG5HYPERTEXT) && (target->clazz != MHEG5ENTRYFIELD))
477  {
478  return MHEG5ERR_WRONGTARGET;
479  }
480 
481  if (!params)
482  {
484  }
485 
486  MHEG5resolveORef(params, &tVar);
487 
488  if (!tVar)
489  {
491  }
492 
493  if (!tVar->runningStatus)
494  {
496  }
497 
498  if (tVar->clazz != MHEG5OCTETSTRINGVARIABLE)
499  {
500  return MHEG5ERR_WRONGPARAM;
501  }
502 
503  MHEG5stringDestruct(&((MHEG5OctetStringVariable *) tVar)->value);
504 
505  if ((target->clazz == MHEG5TEXT) || (target->clazz == MHEG5HYPERTEXT))
506  {
507  #ifdef TRACING
508  if (mheg_trace_debug & TACTIONS)
509  {
510  char buff[256];
511  strcpy(buff, T_NL "MHEG5getTextData ");
512  MHEG5stringTrace(((MHEG5Text *) target)->textDataRaw, buff, 0, 120 );
513  DBG_PRINTF(buff);
514  DBG_PRINTF(" )");
515  }
516  #endif
517  /* For non-interactible Text classes, the raw text data is kept. This
518  * allows non-UTF-8 complient content to be returned.
519  */
520  ((MHEG5OctetStringVariable *) tVar)->value = MHEG5stringCopy(((MHEG5Text *) target)->textDataRaw);
521  }
522  else
523  {
524  if (((MHEG5Ingredient *)target)->contentHook == 11)
525  {
526  MHEG5textContentUnadaptUTF16((MHEG5Text *)target, &((MHEG5OctetStringVariable *) tVar)->value.data, &((MHEG5OctetStringVariable *) tVar)->value.len);
527  }
528  else
529  {
530  /* For entryfield class, we must unadapt the existing content */
531  MHEG5textContentUnadapt((MHEG5Text *)target, &((MHEG5OctetStringVariable *) tVar)->value.data, &((MHEG5OctetStringVariable *) tVar)->value.len);
532  }
533  }
534 
535  return MHEG5ERR_NOERROR;
536 }
537 
549 {
550  MHEG5String newFontAttributes;
551  MHEG5Bool invalidString;
552  MHEG5Text *text;
553 
554  assert(target);
555 
556  if ((target->clazz != MHEG5TEXT) && (target->clazz != MHEG5HYPERTEXT) && (target->clazz != MHEG5ENTRYFIELD))
557  {
558  return MHEG5ERR_WRONGTARGET;
559  }
560  text = (MHEG5Text *) target;
561 
562  if (!params)
564  MHEG5resolveGenericOctetString(params, &newFontAttributes, &invalidString);
565  if (invalidString == MHEG5TRUE)
566  return MHEG5ERR_NOERROR;
567 
568  text->fontAttributes = MHEG5stringCopy(newFontAttributes);
569 
570  MHEG5textRedraw((MHEG5Text *) target);
571 
572  return MHEG5ERR_NOERROR;
573 }
574 
586 {
587  MHEG5Colour newTextColour;
588  MHEG5Text *text;
589 
590  assert(target);
591 
592  if ((target->clazz != MHEG5TEXT) && (target->clazz != MHEG5HYPERTEXT) && (target->clazz != MHEG5ENTRYFIELD))
593  {
594  return MHEG5ERR_WRONGTARGET;
595  }
596  text = (MHEG5Text *) target;
597 
598  if (!params)
600  MHEG5resolveGenericGeneric(params, &newTextColour);
601 
603  MHEG5genericCopy(&text->textColour, &newTextColour);
604 
605  MHEG5textRedraw((MHEG5Text *) target);
606 
607  return MHEG5ERR_NOERROR;
608 }
609 
621 {
622  MHEG5Colour newBackgroundColour;
623  MHEG5Text *text;
624 
625  assert(target);
626 
627  if ((target->clazz != MHEG5TEXT) && (target->clazz != MHEG5HYPERTEXT) && (target->clazz != MHEG5ENTRYFIELD))
628  {
629  return MHEG5ERR_WRONGTARGET;
630  }
631  text = (MHEG5Text *) target;
632 
633  if (!params)
635  MHEG5resolveGenericGeneric(params, &newBackgroundColour);
636 
637  MHEG5genericCopy(&text->backgroundColour, &newBackgroundColour);
638 
639  MHEG5textRedraw((MHEG5Text *) target);
640 
641  return MHEG5ERR_NOERROR;
642 }
643 
656 {
657  MHEG5Text *text;
658  MHEG5Generic g;
659 
660  assert(target);
661 
662  if ((target->clazz != MHEG5TEXT) && (target->clazz != MHEG5HYPERTEXT) && (target->clazz != MHEG5ENTRYFIELD))
663  {
664  return MHEG5ERR_WRONGTARGET;
665  }
666  text = (MHEG5Text *) target;
667 
668  if (!params)
670  MHEG5resolveGenericGeneric(params, &g);
671  if (g.type == MHEG5OBJECTREF)
672  {
673  if (text->font.referenced)
674  {
676  }
677  else
678  {
680  }
681  text->font.referenced = MHEG5TRUE;
682  if (g.value.o.gref.len != 0)
683  {
684  MHEG5String name;
685  name.len = g.value.o.gref.len;
686  name.data = g.value.o.gref.ptr.name;
687  name = MHEG5stringCopy(name);
688  text->font.ref.referenced.grp.len = name.len;
689  text->font.ref.referenced.grp.ptr.name = name.data;
690  }
691  else
692  {
693  text->font.ref.referenced.grp = g.value.o.gref;
694  }
695  text->font.ref.referenced.id = g.value.o.id;
696  }
697  else if (g.type == MHEG5OCTETSTRING)
698  {
699  if (text->font.referenced)
700  {
702  }
703  else
704  {
706  }
707  text->font.referenced = MHEG5FALSE;
708  text->font.ref.included = MHEG5stringCopy(g.value.s);
709  }
710 
711  MHEG5textRedraw((MHEG5Text *) target);
712 
713  return MHEG5ERR_NOERROR;
714 }
715 
721 static MHEG5Int getMarkupLength(unsigned char *data, MHEG5Int len)
722 {
723  if (len > 0)
724  {
725  if (*data >= 0x40 && *data <= 0x5e)
726  {
727  /* Start of markup */
728  MHEG5Int paramLength;
729 
730  if (len > 1)
731  {
732  paramLength = data[1];
733  }
734  else
735  {
736  paramLength = -1;
737  }
738 
739  /* Return the length of markup_start_identifier,
740  * parameters_length and parameter_bytes
741  */
742  return paramLength + 2;
743  }
744 
745  if (*data >= 0x60 && *data <= 0x7e)
746  {
747  /* End of markup */
748  /* Return the length of end_of_markup and markup_end_identifier bytes
749  */
750  return 1;
751  }
752  }
753  /* Unknown markup identifier */
754  return 0;
755 }
756 
765 void MHEG5textUtf8Content(MHEG5Text *text, unsigned char *data, int len)
766 {
767  int pos;
768  int adaptedDataLen;
769  unsigned short *adaptedData;
770 
771  /* Set default adapted data to be empty */
772  text->visible.ingredient.data = 0;
773  text->visible.ingredient.dataLen = 0;
774 
775  /* Create a temporary buffer the maximum possible adapted size */
776  adaptedData = MHEG5getMem(len * sizeof(unsigned short));
777 
778  if (adaptedData == NULL)
779  {
780  ERROR_PRINT(("ERROR : MHEG5textContentAdapt out of memory\n"));
781  return;
782  }
783 
784  pos = 0;
785  adaptedDataLen = 0;
786  while (pos < len)
787  {
788  if (data[pos] == 0x1b)
789  {
790  /* Skip all markup - copy it unchanged */
791  unsigned int markupLength;
792 
793  adaptedData[adaptedDataLen] = data[pos];
794  pos++;
795  adaptedDataLen++;
796 
797  markupLength = getMarkupLength(&data[pos], len - pos);
798 
799  while (markupLength > 0)
800  {
801  adaptedData[adaptedDataLen] = data[pos];
802  pos++;
803  adaptedDataLen++;
804  markupLength--;
805  }
806  }
807  else
808  {
809  /* Convert UTF8 chars to unicode character:
810  *
811  * 0x00000000 - 0x0000007F:
812  * 0xxxxxxx
813  *
814  * 0x00000080 - 0x000007FF:
815  * 110xxxxx 10xxxxxx
816  *
817  * 0x00000800 - 0x0000FFFF:
818  * 1110xxxx 10xxxxxx 10xxxxxx
819  *
820  * 0x00010000 - 0x001FFFFF:
821  * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
822  *
823  * The xxx bit positions are filled with the bits of the
824  * character code number in binary representation. Only the
825  * shortest possible multibyte sequence which can represent
826  * the code number of the character can be used.
827  */
828  if ((data[pos] & 0x80) == 0x00)
829  {
830  /* 1 Byte code */
831  adaptedData[adaptedDataLen] = data[pos];
832  }
833  else if ((data[pos] & 0xe0) == 0xc0)
834  {
835  /* 2 Byte code */
836  if (pos + 1 == len)
837  {
838  /* This char exceeds the end of data - break out of while loop */
839  /* assert(0); */
840  break;
841  }
842  adaptedData[adaptedDataLen] = (data[pos] & 0x1F) << 6;
843  pos++;
844  adaptedData[adaptedDataLen] |= (data[pos] & 0x3F);
845  }
846  else if ((data[pos] & 0xf0) == 0xe0)
847  {
848  /* 3 Byte code */
849  if (pos + 2 >= len)
850  {
851  /* This char exceeds the end of data - break out of while loop */
852  /* assert(0); DTG X.1 test gets here */
853  break;
854  }
855  adaptedData[adaptedDataLen] = (data[pos] & 0x0F) << 12;
856  pos++;
857  adaptedData[adaptedDataLen] |= (data[pos] & 0x3F) << 6;
858  pos++;
859  adaptedData[adaptedDataLen] |= (data[pos] & 0x3F);
860  }
861  else if ((data[pos] & 0xf8) == 0xf0)
862  {
863  /* 4 Byte code - not used by UK1.05 profile */
864  if (pos + 3 >= len)
865  {
866  /* This char exceeds the end of data - break out of while loop */
867  /* assert(0); */
868  break;
869  }
870  adaptedData[adaptedDataLen] = 0;
871  pos += 3;
872  }
873  else
874  {
875  /* Unrecognised code - ignore it. */
876  adaptedData[adaptedDataLen] = 0;
877  }
878  pos++;
879  adaptedDataLen++;
880  }
881  }
882 
883  if (((MHEG5Root *)text)->clazz == MHEG5ENTRYFIELD)
884  {
885  if ((((MHEG5Entryfield *)text)->maxlength > 0) &&
886  (adaptedDataLen > ((MHEG5Entryfield *)text)->maxlength))
887  {
888  adaptedDataLen = ((MHEG5Entryfield *)text)->maxlength;
889  }
890  }
891 
892  if (adaptedDataLen == len)
893  {
894  /* The temporary buffer was already the correct size. Just store a
895  * pointer to it - there's no need to copy the data again.
896  */
897  text->visible.ingredient.data = (unsigned char *)adaptedData;
898  text->visible.ingredient.dataLen = adaptedDataLen;
899  }
900  else
901  {
902  /* We now know the size of the adapted content, so allocate a buffer for
903  * it and copy the adapted data into it from the temporary buffer.
904  */
905  text->visible.ingredient.data = MHEG5getMem(adaptedDataLen * sizeof(unsigned short));
906  if (text->visible.ingredient.data != 0)
907  {
908  memcpy(text->visible.ingredient.data, adaptedData,
909  adaptedDataLen * sizeof(unsigned short));
910  text->visible.ingredient.dataLen = adaptedDataLen;
911  }
912 
913  /* Free off the temporay buffer */
914  MHEG5freeMem(adaptedData);
915  }
916 
917  if (((MHEG5Root *)text)->clazz != MHEG5ENTRYFIELD)
918  {
919  /* Make a copy of the raw content for Text and HyperText classes. Note that
920  * this is not done for EntryField classes, which can alter the TextData
921  * internal attribute through interaction.
922  */
923  /* Destruct the old copy */
925 
926  /* Allocate memory for new raw text data */
927  text->textDataRaw.data = STR_DataAlloc( len );
928  if (text->textDataRaw.data == NULL)
929  {
930  ERROR_PRINT(("ERROR : MHEG5textContentAdapt out of memory\n"));
931  return;
932  }
933 
934  /* Copy the raw text data */
935  memcpy(text->textDataRaw.data, data, len);
936  text->textDataRaw.len = len;
937 #ifdef DRAW_IN_ADVANCE
938  if (((MHEG5Root *)text)->clazz == MHEG5HYPERTEXT)
939  {
941  }
942  else
943  {
944  MHEG5drawText((MHEG5Text *)text );
945  }
946  }
947  else
948  {
950 #endif /*DRAW_IN_ADVANCE*/
951  }
952 }
953 
961 void MHEG5textUtf16Content(MHEG5Text *text, unsigned char *data, int len)
962 {
963  unsigned char *p_data, *p_end;
964  int is_little_endian;
965  int adpt_len, m_len;
966  unsigned short *p_adpt, tmp_adpt;
967 
968  tmp_adpt = (data[0] << 8) | data[1];
969  text->byteOrderMark = BOM_NONE;
970  switch (tmp_adpt)
971  {
973  is_little_endian = 1;
974  data += 2; /* skip BOM */
975  len -= 2;
977  break;
978 
980  data += 2; /* skip BOM */
981  len -= 2;
983  /* fallthrough */
984 
985  default: /* assumes big endian */
986  is_little_endian = 0;
987  }
988 
989  adpt_len = 0;
990  p_data = data;
991  p_end = data + len;
992  if (is_little_endian)
993  {
994  while (p_data < p_end)
995  {
996  tmp_adpt = *p_data;
997  p_data++;
998  tmp_adpt |= *p_data << 8;
999  p_data++;
1000  adpt_len++;
1001  if (tmp_adpt == 0x001B)
1002  {
1003  m_len = getMarkupLength(p_data, p_end - p_data);
1004  adpt_len += m_len;
1005  p_data += m_len;
1006  }
1007  }
1008  }
1009  else
1010  {
1011  while (p_data < p_end)
1012  {
1013  tmp_adpt = *p_data << 8;
1014  p_data++;
1015  tmp_adpt |= *p_data;
1016  p_data++;
1017  adpt_len++;
1018  if (tmp_adpt == 0x001B)
1019  {
1020  m_len = getMarkupLength(p_data, p_end - p_data);
1021  adpt_len += m_len;
1022  p_data += m_len;
1023  }
1024  }
1025  }
1026 
1027  /* Create a buffer the right adapted size */
1028  p_adpt = MHEG5getMem(adpt_len * sizeof(unsigned short));
1029 
1030  if (p_adpt == NULL)
1031  {
1032  ERROR_PRINT(("ERROR : MHEG5textContentAdapt out of memory\n"));
1033  }
1034  else
1035  {
1036  text->visible.ingredient.data = (unsigned char *)p_adpt;
1037  text->visible.ingredient.dataLen = adpt_len;
1038 
1039  p_data = data;
1040  if (is_little_endian)
1041  {
1042  while (p_data < p_end)
1043  {
1044  *p_adpt = *p_data;
1045  p_data++;
1046  *p_adpt |= *p_data << 8;
1047  p_data++;
1048  if (*p_adpt == 0x001B)
1049  {
1050  p_adpt++;
1051  m_len = getMarkupLength(p_data, p_end - p_data);
1052  while (m_len--)
1053  {
1054  *p_adpt++ = *p_data++;
1055  }
1056  }
1057  else
1058  {
1059  p_adpt++;
1060  }
1061  }
1062  }
1063  else
1064  {
1065  while (p_data < p_end)
1066  {
1067  *p_adpt = *p_data << 8;
1068  p_data++;
1069  *p_adpt |= *p_data;
1070  p_data++;
1071  if (*p_adpt == 0x001B)
1072  {
1073  p_adpt++;
1074  m_len = getMarkupLength(p_data, p_end - p_data);
1075  /* copy mark up */
1076  while (m_len--)
1077  {
1078  *p_adpt++ = *p_data++;
1079  }
1080  }
1081  else
1082  {
1083  p_adpt++;
1084  }
1085  }
1086  }
1087  }
1088 
1089  if (((MHEG5Root *)text)->clazz == MHEG5ENTRYFIELD)
1090  {
1091  if ((((MHEG5Entryfield *)text)->maxlength > 0) &&
1092  (adpt_len > ((MHEG5Entryfield *)text)->maxlength))
1093  {
1094  adpt_len = ((MHEG5Entryfield *)text)->maxlength;
1095  }
1096  }
1097 
1098  if (((MHEG5Root *)text)->clazz != MHEG5ENTRYFIELD)
1099  {
1100  /* Make a copy of the raw content for Text and HyperText classes. Note that
1101  * this is not done for EntryField classes, which can alter the TextData
1102  * internal attribute through interaction.
1103  */
1104  /* Destruct the old copy */
1106 
1107  /* Allocate memory for new raw text data */
1108  text->textDataRaw.data = STR_DataAlloc( len );
1109  if (text->textDataRaw.data == NULL)
1110  {
1111  ERROR_PRINT(("ERROR : MHEG5textContentAdapt out of memory\n"));
1112  return;
1113  }
1114 
1115  /* Copy the raw text data */
1116  memcpy(text->textDataRaw.data, data, len);
1117  text->textDataRaw.len = len;
1118 #ifdef DRAW_IN_ADVANCE
1119  if (((MHEG5Root *)text)->clazz == MHEG5HYPERTEXT)
1120  {
1122  }
1123  else
1124  {
1125  MHEG5drawText((MHEG5Text *)text );
1126  }
1127  }
1128  else
1129  {
1131 #endif /*DRAW_IN_ADVANCE*/
1132  }
1133 }
1134 
1143 void MHEG5textContentUnadapt(MHEG5Text *text, MHEG5Byte **utf8Data, MHEG5Int *utf8Len)
1144 {
1145  int pos;
1146  int unadaptedLen;
1147  unsigned char *unadaptedData;
1148  unsigned short *data;
1149  int dataLen;
1150 
1151  *utf8Data = 0;
1152  *utf8Len = 0;
1153 
1154  data = (unsigned short *)text->visible.ingredient.data;
1155  dataLen = text->visible.ingredient.dataLen;
1156 
1157  if ((data == 0) || (dataLen == 0))
1158  {
1159  /* No data to unadapt */
1160  return;
1161  }
1162 
1163  /* Allocate some memory for storing the unadapted content. Since we don't
1164  * know the size, allocate the largest possible required (3 times the number
1165  * of characters in the text content) as a temporary buffer.
1166  */
1167  unadaptedData = MHEG5getMem( text->visible.ingredient.dataLen * 3 );
1168 
1169  if (unadaptedData == NULL)
1170  {
1171  /* Unable to allocate memory for unadapted data */
1172  ERROR_PRINT(("ERROR: MHEG5textContentUnadapt out of memory\n"));
1173  return;
1174  }
1175 
1176  pos = 0;
1177  unadaptedLen = 0;
1178  while (pos < dataLen)
1179  {
1180  if (data[pos] == 0x1b)
1181  {
1182  /* Skip all markup - copy it unchanged */
1183  unsigned int markupLength;
1184 
1185  if ((data[pos + 1] >= 0x40) && (data[pos + 1] <= 0x5e))
1186  {
1187  markupLength = data[pos + 2] + 3;
1188  }
1189  else if ((data[pos + 1] >= 0x60) && (data[pos + 1] <= 0x7e))
1190  {
1191  markupLength = 2;
1192  }
1193  else
1194  {
1195  markupLength = 1;
1196  }
1197 
1198  while (markupLength > 0)
1199  {
1200  assert(data[pos] <= 0xff);
1201  unadaptedData[unadaptedLen] = (unsigned char)data[pos];
1202  pos++;
1203  unadaptedLen++;
1204  markupLength--;
1205  }
1206  }
1207  else
1208  {
1209  /* Convert from Unicode to UTF8 encoding */
1210  if (data[pos] <= 0x7f)
1211  {
1212  /* 0x00000000 - 0x0000007F:
1213  * 0xxxxxxx
1214  */
1215  unadaptedData[unadaptedLen++] = (unsigned char)data[pos];
1216  }
1217  else if (data[pos] <= 0x7ff)
1218  {
1219  /* 0x00000080 - 0x000007FF:
1220  * 110xxxxx 10xxxxxx
1221  */
1222  unadaptedData[unadaptedLen++] = (unsigned char)((data[pos] & 0x07c0) >> 6) | 0xc0;
1223  unadaptedData[unadaptedLen++] = (unsigned char)(data[pos] & 0x003f) | 0x80;
1224  }
1225  else
1226  {
1227  /* 0x00000800 - 0x0000FFFF:
1228  * 1110xxxx 10xxxxxx 10xxxxxx
1229  */
1230  unadaptedData[unadaptedLen++] = ((data[pos] & 0xf000) >> 12) | 0xe0;
1231  unadaptedData[unadaptedLen++] = ((data[pos] & 0x0fc0) >> 6) | 0x80;
1232  unadaptedData[unadaptedLen++] = (data[pos] & 0x003f) | 0x80;
1233  }
1234 
1235  pos++;
1236  }
1237  }
1238 
1239  /* We now know the size of the unadapted content, so allocate a buffer for
1240  * it and copy the unadapted data into it from the temporary buffer.
1241  */
1242  *utf8Data = STR_DataAlloc( unadaptedLen );
1243  if (*utf8Data != 0)
1244  {
1245  memcpy(*utf8Data, unadaptedData, unadaptedLen);
1246  *utf8Len = unadaptedLen;
1247  }
1248 
1249  /* Free off out temporary buffer */
1250  MHEG5freeMem(unadaptedData);
1251 }
1252 
1261 void MHEG5textContentUnadaptUTF16(MHEG5Text *text, MHEG5Byte **utf16Data, MHEG5Int *utf16Len)
1262 {
1263  int pos;
1264  int unadaptedLen;
1265  unsigned char *unadaptedData;
1266  unsigned short *data;
1267  int dataLen;
1268 
1269  *utf16Data = 0;
1270  *utf16Len = 0;
1271 
1272  data = (unsigned short *)text->visible.ingredient.data;
1273  dataLen = text->visible.ingredient.dataLen;
1274 
1275  if ((data == 0) || (dataLen == 0))
1276  {
1277  /* No data to unadapt */
1278  return;
1279  }
1280 
1281  /* Allocate some memory for storing the unadapted content. Since we don't
1282  * know the size, allocate the largest possible required (3 times the number
1283  * of characters in the text content) as a temporary buffer.
1284  */
1285  unadaptedData = MHEG5getMem( text->visible.ingredient.dataLen * 3 );
1286 
1287  if (unadaptedData == NULL)
1288  {
1289  /* Unable to allocate memory for unadapted data */
1290  ERROR_PRINT(("ERROR: MHEG5textContentUnadapt out of memory\n"));
1291  return;
1292  }
1293 
1294  pos = 0;
1295 
1296  if (text->byteOrderMark == BOM_LITTLE_ENDIAN)
1297  {
1298  unadaptedData[0] = 0xFF;
1299  unadaptedData[1] = 0xFE;
1300  unadaptedLen = 2;
1301  }
1302  else if (text->byteOrderMark == BOM_BIG_ENDIAN)
1303  {
1304  unadaptedData[0] = 0xFE;
1305  unadaptedData[1] = 0xFF;
1306  unadaptedLen = 2;
1307  }
1308  else
1309  {
1310  unadaptedLen = 0;
1311  }
1312 
1313  while (pos < dataLen)
1314  {
1315  if (data[pos] == 0x1b)
1316  {
1317  /* Skip all markup - copy it unchanged */
1318  unsigned int markupLength;
1319 
1320  if ((data[pos + 1] >= 0x40) && (data[pos + 1] <= 0x5e))
1321  {
1322  markupLength = data[pos + 2] + 3;
1323  }
1324  else if ((data[pos + 1] >= 0x60) && (data[pos + 1] <= 0x7e))
1325  {
1326  markupLength = 2;
1327  }
1328  else
1329  {
1330  markupLength = 1;
1331  }
1332 
1333  while (markupLength > 0)
1334  {
1335  assert(data[pos] <= 0xff);
1336  unadaptedData[unadaptedLen] = (unsigned char)data[pos];
1337  pos++;
1338  unadaptedLen++;
1339  markupLength--;
1340  }
1341  }
1342  else
1343  {
1344  /* Convert from Unicode to UTF16 encoding */
1345  if (text->byteOrderMark == BOM_LITTLE_ENDIAN)
1346  {
1347  unadaptedData[unadaptedLen++] = data[pos] & 0xff;
1348  unadaptedData[unadaptedLen++] = (data[pos] >> 8) & 0xff;
1349  }
1350  else
1351  {
1352  unadaptedData[unadaptedLen++] = (data[pos] >> 8) & 0xff;
1353  unadaptedData[unadaptedLen++] = data[pos] & 0xff;
1354  }
1355  pos++;
1356  }
1357  }
1358  /* We now know the size of the unadapted content, so allocate a buffer for
1359  * it and copy the unadapted data into it from the temporary buffer.
1360  */
1361  *utf16Data = STR_DataAlloc( unadaptedLen );
1362  if (*utf16Data != 0)
1363  {
1364  memcpy(*utf16Data, unadaptedData, unadaptedLen);
1365  *utf16Len = unadaptedLen;
1366  }
1367 
1368  /* Free off out temporary buffer */
1369  MHEG5freeMem(unadaptedData);
1370 }
1371 
1378 {
1380 }
1381 
MHEG5Bool availabilityStatus
Definition: mh5root.h:52
#define BOM_LITTLE_ENDIAN
Definition: mh5text.h:53
U8BIT indirect
Definition: mh5base.h:149
void MHEG5textUtf8Content(MHEG5Text *text, unsigned char *data, int len)
Adapt new content for Text objects. Content is encoded using UTF8 - this is converted to 16 bit unico...
Definition: mh5text.c:765
MH5GroupRef gref
Definition: mh5base.h:110
MHEG5Visible visible
Definition: mh5text.h:62
MHEG5Byte * data
Definition: mh5ingredient.h:80
void MHEG5visibleActivate(MHEG5Visible *visible)
Apply the activation behaviour of the visible class. Apply the activation behaviour off the visible c...
Definition: mh5visible.c:306
void MHEG5textUtf16Content(MHEG5Text *text, unsigned char *data, int len)
Content for Text objects is encoded using UTF16.
Definition: mh5text.c:961
#define HJUSTIFICATION_JUSTIFIED
Definition: mh5text.h:42
#define BOM_BIG_ENDIAN
Definition: mh5text.h:54
#define DBG_PRINTF(...)
Definition: glue_debug.h:127
const char * data
Definition: mh5gate.c:56
MHEG5Int verticalJustification
Definition: mh5text.h:71
void MHEG5drawHypertext(MHEG5Hypertext *hypertxt)
Definition: mh5drawtext.c:578
#define HJUSTIFICATION_START
Definition: mh5text.h:39
MHEG5Int horizontalJustification
Definition: mh5text.h:70
MHEG5String s
Definition: mh5base.h:156
MHEG5Text * MHEG5textClone(MHEG5Text *source)
Copy a text object with original values.
Definition: mh5text.c:232
void MHEG5textActivate(MHEG5Text *text)
Apply the activation behaviour of the text class. As this class has no own activation behaviour this ...
Definition: mh5text.c:330
MHEG5ObjectReference o
Definition: mh5base.h:159
U16BIT type
Definition: mh5base.h:151
unsigned char * STR_DataAlloc(unsigned int size)
Definition: glue_memory.c:596
void MHEG5textRedraw(MHEG5Text *text)
Definition: mh5text.c:386
#define MHEG5getMem
Definition: glue_memory.h:93
Implement the MHEG5 Text Class 36 Text Class Defines attributes and behaviour of pieces of textual in...
MHEG5Final clazz
Definition: mh5root.h:55
void MHEG5visibleFree(MHEG5Visible *visible)
Free off all memory associated with the specified object, including any exchanged attributes and inte...
Definition: mh5visible.c:186
void MG_FreeData(void *data)
free surface buffer
Definition: mg_osd.c:1536
union sMH5GroupRef::@5 ptr
#define VJUSTIFICATION_JUSTIFIED
Definition: mh5text.h:47
void MHEG5genericCopy(MHEG5Generic *dest, MHEG5Generic *src)
Copy a MHEG5Generic.
Definition: mh5base.c:861
MHEG5ErrorCode MHEG5setBackgroundColour(MHEG5Root *target, MHEG5GList *params)
The effect of this action is to set the BackgroundColour to the given colour. Implementation of the M...
Definition: mh5text.c:620
void MHEG5drawEntry(MHEG5Entryfield *entry, entryfieldCursor_t cursor)
Definition: mh5drawtext.c:502
MHEG5Int characterSet
Definition: mh5text.h:69
union MHEG5Generic::@6 value
MHEG5ErrorCode MHEG5setTextColour(MHEG5Root *target, MHEG5GList *params)
The effect of this action is to set the TextColour to the given colour. Implementation of the MHEG5se...
Definition: mh5text.c:585
void MHEG5visiblePrepare(MHEG5Visible *visible)
Apply the preparation behaviour off the visible class Apply the preparation behaviour of the visible ...
Definition: mh5visible.c:239
MHEG5String MHEG5stringCopy(MHEG5String source)
<Function description>="">
Definition: mh5base.c:574
MHEG5FontBody font
Definition: mh5text.h:88
Implement the MHEG5 Variable Class 21 Variable Class Defines a variable within the context of a Group...
MHEG5Colour textColour
Definition: mh5text.h:90
void MHEG5stringDestruct(MHEG5String *item)
Destruct a MHEG5String.
Definition: mh5base.c:686
void * graphic_data
Definition: mh5visible.h:64
MHEG5String fontAttributes
Definition: mh5text.h:89
#define VJUSTIFICATION_CENTRE
Definition: mh5text.h:46
void MHEG5visibleDestruct(MHEG5Visible *visible)
Destruct a visible object.
Definition: mh5visible.c:282
void MHEG5textFree(MHEG5Text *text)
Free off all memory associated with the specified object, including any exchanged attributes and inte...
Definition: mh5text.c:204
long MHEG5Int
Definition: mh5base.h:73
MHEG5Bool textWrapping
Definition: mh5text.h:74
#define HJUSTIFICATION_CENTRE
Definition: mh5text.h:41
MHEG5Colour backgroundColour
Definition: mh5text.h:91
MHEG5ErrorCode MHEG5setFontAttributes(MHEG5Root *target, MHEG5GList *params)
The effect of this action is to set the FontAttributes to the given attributes. Implementation of the...
Definition: mh5text.c:548
#define MHEG5freeMem
Definition: glue_memory.h:94
MHEG5String originalFontAttributes
Definition: mh5text.h:66
void MHEG5textPrepare(MHEG5Text *text)
Apply the preparation behaviour of the text class Apply the preparation behaviour of the text class...
Definition: mh5text.c:293
This file defines the profile for the MHEG engine.
MHEG5GList * MHEG5resolveGenericOctetString(MHEG5GList *params, MHEG5String *value, MHEG5Bool *invalidString)
Resolve a parameter reference to a generic octet string. The reference can be either direct or indire...
Definition: mh5object.c:478
MHEG5Bool referenced
Definition: mh5base.h:242
MHEG5FontBody originalFont
Definition: mh5text.h:65
#define MHEG5displayRedraw(v)
Definition: mh5display.h:47
MHEG5Colour originalTextColour
Definition: mh5text.h:67
#define UNICODE_BOM_LITTLE_ENDIAN
Definition: mh5text.c:46
short MHEG5Bool
Definition: mh5base.h:71
MHEG5ErrorCode MHEG5getTextContent(MHEG5Root *target, MHEG5GList *params)
The effect of this action is to transfer the data of the content attribute of the text to the variabl...
Definition: mh5text.c:421
MHEG5ErrorCode
Definition: mh5base.h:222
#define BOM_NONE
Definition: mh5text.h:52
unsigned char MHEG5Byte
Definition: mh5base.h:74
#define MHEG5colourDestruct
Definition: mh5base.h:62
void MHEG5textInit(MHEG5Text *text)
Initialise a text object with default values.
Definition: mh5text.c:190
#define VJUSTIFICATION_END
Definition: mh5text.h:45
union sMHEG5FontBody::@7 ref
#define UNICODE_BOM_BIG_ENDIAN
Definition: mh5text.c:47
MHEG5Byte * data
Definition: mh5base.h:85
int len
Definition: mh5gate.c:57
void MHEG5textContentUnadaptUTF16(MHEG5Text *text, MHEG5Byte **utf16Data, MHEG5Int *utf16Len)
Undo the adaption of content for Text objects. Adapted content is stored as 16 bit unicode - this is ...
Definition: mh5text.c:1261
#define MHEG5TRUE
Definition: mh5base.h:49
Implement functions to retrieve MHEG5objects by GroupID and ID.
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.
Mheg5 logging and debug printing.
MHEG class interface to graphics text render.
MHEG5Int len
Definition: mh5base.h:99
MHEG5Bool runningStatus
Definition: mh5root.h:51
void MHEG5textContentUnadapt(MHEG5Text *text, MHEG5Byte **utf8Data, MHEG5Int *utf8Len)
Undo the adaption of content for Text objects. Adapted content is stored as 16 bit unicode - this is ...
Definition: mh5text.c:1143
MHEG5Ingredient ingredient
Definition: mh5visible.h:49
MHEG5Byte * name
Definition: mh5base.h:102
MHEG5String textDataRaw
Definition: mh5text.h:87
redirection include
MHEG5Int startCorner
Definition: mh5text.h:73
void MHEG5visibleClone(MHEG5Visible *destination, MHEG5Visible *source)
Copy a visible object with original values.
Definition: mh5visible.c:206
#define ERROR_PRINT(x)
Definition: mh5debug.h:76
MHEG5ErrorCode MHEG5getTextData(MHEG5Root *target, MHEG5GList *params)
Set the Variable referenced by TextDataVar to the value of the TextData attribute. Implementation of the GetTextData (Target, TextDataVar) action of the text class.
Definition: mh5text.c:470
MHEG5Bool verticalLineOrientation
Definition: mh5text.h:72
MHEG5Int len
Definition: mh5base.h:84
MHEG5Int byteOrderMark
Definition: mh5text.h:95
MHEG5GList * MHEG5resolveORef(MHEG5GList *params, MHEG5Root **object)
Definition: mh5object.c:126
MHEG5String included
Definition: mh5base.h:245
MHEG5GList * MHEG5resolveGenericGeneric(MHEG5GList *params, MHEG5Generic *value)
Definition: mh5object.c:364
#define HJUSTIFICATION_END
Definition: mh5text.h:40
#define VJUSTIFICATION_START
Definition: mh5text.h:44
Implement generic MHEG5-display functions - independent from the OSD These are generic functions used...
void MHEG5visibleDeactivate(MHEG5Visible *visible)
Apply the deactivation behaviour of the visible class. As this class has no own deactivation behaviou...
Definition: mh5visible.c:338
void MHEG5textDestruct(MHEG5Text *text)
Destruct a text object.
Definition: mh5text.c:365
void MHEG5textDeactivate(MHEG5Text *text)
Apply the deactivation behaviour of the text class. As this class has no own deactivation behaviour t...
Definition: mh5text.c:348
MHEG5ErrorCode MHEG5setFontRef(MHEG5Root *target, MHEG5GList *params)
The effect of this action is to change the character font used to preset a text. Implementation of th...
Definition: mh5text.c:655
MHEG5Colour originalBackgroundColour
Definition: mh5text.h:68
#define MHEG5FALSE
Definition: mh5base.h:48
void MHEG5drawText(MHEG5Text *txt)
Definition: mh5drawtext.c:485
void MHEG5visibleInit(MHEG5Visible *visible)
Initialise a visible object with default values.
Definition: mh5visible.c:172
void MHEG5textClearTextData(MHEG5Text *text)
Clear text data.
Definition: mh5text.c:1377
Implement the MHEG5 EntryField Class. Defines an interaction widget used by the final user to edit an...