diff options
author | rsc <devnull@localhost> | 2006-02-21 18:37:05 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2006-02-21 18:37:05 +0000 |
commit | c42a1d3d6168df56f966ea1f3ba3ef39ebbff4e4 (patch) | |
tree | 400f263e56681842ba1e6e1fdd8be453856474ef /src/cmd/htmlroff/html.c | |
parent | 49a1496cbbb871bc623cfd0925566628e246c9ba (diff) | |
download | plan9port-c42a1d3d6168df56f966ea1f3ba3ef39ebbff4e4.tar.gz plan9port-c42a1d3d6168df56f966ea1f3ba3ef39ebbff4e4.tar.bz2 plan9port-c42a1d3d6168df56f966ea1f3ba3ef39ebbff4e4.zip |
add
Diffstat (limited to 'src/cmd/htmlroff/html.c')
-rw-r--r-- | src/cmd/htmlroff/html.c | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/src/cmd/htmlroff/html.c b/src/cmd/htmlroff/html.c new file mode 100644 index 00000000..fd48382a --- /dev/null +++ b/src/cmd/htmlroff/html.c @@ -0,0 +1,287 @@ +/* + * 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)); +} + |