blob: 810959957eb2cf384056cba97d03f7af45eafff6 [file] [log] [blame]
rscc42a1d32006-02-21 18:37:05 +00001/*
2 * Emit html. Keep track of tags so that user doesn't have to.
3 */
4
5#include "a.h"
6
7typedef struct Tag Tag;
8struct Tag
9{
10 Tag *next;
11 Rune *id;
12 Rune *open;
13 Rune *close;
14};
15
16Tag *tagstack;
17Tag *tagset;
18int hidingset;
19
20static Rune*
21closingtag(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
58void
59html(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
84cleared:
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
107void
108closehtml(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
124static void
125rshow(Tag *t, Tag *end)
126{
127 if(t == nil || t == end)
128 return;
129 rshow(t->next, end);
130 out(t->open);
131}
132
133void
134ihtml(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
159cleared:
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
172void
173hideihtml(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
184void
185showihtml(void)
186{
187 if(!hidingset)
188 return;
189 hidingset = 0;
190 rshow(tagset, nil);
191}
192
193int
194e_lt(void)
195{
196 return Ult;
197}
198
199int
200e_gt(void)
201{
202 return Ugt;
203}
204
205int
206e_at(void)
207{
208 return Uamp;
209}
210
211int
212e_tick(void)
213{
214 return Utick;
215}
216
217int
218e_btick(void)
219{
220 return Ubtick;
221}
222
223int
224e_minus(void)
225{
226 return Uminus;
227}
228
229void
230r_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
260char defaultfont[] =
261 ".ihtml f1\n"
262 ".ihtml f\n"
rsc495eda02006-05-09 13:20:48 +0000263 ".ihtml f <span style=\"font-size: \\n(.spt\">\n"
rscc42a1d32006-02-21 18:37:05 +0000264 ".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
272void
273htmlinit(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}
287