for(;;) switch(pl_gettoken(&g)){
case TAG:
switch(tag[g.tag].action){
case OPTEND:
for(sp=g.state;sp!=g.stack && sp->tag!=g.tag;--sp);
if(sp->tag!=g.tag)
pl_pushstate(&g, g.tag);
else
for(;g.state!=sp;--g.state){
if(tag[g.state->tag].action!=OPTEND)
htmlerror(g.name, g.lineno,
"end tag </%s> missing",
tag[g.state->tag].name);
pl_popstate(g.state);
}
break;
case END:
pl_pushstate(&g, g.tag);
break;
}
str=pl_getattr(g.attr, "id");
if(str && *str){
char *swap;
swap = g.state->name;
g.state->name = str;
pl_htmloutput(&g, 0, "", 0);
g.state->name = swap;
}
switch(g.tag){
default:
htmlerror(g.name, g.lineno,
"unimplemented tag <%s>", tag[g.tag].name);
break;
case Tag_end: /* unrecognized start tag */
break;
case Tag_img:
case Tag_image:
str=pl_getattr(g.attr, "src");
if(str && *str){
free(g.state->image);
g.state->image = strdup(str);
} else {
Pair *a;
/*
* hack to emulate javascript that rewrites some attribute
* into src= after page got loaded. just look for some
* attribute that looks like a url.
*/
for(a = g.attr; a->name; a++){
if(strcmp(a->name, "longdesc") == 0)
continue;
if(str = linkify(a->value)){
free(g.state->image);
g.state->image = str;
break;
}
}
}
g.state->ismap=pl_hasattr(g.attr, "ismap");
str=pl_getattr(g.attr, "width");
if(str && *str)
g.state->width=strtolength(&g, HORIZ, str);
str=pl_getattr(g.attr, "height");
if(str && *str)
g.state->height=strtolength(&g, VERT, str);
str=pl_getattr(g.attr, "alt");
if(str==0 || *str == 0){
if(g.state->image)
str=g.state->image;
else
str="[[image]]";
}
pl_htmloutput(&g, 0, str, 0);
free(g.state->image);
g.state->image=0;
g.state->ismap=0;
g.state->width=0;
g.state->height=0;
break;
case Tag_plaintext:
g.spacc=0;
plaintext(&g);
break;
case Tag_comment:
case Tag_html:
case Tag_link:
case Tag_nextid:
case Tag_table:
break;
case Tag_tr:
g.spacc=0;
g.linebrk=1;
break;
case Tag_th:
g.state->font=BOLD;
case Tag_td:
g.spacc++;
break;
case Tag_base:
str=pl_getattr(g.attr, "href");
if(str && *str){
seturl(g.dst->url, str, g.dst->url->fullname);
nstrcpy(g.dst->url->fullname, str, sizeof(g.dst->url->fullname));
/* base should be a full url, but it often isnt so have to resolve */
urlresolve(g.dst->url);
}
break;
case Tag_a:
str=pl_getattr(g.attr, "name");
if(str && *str){
free(g.state->name);
g.state->name = strdup(str);
}
pl_htmloutput(&g, 0, "", 0);
str=pl_getattr(g.attr, "href");
if(str && *str){
free(g.state->link);
g.state->link = strdup(str);
}
break;
case Tag_meta:
if((str=pl_getattr(g.attr, "http-equiv"))==0)
break;
if(cistrcmp(str, "refresh"))
break;
if((str=pl_getattr(g.attr, "content"))==0)
break;
if((str=strchr(str, '='))==0)
break;
str++;
pl_htmloutput(&g, 0, "[refresh: ", 0);
free(g.state->link);
g.state->link=unquot(str);
pl_htmloutput(&g, 0, g.state->link, 0);
free(g.state->link);
g.state->link=0;
pl_htmloutput(&g, 0, "]", 0);
g.linebrk=1;
g.spacc=0;
break;
case Tag_source:
case Tag_video:
case Tag_audio:
case Tag_embed:
case Tag_frame:
case Tag_iframe:
snprint(buf, sizeof(buf), "[%s: ", tag[g.tag].name);
pl_htmloutput(&g, 0, buf, 0);
str=pl_getattr(g.attr, "src");
if(str && *str){
free(g.state->link);
g.state->link = strdup(str);
}
str=pl_getattr(g.attr, "name");
if(str && *str){
free(g.state->name);
g.state->name = strdup(str);
} else if(g.state->link)
str = g.state->link;
else
str = "";
pl_htmloutput(&g, 0, str, 0);
free(g.state->link);
g.state->link=0;
free(g.state->name);
g.state->name=0;
pl_htmloutput(&g, 0, "]", 0);
g.linebrk=1;
g.spacc=0;
break;
case Tag_address:
g.spacc=0;
g.linebrk=1;
g.state->font=ROMAN;
g.state->size=NORMAL;
g.state->margin=300;
g.state->indent=50;
break;
case Tag_b:
case Tag_strong:
g.state->font=BOLD;
break;
case Tag_s:
case Tag_strike:
case Tag_del:
g.state->strike=1;
break;
case Tag_sub:
g.state->sub++;
break;
case Tag_sup:
g.state->sub--;
break;
case Tag_blockquot:
g.spacc=0;
g.linebrk=1;
g.state->margin+=50;
g.state->indent=20;
break;
case Tag_body:
break;
case Tag_head:
g.state->font=ROMAN;
g.state->size=NORMAL;
g.state->margin=0;
g.state->indent=20;
g.spacc=0;
break;
case Tag_div:
case Tag_br:
case Tag_wbr:
g.spacc=0;
g.linebrk=1;
break;
case Tag_span:
case Tag_center:
/* more to come */
break;
case Tag_cite:
case Tag_acronym:
g.state->font=ITALIC;
g.state->size=NORMAL;
break;
case Tag_code:
g.state->font=CWIDTH;
g.state->size=NORMAL;
break;
case Tag_dd:
g.linebrk=1;
g.state->indent=0;
g.state->font=ROMAN;
g.spacc=0;
break;
case Tag_dfn:
htmlerror(g.name, g.lineno, "<dfn> deprecated");
case Tag_abbr:
g.state->font=BOLD;
g.state->size=NORMAL;
break;
case Tag_dl:
g.state->font=BOLD;
g.state->size=NORMAL;
g.state->margin+=40;
g.spacc=0;
break;
case Tag_dt:
g.para=1;
g.state->indent=-40;
g.state->font=BOLD;
g.spacc=0;
break;
case Tag_font:
/* more to come */
break;
case Tag_u:
htmlerror(g.name, g.lineno, "<u> deprecated");
case Tag_ins:
case Tag_em:
case Tag_i:
case Tag_var:
g.state->font=ITALIC;
break;
case Tag_h1:
g.linebrk=1;
g.state->font=BOLD;
g.state->size=ENORMOUS;
g.state->margin+=100;
g.spacc=0;
break;
case Tag_h2:
pl_linespace(&g);
g.state->font=BOLD;
g.state->size=ENORMOUS;
g.spacc=0;
break;
case Tag_h3:
g.linebrk=1;
pl_linespace(&g);
g.state->font=ITALIC;
g.state->size=ENORMOUS;
g.state->margin+=20;
g.spacc=0;
break;
case Tag_h4:
pl_linespace(&g);
g.state->font=BOLD;
g.state->size=LARGE;
g.state->margin+=10;
g.spacc=0;
break;
case Tag_h5:
pl_linespace(&g);
g.state->font=ITALIC;
g.state->size=LARGE;
g.state->margin+=10;
g.spacc=0;
break;
case Tag_h6:
pl_linespace(&g);
g.state->font=BOLD;
g.state->size=LARGE;
g.spacc=0;
break;
case Tag_hr:
g.spacc=0;
plrtbitmap(&g.dst->text, 1000000, g.state->margin, 0, hrule, 0, 0);
break;
case Tag_key:
htmlerror(g.name, g.lineno, "<key> deprecated");
case Tag_kbd:
g.state->font=CWIDTH;
break;
case Tag_dir:
case Tag_menu:
case Tag_ol:
case Tag_ul:
g.state->number=0;
g.linebrk=1;
g.state->margin+=25;
g.state->indent=-25;
g.spacc=0;
break;
case Tag_li:
g.spacc=0;
switch(g.state->tag){
default:
htmlerror(g.name, g.lineno, "can't have <li> in <%s>",
tag[g.state->tag].name);
case Tag_dir: /* supposed to be multi-columns, can't do! */
case Tag_menu:
g.linebrk=1;
break;
case Tag_ol:
g.para=1;
snprint(buf, sizeof(buf), "%2d ", ++g.state->number);
pl_htmloutput(&g, 0, buf, 0);
break;
case Tag_ul:
g.para=0;
g.linebrk=0;
g.spacc=-1;
plrtbitmap(&g.dst->text, 100000,
g.state->margin+g.state->indent, 0, bullet, 0, 0);
break;
}
break;
case Tag_p:
pl_linespace(&g);
g.linebrk=1;
g.spacc=0;
break;
case Tag_listing:
case Tag_xmp:
htmlerror(g.name, g.lineno, "<%s> deprecated", tag[g.tag].name);
case Tag_pre:
case Tag_samp:
g.state->indent=0;
g.state->pre=1;
g.state->font=CWIDTH;
g.state->size=NORMAL;
pl_linespace(&g);
break;
case Tag_tt:
g.state->font=CWIDTH;
g.state->size=NORMAL;
break;
case Tag_title:
g.text=dst->title+strlen(dst->title);
g.tp=g.text;
g.etext=dst->title+NTITLE-1;
break;
case Tag_form:
case Tag_input:
case Tag_button:
case Tag_select:
case Tag_option:
case Tag_textarea:
case Tag_isindex:
rdform(&g);
break;
case Tag_script:
case Tag_style:
g.state->isscript=1;
break;
}
break;
case ENDTAG:
/*
* If the end tag doesn't match the top, we try to uncover a match
* on the stack.
*/
if(g.state->tag!=g.tag){
tagerr=0;
for(sp=g.state;sp!=g.stack;--sp){
if(sp->tag==g.tag)
break;
if(tag[g.state->tag].action!=OPTEND) tagerr++;
}
if(sp==g.stack){
if(tagerr)
htmlerror(g.name, g.lineno,
"end tag mismatch <%s>...</%s>, ignored",
tag[g.state->tag].name, tag[g.tag].name);
}
else{
if(tagerr)
htmlerror(g.name, g.lineno,
"end tag mismatch <%s>...</%s>, "
"intervening tags popped",
tag[g.state->tag].name, tag[g.tag].name);
for(--sp; g.state!=sp; --g.state)
pl_popstate(g.state);
}
}
else if(g.state==g.stack)
htmlerror(g.name, g.lineno, "end tag </%s> at stack bottom",
tag[g.tag].name);
else
pl_popstate(g.state--);
switch(g.tag){
case Tag_select:
case Tag_form:
case Tag_textarea:
endform(&g);
break;
case Tag_h1:
case Tag_h2:
case Tag_h3:
case Tag_h4:
pl_linespace(&g);
break;
case Tag_div:
case Tag_address:
case Tag_blockquot:
case Tag_body:
case Tag_dir:
case Tag_dl:
case Tag_dt:
case Tag_h5:
case Tag_h6:
case Tag_listing:
case Tag_menu:
case Tag_ol:
case Tag_samp:
case Tag_title:
case Tag_ul:
case Tag_xmp:
case Tag_table:
g.linebrk=1;
break;
case Tag_pre:
pl_linespace(&g);
break;
}
break;
case TEXT:
if(g.state->isscript)
continue;
if(g.state->link==0 && (str = linkify(g.token))){
g.state->link=str;
pl_htmloutput(&g, g.nsp, g.token, 0);
free(g.state->link);
g.state->link=0;
} else
pl_htmloutput(&g, g.nsp, g.token, 0);
break;
case EOF:
for(;g.state!=g.stack;--g.state){
if(tag[g.state->tag].action!=OPTEND)
htmlerror(g.name, g.lineno,
"missing </%s> at EOF", tag[g.state->tag].name);
pl_popstate(g.state);
}
pl_popstate(g.state);
*g.tp='\0';
if (!killimgs)
getpix(dst->text, dst);
finish(dst);
return;
}
}