├── rsrc ├── TEXT │ ├── 129.txt │ ├── 128.txt │ └── 130.txt ├── WWW6 │ └── 0.hex ├── FREF │ ├── 128.hex │ ├── 129.hex │ ├── 130.hex │ ├── 131.hex │ ├── 132.hex │ ├── 133.hex │ ├── 134.hex │ ├── 135.hex │ ├── 136.hex │ └── 137.hex ├── MBAR │ └── 128.hex ├── SIZE │ └── 128.hex ├── ALRT │ └── 129.hex ├── DLOG │ ├── 128.hex │ └── 1042.hex ├── CNTL │ ├── 130.hex │ ├── 132.hex │ ├── 512.hex │ ├── 513.hex │ ├── 514.hex │ ├── 300.hex │ ├── 301.hex │ ├── 302.hex │ ├── 305.hex │ ├── 128.hex │ └── 257.hex ├── MENU │ ├── 132.hex │ ├── 128.hex │ ├── 131.hex │ ├── 130.hex │ └── 129.hex ├── WIND │ └── 128.hex ├── acur │ ├── 129.hex │ └── 128.hex ├── vers │ ├── 2.hex │ └── 1.hex ├── DITL │ ├── 129.hex │ ├── 128.hex │ └── 1042.hex ├── ics# │ ├── 128.hex │ ├── 129.hex │ └── 130.hex ├── BNDL │ └── 128.hex ├── CURS │ ├── 1001.hex │ ├── 1002.hex │ ├── 1003.hex │ ├── 1004.hex │ ├── 1005.hex │ ├── 1006.hex │ ├── 1007.hex │ ├── 128.hex │ ├── 129.hex │ ├── 6500.hex │ ├── 6501.hex │ ├── 6502.hex │ ├── 6503.hex │ ├── 6504.hex │ ├── 6505.hex │ ├── 6506.hex │ ├── 30000.hex │ ├── 30001.hex │ ├── 30002.hex │ └── 30003.hex ├── FOND │ └── 488.hex ├── STR# │ ├── 128.hex │ └── 700.hex ├── ics4 │ ├── 128.hex │ ├── 129.hex │ └── 130.hex ├── SICN │ ├── 128.hex │ └── 129.hex ├── TMPL │ └── 129.hex ├── ICN# │ ├── 128.hex │ ├── 129.hex │ └── 130.hex ├── ics8 │ ├── 128.hex │ ├── 129.hex │ └── 130.hex ├── icl4 │ ├── 128.hex │ ├── 129.hex │ └── 130.hex ├── Styl │ └── 128.hex ├── icl8 │ ├── 128.hex │ ├── 129.hex │ ├── 130.hex │ └── 140.hex ├── MIME │ └── 256.hex └── FONT │ └── 3060.hex ├── src ├── parser.c ├── uri │ ├── about.h │ ├── file.h │ ├── http.h │ ├── about.c │ ├── file.c │ └── http.c ├── menus.h ├── parser.h ├── Browsy.h ├── document.h ├── document.c ├── utils.h ├── window.h ├── tokenizer.h ├── uri.h ├── menus.c ├── uri.c ├── main.c ├── utils.c ├── tokenizer.c └── window.c ├── .gitignore ├── README.md ├── page.html └── Makefile /rsrc/TEXT/129.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /rsrc/WWW6/0.hex: -------------------------------------------------------------------------------- 1 | 00 2 | -------------------------------------------------------------------------------- /rsrc/FREF/128.hex: -------------------------------------------------------------------------------- 1 | 4150 504C 0000 00 2 | -------------------------------------------------------------------------------- /rsrc/FREF/129.hex: -------------------------------------------------------------------------------- 1 | 5445 5854 0001 00 2 | -------------------------------------------------------------------------------- /rsrc/FREF/130.hex: -------------------------------------------------------------------------------- 1 | 4854 4D4C 0002 00 2 | -------------------------------------------------------------------------------- /rsrc/FREF/131.hex: -------------------------------------------------------------------------------- 1 | 5552 4C20 0003 00 2 | -------------------------------------------------------------------------------- /rsrc/FREF/132.hex: -------------------------------------------------------------------------------- 1 | 4150 504C 0000 00 2 | -------------------------------------------------------------------------------- /rsrc/FREF/133.hex: -------------------------------------------------------------------------------- 1 | 5445 5854 0001 00 2 | -------------------------------------------------------------------------------- /rsrc/FREF/134.hex: -------------------------------------------------------------------------------- 1 | 4854 4D4C 0002 00 2 | -------------------------------------------------------------------------------- /rsrc/FREF/135.hex: -------------------------------------------------------------------------------- 1 | 5552 4C20 0003 00 2 | -------------------------------------------------------------------------------- /rsrc/FREF/136.hex: -------------------------------------------------------------------------------- 1 | 4749 4666 0004 00 2 | -------------------------------------------------------------------------------- /rsrc/FREF/137.hex: -------------------------------------------------------------------------------- 1 | 4A50 4547 0005 00 2 | -------------------------------------------------------------------------------- /rsrc/MBAR/128.hex: -------------------------------------------------------------------------------- 1 | 0004 0080 0081 0082 0083 2 | -------------------------------------------------------------------------------- /rsrc/SIZE/128.hex: -------------------------------------------------------------------------------- 1 | 5840 0001 F400 0000 FA00 2 | -------------------------------------------------------------------------------- /rsrc/ALRT/129.hex: -------------------------------------------------------------------------------- 1 | 0050 0078 00D3 0180 0081 5555 2 | -------------------------------------------------------------------------------- /rsrc/DLOG/128.hex: -------------------------------------------------------------------------------- 1 | 0060 0096 00BA 017D 0001 0100 0100 0000 2 | 0000 0080 00 3 | -------------------------------------------------------------------------------- /rsrc/CNTL/130.hex: -------------------------------------------------------------------------------- 1 | 001E 01DD 019C 01ED 0000 0100 0064 0000 2 | 0010 0000 000A 00 3 | -------------------------------------------------------------------------------- /rsrc/CNTL/132.hex: -------------------------------------------------------------------------------- 1 | 019B 01A2 01AB 01DE 0000 0100 0064 0000 2 | 0010 0000 000A 00 3 | -------------------------------------------------------------------------------- /rsrc/CNTL/512.hex: -------------------------------------------------------------------------------- 1 | 0000 FC18 0014 FC28 0000 0000 0001 0000 2 | 0000 0000 0004 00 3 | -------------------------------------------------------------------------------- /rsrc/CNTL/513.hex: -------------------------------------------------------------------------------- 1 | 0000 FC18 0012 FC28 0000 0000 0001 0000 2 | 0001 0000 0004 00 3 | -------------------------------------------------------------------------------- /rsrc/CNTL/514.hex: -------------------------------------------------------------------------------- 1 | 0000 FC18 0012 FC28 0000 0000 0001 0000 2 | 0002 0000 0004 00 3 | -------------------------------------------------------------------------------- /rsrc/MENU/132.hex: -------------------------------------------------------------------------------- 1 | 0084 0000 0000 0000 0000 FFFF FFFF 0748 2 | 6973 746F 7279 00 3 | -------------------------------------------------------------------------------- /rsrc/CNTL/300.hex: -------------------------------------------------------------------------------- 1 | 00BE 00E8 00D1 00FB 0000 0100 0001 0000 2 | 0000 0000 0000 0100 3 | -------------------------------------------------------------------------------- /rsrc/CNTL/301.hex: -------------------------------------------------------------------------------- 1 | 0004 0072 001A 008A 0000 0100 0001 0000 2 | 0000 0000 0000 0200 8E 3 | -------------------------------------------------------------------------------- /rsrc/CNTL/302.hex: -------------------------------------------------------------------------------- 1 | 0004 0090 001A 00A8 0000 0100 0001 0000 2 | 0000 0000 0000 0100 3 | -------------------------------------------------------------------------------- /rsrc/CNTL/305.hex: -------------------------------------------------------------------------------- 1 | 0004 00CA 001A 00E2 0000 0100 0001 0000 2 | 0C90 0000 0000 0400 9600 97 3 | -------------------------------------------------------------------------------- /rsrc/WIND/128.hex: -------------------------------------------------------------------------------- 1 | 0032 000B 0146 01F1 0008 0100 0100 0000 2 | 0000 0855 6E74 6974 6C65 646F 280A 3 | -------------------------------------------------------------------------------- /rsrc/DLOG/1042.hex: -------------------------------------------------------------------------------- 1 | 008A 0075 00BE 0179 0005 0100 0000 0000 2 | 0000 0412 094D 6163 5443 502E 2E2E 280A 3 | -------------------------------------------------------------------------------- /rsrc/acur/129.hex: -------------------------------------------------------------------------------- 1 | 0007 0000 03E9 0000 03EA 0000 03EB 0000 2 | 03EC 0000 03ED 0000 03EE 0000 03EF 0000 3 | -------------------------------------------------------------------------------- /rsrc/CNTL/128.hex: -------------------------------------------------------------------------------- 1 | 001E 0011 0034 011D 0000 0100 0000 0000 2 | 0000 0000 0000 0C41 6464 7265 7373 2062 3 | 6172 3F 4 | -------------------------------------------------------------------------------- /rsrc/CNTL/257.hex: -------------------------------------------------------------------------------- 1 | 019F 0153 01A7 019E 0000 0100 0064 8000 2 | 2000 0000 0000 0C50 726F 6772 6573 7320 3 | 4261 72 4 | -------------------------------------------------------------------------------- /src/parser.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "document.h" 4 | #include "parser.h" 5 | 6 | -------------------------------------------------------------------------------- /rsrc/acur/128.hex: -------------------------------------------------------------------------------- 1 | 0008 0000 0004 0000 1964 0000 1965 0000 2 | 1966 0000 1967 0000 1968 0000 1969 0000 3 | 196A 0000 4 | -------------------------------------------------------------------------------- /rsrc/vers/2.hex: -------------------------------------------------------------------------------- 1 | 0020 2000 0000 0530 2E32 2E30 1967 6974 2 | 6875 622E 636F 6D2F 636C 6568 6E65 722F 3 | 4272 6F77 7379 4 | -------------------------------------------------------------------------------- /src/uri/about.h: -------------------------------------------------------------------------------- 1 | #ifndef _URI_ABOUT_H 2 | #define _URI_ABOUT_H 3 | 4 | struct URIProvider *aboutURIProvider; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bin 2 | *.dsk 3 | *.68k 4 | *.gdb 5 | *.o 6 | *.i 7 | *.d 8 | rsrc-args 9 | rsrc/*/*.dat 10 | dep 11 | lib 12 | -------------------------------------------------------------------------------- /rsrc/MENU/128.hex: -------------------------------------------------------------------------------- 1 | 0080 0000 0000 0000 0000 FFFF FFFB 0114 2 | 0D41 626F 7574 2042 726F 7773 79C9 0000 3 | 0000 012D 0000 0000 00 4 | -------------------------------------------------------------------------------- /src/uri/file.h: -------------------------------------------------------------------------------- 1 | #ifndef _URI_FILE_H 2 | #define _URI_FILE_H 3 | 4 | struct URIProvider *fileURIProvider; 5 | 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /src/uri/http.h: -------------------------------------------------------------------------------- 1 | #ifndef _URI_HTTP_H 2 | #define _URI_HTTP_H 3 | 4 | struct URIProvider *httpURIProvider; 5 | 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /src/menus.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H 2 | #define _UTILs_H 3 | 4 | void SetupMenus(); 5 | void HandleMenu(long menuAction); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /rsrc/DITL/129.hex: -------------------------------------------------------------------------------- 1 | 0001 0000 0000 0060 00BE 0074 00F8 0402 2 | 4F4B 0000 0000 000B 0044 0059 00FF 080B 3 | 5E30 0D5E 310D 5E32 0D5E 3300 4 | -------------------------------------------------------------------------------- /rsrc/vers/1.hex: -------------------------------------------------------------------------------- 1 | 0020 2000 0000 0530 2E32 2E30 2742 726F 2 | 7773 7920 302E 322E 300D A920 3230 3132 3 | 2D32 3031 3420 4368 6172 6C65 7320 4C65 4 | 686E 6572 5 | -------------------------------------------------------------------------------- /rsrc/ics#/128.hex: -------------------------------------------------------------------------------- 1 | 0000 0100 0280 0440 0920 1110 2708 4464 2 | 9C92 414E 26F6 1106 08FE 0446 0280 0100 3 | 0000 0100 0380 07C0 0FE0 1FF0 3FF8 7FFC 4 | FFFE 7FFE 3FFE 1FFE 0FFE 07C6 0380 0100 5 | -------------------------------------------------------------------------------- /rsrc/ics#/129.hex: -------------------------------------------------------------------------------- 1 | 7FE0 4030 4028 55BC 5C84 55C4 4004 4004 2 | 5EE4 4004 5F84 4024 4F54 4024 4004 7FFC 3 | 7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC 4 | 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 5 | -------------------------------------------------------------------------------- /rsrc/ics#/130.hex: -------------------------------------------------------------------------------- 1 | 7FE0 4030 4028 403C 4384 47C4 47C4 5FC4 2 | 5184 5114 5134 5F54 4094 41F4 4004 7FFC 3 | 7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC 4 | 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 5 | -------------------------------------------------------------------------------- /rsrc/BNDL/128.hex: -------------------------------------------------------------------------------- 1 | 5757 5736 0000 0001 4652 4546 0005 0000 2 | 0084 0001 0085 0002 0086 0003 0087 0004 3 | 0088 0005 0089 4943 4E23 0005 0000 0080 4 | 0001 0081 0002 0081 0003 0000 0004 0082 5 | 0005 0082 6 | -------------------------------------------------------------------------------- /rsrc/CURS/1001.hex: -------------------------------------------------------------------------------- 1 | 07C0 1F30 2D98 4ECC 4FA4 8762 87C2 87C2 2 | 83A2 8182 40F4 40F4 2068 1870 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/1002.hex: -------------------------------------------------------------------------------- 1 | 07C0 1870 30E8 70F4 50F4 E07E E07E C07A 2 | 803A C81A 5C0C 7C04 2008 1830 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/1003.hex: -------------------------------------------------------------------------------- 1 | 07C0 1FB0 3D18 7F0C 7D0C FE02 FE02 FC02 2 | A802 8482 51C4 43C4 2008 1830 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/1004.hex: -------------------------------------------------------------------------------- 1 | 07C0 18F0 3FD8 7FFC 7FD4 9FE2 EFE2 F6C2 2 | F282 E04A 611C 503C 2008 1830 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/1005.hex: -------------------------------------------------------------------------------- 1 | 07C0 1E70 3FF8 7FFC 7FFC 91FE 8EFE 9F6E 2 | 9F2A 8E02 4E14 4D04 2008 1830 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/1006.hex: -------------------------------------------------------------------------------- 1 | 07C0 1AF0 29F8 63FC 53FC B11E E0CE E1F2 2 | D1F2 C0E2 78E4 78D4 3008 1830 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/1007.hex: -------------------------------------------------------------------------------- 1 | 07C0 19B0 2C98 763C 7D3C BB12 BE0E BE1E 2 | 9D1E 8C0E 4784 4784 2308 1B30 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/128.hex: -------------------------------------------------------------------------------- 1 | 0300 0480 0480 0480 0480 0480 64F8 94AC 2 | 4CAA 240A 2402 1002 0802 0804 0404 0404 3 | 0300 0780 0780 0780 0780 0780 67F8 F7FC 4 | 7FFE 3FFE 3FFE 1FFE 0FFE 0FFC 07FC 07FC 5 | 0000 0006 6 | -------------------------------------------------------------------------------- /rsrc/CURS/129.hex: -------------------------------------------------------------------------------- 1 | 0380 04C0 04C0 04C0 04C0 04C0 74F8 9CAE 2 | 4CAB 240B 2403 1003 0803 0806 0406 0406 3 | 0300 0780 0780 0780 0780 0780 67F8 F7FC 4 | 7FFE 3FFE 3FFE 1FFE 0FFE 0FFC 07FC 07FC 5 | 0000 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/6500.hex: -------------------------------------------------------------------------------- 1 | 3F00 3F00 3F00 3F00 4080 8040 8140 8260 2 | 9C60 8040 8040 4080 3F00 3F00 3F00 3F00 3 | 3F00 3F00 3F00 3F00 7F80 FFC0 FFC0 FFC0 4 | FFC0 FFC0 FFC0 7F80 3F00 3F00 3F00 3F00 5 | 0008 0008 6 | -------------------------------------------------------------------------------- /rsrc/CURS/6501.hex: -------------------------------------------------------------------------------- 1 | 3F00 3F00 3F00 3F00 4080 8040 8040 8060 2 | 9F60 8040 8040 4080 3F00 3F00 3F00 3F00 3 | 3F00 3F00 3F00 3F00 7F80 FFC0 FFC0 FFC0 4 | FFC0 FFC0 FFC0 7F80 3F00 3F00 3F00 3F00 5 | 0008 0008 6 | -------------------------------------------------------------------------------- /rsrc/CURS/6502.hex: -------------------------------------------------------------------------------- 1 | 3F00 3F00 3F00 3F00 4080 8040 8040 8060 2 | 9C60 8240 8040 4080 3F00 3F00 3F00 3F00 3 | 3F00 3F00 3F00 3F00 7F80 FFC0 FFC0 FFC0 4 | FFC0 FFC0 FFC0 7F80 3F00 3F00 3F00 3F00 5 | 0008 0008 6 | -------------------------------------------------------------------------------- /rsrc/CURS/6503.hex: -------------------------------------------------------------------------------- 1 | 3F00 3F00 3F00 3F00 4080 8040 8040 8060 2 | 9C60 8440 8440 4080 3F00 3F00 3F00 3F00 3 | 3F00 3F00 3F00 3F00 7F80 FFC0 FFC0 FFC0 4 | FFC0 FFC0 FFC0 7F80 3F00 3F00 3F00 3F00 5 | 0008 0008 6 | -------------------------------------------------------------------------------- /rsrc/CURS/6504.hex: -------------------------------------------------------------------------------- 1 | 3F00 3F00 3F00 3F00 4080 8040 8040 8060 2 | 9C60 8840 9040 4080 3F00 3F00 3F00 3F00 3 | 3F00 3F00 3F00 3F00 7F80 FFC0 FFC0 FFC0 4 | FFC0 FFC0 FFC0 7F80 3F00 3F00 3F00 3F00 5 | 0008 0008 6 | -------------------------------------------------------------------------------- /rsrc/CURS/6505.hex: -------------------------------------------------------------------------------- 1 | 3F00 3F00 3F00 3F00 4080 8040 8040 8060 2 | BC60 8040 8040 4080 3F00 3F00 3F00 3F00 3 | 3F00 3F00 3F00 3F00 7F80 FFC0 FFC0 FFC0 4 | FFC0 FFC0 FFC0 7F80 3F00 3F00 3F00 3F00 5 | 0008 0008 6 | -------------------------------------------------------------------------------- /rsrc/CURS/6506.hex: -------------------------------------------------------------------------------- 1 | 3F00 3F00 3F00 3F00 4080 8040 9040 8860 2 | 9C60 8040 8040 4080 3F00 3F00 3F00 3F00 3 | 3F00 3F00 3F00 3F00 7F80 FFC0 FFC0 FFC0 4 | FFC0 FFC0 FFC0 7F80 3F00 3F00 3F00 3F00 5 | 0008 0008 6 | -------------------------------------------------------------------------------- /rsrc/DITL/128.hex: -------------------------------------------------------------------------------- 1 | 0000 0000 0000 0008 0020 0056 0110 8834 2 | 4272 6F77 7379 200D 6120 636F 6F6C 2062 3 | 726F 7773 6572 2E0D 0DA9 2043 6861 726C 4 | 6573 204C 6568 6E65 722C 2032 3031 322D 5 | 3230 3134 6 | -------------------------------------------------------------------------------- /rsrc/CURS/30000.hex: -------------------------------------------------------------------------------- 1 | 07C0 1830 2008 701C 783C FC7E FEFE FFFE 2 | FEFE FC7E 783C 701C 2008 1830 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/30001.hex: -------------------------------------------------------------------------------- 1 | 07C0 19F0 21F8 41FC 41FC 81FE 81FE FFFE 2 | FF02 FF02 7F04 7F04 3F08 1F30 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/30002.hex: -------------------------------------------------------------------------------- 1 | 07C0 1FF0 3FF8 5FF4 4FE4 87C2 8382 8102 2 | 8382 87C2 4FE4 5FF4 3FF8 1FF0 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /rsrc/CURS/30003.hex: -------------------------------------------------------------------------------- 1 | 07C0 1F30 3F08 7F04 7F04 FF02 FF02 FFFE 2 | 81FE 81FE 41FC 41FC 21F8 19F0 07C0 0000 3 | 07C0 1FF0 3FF8 7FFC 7FFC FFFE FFFE FFFE 4 | FFFE FFFE 7FFC 7FFC 3FF8 1FF0 07C0 0000 5 | 0007 0007 6 | -------------------------------------------------------------------------------- /src/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARSER_H 2 | #define _PARSER_H 3 | 4 | typedef enum { 5 | ParserStateStart, 6 | } ParserState; 7 | 8 | typedef struct { 9 | ParserState state; 10 | } Parser; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /rsrc/FOND/488.hex: -------------------------------------------------------------------------------- 1 | 0000 01E8 0000 00FF 0000 0000 0000 0000 2 | 0000 0000 0000 0000 0000 0000 0000 0000 3 | 0000 0000 0000 0000 0000 0000 0000 0000 4 | 0000 0002 0000 000C 0000 F40C 0000 0000 5 | 0006 0000 0000 0000 FC00 1000 0C00 6 | -------------------------------------------------------------------------------- /rsrc/DITL/1042.hex: -------------------------------------------------------------------------------- 1 | 0001 0000 0000 0008 003C 0028 00F0 882F 2 | 506C 6561 7365 2077 6169 7420 666F 7220 3 | 6E65 7477 6F72 6B20 6F70 6572 6174 696F 4 | 6E73 2074 6F20 636F 6D70 6C65 7465 2E00 5 | 0000 0000 0008 0008 0028 0028 A002 0001 6 | -------------------------------------------------------------------------------- /rsrc/STR#/128.hex: -------------------------------------------------------------------------------- 1 | 0002 1D42 726F 7773 792F 2573 2028 4D61 2 | 6369 6E74 6F73 683B 204E 3B20 3638 4B29 3 | 334C 796E 782F 322E 3820 2863 6F6D 7061 4 | 7469 626C 653B 2042 726F 7773 792F 2573 5 | 2028 4D61 6369 6E74 6F73 683B 204E 3B20 6 | 3638 4B29 7 | -------------------------------------------------------------------------------- /rsrc/MENU/131.hex: -------------------------------------------------------------------------------- 1 | 0083 0000 0000 0000 0000 FFFF FF6F 084E 2 | 6176 6967 6174 6508 4261 636B 7761 7264 3 | 005B 0000 0746 6F72 7761 7264 005D 0000 4 | 0448 6F6D 6500 4800 0001 2D00 0000 0004 5 | 5374 6F70 002E 0000 0652 656C 6F61 6400 6 | 5200 0001 2D00 0000 0007 4869 7374 6F72 7 | 7900 1B84 0000 8 | -------------------------------------------------------------------------------- /rsrc/TEXT/128.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | about:Browsy 5 | 6 | 7 |

about:Browsy

8 |

A web browser made for 68k Macs.

9 | 13 | 14 | -------------------------------------------------------------------------------- /rsrc/MENU/130.hex: -------------------------------------------------------------------------------- 1 | 0082 0000 0000 0000 0000 FFFF F97B 0445 2 | 6469 7404 556E 646F 005A 0000 012D 0000 3 | 0000 0343 7574 0058 0000 0443 6F70 7900 4 | 4300 0005 5061 7374 6500 5600 0005 436C 5 | 6561 7200 0000 0001 2D00 0000 000A 5365 6 | 6C65 6374 2041 6C6C 0041 0000 012D 0000 7 | 0000 0E50 7265 6665 7265 6E63 6573 2E2E 8 | 2E00 3B00 0000 9 | -------------------------------------------------------------------------------- /rsrc/ics4/128.hex: -------------------------------------------------------------------------------- 1 | 0000 0000 0000 0000 0000 000F 0000 0000 2 | 0000 00F0 F000 0000 0000 0F0C 0F00 0000 3 | 0000 F0CF C0F0 0000 000F 0C0F 0C0F 0000 4 | 00F0 CFFF C0C0 F000 0F0C 0F0C 0FFC 0F00 5 | F0CF FFC0 F02F C0F0 0F0C 0C0F 2F02 FFF0 6 | 00F0 CFF0 FFFF 2FF0 000F 0C0F 0202 0FF0 7 | 0000 F0C0 FFFF FFF0 0000 0F0C 0F00 0FF0 8 | 0000 00F0 F000 0000 0000 000F 0000 0000 9 | -------------------------------------------------------------------------------- /rsrc/ics4/129.hex: -------------------------------------------------------------------------------- 1 | 0FFF FFFF FFF0 0000 0F0C 0C0C 0CFF 0000 2 | 0FC0 C0C0 C0FC F000 0F0F 0F0F FCFF FF00 3 | 0FCF FFC0 F0CC CF00 0F0F 0F0F FF0C CF00 4 | 0FC0 C0C0 C0C0 CF00 0F0C 0C0C 0C0C CF00 5 | 0FCF FFF0 FFF0 CF00 0F0C 0C0C 0C0C CF00 6 | 0FCF FFFF F0C0 CF00 0F0C 0C0C 0CFC CF00 7 | 0FC0 FFFF CF0F CF00 0F0C 0C0C 0CFC CF00 8 | 0FC0 C0C0 C0C0 CF00 0FFF FFFF FFFF FF00 9 | -------------------------------------------------------------------------------- /rsrc/ics4/130.hex: -------------------------------------------------------------------------------- 1 | 0FFF FFFF FFF0 0000 0F0C 0C0C 0CFF 0000 2 | 0FC0 C0C0 C0FC F000 0F0C 0C0C 0CFF FF00 3 | 0FC0 C0EE E0CC CF00 0F0C 0E88 8E0C CF00 4 | 0FC0 CE88 8EC0 CF00 0F06 6666 8E0C CF00 5 | 0FC6 CCC6 E0C0 CF00 0F06 CCC6 0C04 CF00 6 | 0FC6 CCC6 C044 CF00 0F06 6666 0424 CF00 7 | 0FC0 C0C0 4224 CF00 0F0C 0C04 4444 CF00 8 | 0FC0 C0C0 C0C0 CF00 0FFF FFFF FFFF FF00 9 | -------------------------------------------------------------------------------- /src/Browsy.h: -------------------------------------------------------------------------------- 1 | #ifndef _BROWSY_H 2 | #define _BROWSY_H 3 | 4 | //const short defaultALRT = 129; 5 | 6 | #define BROWSY_VERSION "0.2.0" 7 | 8 | Boolean HasColorQD; 9 | Boolean Sys7; 10 | 11 | typedef struct HistoryItem { 12 | char *title; 13 | char *address; 14 | struct HistoryItem *prev; 15 | struct HistoryItem *next; 16 | } HistoryItem; 17 | 18 | void Terminate(); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /rsrc/MENU/129.hex: -------------------------------------------------------------------------------- 1 | 0081 0000 0000 0000 0000 FFFF FB6F 0446 2 | 696C 650A 4E65 7720 5769 6E64 6F77 004E 3 | 0000 0A4F 7065 6E20 4669 6C65 C900 4F00 4 | 000E 4F70 656E 204C 6F63 6174 696F 6EC9 5 | 004C 0000 012D 0000 0000 0C43 6C6F 7365 6 | 2057 696E 646F 7700 5700 0008 5361 7665 7 | 2041 73C9 0053 0000 012D 0000 0000 0B50 8 | 6167 6520 5365 7475 70C9 0000 0000 0650 9 | 7269 6E74 C900 5000 0001 2D00 0000 0004 10 | 5175 6974 0051 0000 00 11 | -------------------------------------------------------------------------------- /rsrc/SICN/128.hex: -------------------------------------------------------------------------------- 1 | 0000 0000 0000 0000 0100 0300 0700 0FFC 2 | 1FFC 0FFC 0700 0300 0100 0000 0000 0000 3 | 0000 0000 0000 0000 0040 0060 0070 1FF8 4 | 1FFC 1FF8 0070 0060 0040 0000 0000 0000 5 | 0000 0000 0000 0090 01D0 03E0 07F0 0FF8 6 | 1FFC 07F0 0670 0670 0670 0670 0000 0000 7 | 0000 0000 0000 0000 0C18 0E38 0770 03E0 8 | 01C0 03E0 0770 0E38 0C18 0000 0000 0000 9 | 0000 0000 0000 0000 03C8 0FF8 0C38 1878 10 | 18F8 1800 1800 0C30 0FF0 03C0 0000 0000 11 | -------------------------------------------------------------------------------- /rsrc/SICN/129.hex: -------------------------------------------------------------------------------- 1 | 0000 0000 0000 0000 0100 0200 0500 0A54 2 | 15A8 0A54 0500 0200 0100 0000 0000 0000 3 | 0000 0000 0000 0000 0040 0020 0050 1528 4 | 0AD4 1528 0050 0020 0040 0000 0000 0000 5 | 0000 0000 0000 0080 0150 02A0 0550 0AA8 6 | 1554 02A0 0450 0220 0450 0220 0000 0000 7 | 0000 0000 0000 0000 0410 0A28 0550 02A0 8 | 0140 02A0 0550 0A28 0410 0000 0000 0000 9 | 0000 0000 0000 0000 0288 0550 0828 1050 10 | 08A8 1000 0800 0410 0AA0 0140 0000 0000 11 | -------------------------------------------------------------------------------- /src/document.h: -------------------------------------------------------------------------------- 1 | #ifndef _DOCUMENT_H 2 | #define _DOCUMENT_H 3 | 4 | #include "tokenizer.h" 5 | 6 | typedef struct Node { 7 | struct Node *parentNode; 8 | struct Node *firstChild; 9 | struct Node *nextSibling; 10 | } Node; 11 | 12 | typedef struct { 13 | void *data; 14 | Node *rootNode; 15 | Tokenizer *tokenizer; 16 | } DOMDocument; 17 | 18 | Node *NewNode(); 19 | void DisposeNode(Node *node); 20 | void DisposeNodes(Node *node); 21 | 22 | DOMDocument *NewDOMDocument(); 23 | void DisposeDOMDocument(DOMDocument *doc); 24 | void DOMDocumentParseAppend(DOMDocument *doc, Ptr data, long bytes); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /rsrc/TEXT/130.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | about:Browsy 5 | 6 | 7 |

about:Browsy

8 |

A web browser made for 68k Macs.

9 | 13 | 14 | 15 | 16 | 17 | about:Browsy 18 | 19 | 20 |

about:Browsy

21 |

A web browser made for 68k Macs.

22 | 26 | 27 | -------------------------------------------------------------------------------- /rsrc/TMPL/129.hex: -------------------------------------------------------------------------------- 1 | 0756 6572 7369 6F6E 4457 5244 074E 5374 2 | 796C 6573 4F43 4E54 052A 2A2A 2A2A 4C53 3 | 5443 0774 6167 4E61 6D65 4330 3130 0648 4 | 6964 6465 6E42 4249 5405 426C 6F63 6B42 5 | 4249 5404 426F 6C64 4242 4954 0649 7461 6 | 6C69 6342 4249 5409 556E 6465 726C 696E 7 | 6542 4249 540C 4C69 6E65 2D74 6872 6F75 8 | 6768 4242 4954 0852 6573 6572 7665 6442 9 | 4249 5408 5265 7365 7276 6564 4242 4954 10 | 0B66 6F6E 742D 6661 6D69 6C79 5030 3146 11 | 0966 6F6E 742D 7369 7A65 4442 5954 0A6D 12 | 6172 6769 6E2D 746F 7044 4259 540D 6D61 13 | 7267 696E 2D62 6F74 746F 6D44 4259 540B 14 | 7465 7874 2D69 6E64 656E 7444 5752 4405 15 | 636F 6C6F 7248 3030 3300 4157 5244 052A 16 | 2A2A 2A2A 4C53 5445 17 | -------------------------------------------------------------------------------- /rsrc/ICN#/128.hex: -------------------------------------------------------------------------------- 1 | 0001 0000 0002 8000 0004 4000 0008 2000 2 | 0010 1000 0020 0800 0040 2400 0080 1200 3 | 0100 5100 0201 2080 0404 C040 0802 0020 4 | 100A 0010 2024 0008 4018 3F04 8040 4082 5 | 4020 8041 20A1 3022 1241 C814 098E 7F8F 6 | 0402 3007 0201 0007 0100 8007 0080 6007 7 | 0040 1FE7 0020 021F 0010 0407 0008 0800 8 | 0004 1000 0002 2000 0001 4000 0000 8000 9 | 0001 0000 0003 8000 0007 C000 000F E000 10 | 001F F000 003F F800 007F FC00 00FF FE00 11 | 01FF FF00 03FF FF80 07FF FFC0 0FFF FFE0 12 | 1FFF FFF0 3FFF FFF8 7FFF FFFC FFFF FFFE 13 | 7FFF FFFF 3FFF FFFE 1FFF FFFC 0FFF FFFF 14 | 07FF FFFF 03FF FFFF 01FF FFFF 00FF FFFF 15 | 007F FFFF 003F FE1F 001F FC07 000F F800 16 | 0007 F000 0003 E000 0001 C000 0000 8000 17 | -------------------------------------------------------------------------------- /rsrc/ICN#/129.hex: -------------------------------------------------------------------------------- 1 | 1FFF FC00 1000 0600 1000 0500 1000 0480 2 | 1000 0440 1000 0420 1000 07F0 1000 0010 3 | 1000 0010 115D 1410 11C9 B410 1149 5710 4 | 1000 0010 1000 0010 1000 0010 1000 0010 5 | 11FB DF10 1000 0010 11F7 EE10 1000 0010 6 | 11EF 7810 1000 0010 1000 0010 1000 0010 7 | 1000 0010 11FF E610 1100 2910 11FF E610 8 | 1000 0010 1000 0010 1000 0010 1FFF FFF0 9 | 1FFF FC00 1FFF FE00 1FFF FF00 1FFF FF80 10 | 1FFF FFC0 1FFF FFE0 1FFF FFF0 1FFF FFF0 11 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 12 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 13 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 14 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 15 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 16 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 17 | -------------------------------------------------------------------------------- /rsrc/ICN#/130.hex: -------------------------------------------------------------------------------- 1 | 1FFF FC00 1000 0600 1000 0500 1000 0480 2 | 1000 0440 1000 0420 1000 07F0 1000 0010 3 | 1003 C010 100F F010 100F F010 101F F810 4 | 101F F810 11FF F810 1101 F810 1101 F010 5 | 1101 F210 1101 C610 1101 0A10 1101 1610 6 | 1101 2A10 11FF 5610 1000 AA10 1001 5610 7 | 1002 AA10 1007 FE10 1000 0010 1000 0010 8 | 1000 0010 1000 0010 1000 0010 1FFF FFF0 9 | 1FFF FC00 1FFF FE00 1FFF FF00 1FFF FF80 10 | 1FFF FFC0 1FFF FFE0 1FFF FFF0 1FFF FFF0 11 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 12 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 13 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 14 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 15 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 16 | 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 17 | -------------------------------------------------------------------------------- /rsrc/ics8/128.hex: -------------------------------------------------------------------------------- 1 | 0000 0000 0000 0000 0000 0000 0000 0000 2 | 0000 0000 0000 00FF 0000 0000 0000 0000 3 | 0000 0000 0000 FFF5 FF00 0000 0000 0000 4 | 0000 0000 00FF F5F5 F5FF 0000 0000 0000 5 | 0000 0000 FFF5 F5FF F5F5 FF00 0000 0000 6 | 0000 00FF F5F5 F5FF F5F5 F5FF 0000 0000 7 | 0000 FFF5 F5FF FFFF F5F5 F5F5 FF00 0000 8 | 00FF F5F5 F5FF F5F5 F5FF FFF5 F5FF 0000 9 | FFF5 F5FF FFFF F5F5 FF08 08FF F5F5 FF00 10 | 00FF F5F5 F5F5 F5FF 08FF 0808 FFFF FF00 11 | 0000 FFF5 F5FF FF08 FFFF FFFF 08FF FF00 12 | 0000 00FF F5F5 F5FF 0808 0808 08FF FF00 13 | 0000 0000 FFF5 F5F5 FFFF FFFF FFFF FF00 14 | 0000 0000 00FF F5F5 F5FF 0000 00FF FF00 15 | 0000 0000 0000 FFF5 FF00 0000 0000 0000 16 | 0000 0000 0000 00FF 0000 0000 0000 0000 17 | -------------------------------------------------------------------------------- /rsrc/ics8/129.hex: -------------------------------------------------------------------------------- 1 | 00FF FFFF FFFF FFFF FFFF FF00 0000 0000 2 | 00FF F5F5 F5F5 F5F5 F5F5 FFFF 0000 0000 3 | 00FF F5F5 F5F5 F5F5 F5F5 FF2B FF00 0000 4 | 00FF F5FF F5FF F5FF FFF5 FFFF FFFF 0000 5 | 00FF F5FF FFFF F5F5 FFF5 F62B 2BFF 0000 6 | 00FF F5FF F5FF F5FF FFFF F5F5 2BFF 0000 7 | 00FF F5F5 F5F5 F5F5 F5F5 F5F5 2BFF 0000 8 | 00FF F5F5 F5F5 F5F5 F5F5 F5F5 2BFF 0000 9 | 00FF F5FF FFFF FFF5 FFFF FFF5 2BFF 0000 10 | 00FF F5F5 F5F5 F5F5 F5F5 F5F5 2BFF 0000 11 | 00FF F5FF FFFF FFFF FFF5 F5F5 2BFF 0000 12 | 00FF F5F5 F5F5 F5F5 F5F5 FFF5 2BFF 0000 13 | 00FF F5F5 FFFF FFFF F5FF 00FF 2BFF 0000 14 | 00FF F5F5 F5F5 F5F5 F5F5 FFF5 2BFF 0000 15 | 00FF F5F5 F5F5 F5F5 F5F5 F5F5 2BFF 0000 16 | 00FF FFFF FFFF FFFF FFFF FFFF FFFF 0000 17 | -------------------------------------------------------------------------------- /rsrc/ics8/130.hex: -------------------------------------------------------------------------------- 1 | 00FF FFFF FFFF FFFF FFFF FF00 0000 0000 2 | 00FF F5F5 F5F5 F5F5 F5F5 FFFF 0000 0000 3 | 00FF F5F5 F5F5 F5F5 F5F5 FF2B FF00 0000 4 | 00FF F5F5 F5F5 F5F5 F5F5 FFFF FFFF 0000 5 | 00FF F5F5 F5F5 A5A5 A5F5 F5F6 F6FF 0000 6 | 00FF F5F5 F5A5 E3E3 E3A5 F5F5 F6FF 0000 7 | 00FF F5F5 F5A5 E3E3 E3A5 F5F5 F6FF 0000 8 | 00FF F5EC ECEC ECEC E3A5 F5F5 F6FF 0000 9 | 00FF F5EC 5454 54EC A5F5 F5F5 F6FF 0000 10 | 00FF F5EC 5454 54EC F5F5 F569 F6FF 0000 11 | 00FF F5EC 5454 54EC F5F5 6969 F6FF 0000 12 | 00FF F5EC ECEC ECEC F569 1669 F6FF 0000 13 | 00FF F5F5 F5F5 F5F5 6916 1669 F6FF 0000 14 | 00FF F5F5 F5F5 F569 6969 6969 F6FF 0000 15 | 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F6FF 0000 16 | 00FF FFFF FFFF FFFF FFFF FFFF FFFF 0000 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Browsy 2 | 3 | A browser for System 6. 4 | 5 | ![Browsy screenshot](https://cloud.githubusercontent.com/assets/95347/3683770/631346c6-12ed-11e4-8031-6242d7e36cfc.png) 6 | 7 | ## Stuff used 8 | 9 | - Development environment: [Retro68](https://github.com/autc04/Retro68/) 10 | - Streaming I/O library: [c-streams](https://github.com/clehner/c-streams) 11 | - HTTP parser: [http-parser](https://github.com/joyent/http-parser) 12 | 13 | ## TODO 14 | 15 | - Implement scrolling 16 | - Fix handling of chunked transfer encoding 17 | - Add download window 18 | - Parse HTML and maybe CSS 19 | - Render pages 20 | - Optimize memory usage (Use handles) 21 | 22 | Current plan: implement rendering of text into a TextEdit field. Style the text 23 | according to tag type (and later, CSS). Draw form controls and images (maybe) 24 | on top. 25 | -------------------------------------------------------------------------------- /src/document.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "document.h" 6 | #include "window.h" 7 | #include "utils.h" 8 | #include "tokenizer.h" 9 | 10 | Node *NewNode() { 11 | return (Node *)calloc(1, sizeof(Node)); 12 | } 13 | 14 | void DisposeNode(Node *node) { 15 | free(node); 16 | } 17 | 18 | void DisposeNodes(Node *node) { 19 | Node *curr; 20 | for (curr = node->firstChild; curr; curr = curr->nextSibling) { 21 | DisposeNodes(curr); 22 | } 23 | DisposeNode(node); 24 | } 25 | 26 | DOMDocument *NewDOMDocument() { 27 | DOMDocument *doc = (DOMDocument *)malloc(sizeof(DOMDocument)); 28 | doc->data = NULL; 29 | doc->rootNode = NewNode(); 30 | doc->tokenizer = NewTokenizer(); 31 | return doc; 32 | } 33 | 34 | void DisposeDOMDocument(DOMDocument *doc) { 35 | DisposeNodes(doc->rootNode); 36 | DisposeTokenizer(doc->tokenizer); 37 | free(doc); 38 | } 39 | 40 | void DOMDocumentParseAppend(DOMDocument *doc, Ptr data, long bytes) { 41 | //tokenize(doc->tokenizer); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H 2 | #define _UTILs_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define SIZE(array) (sizeof(array) / sizeof((array)[0])) 9 | #define MIN(a,b) ((a) < (b) ? (a) : (b)) 10 | 11 | typedef short SICN[16]; 12 | typedef SICN **SICNHand; 13 | void PlotSICN(Rect *theRect, SICNHand theSICN, long theIndex); 14 | 15 | void CheckWNE(); 16 | Boolean WNE(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn); 17 | char *GetFilePathName(int vRefNum, Str255 fName); 18 | int GetFilePathVolRef(char *pathFileName); 19 | const char *getFilePathFileName(const char *pathFileName); 20 | StringPtr CtoPCopy(const char *cstr); 21 | char *url_encode(char *str); 22 | char *url_decode(char *str); 23 | char *url_sanitize(char *str); 24 | //void PlotSICN(Rect *theRect, Handle theSICN, long theIndex); 25 | void CtoP(char *cstr, unsigned char *pstr); 26 | void ErrorAlert(char *text); 27 | void alertf(char *fmt, ...); 28 | void TEAppendText(const void *text, long length, TEHandle hTE); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /rsrc/icl4/128.hex: -------------------------------------------------------------------------------- 1 | 0000 0000 0000 000F 0000 0000 0000 0000 2 | 0000 0000 0000 00FC F000 0000 0000 0000 3 | 0000 0000 0000 0FC0 CF00 0000 0000 0000 4 | 0000 0000 0000 FC0C 0CF0 0000 0000 0000 5 | 0000 0000 000F C0C0 C0CF 0000 0000 0000 6 | 0000 0000 00FC 0C0C 0C0C F000 0000 0000 7 | 0000 0000 0FC0 C0C0 C0F0 CF00 0000 0000 8 | 0000 0000 FC0C 0C0C 0C0F 0CF0 0000 0000 9 | 0000 000F C0C0 C0C0 CFCF C0CF 0000 0000 10 | 0000 00FC 0C0C 0C0F 0CFC 0C0C F000 0000 11 | 0000 0FC0 C0C0 CFC0 FFC0 C0C0 CF00 0000 12 | 0000 FC0C 0C0C 0CFC 0C0C 0C0C 0CF0 0000 13 | 000F C0C0 C0C0 F0F0 C0C0 C0C0 C0CF 0000 14 | 00FC 0C0C 0CFC 0F0C 0C0C 0C0C 0C0C F000 15 | 0FC0 C0C0 C0CF F0C0 C0FF FFFF C0C0 CF00 16 | FC0C 0C0C 0F0C 0C0C 0F02 0202 FC0C 0CF0 17 | 0FC0 C0C0 C0F0 C0C0 F020 2020 2FC0 C0CF 18 | 00FC 0C0C FCFC 0C0F 02FF 0202 02FC 0CF0 19 | 000F C0F0 CFC0 C0CF FFC0 F020 202F CF00 20 | 0000 FC0F FC0C FFF2 0FFF FFFF F202 FFFF 21 | 0000 0FC0 C0C0 C0F0 20FF 2020 2020 2FFF 22 | 0000 00FC 0C0C 0C0F 0202 0202 0202 0FFF 23 | 0000 000F C0C0 C0C0 F020 2020 2020 2FFF 24 | 0000 0000 FC0C 0C0C 0FF2 0202 0202 0FFF 25 | 0000 0000 0FC0 C0C0 C0CF FFFF FFF0 2FFF 26 | 0000 0000 00FC 0C0C 0C0C 0CF0 000F FFFF 27 | 0000 0000 000F C0C0 C0C0 CF00 0000 0FFF 28 | 0000 0000 0000 FC0C 0C0C F000 0000 0000 29 | 0000 0000 0000 0FC0 C0CF 0000 0000 0000 30 | 0000 0000 0000 00FC 0CF0 0000 0000 0000 31 | 0000 0000 0000 000F CF00 0000 0000 0000 32 | 0000 0000 0000 0000 F000 0000 0000 0000 33 | -------------------------------------------------------------------------------- /rsrc/icl4/129.hex: -------------------------------------------------------------------------------- 1 | 000F FFFF FFFF FFFF FFFF FF00 0000 0000 2 | 000F 0C0C 0C0C 0C0C 0C0C 0FF0 0000 0000 3 | 000F C0C0 C0C0 C0C0 C0C0 CFCF 0000 0000 4 | 000F 0C0C 0C0C 0C0C 0C0C 0FCC F000 0000 5 | 000F C0C0 C0C0 C0C0 C0C0 CFCC CF00 0000 6 | 000F 0C0C 0C0C 0C0C 0C0C 0FCC CCF0 0000 7 | 000F C0C0 C0C0 C0C0 C0C0 CFFF FFDF 0000 8 | 000F 0C0C 0C0C 0C0C 0C0C 0CDD DDDF 0000 9 | 000F C0C0 C0C0 C0C0 C0C0 C0CC CCDF 0000 10 | 000F 0C0F 0F0F FF0F 0C0F 0F0C 0CDF 0000 11 | 000F C0CF FFC0 F0CF F0FF CFC0 CCDF 0000 12 | 000F 0C0F 0F0C FC0F 0F0F 0FFF 0CDF 0000 13 | 000F C0C0 C0C0 C0C0 C0C0 C0C0 CCDF 0000 14 | 000F 0C0C 0C0C 0C0C 0C0C 0C0C 0CDF 0000 15 | 000F C0C0 C0C0 C0C0 C0C0 C0C0 CCDF 0000 16 | 000F 0C0C 0C0C 0C0C 0C0C 0C0C 0CDF 0000 17 | 000F C0CF FFFF F0FF FFCF FFFF CCDF 0000 18 | 000F 0C0C 0C0C 0C0C 0C0C 0C0C 0CDF 0000 19 | 000F C0CF FFFF CFFF FFF0 FFF0 CCDF 0000 20 | 000F 0C0C 0C0C 0C0C 0C0C 0C0C 0CDF 0000 21 | 000F C0CF FFF0 FFFF CFFF F0C0 CCDF 0000 22 | 000F 0C0C 0C0C 0C0C 0C0C 0C0C 0CDF 0000 23 | 000F C0C0 C0C0 C0C0 C0C0 C0C0 CCDF 0000 24 | 000F 0C0C 0C0C 0C0C 0C0C 0C0C 0CDF 0000 25 | 000F C0C0 C0C0 C0C0 C0C0 C0C0 CCDF 0000 26 | 000F 0C0F FFFF FFFF FFFC 0FFC 0CDF 0000 27 | 000F C0CF 0000 0000 00F0 FCCF CCDF 0000 28 | 000F 0C0F FFFF FFFF FFFC 0FFC 0CDF DD00 29 | 000F C0C0 C0C0 C0C0 C0C0 C0C0 CCDF DDDD 30 | 000F 0C0C 0C0C 0C0C 0C0C 0C0C 0CDF DDDD 31 | 000F C0C0 C0C0 C0C0 C0C0 C0C0 CCDF DD00 32 | 000F FFFF FFFF FFFF FFFF FFFF FFFF 0000 33 | -------------------------------------------------------------------------------- /rsrc/icl4/130.hex: -------------------------------------------------------------------------------- 1 | 000F FFFF FFFF FFFF FFFF FF00 0000 0000 2 | 000F 0C0C 0C0C 0C0C 0C0C 0FF0 0000 0000 3 | 000F C0C0 C0C0 C0C0 C0C0 CFCF 0000 0000 4 | 000F 0C0C 0C0C 0C0C 0C0C 0FCC F000 0000 5 | 000F C0C0 C0C0 C0C0 C0C0 CFCC CF00 0000 6 | 000F 0C0C 0C0C 0C0C 0C0C 0FCC CCF0 0000 7 | 000F C0C0 C0C0 C0C0 C0C0 CFFF FFFF 0000 8 | 000F 0C0C 0C0C 0C0C 0C0C 0CCC CCCF 0000 9 | 000F C0C0 C0C0 C0EE EEC0 C0C0 C0CF 0000 10 | 000F 0C0C 0C0C EE88 88EE 0C0C 0CCF 0000 11 | 000F C0C0 C0C0 E888 888E C0C0 C0CF 0000 12 | 000F 0C0C 0C0E 8888 8888 EC0C 0CCF 0000 13 | 000F C0C0 C0CE 8888 8888 E0C0 C0CF 0000 14 | 000F 0C06 6666 6666 8888 EC0C 0CCF 0000 15 | 000F C0C6 CCCC CCC6 8888 E0C0 C0CF 0000 16 | 000F 0C06 CCCC CCC6 888E 0C0C 0CCF 0000 17 | 000F C0C6 CCCC CCC6 88EE C040 C0CF 0000 18 | 000F 0C06 CCCC CCC6 EE0C 044C 0CCF 0000 19 | 000F C0C6 CCCC CCC6 C0C0 4240 C0CF 0000 20 | 000F 0C06 CCCC CCC6 0C04 224C 0CCF 0000 21 | 000F C0C6 CCCC CCC6 C042 2240 C0CF 0000 22 | 000F 0C06 6666 6666 0422 224C 0CCF 0000 23 | 000F C0C0 C0C0 C0C0 4222 2240 C0CF 0000 24 | 000F 0C0C 0C0C 0C04 2222 224C 0CCF 0000 25 | 000F C0C0 C0C0 C042 2222 2240 C0CF 0000 26 | 000F 0C0C 0C0C 0444 4444 444C 0CCF 0000 27 | 000F C0C0 C0C0 C0C0 C0C0 C0C0 C0CF 0000 28 | 000F 0C0C 0C0C 0C0C 0C0C 0C0C 0CCF 0000 29 | 000F C0C0 C0C0 C0C0 C0C0 C0C0 C0CF 0000 30 | 000F 0C0C 0C0C 0C0C 0C0C 0C0C 0CCF 0000 31 | 000F C0C0 C0C0 C0C0 C0C0 C0C0 C0CF 0000 32 | 000F FFFF FFFF FFFF FFFF FFFF FFFF 0000 33 | -------------------------------------------------------------------------------- /rsrc/STR#/700.hex: -------------------------------------------------------------------------------- 1 | 001F 1161 6966 663B 6175 6469 6F2F 782D 2 | 6169 6666 0E61 753B 6175 6469 6F2F 6261 3 | 7369 630C 633B 7465 7874 2F70 6C61 696E 4 | 0C43 3B74 6578 742F 706C 6169 6E0D 6769 5 | 663B 696D 6167 652F 6769 660C 683B 7465 6 | 7874 2F70 6C61 696E 1C68 7178 3B61 7070 7 | 6C69 6361 7469 6F6E 2F6D 6163 2D62 696E 8 | 6865 7834 300D 6874 6D3B 7465 7874 2F68 9 | 746D 6C0E 6874 6D6C 3B74 6578 742F 6874 10 | 6D6C 0E6A 7065 3B69 6D61 6765 2F6A 7065 11 | 670F 6A70 6567 3B69 6D61 6765 2F6A 7065 12 | 670E 6A70 673B 696D 6167 652F 6A70 6567 13 | 136D 6F76 3B76 6964 656F 2F71 7569 636B 14 | 7469 6D65 146D 6F6F 763B 7669 6465 6F2F 15 | 7175 6963 6B74 696D 650E 6D70 653B 7669 16 | 6465 6F2F 6D70 6567 0F6D 7065 673B 7669 17 | 6465 6F2F 6D70 6567 0E6D 7067 3B76 6964 18 | 656F 2F6D 7065 6713 7064 663B 6170 706C 19 | 6963 6174 696F 6E2F 7064 660F 7069 6374 20 | 3B69 6D61 6765 2F70 6963 7419 7073 3B61 21 | 7070 6C69 6361 7469 6F6E 2F70 6F73 7473 22 | 6372 6970 7412 7174 3B76 6964 656F 2F71 23 | 7569 636B 7469 6D65 1973 6974 3B61 7070 24 | 6C69 6361 7469 6F6E 2F78 2D73 7475 6666 25 | 6974 0F73 6E64 3B61 7564 696F 2F62 6173 26 | 6963 0F74 6578 743B 7465 7874 2F70 6C61 27 | 696E 0E74 6966 3B69 6D61 6765 2F74 6966 28 | 660F 7469 6666 3B69 6D61 6765 2F74 6966 29 | 660E 7478 743B 7465 7874 2F70 6C61 696E 30 | 0F77 6176 3B61 7564 696F 2F78 2D77 6176 31 | 1378 626D 3B69 6D61 6765 2F78 2D78 6269 32 | 746D 6170 0C2A 3B74 6578 742F 706C 6169 33 | 6E0E 2A2E 2A3B 7465 7874 2F70 6C61 696E 34 | -------------------------------------------------------------------------------- /src/window.h: -------------------------------------------------------------------------------- 1 | #ifndef _WINDOW_H 2 | #define _WINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "document.h" 8 | #include "Browsy.h" 9 | #include "uri.h" 10 | 11 | typedef struct { 12 | WindowPtr window; 13 | char *location; 14 | URI *uri; // resource request/response in progress 15 | TEHandle addressBarTE; 16 | TEHandle contentTE; 17 | TEHandle focusTE; // whichever TE has focus 18 | TEHandle statusTE; // text in status bar 19 | HistoryItem *history; 20 | ControlHandle vScrollBar; 21 | //ControlHandle toolbarBackBtn; 22 | Boolean isLoading; 23 | DOMDocument *document; 24 | } PageWindow; 25 | 26 | PageWindow* NewPageWindow(); 27 | PageWindow* GetPageWindow(WindowPtr win); 28 | void InitPageWindows(); 29 | void ClosePageWindow(PageWindow *pWin); 30 | void PageWindowNavigates(PageWindow *pWin, char *location); 31 | void UpdatePageWindow(PageWindow *pWin); 32 | void PageWindowActivate(PageWindow *pWin); 33 | void PageWindowDeactivate(PageWindow *pWin); 34 | void PageWindowAdjustScrollBars(PageWindow *pWin); 35 | void PageWindowResized(PageWindow *pWin, Rect oldPort); 36 | void CloseAll(); 37 | void PageWindowIdle(PageWindow *pWin); 38 | void PageWindowMouseDown(PageWindow* pWin, Point where, int modifiers); 39 | void PageWindowFocusTE(PageWindow *pWin, TEHandle te); 40 | void PageWindowKeyDown(PageWindow *pWin, char theChar); 41 | void PageWindowSetStatus(PageWindow *pWin, char *status); 42 | void PageWindowSaveAs(PageWindow *pWin); 43 | void PageWindowOpenFile(PageWindow *pWin); 44 | void PageWindowNavigateHistory(PageWindow *pWin, short amount); 45 | void PageWindowNavigateHome(PageWindow *pWin); 46 | void PageWindowStop(PageWindow *pWin); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Cool Page 5 | 6 | 7 | Outside paragraph
8 | After Line break
9 | It is Bold, Italic, Underline 10 |

In paragraph

11 |

Second paragraph

12 |

Paragraph without closing tag 13 |

Another paragraph without closing tag 14 |

First Heading

15 |

Another paragraph

16 |

Second Heading

17 |

Meow paragraph

18 |

Unordered list

19 |
    20 |
  • List item 1
  • 21 |
  • List item 2
  • 22 |
23 |

Ordered list

24 |
    25 |
  1. List item 1
  2. 26 |
  3. List item 2
  4. 27 |
28 |

Definition list

29 |
30 |
Term 1
31 |
Definition 1
32 |
Term 2
33 |
Definition 3
34 |
35 |

Fourth heading

36 |

Link to Home Page

37 |
Fifth heading
38 |

Form

39 |
40 | Plain input: 41 | Input text:
42 | Password:
43 | Checkboxes:
44 | Meow
45 | Pizza
46 | Select ice cream flavor: 51 | Scoops:
52 | 1
53 | 2
54 | 3
55 | Todo: multi select
56 | Textarea:
57 |
58 | Submit button:
59 | Reset button: 60 |
61 |

HTML entities

62 |

&amp: "&"
63 | &nbsp: " "
64 |

More Stuff

65 |
Preformatted text
66 |
Address
67 | -------------------------------------------------------------------------------- /src/uri/about.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "stream.h" 7 | #include "utils.h" 8 | #include "uri.h" 9 | #include "uri/about.h" 10 | 11 | void *AboutProviderInit(URI *uri, char *uriStr); 12 | void AboutProviderClose(URI *uri, void *providerData); 13 | void AboutProviderRequest(URI *uri, void *providerData, HTTPMethod *method, 14 | Stream *postData); 15 | 16 | struct URIProvider *aboutURIProvider = &(URIProvider) { 17 | .init = AboutProviderInit, 18 | .request = AboutProviderRequest, 19 | .close = AboutProviderClose 20 | }; 21 | 22 | struct { 23 | char *name; 24 | short id; 25 | } pageResources[] = { 26 | {"about:Browsy", 128}, 27 | {"about:blank", 129}, 28 | {"about:stuff", 130}, 29 | }; 30 | 31 | short getPageResourceId(char *uri) 32 | { 33 | if (!uri) return 0; 34 | for (int i = 0; i < SIZE(pageResources); i++) { 35 | if (!strcmp(uri, pageResources[i].name)) { 36 | return pageResources[i].id; 37 | } 38 | } 39 | return 0; 40 | } 41 | 42 | // create and return the provider data 43 | void *AboutProviderInit(URI *uri, char *uriStr) 44 | { 45 | size_t len = strlen(uriStr) + 1; 46 | char *data = malloc(len); 47 | if (!data) return NULL; 48 | strncpy(data, uriStr, len); 49 | return data; 50 | } 51 | 52 | void AboutProviderClose(URI *uri, void *providerData) 53 | { 54 | //TODO: fix stream freeing 55 | //free(providerData); 56 | } 57 | 58 | void AboutProviderRequest(URI *uri, void *providerData, HTTPMethod *method, 59 | Stream *postData) 60 | { 61 | Handle text = NULL; 62 | short rsrcId; 63 | char *uriStr = (char *)providerData; 64 | 65 | // ignore POST data 66 | (void)postData; 67 | 68 | if (method->type != httpGET) { 69 | // only GET is supported 70 | URIClosed(uri, uriBadMethodErr); 71 | return; 72 | } 73 | 74 | rsrcId = getPageResourceId(uriStr); 75 | if (rsrcId) { 76 | text = GetResource('TEXT', rsrcId); 77 | } 78 | if (text == NULL) { 79 | URIGotStatus(uri, 404); 80 | URIMessageBegin(uri); 81 | } else { 82 | URIGotStatus(uri, 200); 83 | URIGotHeader(uri, &(HTTPHeader){httpContentType, "text/plain"}); 84 | URIMessageBegin(uri); 85 | HLock(text); 86 | URIGotData(uri, *text, InlineGetHandleSize(text)); 87 | HUnlock(text); 88 | ReleaseResource(text); 89 | } 90 | URIClosed(uri, 0); 91 | free(providerData); 92 | } 93 | 94 | -------------------------------------------------------------------------------- /rsrc/Styl/128.hex: -------------------------------------------------------------------------------- 1 | 0001 0010 526F 6F74 0000 0000 0000 0000 2 | 0000 0000 4005 7365 7269 6600 0000 0000 3 | 0000 0000 0000 0000 0000 0000 0000 0000 4 | 0000 0000 000C 0000 0000 0000 0000 6874 5 | 6D6C 0000 0000 0000 0000 0000 0000 4000 6 | 0000 0000 0000 0000 0000 0000 0000 0000 7 | 0000 0000 0000 0000 0000 0000 0000 0000 8 | 0000 0000 0000 0000 6865 6164 0000 0000 9 | 0000 0000 0000 0000 8000 0000 0000 0000 10 | 0000 0000 0000 0000 0000 0000 0000 0000 11 | 0000 0000 0000 0000 0000 0000 0000 0000 12 | 0000 7469 746C 6500 0000 0000 0000 0000 13 | 0000 8000 0000 0000 0000 0000 0000 0000 14 | 0000 0000 0000 0000 0000 0000 0000 0000 15 | 0000 0000 0000 0000 0000 0000 7374 796C 16 | 6500 0000 0000 0000 0000 0000 8000 0000 17 | 0000 0000 0000 0000 0000 0000 0000 0000 18 | 0000 0000 0000 0000 0000 0000 0000 0000 19 | 0000 0000 0000 7363 7269 7074 0000 0000 20 | 0000 0000 0000 8000 0000 0000 0000 0000 21 | 0000 0000 0000 0000 0000 0000 0000 0000 22 | 0000 0000 0000 0000 0000 0000 0000 0000 23 | 626F 6479 0000 0000 0000 0000 0000 0000 24 | 0000 0000 0000 0000 0000 0000 0000 0000 25 | 0000 0000 0000 0000 0000 0000 0000 0000 26 | 0000 0100 0000 0000 0000 6831 0000 0000 27 | 0000 0000 0000 0000 0000 6000 0000 0000 28 | 0000 0000 0000 0000 0000 0000 0000 0000 29 | 0000 0000 0000 0000 0000 0018 1010 0000 30 | 0000 0000 6832 0000 0000 0000 0000 0000 31 | 0000 0000 6000 0000 0000 0000 0000 0000 32 | 0000 0000 0000 0000 0000 0000 0000 0000 33 | 0000 0000 0012 0E0E 0000 0000 0000 6833 34 | 0000 0000 0000 0000 0000 0000 0000 6000 35 | 0000 0000 0000 0000 0000 0000 0000 0000 36 | 0000 0000 0000 0000 0000 0000 0000 000E 37 | 0C0C 0000 0000 0000 6834 0000 0000 0000 38 | 0000 0000 0000 0000 6000 0000 0000 0000 39 | 0000 0000 0000 0000 0000 0000 0000 0000 40 | 0000 0000 0000 0000 000C 0D0D 0000 0000 41 | 0000 6835 0000 0000 0000 0000 0000 0000 42 | 0000 6000 0000 0000 0000 0000 0000 0000 43 | 0000 0000 0000 0000 0000 0000 0000 0000 44 | 0000 000A 0F0F 0000 0000 0000 6836 0000 45 | 0000 0000 0000 0000 0000 0000 6000 0000 46 | 0000 0000 0000 0000 0000 0000 0000 0000 47 | 0000 0000 0000 0000 0000 0000 0009 0F0F 48 | 0000 0000 0000 6269 6700 0000 0000 0000 49 | 0000 0000 0000 0000 0000 0000 0000 0000 50 | 0000 0000 0000 0000 0000 0000 0000 0000 51 | 0000 0000 0000 000E 0000 0000 0000 0000 52 | 736D 616C 6C00 0000 0000 0000 0000 0000 53 | 0000 0000 0000 0000 0000 0000 0000 0000 54 | 0000 0000 0000 0000 0000 0000 0000 0000 55 | 000A 0000 0000 0000 0000 6100 0000 0000 56 | 0000 0000 0000 0000 0000 0800 0000 0000 57 | 0000 0000 0000 0000 0000 0000 0000 0000 58 | 0000 0000 0000 0000 0000 0000 0000 0000 59 | 0000 FF00 60 | -------------------------------------------------------------------------------- /rsrc/icl8/128.hex: -------------------------------------------------------------------------------- 1 | 0000 0000 0000 0000 0000 0000 0000 00FF 2 | 0000 0000 0000 0000 0000 0000 0000 0000 3 | 0000 0000 0000 0000 0000 0000 0000 FFF5 4 | FF00 0000 0000 0000 0000 0000 0000 0000 5 | 0000 0000 0000 0000 0000 0000 00FF F5F5 6 | F5FF 0000 0000 0000 0000 0000 0000 0000 7 | 0000 0000 0000 0000 0000 0000 FFF5 F5F5 8 | F5F5 FF00 0000 0000 0000 0000 0000 0000 9 | 0000 0000 0000 0000 0000 00FF F5F5 F5F5 10 | F5F5 F5FF 0000 0000 0000 0000 0000 0000 11 | 0000 0000 0000 0000 0000 FFF5 F5F5 F5F5 12 | F5F5 F5F5 FF00 0000 0000 0000 0000 0000 13 | 0000 0000 0000 0000 00FF F5F5 F5F5 F5F5 14 | F5F5 FFF5 F5FF 0000 0000 0000 0000 0000 15 | 0000 0000 0000 0000 FFF5 F5F5 F5F5 F5F5 16 | F5F5 F5FF F5F5 FF00 0000 0000 0000 0000 17 | 0000 0000 0000 00FF F5F5 F5F5 F5F5 F5F5 18 | F5FF F5FF F5F5 F5FF 0000 0000 0000 0000 19 | 0000 0000 0000 FFF5 F5F5 F5F5 F5F5 F5FF 20 | F5F5 FFF5 F5F5 F5F5 FF00 0000 0000 0000 21 | 0000 0000 00FF F5F5 F5F5 F5F5 F5FF F5F5 22 | FFFF F5F5 F5F5 F5F5 F5FF 0000 0000 0000 23 | 0000 0000 FFF5 F5F5 F5F5 F5F5 F5F5 FFF5 24 | F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000 0000 25 | 0000 00FF F5F5 F5F5 F5F5 F5F5 FFF5 FFF5 26 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 27 | 0000 FFF5 F5F5 F5F5 F5F5 FFF5 F5FF F5F5 28 | F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000 29 | 00FF F5F5 F5F5 F5F5 F5F5 F5FF FFF5 F5F5 30 | F5F5 FFFF FFFF FFFF F5F5 F5F5 F5FF 0000 31 | FFF5 F5F5 F5F5 F5F5 F5FF F5F5 F5F5 F5F5 32 | F5FF 0808 0808 0808 FFF5 F5F5 F5F5 FF00 33 | 00FF F5F5 F5F5 F5F5 F5F5 FFF5 F5F5 F5F5 34 | FF08 0808 0808 0808 08FF F5F5 F5F5 F5FF 35 | 0000 FFF5 F5F5 F5F5 FFF5 FFF5 F5F5 F5FF 36 | 0808 FFFF 0808 0808 0808 FFF5 F5F5 FF00 37 | 0000 00FF F5F5 FFF5 F5FF F5F5 F5F5 F5FF 38 | FFFF F5F5 FF08 0808 0808 08FF F5FF 0000 39 | 0000 0000 FFF5 F5FF FFF5 F5F5 FFFF FF08 40 | 08FF FFFF FFFF FFFF FF08 0808 FFFF FFFF 41 | 0000 0000 00FF F5F5 F5F5 F5F5 F5F5 FF08 42 | 0808 FFFF 0808 0808 0808 0808 08FF FFFF 43 | 0000 0000 0000 FFF5 F5F5 F5F5 F5F5 F5FF 44 | 0808 0808 0808 0808 0808 0808 08FF FFFF 45 | 0000 0000 0000 00FF F5F5 F5F5 F5F5 F5F5 46 | FF08 0808 0808 0808 0808 0808 08FF FFFF 47 | 0000 0000 0000 0000 FFF5 F5F5 F5F5 F5F5 48 | F5FF FF08 0808 0808 0808 0808 08FF FFFF 49 | 0000 0000 0000 0000 00FF F5F5 F5F5 F5F5 50 | F5F5 F5FF FFFF FFFF FFFF FF08 08FF FFFF 51 | 0000 0000 0000 0000 0000 FFF5 F5F5 F5F5 52 | F5F5 F5F5 F5F5 FF00 0000 00FF FFFF FFFF 53 | 0000 0000 0000 0000 0000 00FF F5F5 F5F5 54 | F5F5 F5F5 F5FF 0000 0000 0000 00FF FFFF 55 | 0000 0000 0000 0000 0000 0000 FFF5 F5F5 56 | F5F5 F5F5 FF00 0000 0000 0000 0000 0000 57 | 0000 0000 0000 0000 0000 0000 00FF F5F5 58 | F5F5 F5FF 0000 0000 0000 0000 0000 0000 59 | 0000 0000 0000 0000 0000 0000 0000 FFF5 60 | F5F5 FF00 0000 0000 0000 0000 0000 0000 61 | 0000 0000 0000 0000 0000 0000 0000 00FF 62 | F5FF 0000 0000 0000 0000 0000 0000 0000 63 | 0000 0000 0000 0000 0000 0000 0000 0000 64 | FF00 0000 0000 0000 0000 0000 0000 0000 65 | -------------------------------------------------------------------------------- /rsrc/icl8/129.hex: -------------------------------------------------------------------------------- 1 | 0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF 2 | FFFF FFFF FFFF 0000 0000 0000 0000 0000 3 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 4 | F5F5 F5F5 F5FF FF00 0000 0000 0000 0000 5 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 6 | F5F5 F5F5 F5FF 2BFF 0000 0000 0000 0000 7 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 8 | F5F5 F5F5 F5FF 2B2B FF00 0000 0000 0000 9 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 10 | F5F5 F5F5 F5FF 2B2B 2BFF 0000 0000 0000 11 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 12 | F5F5 F5F5 F5FF 2B2B 2B2B FF00 0000 0000 13 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 14 | F5F5 F5F5 F5FF FFFF FFFF FFFF 0000 0000 15 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 16 | F5F5 F5F5 F5F5 F7F7 F7F7 F7FF 0000 0000 17 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 18 | F5F5 F5F5 F5F5 F5F6 F6F6 F7FF 0000 0000 19 | 0000 00FF F5F5 F5FF F6FF F5FF FFFF F5FF 20 | F6F5 F6FF F5FF F5F5 F5F6 F7FF 0000 0000 21 | 0000 00FF F5F5 F5FF FFFF F5F5 FFF5 F5FF 22 | FFF6 FFFF F5FF F5F5 F5F6 F7FF 0000 0000 23 | 0000 00FF F5F5 F5FF F5FF F5F5 FFF5 F5FF 24 | F5FF F5FF F5FF FFFF F5F6 F7FF 0000 0000 25 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 26 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF 0000 0000 27 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 28 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF 0000 0000 29 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 30 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF 0000 0000 31 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 32 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF 0000 0000 33 | 0000 00FF F5F5 F5FF FFFF FFFF FFF5 FFFF 34 | FFFF F5FF FFFF FFFF F5F6 F7FF 0000 0000 35 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 36 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF 0000 0000 37 | 0000 00FF F5F5 F5FF FFFF FFFF F5FF FFFF 38 | FFFF FFF5 FFFF FFF5 F5F6 F7FF 0000 0000 39 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 40 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF 0000 0000 41 | 0000 00FF F5F5 F5FF FFFF FFF5 FFFF FFFF 42 | F5FF FFFF FFF5 F5F5 F5F6 F7FF 0000 0000 43 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 44 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF 0000 0000 45 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 46 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF 0000 0000 47 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 48 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF 0000 0000 49 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 50 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF 0000 0000 51 | 0000 00FF F5F5 F5FF FFFF FFFF FFFF FFFF 52 | FFFF FFF5 F6FF FFF6 F5F6 F7FF 0000 0000 53 | 0000 00FF F5F5 F5FF 0000 0000 0000 0000 54 | 0000 FFF5 FF2B 2BFF F5F6 F7FF 0000 0000 55 | 0000 00FF F5F5 F5FF FFFF FFFF FFFF FFFF 56 | FFFF FFF5 F6FF FFF6 F5F6 F7FF FAFA 0000 57 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 58 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF FAFA FAFA 59 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 60 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF FAFA FAFA 61 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 62 | F5F5 F5F5 F5F5 F5F5 F5F6 F7FF FAFA 0000 63 | 0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF 64 | FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000 65 | -------------------------------------------------------------------------------- /rsrc/icl8/130.hex: -------------------------------------------------------------------------------- 1 | 0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF 2 | FFFF FFFF FFFF 0000 0000 0000 0000 0000 3 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 4 | F5F5 F5F5 F5FF FF00 0000 0000 0000 0000 5 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 6 | F5F5 F5F5 F5FF 2BFF 0000 0000 0000 0000 7 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 8 | F5F5 F5F5 F5FF 2B2B FF00 0000 0000 0000 9 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 10 | F5F5 F5F5 F5FF 2B2B 2BFF 0000 0000 0000 11 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 12 | F5F5 F5F5 F5FF 2B2B 2B2B FF00 0000 0000 13 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 14 | F5F5 F5F5 F5FF FFFF FFFF FFFF 0000 0000 15 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 16 | F5F5 F5F5 F5F5 2B2B 2B2B 2BFF 0000 0000 17 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 A5A5 18 | A5A5 F5F5 F5F5 F5F6 F6F6 2BFF 0000 0000 19 | 0000 00FF F5F5 F5F5 F5F5 F5F5 A5A5 E3E3 20 | E3E3 A5A5 F5F5 F5F5 F5F6 2BFF 0000 0000 21 | 0000 00FF F5F5 F5F5 F5F5 F5F5 A5E3 E3E3 22 | E3E3 E3A5 F5F5 F5F5 F5F6 2BFF 0000 0000 23 | 0000 00FF F5F5 F5F5 F5F5 F5A5 E3E3 E3E3 24 | E3E3 E3E3 A5F5 F5F5 F5F6 2BFF 0000 0000 25 | 0000 00FF F5F5 F5F5 F5F5 F5A5 E3E3 E3E3 26 | E3E3 E3E3 A5F5 F5F5 F5F6 2BFF 0000 0000 27 | 0000 00FF F5F5 F5EC ECEC ECEC ECEC ECEC 28 | E3E3 E3E3 A5F5 F5F5 F5F6 2BFF 0000 0000 29 | 0000 00FF F5F5 F5EC 5454 5454 5454 54EC 30 | E3E3 E3E3 A5F5 F5F5 F5F6 2BFF 0000 0000 31 | 0000 00FF F5F5 F5EC 5454 5454 5454 54EC 32 | E3E3 E3A5 F5F5 F5F5 F5F6 2BFF 0000 0000 33 | 0000 00FF F5F5 F5EC 5454 5454 5454 54EC 34 | E3E3 A5A5 F5F5 69F5 F5F6 2BFF 0000 0000 35 | 0000 00FF F5F5 F5EC 5454 5454 5454 54EC 36 | A5A5 F5F5 F569 69F5 F5F6 2BFF 0000 0000 37 | 0000 00FF F5F5 F5EC 5454 5454 5454 54EC 38 | F5F5 F5F5 6916 69F5 F5F6 2BFF 0000 0000 39 | 0000 00FF F5F5 F5EC 5454 5454 5454 54EC 40 | F5F5 F569 1616 69F5 F5F6 2BFF 0000 0000 41 | 0000 00FF F5F5 F5EC 5454 5454 5454 54EC 42 | F5F5 6916 1616 69F5 F5F6 2BFF 0000 0000 43 | 0000 00FF F5F5 F5EC ECEC ECEC ECEC ECEC 44 | F569 1616 1616 69F5 F5F6 2BFF 0000 0000 45 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 46 | 6916 1616 1616 69F5 F5F6 2BFF 0000 0000 47 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F569 48 | 1616 1616 1616 69F5 F5F6 2BFF 0000 0000 49 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 6916 50 | 1616 1616 1616 69F5 F5F6 2BFF 0000 0000 51 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F569 6969 52 | 6969 6969 6969 69F5 F5F6 2BFF 0000 0000 53 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 54 | F5F5 F5F5 F5F5 F5F5 F5F6 2BFF 0000 0000 55 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 56 | F5F5 F5F5 F5F5 F5F5 F5F6 2BFF 0000 0000 57 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 58 | F5F5 F5F5 F5F5 F5F5 F5F6 2BFF 0000 0000 59 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 60 | F5F5 F5F5 F5F5 F5F5 F5F6 2BFF 0000 0000 61 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 62 | F5F5 F5F5 F5F5 F5F5 F5F6 2BFF 0000 0000 63 | 0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF 64 | FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000 65 | -------------------------------------------------------------------------------- /rsrc/icl8/140.hex: -------------------------------------------------------------------------------- 1 | 0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF 2 | FFFF FFFF FFFF 0000 0000 0000 0000 0000 3 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 4 | F5F5 F5F5 F5FF FF00 0000 0000 0000 0000 5 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 6 | F5F5 F5F5 F5FF 2BFF 0000 0000 0000 0000 7 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 8 | F5F5 F5F5 F5FF 2B2B FF00 0000 0000 0000 9 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 10 | F5F5 F5F5 F5FF 2B2B 2BFF 0000 0000 0000 11 | 0000 00FF F5F5 F5FF F5FF F5FF FFF5 F5F5 12 | F5F5 F5F5 F5FF 2B2B 2B2B FF00 0000 0000 13 | 0000 00FF F5F5 F5FF FFFF F5F5 FFF5 F5F5 14 | F5F5 F5F5 F5FF FFFF FFFF FFFF 0000 0000 15 | 0000 00FF F5F5 F5FF F5FF F5FF FFFF F5F5 16 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 17 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 18 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 19 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 20 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 21 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 22 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 23 | 0000 00FF F5F5 F5FF FFFF FFFF FFF5 FFFF 24 | FFFF F5FF FFFF FFFF F5F5 F5FF 0000 0000 25 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 26 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 27 | 0000 00FF F5F5 F5FF FFFF FFFF F5FF FFFF 28 | FFFF FFF5 FFFF FFF5 F5F5 F5FF 0000 0000 29 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 30 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 31 | 0000 00FF F5F5 F5FF FFFF FFF5 FFFF FFFF 32 | F5FF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000 33 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 34 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 35 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 36 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 37 | 0000 00FF F5F5 F5F5 F5FF F5FF FFFF FFFF 38 | FFF5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 39 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 40 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 41 | 0000 00FF F5F5 F5F5 F5FF F5FF FFFF FFF5 42 | FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000 43 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 44 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 45 | 0000 00FF F5F5 F5F5 F5FF F5FF FFFF F5FF 46 | FFFF FFF5 F5F5 F5F5 F5F5 F5FF 0000 0000 47 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 48 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 49 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 50 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 51 | 0000 00FF F5F5 F5FF FFFF FFFF FFFF FFFF 52 | FFFF FFF5 F5FF FFF5 F5F5 F5FF 0000 0000 53 | 0000 00FF F5F5 F5FF 0000 0000 0000 0000 54 | 0000 FFF5 FF00 00FF F5F5 F5FF 0000 0000 55 | 0000 00FF F5F5 F5FF FFFF FFFF FFFF FFFF 56 | FFFF FFF5 F5FF FFF5 F5F5 F5FF 0000 0000 57 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 58 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 59 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 60 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 61 | 0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 62 | F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000 63 | 0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF 64 | FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000 65 | -------------------------------------------------------------------------------- /src/tokenizer.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKENIZER_H 2 | #define _TOKENIZER_H 3 | 4 | #ifndef EOF 5 | #define EOF -1 6 | #endif 7 | 8 | typedef enum { 9 | DATA_STATE, 10 | CHARACTER_REFERENCE_IN_DATA_STATE, 11 | RCDATA_STATE, 12 | CHARACTER_REFERENCE_IN_RCDATA_STATE, 13 | RAWTEXT_STATE, 14 | SCRIPT_DATA_STATE, 15 | PLAINTEXT_STATE, 16 | TAG_OPEN_STATE, 17 | END_TAG_OPEN_STATE, 18 | TAG_NAME_STATE, 19 | RCDATA_LESS_THAN_SIGN_STATE, 20 | RCDATA_END_TAG_OPEN_STATE, 21 | RCDATA_END_TAG_NAME_STATE, 22 | RAWTEXT_LESS_THAN_SIGN_STATE, 23 | RAWTEXT_END_TAG_OPEN_STATE, 24 | RAWTEXT_END_TAG_NAME_STATE, 25 | SCRIPT_DATA_LESS_THAN_SIGN_STATE, 26 | SCRIPT_DATA_END_TAG_OPEN_STATE, 27 | SCRIPT_DATA_END_TAG_NAME_STATE, 28 | SCRIPT_DATA_ESCAPE_START_STATE, 29 | SCRIPT_DATA_ESCAPE_START_DASH_STATE, 30 | SCRIPT_DATA_ESCAPED_STATE, 31 | SCRIPT_DATA_ESCAPED_DASH_STATE, 32 | SCRIPT_DATA_ESCAPED_DASH_DASH_STATE, 33 | SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN_STATE, 34 | SCRIPT_DATA_ESCAPED_END_TAG_OPEN_STATE, 35 | SCRIPT_DATA_ESCAPED_END_TAG_NAME_STATE, 36 | SCRIPT_DATA_DOUBLE_ESCAPE_START_STATE, 37 | SCRIPT_DATA_DOUBLE_ESCAPED_STATE, 38 | SCRIPT_DATA_DOUBLE_ESCAPED_DASH_STATE, 39 | SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH_STATE, 40 | SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN_STATE, 41 | SCRIPT_DATA_DOUBLE_ESCAPE_END_STATE, 42 | BEFORE_ATTRIBUTE_NAME_STATE, 43 | ATTRIBUTE_NAME_STATE, 44 | AFTER_ATTRIBUTE_NAME_STATE, 45 | BEFORE_ATTRIBUTE_VALUE_STATE, 46 | ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE, 47 | ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE, 48 | ATTRIBUTE_VALUE_UNQUOTED_STATE, 49 | CHARACTER_REFERENCE_IN_ATTRIBUTE_VALUE_STATE, 50 | AFTER_ATTRIBUTE_VALUE_QUOTED_STATE, 51 | SELF_CLOSING_START_TAG_STATE, 52 | BOGUS_COMMENT_STATE, 53 | MARKUP_DECLARATION_OPEN_STATE, 54 | COMMENT_START_STATE, 55 | COMMENT_START_DASH_STATE, 56 | COMMENT_STATE, 57 | COMMENT_END_DASH_STATE, 58 | COMMENT_END_STATE, 59 | COMMENT_END_BANG_STATE, 60 | DOCTYPE_STATE, 61 | BEFORE_DOCTYPE_NAME_STATE, 62 | DOCTYPE_NAME_STATE, 63 | AFTER_DOCTYPE_NAME_STATE, 64 | AFTER_DOCTYPE_PUBLIC_KEYWORD_STATE, 65 | BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE, 66 | DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED_STATE, 67 | DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED_STATE, 68 | AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE, 69 | BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS_STATE, 70 | AFTER_DOCTYPE_SYSTEM_KEYWORD_STATE, 71 | BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE, 72 | DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE, 73 | DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE, 74 | AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE, 75 | BOGUS_DOCTYPE_STATE, 76 | CDATA_SECTION_STATE 77 | } TokenizerState; 78 | 79 | typedef enum { 80 | CHARACTER_TOKEN, 81 | CHARACTER_TOKENS, 82 | TAG_TOKEN, 83 | EOF_TOKEN 84 | } TokenTypes; 85 | 86 | typedef struct { 87 | TokenizerState state; 88 | char *input; 89 | short position; 90 | } Tokenizer; 91 | 92 | typedef struct { 93 | char tagName[16]; 94 | short tagNameLength; 95 | } TagToken; 96 | 97 | Tokenizer *NewTokenizer(); 98 | void DisposeTokenizer(Tokenizer *tokenizer); 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /src/uri.h: -------------------------------------------------------------------------------- 1 | #ifndef _URI_H 2 | #define _URI_H 3 | 4 | /* 5 | typedef enum { 6 | stateResolving, 7 | stateConnecting, 8 | stateLoading, 9 | stateComplete 10 | } URIRequestState; 11 | 12 | typedef struct { 13 | short status; 14 | long length; 15 | long offset; 16 | char *contentType; 17 | HTTPHeader *headers; 18 | Handle contentHandle; 19 | } URIResponse; 20 | 21 | typedef struct URIRequest { 22 | char method; 23 | char *uri; 24 | HTTPHeader *headers; // list of headers 25 | Handle data; // POST data 26 | void (*callback)(struct URIRequest*); // called on data recieve and done 27 | void *refCon; // User/app reference data 28 | URIRequestState state; 29 | URIResponse *response; 30 | } URIRequest; 31 | */ 32 | 33 | /* 34 | URIResponse *NewResponse(); 35 | void DisposeResponse(URIResponse *resp); 36 | void DisposeHeaders(HTTPHeader *header); 37 | void DisposeRequest(URIRequest *req); 38 | void Request(char *uri, void (*callback)(URIRequest *req), void *refCon); 39 | */ 40 | 41 | #include 42 | 43 | struct Stream; 44 | 45 | typedef struct URI URI; 46 | typedef struct URIConsumer URIConsumer; 47 | typedef struct URIProvider URIProvider; 48 | 49 | enum URIError { 50 | uriBadMethodErr = -1, 51 | }; 52 | 53 | typedef struct HTTPHeader { 54 | enum { 55 | httpContentType, 56 | httpContentLength, 57 | } name; 58 | char *value; 59 | } HTTPHeader; 60 | 61 | typedef struct HTTPMethod { 62 | enum { 63 | httpGET, 64 | httpPOST, 65 | httpOtherMethod 66 | } type; 67 | char *value; 68 | } HTTPMethod; 69 | 70 | // callbacks for consuming a stream 71 | struct URIConsumer { 72 | void (*on_status)(void *consumerData, short httpStatus); 73 | void (*on_header)(void *consumerData, struct HTTPHeader *header); 74 | void (*on_headers_complete)(void *consumerData); 75 | void (*on_message_begin)(void *consumerData); 76 | void (*on_data)(void *consumerData, char *data, short len); 77 | void (*on_close)(void *consumerData, short err); 78 | }; 79 | 80 | // functions for writing and receiving from a stream 81 | struct URIProvider { 82 | void *(*init)(URI *uri, char *uriStr); 83 | void (*request)(URI *uri, void *providerData, struct HTTPMethod *method, 84 | struct Stream *postData); 85 | void (*close)(URI *uri, void *providerData); 86 | /* 87 | void (*write)(Stream *s, void *pData, char *data, unsigned short len); 88 | void (*poll)(Stream *s, void *providerData); 89 | */ 90 | }; 91 | 92 | URIProvider *URIGetProvider(char *uri); 93 | 94 | URI *NewURI(char *uri); 95 | void URIConsume(URI *uri, URIConsumer *consumer, void *consumerData); 96 | void URIClose(URI *uri); 97 | void URIRequest(URI *uri, char *method, struct Stream *postData); 98 | void URIGet(URI *uri); 99 | void URIPost(URI *uri, struct Stream *postData); 100 | 101 | // call by provider 102 | int URIProvide(URI *uri, URIProvider *provider, char *uriStr); 103 | void URIGotStatus(URI *uri, short status); 104 | void URIGotHeader(URI *uri, struct HTTPHeader *header); 105 | void URIHeadersComplete(URI *uri); 106 | void URIMessageBegin(URI *uri); 107 | void URIGotData(URI *uri, char *data, short len); 108 | void URIClosed(URI *uri, short error); 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BIN = Browsy 2 | TOOLCHAIN = /opt/Retro68-build/toolchain 3 | ARCH = m68k-unknown-elf 4 | CC = $(TOOLCHAIN)/bin/$(ARCH)-gcc 5 | LD = $(TOOLCHAIN)/bin/$(ARCH)-g++ 6 | AS = $(TOOLCHAIN)/bin/$(ARCH)-as 7 | AR = $(TOOLCHAIN)/bin/$(ARCH)-ar 8 | MAKE_APPL = $(TOOLCHAIN)/bin/MakeAPPL 9 | FROM_HEX= xxd -r -ps 10 | CSRC = $(wildcard src/*.c src/**/*.c) 11 | INC = $(wildcard src/*.h src/**/*.h) 12 | OBJ = $(CSRC:.c=.o) 13 | CDEP = $(CSRC:.c=.d) 14 | SHAREDIR= Shared 15 | DEP_DIR = dep 16 | LIB_DIR = lib 17 | DEPS = http_parser cstreams 18 | LIBS = $(DEPS:%=$(LIB_DIR)/lib%.a) 19 | LIBS_L = $(DEPS:%=-l%) 20 | CFLAGS = -MMD 21 | CFLAGS += -O3 -DNDEBUG -std=c11 22 | CFLAGS += -Wno-multichar -Wno-attributes -Werror 23 | CFLAGS += -Isrc -Idep/http-parser -Idep/c-streams/src 24 | LDFLAGS = -L$(LIB_DIR) -lretrocrt $(LIBS_L) -Wl,-elf2flt -Wl,-q -Wl,-Map=linkmap.txt -Wl,-undefined=consolewrite -Wl,-gc-sections 25 | SFLAGS = 26 | 27 | RSRC_HEX=$(wildcard rsrc/*/*.hex) 28 | RSRC_TXT=$(wildcard rsrc/*/*.txt) 29 | RSRC_DAT=$(RSRC_HEX:.hex=.dat) $(RSRC_TXT:.txt=.dat) 30 | 31 | MINI_VMAC_DIR=~/Mac/Emulation/Mini\ vMac 32 | MINI_VMAC=$(MINI_VMAC_DIR)/Mini\ vMac 33 | MINI_VMAC_LAUNCHER_DISK=$(MINI_VMAC_DIR)/launcher-sys.dsk 34 | 35 | ifndef V 36 | QUIET_CC = @echo ' CC ' $<; 37 | QUIET_AS = @echo ' AS ' $<; 38 | QUIET_LINK = @echo ' LINK ' $@; 39 | QUIET_APPL = @echo ' APPL ' $*; 40 | QUIET_RSRC = @echo ' RSRC ' $@; 41 | QUIET_RUN = @echo ' RUN ' $<; 42 | endif 43 | 44 | # Main 45 | 46 | all: deps $(BIN).bin 47 | 48 | -include $(CDEP) 49 | 50 | $(BIN).68k: $(OBJ) $(LIBS) 51 | $(QUIET_LINK)$(LD) -o $@ $^ $(LDFLAGS) 52 | 53 | %.dsk %.bin %.APPL: %.68k rsrc-args 54 | $(QUIET_APPL)$(MAKE_APPL) -c $< -o $* -C WWW6 $(shell cat rsrc-args) 55 | 56 | %.o: %.c 57 | $(QUIET_CC)$(CC) $(CFLAGS) -c -o $@ $< 58 | 59 | %.o: %.s 60 | $(QUIET_AS)$(AS) $(SFLAGS) -o $@ $< 61 | 62 | # Resources 63 | 64 | rsrc: $(RSRC_DAT) rsrc-args 65 | 66 | rsrc/%.dat: rsrc/%.hex 67 | $(QUIET_RSRC)$(FROM_HEX) $< > $@ 68 | 69 | rsrc/TEXT/%.dat: rsrc/TEXT/%.txt 70 | $(QUIET_RSRC)tr '\n' '\r' < $< > $@ 71 | 72 | rsrc-args: $(RSRC_DAT) 73 | @cd rsrc && for code in $$(ls); do \ 74 | echo -n "-t $$code "; \ 75 | cd "$$code" && for file in *.dat; do \ 76 | echo -n "-r $${file%.dat} rsrc/$$code/$$file "; \ 77 | done; \ 78 | cd ..; \ 79 | done > ../$@ 80 | 81 | # Dependencies 82 | 83 | deps: $(LIBS) $(LIB_DIR) 84 | 85 | $(LIB_DIR)/libhttp_parser.a: $(DEP_DIR)/http-parser/libhttp_parser.a $(LIB_DIR) 86 | cp $< $@ 87 | 88 | $(LIB_DIR)/libcstreams.a: $(DEP_DIR)/c-streams/libcstreams.a $(LIB_DIR) 89 | cp $< $@ 90 | 91 | $(DEP_DIR)/http-parser/libhttp_parser.a: $(DEP_DIR)/http-parser 92 | cd $< && make package CC=$(CC) AR=$(AR) 93 | 94 | $(DEP_DIR)/c-streams/libcstreams.a: $(DEP_DIR)/c-streams 95 | cd $< && make libcstreams.a 96 | 97 | $(DEP_DIR)/http-parser: | $(DEP_DIR) 98 | git clone https://github.com/joyent/http-parser $@ 99 | 100 | $(DEP_DIR)/c-streams: | $(DEP_DIR) 101 | git clone https://github.com/clehner/c-streams $@ 102 | 103 | $(DEP_DIR) $(LIB_DIR): 104 | mkdir -p $@ 105 | 106 | # Running 107 | 108 | run: $(BIN).dsk 109 | $(QUIET_RUN)$(MINI_VMAC) $(MINI_VMAC_LAUNCHER_DISK) $(DISK) $(BIN).dsk 110 | 111 | share: $(SHAREDIR)/$(BIN) 112 | 113 | $(SHAREDIR)/$(BIN): $(BIN).APPL 114 | cp $(BIN).APPL $(SHAREDIR)/$(BIN) 115 | @cp .rsrc/$(BIN).APPL $(SHAREDIR)/.rsrc/$(BIN) 116 | @cp .finf/$(BIN).APPL $(SHAREDIR)/.finf/$(BIN) 117 | 118 | run-basiliskii: share 119 | ps aux | grep -v grep | grep BasiliskII -s || BasiliskII & 120 | 121 | # Misc 122 | 123 | wc: 124 | @wc -l $(CSRC) $(INC) | sort -n 125 | 126 | clean: 127 | rm -f $(BIN) $(BIN).dsk $(BIN).bin $(BIN).68k $(BIN).68k.gdb \ 128 | $(OBJ) $(CDEP) rsrc/*/*.dat rsrc-args linkmap.txt $(LIBS) 129 | 130 | .PHONY: clean wc run 131 | -------------------------------------------------------------------------------- /src/uri/file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "stream.h" 6 | #include "filestream.h" 7 | #include "utils.h" 8 | #include "uri.h" 9 | #include "uri/file.h" 10 | 11 | struct FileURIData { 12 | URI *uri; 13 | char *filePath; 14 | Stream *fileStream; 15 | short err; 16 | bool closed; 17 | }; 18 | 19 | void *FileProviderInit(URI *uri, char *uriStr); 20 | void FileProviderClose(URI *uri, void *providerData); 21 | void FileProviderRequest(URI *uri, void *providerData, HTTPMethod *method, 22 | Stream *postData); 23 | 24 | struct URIProvider *fileURIProvider = &(URIProvider) { 25 | .init = FileProviderInit, 26 | .request = FileProviderRequest, 27 | .close = FileProviderClose 28 | }; 29 | 30 | void FileConsumeOpen(void *consumerData); 31 | void FileConsumeData(void *consumerData, char *data, short len); 32 | void FileConsumeError(void *consumerData, short err); 33 | void FileConsumeClose(void *consumerData); 34 | 35 | StreamConsumer consumer = { 36 | .on_open = FileConsumeOpen, 37 | .on_data = FileConsumeData, 38 | .on_error = FileConsumeError, 39 | .on_close = FileConsumeClose, 40 | .on_end = FileConsumeClose, 41 | }; 42 | 43 | // create and return the provider data 44 | void *FileProviderInit(URI *uri, char *uriStr) 45 | { 46 | char *pathStart, *path; 47 | short len; 48 | struct FileURIData *data; 49 | Stream *fileStream = NewStream(); 50 | if (!fileStream) return NULL; 51 | 52 | data = malloc(sizeof(struct FileURIData)); 53 | if (!data) { 54 | free(fileStream); 55 | return NULL; 56 | } 57 | 58 | data->uri = uri; 59 | data->fileStream = fileStream; 60 | data->closed = false; 61 | data->err = 0; 62 | StreamConsume(fileStream, &consumer, data); 63 | 64 | // skip "file:" 65 | uriStr += 5; 66 | data->filePath = url_decode(uriStr); 67 | // skip initial slashes 68 | for (pathStart = data->filePath; pathStart[0] == '/'; pathStart++); 69 | // replace / with : 70 | len = 0; 71 | for (path = pathStart; *path; path++) { 72 | len++; 73 | switch (*path) { 74 | case '/': *path = ':'; break; 75 | case ':': *path = '/'; 76 | } 77 | } 78 | 79 | // make into pascal string 80 | *--pathStart = len; 81 | 82 | // set up the file stream 83 | ProvideFileStream(fileStream, pathStart, 0); 84 | 85 | return data; 86 | } 87 | 88 | void FileProviderClose(URI *uri, void *providerData) 89 | { 90 | struct FileURIData *data = (struct FileURIData *)providerData; 91 | free(data->filePath); 92 | free(data); 93 | } 94 | 95 | void FileProviderRequest(URI *uri, void *providerData, HTTPMethod *method, 96 | Stream *postData) 97 | { 98 | struct FileURIData *data = (struct FileURIData *)providerData; 99 | 100 | // ignore POST data 101 | (void)postData; 102 | 103 | if (method->type != httpGET) { 104 | // only GET is supported 105 | URIClosed(uri, uriBadMethodErr); 106 | return; 107 | } 108 | 109 | StreamOpen(data->fileStream); 110 | } 111 | 112 | void FileConsumeOpen(void *consumerData) 113 | { 114 | struct FileURIData *data = (struct FileURIData *)consumerData; 115 | URIGotStatus(data->uri, 200); 116 | URIMessageBegin(data->uri); 117 | } 118 | 119 | void FileConsumeData(void *consumerData, char *data, short len) 120 | { 121 | struct FileURIData *fData = (struct FileURIData *)consumerData; 122 | URIGotData(fData->uri, data, len); 123 | } 124 | 125 | void FileConsumeError(void *consumerData, short err) 126 | { 127 | struct FileURIData *data = (struct FileURIData *)consumerData; 128 | short status = 0; 129 | alertf("file stream error: %ld", err); 130 | data->err = err; 131 | if (err == fnfErr || err == nsvErr) { 132 | status = 404; 133 | } 134 | if (status) { 135 | URIGotStatus(data->uri, status); 136 | } 137 | } 138 | 139 | void FileConsumeClose(void *consumerData) 140 | { 141 | struct FileURIData *data = (struct FileURIData *)consumerData; 142 | if (data->closed) return; 143 | data->closed = true; 144 | URIClosed(data->uri, data->err); 145 | } 146 | 147 | -------------------------------------------------------------------------------- /rsrc/MIME/256.hex: -------------------------------------------------------------------------------- 1 | 0001 0010 6170 706C 6963 6174 696F 6E2F 2 | 6D61 632D 6269 6E68 6578 3430 0000 0000 3 | 0000 0000 1053 7475 6666 4974 2045 7870 4 | 616E 6465 7200 0000 0000 0000 0000 0000 5 | 0000 0000 0000 0000 0000 0000 0000 0000 6 | 0000 0000 0000 0000 0000 0000 0000 0000 7 | 0000 0000 5445 5854 5349 5478 5349 5478 8 | 0000 00B0 6170 706C 6963 6174 696F 6E2F 9 | 7064 6600 0000 0000 0000 0000 0000 0000 10 | 0000 0000 0F41 6372 6F62 6174 AA20 5265 11 | 6164 6572 0000 0000 0000 0000 0000 0000 12 | 0000 0000 0000 0000 0000 0000 0000 0000 13 | 0000 0000 0000 0000 0000 0000 0000 0000 14 | 0000 0000 5044 4620 4341 524F 4341 524F 15 | 0000 0050 6170 706C 6963 6174 696F 6E2F 16 | 706F 7374 7363 7269 7074 0000 0000 0000 17 | 0000 0000 0F4D 6163 2047 686F 7374 7363 18 | 7269 7074 0000 0000 0000 0000 0000 0000 19 | 0000 0000 0000 0000 0000 0000 0000 0000 20 | 0000 0000 0000 0000 0000 0000 0000 0000 21 | 0000 0000 5445 5854 7474 7874 5E46 5346 22 | 0000 0021 6170 706C 6963 6174 696F 6E2F 23 | 782D 706F 7765 7270 6F69 6E74 0000 0000 24 | 0000 0000 0D4D 5320 506F 7765 7250 6F69 25 | 6E74 0000 0000 0000 0000 0000 0000 0000 26 | 0000 0000 0000 0000 0000 0000 0000 0000 27 | 0000 0000 0000 0000 0000 0000 0000 0000 28 | 0000 0000 534C 4433 5050 5456 5050 5456 29 | 0000 0000 6170 706C 6963 6174 696F 6E2F 30 | 782D 7374 7566 6669 7400 0000 0000 0000 31 | 0000 0000 1053 7475 6666 4974 2045 7870 32 | 616E 6465 7200 0000 0000 0000 0000 0000 33 | 0000 0000 0000 0000 0000 0000 0000 0000 34 | 0000 0000 0000 0000 0000 0000 0000 0000 35 | 0000 0000 5349 5444 5349 5478 5349 5478 36 | 0000 0030 6175 6469 6F2F 6261 7369 6300 37 | 0000 0000 0000 0000 0000 0000 0000 0000 38 | 0000 0000 0D53 6F75 6E64 204D 6163 6869 39 | 6E65 0000 0000 0000 0000 0000 0000 0000 40 | 0000 0000 0000 0000 0000 0000 0000 0000 41 | 0000 0000 0000 0000 0000 0000 0000 0000 42 | 0000 0000 2A2A 2A2A 534E 444D 534E 444D 43 | 0000 0012 6175 6469 6F2F 782D 6169 6666 44 | 0000 0000 0000 0000 0000 0000 0000 0000 45 | 0000 0000 0D53 6F75 6E64 204D 6163 6869 46 | 6E65 0000 0000 0000 0000 0000 0000 0000 47 | 0000 0000 0000 0000 0000 0000 0000 0000 48 | 0000 0000 0000 0000 0000 0000 0000 0000 49 | 0000 0000 2A2A 2A2A 534E 444D 534E 444D 50 | 0000 0012 6175 6469 6F2F 782D 7761 7600 51 | 0000 0000 0000 0000 0000 0000 0000 0000 52 | 0000 0000 043F 3F3F 3F00 0000 0000 0000 53 | 0000 0000 0000 0000 0000 0000 0000 0000 54 | 0000 0000 0000 0000 0000 0000 0000 0000 55 | 0000 0000 0000 0000 0000 0000 0000 0000 56 | 0000 0000 3F3F 3F3F 3F3F 3F3F 3F3F 3F3F 57 | 0000 0002 696D 6167 652F 6769 6600 0000 58 | 0000 0000 0000 0000 0000 0000 0000 0000 59 | 0000 0000 084A 5045 4756 6965 7700 0000 60 | 0000 0000 0000 0000 0000 0000 0000 0000 61 | 0000 0000 0000 0000 0000 0000 0000 0000 62 | 0000 0000 0000 0000 0000 0000 0000 0000 63 | 0000 0000 4749 4666 4A56 5752 4A56 5752 64 | 0000 0002 696D 6167 652F 6A70 6567 0000 65 | 0000 0000 0000 0000 0000 0000 0000 0000 66 | 0000 0000 084A 5045 4756 6965 7700 0000 67 | 0000 0000 0000 0000 0000 0000 0000 0000 68 | 0000 0000 0000 0000 0000 0000 0000 0000 69 | 0000 0000 0000 0000 0000 0000 0000 0000 70 | 0000 0000 4A50 4547 4A56 5752 4A56 5752 71 | 0000 0002 696D 6167 652F 7069 6374 0000 72 | 0000 0000 0000 0000 0000 0000 0000 0000 73 | 0000 0000 084A 5045 4756 6965 7700 0000 74 | 0000 0000 0000 0000 0000 0000 0000 0000 75 | 0000 0000 0000 0000 0000 0000 0000 0000 76 | 0000 0000 0000 0000 0000 0000 0000 0000 77 | 0000 0000 5049 4354 4A56 5752 4A56 5752 78 | 0000 0012 696D 6167 652F 782D 7862 6974 79 | 6D61 7000 0000 0000 0000 0000 0000 0000 80 | 0000 0000 1247 7261 7068 6963 7320 436F 81 | 6E76 6572 7465 7200 0000 0000 0000 0000 82 | 0000 0000 0000 0000 0000 0000 0000 0000 83 | 0000 0000 0000 0000 0000 0000 0000 0000 84 | 0000 0000 5842 4D20 474B 4F4E 474B 4F4E 85 | 0000 0012 7669 6465 6F2F 6D70 6567 0000 86 | 0000 0000 0000 0000 0000 0000 0000 0000 87 | 0000 0000 0753 7061 726B 6C65 0000 0000 88 | 0000 0000 0000 0000 0000 0000 0000 0000 89 | 0000 0000 0000 0000 0000 0000 0000 0000 90 | 0000 0000 0000 0000 0000 0000 0000 0000 91 | 0000 0000 4D50 4547 6D4D 5047 6D4D 5047 92 | 0000 0012 7669 6465 6F2F 7175 6963 6B74 93 | 696D 6500 0000 0000 0000 0000 0000 0000 94 | 0000 0000 0D53 696D 706C 6520 506C 6179 95 | 6572 0000 0000 0000 0000 0000 0000 0000 96 | 0000 0000 0000 0000 0000 0000 0000 0000 97 | 0000 0000 0000 0000 0000 0000 0000 0000 98 | 0000 0000 4D6F 6F56 5456 4F44 5456 4F44 99 | 0000 0012 7465 7874 2F70 6C61 696E 0000 100 | 0000 0000 0000 0000 0000 0000 0000 0000 101 | 0000 0000 0954 6561 6368 5465 7874 0000 102 | 0000 0000 0000 0000 0000 0000 0000 0000 103 | 0000 0000 0000 0000 0000 0000 0000 0000 104 | 0000 0000 0000 0000 0000 0000 0000 0000 105 | 0000 0000 5445 5854 7474 7874 4D57 4542 106 | 0000 8080 7465 7874 2F68 746D 6C00 0000 107 | 0000 0000 0000 0000 0000 0000 0000 0000 108 | 0000 0000 0642 4245 6469 7400 0000 0000 109 | 0000 0000 0000 0000 0000 0000 0000 0000 110 | 0000 0000 0000 0000 0000 0000 0000 0000 111 | 0000 0000 0000 0000 0000 0000 0000 0000 112 | 0000 0000 5445 5854 7474 7874 522A 6368 113 | 0000 8080 114 | -------------------------------------------------------------------------------- /src/menus.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "Browsy.h" 11 | #include "window.h" 12 | #include "menus.h" 13 | 14 | const short defaultMenubar = 128; 15 | const short aboutDialog = 128; 16 | 17 | enum {appleMenu=128, fileMenu, editMenu, navigateMenu, historyMenu}; 18 | 19 | enum { 20 | fileNewItem=1, fileOpenItem, fileOpenURLItem, 21 | fileCloseItem=5, fileSaveAsItem, 22 | filePageSetupItem=8, filePrintItem, 23 | fileQuitItem=11, 24 | 25 | editUndoItem=1, 26 | editCutItem=3, editCopyItem, editPasteItem, editClearItem, 27 | editSelectAllItem=8, 28 | 29 | navigateBackItem=1, navigateForwardItem, navigateHomeItem, 30 | navigateStopItem=5, navigateReloadItem 31 | }; 32 | 33 | static void ShowAbout(); 34 | 35 | QDGlobals qd; 36 | 37 | void SetupMenus() { 38 | MenuHandle menu; 39 | Handle menubar = GetNewMBar(defaultMenubar); 40 | SetMenuBar(menubar); 41 | menu = GetMenuHandle(appleMenu); 42 | AppendResMenu(menu, 'DRVR'); 43 | DrawMenuBar(); 44 | } 45 | 46 | void HandleMenu(long menuAction) { 47 | 48 | short menu = HiWord(menuAction); 49 | short item = LoWord(menuAction); 50 | MenuHandle mh = GetMenuHandle(menu); 51 | WindowPtr topWin = FrontWindow(); 52 | PageWindow* pWin = GetPageWindow(topWin); 53 | WindowPeek peek; 54 | Str255 name; 55 | GrafPtr savePort = 0; 56 | 57 | if (menuAction <= 0) { 58 | return; 59 | } 60 | 61 | switch(menu) { 62 | case appleMenu: 63 | if (item == 1) { 64 | ShowAbout(); 65 | } else { 66 | GetPort(&savePort); 67 | GetMenuItemText(mh, item, name); 68 | OpenDeskAcc(name); 69 | SetPort(savePort); 70 | } 71 | break; 72 | case fileMenu: 73 | switch(item) { 74 | case fileNewItem: 75 | pWin = NewPageWindow(); 76 | break; 77 | case fileQuitItem: 78 | // todo: wait for mactcp and name resolver 79 | Terminate(); 80 | break; 81 | case fileOpenItem: 82 | PageWindowOpenFile(pWin); 83 | break; 84 | case fileOpenURLItem: 85 | if (!pWin) { 86 | pWin = NewPageWindow(); 87 | } 88 | PageWindowFocusTE(pWin, pWin->addressBarTE); 89 | TESetSelect(0, (*pWin->addressBarTE)->teLength, 90 | pWin->addressBarTE); 91 | break; 92 | case fileCloseItem: 93 | peek = (WindowPeek)topWin; 94 | if (peek->windowKind < 0) { 95 | CloseDeskAcc(peek->windowKind); 96 | } else if (peek->goAwayFlag) { 97 | if (pWin) { 98 | ClosePageWindow(pWin); 99 | } 100 | } 101 | break; 102 | case fileSaveAsItem: 103 | PageWindowSaveAs(pWin); 104 | break; 105 | case filePageSetupItem: 106 | SysBeep(5); 107 | break; 108 | case filePrintItem: 109 | SysBeep(5); 110 | break; 111 | } 112 | break; 113 | case editMenu: { 114 | TEHandle te; 115 | Boolean inPage; 116 | 117 | // give to desk accessories first 118 | if (SystemEdit(item-1)) { 119 | break; 120 | } 121 | if (!pWin) { 122 | break; 123 | } 124 | te = pWin->focusTE; 125 | inPage = te == pWin->contentTE; 126 | switch (item) { 127 | case editUndoItem: 128 | // todo 129 | break; 130 | case editCutItem: 131 | if (te && !inPage) { 132 | TECut(te); 133 | if (!inPage) { 134 | //ZeroScrap(); 135 | //TEToScrap(); 136 | } 137 | } else { 138 | SysBeep(5); 139 | } 140 | break; 141 | case editCopyItem: 142 | if (te) { 143 | TECopy(te); 144 | if (!inPage) { 145 | //ZeroScrap(); 146 | //TEToScrap(); 147 | } 148 | } 149 | break; 150 | case editPasteItem: 151 | if (te && !inPage) { 152 | //TEFromScrap(); 153 | //TEPaste(te); 154 | } else { 155 | SysBeep(5); 156 | } 157 | break; 158 | case editClearItem: 159 | if (te && !inPage) { 160 | TEDelete(te); 161 | } else { 162 | SysBeep(5); 163 | } 164 | break; 165 | case editSelectAllItem: 166 | if (te) { 167 | TESetSelect(0, (*te)->teLength, te); 168 | } 169 | break; 170 | } 171 | break; 172 | } 173 | case navigateMenu: 174 | switch(item) { 175 | case navigateBackItem: 176 | //PageWindowNavigateBack(pWin); 177 | PageWindowNavigateHistory(pWin, -1); 178 | break; 179 | case navigateForwardItem: 180 | //PageWindowNavigateForward(pWin); 181 | PageWindowNavigateHistory(pWin, 1); 182 | break; 183 | case navigateHomeItem: 184 | PageWindowNavigateHome(pWin); 185 | break; 186 | case navigateStopItem: 187 | PageWindowStop(pWin); 188 | break; 189 | case navigateReloadItem: 190 | PageWindowNavigateHistory(pWin, 0); 191 | //PageWindowReload(pWin); 192 | break; 193 | } 194 | break; 195 | } 196 | HiliteMenu(0); 197 | } 198 | 199 | pascal Boolean aboutFilter(DialogPtr dialog, EventRecord *event, 200 | short *itemHit) { 201 | switch (event->what) { 202 | case keyDown: { 203 | char key = event->message & charCodeMask; 204 | if (key == 'q' && event->modifiers & cmdKey) { 205 | Terminate(); 206 | } 207 | // fall-through 208 | } 209 | case mouseDown: 210 | *itemHit = 1; 211 | return true; 212 | } 213 | 214 | return false; 215 | } 216 | 217 | 218 | static void ShowAbout() { 219 | DialogPtr dlg = GetNewDialog(aboutDialog, nil, (WindowPtr)-1L); 220 | short item; 221 | ModalDialog(aboutFilter, &item); 222 | DisposeDialog(dlg); 223 | } 224 | -------------------------------------------------------------------------------- /src/uri.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "http_parser.h" 12 | #include "stream.h" 13 | 14 | #include "Browsy.h" 15 | #include "uri.h" 16 | #include "utils.h" 17 | #include "window.h" 18 | 19 | #include "uri/about.h" 20 | #include "uri/file.h" 21 | #include "uri/http.h" 22 | 23 | /* 24 | char *GuessContentType(char *path) { 25 | char *extension = strrchr(path, '.'); 26 | if (!extension) 27 | return "text/plain"; 28 | if (!strcmp(extension, "html") || !strcmp(extension, "htm")) 29 | return "text/html"; 30 | return "text/plain"; 31 | } 32 | 33 | void DisposeResponse(URIResponse *resp) { 34 | if (resp->contentHandle) DisposeHandle(resp->contentHandle); 35 | if (resp->contentType) free(resp->contentType); 36 | DisposeHeaders(resp->headers); 37 | free(resp); 38 | } 39 | 40 | void RequestURI( 41 | char *uri, 42 | void (*callback)(struct URIRequest *req), 43 | void *refCon) 44 | { 45 | URIRequest *req; 46 | URIResponse *resp; 47 | char scheme[8]; // uri scheme 48 | short i; 49 | short len = strlen(uri)+1; 50 | char *path; // part of the uri after the scheme: 51 | 52 | req = (URIRequest *)malloc(sizeof(URIRequest)); 53 | if (!req) { 54 | ErrorAlert("Unable to create URI request."); 55 | return; 56 | } 57 | 58 | req->refCon = refCon; 59 | req->callback = callback; 60 | req->uri = (char *)malloc(sizeof(char)*len); 61 | strncpy(req->uri, uri, len); 62 | 63 | // get scheme/protocol 64 | // and make it lowercase 65 | for (i=0; ilength = bytes; 104 | resp->contentHandle = fileContents; 105 | resp->contentType = GuessContentType(filePath); 106 | req->state = stateComplete; 107 | req->response = resp; 108 | callback(req); 109 | //TESetText(*fileContents, bytes, pWin->contentTE); 110 | //HLock(fileContents); 111 | //(*pWin->contentTE)->hText = fileContents; 112 | //TECalText(pWin->contentTE); 113 | //InvalRect(&(*pWin->contentTE)->viewRect); 114 | //HUnlock(fileContents); 115 | } 116 | if (refNum) FSClose(refNum); 117 | //if (fileContents) DisposeHandle(fileContents); 118 | free(filePath); 119 | DisposePtr(fName); 120 | 121 | } else if (strcmp(scheme, "http")==0) { 122 | Handle errorText = NewHandle(25); 123 | strcpy(*errorText, "http not yet implemented!"); 124 | //char *path; 125 | //PageWindowSetStatus(pWin, "http not yet implemented!"); 126 | resp = NewResponse(); 127 | resp->contentHandle = errorText; 128 | resp->length = 25; 129 | resp->contentType = "text/plain"; 130 | req->state = stateComplete; 131 | req->response = resp; 132 | callback(req); 133 | 134 | } else { 135 | char errorText[] = "Unknown URI scheme."; 136 | //char *path; 137 | //PageWindowSetStatus(pWin, "http not yet implemented!"); 138 | resp = NewResponse(); 139 | resp->contentHandle = (Handle)&errorText; 140 | resp->length = sizeof(errorText); 141 | resp->contentType = "text/plain"; 142 | req->state = stateComplete; 143 | req->response = resp; 144 | callback(req); 145 | //PageWindowSetStatus(pWin, "Unknown URI scheme."); 146 | } 147 | } 148 | */ 149 | 150 | #define HTTP_SCHEME_PROVIDERS \ 151 | X("about", aboutURIProvider) \ 152 | X("file", fileURIProvider) \ 153 | X("http", httpURIProvider) 154 | 155 | // URI object: a remote resource that may be requested and may respond 156 | struct URI { 157 | URIConsumer *consumer; 158 | void *consumerData; 159 | URIProvider *provider; 160 | void *providerData; 161 | }; 162 | 163 | // create a new uri object 164 | URI *NewURI(char *uriStr) 165 | { 166 | URIProvider *provider; 167 | URI *uri; 168 | 169 | provider = URIGetProvider(uriStr); 170 | if (!provider) return NULL; 171 | 172 | uri = malloc(sizeof(URI)); 173 | if (!uri) return NULL; 174 | 175 | if (URIProvide(uri, provider, uriStr)) { 176 | free(uri); 177 | return NULL; 178 | } 179 | 180 | return uri; 181 | } 182 | 183 | URIProvider *URIGetProvider(char *uri) 184 | { 185 | short i; 186 | struct URISchemeProvider *provider; 187 | 188 | #define X(scheme, provider) \ 189 | if (strncmp(uri, scheme, sizeof(scheme)-1) == 0 \ 190 | && uri[sizeof(scheme)-1] == ':') { \ 191 | return provider; \ 192 | } 193 | HTTP_SCHEME_PROVIDERS 194 | 195 | return NULL; 196 | 197 | /* 198 | struct http_parser_url u; 199 | int result; 200 | if ((result = http_parser_parse_url(uriStr, strlen(uriStr), 0, &u))) { 201 | alertf("Unable to parse URL %s: %d", uriStr, result); 202 | free(uri); 203 | return NULL; 204 | } 205 | */ 206 | } 207 | 208 | // set the uri consumer 209 | void URIConsume(URI *uri, URIConsumer *consumer, void *consumerData) 210 | { 211 | uri->consumer = consumer; 212 | uri->consumerData = consumerData; 213 | } 214 | 215 | // set the uri provider 216 | int URIProvide(URI *uri, URIProvider *provider, char *uriStr) 217 | { 218 | uri->provider = provider; 219 | uri->providerData = provider->init(uri, uriStr); 220 | return uri->providerData ? 0 : -1; 221 | } 222 | 223 | // request the URI, optionally sending along some data 224 | void URIRequest(URI *uri, char *method, Stream *postData) 225 | { 226 | uri->provider->request(uri, uri->providerData, 227 | &(HTTPMethod){httpOtherMethod, method}, postData); 228 | } 229 | 230 | // GET the URI 231 | void URIGet(URI *uri) 232 | { 233 | uri->provider->request(uri, uri->providerData, 234 | &(HTTPMethod){httpGET}, NULL); 235 | } 236 | 237 | // POST to the URI 238 | void URIPost(URI *uri, Stream *postData) 239 | { 240 | uri->provider->request(uri, uri->providerData, 241 | &(HTTPMethod){httpPOST}, NULL); 242 | } 243 | 244 | // forcibly close the uri request and response 245 | void URIClose(URI *uri) 246 | { 247 | uri->provider->close(uri, uri->providerData); 248 | } 249 | 250 | // Provider methods: 251 | 252 | void URIGotStatus(URI *uri, short status) 253 | { 254 | uri->consumer->on_status(uri->consumerData, status); 255 | } 256 | 257 | void URIGotHeader(URI *uri, struct HTTPHeader *header) 258 | { 259 | uri->consumer->on_header(uri->consumerData, header); 260 | } 261 | 262 | void URIHeadersComplete(URI *uri) 263 | { 264 | uri->consumer->on_headers_complete(uri->consumerData); 265 | } 266 | 267 | void URIMessageBegin(URI *uri) 268 | { 269 | uri->consumer->on_message_begin(uri->consumerData); 270 | } 271 | 272 | void URIGotData(URI *uri, char *data, short len) 273 | { 274 | uri->consumer->on_data(uri->consumerData, data, len); 275 | } 276 | 277 | void URIClosed(URI *uri, short error) 278 | { 279 | uri->consumer->on_close(uri->consumerData, error); 280 | } 281 | 282 | -------------------------------------------------------------------------------- /src/uri/http.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Browsy.h" 7 | #include "stream.h" 8 | #include "tcpstream.h" 9 | #include "utils.h" 10 | #include "uri.h" 11 | #include "http_parser.h" 12 | #include "uri/http.h" 13 | 14 | #define HTTP_UA "Browsy/" BROWSY_VERSION " (Macintosh; N; 68K)" 15 | // "Lynx/2.8 (compatible; Browsy/" VERSION " (Macintosh; N; 68K)" 16 | 17 | struct HTTPURIData { 18 | URI *uri; 19 | Stream *tcpStream; 20 | http_parser parser; 21 | short err; 22 | short port; 23 | char host[256]; 24 | char path[256]; 25 | }; 26 | 27 | void *HTTPProviderInit(URI *uri, char *uriStr); 28 | void HTTPProviderClose(URI *uri, void *providerData); 29 | void HTTPProviderRequest(URI *uri, void *providerData, HTTPMethod *method, 30 | Stream *postData); 31 | 32 | struct URIProvider *httpURIProvider = &(URIProvider) { 33 | .init = HTTPProviderInit, 34 | .request = HTTPProviderRequest, 35 | .close = HTTPProviderClose 36 | }; 37 | 38 | int HTTPOnMessageBegin(http_parser *parser); 39 | int HTTPOnStatus(http_parser *parser, const char *at, size_t len); 40 | int HTTPOnHeaderField(http_parser *parser, const char *at, size_t len); 41 | int HTTPOnHeaderValue(http_parser *parser, const char *at, size_t len); 42 | int HTTPOnHeadersComplete(http_parser *parser); 43 | int HTTPOnBody(http_parser *parser, const char *at, size_t len); 44 | int HTTPOnMessageComplete(http_parser *parser); 45 | 46 | http_parser_settings parserSettings = { 47 | .on_message_begin = HTTPOnMessageBegin, 48 | .on_status = HTTPOnStatus, 49 | .on_header_field = HTTPOnHeaderField, 50 | .on_header_value = HTTPOnHeaderValue, 51 | .on_headers_complete = HTTPOnHeadersComplete, 52 | .on_body = HTTPOnBody, 53 | .on_message_complete = HTTPOnMessageComplete 54 | }; 55 | 56 | void TCPOnOpen(void *consumerData); 57 | void TCPOnData(void *consumerData, char *data, short len); 58 | void TCPOnError(void *consumerData, short err); 59 | void TCPOnClose(void *consumerData); 60 | void TCPOnEnd(void *consumerData); 61 | 62 | StreamConsumer tcpConsumer = { 63 | .on_open = TCPOnOpen, 64 | .on_data = TCPOnData, 65 | .on_error = TCPOnError, 66 | .on_close = TCPOnClose, 67 | .on_end = TCPOnEnd, 68 | }; 69 | 70 | // create and return the provider data 71 | void *HTTPProviderInit(URI *uri, char *uriStr) 72 | { 73 | struct HTTPURIData *data; 74 | Stream *tcpStream; 75 | struct http_parser_url urlParser; 76 | size_t hostLen, pathLen; 77 | 78 | if (http_parser_parse_url(uriStr, strlen(uriStr), false, &urlParser)) { 79 | alertf("Error parsing URL %s", uriStr); 80 | return NULL; 81 | } 82 | 83 | if (!(urlParser.field_set & (1 << UF_HOST))) { 84 | alertf("URL missing host"); 85 | return NULL; 86 | } 87 | hostLen = urlParser.field_data[UF_HOST].len; 88 | if (hostLen > sizeof data->host) { 89 | alertf("URL host too long"); 90 | return NULL; 91 | } 92 | 93 | if (!(urlParser.field_set & (1 << UF_PATH))) { 94 | // missing path 95 | pathLen = 0; 96 | } else { 97 | pathLen = urlParser.field_data[UF_PATH].len; 98 | if (pathLen > sizeof data->path) { 99 | alertf("URL path too long"); 100 | return NULL; 101 | } 102 | } 103 | 104 | data = malloc(sizeof(struct HTTPURIData)); 105 | if (!data) { 106 | return NULL; 107 | } 108 | 109 | data->port = urlParser.port ? urlParser.port : 80; 110 | strncpy(data->host, uriStr + urlParser.field_data[UF_HOST].off, hostLen); 111 | strncpy(data->path, uriStr + urlParser.field_data[UF_PATH].off, pathLen); 112 | 113 | // special case: use "/" for empty path 114 | if (pathLen == 0) { 115 | data->path[0] = '/'; 116 | pathLen++; 117 | } 118 | 119 | data->path[pathLen] = '\0'; 120 | data->host[hostLen] = '\0'; 121 | 122 | tcpStream = NewStream(); 123 | if (!tcpStream) { 124 | free(data); 125 | return NULL; 126 | } 127 | 128 | data->uri = uri; 129 | data->tcpStream = tcpStream; 130 | data->err = 0; 131 | http_parser_init(&data->parser, HTTP_RESPONSE); 132 | data->parser.data = data; 133 | 134 | StreamConsume(tcpStream, &tcpConsumer, data); 135 | ProvideTCPActiveStream(tcpStream, data->host, data->port); 136 | return data; 137 | } 138 | 139 | void HTTPProviderClose(URI *uri, void *providerData) 140 | { 141 | struct HTTPURIData *data = (struct HTTPURIData *)providerData; 142 | StreamClose(data->tcpStream); 143 | free(data); 144 | } 145 | 146 | void HTTPProviderRequest(URI *uri, void *providerData, HTTPMethod *method, 147 | Stream *postData) 148 | { 149 | struct HTTPURIData *data = (struct HTTPURIData *)providerData; 150 | 151 | // ignore POST data 152 | (void)postData; 153 | 154 | if (method->type != httpGET) { 155 | // only GET is supported 156 | URIClosed(uri, uriBadMethodErr); 157 | return; 158 | } 159 | 160 | StreamOpen(data->tcpStream); 161 | } 162 | 163 | // TCP connection opened 164 | void TCPOnOpen(void *consumerData) 165 | { 166 | struct HTTPURIData *hData = (struct HTTPURIData *)consumerData; 167 | char reqMsg[256]; 168 | short reqLen; 169 | 170 | // Build the HTTP request 171 | reqLen = snprintf(reqMsg, sizeof reqMsg, 172 | "GET %s HTTP/1.1\r\n" 173 | "User-Agent: " HTTP_UA "\r\n" 174 | "Host: %s\r\n" 175 | "Connection: Close\r\n" 176 | "\r\n", 177 | hData->path, hData->host); 178 | if (reqLen >= sizeof reqMsg) { 179 | // request was truncated 180 | alertf("request truncated"); 181 | StreamClose(hData->tcpStream); 182 | URIClosed(hData->uri, -2); 183 | return; 184 | } 185 | 186 | //alertf("sending http request (%hu): %s", reqLen, reqMsg); 187 | 188 | // Send the request 189 | StreamWrite(hData->tcpStream, reqMsg, reqLen); 190 | } 191 | 192 | void TCPOnData(void *consumerData, char *data, short len) 193 | { 194 | struct HTTPURIData *hData = (struct HTTPURIData *)consumerData; 195 | size_t nparsed; 196 | 197 | /* 198 | alertf("got data (%lu)", len); 199 | URIGotData(hData->uri, data, len); 200 | return; 201 | */ 202 | 203 | nparsed = http_parser_execute(&hData->parser, &parserSettings, data, len); 204 | if (nparsed != len) { 205 | // parser had an error. close connection 206 | alertf("parsing error %u/%u for text (%lu): %.*s", (int)nparsed, (int)len, len, (int)len, data); 207 | //StreamClose(hData->tcpStream); 208 | //URIClosed(hData->uri, -1); 209 | } 210 | 211 | } 212 | 213 | void TCPOnError(void *consumerData, short err) 214 | { 215 | struct HTTPURIData *data = (struct HTTPURIData *)consumerData; 216 | data->err = err; 217 | if (err == tcpMissingDriverErr) { 218 | alertf("Missing MacTCP driver"); 219 | return; 220 | } 221 | alertf("tcp stream error: %ld", err); 222 | /* 223 | URIGotStatus(data->uri, status); 224 | */ 225 | } 226 | 227 | void TCPOnClose(void *consumerData) 228 | { 229 | struct HTTPURIData *data = (struct HTTPURIData *)consumerData; 230 | http_parser_execute(&data->parser, &parserSettings, "", 0); 231 | } 232 | 233 | void TCPOnEnd(void *consumerData) 234 | { 235 | } 236 | 237 | int HTTPOnMessageBegin(http_parser *parser) 238 | { 239 | struct HTTPURIData *hData = (struct HTTPURIData *)parser->data; 240 | URIMessageBegin(hData->uri); 241 | //alertf("message begin"); 242 | return 0; 243 | } 244 | 245 | int HTTPOnStatus(http_parser *parser, const char *at, size_t len) 246 | { 247 | struct HTTPURIData *hData = (struct HTTPURIData *)parser->data; 248 | URIGotStatus(hData->uri, parser->status_code); 249 | return 0; 250 | } 251 | 252 | int HTTPOnHeaderField(http_parser *parser, const char *at, size_t len) 253 | { 254 | return 0; 255 | } 256 | 257 | int HTTPOnHeaderValue(http_parser *parser, const char *at, size_t len) 258 | { 259 | return 0; 260 | } 261 | 262 | int HTTPOnHeadersComplete(http_parser *parser) 263 | { 264 | struct HTTPURIData *hData = (struct HTTPURIData *)parser->data; 265 | URIHeadersComplete(hData->uri); 266 | return 0; 267 | } 268 | 269 | int HTTPOnBody(http_parser *parser, const char *at, size_t len) 270 | { 271 | struct HTTPURIData *hData = (struct HTTPURIData *)parser->data; 272 | URIGotData(hData->uri, (char *)at, len); 273 | return 0; 274 | } 275 | 276 | int HTTPOnMessageComplete(http_parser *parser) 277 | { 278 | struct HTTPURIData *hData = (struct HTTPURIData *)parser->data; 279 | //TODO: check if it happens multiple times 280 | URIClosed(hData->uri, hData->err); 281 | } 282 | 283 | -------------------------------------------------------------------------------- /rsrc/FONT/3060.hex: -------------------------------------------------------------------------------- 1 | 9000 0000 00FF 000D 0000 FFFE 000D 000C 2 | 04D3 000A 0002 0001 0051 0000 0000 0000 3 | 0000 0000 0000 0000 0000 0000 0000 0000 4 | 0000 0000 0000 0000 0000 0000 0000 0000 5 | 0000 0000 0000 0000 0000 0000 0000 0000 6 | 0000 0000 0000 0000 0000 0000 0000 0000 7 | 0000 0000 0000 0000 0000 0000 0000 0000 8 | 0000 0000 0000 0000 0000 0000 0000 0000 9 | 0000 0000 0000 0000 0000 0000 0000 0000 10 | 0000 0000 0000 0000 0000 0000 0000 0000 11 | 0000 0000 0000 0000 0000 0000 0000 0000 12 | 0000 0000 0000 0000 0000 0F80 0000 0000 13 | 0000 0000 0000 0000 0000 0000 0000 0000 14 | 0000 0000 0000 0000 0000 0000 0000 0000 15 | 0000 0000 0000 0000 0000 0000 0000 0000 16 | 0000 0000 0000 0000 0000 0000 0000 0000 17 | 0000 0000 0000 0000 0000 0000 0000 0000 18 | 0000 0000 0000 0000 0000 0000 0000 0000 19 | 0000 0000 0000 0000 0000 0000 0000 0000 20 | 0000 0000 0000 0000 0000 0000 0000 0000 21 | 0000 0000 0000 0000 0000 0000 0000 0000 22 | 0000 0000 0000 0000 0000 0000 3FE0 0000 23 | 0000 0000 0000 0000 0000 0000 0000 0000 24 | 0000 0000 0000 0000 0000 0000 0000 0000 25 | 0000 0000 0000 0000 0000 0000 0000 0000 26 | 0000 0000 0000 0000 0000 0000 0000 0000 27 | 0000 0000 0000 0000 0000 0000 0000 0000 28 | 0000 0000 0000 0000 0000 0000 0000 0000 29 | 0000 0000 0000 0000 0000 0000 0000 0000 30 | 0000 0000 0000 0000 0000 0000 0000 0000 31 | 0000 0000 0000 0000 0000 0000 0000 0000 32 | 0000 0000 0000 0000 0000 0000 0000 7FF0 33 | 0000 0000 0000 0000 0000 0000 0000 0000 34 | 0000 0000 0000 0000 0000 0000 0000 0000 35 | 0000 0000 0000 0000 0000 0000 0000 0000 36 | 0000 0000 0000 0000 0000 0000 0000 0000 37 | 0000 0000 0000 0000 0000 0000 0000 0000 38 | 0000 0000 0000 0000 0000 0000 0000 0000 39 | 0000 0000 0000 0000 0000 0000 0000 0000 40 | 0000 0000 0000 0000 0000 0000 0000 0000 41 | 0000 0000 0000 0000 0000 0000 0000 0000 42 | 0000 0000 0000 0000 0000 0000 0000 0000 43 | 7FF0 739C E739 CE73 9CE7 39CE 739C E739 44 | CE73 9CE7 39CE 739C E739 CE73 9CE7 39CE 45 | 739C E739 CE73 9CE7 39CE 739C E739 CE73 46 | 9CE7 39CE 739C E739 CE73 9CE7 39CE 739C 47 | E739 CE73 9CE7 39CE 739C E739 CE73 9CE7 48 | 39CE 739C E739 CE73 9CE7 39CE 739C E739 49 | CE73 9CE7 39CE 739C E739 CE73 9CE7 39CE 50 | 739C E739 CE73 9CE7 39CE 739C E739 CE73 51 | 9CE7 39CE 739C E739 CE73 9CE7 39CE 739C 52 | E739 CE73 9CE7 39CE 739C E739 CE73 9CE7 53 | 39CE FFF8 FFFF FFFF FFFF FFFF FFFF FFFF 54 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 55 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 56 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 57 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 58 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 59 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 60 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 61 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 62 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 63 | FFFF FFFF FFF8 FFFF FFFF FFFF FFFF FFFF 64 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 65 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 66 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 67 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 68 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 69 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 70 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 71 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 72 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 73 | FFFF FFFF FFFF FFF8 FFFF FFFF FFFF FFFF 74 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 75 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 76 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 77 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 78 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 79 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 80 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 81 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 82 | FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF 83 | FFFF FFFF FFFF FFFF FFF8 739C E739 CE73 84 | 9CE7 39CE 739C E739 CE73 9CE7 39CE 739C 85 | E739 CE73 9CE7 39CE 739C E739 CE73 9CE7 86 | 39CE 739C E739 CE73 9CE7 39CE 739C E739 87 | CE73 9CE7 39CE 739C E739 CE73 9CE7 39CE 88 | 739C E739 CE73 9CE7 39CE 739C E739 CE73 89 | 9CE7 39CE 739C E739 CE73 9CE7 39CE 739C 90 | E739 CE73 9CE7 39CE 739C E739 CE73 9CE7 91 | 39CE 739C E739 CE73 9CE7 39CE 739C E739 92 | CE73 9CE7 39CE 739C E739 CE73 9CE7 39CE 93 | 739C E739 CE73 9CE7 39CE 7FF0 0000 0000 94 | 0000 0000 0000 0000 0000 0000 0000 0000 95 | 0000 0000 0000 0000 0000 0000 0000 0000 96 | 0000 0000 0000 0000 0000 0000 0000 0000 97 | 0000 0000 0000 0000 0000 0000 0000 0000 98 | 0000 0000 0000 0000 0000 0000 0000 0000 99 | 0000 0000 0000 0000 0000 0000 0000 0000 100 | 0000 0000 0000 0000 0000 0000 0000 0000 101 | 0000 0000 0000 0000 0000 0000 0000 0000 102 | 0000 0000 0000 0000 0000 0000 0000 0000 103 | 0000 0000 0000 0000 0000 0000 7FF0 0000 104 | 0000 0000 0000 0000 0000 0000 0000 0000 105 | 0000 0000 0000 0000 0000 0000 0000 0000 106 | 0000 0000 0000 0000 0000 0000 0000 0000 107 | 0000 0000 0000 0000 0000 0000 0000 0000 108 | 0000 0000 0000 0000 0000 0000 0000 0000 109 | 0000 0000 0000 0000 0000 0000 0000 0000 110 | 0000 0000 0000 0000 0000 0000 0000 0000 111 | 0000 0000 0000 0000 0000 0000 0000 0000 112 | 0000 0000 0000 0000 0000 0000 0000 0000 113 | 0000 0000 0000 0000 0000 0000 0000 3FE0 114 | 0000 0000 0000 0000 0000 0000 0000 0000 115 | 0000 0000 0000 0000 0000 0000 0000 0000 116 | 0000 0000 0000 0000 0000 0000 0000 0000 117 | 0000 0000 0000 0000 0000 0000 0000 0000 118 | 0000 0000 0000 0000 0000 0000 0000 0000 119 | 0000 0000 0000 0000 0000 0000 0000 0000 120 | 0000 0000 0000 0000 0000 0000 0000 0000 121 | 0000 0000 0000 0000 0000 0000 0000 0000 122 | 0000 0000 0000 0000 0000 0000 0000 0000 123 | 0000 0000 0000 0000 0000 0000 0000 0000 124 | 0F80 0000 0005 000A 000F 0014 0019 001E 125 | 0023 0028 002D 0032 0037 003C 0041 0046 126 | 004B 0050 0055 005A 005F 0064 0069 006E 127 | 0073 0078 007D 0082 0087 008C 0091 0096 128 | 009B 00A0 00A5 00AA 00AF 00B4 00B9 00BE 129 | 00C3 00C8 00CD 00D2 00D7 00DC 00E1 00E6 130 | 00EB 00F0 00F5 00FA 00FF 0104 0109 010E 131 | 0113 0118 011D 0122 0127 012C 0131 0136 132 | 013B 0140 0145 014A 014F 0154 0159 015E 133 | 0163 0168 016D 0172 0177 017C 0181 0186 134 | 018B 0190 0195 019A 019F 01A4 01A9 01AE 135 | 01B3 01B8 01BD 01C2 01C7 01CC 01D1 01D6 136 | 01DB 01E0 01E5 01EA 01EF 01F4 01F9 01FE 137 | 0203 0208 020D 0212 0217 021C 0221 0226 138 | 022B 0230 0235 023A 023F 0244 0249 024E 139 | 0253 0258 025D 0262 0267 026C 0271 0276 140 | 027B 0280 0285 028A 028F 0294 0299 029E 141 | 02A3 02A8 02AD 02B2 02B7 02BC 02C1 02C6 142 | 02CB 02D0 02D5 02DA 02DF 02E4 02E9 02EE 143 | 02F3 02F8 02FD 0302 0307 030C 0311 0316 144 | 031B 0320 0325 032A 032F 0334 0339 033E 145 | 0343 0348 034D 0352 0357 035C 0361 0366 146 | 036B 0370 0375 037A 037F 0384 0389 038E 147 | 0393 0398 039D 03A2 03A7 03AC 03B1 03B6 148 | 03BB 03C0 03C5 03CA 03CF 03D4 03D9 03DE 149 | 03E3 03E8 03ED 03F2 03F7 03FC 0401 0406 150 | 040B 0410 0415 041A 041F 0424 0429 042E 151 | 0433 0438 043D 0442 0447 044C 0451 0456 152 | 045B 0460 0465 046A 046F 0474 0479 047E 153 | 0483 0488 048D 0492 0497 049C 04A1 04A6 154 | 04AB 04B0 04B5 04BA 04BF 04C4 04C9 04CE 155 | 04D3 04D8 04DD 04E2 04E7 04EC 04F1 04F6 156 | 04FB 0500 050D 0107 0107 0107 0107 0107 157 | 0107 0107 0107 0107 0107 0107 0107 0107 158 | 0107 0107 0107 0107 0107 0107 0107 0107 159 | 0107 0107 0107 0107 0107 0107 0107 0107 160 | 0107 0107 0107 0107 0107 0107 0107 0107 161 | 0107 0107 0107 0107 0107 0107 0107 0107 162 | 0107 0107 0107 0107 0107 0107 0107 0107 163 | 0107 0107 0107 0107 0107 0107 0107 0107 164 | 0107 0107 0107 0107 0107 0107 0107 0107 165 | 0107 0107 0107 0107 0107 0107 0107 0107 166 | 0107 0107 0107 0107 0107 0107 0107 0107 167 | 0107 0107 0107 0107 0107 0107 0107 0107 168 | 0107 0107 0107 0107 0107 0107 0107 0107 169 | 0107 0107 0107 0107 0107 0107 0107 0107 170 | 0107 0107 0107 0107 0107 0107 0107 0107 171 | 0107 0107 0107 0107 0107 0107 0107 0107 172 | 0107 0107 0107 0107 0107 0107 0107 0107 173 | 0107 0107 0107 0107 0107 0107 0107 0107 174 | 0107 0107 0107 0107 0107 0107 0107 0107 175 | 0107 0107 0107 0107 0107 0107 0107 0107 176 | 0107 0107 0107 0107 0107 0107 0107 0107 177 | 0107 0107 0107 0107 0107 0107 0107 0107 178 | 0107 0107 0107 0107 0107 0107 0107 0107 179 | 0107 0107 0107 0107 0107 0107 0107 0107 180 | 0107 0107 0107 0107 0107 0107 0107 0107 181 | 0107 0107 0107 0107 0107 0107 0107 0107 182 | 0107 0107 0107 0107 0107 0107 0107 0107 183 | 0107 0107 0107 0107 0107 0107 0107 0107 184 | 0107 0107 0107 0107 0107 0107 0107 0107 185 | 0107 0107 0107 0107 0107 0107 0107 0107 186 | 0107 0107 0107 0107 0107 0107 0107 0107 187 | 0107 0107 0107 0107 0107 0107 0107 0107 188 | 0107 0107 0107 000D FFFF 189 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "stream.h" 8 | #include "Browsy.h" 9 | #include "window.h" 10 | #include "menus.h" 11 | #include "utils.h" 12 | 13 | void Initialize(); 14 | void MainLoop(); 15 | void CheckEnvironment(); 16 | void DoIdle(); 17 | void Terminate(); 18 | void HandleEvent(EventRecord *event); 19 | void HandleUpdateEvt(EventRecord *event); 20 | void HandleKeyDown(EventRecord *event, WindowPtr topWin); 21 | void HandleMouseDown(EventRecord *event, WindowPtr topWin); 22 | void HandleActivate(EventRecord *event); 23 | void InitAppleEvents(); 24 | //void HandleNullEvent(EventRecord *event); 25 | 26 | QDGlobals qd; 27 | 28 | void main() { 29 | Initialize(); 30 | 31 | // todo: open specified files 32 | // else open empty window 33 | PageWindowNavigateHome(NewPageWindow()); 34 | 35 | MainLoop(); 36 | Terminate(); 37 | } 38 | 39 | void Initialize() { 40 | InitGraf(&qd.thePort); 41 | InitFonts(); 42 | InitWindows(); 43 | InitMenus(); 44 | TEInit(); 45 | InitDialogs(nil); 46 | InitCursor(); 47 | 48 | CheckEnvironment(); 49 | SetupMenus(); 50 | InitAppleEvents(); 51 | InitStreams(); 52 | InitPageWindows(); 53 | } 54 | 55 | void CheckEnvironment() { 56 | SysEnvRec sEnv; 57 | OSErr oe; 58 | 59 | oe = SysEnvirons(1,&sEnv); 60 | 61 | Sys7 = sEnv.systemVersion >= 0x0700; 62 | HasColorQD = sEnv.hasColorQD; 63 | } 64 | 65 | void MainLoop() { 66 | EventRecord event; 67 | Boolean ok; 68 | while (true) { 69 | ok = WNE(everyEvent, &event, 10L, nil); 70 | if (ok) { 71 | HandleEvent(&event); 72 | } else { 73 | // idle 74 | } 75 | PollStreams(); 76 | DoIdle(); 77 | } 78 | } 79 | 80 | void DoIdle() { 81 | PageWindow *topPWin = GetPageWindow(FrontWindow()); 82 | if (topPWin) { 83 | PageWindowIdle(topPWin); 84 | } 85 | } 86 | 87 | void Terminate() { 88 | ExitToShell(); 89 | } 90 | 91 | void HandleEvent(EventRecord *event) { 92 | WindowPtr topWin = FrontWindow(); 93 | switch (event->what) { 94 | case mouseDown: 95 | HandleMouseDown(event, topWin); 96 | break; 97 | case keyDown: 98 | case autoKey: 99 | HandleKeyDown(event, topWin); 100 | break; 101 | case updateEvt: 102 | HandleUpdateEvt(event); 103 | break; 104 | case diskEvt: 105 | //HandleDiskEvt(event); 106 | break; 107 | case activateEvt: 108 | HandleActivate(event); 109 | break; 110 | case mouseMovedMessage: 111 | //HandleMouseMoved(event); 112 | break; 113 | case mouseUp: 114 | //HandleMouseUp(event); 115 | break; 116 | case nullEvent: 117 | //HandleNullEvent(event); 118 | break; 119 | } 120 | } 121 | 122 | void HandleMouseDown(EventRecord *event, WindowPtr topWin) { 123 | WindowPtr win; 124 | PageWindow* pWin; 125 | short windowCode = FindWindow(event->where, &win); 126 | Rect oldPort; 127 | switch (windowCode) { 128 | case inMenuBar: 129 | //AdjustMenus(); 130 | HandleMenu(MenuSelect(event->where)); 131 | break; 132 | case inSysWindow: 133 | SystemClick(event, win); 134 | break; 135 | case inDrag: 136 | DragWindow(win, event->where, &qd.screenBits.bounds); 137 | break; 138 | case inZoomIn: 139 | case inZoomOut: 140 | if (TrackBox(win, event->where, windowCode)) { 141 | SetPort(win); 142 | oldPort = win->portRect; 143 | EraseRect(&win->portRect); 144 | ZoomWindow(win, windowCode, false); 145 | //AdjustScrollBars(win, true); 146 | //DrawPage(win); 147 | InvalRect(&win->portRect); 148 | pWin = GetPageWindow(win); 149 | if (pWin) { 150 | PageWindowResized(pWin, oldPort); 151 | } 152 | } 153 | break; 154 | case inGrow: 155 | { 156 | long size; 157 | Rect r = qd.screenBits.bounds; 158 | //GrafPtr oldPort = 0; 159 | //GetPort(&oldPort); 160 | 161 | r.top = 100; 162 | r.left = 150; 163 | r.bottom -= (GetMBarHeight()<<1); 164 | r.right -= 20; 165 | //SetRect(&r, MaxWindowWidth+SBarSize-1, 64, 166 | //MaxWindowWidth+SBarSize-1, gMaxHeight); 167 | 168 | if (win != topWin) { 169 | SelectWindow(win); 170 | } 171 | 172 | oldPort = win->portRect; 173 | size = GrowWindow(win, event->where, &r); 174 | SizeWindow(win, LoWord(size), HiWord(size), true); 175 | pWin = GetPageWindow(win); 176 | if (pWin) { 177 | PageWindowResized(pWin, oldPort); 178 | } 179 | //DrawPage(win); 180 | SetPort(win); 181 | InvalRect(&win->portRect); 182 | //SetPort(oldPort); 183 | } 184 | break; 185 | case inContent: 186 | if (win != topWin) { 187 | SelectWindow(win); 188 | // todo: draw 189 | } else { 190 | pWin = GetPageWindow(win); 191 | if (pWin) { 192 | PageWindowMouseDown(pWin, event->where, event->modifiers); 193 | } 194 | } 195 | break; 196 | case inGoAway: 197 | if (TrackGoAway(win, event->where)) { 198 | if (event->modifiers & optionKey) { 199 | CloseAll(); 200 | } else { 201 | pWin = GetPageWindow(win); 202 | ClosePageWindow(pWin); 203 | } 204 | } 205 | break; 206 | } 207 | } 208 | 209 | void HandleKeyDown(EventRecord *event, WindowPtr topWin) { 210 | PageWindow *pWin; 211 | char theChar = (char)(event->message & charCodeMask); 212 | if (event->modifiers & cmdKey) { 213 | HandleMenu(MenuKey(theChar)); 214 | } else { 215 | pWin = GetPageWindow(topWin); 216 | PageWindowKeyDown(pWin, theChar); 217 | } 218 | } 219 | 220 | void HandleUpdateEvt(EventRecord *event) { 221 | WindowPtr win = (WindowPtr)(event->message); 222 | PageWindow *pWin = GetPageWindow(win); 223 | BeginUpdate(win); 224 | if (pWin) { 225 | UpdatePageWindow(pWin); 226 | } 227 | EndUpdate(win); 228 | } 229 | 230 | void HandleActivate(EventRecord *event) { 231 | WindowPtr win = (WindowPtr) event->message; 232 | PageWindow *pWin = GetPageWindow(win); 233 | if (!pWin) return; 234 | if (event->modifiers & activeFlag) { 235 | PageWindowActivate(pWin); 236 | } else { 237 | PageWindowDeactivate(pWin); 238 | } 239 | } 240 | 241 | /*void HandleNullEvent(EventRecord *event) { 242 | WindowPtr win = (WindowPtr) event->message; 243 | PageWindow *pWin = GetPageWindow(win); 244 | if (!pWin) return; 245 | PageWindowNullEvent(pWin, event); 246 | }*/ 247 | 248 | Boolean GotRequiredParams(AppleEvent *event) { 249 | DescType returnedType; 250 | Size actualSize; 251 | OSErr err; 252 | err = AEGetAttributePtr (event, keyMissedKeywordAttr, 253 | typeWildCard, &returnedType, NULL, 0, 254 | &actualSize); 255 | 256 | return err == errAEDescNotFound; 257 | 258 | } /* CAppleEvent::GotRequiredParams */ 259 | 260 | 261 | void HandleOpenAE(AppleEvent *event, AppleEvent *reply, long refCon) { 262 | #pragma unused(reply, refCon) 263 | Handle docList = NULL; 264 | long i, itemCount; 265 | FSRef myFSRef; 266 | AEDescList theList; 267 | OSErr oe; 268 | //PageWindow *pwin = GetPageWindow(FrontWindow()); 269 | if ((oe = AEGetParamDesc( event, keyDirectObject, typeAEList, &theList)) != noErr) { 270 | //DebugStr("\pAEGetParamDesc"); 271 | return; 272 | } 273 | 274 | 275 | /*if (!GotRequiredParams(event)) { 276 | //DebugStr("\pGotRequiredParams"); 277 | return; 278 | }*/ 279 | 280 | if ((oe = AECountItems( &theList, &itemCount)) != noErr) { 281 | //DebugStr("\pAECountItems"); 282 | return; 283 | } 284 | 285 | for (i = 1; i <= itemCount; i++) { 286 | //oe = AEGetNthPtr( &theList, i, typeFSRef, &aeKeyword, &actualType, 287 | //(Ptr) &myFSRef, sizeof( FSRef), &actualSize); 288 | oe = AEGetNthPtr( &theList, i, typeFSRef, NULL, NULL, &myFSRef, sizeof(FSRef), NULL); 289 | 290 | if (oe == noErr) { 291 | NewPageWindow(); 292 | //OpenEditWindow(&myFSS); 293 | } 294 | } 295 | AEDisposeDesc(&theList); 296 | // event was handled successfully 297 | } 298 | 299 | pascal OSErr HandleAppleEvent(AppleEvent *event,AppleEvent *reply, long refCon) { 300 | #pragma unused(reply, refCon) 301 | DescType actualType; 302 | Size actualSize; 303 | DescType eventClass, eventID; 304 | OSErr oe; 305 | 306 | if ((oe = AEGetAttributePtr( (AppleEvent*) event, keyEventClassAttr, 307 | typeType, &actualType, (Ptr) &eventClass, 308 | sizeof(eventClass), &actualSize)) != noErr) 309 | return oe; 310 | 311 | 312 | if ((oe = AEGetAttributePtr( (AppleEvent*) event, keyEventIDAttr, 313 | typeType, &actualType, (Ptr) &eventID, 314 | sizeof(eventID), &actualSize)) != noErr) 315 | return oe; 316 | 317 | if (eventClass == kCoreEventClass) { 318 | switch (eventID) { 319 | case kAEOpenApplication: 320 | if (GotRequiredParams(event)) { 321 | } 322 | break; 323 | 324 | case kAEOpenDocuments: 325 | //HandleOpenEvent(event); 326 | break; 327 | 328 | case kAEPrintDocuments: 329 | break; 330 | 331 | case kAEQuitApplication: 332 | if (GotRequiredParams(event)) { 333 | Terminate(); 334 | } 335 | break; 336 | } 337 | } 338 | 339 | return noErr; 340 | } 341 | 342 | void InitAppleEvents() { 343 | if (Sys7) { 344 | AEInstallEventHandler(typeWildCard, typeWildCard, 345 | (AEEventHandlerUPP) NewAEEventHandlerProc((ProcPtr) HandleAppleEvent), 0, FALSE); 346 | AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, 347 | NewAEEventHandlerUPP(HandleOpenAE), 0, FALSE); 348 | //(EventHandlerProcPtr) AppleEventHandler, 0, FALSE); 349 | } 350 | } 351 | -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "Browsy.h" 12 | #include "utils.h" 13 | 14 | static Boolean HasWNE; 15 | 16 | void CheckWNE() { 17 | HasWNE = (GetTrapAddress(_WaitNextEvent) != 18 | GetTrapAddress(_Unimplemented)); 19 | } 20 | 21 | // wait/get next event 22 | Boolean WNE(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn) { 23 | if (HasWNE) { 24 | return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn); 25 | } else { 26 | // Single Finder, System 6 or less 27 | // Give time to desk accessories 28 | SystemTask(); 29 | return GetNextEvent(eventMask, theEvent); 30 | } 31 | } 32 | 33 | // check equality of pascal strings (case insensitive) 34 | Boolean EqualPStringCase(ConstStr255Param str1, ConstStr255Param str2) { 35 | return !strncasecmp(str1, str2, str1[0]+1); 36 | } 37 | 38 | // GetFilePathName and GetFilePathVolRef are from MacTech: 39 | // www.mactech.com/articles/mactech/Vol.07/07.09/FilePath/ 40 | 41 | char *GetFilePathName(vRefNum, fName) 42 | int vRefNum; /* File's vol/dir ref */ 43 | Str255 fName; /* (pascal string) */ 44 | { 45 | WDPBRec wDir; /* Working directory */ 46 | HVolumeParam wVol; /* Working HFS param blk */ 47 | DirInfo wCInfo; /* Working cat info blk */ 48 | long wDirID; /* Working dir number */ 49 | Str255 wName; /* Working directory name*/ 50 | char *wPtr; /* Working string pointer*/ 51 | long wLength; /* Working string length */ 52 | char *pathFileName;/* Working file path name*/ 53 | short i; 54 | 55 | wDir.ioNamePtr = 0L; /* Init working directory*/ 56 | wDir.ioVRefNum = vRefNum; 57 | wDir.ioWDIndex = 0; 58 | wDir.ioWDProcID = 0; 59 | wDir.ioWDVRefNum = vRefNum; 60 | 61 | (void) PBGetWDInfo(&wDir,FALSE); /* Get the directory ref */ 62 | 63 | vRefNum = wDir.ioWDVRefNum;/* Save working vol ref #*/ 64 | wDirID = wDir.ioWDDirID; /* Save working dir ref #*/ 65 | 66 | wVol.ioNamePtr = (StringPtr)&wName;/* Init vol block*/ 67 | wVol.ioVRefNum = vRefNum; 68 | wVol.ioVolIndex = 0; 69 | 70 | wLength = 0L; /* Set path length to zip*/ 71 | pathFileName = NewPtr(0L); /* Set null file's path */ 72 | 73 | if (!PBHGetVInfoSync((HParmBlkPtr)&wVol) &&/* Got vol info? */ 74 | pathFileName) { /* Got file path pointer?*/ 75 | if (wVol.ioVSigWord == 0x4244) {/* Check if it HFS */ 76 | wCInfo.ioNamePtr = (StringPtr)&wName;/* Init it */ 77 | wCInfo.ioVRefNum = vRefNum; 78 | wCInfo.ioFDirIndex = -1; 79 | wCInfo.ioDrParID = wDirID; 80 | wCInfo.ioDrDirID = wDirID; 81 | 82 | while (wCInfo.ioDrParID != 1){/* Do full path */ 83 | wCInfo.ioDrDirID = wCInfo.ioDrParID;/*Move up dir*/ 84 | 85 | if (PBGetCatInfo((CInfoPBPtr)&wCInfo,FALSE))/* Get dir info */ 86 | break; /* Break-out if failed!! */ 87 | 88 | wLength += wName[0] + 1L;/* Set string length */ 89 | wPtr = NewPtr(wLength + 1L);/* Alloc new str */ 90 | 91 | if (!wPtr) { /* Didn't get str ptr? */ 92 | if (pathFileName) /* Check if got memory */ 93 | DisposePtr(pathFileName);/* Release it */ 94 | pathFileName = 0L; /* Invalidate str pointer*/ 95 | break; /* Break-out if failed!! */ 96 | } 97 | /* Shuffle file path down*/ 98 | BlockMove(pathFileName,wPtr + wName[0] + 1, 99 | wLength - (long)(wName[0])); 100 | DisposePtr(pathFileName);/* Release old one */ 101 | *(wPtr + wName[0]) = ':';/* Add dir delimeter */ 102 | BlockMove(&wName[1],pathFileName = wPtr, (long)(wName[0])); 103 | } 104 | } 105 | else { /* Oops, get vol info */ 106 | wLength = wName[0] + 1L; /* Set string length */ 107 | wPtr = NewPtr(wLength + 1L);/* Alloc new string */ 108 | 109 | if (wPtr) { /* Got string pointer? */ 110 | *(wPtr + wName[0]) = ':';/* Tack on dir delimeter*/ 111 | BlockMove(&wName[1],pathFileName = wPtr, 112 | (long)(wName[0])); 113 | } 114 | 115 | } 116 | if (pathFileName) /* Check if got da string*/ 117 | pathFileName[wLength] = 0;/* Set end-of-string */ 118 | } 119 | 120 | // append filename 121 | //strncpy(pathFileName + wLength, fName+1, fName[0]); 122 | wPtr = NewPtr(wLength + fName[0] + 1); 123 | BlockMove(pathFileName, wPtr, wLength); 124 | DisposePtr(pathFileName); 125 | BlockMove(&fName[1], (pathFileName = wPtr) + wLength, (long)(fName[0])); 126 | wLength += fName[0]; 127 | pathFileName[wLength] = 0; 128 | 129 | // convert path to unix-style 130 | for (i=0; i> 4), *pbuf++ = to_hex(*pstr & 15); 249 | pstr++; 250 | } 251 | *pbuf = '\0'; 252 | return buf; 253 | } 254 | 255 | /* Returns a url-decoded version of str */ 256 | /* IMPORTANT: be sure to free() the returned string after use */ 257 | char *url_decode(char *str) { 258 | char *pstr = str, *buf = (char*)malloc(strlen(str) + 1), *pbuf = buf; 259 | if (!buf) return NULL; 260 | while (*pstr) { 261 | if (*pstr == '%') { 262 | if (pstr[1] && pstr[2]) { 263 | *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]); 264 | pstr += 2; 265 | } 266 | //} else if (*pstr == '+') { 267 | //*pbuf++ = ' '; 268 | } else { 269 | *pbuf++ = *pstr; 270 | } 271 | pstr++; 272 | } 273 | *pbuf = '\0'; 274 | return buf; 275 | } 276 | 277 | // get where a character is safe for url 278 | // return true if it is safe 279 | // return false if it has to be escaped 280 | static inline char is_char_urlsafe(char c) { 281 | return isalnum(c) || 282 | c == '-' || c == '_' || c == '.' || c == '~' || 283 | c == ':' || c == '/' || c == '?' || c == '&' || 284 | c == '=' || c == '%' || c == ';'; 285 | } 286 | 287 | /* Make sure a str is url-encoded and has a scheme */ 288 | /* IMPORTANT: be sure to free() the returned string after use */ 289 | char *url_sanitize(char *str) { 290 | static const char default_scheme[] = "http://"; 291 | char insert_default_scheme = true; 292 | short len = strlen(str) + 1; 293 | char pchar; 294 | char *pstr, *buf, *pbuf; 295 | 296 | // calculate new string length 297 | for (pstr = str; pchar = *pstr; pstr++) { 298 | if (!is_char_urlsafe(pchar)) 299 | len += 2; 300 | else if (pchar == ':' && insert_default_scheme) { 301 | insert_default_scheme = false; 302 | } 303 | } 304 | if (insert_default_scheme) { 305 | len += sizeof(default_scheme) - 1; 306 | } 307 | 308 | // allocate the string 309 | buf = pbuf = malloc(len); 310 | if (!buf) return NULL; 311 | 312 | // copy the string 313 | if (insert_default_scheme) { 314 | strcpy(pbuf, default_scheme); 315 | pbuf += sizeof(default_scheme) - 1; 316 | } 317 | for (pstr = str; pchar = *pstr; pstr++) { 318 | if (is_char_urlsafe(pchar)) { 319 | *pbuf++ = pchar; 320 | } else { 321 | *pbuf++ = '%'; 322 | *pbuf++ = to_hex(pchar >> 4); 323 | *pbuf++ = to_hex(pchar & 15); 324 | } 325 | } 326 | *pbuf = '\0'; 327 | return buf; 328 | } 329 | 330 | // from Apple Technical Note TN1019, 331 | // with modifications for changing the source mode (removed) 332 | void PlotSICN(Rect *theRect, SICNHand theSICN, long theIndex/*, short srcMode*/) { 333 | char state; /* saves original flags of 'SICN' handle */ 334 | BitMap srcBits; /* built up around 'SICN' data so we can CopyBits */ 335 | short srcMode = srcCopy; 336 | //if (!srcMode) srcMode = srcCopy; 337 | 338 | /* check the index for a valid value */ 339 | if ((InlineGetHandleSize((Handle)theSICN) / sizeof(SICN)) > theIndex) { 340 | 341 | /* store the resource's current locked/unlocked condition */ 342 | state = HGetState((Handle)theSICN); 343 | 344 | /* lock the resource so it won't move during the CopyBits call */ 345 | HLock((Handle)theSICN); 346 | 347 | /* set up the small icon's bitmap */ 348 | srcBits.baseAddr = (Ptr) (*theSICN)[theIndex]; 349 | srcBits.rowBytes = 2; 350 | SetRect(&srcBits.bounds, 0, 0, 16, 16); 351 | 352 | /* draw the small icon in the current grafport */ 353 | CopyBits(&srcBits,&(*qd.thePort).portBits, 354 | &srcBits.bounds,theRect,srcMode,nil); 355 | 356 | /* restore the resource's locked/unlocked condition */ 357 | HSetState((Handle) theSICN, state); 358 | } 359 | } 360 | 361 | void CtoP(char *cstr, unsigned char *pstr) { 362 | short len = strlen(cstr); 363 | strncpy(pstr+1, cstr, len); 364 | pstr[0] = len; 365 | } 366 | 367 | // copy a c string to new pascal string, allocating memory for it 368 | StringPtr CtoPCopy(const char *cstr) 369 | { 370 | short len = strlen(cstr); 371 | StringPtr pstr = NewPtr(len + 1L); 372 | if (!pstr) return NULL; 373 | BlockMove(cstr, pstr+1, len); 374 | pstr[0] = len; 375 | return pstr; 376 | } 377 | 378 | void ErrorAlert(char *text) { 379 | Str255 errStr; 380 | short len = strlen(text); 381 | strncpy(errStr+1, text, len); 382 | //BlockMove(text, errStr+1, len); 383 | errStr[0] = len; 384 | 385 | ParamText(errStr, "\p", "\p", "\p"); 386 | StopAlert(129, NULL); 387 | } 388 | 389 | void alertf(char *fmt, ...) { 390 | va_list ap; 391 | Str255 str; 392 | size_t len; 393 | 394 | va_start(ap, fmt); 395 | len = vsnprintf(str+1, sizeof(str)-1, fmt, ap); 396 | va_end(ap); 397 | str[0] = len; 398 | 399 | ParamText(str, "\p", "\p", "\p"); 400 | StopAlert(129, NULL); 401 | } 402 | 403 | // append text to a textedit field 404 | void TEAppendText(const void *text, long len, TEHandle hTE) 405 | { 406 | static const short tabSize = 4; 407 | char *cur, *end, *dest; 408 | long newLen; 409 | short i; 410 | char c; 411 | 412 | end = (char *)text + len; 413 | TEPtr te = *hTE; 414 | Handle hText = te->hText; 415 | newLen = te->teLength + len; 416 | 417 | // Adjust length 418 | for (cur = (char *)text; cur < end; cur++) { 419 | switch (*cur) { 420 | // Expand tabs 421 | case '\t': 422 | newLen += tabSize; 423 | break; 424 | // Collapse \r\n 425 | case '\n': 426 | if (cur[-1] == '\r') { 427 | newLen--; 428 | } 429 | break; 430 | } 431 | } 432 | 433 | // Expand block if needed 434 | if (InlineGetHandleSize(hText) < newLen) { 435 | SetHandleSize(hText, newLen); 436 | } 437 | 438 | // Append the text 439 | dest = *hText + te->teLength; 440 | for (cur = (char *)text; cur < end; cur++) { 441 | switch (c = *cur) { 442 | case '\t': 443 | for (i = 0; i < tabSize; i++) 444 | *dest++ = ' '; 445 | break; 446 | case '\n': 447 | // Replace \r\n and \n with \r 448 | if (cur[-1] != '\r') { 449 | *dest++ = '\r'; 450 | } 451 | break; 452 | default: 453 | *dest++ = c; 454 | } 455 | } 456 | 457 | te->teLength = newLen; 458 | TECalText(hTE); 459 | } 460 | -------------------------------------------------------------------------------- /src/tokenizer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "tokenizer.h" 7 | 8 | Tokenizer *NewTokenizer() { 9 | Tokenizer *tok = (Tokenizer *)malloc(sizeof(Tokenizer)); 10 | tok->state = DATA_STATE; 11 | return tok; 12 | } 13 | 14 | void DisposeTokenizer(Tokenizer *tokenizer) { 15 | free(tokenizer); 16 | } 17 | 18 | char readchar(Tokenizer *tokenizer) { 19 | 20 | } 21 | 22 | // Function prototypes 23 | char *ConsumeCharacterReference(Tokenizer *tokenizer); 24 | Boolean isAppropriateEndTagToken(TagToken *endTagToken); 25 | 26 | #define STATE tokenizer->state 27 | 28 | #define CASE_AZ \ 29 | case 'A': \ 30 | case 'B': \ 31 | case 'C': \ 32 | case 'D': \ 33 | case 'E': \ 34 | case 'F': \ 35 | case 'G': \ 36 | case 'H': \ 37 | case 'I': \ 38 | case 'J': \ 39 | case 'K': \ 40 | case 'L': \ 41 | case 'M': \ 42 | case 'N': \ 43 | case 'O': \ 44 | case 'P': \ 45 | case 'Q': \ 46 | case 'R': \ 47 | case 'S': \ 48 | case 'T': \ 49 | case 'U': \ 50 | case 'V': \ 51 | case 'W': \ 52 | case 'X': \ 53 | case 'Y': \ 54 | case 'Z' 55 | 56 | #define CASE_az \ 57 | case 'a': \ 58 | case 'b': \ 59 | case 'c': \ 60 | case 'd': \ 61 | case 'e': \ 62 | case 'f': \ 63 | case 'g': \ 64 | case 'h': \ 65 | case 'i': \ 66 | case 'j': \ 67 | case 'k': \ 68 | case 'l': \ 69 | case 'm': \ 70 | case 'n': \ 71 | case 'o': \ 72 | case 'p': \ 73 | case 'q': \ 74 | case 'r': \ 75 | case 's': \ 76 | case 't': \ 77 | case 'u': \ 78 | case 'v': \ 79 | case 'w': \ 80 | case 'x': \ 81 | case 'y': \ 82 | case 'z' 83 | 84 | #define CASE_WHITESPACE \ 85 | case '\t': \ 86 | case '\n': \ 87 | case '\r': \ 88 | case '\f': \ 89 | case ' ' \ 90 | 91 | #define PARSE_ERROR()\ 92 | ; // TODO 93 | 94 | #define EMIT(type, value)\ 95 | ; // TODO 96 | 97 | #define EMIT_EOF_TOKEN\ 98 | ; // TODO 99 | 100 | #define RECONSUME(input)\ 101 | continue 102 | 103 | void tokenize(Tokenizer *tokenizer) { 104 | TokenizerState state = tokenizer->state; 105 | static char replacementChar = '\xfd'; // U+FFFD 106 | char tempBuffer[64]; 107 | char tempBufferL; 108 | TagToken *currentTagToken; 109 | TagToken *startTagToken; 110 | TagToken *endTagToken; 111 | char input; 112 | 113 | while (input = readchar(tokenizer)) { 114 | 115 | switch (state) { 116 | case DATA_STATE: 117 | switch(input) { 118 | case '&': 119 | STATE = CHARACTER_REFERENCE_IN_DATA_STATE; 120 | break; 121 | case '<': 122 | STATE = TAG_OPEN_STATE; 123 | break; 124 | case '\0': 125 | PARSE_ERROR(); 126 | EMIT(CHARACTER_TOKEN, '\0'); 127 | break; 128 | case EOF: 129 | EMIT_EOF_TOKEN; 130 | break; 131 | default: 132 | EMIT(CHARACTER_TOKEN, input); 133 | break; 134 | } 135 | break; 136 | case CHARACTER_REFERENCE_IN_DATA_STATE: 137 | { 138 | char *charRefs = ConsumeCharacterReference(tokenizer); 139 | if (charRefs) { 140 | EMIT(CHARACTER_TOKENS, charRefs); 141 | } else { 142 | EMIT(CHARACTER_TOKEN, '&'); 143 | } 144 | } 145 | break; 146 | case RCDATA_STATE: 147 | switch(input) { 148 | case '&': 149 | STATE = CHARACTER_REFERENCE_IN_RCDATA_STATE; 150 | break; 151 | case '<': 152 | STATE = RCDATA_LESS_THAN_SIGN_STATE; 153 | break; 154 | case '\0': 155 | PARSE_ERROR(); 156 | EMIT(CHARACTER_TOKEN, replacementChar); 157 | break; 158 | case EOF: 159 | EMIT_EOF_TOKEN; 160 | break; 161 | default: 162 | EMIT(CHARACTER_TOKEN, input); 163 | break; 164 | } 165 | break; 166 | case CHARACTER_REFERENCE_IN_RCDATA_STATE: 167 | { 168 | char *charRefs = ConsumeCharacterReference(tokenizer); 169 | if (charRefs) { 170 | EMIT(CHARACTER_TOKENS, charRefs); 171 | } else { 172 | EMIT(CHARACTER_TOKEN, '&'); 173 | } 174 | } 175 | break; 176 | case RAWTEXT_STATE: 177 | switch(input) { 178 | case '<': 179 | STATE = RAWTEXT_LESS_THAN_SIGN_STATE; 180 | break; 181 | case '\0': 182 | PARSE_ERROR(); 183 | EMIT(CHARACTER_TOKEN, replacementChar); 184 | break; 185 | case EOF: 186 | EMIT_EOF_TOKEN; 187 | break; 188 | default: 189 | EMIT(CHARACTER_TOKEN, input); 190 | break; 191 | } 192 | break; 193 | case SCRIPT_DATA_STATE: 194 | switch(input) { 195 | case '<': 196 | STATE = SCRIPT_DATA_LESS_THAN_SIGN_STATE; 197 | break; 198 | case '\0': 199 | PARSE_ERROR(); 200 | EMIT(CHARACTER_TOKEN, replacementChar); 201 | break; 202 | case EOF: 203 | EMIT_EOF_TOKEN; 204 | break; 205 | default: 206 | EMIT(CHARACTER_TOKEN, input); 207 | break; 208 | } 209 | break; 210 | case PLAINTEXT_STATE: 211 | switch(input) { 212 | case '\0': 213 | PARSE_ERROR(); 214 | EMIT(CHARACTER_TOKEN, replacementChar); 215 | break; 216 | case EOF: 217 | EMIT_EOF_TOKEN; 218 | break; 219 | default: 220 | EMIT(CHARACTER_TOKEN, input); 221 | break; 222 | } 223 | break; 224 | case TAG_OPEN_STATE: 225 | switch(input) { 226 | case '!': 227 | STATE = MARKUP_DECLARATION_OPEN_STATE; 228 | break; 229 | case '/': 230 | STATE = END_TAG_OPEN_STATE; 231 | break; 232 | CASE_AZ: 233 | // new startTagToken 234 | startTagToken->tagName[0] = tolower(input); 235 | startTagToken->tagName[1] = '\0'; 236 | startTagToken->tagNameLength = 1; 237 | STATE = TAG_NAME_STATE; 238 | break; 239 | CASE_az: 240 | // new startTagToken 241 | startTagToken->tagName[0] = input; 242 | startTagToken->tagName[1] = '\0'; 243 | startTagToken->tagNameLength = 1; 244 | STATE = TAG_NAME_STATE; 245 | break; 246 | case '?': 247 | PARSE_ERROR(); 248 | STATE = BOGUS_COMMENT_STATE; 249 | break; 250 | default: 251 | PARSE_ERROR(); 252 | STATE = DATA_STATE; 253 | EMIT(CHARACTER_TOKEN, '<'); 254 | RECONSUME(input); 255 | break; 256 | } 257 | break; 258 | case END_TAG_OPEN_STATE: 259 | switch(input) { 260 | CASE_AZ: 261 | // new startTagToken 262 | endTagToken->tagName[0] = tolower(input); 263 | endTagToken->tagName[1] = '\0'; 264 | endTagToken->tagNameLength = 1; 265 | STATE = TAG_NAME_STATE; 266 | break; 267 | CASE_az: 268 | // new startTagToken 269 | endTagToken->tagName[0] = input; 270 | endTagToken->tagName[1] = '\0'; 271 | endTagToken->tagNameLength = 1; 272 | STATE = TAG_NAME_STATE; 273 | break; 274 | case '>': 275 | PARSE_ERROR(); 276 | STATE = DATA_STATE; 277 | break; 278 | case EOF: 279 | PARSE_ERROR(); 280 | STATE = DATA_STATE; 281 | EMIT(CHARACTER_TOKENS, "': 299 | STATE = DATA_STATE; 300 | EMIT(CHARACTER_TOKEN, input); 301 | break; 302 | CASE_AZ: 303 | if (currentTagToken->tagNameLength+1 < 304 | sizeof(currentTagToken->tagName)) { 305 | currentTagToken->tagName[currentTagToken->tagNameLength++] = 306 | tolower(input); 307 | } 308 | break; 309 | case '\0': 310 | PARSE_ERROR(); 311 | EMIT(CHARACTER_TOKEN, replacementChar); 312 | break; 313 | case EOF: 314 | PARSE_ERROR(); 315 | STATE = DATA_STATE; 316 | RECONSUME(input); 317 | break; 318 | default: 319 | if (currentTagToken->tagNameLength+1 < 320 | sizeof(currentTagToken->tagName)) { 321 | currentTagToken->tagName[currentTagToken->tagNameLength++] = 322 | input; 323 | } 324 | } 325 | break; 326 | case RCDATA_LESS_THAN_SIGN_STATE: 327 | switch(input) { 328 | case '/': 329 | tempBuffer[0] = '\0'; 330 | tempBufferL = 0; 331 | STATE = RCDATA_END_TAG_OPEN_STATE; 332 | break; 333 | default: 334 | STATE = RCDATA_STATE; 335 | EMIT(CHARACTER_TOKEN, '<'); 336 | RECONSUME(input); 337 | } 338 | break; 339 | case RCDATA_END_TAG_OPEN_STATE: 340 | switch(input) { 341 | CASE_AZ: 342 | endTagToken->tagName[0] = tolower(input); 343 | endTagToken->tagName[1] = '\0'; 344 | endTagToken->tagNameLength = 1; 345 | if (tempBufferL+1 < sizeof(tempBuffer)) { 346 | tempBuffer[tempBufferL++] = input; 347 | } 348 | STATE = RCDATA_END_TAG_NAME_STATE; 349 | break; 350 | CASE_az: 351 | endTagToken->tagName[0] = input; 352 | endTagToken->tagName[1] = '\0'; 353 | endTagToken->tagNameLength = 1; 354 | if (tempBufferL+1 < sizeof(tempBuffer)) { 355 | tempBuffer[tempBufferL++] = input; 356 | } 357 | STATE = RCDATA_END_TAG_NAME_STATE; 358 | break; 359 | default: 360 | STATE = RCDATA_STATE; 361 | EMIT(CHARACTER_TOKENS, "': 382 | if (isAppropriateEndTagToken(endTagToken)) { 383 | STATE = DATA_STATE; 384 | EMIT(TAG_TOKEN, endTagToken); 385 | } else { 386 | goto nowayjose; 387 | } 388 | break; 389 | CASE_AZ: 390 | if (endTagToken->tagNameLength+1 < 391 | sizeof(endTagToken->tagName)) { 392 | endTagToken->tagName[endTagToken->tagNameLength++] = 393 | tolower(input); 394 | } 395 | if (tempBufferL+1 < sizeof(tempBuffer)) { 396 | tempBuffer[tempBufferL++] = input; 397 | } 398 | break; 399 | CASE_az: 400 | if (endTagToken->tagNameLength+1 < 401 | sizeof(endTagToken->tagName)) { 402 | endTagToken->tagName[endTagToken->tagNameLength++] = 403 | input; 404 | } 405 | if (tempBufferL+1 < sizeof(tempBuffer)) { 406 | tempBuffer[tempBufferL++] = input; 407 | } 408 | break; 409 | default: 410 | STATE = RCDATA_STATE; 411 | EMIT(CHARACTER_TOKENS, "tagName[0] = tolower(input); 434 | endTagToken->tagName[1] = '\0'; 435 | endTagToken->tagNameLength = 1; 436 | if (tempBufferL+1 < sizeof(tempBuffer)) { 437 | tempBuffer[tempBufferL++] = input; 438 | } 439 | STATE = RAWTEXT_END_TAG_NAME_STATE; 440 | break; 441 | CASE_az: 442 | // new endTagToken 443 | endTagToken->tagName[0] = input; 444 | endTagToken->tagName[1] = '\0'; 445 | endTagToken->tagNameLength = 1; 446 | if (tempBufferL+1 < sizeof(tempBuffer)) { 447 | tempBuffer[tempBufferL++] = input; 448 | } 449 | break; 450 | default: 451 | STATE = RAWTEXT_STATE; 452 | EMIT(CHARACTER_TOKENS, "': 473 | if (isAppropriateEndTagToken(endTagToken)) { 474 | STATE = DATA_STATE; 475 | } else { 476 | goto nowayjose; 477 | } 478 | break; 479 | CASE_AZ: 480 | if (endTagToken->tagNameLength+1 < 481 | sizeof(endTagToken->tagName)) { 482 | endTagToken->tagName[endTagToken->tagNameLength++] = 483 | tolower(input); 484 | } 485 | if (tempBufferL+1 < sizeof(tempBuffer)) { 486 | tempBuffer[tempBufferL++] = input; 487 | } 488 | break; 489 | CASE_az: 490 | if (endTagToken->tagNameLength+1 < 491 | sizeof(endTagToken->tagName)) { 492 | endTagToken->tagName[endTagToken->tagNameLength++] = 493 | input; 494 | } 495 | if (tempBufferL+1 < sizeof(tempBuffer)) { 496 | tempBuffer[tempBufferL++] = input; 497 | } 498 | break; 499 | default: 500 | nowayjose: 501 | STATE = RAWTEXT_STATE; 502 | EMIT(CHARACTER_TOKENS, " 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "Browsy.h" 15 | #include "utils.h" 16 | #include "window.h" 17 | #include "uri.h" 18 | #include "document.h" 19 | 20 | #define toolbarHeight 28 21 | #define statusBarHeight 15 22 | #define defaultWindow 128 23 | #define handCursor 128 24 | #define toolbarButtonsWidth 82 25 | #define navBtn 1 26 | #define toolbarIconsSICN 128 27 | #define toolbarIconsDisabledSICN 129 28 | #define navMenuPopupIds 1000 29 | enum {iconBack, iconForward, iconHome, iconStop, iconRefresh}; 30 | 31 | /*static Rect toolbarRects[] = {toolbarRectBack, toolbarRectForward, 32 | toolbarRectHome, toolbarRectStop};*/ 33 | 34 | Rect toolbarButtonsRect = {4, 4, toolbarHeight, toolbarButtonsWidth + 4}; 35 | 36 | Rect toolbarRectBack = {5, 5, 21, 21}; // top left bottom right 37 | Rect toolbarRectForward = {5, 25, 21, 41}; 38 | Rect toolbarRectHome = {5, 45, 21, 61}; 39 | Rect toolbarRectStopRefresh = {5, 65, 21, 81}; 40 | 41 | void Scroll(PageWindow *pWin, int h, int v); 42 | //void PageWindowAdjustScrollBars(PageWindow *pWin); 43 | void FrameAddressBar(PageWindow *pWin); 44 | void PageWindowDrawGrowIcon(PageWindow *pWin); 45 | HistoryItem *HistoryItemNewNext(HistoryItem *base); 46 | void DrawToolbarButtons(PageWindow *pWin); 47 | void HandleNavButtonClick(PageWindow *pWin, Point where); 48 | void PopupNavMenu(PageWindow *pWin, Rect *buttonRect); 49 | void DebugSave(long bytes, Ptr buffer); 50 | void LoadingStarted(PageWindow *pWin); 51 | void LoadingEnded(PageWindow *pWin); 52 | 53 | pascal void ScrollAction(ControlHandle control, short part); 54 | 55 | void PageURIOnStatus(void *obj, short httpStatus); 56 | void PageURIOnHeader(void *obj, struct HTTPHeader *header); 57 | void PageURIOnHeadersComplete(void *obj); 58 | void PageURIOnMessageBegin(void *obj); 59 | void PageURIOnData(void *obj, char *data, short len); 60 | void PageURIOnClose(void *obj, short err); 61 | 62 | URIConsumer PageURIConsumer = { 63 | .on_status = PageURIOnStatus, 64 | .on_header = PageURIOnHeader, 65 | .on_headers_complete = PageURIOnHeadersComplete, 66 | .on_message_begin = PageURIOnMessageBegin, 67 | .on_data = PageURIOnData, 68 | .on_close = PageURIOnClose 69 | }; 70 | 71 | void InitPageWindows() { 72 | // left top right bottom 73 | //SetRect(&toolbarButtonsRect, 4, 4, toolbarButtonsWidth + 4, toolbarHeight); 74 | //(SICNHand) GetResource('SICN', mySICN); 75 | } 76 | 77 | PageWindow* GetPageWindow(WindowPtr win) { 78 | WindowPeek peek = (WindowPeek) win; 79 | if (!win) return nil; 80 | if (peek->windowKind >= userKind) { 81 | return (PageWindow*) GetWRefCon(win); 82 | } 83 | return nil; 84 | } 85 | 86 | void ClosePageWindow(PageWindow *pWin) { 87 | HistoryItem *history = pWin->history, *curr, *next; 88 | TEDispose(pWin->addressBarTE); 89 | TEDispose(pWin->contentTE); 90 | TEDispose(pWin->statusTE); 91 | DisposeWindow(pWin->window); 92 | 93 | // Dispose window history. 94 | if (history) { 95 | for (curr = history->next; curr; curr = next) { 96 | next = curr->next; 97 | if (curr->address) free(curr->address); 98 | if (curr->title) free(curr->title); 99 | free(curr); 100 | } 101 | for (curr = history; curr; curr = next) { 102 | next = curr->prev; 103 | if (curr->address) free(curr->address); 104 | if (curr->title) free(curr->title); 105 | free(curr); 106 | } 107 | } 108 | 109 | free(pWin); 110 | } 111 | 112 | void CloseAll() { 113 | WindowPeek win = (WindowPeek) FrontWindow(); 114 | PageWindow* pWin; 115 | while (win) { 116 | pWin = GetPageWindow((WindowPtr)&win); 117 | if (pWin) { 118 | ClosePageWindow(pWin); 119 | } 120 | win = win->nextWindow; 121 | } 122 | } 123 | 124 | PageWindow* NewPageWindow() { 125 | //Str255 name = "\pUntitled"; 126 | PageWindow* pWin = (PageWindow*) malloc(sizeof(PageWindow)); 127 | WindowPtr window = GetNewWindow(defaultWindow, nil, (WindowPtr)-1L); 128 | TEHandle addressBarTE, contentTE, statusTE; 129 | TEPtr te; 130 | Rect destRect, viewRect, scrollRect, pr; 131 | //ControlHandle vScrollBar; 132 | 133 | SetPort(window); 134 | pr = window->portRect; 135 | 136 | //PageWindowDrawGrowIcon(pWin); 137 | 138 | // Address bar 139 | destRect.top = viewRect.top = 7; 140 | destRect.left = viewRect.left = 7 + toolbarButtonsWidth; 141 | destRect.bottom = viewRect.bottom = 21; 142 | destRect.right = 1000; 143 | viewRect.right = pr.right - pr.left - 7; 144 | addressBarTE = TENew(&destRect, &viewRect); 145 | //(*addressBarTE)->txFont = 0; 146 | //(*addressBarTE)->txFace = 0; 147 | (*addressBarTE)->txSize = 10; 148 | (*addressBarTE)->lineHeight = 13; 149 | (*addressBarTE)->fontAscent = 10; 150 | TESetText("http://", 7, addressBarTE); 151 | pWin->addressBarTE = addressBarTE; 152 | //TEActivate(addressBarTE); 153 | //InvalRect(&viewRect); 154 | 155 | // Content TE 156 | destRect.top = viewRect.top = pr.top + toolbarHeight; 157 | destRect.left = viewRect.left = 0; 158 | //destRect.bottom = viewRect.bottom = 30; 159 | viewRect.bottom = pr.bottom - statusBarHeight; 160 | destRect.bottom = 1000; // page length? 161 | destRect.right = viewRect.right = pr.right - 15; 162 | contentTE = TEStyleNew(&destRect, &viewRect); 163 | pWin->contentTE = contentTE; 164 | //TEActivate(contentTE); 165 | te = *contentTE; 166 | te->txFont = kFontIDMonaco; 167 | te->txFace = 0; 168 | te->txSize = 9; 169 | te->lineHeight = 12; 170 | te->fontAscent = 9; 171 | 172 | // Status bar TE 173 | //destRect.left = viewRect.left = 2; 174 | destRect.left = 2; 175 | viewRect.left = 0; 176 | //destRect.top = viewRect.top = pr.bottom - statusBarHeight + 4; 177 | destRect.top = pr.bottom - statusBarHeight + 2; 178 | viewRect.top = destRect.top - 1; 179 | //destRect.bottom = viewRect.bottom = destRect.top + 12; 180 | //destRect.bottom = viewRect.top + 12; 181 | //viewRect.bottom = pr.bottom; 182 | //statusTEPtr->destRect.right = pr.right - 16; 183 | //statusTEPtr->viewRect.right = pr.right; 184 | destRect.bottom = viewRect.top + 12; 185 | viewRect.bottom = pr.bottom; 186 | //viewRect.right = destRect.right = pr.right - 16; 187 | //destRect.right = pr.right - 16; 188 | //viewRect.right = pr.right; 189 | 190 | statusTE = TENew(&destRect, &viewRect); 191 | (*statusTE)->txSize = 9; 192 | (*statusTE)->lineHeight = 12; 193 | (*statusTE)->fontAscent = 9; 194 | (*statusTE)->crOnly = -1; 195 | //TESetText("Statusy", 7, statusTE); 196 | //InvalRect(&viewRect); 197 | pWin->statusTE = statusTE; 198 | 199 | //PageWindowSetStatus(pWin, "Statusy the status is good because it is a good status and here it is."); 200 | 201 | // Scrollbar 202 | scrollRect.left = pr.right - 15; 203 | scrollRect.top = pr.top - 1; 204 | scrollRect.right = pr.right + 1; 205 | scrollRect.bottom = viewRect.bottom; 206 | pWin->vScrollBar = NewControl(window, &scrollRect, "\p", true, 0, 0, 207 | scrollRect.bottom - scrollRect.top, 16, 1L); 208 | //pWin->vScrollBar = vScrollBar; 209 | //PageWindowAdjustScrollBars(pWin); 210 | 211 | /*pWin->toolbarBackBtn = NewControl(window, &toolbarRectBack, "\p", true, 212 | 0, 0, 0, pushButProc, navBtn);*/ 213 | 214 | SetWRefCon(window, (long) pWin); 215 | //SetWTitle(window, name); 216 | pWin->window = window; 217 | pWin->location = ""; 218 | pWin->focusTE = NULL; 219 | pWin->history = NULL; 220 | pWin->isLoading = false; 221 | pWin->document = NULL; 222 | pWin->uri = NULL; 223 | 224 | FrameAddressBar(pWin); 225 | PageWindowAdjustScrollBars(pWin); 226 | DrawToolbarButtons(pWin); 227 | 228 | return pWin; 229 | } 230 | 231 | void DrawToolbarButtons(PageWindow *pWin) { 232 | SICNHand iconsActive = (SICNHand) GetResource('SICN', toolbarIconsSICN); 233 | SICNHand iconsDisabled = (SICNHand) GetResource('SICN', toolbarIconsDisabledSICN); 234 | HistoryItem *history = pWin->history; 235 | 236 | SetPort(pWin->window); 237 | //EraseRect(&toolbarButtonsRect); 238 | 239 | PlotSICN(&toolbarRectBack, history && history->prev ? iconsActive : iconsDisabled, iconBack); 240 | PlotSICN(&toolbarRectForward, history && history->next ? iconsActive : iconsDisabled, iconForward); 241 | PlotSICN(&toolbarRectHome, iconsActive, iconHome); 242 | PlotSICN(&toolbarRectStopRefresh, 243 | pWin->isLoading || history ? iconsActive : iconsDisabled, 244 | pWin->isLoading ? iconStop : iconRefresh); 245 | } 246 | 247 | void UpdatePageWindow(PageWindow *pWin) { 248 | WindowPtr win = pWin->window; 249 | Rect pr = win->portRect; 250 | Rect updateRect = (*win->visRgn)->rgnBBox; 251 | SetPort(win); 252 | //EraseRect(&updateRect); 253 | PageWindowDrawGrowIcon(pWin); 254 | 255 | if (RectInRgn(&(*(pWin->statusTE))->viewRect, win->visRgn)) { 256 | EraseRect(&(*(pWin->statusTE))->viewRect); 257 | } 258 | 259 | //(*(pWin->addressBarTE))->viewRect.right = pr.right - pr.left - 7; 260 | TEUpdate(&updateRect, pWin->addressBarTE); 261 | TEUpdate(&updateRect, pWin->contentTE); 262 | TEUpdate(&updateRect, pWin->statusTE); 263 | FrameAddressBar(pWin); 264 | 265 | UpdateControls(win, win->visRgn); 266 | 267 | if (RectInRgn(&toolbarButtonsRect, win->visRgn)) { 268 | DrawToolbarButtons(pWin); 269 | } 270 | 271 | //DrawDOMDocument(pWin->DOMDocument); 272 | } 273 | 274 | void PageWindowActivate(PageWindow *pWin) { 275 | WindowPtr win = pWin->window; 276 | ControlHandle ch; 277 | 278 | //SetPort(win); 279 | PageWindowDrawGrowIcon(pWin); 280 | if (pWin->focusTE) { 281 | TEActivate(pWin->focusTE); 282 | } 283 | //FrameAddressBar(pWin); 284 | //HiliteControl(pWin->vScrollBar, 0); 285 | 286 | for (ch = (ControlHandle) ((WindowPeek)(win))->controlList; 287 | ch != nil; 288 | ch = (*ch)->nextControl) { 289 | ShowControl(ch); 290 | } 291 | } 292 | 293 | void PageWindowDeactivate(PageWindow *pWin) { 294 | WindowPtr win = pWin->window; 295 | ControlHandle ch; 296 | 297 | //SetPort(win); 298 | //PageWindowDrawGrowIcon(pWin); 299 | if (pWin->focusTE) { 300 | TEDeactivate(pWin->focusTE); 301 | } 302 | //HiliteControl(pWin->vScrollBar, 255); 303 | 304 | //HideControl(pWin->vScrollBar); 305 | 306 | ch = (ControlHandle) ((WindowPeek)(win))->controlList; 307 | while (ch != nil) { 308 | HideControl(ch); 309 | ch = (*ch)->nextControl; 310 | } 311 | PageWindowDrawGrowIcon(pWin); 312 | } 313 | 314 | void PageWindowIdle(PageWindow *pWin) { 315 | WindowPtr win = pWin->window; 316 | //ControlHandle ch; 317 | Point mouse; 318 | Cursor *cursor; 319 | 320 | if (pWin->focusTE && (pWin->focusTE != pWin->contentTE)) { 321 | TEIdle(pWin->focusTE); 322 | } 323 | 324 | //SetPort(win); 325 | GetMouse(&mouse); 326 | SetPort(win); 327 | 328 | //if (FindControl(mouse, win, &ch)) 329 | 330 | if (PtInRect(mouse, &(*(pWin->addressBarTE))->viewRect)) { 331 | cursor = *GetCursor(iBeamCursor); 332 | } else if (PtInRect(mouse, &(*(pWin->contentTE))->viewRect)) { 333 | cursor = *GetCursor(iBeamCursor); 334 | } else { 335 | //PageWindowKeyDown(pWin, 'a'); 336 | // if (mouse is over ) cursor = handCursor; 337 | cursor = &qd.arrow; 338 | } 339 | SetCursor(cursor); 340 | } 341 | 342 | void PageWindowAdjustScrollBars(PageWindow *pWin) { 343 | short h; 344 | Rect pr = pWin->window->portRect; 345 | MoveControl(pWin->vScrollBar, pr.right - 15, -1 + toolbarHeight); 346 | SizeControl(pWin->vScrollBar, 16, (pr.bottom - pr.top) - 13 - toolbarHeight); 347 | h = TEGetHeight((*pWin->contentTE)->nLines, 1, pWin->contentTE); 348 | //SetCtlMax(pWin->vScrollBar, h); 349 | (*pWin->vScrollBar)->contrlMax = h; 350 | } 351 | 352 | void PageWindowResized(PageWindow *pWin, Rect oldPort) { 353 | Rect pr = pWin->window->portRect, r; 354 | TEPtr addressBarTEPtr = *(pWin->addressBarTE); 355 | TEPtr contentTEPtr = *(pWin->contentTE); 356 | TEPtr statusTEPtr = *(pWin->statusTE); 357 | addressBarTEPtr->viewRect.right = pr.right - pr.left - 7; 358 | contentTEPtr->viewRect.bottom = pr.bottom /*- pr.top*/ - statusBarHeight; 359 | contentTEPtr->viewRect.right = pr.right - 15; 360 | 361 | //statusTEPtr->viewRect.top = statusTEPtr->destRect.top = pr.bottom - statusBarHeight + 4; 362 | statusTEPtr->destRect.top = pr.bottom - statusBarHeight + 2; 363 | statusTEPtr->viewRect.top = statusTEPtr->destRect.top - 1; 364 | //statusTEPtr->viewRect.bottom = statusTEPtr->destRect.bottom = statusTEPtr->viewRect.top + 12; 365 | statusTEPtr->destRect.bottom = statusTEPtr->viewRect.top + 12; 366 | statusTEPtr->viewRect.bottom = pr.bottom; 367 | statusTEPtr->viewRect.right = statusTEPtr->destRect.right = pr.right - 15; 368 | 369 | InvalRect(&contentTEPtr->viewRect); 370 | EraseRect(&contentTEPtr->viewRect); 371 | 372 | EraseRect(&statusTEPtr->viewRect); 373 | InvalRect(&statusTEPtr->viewRect); 374 | 375 | PageWindowAdjustScrollBars(pWin); 376 | //PageWindowSetStatus(pWin, "asdfgasdfasdfy"); 377 | 378 | r.left = (pr.right < oldPort.right ? pr.right : oldPort.right) - 8; 379 | r.right = pr.right; 380 | r.top = 0; 381 | r.bottom = toolbarHeight; 382 | EraseRect(&r); 383 | InvalRect(&r); 384 | 385 | //SetPort(pWin->window); 386 | } 387 | 388 | void PageWindowFocusTE(PageWindow *pWin, TEHandle te) { 389 | if (te != pWin->focusTE) { 390 | if (pWin->focusTE) { 391 | TEDeactivate(pWin->focusTE); 392 | } 393 | if (te) { 394 | TEActivate(te); 395 | } 396 | pWin->focusTE = te; 397 | } 398 | } 399 | 400 | void PageWindowMouseDown(PageWindow *pWin, Point where, int modifiers) { 401 | TEHandle te = NULL; 402 | ControlHandle ch; 403 | unsigned short part; 404 | int oldValue, delta; 405 | 406 | GlobalToLocal(&where); 407 | SetPort(pWin->window); 408 | 409 | part = (short)FindControl(where, pWin->window, &ch); 410 | if (!part) { 411 | if (PtInRect(where, &toolbarButtonsRect)) { 412 | HandleNavButtonClick(pWin, where); 413 | } else if (PtInRect(where, &((*(te = pWin->addressBarTE))->viewRect))) { 414 | // click in address bar 415 | //te = pWin->addressBarTE; 416 | PageWindowFocusTE(pWin, te); 417 | TEClick(where, (modifiers & shiftKey) != 0, te); 418 | } else if (PtInRect(where, &((*(te = pWin->contentTE))->viewRect))) { 419 | // click in page context text 420 | //te = pWin->contentTE; 421 | PageWindowFocusTE(pWin, te); 422 | TEClick(where, (modifiers & shiftKey) != 0, te); 423 | // hide insertion point 424 | if ((*te)->selStart == (*te)->selEnd) { 425 | TEDeactivate(te); 426 | pWin->focusTE = NULL; 427 | } 428 | } 429 | } else { 430 | switch(part) { 431 | // Form element 432 | case kControlButtonPart: 433 | //if (TrackControl(ch, where, 0)) { 434 | //if (where.top < toolbarHeight) { 435 | break; 436 | case kControlCheckBoxPart: 437 | break; 438 | 439 | // Scroll bar 440 | case kControlIndicatorPart: 441 | oldValue = GetControlValue(ch); 442 | if (TrackControl(ch, where, 0)) { 443 | delta = oldValue - GetControlValue(ch); 444 | if (delta) { 445 | if (ch == pWin->vScrollBar) { 446 | Scroll(pWin, 0, delta); 447 | } else { 448 | Scroll(pWin, delta, 0); 449 | } 450 | } 451 | } 452 | break; 453 | case kControlUpButtonPart: 454 | case kControlDownButtonPart: 455 | case kControlPageUpPart: 456 | case kControlPageDownPart: 457 | TrackControl(ch, where, ScrollAction); 458 | break; 459 | } 460 | } 461 | } 462 | 463 | pascal void ScrollAction(ControlHandle control, short part) { 464 | WindowPtr win = (*control)->contrlOwner; 465 | PageWindow *pWin = GetPageWindow(win); 466 | short delta, page, ex; 467 | Boolean isH; 468 | Rect r = (*control)->contrlRect; 469 | Rect wr = (*(pWin->contentTE))->viewRect; //pWin->window->portRect 470 | static unsigned long lastTicks; 471 | 472 | if (TickCount()-lastTicks < 4) return; 473 | else lastTicks = TickCount(); 474 | isH = r.right-r.left > r.bottom-r.top; 475 | //page = (isH ? RoundDiv(r.right-r.left, win->hPitch) 476 | //: RoundDiv(r.bottom-r.top, win->vPitch))-1; 477 | page = isH ? wr.right-wr.left : wr.bottom-wr.top; 478 | switch(part) { 479 | case kControlUpButtonPart: delta = 16; break; 480 | case kControlDownButtonPart: delta = -16; break; 481 | case kControlPageUpPart: delta = page; break; 482 | case kControlPageDownPart: delta = -page; break; 483 | default: delta = 0; 484 | } 485 | ex = GetControlValue(control) + delta; 486 | SetControlValue(control, ex); 487 | if (delta) { 488 | if (isH) 489 | Scroll(pWin, delta, 0); 490 | else 491 | Scroll(pWin, 0, delta); 492 | //PageWindowUpdate(pWin); 493 | } 494 | } 495 | 496 | void Scroll(PageWindow *pWin, int h, int v) { 497 | TEPinScroll(h, v, pWin->contentTE); 498 | } 499 | 500 | void HandleNavButtonClick(PageWindow *pWin, /*ControlHandle ch, */Point where) { 501 | Rect *r;// = (*ch)->contrlRect; 502 | Boolean hit = false; 503 | int i = 0; 504 | EventRecord evt; 505 | RgnHandle mouseRgn = NewRgn(); 506 | Boolean btnHasMenu; 507 | 508 | /*short i; 509 | for (i=0; *i; i++) { 510 | if (PtInRect(where, toolbarRects[i])) { 511 | r = toolbarRects[i]; 512 | } 513 | }*/ 514 | if (PtInRect(where, &toolbarRectBack)) { 515 | if (!pWin->history->prev) return; 516 | r = &toolbarRectBack; 517 | } else if (PtInRect(where, &toolbarRectForward)) { 518 | if (!pWin->history->next) return; 519 | r = &toolbarRectForward; 520 | } else if (PtInRect(where, &toolbarRectHome)) { 521 | r = &toolbarRectHome; 522 | } else if (PtInRect(where, &toolbarRectStopRefresh)) { 523 | if (!pWin->isLoading && !pWin->history) return; 524 | r = &toolbarRectStopRefresh; 525 | } 526 | RectRgn(mouseRgn, r); 527 | //if (GetControlReference(ch) != navBtn) return; 528 | //if (!TrackControl(ch, where, nil)) return; 529 | //if (ch == pWin->toolbarBackBtn) { 530 | btnHasMenu = (r == &toolbarRectBack || r == &toolbarRectForward); 531 | do { 532 | GetMouse(&where); 533 | if (PtInRect(where, r)) { 534 | if (!hit) { 535 | hit = true; 536 | InvertRect(r); 537 | } 538 | if (btnHasMenu && (i > 8)) { 539 | PopupNavMenu(pWin, r); 540 | InvertRect(r); 541 | return; 542 | } 543 | } else { 544 | if (btnHasMenu) { 545 | PopupNavMenu(pWin, r); 546 | InvertRect(r); 547 | return; 548 | } 549 | if (hit) { 550 | hit = false; 551 | InvertRect(r); 552 | } 553 | } 554 | WNE(mUpMask | app4Mask, &evt, 10L, mouseRgn); 555 | i++; 556 | } while (Button()); 557 | 558 | if (hit) { 559 | InvertRect(r); 560 | if (r == &toolbarRectBack) { 561 | PageWindowNavigateHistory(pWin, -1); 562 | } else if (r == &toolbarRectForward) { 563 | PageWindowNavigateHistory(pWin, 1); 564 | } else if (r == &toolbarRectHome) { 565 | PageWindowNavigateHome(pWin); 566 | } else if (r == &toolbarRectStopRefresh) { 567 | if (pWin->isLoading) { 568 | // stop 569 | PageWindowStop(pWin); 570 | } else { 571 | // refresh 572 | PageWindowNavigateHistory(pWin, 0); 573 | } 574 | } else { 575 | ErrorAlert("Unknown button pressed."); 576 | } 577 | } 578 | } 579 | 580 | /* I couldn't get AppendMenuItemText to work in 68k. 581 | This version takes a c string instead of pascal string.*/ 582 | void MyAppendMenuItemText(MenuHandle menuH, char *itemText) { 583 | /*Str255 ptext; 584 | CtoP(itemText, ptext); 585 | AppendMenu(menuH, ptext);*/ 586 | static const char *metaChars = ";^!menuData; 588 | short menuTitleLength = menuData[0]; 589 | Ptr menuItemData = menuData + menuTitleLength + 1; 590 | //Handle menuDataH = RecoverHandle(menuData); 591 | short menuItems = CountMItems(menuH)+1; 592 | short i = 0; 593 | Str255 sanitizedText; 594 | char replacedChars[255]; 595 | short itemLength = strlen(itemText); 596 | memset(replacedChars, 0, 255); 597 | memcpy(sanitizedText+1, itemText, itemLength); 598 | sanitizedText[0] = itemLength; 599 | //CtoP(itemText, sanitizedText); 600 | // Strip out metacharacters 601 | while (itemText[i] 602 | && ((i += strcspn(itemText+i, metaChars)+1)) 603 | && ihistory; 632 | //Str255 menuItemData; 633 | char *menuText; 634 | //short len; 635 | short choice; 636 | Point pt; 637 | 638 | while (curr = (back ? curr->prev : curr->next), curr) { 639 | menuText = curr->title ? curr->title : curr->address; 640 | MyAppendMenuItemText(menuH, menuText); 641 | } 642 | 643 | //PageWindowSaveAs(pWin, 256, (Ptr)(*menuH)->menuData); 644 | 645 | SetPt(&pt, buttonRect->left, buttonRect->bottom); 646 | LocalToGlobal(&pt); 647 | InsertMenu(menuH, -1); 648 | choice = PopUpMenuSelect(menuH, pt.v, pt.h, 0) & 0xffff; 649 | if (choice) { 650 | PageWindowNavigateHistory(pWin, back ? -choice : choice); 651 | } 652 | DeleteMenu(navMenuPopupIds + back); 653 | SetPort(pWin->window); 654 | } 655 | 656 | void PageWindowStop(PageWindow *pWin) { 657 | if (pWin->uri) { 658 | URIClose(pWin->uri); 659 | // free? 660 | pWin->uri = NULL; 661 | LoadingEnded(pWin); 662 | } 663 | } 664 | 665 | void PageWindowNavigate(PageWindow *pWin, char *location) { 666 | HistoryItem *historyItem; 667 | char *newLocation = url_sanitize(location); 668 | short len; 669 | if (!newLocation) { 670 | ErrorAlert("Unable to copy URI"); 671 | return; 672 | } 673 | 674 | len = strlen(newLocation); 675 | 676 | TESetText(newLocation, len, pWin->addressBarTE); 677 | InvalRect(&(*pWin->addressBarTE)->viewRect); 678 | 679 | // don't put a new history item for the same address 680 | if (!pWin->history || 681 | strncmp(newLocation, pWin->history->address, len+1) != 0) { 682 | historyItem = HistoryItemNewNext(pWin->history); 683 | if (historyItem) { 684 | historyItem->address = newLocation; 685 | //historyItem->title = "Title"; 686 | pWin->history = historyItem; 687 | //PageWindowSetStatus(pWin, pWin->location); 688 | } 689 | } 690 | 691 | // redraw buttons 692 | InvalRect(&toolbarButtonsRect); 693 | 694 | // cancel previous request 695 | PageWindowStop(pWin); 696 | 697 | pWin->uri = NewURI(newLocation); 698 | if (!pWin->uri) { 699 | ErrorAlert("Unable to create URI request."); 700 | return; 701 | } 702 | URIConsume(pWin->uri, &PageURIConsumer, pWin); 703 | URIGet(pWin->uri); 704 | } 705 | 706 | /* 707 | void RecievePageData(URIRequest* req) { 708 | PageWindow *pWin = (PageWindow *)req->refCon; 709 | URIResponse *resp = req->response; 710 | if (resp->offset == 0) { 711 | // started loading. 712 | pWin->location = pWin->history->address; 713 | LoadingStarted(pWin); 714 | if (pWin->document) { 715 | DisposeDOMDocument(pWin->document); 716 | } 717 | pWin->document = NewDOMDocument(); 718 | } 719 | if (req->state == stateComplete) { 720 | // done loading 721 | LoadingEnded(pWin); 722 | } 723 | 724 | /* 725 | HLock(resp->contentHandle); 726 | DOMDocumentParseAppend(pWin->document, *resp->contentHandle + resp->offset, 727 | resp->length); 728 | HUnlock(resp->contentHandle); 729 | * / 730 | PageWindowAdjustScrollBars(pWin); 731 | 732 | TESetText(*(resp->contentHandle), resp->length, pWin->contentTE); 733 | 734 | InvalRect(&(*pWin->contentTE)->viewRect); 735 | EraseRect(&(*pWin->contentTE)->viewRect); 736 | //TEUpdate(&(*pWin->contentTE)->viewRect, pWin->contentTE); 737 | } 738 | */ 739 | 740 | // delete items after given item, and replace with new one. 741 | HistoryItem *HistoryItemNewNext(HistoryItem *base) { 742 | HistoryItem *curr, *next, *newNext; 743 | newNext = (HistoryItem *)malloc(sizeof(HistoryItem)); 744 | if (!newNext) { 745 | ErrorAlert("Unable to create history item."); 746 | return NULL; 747 | } 748 | newNext->address = NULL; 749 | newNext->title = NULL; 750 | newNext->prev = base; 751 | newNext->next = NULL; 752 | if (base != NULL) { 753 | for (curr = base->next; curr; curr = next) { 754 | next = curr->next; 755 | if (curr->address) free(curr->address); 756 | if (curr->title) free(curr->title); 757 | free(curr); 758 | } 759 | base->next = newNext; 760 | } 761 | return newNext; 762 | } 763 | 764 | void PageWindowKeyDown(PageWindow *pWin, char theChar) { 765 | char *location; 766 | TEPtr te; 767 | if (!pWin->focusTE) return; 768 | te = *pWin->focusTE; 769 | 770 | if (pWin->focusTE == pWin->contentTE) { 771 | } else if (pWin->focusTE == pWin->addressBarTE) { 772 | switch(theChar) { 773 | case '\r': 774 | case '\n': 775 | case 3: // enter 776 | // go to the address 777 | if (te->teLength == 0 && pWin->history) { 778 | // Put back current address 779 | location = pWin->history->address; 780 | TESetText(location, strlen(location), pWin->addressBarTE); 781 | InvalRect(&te->viewRect); 782 | } else { 783 | size_t len = te->teLength; 784 | location = (char *) malloc((len + 1) * sizeof(char)); 785 | strncpy(location, *te->hText, len); 786 | location[len] = '\0'; 787 | 788 | PageWindowNavigate(pWin, location); 789 | free(location); 790 | } 791 | break; 792 | case 27: // delete 793 | // unprintable 794 | break; 795 | case 11: // page up 796 | case 1: // home 797 | // up arrow 798 | TEKey(30, pWin->addressBarTE); 799 | break; 800 | case 12: // page down 801 | case 4: // end 802 | // down arrow 803 | TEKey(31, pWin->addressBarTE); 804 | break; 805 | case 127: // forward delete 806 | if (te->selStart != te->teLength) { 807 | TEKey(29, pWin->addressBarTE); // right 808 | TEKey(8, pWin->addressBarTE); // delete 809 | } 810 | break; 811 | default: 812 | // regular character 813 | TEKey(theChar, pWin->addressBarTE); 814 | } 815 | } else { 816 | if (theChar == '\r') { 817 | // todo: find and submit form 818 | } else { 819 | TEKey(theChar, pWin->focusTE); 820 | } 821 | } 822 | } 823 | 824 | void FrameAddressBar(PageWindow *pWin) { 825 | Rect frame = (*(pWin->addressBarTE))->viewRect; 826 | frame.left -= 3; 827 | frame.top -= 3; 828 | frame.right += 3; 829 | frame.bottom += 2; 830 | SetPort(pWin->window); 831 | FrameRect(&frame); 832 | } 833 | 834 | void PageWindowSetStatus(PageWindow *pWin, char *status) { 835 | //(*pWin->statusTE)->hText = &status; 836 | //TECalText(pWin->statusTE); 837 | TESetText(status, strlen(status), pWin->statusTE); 838 | InvalRect(&(*pWin->statusTE)->viewRect); 839 | } 840 | 841 | void PageWindowDrawGrowIcon(PageWindow *pWin) { 842 | Rect r = pWin->window->portRect; 843 | RgnHandle oldClip = pWin->window->clipRgn; 844 | SetPort(pWin->window); 845 | 846 | r.top = toolbarHeight - 1; 847 | 848 | pWin->window->clipRgn = NewRgn(); 849 | ClipRect(&r); 850 | DrawGrowIcon(pWin->window); 851 | DisposeRgn(pWin->window->clipRgn); 852 | pWin->window->clipRgn = oldClip; 853 | 854 | // Draw toolbar line 855 | MoveTo(0, toolbarHeight - 1); 856 | Line(r.right - r.left, 0); 857 | } 858 | 859 | void PageWindowOpenFile(PageWindow *pWin) { 860 | short modifiers = 0; // todo 861 | SFTypeList tl; 862 | short numTypes; 863 | SFReply reply; 864 | char *pathName; 865 | char *encodedPathName; 866 | char uri[256] = "file:///"; 867 | 868 | Point where; 869 | Rect *rp = &qd.screenBits.bounds; 870 | where.h = (rp->right - rp->left) - 348; 871 | where.v = (rp->bottom - rp->top) - 136; 872 | where.h >>= 1; 873 | where.v >>= 2; 874 | 875 | if (modifiers & optionKey) 876 | numTypes = -1; 877 | else { 878 | numTypes = 2; 879 | tl[0] = 'TEXT'; 880 | tl[1] = 'HTML'; 881 | } 882 | SFGetFile(where, "\pOpen...", NULL, numTypes, tl, nil, &reply); 883 | if (reply.good) { 884 | //char blah[255]; 885 | short len; 886 | if (!pWin) { 887 | pWin = NewPageWindow(); 888 | } 889 | 890 | pathName = GetFilePathName(reply.vRefNum, reply.fName); 891 | encodedPathName = url_encode(pathName); 892 | if (!encodedPathName) { 893 | alertf("Unable to convert file name"); 894 | DisposePtr(pathName); 895 | return; 896 | } 897 | strncat(uri, encodedPathName, sizeof uri); 898 | 899 | free(encodedPathName); 900 | DisposePtr(pathName); 901 | 902 | PageWindowNavigate(pWin, uri); 903 | } 904 | } 905 | 906 | void PageWindowSaveAs(PageWindow *pWin) { 907 | short refNum; 908 | OSErr oe; 909 | SFReply reply; 910 | StringPtr fileName; 911 | Point where; 912 | Rect *rp = &qd.screenBits.bounds; 913 | //Str255 loc = "\pabcdefghijklmnopqrstuvwxyz"; 914 | long bytes = 5; 915 | Ptr buffer; 916 | 917 | where.h = (rp->right - rp->left) - 348; 918 | where.v = (rp->bottom - rp->top) - 136; 919 | where.h >>= 1; 920 | where.v >>= 2; 921 | 922 | //GetFilename(pWin, fileName); 923 | /* 924 | ParamText("\pNot yet implemented.","\p","\p","\p"); 925 | StopAlert(129, NULL); 926 | */ 927 | 928 | //BlockMove(pWin->location, loc+1, strlen(pWin->location)); 929 | //loc[0] = strlen(pWin->location)+1; 930 | //ParamText("\pLocation:",loc,"\p","\p"); 931 | //StopAlert(129, NULL); 932 | 933 | fileName = CtoPCopy(getFilePathFileName(pWin->location)); 934 | //PageWindowSetStatus(pWin, fileName); 935 | SFPutFile(where, "\pSave As...", fileName, NULL, &reply); 936 | DisposePtr(fileName); 937 | if (!reply.good) { 938 | return; 939 | } 940 | 941 | //oe = SFPutOpen(reply.fName, reply.vRefNum, 'WWW6', 'TEXT', &refNum, NULL, NULL); 942 | oe = Create(reply.fName, reply.vRefNum, 'WWW6', 'TEXT'); 943 | if (oe != noErr) { 944 | alertf("Unable to create file. %u", oe); 945 | return; 946 | } 947 | oe = FSOpen(reply.fName, reply.vRefNum, &refNum); 948 | if (oe != noErr) { 949 | ParamText("\pUnable to save file.","\p","\p","\p"); 950 | StopAlert(129, NULL); 951 | //PageWindowSetStatus(pWin, errStr); 952 | return; 953 | } 954 | oe = SetFPos(refNum, fsFromStart, 0); 955 | if (oe != noErr) { 956 | ParamText("\pUnable to save file!","\p","\p","\p"); 957 | StopAlert(129, NULL); 958 | return; 959 | } 960 | // todo 961 | buffer = "abcde"; 962 | oe = FSWrite(refNum, &bytes, buffer); 963 | if (oe != noErr) { 964 | ParamText("\pUnable to write file.","\p","\p","\p"); 965 | StopAlert(129, NULL); 966 | return; 967 | } 968 | FSClose(refNum); 969 | } 970 | 971 | void PageWindowNavigateHome(PageWindow *pWin) { 972 | //char *home = "http://192.168.1.128/stuff/election/2011candidates.html"; 973 | //char *home = "file:///Macintosh HD/DOMDocuments/Browsy/page.html"; 974 | //char *home = "about:Browsy"; 975 | char *home = "about:stuff"; 976 | //char *home = "file:///Macintosh HD/asdf.txt"; 977 | //char *home = "file:///Untitled/Browsy"; 978 | //char *home = "file:///Launcher/page.html"; 979 | 980 | //"http://www.lehnerstudios.com/newsite/"; 981 | // GetPrefStr(prefHomePage, home); 982 | PageWindowNavigate(pWin, home); 983 | } 984 | 985 | void PageWindowNavigateHistory(PageWindow *pWin, short amount) { 986 | HistoryItem *curr = pWin->history; 987 | short i = 1; 988 | // amount=0 for refresh 989 | if (curr == NULL) { 990 | i = 0; 991 | } else if (amount < 0) { 992 | // Back 993 | for (i=0; i>amount && curr->prev; i--) { 994 | curr = curr->prev; 995 | } 996 | pWin->history = curr; 997 | } else if (amount > 0) { 998 | // Forward 999 | for (i=0; inext; i++) { 1000 | curr = curr->next; 1001 | } 1002 | pWin->history = curr; 1003 | } 1004 | if (i == 0) { 1005 | SysBeep(5); 1006 | } else { 1007 | PageWindowNavigate(pWin, curr->address); 1008 | } 1009 | } 1010 | 1011 | void DebugSave(long bytes, Ptr buffer) { 1012 | short refNum; 1013 | OSErr oe; 1014 | SFReply reply; 1015 | Point where; 1016 | Rect *rp = &qd.screenBits.bounds; 1017 | //Str255 loc = "\pabcdefghijklmnopqrstuvwxyz"; 1018 | 1019 | where.h = (rp->right - rp->left) - 348; 1020 | where.v = (rp->bottom - rp->top) - 136; 1021 | where.h >>= 1; 1022 | where.v >>= 2; 1023 | 1024 | ErrorAlert("Files not currently supported."); 1025 | /* 1026 | 1027 | SFPutFile(where, "\pSave As...", "\pdebug", NULL, &reply); 1028 | if (!reply.good) { 1029 | return; 1030 | } 1031 | //oe = SFPutOpen(reply.fName, reply.vRefNum, 'WWW6', 'TEXT', &refNum, NULL, NULL); 1032 | oe = Create(reply.fName, reply.vRefNum, 'WWW6', 'TEXT'); 1033 | /*if (oe != noErr) { 1034 | ParamText("\pUnable to save file.","\p","\p","\p"); 1035 | StopAlert(129, NULL); 1036 | return; 1037 | }* / 1038 | oe = FSOpen(reply.fName, reply.vRefNum, &refNum); 1039 | if (oe != noErr) { 1040 | ParamText("\pUnable to save file.","\p","\p","\p"); 1041 | StopAlert(129, NULL); 1042 | return; 1043 | } 1044 | oe = SetFPos(refNum, fsFromStart, 0); 1045 | if (oe != noErr) { 1046 | ParamText("\pUnable to save file!","\p","\p","\p"); 1047 | StopAlert(129, NULL); 1048 | return; 1049 | } 1050 | oe = FSWrite(refNum, &bytes, buffer); 1051 | if (oe != noErr) { 1052 | ParamText("\pUnable to write file.","\p","\p","\p"); 1053 | StopAlert(129, NULL); 1054 | return; 1055 | } 1056 | FSClose(refNum); 1057 | */ 1058 | } 1059 | 1060 | void LoadingStarted(PageWindow *pWin) { 1061 | pWin->isLoading = true; 1062 | DrawToolbarButtons(pWin); 1063 | } 1064 | 1065 | void LoadingEnded(PageWindow *pWin) { 1066 | pWin->isLoading = false; 1067 | DrawToolbarButtons(pWin); 1068 | } 1069 | 1070 | // URI consumer callbacks 1071 | 1072 | void PageURIOnStatus(void *obj, short httpStatus) 1073 | { 1074 | PageWindow *pWin = (PageWindow *)obj; 1075 | pWin->location = pWin->history->address; 1076 | LoadingStarted(pWin); 1077 | if (pWin->document) { 1078 | DisposeDOMDocument(pWin->document); 1079 | } 1080 | pWin->document = NewDOMDocument(); 1081 | InvalRect(&(*pWin->contentTE)->viewRect); 1082 | EraseRect(&(*pWin->contentTE)->viewRect); 1083 | 1084 | static char statusBuf[128]; 1085 | snprintf(statusBuf, sizeof(statusBuf), "status: %hu", httpStatus); 1086 | PageWindowSetStatus(pWin, statusBuf); 1087 | } 1088 | 1089 | void PageURIOnHeader(void *obj, HTTPHeader *header) 1090 | { 1091 | PageWindow *pWin = (PageWindow *)obj; 1092 | switch (header->name) { 1093 | case httpContentType: 1094 | //alertf("Got content type: %s", header->value); 1095 | break; 1096 | case httpContentLength: 1097 | //alertf("Got content length: %s", header->value); 1098 | break; 1099 | } 1100 | } 1101 | 1102 | void PageURIOnHeadersComplete(void *obj) 1103 | { 1104 | } 1105 | 1106 | void PageURIOnMessageBegin(void *obj) 1107 | { 1108 | PageWindow *pWin = (PageWindow *)obj; 1109 | TESetText("", 0, pWin->contentTE); 1110 | } 1111 | 1112 | void PageURIOnData(void *obj, char *data, short len) 1113 | { 1114 | PageWindow *pWin = (PageWindow *)obj; 1115 | //DOMDocumentParseAppend(pWin->document, data, len); 1116 | 1117 | //PageWindowAdjustScrollBars(pWin); 1118 | 1119 | TEAppendText(data, len, pWin->contentTE); 1120 | 1121 | InvalRect(&(*pWin->contentTE)->viewRect); 1122 | EraseRect(&(*pWin->contentTE)->viewRect); 1123 | } 1124 | 1125 | void PageURIOnClose(void *obj, short err) 1126 | { 1127 | PageWindow *pWin = (PageWindow *)obj; 1128 | LoadingEnded(pWin); 1129 | } 1130 | --------------------------------------------------------------------------------