]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/htmlroff/html.c
ndb/dns: remove single-ip-address assuptions
[plan9front.git] / sys / src / cmd / htmlroff / html.c
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 }
287