123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /*
- * 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));
- }
|