Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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