/* * Emit html. Keep track of tags so that user doesn't have to. */ #include "a.h" typedef struct Tag Tag;struct Tag{ Tag *next; Rune *id; Rune *open; Rune *close;}; Tag *tagstack;Tag *tagset;int hidingset; static Rune*closingtag(Rune *s){ Rune *t; Rune *p0, *p; t = runemalloc(sizeof(Rune)); if(s == nil) return t; for(p=s; *p; p++){ if(*p == Ult){ p++; if(*p == '/'){ while(*p && *p != Ugt) p++; goto close; } p0 = p; while(*p && !isspacerune(*p) && *p != Uspace && *p != Ugt) p++; t = runerealloc(t, 1+(p-p0)+2+runestrlen(t)+1); runemove(t+(p-p0)+3, t, runestrlen(t)+1); t[0] = Ult; t[1] = '/'; runemove(t+2, p0, p-p0); t[2+(p-p0)] = Ugt; } if(*p == Ugt && p>s && *(p-1) == '/'){ close: for(p0=t+1; *p0 && *p0 != Ult; p0++) ; runemove(t, p0, runestrlen(p0)+1); } } return t; } voidhtml(Rune *id, Rune *s){ Rune *es; Tag *t, *tt, *next; br(); hideihtml(); /* br already did, but be paranoid */ for(t=tagstack; t; t=t->next){ if(runestrcmp(t->id, id) == 0){ for(tt=tagstack;; tt=next){ next = tt->next; free(tt->id); free(tt->open); out(tt->close); outrune('\n'); free(tt->close); free(tt); if(tt == t){ tagstack = next; goto cleared; } } } } cleared: if(s == nil || s[0] == 0) return; out(s); outrune('\n'); es = closingtag(s); if(es[0] == 0){ free(es); return; } if(runestrcmp(id, L("-")) == 0){ out(es); outrune('\n'); free(es); return; } t = emalloc(sizeof *t); t->id = erunestrdup(id); t->close = es; t->next = tagstack; tagstack = t;} voidclosehtml(void){ Tag *t, *next; br(); hideihtml(); for(t=tagstack; t; t=next){ next = t->next; out(t->close); outrune('\n'); free(t->id); free(t->close); free(t); }} static voidrshow(Tag *t, Tag *end){ if(t == nil || t == end) return; rshow(t->next, end); out(t->open);} voidihtml(Rune *id, Rune *s){ Tag *t, *tt, **l; for(t=tagset; t; t=t->next){ if(runestrcmp(t->id, id) == 0){ if(s && t->open && runestrcmp(t->open, s) == 0) return; for(l=&tagset; (tt=*l); l=&tt->next){ if(!hidingset) out(tt->close); if(tt == t) break; } *l = t->next; free(t->id); free(t->close); free(t->open); free(t); if(!hidingset) rshow(tagset, *l); goto cleared; } } cleared: if(s == nil || s[0] == 0) return; t = emalloc(sizeof *t); t->id = erunestrdup(id); t->open = erunestrdup(s); t->close = closingtag(s); if(!hidingset) out(s); t->next = tagset; tagset = t;} voidhideihtml(void){ Tag *t; if(hidingset) return; hidingset = 1; for(t=tagset; t; t=t->next) out(t->close);} voidshowihtml(void){ if(!hidingset) return; hidingset = 0; rshow(tagset, nil);} inte_lt(void){ return Ult;} inte_gt(void){ return Ugt;} inte_at(void){ return Uamp;} inte_tick(void){ return Utick;} inte_btick(void){ return Ubtick;} inte_minus(void){ return Uminus;} voidr_html(Rune *name){ Rune *id, *line, *p; id = copyarg(); line = readline(HtmlMode); for(p=line; *p; p++){ switch(*p){ case '<': *p = Ult; break; case '>': *p = Ugt; break; case '&': *p = Uamp; break; case ' ': *p = Uspace; break; } } if(name[0] == 'i') ihtml(id, line); else html(id, line); free(id); free(line);} char defaultfont[] = ".ihtml f1\n" ".ihtml f\n" ".ihtml f <span style=\"font-size: \\n(.spt\">\n" ".if \\n(.f==2 .ihtml f1 <i>\n" ".if \\n(.f==3 .ihtml f1 <b>\n" ".if \\n(.f==4 .ihtml f1 <b><i>\n" ".if \\n(.f==5 .ihtml f1 <tt>\n" ".if \\n(.f==6 .ihtml f1 <tt><i>\n" "..\n"; voidhtmlinit(void){ addraw(L("html"), r_html); addraw(L("ihtml"), r_html); addesc('<', e_lt, CopyMode); addesc('>', e_gt, CopyMode); addesc('\'', e_tick, CopyMode); addesc('`', e_btick, CopyMode); addesc('-', e_minus, CopyMode); addesc('@', e_at, CopyMode); ds(L("font"), L(defaultfont));}
/*
* Emit html. Keep track of tags so that user doesn't have to.
*/
#include "a.h"
typedef struct Tag Tag;
struct Tag
{
Tag *next;
Rune *id;
Rune *open;
Rune *close;
};
Tag *tagstack;
Tag *tagset;
int hidingset;
static Rune*
closingtag(Rune *s)
{
Rune *t;
Rune *p0, *p;
t = runemalloc(sizeof(Rune));
if(s == nil)
return t;
for(p=s; *p; p++){
if(*p == Ult){
p++;
if(*p == '/'){
while(*p && *p != Ugt)
p++;
goto close;
}
p0 = p;
while(*p && !isspacerune(*p) && *p != Uspace && *p != Ugt)
p++;
t = runerealloc(t, 1+(p-p0)+2+runestrlen(t)+1);
runemove(t+(p-p0)+3, t, runestrlen(t)+1);
t[0] = Ult;
t[1] = '/';
runemove(t+2, p0, p-p0);
t[2+(p-p0)] = Ugt;
}
if(*p == Ugt && p>s && *(p-1) == '/'){
close:
for(p0=t+1; *p0 && *p0 != Ult; p0++)
;
runemove(t, p0, runestrlen(p0)+1);
}
}
return t;
}
void
html(Rune *id, Rune *s)
{
Rune *es;
Tag *t, *tt, *next;
br();
hideihtml(); /* br already did, but be paranoid */
for(t=tagstack; t; t=t->next){
if(runestrcmp(t->id, id) == 0){
for(tt=tagstack;; tt=next){
next = tt->next;
free(tt->id);
free(tt->open);
out(tt->close);
outrune('\n');
free(tt->close);
free(tt);
if(tt == t){
tagstack = next;
goto cleared;
}
}
}
}
cleared:
if(s == nil || s[0] == 0)
return;
out(s);
outrune('\n');
es = closingtag(s);
if(es[0] == 0){
free(es);
return;
}
if(runestrcmp(id, L("-")) == 0){
out(es);
outrune('\n');
free(es);
return;
}
t = emalloc(sizeof *t);
t->id = erunestrdup(id);
t->close = es;
t->next = tagstack;
tagstack = t;
}
void
closehtml(void)
{
Tag *t, *next;
br();
hideihtml();
for(t=tagstack; t; t=next){
next = t->next;
out(t->close);
outrune('\n');
free(t->id);
free(t->close);
free(t);
}
}
static void
rshow(Tag *t, Tag *end)
{
if(t == nil || t == end)
return;
rshow(t->next, end);
out(t->open);
}
void
ihtml(Rune *id, Rune *s)
{
Tag *t, *tt, **l;
for(t=tagset; t; t=t->next){
if(runestrcmp(t->id, id) == 0){
if(s && t->open && runestrcmp(t->open, s) == 0)
return;
for(l=&tagset; (tt=*l); l=&tt->next){
if(!hidingset)
out(tt->close);
if(tt == t)
break;
}
*l = t->next;
free(t->id);
free(t->close);
free(t->open);
free(t);
if(!hidingset)
rshow(tagset, *l);
goto cleared;
}
}
cleared:
if(s == nil || s[0] == 0)
return;
t = emalloc(sizeof *t);
t->id = erunestrdup(id);
t->open = erunestrdup(s);
t->close = closingtag(s);
if(!hidingset)
out(s);
t->next = tagset;
tagset = t;
}
void
hideihtml(void)
{
Tag *t;
if(hidingset)
return;
hidingset = 1;
for(t=tagset; t; t=t->next)
out(t->close);
}
void
showihtml(void)
{
if(!hidingset)
return;
hidingset = 0;
rshow(tagset, nil);
}
int
e_lt(void)
{
return Ult;
}
int
e_gt(void)
{
return Ugt;
}
int
e_at(void)
{
return Uamp;
}
int
e_tick(void)
{
return Utick;
}
int
e_btick(void)
{
return Ubtick;
}
int
e_minus(void)
{
return Uminus;
}
void
r_html(Rune *name)
{
Rune *id, *line, *p;
id = copyarg();
line = readline(HtmlMode);
for(p=line; *p; p++){
switch(*p){
case '<':
*p = Ult;
break;
case '>':
*p = Ugt;
break;
case '&':
*p = Uamp;
break;
case ' ':
*p = Uspace;
break;
}
}
if(name[0] == 'i')
ihtml(id, line);
else
html(id, line);
free(id);
free(line);
}
char defaultfont[] =
".ihtml f1\n"
".ihtml f\n"
".ihtml f <span style=\"font-size: \\n(.spt\">\n"
".if \\n(.f==2 .ihtml f1 <i>\n"
".if \\n(.f==3 .ihtml f1 <b>\n"
".if \\n(.f==4 .ihtml f1 <b><i>\n"
".if \\n(.f==5 .ihtml f1 <tt>\n"
".if \\n(.f==6 .ihtml f1 <tt><i>\n"
"..\n"
;
void
htmlinit(void)
{
addraw(L("html"), r_html);
addraw(L("ihtml"), r_html);
addesc('<', e_lt, CopyMode);
addesc('>', e_gt, CopyMode);
addesc('\'', e_tick, CopyMode);
addesc('`', e_btick, CopyMode);
addesc('-', e_minus, CopyMode);
addesc('@', e_at, CopyMode);
ds(L("font"), L(defaultfont));
}