From a31e4f61a4c9afb9696a7ff4ff09e02b3281a2f3 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 20 Sep 2011 00:38:28 +0200 Subject: [PATCH] uhtml: add html to unicode converter, used by mothra and page/html2ms --- sys/src/cmd/html2ms.c | 93 ++--------- sys/src/cmd/mothra/html.h | 2 - sys/src/cmd/mothra/html.syntax.c | 269 ------------------------------- sys/src/cmd/mothra/mkfile | 2 +- sys/src/cmd/mothra/mothra.c | 5 +- sys/src/cmd/mothra/rdhtml.c | 118 ++------------ sys/src/cmd/page.c | 2 +- sys/src/cmd/uhtml.c | 121 ++++++++++++++ 8 files changed, 154 insertions(+), 458 deletions(-) create mode 100644 sys/src/cmd/uhtml.c diff --git a/sys/src/cmd/html2ms.c b/sys/src/cmd/html2ms.c index 229836216..fd175d72f 100644 --- a/sys/src/cmd/html2ms.c +++ b/sys/src/cmd/html2ms.c @@ -296,79 +296,6 @@ parsetag(Tag *t) return n > 0; } -struct { - char *entity; - Rune rune; -} entities[] = { - "AElig", 198, "Aacute", 193, "Acirc", 194, "Agrave", 192, - "Alpha", 913, "Aring", 197, "Atilde", 195, "Auml", 196, - "Beta", 914, "Ccedil", 199, "Chi", 935, "Dagger", 8225, - "Delta", 916, "ETH", 208, "Eacute", 201, "Ecirc", 202, - "Egrave", 200, "Epsilon", 917, "Eta", 919, "Euml", 203, - "Gamma", 915, "Iacute", 205, "Icirc", 206, "Igrave", 204, - "Iota", 921, "Iuml", 207, "Kappa", 922, "Lambda", 923, - "Mu", 924, "Ntilde", 209, "Nu", 925, "OElig", 338, - "Oacute", 211, "Ocirc", 212, "Ograve", 210, "Omega", 937, - "Omicron", 927, "Oslash", 216, "Otilde", 213, "Ouml", 214, - "Phi", 934, "Pi", 928, "Prime", 8243, "Psi", 936, - "Rho", 929, "Scaron", 352, "Sigma", 931, "THORN", 222, - "Tau", 932, "Theta", 920, "Uacute", 218, "Ucirc", 219, - "Ugrave", 217, "Upsilon", 933, "Uuml", 220, "Xi", 926, - "Yacute", 221, "Yuml", 376, "Zeta", 918, "aacute", 225, - "acirc", 226, "acute", 180, "aelig", 230, "agrave", 224, - "alefsym", 8501,"alpha", 945, "amp", 38, "and", 8743, - "ang", 8736, "aring", 229, "asymp", 8776, "atilde", 227, - "auml", 228, "bdquo", 8222, "beta", 946, "brvbar", 166, - "bull", 8226, "cap", 8745, "ccedil", 231, "cdots", 8943, - "cedil", 184, "cent", 162, "chi", 967, "circ", 710, - "clubs", 9827, "cong", 8773, "copy", 169, "crarr", 8629, - "cup", 8746, "curren", 164, "dArr", 8659, "dagger", 8224, - "darr", 8595, "ddots", 8945, "deg", 176, "delta", 948, - "diams", 9830, "divide", 247, "eacute", 233, "ecirc", 234, - "egrave", 232, "emdash", 8212, "empty", 8709, "emsp", 8195, - "endash", 8211, "ensp", 8194, "epsilon", 949, "equiv", 8801, - "eta", 951, "eth", 240, "euml", 235, "euro", 8364, - "exist", 8707, "fnof", 402, "forall", 8704, "frac12", 189, - "frac14", 188, "frac34", 190, "frasl", 8260, "gamma", 947, - "ge", 8805, "gt", 62, "hArr", 8660, "harr", 8596, - "hearts", 9829, "hellip", 8230, "iacute", 237, "icirc", 238, - "iexcl", 161, "igrave", 236, "image", 8465, "infin", 8734, - "int", 8747, "iota", 953, "iquest", 191, "isin", 8712, - "iuml", 239, "kappa", 954, "lArr", 8656, "lambda", 955, - "lang", 9001, "laquo", 171, "larr", 8592, "lceil", 8968, - "ldots", 8230, "ldquo", 8220, "le", 8804, "lfloor", 8970, - "lowast", 8727, "loz", 9674, "lrm", 8206, "lsaquo", 8249, - "lsquo", 8216, "lt", 60, "macr", 175, "mdash", 8212, - "micro", 181, "middot", 183, "minus", 8722, "mu", 956, - "nabla", 8711, "nbsp", 160, "ndash", 8211, "ne", 8800, - "ni", 8715, "not", 172, "notin", 8713, "nsub", 8836, - "ntilde", 241, "nu", 957, "oacute", 243, "ocirc", 244, - "oelig", 339, "ograve", 242, "oline", 8254, "omega", 969, - "omicron", 959, "oplus", 8853, "or", 8744, "ordf", 170, - "ordm", 186, "oslash", 248, "otilde", 245, "otimes", 8855, - "ouml", 246, "para", 182, "part", 8706, "permil", 8240, - "perp", 8869, "phi", 966, "pi", 960, "piv", 982, - "plusmn", 177, "pound", 163, "prime", 8242, "prod", 8719, - "prop", 8733, "psi", 968, "quad", 8193, "quot", 34, - "rArr", 8658, "radic", 8730, "rang", 9002, "raquo", 187, - "rarr", 8594, "rceil", 8969, "rdquo", 8221, "real", 8476, - "reg", 174, "rfloor", 8971, "rho", 961, "rlm", 8207, - "rsaquo", 8250, "rsquo", 8217, "sbquo", 8218, "scaron", 353, - "sdot", 8901, "sect", 167, "shy", 173, "sigma", 963, - "sigmaf", 962, "sim", 8764, "sp", 8194, "spades", 9824, - "sub", 8834, "sube", 8838, "sum", 8721, "sup", 8835, - "sup1", 185, "sup2", 178, "sup3", 179, "supe", 8839, - "szlig", 223, "tau", 964, "there4", 8756, "theta", 952, - "thetasym", 977,"thinsp", 8201, "thorn", 254, "tilde", 732, - "times", 215, "trade", 8482, "uArr", 8657, "uacute", 250, - "uarr", 8593, "ucirc", 251, "ugrave", 249, "uml", 168, - "upsih", 978, "upsilon", 965, "uuml", 252, "varepsilon", 8712, - "varphi", 981, "varpi", 982, "varrho", 1009, "vdots", 8942, - "vsigma", 962, "vtheta", 977, "weierp", 8472, "xi", 958, - "yacute", 253, "yen", 165, "yuml", 255, "zeta", 950, - "zwj", 8205, "zwnj", 8204, -}; - Rune parserune(int c) { @@ -379,7 +306,7 @@ parserune(int c) n = 0; if(c == '&'){ while((c = Bgetc(&in)) > 0){ - if(strchr("\n\r\t ;", c)){ + if(strchr(";&\n\r\t ", c)){ if(c != ';') Bungetc(&in); if(n == 0) @@ -391,15 +318,15 @@ parserune(int c) buf[n++] = c; } buf[n] = 0; - if(buf[0] == '#') - return atoi(buf+1); - for(i=0; i'; + if(strcmp(buf, "quot") == 0) + return '"'; + if(strcmp(buf, "amp") == 0) + return '&'; + /* use tcs -f html to handle the rest. */ } else { do { buf[n++] = c; diff --git a/sys/src/cmd/mothra/html.h b/sys/src/cmd/mothra/html.h index f5462ceea..fb2aaabfa 100644 --- a/sys/src/cmd/mothra/html.h +++ b/sys/src/cmd/mothra/html.h @@ -192,8 +192,6 @@ enum{ ERR, /* tag must not occur */ }; Tag tag[]; -Entity pl_entity[]; -int pl_entities; void rdform(Hglob *); void endform(Hglob *); char *pl_getattr(Pair *, char *); diff --git a/sys/src/cmd/mothra/html.syntax.c b/sys/src/cmd/mothra/html.syntax.c index 3001245ef..cfbb1d894 100644 --- a/sys/src/cmd/mothra/html.syntax.c +++ b/sys/src/cmd/mothra/html.syntax.c @@ -69,272 +69,3 @@ Tag tag[]={ [Tag_frame] "frame", NOEND, [Tag_end] 0, ERR, }; -Entity pl_entity[]={ -"AElig", L'Æ', -"Aacute", L'Á', -"Acirc", L'Â', -"Agrave", L'À', -"Alpha", L'Α', -"Aring", L'Å', -"Atilde", L'Ã', -"Auml", L'Ä', -"Beta", L'Β', -"Ccedil", L'Ç', -"Chi", L'Χ', -"Dagger", L'‡', -"Delta", L'Δ', -"ETH", L'Ð', -"Eacute", L'É', -"Ecirc", L'Ê', -"Egrave", L'È', -"Epsilon", L'Ε', -"Eta", L'Η', -"Euml", L'Ë', -"Gamma", L'Γ', -"Iacute", L'Í', -"Icirc", L'Î', -"Igrave", L'Ì', -"Iota", L'Ι', -"Iuml", L'Ï', -"Kappa", L'Κ', -"Lambda", L'Λ', -"Mu", L'Μ', -"Ntilde", L'Ñ', -"Nu", L'Ν', -"OElig", L'Œ', -"Oacute", L'Ó', -"Ocirc", L'Ô', -"Ograve", L'Ò', -"Omega", L'Ω', -"Omicron", L'Ο', -"Oslash", L'Ø', -"Otilde", L'Õ', -"Ouml", L'Ö', -"Phi", L'Φ', -"Pi", L'Π', -"Prime", L'″', -"Psi", L'Ψ', -"Rho", L'Ρ', -"Scaron", L'Š', -"Sigma", L'Σ', -"THORN", L'Þ', -"Tau", L'Τ', -"Theta", L'Θ', -"Uacute", L'Ú', -"Ucirc", L'Û', -"Ugrave", L'Ù', -"Upsilon", L'Υ', -"Uuml", L'Ü', -"Xi", L'Ξ', -"Yacute", L'Ý', -"Yuml", L'Ÿ', -"Zeta", L'Ζ', -"aacute", L'á', -"acirc", L'â', -"acute", L'´', -"aelig", L'æ', -"agrave", L'à', -"alefsym", L'ℵ', -"alpha", L'α', -"amp", L'&', -"and", L'∧', -"ang", L'∠', -"aring", L'å', -"asymp", L'≈', -"atilde", L'ã', -"auml", L'ä', -"bdquo", L'„', -"beta", L'β', -"brvbar", L'¦', -"bull", L'•', -"cap", L'∩', -"ccedil", L'ç', -"cdots", L'⋯', -"cedil", L'¸', -"cent", L'¢', -"chi", L'χ', -"circ", L'ˆ', -"clubs", L'♣', -"cong", L'≅', -"copy", L'©', -"crarr", L'↵', -"cup", L'∪', -"curren", L'¤', -"dArr", L'⇓', -"dagger", L'†', -"darr", L'↓', -"ddots", L'⋱', -"deg", L'°', -"delta", L'δ', -"diams", L'♦', -"divide", L'÷', -"eacute", L'é', -"ecirc", L'ê', -"egrave", L'è', -"emdash", L'—', -"empty", L'∅', -"emsp", L' ', -"endash", L'–', -"ensp", L' ', -"epsilon", L'ε', -"equiv", L'≡', -"eta", L'η', -"eth", L'ð', -"euml", L'ë', -"euro", L'€', -"exist", L'∃', -"fnof", L'ƒ', -"forall", L'∀', -"frac12", L'½', -"frac14", L'¼', -"frac34", L'¾', -"frasl", L'⁄', -"gamma", L'γ', -"ge", L'≥', -"gt", L'>', -"hArr", L'⇔', -"harr", L'↔', -"hearts", L'♥', -"hellip", L'…', -"iacute", L'í', -"icirc", L'î', -"iexcl", L'¡', -"igrave", L'ì', -"image", L'ℑ', -"infin", L'∞', -"int", L'∫', -"iota", L'ι', -"iquest", L'¿', -"isin", L'∈', -"iuml", L'ï', -"kappa", L'κ', -"lArr", L'⇐', -"lambda", L'λ', -"lang", L'〈', -"laquo", L'«', -"larr", L'←', -"lceil", L'⌈', -"ldots", L'…', -"ldquo", L'“', -"le", L'≤', -"lfloor", L'⌊', -"lowast", L'∗', -"loz", L'◊', -"lrm", L'‎', -"lsaquo", L'‹', -"lsquo", L'‘', -"lt", L'<', -"macr", L'¯', -"mdash", L'—', -"micro", L'µ', -"middot", L'·', -"minus", L'−', -"mu", L'μ', -"nabla", L'∇', -"nbsp", L' ', -"ndash", L'–', -"ne", L'≠', -"ni", L'∋', -"not", L'¬', -"notin", L'∉', -"nsub", L'⊄', -"ntilde", L'ñ', -"nu", L'ν', -"oacute", L'ó', -"ocirc", L'ô', -"oelig", L'œ', -"ograve", L'ò', -"oline", L'‾', -"omega", L'ω', -"omicron", L'ο', -"oplus", L'⊕', -"or", L'∨', -"ordf", L'ª', -"ordm", L'º', -"oslash", L'ø', -"otilde", L'õ', -"otimes", L'⊗', -"ouml", L'ö', -"para", L'¶', -"part", L'∂', -"permil", L'‰', -"perp", L'⊥', -"phi", L'φ', -"pi", L'π', -"piv", L'ϖ', -"plusmn", L'±', -"pound", L'£', -"prime", L'′', -"prod", L'∏', -"prop", L'∝', -"psi", L'ψ', -"quad", L' ', -"quot", L'"', -"rArr", L'⇒', -"radic", L'√', -"rang", L'〉', -"raquo", L'»', -"rarr", L'→', -"rceil", L'⌉', -"rdquo", L'”', -"real", L'ℜ', -"reg", L'®', -"rfloor", L'⌋', -"rho", L'ρ', -"rlm", L'‏', -"rsaquo", L'›', -"rsquo", L'’', -"sbquo", L'‚', -"scaron", L'š', -"sdot", L'⋅', -"sect", L'§', -"shy", L'­', -"sigma", L'σ', -"sigmaf", L'ς', -"sim", L'∼', -"sp", L' ', -"spades", L'♠', -"sub", L'⊂', -"sube", L'⊆', -"sum", L'∑', -"sup", L'⊃', -"sup1", L'¹', -"sup2", L'²', -"sup3", L'³', -"supe", L'⊇', -"szlig", L'ß', -"tau", L'τ', -"there4", L'∴', -"theta", L'θ', -"thetasym", L'ϑ', -"thinsp", L' ', -"thorn", L'þ', -"tilde", L'˜', -"times", L'×', -"trade", L'™', -"uArr", L'⇑', -"uacute", L'ú', -"uarr", L'↑', -"ucirc", L'û', -"ugrave", L'ù', -"uml", L'¨', -"upsih", L'ϒ', -"upsilon", L'υ', -"uuml", L'ü', -"varepsilon", L'∈', -"varphi", L'ϕ', -"varpi", L'ϖ', -"varrho", L'ϱ', -"vdots", L'⋮', -"vsigma", L'ς', -"vtheta", L'ϑ', -"weierp", L'℘', -"xi", L'ξ', -"yacute", L'ý', -"yen", L'¥', -"yuml", L'ÿ', -"zeta", L'ζ', -"zwj", L'‍', -"zwnj", L'‌', -}; -int pl_entities = nelem(pl_entity); diff --git a/sys/src/cmd/mothra/mkfile b/sys/src/cmd/mothra/mkfile index a0ff8a31a..d9673e38d 100644 --- a/sys/src/cmd/mothra/mkfile +++ b/sys/src/cmd/mothra/mkfile @@ -11,7 +11,7 @@ CFILES= \ rdhtml.c \ OFILES=${CFILES:%.c=%.$O} version.$O -HFILES=mothra.h html.h tcs.h libpanel/panel.h libpanel/rtext.h +HFILES=mothra.h html.h libpanel/panel.h libpanel/rtext.h BIN=/$objtype/bin type&GUNZIP) fd=pipeline("/bin/gunzip", fd); + snprint(cmd, sizeof(cmd), selection->charset[0] ? + "/bin/uhtml -c %s" : "/bin/uhtml", selection->charset); + fd = pipeline(cmd, fd); switch(selection->type&~COMPRESSION){ default: message("Bad type %x in geturl", selection->type); break; - case PLAIN: case HTML: + case PLAIN: w = www(i = wwwtop++); if(i >= NWWW){ extern void freeform(void *p); diff --git a/sys/src/cmd/mothra/rdhtml.c b/sys/src/cmd/mothra/rdhtml.c index efcf724bb..b9f4624e9 100644 --- a/sys/src/cmd/mothra/rdhtml.c +++ b/sys/src/cmd/mothra/rdhtml.c @@ -154,58 +154,6 @@ void pl_htmloutput(Hglob *g, int nsp, char *s, Field *field){ g->dst->changed=1; } -void pl_applycharset(Hglob *g) -{ - int fd, pfd[2], n; - char buf[NHBUF]; - char **cs, *charset; - - charset = nil; - for(cs = tcs; *cs; cs += 2){ - if(cistrcmp(cs[0], g->charset) == 0){ - charset = cs[1]; - break; - } - } - /* make sure we dont convet multiple times */ - g->charset[0]=0; - - /* no match, dont convert */ - if(charset == nil) - return; - - fd = g->hfd; - n = g->ehbuf - g->hbufp; - memcpy(buf, g->hbufp, n); - - if(pipe(pfd)==-1) - return; - switch(rfork(RFFDG|RFPROC|RFNOWAIT)){ - case -1: - close(pfd[0]); - close(pfd[1]); - return; - case 0: - dup(fd, 0); - dup(pfd[1], 1); - close(pfd[0]); - close(pfd[1]); - close(fd); - - write(1, buf, n); - while((n=read(0, buf, sizeof(buf)))>0) - write(1, buf, n); - _exits("no exec!"); - } - dup(pfd[0], fd); - close(pfd[0]); - close(pfd[1]); - g->hbufp = g->ehbuf; - snprint(buf, sizeof(buf), "tcs -s -f %s -t utf", charset); - if((fd=pipeline(buf, fd)) >= 0) - g->hfd = fd; -} - /* * Buffered read, no translation * Save in cache. @@ -297,22 +245,6 @@ int pl_nextc(Hglob *g){ int entchar(int c){ return c=='#' || 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9'; } -Entity *entsearch(char *s){ - int i, m, n, r; - i=0; - n=pl_entities; - while ((n-i) > 0) { - m=i+(n-i)/2; - r=strcmp(s, pl_entity[m].name); - if (r > 0) - i=m+1; - else if (r < 0) - n=m; - else - return &pl_entity[m]; - } - return 0; -} /* * remove entity references, in place. * Potential bug: @@ -333,30 +265,22 @@ void pl_rmentities(Hglob *g, char *s){ u=s; while(entchar(*s)) s++; svc=*s; - if(svc!=';') - htmlerror(g->name, g->lineno, "entity syntax error"); - *s++='\0'; - if(*u=='#'){ - if (u[1]=='X' || u[1]=='x') - r=strtol(u+2, 0, 16); - else - r=atoi(u+1); - t+=runetochar(t, &r); - if(svc!=';') *--s=svc; - } - else{ - ep=entsearch(u); - if(ep && ep->name){ - t+=runetochar(t, &ep->value); - if(svc!=';') *--s=svc; - } - else{ - htmlerror(g->name, g->lineno, - "unknown entity %s", u); - s[-1]=svc; - s=u; - *t++='&'; - } + *s = 0; + if(svc==';') s++; + if(strcmp(u, "lt") == 0) + *t++='<'; + else if(strcmp(u, "gt") == 0) + *t++='>'; + else if(strcmp(u, "quot") == 0) + *t++='"'; + else if(strcmp(u, "amp") == 0) + *t++='&'; + else { + if(svc==';') s--; + *s=svc; + *t++='&'; + while(ufinished=1; } @@ -713,13 +636,6 @@ void plrdhtml(char *name, int fd, Www *dst){ case Tag_end: /* unrecognized start tag */ break; case Tag_meta: - if((str=pl_getattr(g.attr, "http-equiv")) && - (cistrcmp(str, "content-type"))==0 && - (str=pl_getattr(g.attr, "content")) && - (str=cistrstr(str, "charset="))){ - strncpy(g.charset, str+8, sizeof(g.charset)); - pl_applycharset(&g); - } break; case Tag_img: if(str=pl_getattr(g.attr, "src")) @@ -805,7 +721,7 @@ void plrdhtml(char *name, int fd, Www *dst){ g.state->indent=20; break; case Tag_body: - pl_applycharset(&g); + break; case Tag_head: g.state->font=ROMAN; g.state->size=NORMAL; diff --git a/sys/src/cmd/page.c b/sys/src/cmd/page.c index eb2e761c1..12be5dc51 100644 --- a/sys/src/cmd/page.c +++ b/sys/src/cmd/page.c @@ -626,7 +626,7 @@ popenfile(Page *p) else if(cistrncmp(buf, "data = "html2ms | troff -ms | lp -dstdout"; + p->data = "uhtml | html2ms | troff -ms | lp -dstdout"; p->open = popengs; } else if(memcmp(buf, "\xF7\x02\x01\x83\x92\xC0\x1C;", 8) == 0){ diff --git a/sys/src/cmd/uhtml.c b/sys/src/cmd/uhtml.c new file mode 100644 index 000000000..49503877e --- /dev/null +++ b/sys/src/cmd/uhtml.c @@ -0,0 +1,121 @@ +#include +#include +#include + +int nbuf; +char buf[4096+1]; +char *cset = "utf"; + +void +usage(void) +{ + fprint(2, "%s [ -h ] [ -c charset ] [ file ]\n", argv0); + exits("usage"); +} + +char* +strval(char *s) +{ + char *e, q; + + while(strchr("\t ", *s)) + s++; + q = 0; + if(*s == '"' || *s == '\'') + q = *s++; + for(e = s; *e; e++){ + if(*e == q) + break; + if(isalnum(*e)) + continue; + if(*e == '-' || *e == '_') + continue; + break; + } + if(e - s > 1) + return smprint("%.*s", (int)(e-s), s); + return nil; +} + +void +main(int argc, char *argv[]) +{ + int pfd[2], pflag = 0; + char *arg[4], *s; + + ARGBEGIN { + case 'h': + usage(); + case 'c': + cset = EARGF(usage()); + break; + case 'p': + pflag = 1; + break; + } ARGEND; + + if(*argv){ + close(0); + if(open(*argv, OREAD) != 1) + sysfatal("open: %r"); + } + if((nbuf = read(0, buf, sizeof(buf)-1)) < 0) + sysfatal("read: %r"); + buf[nbuf] = 0; + for(;;){ + if(s = cistrstr(buf, "encoding=")) + if(s = strval(s+9)){ + cset = s; + break; + } + if(s = cistrstr(buf, "charset=")) + if(s = strval(s+8)){ + cset = s; + break; + } + break; + } + + if(pflag){ + print("%s\n", cset); + exits(0); + } + + if(pipe(pfd) < 0) + sysfatal("pipe: %r"); + + if(nbuf == 0){ + write(1, buf, 0); + exits(0); + } + + switch(rfork(RFFDG|RFREND|RFPROC|RFNOWAIT)){ + case -1: + sysfatal("fork: %r"); + case 0: + dup(pfd[0], 0); + close(pfd[0]); + close(pfd[1]); + + arg[0] = "rc"; + arg[1] = "-c"; + if(strcmp(cset, "utf")) + arg[2] = smprint("tcs -f %s -t utf | tcs -f html -t utf", cset); + else + arg[2] = "tcs -f html -t utf"; + arg[3] = nil; + exec("/bin/rc", arg); + } + + dup(pfd[1], 1); + close(pfd[0]); + close(pfd[1]); + + while(nbuf > 0){ + if(write(1, buf, nbuf) != nbuf) + sysfatal("write: %r"); + if((nbuf = read(0, buf, sizeof(buf))) < 0) + sysfatal("read: %r"); + } + exits(0); +}