html2ms: quirks mode

This commit is contained in:
cinap_lenrek 2011-09-21 16:14:15 +02:00
parent d31ff5c94f
commit f616a4c597

View file

@ -41,13 +41,15 @@ struct Text {
}; };
void eatwhite(void); void eatwhite(void);
Tag *parsetext(Text *, Tag *); void parsetext(Text *, Tag *);
int parsetag(Tag *); int parsetag(Tag *);
int parseattr(Attr *); int parseattr(Attr *);
void flushtext(Text *); void flushtext(Text *);
char* getattr(Tag *, char *); char* getattr(Tag *, char *);
int gotattr(Tag *, char *, char *); int gotattr(Tag *, char *, char *);
int gotstyle(Tag *, char *, char *); int gotstyle(Tag *, char *, char *);
void reparent(Text *, Tag *, Tag *);
void debugtag(Tag *, char *);
Biobuf in; Biobuf in;
@ -113,6 +115,12 @@ ongarbage(Text *text, Tag *tag)
text->output = 0; text->output = 0;
} }
void
onmeta(Text *, Tag *tag)
{
tag->closing = 1;
}
void void
onp(Text *text, Tag *) onp(Text *text, Tag *)
{ {
@ -277,6 +285,23 @@ tabletag(Tag *tag)
return tabletag(tag->up); return tabletag(tag->up);
} }
void
reparent(Text *text, Tag *tag, Tag *up)
{
Tag *old;
old = tag->up;
while(old != up){
if(old->close){
debugtag(old, "reparent close");
old->close(text, old);
old->close = nil;
}
old = old->up;
}
tag->up = up;
}
void void
dumprows(Text *text, Table *s, Table *e) dumprows(Text *text, Table *s, Table *e)
{ {
@ -436,11 +461,20 @@ endcell(Text *text, Tag *tag)
void void
oncell(Text *text, Tag *tag) oncell(Text *text, Tag *tag)
{ {
if(tabletag(tag) == nil) Tag *tt;
if((tt = tabletag(tag)) == nil)
return; return;
if(cistrcmp(tag->tag, "tr")){ if(cistrcmp(tag->tag, "tr")){
Table *t; Table *t;
tt = tag->up;
while(tt && cistrcmp(tt->tag, "tr"))
tt = tt->up;
if(tt == nil)
return;
reparent(text, tag, tt);
t = mallocz(sizeof(*t), 1); t = mallocz(sizeof(*t), 1);
t->save = *text; t->save = *text;
tag->aux = t; tag->aux = t;
@ -450,7 +484,8 @@ oncell(Text *text, Tag *tag)
text->nb = 0; text->nb = 0;
text->pos = 0; text->pos = 0;
text->space = 0; text->space = 0;
} } else
reparent(text, tag, tt);
tag->close = endcell; tag->close = endcell;
} }
@ -477,6 +512,8 @@ struct {
"i", oni, "i", oni,
"kbd", ontt, "kbd", ontt,
"li", onli, "li", onli,
"link", onmeta,
"meta", onmeta,
"p", onp, "p", onp,
"pre", onpre, "pre", onpre,
"q", onquote, "q", onquote,
@ -485,12 +522,12 @@ struct {
"small", onsmall, "small", onsmall,
"strong", onb, "strong", onb,
"style", ongarbage, "style", ongarbage,
"tt", ontt,
"var", oni,
"table", ontable, "table", ontable,
"tr", oncell,
"td", oncell, "td", oncell,
"th", oncell, "th", oncell,
"tr", oncell,
"tt", ontt,
"var", oni,
}; };
void void
@ -745,43 +782,41 @@ gotstyle(Tag *tag, char *style, char *val)
return 1; return 1;
} }
Tag* void
parsetext(Text *text, Tag *tag) parsetext(Text *text, Tag *tag)
{ {
int hidden, c; int hidden, c;
Tag *rtag; Tag t, *p;
Rune r; Rune r;
rtag = tag; if(tag){
debugtag(tag, "open"); debugtag(tag, "open");
hidden = tag ? (getattr(tag, "hidden") || gotstyle(tag, "display", "none")) : 0; for(c = 0; c < nelem(ontag); c++){
if(cistrcmp(tag->tag, ontag[c].tag) == 0){
ontag[c].open(text, tag);
break;
}
}
hidden = getattr(tag, "hidden") || gotstyle(tag, "display", "none");
} else
hidden = 0;
if(tag == nil || tag->closing == 0){ if(tag == nil || tag->closing == 0){
while((c = Bgetc(&in)) > 0){ while((c = Bgetc(&in)) > 0){
if(c == '<'){ if(c == '<'){
Tag t;
memset(&t, 0, sizeof(t)); memset(&t, 0, sizeof(t));
if(parsetag(&t)){ if(parsetag(&t)){
text->aftertag = 1; text->aftertag = 1;
if(t.opening){ if(t.opening){
t.up = tag; t.up = tag;
for(c = 0; c < nelem(ontag); c++){ parsetext(text, &t);
if(cistrcmp(t.tag, ontag[c].tag) == 0){ if(t.up != tag)
ontag[c].open(text, &t);
break;
}
}
rtag = parsetext(text, &t);
if(rtag == &t)
rtag = tag;
else
break; break;
} else if(t.closing){ } else if(t.closing){
while(rtag && cistrcmp(rtag->tag, t.tag)) p = tag;
rtag = rtag->up; while(p && cistrcmp(p->tag, t.tag))
if(rtag == nil) p = p->up;
rtag = tag; if(p)
break; break;
} }
} }
continue; continue;
@ -819,10 +854,11 @@ parsetext(Text *text, Tag *tag)
} }
} }
} }
debugtag(tag, "close"); if(tag){
if(tag && tag->close) debugtag(tag, "close");
tag->close(text, tag); if(tag->close)
return rtag; tag->close(text, tag);
}
} }
void void