3 #define MAX_TAG_LEN 256
4 #define MAX_SYMBOL_LEN 256
10 #define FONT_BOLD 0x00000001
11 #define FONT_ITALIC 0x00000002
12 #define FONT_UNDERLINE 0x00000004
21 FontEntry /*void * */font;
33 ImageEntry imageEntry;
50 int minW; // Minimum column width
51 int lineW; // Minimum column width for lines to fit on one row
52 HorizontalAlignment halign;
53 VerticalAlignment valign;
82 imageEntry.bitmapPtrs.Remove(entryPtr);
86 while(child = subBlocks.first)
88 subBlocks.Remove(child);
97 for(child = subBlocks.first; child; child = child.next)
104 String ParseURL(String input)
108 int len = strlen(input);
109 String output = new char[len+1];
111 for(c = 0; (ch = input[c]); c++)
113 if(ch == '%' && isalnum(input[c+1]) && isalnum(input[c+2]))
115 char hex[3] = { input[c+1], input[c+2], 0 };
117 int v = (int)strtoul(hex, &end, 16);
118 if(v && end == hex + 2)
120 output[len++] = (char)v;
128 return renew output char[len];
131 /*static */bool GetKeyWordEx(char ** input, char * keyWord, int maxSize, bool treatEqual, bool acceptSingleQuote)
133 char * string = *input;
136 bool quoted = false, start = true, wasQuoted = false;
139 for(; (ch = *string); string++)
141 if(!quoted && wasQuoted)
144 if((ch == ' ' || ch == '\t') && !quoted)
150 if(!quoted && ((ch == ',' || (treatEqual && ch == '=')) || ch == '>') )
152 else if((ch == '\"' || (acceptSingleQuote && ch == '\'')) && (!quoteChar || quoteChar == ch))
160 else if(ch != '\r' && ch != '\n')
168 for(;*string == '>' || *string == ',' || *string == ' ' || *string == '=' || *string == '\t' || *string == '\r' || *string == '\n'; string++);
171 return (c > 0) ? (wasQuoted ? WORD_QUOTED : WORD_NORMAL) : WORD_NONE;
174 static bool GetKeyWord(char ** input, char * keyWord, int maxSize)
176 return GetKeyWordEx(input, keyWord, maxSize, true, false);
179 static char * GetString(char * string, char * what, int count)
183 for(sc = 0; (!count && string[sc]) || sc<count; sc++)
185 if(string[sc] != ' ' && string[sc] != '\"')
189 for(wc = 0; what[wc]; wc++, sc++)
191 if((count && sc >= count) || (string[sc] != what[wc] && tolower(string[sc]) != tolower(what[wc])))
199 String EncodeString(String input, int * lenPtr)
201 if(UTF8Validate(input))
203 return CopyString(input);
207 int len = strlen(input);
208 String s = new char[len*4+1];
209 len = ISO8859_1toUTF8(input, s, len*4);
210 if(lenPtr) *lenPtr = len;
211 return renew s char[len+1];
218 Block defaultFont { };
222 ColorAlpha background { 255, white };
224 //Button defaultButton;
226 Block ::AddBlock(Block parent, BlockType type)
228 Block block = Block { parent = parent, type = type };
229 parent.subBlocks.Add(block);
241 bool insideTag = false;
242 char tag[MAX_TAG_LEN];
243 char symbol[MAX_SYMBOL_LEN];
245 Block block = this.block, subBlock;
248 bool insideSymbol = false;
250 int insideScript = 0, insideStyle = 0;
251 bool commented = false;
257 Block fontBlock = defaultFont;
258 fontBlock.type = FONT;
259 fontBlock.face = CopyString("Times New Roman");
262 fontBlock.attribs = FONT_UNDERLINE|FONT_BOLD;
264 fontBlock.textColor = LT_BLUE|0xFF000000;
267 fontBlock.textColor = black;
270 /*fontBlock.font = FontEntry { size = fontBlock.size, attribs = fontBlock.attribs, face = CopyString(fontBlock.face) };
271 fontCache.Add(fontBlock.font);*/
275 text = new char[32768*4];
277 block.font = fontBlock.font;
281 while(!f.Eof() && block)
287 //fwrite(&ch, 1, 1, stdout);
291 if((ch == '-' && tagLen < 2) || (ch == '>' && tagLen == 2))
295 if(!strcmp(tag, "-->"))
307 if(ch == '<' && !quoted && !insideScript && !insideStyle)
311 /*else */if(ch == '>' && !quoted)
324 if(GetKeyWord(&string, keyWord, sizeof(keyWord)))
326 if(!strcmpi(keyWord, "object"))
328 subBlock = AddBlock(block, IMAGE);
331 GetKeyWord(&string, keyWord, sizeof(keyWord));
332 if(!strcmpi(keyWord, "width"))
334 GetKeyWord(&string, keyWord, sizeof(keyWord));
335 subBlock.w = atoi(keyWord);
337 else if(!strcmpi(keyWord, "height"))
339 GetKeyWord(&string, keyWord, sizeof(keyWord));
340 subBlock.h = atoi(keyWord);
344 else if(!strcmpi(keyWord, "img"))
347 subBlock = AddBlock(block, IMAGE);
348 subBlock.valign = bottom;
349 subBlock.halign = middle;
352 GetKeyWord(&string, keyWord, sizeof(keyWord));
353 if(!strcmpi(keyWord, "src"))
355 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false, false);
357 subBlock.src = keyWord[0] ? CopyString(keyWord) : null;
359 else if(!strcmpi(keyWord, "width"))
361 GetKeyWord(&string, keyWord, sizeof(keyWord));
362 if(strstr(keyWord, "%"))
363 subBlock.pWidth = atoi(keyWord);
365 subBlock.width = atoi(keyWord);
367 else if(!strcmpi(keyWord, "height"))
369 GetKeyWord(&string, keyWord, sizeof(keyWord));
370 if(strstr(keyWord, "%"))
371 subBlock.pHeight = atoi(keyWord);
373 subBlock.height = atoi(keyWord);
375 else if(!strcmpi(keyWord, "valign"))
377 GetKeyWord(&string, keyWord, sizeof(keyWord));
378 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
380 subBlock.valign = middle;
383 else if(!strcmpi(keyWord, "align"))
385 GetKeyWord(&string, keyWord, sizeof(keyWord));
386 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
388 subBlock.halign = middle;
390 else if(!strcmpi(keyWord, "left"))
392 subBlock.halign = left;
394 else if(!strcmpi(keyWord, "right"))
396 subBlock.halign = right;
398 else if(!strcmpi(keyWord, "top"))
400 subBlock.valign = top;
402 else if(!strcmpi(keyWord, "bottom"))
404 subBlock.valign = bottom;
409 else if(!strcmpi(keyWord, "title"))
411 block = AddBlock(block, TITLE);
414 else if(!strcmpi(keyWord, "body"))
416 block = AddBlock(block, BODY);
422 GetKeyWord(&string, keyWord, sizeof(keyWord));
423 if(!strcmpi(keyWord, "bgcolor"))
425 GetKeyWord(&string, keyWord, sizeof(keyWord));
426 background = !strcmpi(keyWord, "#fff") ? white : strtol((keyWord[0] == '#') ? (keyWord+1) : keyWord, null, 16);
427 if(keyWord[0] != '#' || strlen(keyWord) <= 7)
428 background |= 0xFF000000;
430 else if(!strcmpi(keyWord, "text"))
432 GetKeyWord(&string, keyWord, sizeof(keyWord));
433 fontBlock.textColor =
434 block.textColor = 0xFF000000 | strtol((keyWord[0] == '#') ? (keyWord+1) : keyWord, null, 16);
438 else if(!strcmpi(keyWord, "br") || (!lastBR && (!strcmpi(keyWord, "div") || !strcmpi(keyWord, "li"))))
440 if(!lastBR || (lastCh && lastCh != ' '))
442 subBlock = AddBlock(block, BR);
447 else if(!strcmpi(keyWord, "/ul"))
451 else if(!strcmpi(keyWord, "/ul"))
455 else if(!strcmpi(keyWord, "/div"))
459 subBlock = AddBlock(block, BR);
465 else if(!strcmpi(keyWord, "code"))
469 else if(!strcmpi(keyWord, "/code"))
473 else if(!strcmpi(keyWord, "p"))
476 else if(!strcmpi(keyWord, "font") || !strcmpi(keyWord, "b") || !strcmpi(keyWord, "i")
477 || !strcmpi(keyWord, "strong") || !strcmpi(keyWord, "em") ||
478 !strcmpi(keyWord, "h1") || !strcmpi(keyWord, "h2") || !strcmpi(keyWord, "h3"))
480 if((!strcmpi(keyWord, "h1") || !strcmpi(keyWord, "h2") || !strcmpi(keyWord, "h3")))
482 if(!lastBR || (lastCh && lastCh != ' '))
485 subBlock = AddBlock(block, BR);
486 subBlock = AddBlock(block, BR);
491 subBlock = AddBlock(block, FONT);
492 subBlock.attribs = fontBlock.attribs;
493 if(!strcmpi(keyWord, "font"))
497 GetKeyWord(&string, keyWord, sizeof(keyWord));
499 if(!strcmpi(keyWord, "face"))
501 GetKeyWord(&string, keyWord, sizeof(keyWord));
502 delete subBlock.face;
503 subBlock.face = CopyString(keyWord);
505 else if(!strcmpi(keyWord, "size"))
507 #define NUM_FONT_SIZES 7
508 static float fontSizes[NUM_FONT_SIZES] = { 7.5f, 10, 12, 13.5f, 18, 24, 36 };
510 GetKeyWord(&string, keyWord, sizeof(keyWord));
511 size = atoi(keyWord);
512 if(keyWord[0] == '+')
515 int numTimes = atoi(keyWord+1);
516 for(c = 0; c<NUM_FONT_SIZES-1; c++)
517 if(fontSizes[c] > fontBlock.size)
522 subBlock.size = fontSizes[c];
524 else if(keyWord[0] == '-')
527 int numTimes = atoi(keyWord+1);
528 for(c = NUM_FONT_SIZES-1; c>0; c--)
529 if(fontSizes[c] < fontBlock.size)
534 subBlock.size = fontSizes[c];
536 else if(size && size < NUM_FONT_SIZES)
538 subBlock.size = fontSizes[size-1];
542 else if(!strcmpi(keyWord, "color"))
544 GetKeyWord(&string, keyWord, sizeof(keyWord));
546 0xFF000000 | strtol((keyWord[0] == '#') ? (keyWord+1) : keyWord, null, 16);
552 if(!strcmpi(keyWord, "b") || !strcmpi(keyWord, "strong"))
553 subBlock.attribs |= FONT_BOLD;
554 else if(!strcmpi(keyWord, "i") || !strcmpi(keyWord, "em"))
555 subBlock.attribs |= FONT_ITALIC;
556 else if(!strcmpi(keyWord, "h1"))
558 else if(!strcmpi(keyWord, "h2"))
560 else if(!strcmpi(keyWord, "h3"))
564 if(!subBlock.face) subBlock.face = CopyString(fontBlock.face);
565 if(!subBlock.size) subBlock.size = fontBlock.size;
566 if(!subBlock.textColor) subBlock.textColor = fontBlock.textColor;
568 subBlock.prevFont = fontBlock;
569 fontBlock = subBlock;
572 else if(!strcmpi(keyWord, "/font") ||
573 !strcmpi(keyWord, "/b") ||
574 !strcmpi(keyWord, "/strong") ||
575 !strcmpi(keyWord, "/em") ||
576 !strcmpi(keyWord, "/i") ||
577 !strcmpi(keyWord, "/h1") ||
578 !strcmpi(keyWord, "/h2") ||
579 !strcmpi(keyWord, "/h3"))
581 /*while(block.type != FONT && block.parent && block.parent.type != BODY)
582 block = block.parent;*/
583 if(block.type == FONT || block.type == ANCHOR)
585 fontBlock = block.prevFont;
586 block = block.parent;
588 if(!lastBR && (!strcmpi(keyWord, "/h1") || !strcmpi(keyWord, "/h2") || !strcmpi(keyWord, "/h3")))
590 subBlock = AddBlock(block, BR);
594 else if(!strcmpi(keyWord, "a"))
596 int textDecoration = 0;
597 Block anchor { type = ANCHOR, parent = block };
601 GetKeyWord(&string, keyWord, sizeof(keyWord));
603 if(!strcmpi(keyWord, "name"))
605 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false, false);
606 delete anchor.anchor;
607 anchor.anchor = CopyString(keyWord);
609 else if(!strcmpi(keyWord, "href"))
611 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false, true);
613 anchor.href = CopyString(keyWord);
617 else if(!strcmpi(keyWord, "style"))
621 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false, false);
622 if(strstr(keyWord, "text-decoration:") && strstr(keyWord, "none;"))
628 if(anchor.href && (/*lastBR || */isalnum(lastCh)))
630 subBlock = AddBlock(block, TEXT);
631 subBlock.text = CopyString(" ");
632 subBlock.textLen = 2;
633 subBlock.prevFont = fontBlock;
636 block.subBlocks.Add(subBlock);
638 subBlock.attribs = fontBlock.attribs | FONT_BOLD;
639 delete subBlock.face;
640 subBlock.face = CopyString(fontBlock.face);
641 subBlock.size = fontBlock.size;
642 subBlock.textColor = Color { 85,85,255 };
643 subBlock.prevFont = fontBlock;
644 if(textDecoration == 1) subBlock.attribs |= FONT_UNDERLINE;
645 fontBlock = subBlock;
650 /*else if(!strcmpi(keyWord, "/span"))
654 subBlock = AddBlock(block, TEXT);
655 subBlock.text = CopyString(" ");
656 subBlock.textLen = 2;
657 subBlock.prevFont = block.parent.prevFont;
661 else if(!strcmpi(keyWord, "/a"))
663 if(block.type == ANCHOR)
665 fontBlock = block.prevFont;
666 block = block.parent;
669 else if(!strcmpi(keyWord, "script"))
673 else if(!strcmpi(keyWord, "/script"))
678 else if(!strcmpi(keyWord, "style"))
682 else if(!strcmpi(keyWord, "/style"))
687 else if(!strcmpi(keyWord, "input") || !strcmpi(keyWord, "button"))
689 subBlock = AddBlock(block, INPUT);
692 GetKeyWord(&string, keyWord, sizeof(keyWord));
694 if(!strcmpi(keyWord, "type"))
696 GetKeyWordEx(&string, keyWord, sizeof(keyWord), true, true);
697 if(!strcmpi(keyWord, "text"))
699 subBlock.inputType = InputType::text;
701 else if(!strcmpi(keyWord, "submit") || !strcmpi(keyWord, "image"))
703 subBlock.inputType = submit;
705 else if(!strcmpi(keyWord, "radio"))
707 subBlock.inputType = radio;
709 else if(!strcmpi(keyWord, "checkbox"))
711 subBlock.inputType = checkbox;
713 else if(!strcmpi(keyWord, "hidden"))
715 subBlock.inputType = hidden;
717 delete subBlock.href;
718 subBlock.href = CopyString(keyWord);
720 else if(!strcmpi(keyWord, "size"))
722 GetKeyWord(&string, keyWord, sizeof(keyWord));
723 subBlock.size = atoi(keyWord);
725 else if(!strcmpi(keyWord, "maxlength"))
728 GetKeyWord(&string, keyWord, sizeof(keyWord));
729 maxlength = atoi(keyWord);
731 else if(!strcmpi(keyWord, "value"))
733 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false, true);
734 delete subBlock.value;
735 subBlock.value = EncodeString(keyWord, null);
737 else if(!strcmpi(keyWord, "name"))
739 GetKeyWord(&string, keyWord, sizeof(keyWord));
740 delete subBlock.name;
741 subBlock.name = CopyString(keyWord);
743 else if(!strcmpi(keyWord, "src"))
745 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false, false);
747 subBlock.src = keyWord[0] ? CopyString(keyWord) : null;
751 else if(!strcmpi(keyWord, "form"))
753 subBlock = AddBlock(block, FORM);
756 GetKeyWord(&string, keyWord, sizeof(keyWord));
758 if(!strcmpi(keyWord, "action"))
760 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false, false);
761 delete subBlock.action;
762 subBlock.action = CopyString(keyWord);
767 else if(!strcmpi(keyWord, "/form"))
769 if(block.type == FORM)
771 block = block.parent;
774 else if(!strcmpi(keyWord, "center"))
776 subBlock = AddBlock(block, CENTER);
779 else if(!strcmpi(keyWord, "/center"))
781 if(block.type == CENTER)
783 block = block.parent;
786 else if(!strcmpi(keyWord, "base"))
790 GetKeyWord(&string, keyWord, sizeof(keyWord));
792 if(!strcmpi(keyWord, "href"))
794 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false, true);
796 baseHRef = ParseURL(keyWord);
800 else if(!strcmpi(keyWord, "table"))
803 subBlock = AddBlock(block, TABLE);
804 subBlock.cellPadding = 4;
807 GetKeyWord(&string, keyWord, sizeof(keyWord));
809 if(!strcmpi(keyWord, "width"))
811 GetKeyWord(&string, keyWord, sizeof(keyWord));
812 if(strstr(keyWord, "%"))
813 subBlock.pWidth = atoi(keyWord);
815 subBlock.width = atoi(keyWord);
817 else if(!strcmpi(keyWord, "height"))
819 GetKeyWord(&string, keyWord, sizeof(keyWord));
820 if(strstr(keyWord, "%"))
821 subBlock.pHeight = atoi(keyWord);
823 subBlock.height = atoi(keyWord);
825 else if(!strcmpi(keyWord, "cellpadding"))
827 GetKeyWord(&string, keyWord, sizeof(keyWord));
828 subBlock.cellPadding = atoi(keyWord);
830 else if(!strcmpi(keyWord, "background"))
832 GetKeyWord(&string, keyWord, sizeof(keyWord));
834 subBlock.src = CopyString(keyWord);
836 else if(!strcmpi(keyWord, "bgcolor"))
838 GetKeyWord(&string, keyWord, sizeof(keyWord));
839 subBlock.bgColor = !strcmpi(keyWord, "#fff") ? white : (0xFF000000 | strtol((keyWord[0] == '#') ? (keyWord+1) : keyWord, null, 16));
841 else if(!strcmpi(keyWord, "align"))
843 GetKeyWord(&string, keyWord, sizeof(keyWord));
844 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
846 subBlock.halign = middle;
848 else if(!strcmpi(keyWord, "left"))
850 subBlock.halign = left;
852 else if(!strcmpi(keyWord, "right"))
854 subBlock.halign = right;
861 else if(!strcmpi(keyWord, "/table"))
865 block = block.parent;
870 block = block.parent;
873 if(block.type == TABLE)
875 block = block.parent;
879 else if(!strcmpi(keyWord, "tr"))
883 block = block.parent;
888 block = block.parent;
892 subBlock = AddBlock(block, TR);
896 GetKeyWord(&string, keyWord, sizeof(keyWord));
898 if(!strcmpi(keyWord, "height"))
900 GetKeyWord(&string, keyWord, sizeof(keyWord));
901 subBlock.height = atoi(keyWord);
904 if(!strcmpi(keyWord, "align"))
906 GetKeyWord(&string, keyWord, sizeof(keyWord));
907 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
909 subBlock.valign = middle;
911 else if(!strcmpi(keyWord, "top"))
913 subBlock.valign = top;
915 else if(!strcmpi(keyWord, "bottom"))
917 subBlock.valign = bottom;
923 else if(!strcmpi(keyWord, "/tr"))
927 block = block.parent;
932 block = block.parent;
936 else if(!strcmpi(keyWord, "td"))
938 while(block && block.type != TR && block.type != TABLE)
940 if(block == fontBlock)
941 fontBlock = block.prevFont;
942 block = block.parent;
947 if(block.type == TABLE)
949 block = AddBlock(block, TR);
951 subBlock = AddBlock(block, TD);
952 subBlock.span = subBlock.rowSpan = 1;
953 subBlock.valign = block.valign;
954 subBlock.halign = block.halign;
958 GetKeyWord(&string, keyWord, sizeof(keyWord));
960 if(!strcmpi(keyWord, "width"))
962 GetKeyWord(&string, keyWord, sizeof(keyWord));
963 if(strstr(keyWord, "%"))
964 subBlock.pWidth = atoi(keyWord);
966 subBlock.width = atoi(keyWord);
968 else if(!strcmpi(keyWord, "height"))
970 GetKeyWord(&string, keyWord, sizeof(keyWord));
971 if(strstr(keyWord, "%"))
972 subBlock.pHeight = atoi(keyWord);
974 subBlock.height = atoi(keyWord);
976 else if(!strcmpi(keyWord, "colspan"))
978 GetKeyWord(&string, keyWord, sizeof(keyWord));
979 subBlock.span = atoi(keyWord);
981 else if(!strcmpi(keyWord, "cellpadding"))
983 GetKeyWord(&string, keyWord, sizeof(keyWord));
984 subBlock.cellPadding = atoi(keyWord);
986 else if(!strcmpi(keyWord, "rowspan"))
988 GetKeyWord(&string, keyWord, sizeof(keyWord));
989 subBlock.rowSpan = atoi(keyWord);
991 else if(!strcmpi(keyWord, "nowrap"))
993 subBlock.noWrap = true;
995 else if(!strcmpi(keyWord, "background"))
997 GetKeyWord(&string, keyWord, sizeof(keyWord));
999 subBlock.src = CopyString(keyWord);
1001 else if(!strcmpi(keyWord, "bgcolor"))
1003 GetKeyWord(&string, keyWord, sizeof(keyWord));
1004 subBlock.bgColor = !strcmpi(keyWord, "#fff") ? white : (0xFF000000 |strtol((keyWord[0] == '#') ? (keyWord+1) : keyWord, null, 16));
1006 else if(!strcmpi(keyWord, "valign"))
1008 GetKeyWord(&string, keyWord, sizeof(keyWord));
1009 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
1011 subBlock.valign = middle;
1013 else if(!strcmpi(keyWord, "top"))
1015 subBlock.valign = top;
1017 else if(!strcmpi(keyWord, "bottom"))
1019 subBlock.valign = bottom;
1022 else if(!strcmpi(keyWord, "align"))
1024 GetKeyWord(&string, keyWord, sizeof(keyWord));
1025 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
1027 subBlock.halign = middle;
1029 else if(!strcmpi(keyWord, "left"))
1031 subBlock.halign = left;
1033 else if(!strcmpi(keyWord, "right"))
1035 subBlock.halign = right;
1042 else if(!strcmpi(keyWord, "/td"))
1044 if(block.type == TD)
1046 block = block.parent;
1050 else if(!strcmpi(keyWord, "/html"))
1056 if(tagLen < MAX_TAG_LEN-1)
1065 if((insideScript || insideStyle) && !tagLen && ch != '/')
1071 if(tagLen < MAX_TAG_LEN-1)
1078 if(!strcmp(tag, "!--"))
1090 if(!insideScript && !insideStyle)
1094 if(block.type == TABLE)
1096 subBlock = AddBlock(block, TR);
1099 if(block.type == TR)
1101 subBlock = AddBlock(block, TD);
1102 subBlock.span = subBlock.rowSpan = 1;
1103 subBlock.valign = block.valign;
1104 subBlock.halign = block.halign;
1108 subBlock = AddBlock(block, TEXT);
1109 delete subBlock.text;
1110 subBlock.text = EncodeString(text, &textLen);
1111 subBlock.textLen = textLen;
1112 if(block.type != TITLE)
1123 else if(ch != '\n' && ch != '\r' && ch != '\t' && !insideScript && !insideStyle)
1129 unichar unicode = 0;
1131 if(symbol[0] == '#' && symbol[1] == 'x')
1132 unicode = strtol(symbol+2, null, 16);
1133 else if(!strcmpi(symbol, "nbsp"))
1135 else if(!strcmpi(symbol, "copy"))
1137 else if(!strcmpi(symbol, "raquo"))
1139 else if(!strcmpi(symbol, "eacute"))
1141 else if(!strcmpi(symbol, "egrave"))
1143 else if(!strcmpi(symbol, "ecirc"))
1145 else if(!strcmpi(symbol, "agrave"))
1147 else if(!strcmpi(symbol, "acirc"))
1149 else if(!strcmpi(symbol, "ocirc"))
1153 int len = UTF32toUTF8Len(&unicode, 1, utf8, 5);
1155 for(c = 0; c<len; c++)
1156 text[textLen++] = utf8[c];
1159 text[textLen] = '\0';
1160 insideSymbol = false;
1164 // Give up... Treat it as text
1165 text[textLen++] = '&';
1166 CopyBytes(text + textLen, symbol, symbolLen);
1167 textLen += symbolLen;
1168 lastCh = text[textLen++] = ' ';
1169 text[textLen] = '\0';
1170 insideSymbol = false;
1174 if(symbolLen < MAX_SYMBOL_LEN-1)
1176 symbol[symbolLen++] = ch;
1177 symbol[symbolLen] = '\0';
1185 insideSymbol = true;
1191 if(ch != ' ' || lastCh != ' ' || code)
1192 // if(ch != ' ' || (textLen && text[textLen-1] !=' '))
1195 text[textLen++] = ch;
1196 text[textLen] = '\0';
1201 else if(ch == '\n' && code)
1203 //printf("%d\n", textLen);
1206 subBlock = AddBlock(block, TEXT);
1207 delete subBlock.text;
1208 subBlock.text = EncodeString(text, &textLen);
1209 subBlock.textLen = textLen;
1212 subBlock = AddBlock(block, BR);
1225 property String title
1229 if(titleBlock && titleBlock.subBlocks.first && ((Block)titleBlock.subBlocks.first).type == TEXT)
1231 Block t = titleBlock.subBlocks.first;