1426d2b71SDavid du Colombier /*
2426d2b71SDavid du Colombier * Emit html. Keep track of tags so that user doesn't have to.
3426d2b71SDavid du Colombier */
4426d2b71SDavid du Colombier
5426d2b71SDavid du Colombier #include "a.h"
6426d2b71SDavid du Colombier
7426d2b71SDavid du Colombier typedef struct Tag Tag;
8426d2b71SDavid du Colombier struct Tag
9426d2b71SDavid du Colombier {
10426d2b71SDavid du Colombier Tag *next;
11426d2b71SDavid du Colombier Rune *id;
12426d2b71SDavid du Colombier Rune *open;
13426d2b71SDavid du Colombier Rune *close;
14426d2b71SDavid du Colombier };
15426d2b71SDavid du Colombier
16426d2b71SDavid du Colombier Tag *tagstack;
17426d2b71SDavid du Colombier Tag *tagset;
18426d2b71SDavid du Colombier int hidingset;
19426d2b71SDavid du Colombier
20426d2b71SDavid du Colombier static Rune*
closingtag(Rune * s)21426d2b71SDavid du Colombier closingtag(Rune *s)
22426d2b71SDavid du Colombier {
23426d2b71SDavid du Colombier Rune *t;
24426d2b71SDavid du Colombier Rune *p0, *p;
25426d2b71SDavid du Colombier
26426d2b71SDavid du Colombier t = runemalloc(sizeof(Rune));
27426d2b71SDavid du Colombier if(s == nil)
28426d2b71SDavid du Colombier return t;
29426d2b71SDavid du Colombier for(p=s; *p; p++){
30426d2b71SDavid du Colombier if(*p == Ult){
31426d2b71SDavid du Colombier p++;
32426d2b71SDavid du Colombier if(*p == '/'){
33426d2b71SDavid du Colombier while(*p && *p != Ugt)
34426d2b71SDavid du Colombier p++;
35426d2b71SDavid du Colombier goto close;
36426d2b71SDavid du Colombier }
37426d2b71SDavid du Colombier p0 = p;
38426d2b71SDavid du Colombier while(*p && !isspacerune(*p) && *p != Uspace && *p != Ugt)
39426d2b71SDavid du Colombier p++;
40426d2b71SDavid du Colombier t = runerealloc(t, 1+(p-p0)+2+runestrlen(t)+1);
41426d2b71SDavid du Colombier runemove(t+(p-p0)+3, t, runestrlen(t)+1);
42426d2b71SDavid du Colombier t[0] = Ult;
43426d2b71SDavid du Colombier t[1] = '/';
44426d2b71SDavid du Colombier runemove(t+2, p0, p-p0);
45426d2b71SDavid du Colombier t[2+(p-p0)] = Ugt;
46426d2b71SDavid du Colombier }
47426d2b71SDavid du Colombier
48426d2b71SDavid du Colombier if(*p == Ugt && p>s && *(p-1) == '/'){
49426d2b71SDavid du Colombier close:
50426d2b71SDavid du Colombier for(p0=t+1; *p0 && *p0 != Ult; p0++)
51426d2b71SDavid du Colombier ;
52426d2b71SDavid du Colombier runemove(t, p0, runestrlen(p0)+1);
53426d2b71SDavid du Colombier }
54426d2b71SDavid du Colombier }
55426d2b71SDavid du Colombier return t;
56426d2b71SDavid du Colombier }
57426d2b71SDavid du Colombier
58426d2b71SDavid du Colombier void
html(Rune * id,Rune * s)59426d2b71SDavid du Colombier html(Rune *id, Rune *s)
60426d2b71SDavid du Colombier {
61426d2b71SDavid du Colombier Rune *es;
62426d2b71SDavid du Colombier Tag *t, *tt, *next;
63426d2b71SDavid du Colombier
64426d2b71SDavid du Colombier br();
65426d2b71SDavid du Colombier hideihtml(); /* br already did, but be paranoid */
66426d2b71SDavid du Colombier for(t=tagstack; t; t=t->next){
67426d2b71SDavid du Colombier if(runestrcmp(t->id, id) == 0){
68426d2b71SDavid du Colombier for(tt=tagstack;; tt=next){
69426d2b71SDavid du Colombier next = tt->next;
70426d2b71SDavid du Colombier free(tt->id);
71426d2b71SDavid du Colombier free(tt->open);
72426d2b71SDavid du Colombier out(tt->close);
73426d2b71SDavid du Colombier outrune('\n');
74426d2b71SDavid du Colombier free(tt->close);
75426d2b71SDavid du Colombier free(tt);
76426d2b71SDavid du Colombier if(tt == t){
77426d2b71SDavid du Colombier tagstack = next;
78426d2b71SDavid du Colombier goto cleared;
79426d2b71SDavid du Colombier }
80426d2b71SDavid du Colombier }
81426d2b71SDavid du Colombier }
82426d2b71SDavid du Colombier }
83426d2b71SDavid du Colombier
84426d2b71SDavid du Colombier cleared:
85426d2b71SDavid du Colombier if(s == nil || s[0] == 0)
86426d2b71SDavid du Colombier return;
87426d2b71SDavid du Colombier out(s);
88426d2b71SDavid du Colombier outrune('\n');
89426d2b71SDavid du Colombier es = closingtag(s);
90426d2b71SDavid du Colombier if(es[0] == 0){
91426d2b71SDavid du Colombier free(es);
92426d2b71SDavid du Colombier return;
93426d2b71SDavid du Colombier }
94426d2b71SDavid du Colombier if(runestrcmp(id, L("-")) == 0){
95426d2b71SDavid du Colombier out(es);
96426d2b71SDavid du Colombier outrune('\n');
97426d2b71SDavid du Colombier free(es);
98426d2b71SDavid du Colombier return;
99426d2b71SDavid du Colombier }
100426d2b71SDavid du Colombier t = emalloc(sizeof *t);
101426d2b71SDavid du Colombier t->id = erunestrdup(id);
102426d2b71SDavid du Colombier t->close = es;
103426d2b71SDavid du Colombier t->next = tagstack;
104426d2b71SDavid du Colombier tagstack = t;
105426d2b71SDavid du Colombier }
106426d2b71SDavid du Colombier
107426d2b71SDavid du Colombier void
closehtml(void)108426d2b71SDavid du Colombier closehtml(void)
109426d2b71SDavid du Colombier {
110426d2b71SDavid du Colombier Tag *t, *next;
111426d2b71SDavid du Colombier
112426d2b71SDavid du Colombier br();
113426d2b71SDavid du Colombier hideihtml();
114426d2b71SDavid du Colombier for(t=tagstack; t; t=next){
115426d2b71SDavid du Colombier next = t->next;
116426d2b71SDavid du Colombier out(t->close);
117426d2b71SDavid du Colombier outrune('\n');
118426d2b71SDavid du Colombier free(t->id);
119426d2b71SDavid du Colombier free(t->close);
120426d2b71SDavid du Colombier free(t);
121426d2b71SDavid du Colombier }
122426d2b71SDavid du Colombier }
123426d2b71SDavid du Colombier
124426d2b71SDavid du Colombier static void
rshow(Tag * t,Tag * end)125426d2b71SDavid du Colombier rshow(Tag *t, Tag *end)
126426d2b71SDavid du Colombier {
127426d2b71SDavid du Colombier if(t == nil || t == end)
128426d2b71SDavid du Colombier return;
129426d2b71SDavid du Colombier rshow(t->next, end);
130426d2b71SDavid du Colombier out(t->open);
131426d2b71SDavid du Colombier }
132426d2b71SDavid du Colombier
133426d2b71SDavid du Colombier void
ihtml(Rune * id,Rune * s)134426d2b71SDavid du Colombier ihtml(Rune *id, Rune *s)
135426d2b71SDavid du Colombier {
136426d2b71SDavid du Colombier Tag *t, *tt, **l;
137426d2b71SDavid du Colombier
138426d2b71SDavid du Colombier for(t=tagset; t; t=t->next){
139426d2b71SDavid du Colombier if(runestrcmp(t->id, id) == 0){
140426d2b71SDavid du Colombier if(s && t->open && runestrcmp(t->open, s) == 0)
141426d2b71SDavid du Colombier return;
142426d2b71SDavid du Colombier for(l=&tagset; (tt=*l); l=&tt->next){
143426d2b71SDavid du Colombier if(!hidingset)
144426d2b71SDavid du Colombier out(tt->close);
145426d2b71SDavid du Colombier if(tt == t)
146426d2b71SDavid du Colombier break;
147426d2b71SDavid du Colombier }
148426d2b71SDavid du Colombier *l = t->next;
149426d2b71SDavid du Colombier free(t->id);
150426d2b71SDavid du Colombier free(t->close);
151426d2b71SDavid du Colombier free(t->open);
152426d2b71SDavid du Colombier free(t);
153426d2b71SDavid du Colombier if(!hidingset)
154426d2b71SDavid du Colombier rshow(tagset, *l);
155426d2b71SDavid du Colombier goto cleared;
156426d2b71SDavid du Colombier }
157426d2b71SDavid du Colombier }
158426d2b71SDavid du Colombier
159426d2b71SDavid du Colombier cleared:
160426d2b71SDavid du Colombier if(s == nil || s[0] == 0)
161426d2b71SDavid du Colombier return;
162426d2b71SDavid du Colombier t = emalloc(sizeof *t);
163426d2b71SDavid du Colombier t->id = erunestrdup(id);
164426d2b71SDavid du Colombier t->open = erunestrdup(s);
165426d2b71SDavid du Colombier t->close = closingtag(s);
166426d2b71SDavid du Colombier if(!hidingset)
167426d2b71SDavid du Colombier out(s);
168426d2b71SDavid du Colombier t->next = tagset;
169426d2b71SDavid du Colombier tagset = t;
170426d2b71SDavid du Colombier }
171426d2b71SDavid du Colombier
172426d2b71SDavid du Colombier void
hideihtml(void)173426d2b71SDavid du Colombier hideihtml(void)
174426d2b71SDavid du Colombier {
175426d2b71SDavid du Colombier Tag *t;
176426d2b71SDavid du Colombier
177426d2b71SDavid du Colombier if(hidingset)
178426d2b71SDavid du Colombier return;
179426d2b71SDavid du Colombier hidingset = 1;
180426d2b71SDavid du Colombier for(t=tagset; t; t=t->next)
181426d2b71SDavid du Colombier out(t->close);
182426d2b71SDavid du Colombier }
183426d2b71SDavid du Colombier
184426d2b71SDavid du Colombier void
showihtml(void)185426d2b71SDavid du Colombier showihtml(void)
186426d2b71SDavid du Colombier {
187426d2b71SDavid du Colombier if(!hidingset)
188426d2b71SDavid du Colombier return;
189426d2b71SDavid du Colombier hidingset = 0;
190426d2b71SDavid du Colombier rshow(tagset, nil);
191426d2b71SDavid du Colombier }
192426d2b71SDavid du Colombier
193426d2b71SDavid du Colombier int
e_lt(void)194426d2b71SDavid du Colombier e_lt(void)
195426d2b71SDavid du Colombier {
196426d2b71SDavid du Colombier return Ult;
197426d2b71SDavid du Colombier }
198426d2b71SDavid du Colombier
199426d2b71SDavid du Colombier int
e_gt(void)200426d2b71SDavid du Colombier e_gt(void)
201426d2b71SDavid du Colombier {
202426d2b71SDavid du Colombier return Ugt;
203426d2b71SDavid du Colombier }
204426d2b71SDavid du Colombier
205426d2b71SDavid du Colombier int
e_at(void)206426d2b71SDavid du Colombier e_at(void)
207426d2b71SDavid du Colombier {
208426d2b71SDavid du Colombier return Uamp;
209426d2b71SDavid du Colombier }
210426d2b71SDavid du Colombier
211426d2b71SDavid du Colombier int
e_tick(void)212426d2b71SDavid du Colombier e_tick(void)
213426d2b71SDavid du Colombier {
214426d2b71SDavid du Colombier return Utick;
215426d2b71SDavid du Colombier }
216426d2b71SDavid du Colombier
217426d2b71SDavid du Colombier int
e_btick(void)218426d2b71SDavid du Colombier e_btick(void)
219426d2b71SDavid du Colombier {
220426d2b71SDavid du Colombier return Ubtick;
221426d2b71SDavid du Colombier }
222426d2b71SDavid du Colombier
223426d2b71SDavid du Colombier int
e_minus(void)224426d2b71SDavid du Colombier e_minus(void)
225426d2b71SDavid du Colombier {
226426d2b71SDavid du Colombier return Uminus;
227426d2b71SDavid du Colombier }
228426d2b71SDavid du Colombier
229426d2b71SDavid du Colombier void
r_html(Rune * name)230426d2b71SDavid du Colombier r_html(Rune *name)
231426d2b71SDavid du Colombier {
232426d2b71SDavid du Colombier Rune *id, *line, *p;
233426d2b71SDavid du Colombier
234426d2b71SDavid du Colombier id = copyarg();
235426d2b71SDavid du Colombier line = readline(HtmlMode);
236426d2b71SDavid du Colombier for(p=line; *p; p++){
237426d2b71SDavid du Colombier switch(*p){
238426d2b71SDavid du Colombier case '<':
239426d2b71SDavid du Colombier *p = Ult;
240426d2b71SDavid du Colombier break;
241426d2b71SDavid du Colombier case '>':
242426d2b71SDavid du Colombier *p = Ugt;
243426d2b71SDavid du Colombier break;
244426d2b71SDavid du Colombier case '&':
245426d2b71SDavid du Colombier *p = Uamp;
246426d2b71SDavid du Colombier break;
247426d2b71SDavid du Colombier case ' ':
248426d2b71SDavid du Colombier *p = Uspace;
249426d2b71SDavid du Colombier break;
250426d2b71SDavid du Colombier }
251426d2b71SDavid du Colombier }
252426d2b71SDavid du Colombier if(name[0] == 'i')
253426d2b71SDavid du Colombier ihtml(id, line);
254426d2b71SDavid du Colombier else
255426d2b71SDavid du Colombier html(id, line);
256426d2b71SDavid du Colombier free(id);
257426d2b71SDavid du Colombier free(line);
258426d2b71SDavid du Colombier }
259426d2b71SDavid du Colombier
260426d2b71SDavid du Colombier char defaultfont[] =
261426d2b71SDavid du Colombier ".ihtml f1\n"
262426d2b71SDavid du Colombier ".ihtml f\n"
263*6f1c688eSDavid du Colombier ".ihtml f <span style=\"font-size: \\n(.spt\">\n"
264426d2b71SDavid du Colombier ".if \\n(.f==2 .ihtml f1 <i>\n"
265426d2b71SDavid du Colombier ".if \\n(.f==3 .ihtml f1 <b>\n"
266426d2b71SDavid du Colombier ".if \\n(.f==4 .ihtml f1 <b><i>\n"
267426d2b71SDavid du Colombier ".if \\n(.f==5 .ihtml f1 <tt>\n"
268426d2b71SDavid du Colombier ".if \\n(.f==6 .ihtml f1 <tt><i>\n"
269426d2b71SDavid du Colombier "..\n"
270426d2b71SDavid du Colombier ;
271426d2b71SDavid du Colombier
272426d2b71SDavid du Colombier void
htmlinit(void)273426d2b71SDavid du Colombier htmlinit(void)
274426d2b71SDavid du Colombier {
275426d2b71SDavid du Colombier addraw(L("html"), r_html);
276426d2b71SDavid du Colombier addraw(L("ihtml"), r_html);
277426d2b71SDavid du Colombier
278426d2b71SDavid du Colombier addesc('<', e_lt, CopyMode);
279426d2b71SDavid du Colombier addesc('>', e_gt, CopyMode);
280426d2b71SDavid du Colombier addesc('\'', e_tick, CopyMode);
281426d2b71SDavid du Colombier addesc('`', e_btick, CopyMode);
282426d2b71SDavid du Colombier addesc('-', e_minus, CopyMode);
283426d2b71SDavid du Colombier addesc('@', e_at, CopyMode);
284426d2b71SDavid du Colombier
285426d2b71SDavid du Colombier ds(L("font"), L(defaultfont));
286426d2b71SDavid du Colombier }
287426d2b71SDavid du Colombier
288