3 #define MAX_TAG_LEN 204800
4 #define MAX_SYMBOL_LEN 1000
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 static bool GetKeyWordEx(char ** input, char * keyWord, int maxSize, bool treatEqual)
106 char * string = *input;
109 bool quoted = false, start = true, wasQuoted = false;
111 for(; (ch = *string); string++)
113 if(!quoted && wasQuoted)
116 if((ch == ' ' || ch == '\t') && !quoted)
122 if(!quoted && ((ch == ',' || (treatEqual && ch == '=')) || ch == '>') )
124 else if(ch == '\"' /*|| ch == '\''*/)
130 else if(ch != '\r' && ch != '\n')
138 for(;*string == '>' || *string == ',' || *string == ' ' || *string == '=' || *string == '\t' || *string == '\r' || *string == '\n'; string++);
141 return (c > 0) ? (wasQuoted ? WORD_QUOTED : WORD_NORMAL) : WORD_NONE;
144 static bool GetKeyWord(char ** input, char * keyWord, int maxSize)
146 return GetKeyWordEx(input, keyWord, maxSize, true);
149 static char * GetString(char * string, char * what, int count)
153 for(sc = 0; (!count && string[sc]) || sc<count; sc++)
155 if(string[sc] != ' ' && string[sc] != '\"')
159 for(wc = 0; what[wc]; wc++, sc++)
161 if((count && sc >= count) || (string[sc] != what[wc] && tolower(string[sc]) != tolower(what[wc])))
167 static Block AddBlock(Block parent, BlockType type)
169 Block block = Block { parent = parent, type = type };
170 parent.subBlocks.Add(block);
179 Block defaultFont { };
182 ColorAlpha background { 255, white };
183 //Button defaultButton;
187 bool insideTag = false;
188 char tag[MAX_TAG_LEN];
189 char symbol[MAX_SYMBOL_LEN];
191 Block block = this.block, subBlock;
194 bool insideSymbol = false;
196 int insideScript = 0, insideStyle = 0;
197 bool commented = false;
202 Block fontBlock = defaultFont;
203 fontBlock.type = FONT;
204 fontBlock.face = CopyString("Times New Roman");
207 fontBlock.attribs = FONT_UNDERLINE|FONT_BOLD;
209 fontBlock.textColor = LT_BLUE|0xFF000000;
212 fontBlock.textColor = black;
215 fontBlock.font = FontEntry { size = fontBlock.size, attribs = fontBlock.attribs, face = CopyString(fontBlock.face) };
216 fontCache.Add(fontBlock.font);
220 text = new char[32768*4];
225 while(!f.Eof() && block)
230 //fwrite(&ch, 1, 1, stdout);
233 if((ch == '-' && tagLen < 2) || (ch == '>' && tagLen == 2))
237 if(!strcmp(tag, "-->"))
249 if(ch == '<' && !quoted)
251 /*else */if(ch == '>' && !quoted)
264 if(GetKeyWord(&string, keyWord, sizeof(keyWord)))
266 if(!strcmpi(keyWord, "object"))
268 subBlock = AddBlock(block, IMAGE);
271 GetKeyWord(&string, keyWord, sizeof(keyWord));
272 if(!strcmpi(keyWord, "width"))
274 GetKeyWord(&string, keyWord, sizeof(keyWord));
275 subBlock.w = atoi(keyWord);
277 else if(!strcmpi(keyWord, "height"))
279 GetKeyWord(&string, keyWord, sizeof(keyWord));
280 subBlock.h = atoi(keyWord);
284 else if(!strcmpi(keyWord, "img"))
286 subBlock = AddBlock(block, IMAGE);
287 subBlock.valign = bottom;
288 subBlock.halign = middle;
291 GetKeyWord(&string, keyWord, sizeof(keyWord));
292 if(!strcmpi(keyWord, "src"))
294 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false);
296 subBlock.src = keyWord[0] ? CopyString(keyWord) : null;
298 else if(!strcmpi(keyWord, "width"))
300 GetKeyWord(&string, keyWord, sizeof(keyWord));
301 if(strstr(keyWord, "%"))
302 subBlock.pWidth = atoi(keyWord);
304 subBlock.width = atoi(keyWord);
306 else if(!strcmpi(keyWord, "height"))
308 GetKeyWord(&string, keyWord, sizeof(keyWord));
309 if(strstr(keyWord, "%"))
310 subBlock.pHeight = atoi(keyWord);
312 subBlock.height = atoi(keyWord);
314 else if(!strcmpi(keyWord, "valign"))
316 GetKeyWord(&string, keyWord, sizeof(keyWord));
317 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
319 subBlock.valign = middle;
322 else if(!strcmpi(keyWord, "align"))
324 GetKeyWord(&string, keyWord, sizeof(keyWord));
325 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
327 subBlock.halign = middle;
329 else if(!strcmpi(keyWord, "left"))
331 subBlock.halign = left;
333 else if(!strcmpi(keyWord, "right"))
335 subBlock.halign = right;
337 else if(!strcmpi(keyWord, "top"))
339 subBlock.valign = top;
341 else if(!strcmpi(keyWord, "bottom"))
343 subBlock.valign = bottom;
348 else if(!strcmpi(keyWord, "body"))
350 block = AddBlock(block, BODY);
356 GetKeyWord(&string, keyWord, sizeof(keyWord));
357 if(!strcmpi(keyWord, "bgcolor"))
359 GetKeyWord(&string, keyWord, sizeof(keyWord));
360 background = strtol((keyWord[0] == '#') ? (keyWord+1) : keyWord, null, 16);
361 if(keyWord[0] != '#' || strlen(keyWord) <= 7)
362 background |= 0xFF000000;
364 else if(!strcmpi(keyWord, "text"))
366 GetKeyWord(&string, keyWord, sizeof(keyWord));
367 fontBlock.textColor =
368 block.textColor = 0xFF000000 | strtol((keyWord[0] == '#') ? (keyWord+1) : keyWord, null, 16);
372 else if(!strcmpi(keyWord, "br"))
374 subBlock = AddBlock(block, BR);
377 else if(!strcmpi(keyWord, "code"))
381 else if(!strcmpi(keyWord, "/code"))
385 else if(!strcmpi(keyWord, "p"))
388 else if(!strcmpi(keyWord, "font") || !strcmpi(keyWord, "b") || !strcmpi(keyWord, "i")
389 || !strcmpi(keyWord, "strong") || !strcmpi(keyWord, "em") ||
390 !strcmpi(keyWord, "h1") || !strcmpi(keyWord, "h2") || !strcmpi(keyWord, "h3"))
392 subBlock = AddBlock(block, FONT);
393 subBlock.attribs = fontBlock.attribs;
394 if(!strcmpi(keyWord, "font"))
398 GetKeyWord(&string, keyWord, sizeof(keyWord));
400 if(!strcmpi(keyWord, "face"))
402 GetKeyWord(&string, keyWord, sizeof(keyWord));
403 delete subBlock.face;
404 subBlock.face = CopyString(keyWord);
406 else if(!strcmpi(keyWord, "size"))
408 #define NUM_FONT_SIZES 7
409 static float fontSizes[NUM_FONT_SIZES] = { 7.5f, 10, 12, 13.5f, 18, 24, 36 };
411 GetKeyWord(&string, keyWord, sizeof(keyWord));
412 size = atoi(keyWord);
413 if(keyWord[0] == '+')
416 int numTimes = atoi(keyWord+1);
417 for(c = 0; c<NUM_FONT_SIZES-1; c++)
418 if(fontSizes[c] > fontBlock.size)
423 subBlock.size = fontSizes[c];
425 else if(keyWord[0] == '-')
428 int numTimes = atoi(keyWord+1);
429 for(c = NUM_FONT_SIZES-1; c>0; c--)
430 if(fontSizes[c] < fontBlock.size)
435 subBlock.size = fontSizes[c];
437 else if(size && size < NUM_FONT_SIZES)
439 subBlock.size = fontSizes[size-1];
443 else if(!strcmpi(keyWord, "color"))
445 GetKeyWord(&string, keyWord, sizeof(keyWord));
447 0xFF000000 | strtol((keyWord[0] == '#') ? (keyWord+1) : keyWord, null, 16);
453 if(!strcmpi(keyWord, "b") || !strcmpi(keyWord, "strong"))
454 subBlock.attribs |= FONT_BOLD;
455 else if(!strcmpi(keyWord, "i") || !strcmpi(keyWord, "em"))
456 subBlock.attribs |= FONT_ITALIC;
457 else if(!strcmpi(keyWord, "h1"))
459 else if(!strcmpi(keyWord, "h2"))
461 else if(!strcmpi(keyWord, "h3"))
465 if(!subBlock.face) subBlock.face = CopyString(fontBlock.face);
466 if(!subBlock.size) subBlock.size = fontBlock.size;
467 if(!subBlock.textColor) subBlock.textColor = fontBlock.textColor;
469 subBlock.prevFont = fontBlock;
470 fontBlock = subBlock;
473 else if(!strcmpi(keyWord, "/font") ||
474 !strcmpi(keyWord, "/b") ||
475 !strcmpi(keyWord, "/strong") ||
476 !strcmpi(keyWord, "/em") ||
477 !strcmpi(keyWord, "/i") ||
478 !strcmpi(keyWord, "/h1") ||
479 !strcmpi(keyWord, "/h2") ||
480 !strcmpi(keyWord, "/h3"))
482 if(block.type == FONT)
484 fontBlock = block.prevFont;
485 block = block.parent;
488 else if(!strcmpi(keyWord, "a"))
490 int textDecoration = 0;
491 subBlock = AddBlock(block, ANCHOR);
492 subBlock.attribs = fontBlock.attribs;
496 GetKeyWord(&string, keyWord, sizeof(keyWord));
498 if(!strcmpi(keyWord, "name"))
500 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false);
501 delete subBlock.anchor;
502 subBlock.anchor = CopyString(keyWord);
504 else if(!strcmpi(keyWord, "href"))
506 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false);
507 delete subBlock.href;
508 subBlock.href = CopyString(keyWord);
512 else if(!strcmpi(keyWord, "style"))
516 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false);
517 if(strstr(keyWord, "text-decoration:") && strstr(keyWord, "none;"))
522 subBlock.attribs |= FONT_BOLD;
523 if(textDecoration == 1) subBlock.attribs |= FONT_UNDERLINE;
524 delete subBlock.face;
525 subBlock.face = CopyString(fontBlock.face);
526 subBlock.size = fontBlock.size;
527 subBlock.textColor = Color { 85,85,255 };
528 subBlock.prevFont = fontBlock;
529 fontBlock = subBlock;
532 else if(!strcmpi(keyWord, "/a"))
534 if(block.type == ANCHOR)
536 fontBlock = block.prevFont;
537 block = block.parent;
540 else if(!strcmpi(keyWord, "script"))
544 else if(!strcmpi(keyWord, "/script"))
549 else if(!strcmpi(keyWord, "style"))
553 else if(!strcmpi(keyWord, "/style"))
558 else if(!strcmpi(keyWord, "input"))
560 subBlock = AddBlock(block, INPUT);
563 GetKeyWord(&string, keyWord, sizeof(keyWord));
565 if(!strcmpi(keyWord, "type"))
567 GetKeyWord(&string, keyWord, sizeof(keyWord));
568 if(!strcmpi(keyWord, "text"))
570 subBlock.inputType = InputType::text;
572 else if(!strcmpi(keyWord, "submit"))
574 subBlock.inputType = submit;
576 else if(!strcmpi(keyWord, "radio"))
578 subBlock.inputType = radio;
580 else if(!strcmpi(keyWord, "hidden"))
582 subBlock.inputType = hidden;
584 delete subBlock.href;
585 subBlock.href = CopyString(keyWord);
587 else if(!strcmpi(keyWord, "size"))
590 GetKeyWord(&string, keyWord, sizeof(keyWord));
591 size = atoi(keyWord);
593 else if(!strcmpi(keyWord, "value"))
595 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false);
596 delete subBlock.value;
597 subBlock.value = CopyString(keyWord);
599 else if(!strcmpi(keyWord, "name"))
601 GetKeyWord(&string, keyWord, sizeof(keyWord));
602 delete subBlock.name;
603 subBlock.name = CopyString(keyWord);
607 else if(!strcmpi(keyWord, "form"))
609 subBlock = AddBlock(block, FORM);
612 GetKeyWord(&string, keyWord, sizeof(keyWord));
614 if(!strcmpi(keyWord, "action"))
616 GetKeyWordEx(&string, keyWord, sizeof(keyWord), false);
617 delete subBlock.action;
618 subBlock.action = CopyString(keyWord);
623 else if(!strcmpi(keyWord, "/form"))
625 if(block.type == FORM)
627 block = block.parent;
630 else if(!strcmpi(keyWord, "center"))
632 subBlock = AddBlock(block, CENTER);
635 else if(!strcmpi(keyWord, "/center"))
637 if(block.type == CENTER)
639 block = block.parent;
642 else if(!strcmpi(keyWord, "table"))
645 subBlock = AddBlock(block, TABLE);
646 subBlock.cellPadding = 4;
649 GetKeyWord(&string, keyWord, sizeof(keyWord));
651 if(!strcmpi(keyWord, "width"))
653 GetKeyWord(&string, keyWord, sizeof(keyWord));
654 if(strstr(keyWord, "%"))
655 subBlock.pWidth = atoi(keyWord);
657 subBlock.width = atoi(keyWord);
659 else if(!strcmpi(keyWord, "height"))
661 GetKeyWord(&string, keyWord, sizeof(keyWord));
662 if(strstr(keyWord, "%"))
663 subBlock.pHeight = atoi(keyWord);
665 subBlock.height = atoi(keyWord);
667 else if(!strcmpi(keyWord, "cellpadding"))
669 GetKeyWord(&string, keyWord, sizeof(keyWord));
670 subBlock.cellPadding = atoi(keyWord);
672 else if(!strcmpi(keyWord, "background"))
674 GetKeyWord(&string, keyWord, sizeof(keyWord));
676 subBlock.src = CopyString(keyWord);
678 else if(!strcmpi(keyWord, "bgcolor"))
680 GetKeyWord(&string, keyWord, sizeof(keyWord));
681 subBlock.bgColor = 0xFF000000 | strtol((keyWord[0] == '#') ? (keyWord+1) : keyWord, null, 16);
683 else if(!strcmpi(keyWord, "align"))
685 GetKeyWord(&string, keyWord, sizeof(keyWord));
686 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
688 subBlock.halign = middle;
690 else if(!strcmpi(keyWord, "left"))
692 subBlock.halign = left;
694 else if(!strcmpi(keyWord, "right"))
696 subBlock.halign = right;
703 else if(!strcmpi(keyWord, "/table"))
707 block = block.parent;
712 block = block.parent;
715 if(block.type == TABLE)
717 block = block.parent;
721 else if(!strcmpi(keyWord, "tr"))
725 block = block.parent;
730 block = block.parent;
734 subBlock = AddBlock(block, TR);
738 GetKeyWord(&string, keyWord, sizeof(keyWord));
740 if(!strcmpi(keyWord, "height"))
742 GetKeyWord(&string, keyWord, sizeof(keyWord));
743 subBlock.height = atoi(keyWord);
746 if(!strcmpi(keyWord, "align"))
748 GetKeyWord(&string, keyWord, sizeof(keyWord));
749 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
751 subBlock.valign = middle;
753 else if(!strcmpi(keyWord, "top"))
755 subBlock.valign = top;
757 else if(!strcmpi(keyWord, "bottom"))
759 subBlock.valign = bottom;
765 else if(!strcmpi(keyWord, "/tr"))
769 block = block.parent;
774 block = block.parent;
778 else if(!strcmpi(keyWord, "td"))
780 while(block && block.type != TR && block.type != TABLE)
782 if(block == fontBlock)
783 fontBlock = block.prevFont;
784 block = block.parent;
789 if(block.type == TABLE)
791 block = AddBlock(block, TR);
793 subBlock = AddBlock(block, TD);
794 subBlock.span = subBlock.rowSpan = 1;
795 subBlock.valign = block.valign;
796 subBlock.halign = block.halign;
800 GetKeyWord(&string, keyWord, sizeof(keyWord));
802 if(!strcmpi(keyWord, "width"))
804 GetKeyWord(&string, keyWord, sizeof(keyWord));
805 if(strstr(keyWord, "%"))
806 subBlock.pWidth = atoi(keyWord);
808 subBlock.width = atoi(keyWord);
810 else if(!strcmpi(keyWord, "height"))
812 GetKeyWord(&string, keyWord, sizeof(keyWord));
813 if(strstr(keyWord, "%"))
814 subBlock.pHeight = atoi(keyWord);
816 subBlock.height = atoi(keyWord);
818 else if(!strcmpi(keyWord, "colspan"))
820 GetKeyWord(&string, keyWord, sizeof(keyWord));
821 subBlock.span = atoi(keyWord);
823 else if(!strcmpi(keyWord, "cellpadding"))
825 GetKeyWord(&string, keyWord, sizeof(keyWord));
826 subBlock.cellPadding = atoi(keyWord);
828 else if(!strcmpi(keyWord, "rowspan"))
830 GetKeyWord(&string, keyWord, sizeof(keyWord));
831 subBlock.rowSpan = atoi(keyWord);
833 else if(!strcmpi(keyWord, "nowrap"))
835 subBlock.noWrap = true;
837 else if(!strcmpi(keyWord, "background"))
839 GetKeyWord(&string, keyWord, sizeof(keyWord));
841 subBlock.src = CopyString(keyWord);
843 else if(!strcmpi(keyWord, "bgcolor"))
845 GetKeyWord(&string, keyWord, sizeof(keyWord));
846 subBlock.bgColor = 0xFF000000 | strtol((keyWord[0] == '#') ? (keyWord+1) : keyWord, null, 16);
848 else if(!strcmpi(keyWord, "valign"))
850 GetKeyWord(&string, keyWord, sizeof(keyWord));
851 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
853 subBlock.valign = middle;
855 else if(!strcmpi(keyWord, "top"))
857 subBlock.valign = top;
859 else if(!strcmpi(keyWord, "bottom"))
861 subBlock.valign = bottom;
864 else if(!strcmpi(keyWord, "align"))
866 GetKeyWord(&string, keyWord, sizeof(keyWord));
867 if(!strcmpi(keyWord, "middle") || !strcmpi(keyWord, "center") )
869 subBlock.halign = middle;
871 else if(!strcmpi(keyWord, "left"))
873 subBlock.halign = left;
875 else if(!strcmpi(keyWord, "right"))
877 subBlock.halign = right;
884 else if(!strcmpi(keyWord, "/td"))
888 block = block.parent;
892 else if(!strcmpi(keyWord, "/html"))
907 if(!strcmp(tag, "!--"))
921 if(block.type == TABLE)
923 subBlock = AddBlock(block, TR);
928 subBlock = AddBlock(block, TD);
929 subBlock.span = subBlock.rowSpan = 1;
930 subBlock.valign = block.valign;
931 subBlock.halign = block.halign;
935 subBlock = AddBlock(block, TEXT);
936 delete subBlock.text;
937 subBlock.text = CopyString(text);
938 subBlock.textLen = textLen;
949 else if(ch != '\n' && ch != '\r' && ch != '\t' && !insideScript && !insideStyle)
957 if(!strcmpi(symbol, "nbsp"))
959 else if(!strcmpi(symbol, "copy"))
961 else if(!strcmpi(symbol, "raquo"))
963 else if(!strcmpi(symbol, "eacute"))
965 else if(!strcmpi(symbol, "egrave"))
967 else if(!strcmpi(symbol, "ecirc"))
969 else if(!strcmpi(symbol, "agrave"))
971 else if(!strcmpi(symbol, "acirc"))
973 else if(!strcmpi(symbol, "ocirc"))
977 int len = UTF32toUTF8Len(&unicode, 1, utf8, 5);
979 for(c = 0; c<len; c++)
980 text[textLen++] = utf8[c];
983 text[textLen] = '\0';
984 insideSymbol = false;
988 // Give up... Treat it as text
989 text[textLen++] = '&';
990 CopyBytes(text + textLen, symbol, symbolLen);
991 textLen += symbolLen;
992 lastCh = text[textLen++] = ' ';
993 text[textLen] = '\0';
994 insideSymbol = false;
998 symbol[symbolLen++] = ch;
999 symbol[symbolLen] = '\0';
1006 insideSymbol = true;
1012 if(ch != ' ' || lastCh != ' ' || code)
1013 // if(ch != ' ' || (textLen && text[textLen-1] !=' '))
1016 text[textLen++] = ch;
1017 text[textLen] = '\0';
1022 else if(ch == '\n' && code)
1024 //printf("%d\n", textLen);
1027 subBlock = AddBlock(block, TEXT);
1028 delete subBlock.text;
1029 subBlock.text = CopyString(text);
1030 subBlock.textLen = textLen;
1033 subBlock = AddBlock(block, BR);