Blob


1 /*
2 * Emit html. Keep track of tags so that user doesn't have to.
3 */
5 #include "a.h"
7 typedef struct Tag Tag;
8 struct Tag
9 {
10 Tag *next;
11 Rune *id;
12 Rune *open;
13 Rune *close;
14 };
16 Tag *tagstack;
17 Tag *tagset;
18 int hidingset;
20 static Rune*
21 closingtag(Rune *s)
22 {
23 Rune *t;
24 Rune *p0, *p;
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 }
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 }
58 void
59 html(Rune *id, Rune *s)
60 {
61 Rune *es;
62 Tag *t, *tt, *next;
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 }
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;
107 void
108 closehtml(void)
110 Tag *t, *next;
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);
124 static void
125 rshow(Tag *t, Tag *end)
127 if(t == nil || t == end)
128 return;
129 rshow(t->next, end);
130 out(t->open);
133 void
134 ihtml(Rune *id, Rune *s)
136 Tag *t, *tt, **l;
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;
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;
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;
172 void
173 hideihtml(void)
175 Tag *t;
177 if(hidingset)
178 return;
179 hidingset = 1;
180 for(t=tagset; t; t=t->next)
181 out(t->close);
184 void
185 showihtml(void)
187 if(!hidingset)
188 return;
189 hidingset = 0;
190 rshow(tagset, nil);
193 int
194 e_lt(void)
196 return Ult;
199 int
200 e_gt(void)
202 return Ugt;
205 int
206 e_at(void)
208 return Uamp;
211 int
212 e_tick(void)
214 return Utick;
217 int
218 e_btick(void)
220 return Ubtick;
223 int
224 e_minus(void)
226 return Uminus;
229 void
230 r_html(Rune *name)
232 Rune *id, *line, *p;
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;
252 if(name[0] == 'i')
253 ihtml(id, line);
254 else
255 html(id, line);
256 free(id);
257 free(line);
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"
272 void
273 htmlinit(void)
275 addraw(L("html"), r_html);
276 addraw(L("ihtml"), r_html);
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);
285 ds(L("font"), L(defaultfont));