URI:
       thtml.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       thtml.c (3984B)
       ---
            1 /*
            2  * Emit html.  Keep track of tags so that user doesn't have to.
            3  */
            4 
            5 #include "a.h"
            6 
            7 typedef struct Tag Tag;
            8 struct Tag
            9 {
           10         Tag *next;
           11         Rune *id;
           12         Rune *open;
           13         Rune *close;
           14 };
           15 
           16 Tag *tagstack;
           17 Tag *tagset;
           18 int hidingset;
           19 
           20 static Rune*
           21 closingtag(Rune *s)
           22 {
           23         Rune *t;
           24         Rune *p0, *p;
           25 
           26         t = runemalloc(sizeof(Rune));
           27         if(s == nil)
           28                 return t;
           29         for(p=s; *p; p++){
           30                 if(*p == Ult){
           31                         p++;
           32                         if(*p == '/'){
           33                                 while(*p && *p != Ugt)
           34                                         p++;
           35                                 goto close;
           36                         }
           37                         p0 = p;
           38                         while(*p && !isspacerune(*p) && *p != Uspace && *p != Ugt)
           39                                 p++;
           40                         t = runerealloc(t, 1+(p-p0)+2+runestrlen(t)+1);
           41                         runemove(t+(p-p0)+3, t, runestrlen(t)+1);
           42                         t[0] = Ult;
           43                         t[1] = '/';
           44                         runemove(t+2, p0, p-p0);
           45                         t[2+(p-p0)] = Ugt;
           46                 }
           47 
           48                 if(*p == Ugt && p>s && *(p-1) == '/'){
           49                 close:
           50                         for(p0=t+1; *p0 && *p0 != Ult; p0++)
           51                                 ;
           52                         runemove(t, p0, runestrlen(p0)+1);
           53                 }
           54         }
           55         return t;
           56 }
           57 
           58 void
           59 html(Rune *id, Rune *s)
           60 {
           61         Rune *es;
           62         Tag *t, *tt, *next;
           63 
           64         br();
           65         hideihtml();        /* br already did, but be paranoid */
           66         for(t=tagstack; t; t=t->next){
           67                 if(runestrcmp(t->id, id) == 0){
           68                         for(tt=tagstack;; tt=next){
           69                                 next = tt->next;
           70                                 free(tt->id);
           71                                 free(tt->open);
           72                                 out(tt->close);
           73                                 outrune('\n');
           74                                 free(tt->close);
           75                                 free(tt);
           76                                 if(tt == t){
           77                                         tagstack = next;
           78                                         goto cleared;
           79                                 }
           80                         }
           81                 }
           82         }
           83 
           84 cleared:
           85         if(s == nil || s[0] == 0)
           86                 return;
           87         out(s);
           88         outrune('\n');
           89         es = closingtag(s);
           90         if(es[0] == 0){
           91                 free(es);
           92                 return;
           93         }
           94         if(runestrcmp(id, L("-")) == 0){
           95                 out(es);
           96                 outrune('\n');
           97                 free(es);
           98                 return;
           99         }
          100         t = emalloc(sizeof *t);
          101         t->id = erunestrdup(id);
          102         t->close = es;
          103         t->next = tagstack;
          104         tagstack = t;
          105 }
          106 
          107 void
          108 closehtml(void)
          109 {
          110         Tag *t, *next;
          111 
          112         br();
          113         hideihtml();
          114         for(t=tagstack; t; t=next){
          115                 next = t->next;
          116                 out(t->close);
          117                 outrune('\n');
          118                 free(t->id);
          119                 free(t->close);
          120                 free(t);
          121         }
          122 }
          123 
          124 static void
          125 rshow(Tag *t, Tag *end)
          126 {
          127         if(t == nil || t == end)
          128                 return;
          129         rshow(t->next, end);
          130         out(t->open);
          131 }
          132 
          133 void
          134 ihtml(Rune *id, Rune *s)
          135 {
          136         Tag *t, *tt, **l;
          137 
          138         for(t=tagset; t; t=t->next){
          139                 if(runestrcmp(t->id, id) == 0){
          140                         if(s && t->open && runestrcmp(t->open, s) == 0)
          141                                 return;
          142                         for(l=&tagset; (tt=*l); l=&tt->next){
          143                                 if(!hidingset)
          144                                         out(tt->close);
          145                                 if(tt == t)
          146                                         break;
          147                         }
          148                         *l = t->next;
          149                         free(t->id);
          150                         free(t->close);
          151                         free(t->open);
          152                         free(t);
          153                         if(!hidingset)
          154                                 rshow(tagset, *l);
          155                         goto cleared;
          156                 }
          157         }
          158 
          159 cleared:
          160         if(s == nil || s[0] == 0)
          161                 return;
          162         t = emalloc(sizeof *t);
          163         t->id = erunestrdup(id);
          164         t->open = erunestrdup(s);
          165         t->close = closingtag(s);
          166         if(!hidingset)
          167                 out(s);
          168         t->next = tagset;
          169         tagset = t;
          170 }
          171 
          172 void
          173 hideihtml(void)
          174 {
          175         Tag *t;
          176 
          177         if(hidingset)
          178                 return;
          179         hidingset = 1;
          180         for(t=tagset; t; t=t->next)
          181                 out(t->close);
          182 }
          183 
          184 void
          185 showihtml(void)
          186 {
          187         if(!hidingset)
          188                 return;
          189         hidingset = 0;
          190         rshow(tagset, nil);
          191 }
          192 
          193 int
          194 e_lt(void)
          195 {
          196         return Ult;
          197 }
          198 
          199 int
          200 e_gt(void)
          201 {
          202         return Ugt;
          203 }
          204 
          205 int
          206 e_at(void)
          207 {
          208         return Uamp;
          209 }
          210 
          211 int
          212 e_tick(void)
          213 {
          214         return Utick;
          215 }
          216 
          217 int
          218 e_btick(void)
          219 {
          220         return Ubtick;
          221 }
          222 
          223 int
          224 e_minus(void)
          225 {
          226         return Uminus;
          227 }
          228 
          229 void
          230 r_html(Rune *name)
          231 {
          232         Rune *id, *line, *p;
          233 
          234         id = copyarg();
          235         line = readline(HtmlMode);
          236         for(p=line; *p; p++){
          237                 switch(*p){
          238                 case '<':
          239                         *p = Ult;
          240                         break;
          241                 case '>':
          242                         *p = Ugt;
          243                         break;
          244                 case '&':
          245                         *p = Uamp;
          246                         break;
          247                 case ' ':
          248                         *p = Uspace;
          249                         break;
          250                 }
          251         }
          252         if(name[0] == 'i')
          253                 ihtml(id, line);
          254         else
          255                 html(id, line);
          256         free(id);
          257         free(line);
          258 }
          259 
          260 char defaultfont[] =
          261         ".ihtml f1\n"
          262         ".ihtml f\n"
          263         ".ihtml f <span style=\"font-size: \\n(.spt\">\n"
          264         ".if \\n(.f==2 .ihtml f1 <i>\n"
          265         ".if \\n(.f==3 .ihtml f1 <b>\n"
          266         ".if \\n(.f==4 .ihtml f1 <b><i>\n"
          267         ".if \\n(.f==5 .ihtml f1 <tt>\n"
          268         ".if \\n(.f==6 .ihtml f1 <tt><i>\n"
          269         "..\n"
          270 ;
          271 
          272 void
          273 htmlinit(void)
          274 {
          275         addraw(L("html"), r_html);
          276         addraw(L("ihtml"), r_html);
          277 
          278         addesc('<', e_lt, CopyMode);
          279         addesc('>', e_gt, CopyMode);
          280         addesc('\'', e_tick, CopyMode);
          281         addesc('`', e_btick, CopyMode);
          282         addesc('-', e_minus, CopyMode);
          283         addesc('@', e_at, CopyMode);
          284 
          285         ds(L("font"), L(defaultfont));
          286 }