Don't use .Xo/.Xc. Fix date format.
[netbsd-mini2440.git] / gnu / usr.bin / groff / libXdvi / parse.c
blobb10936907a2c8930b533b965b29123600fa2c89d
1 /*
2 * parse.c
4 * parse dvi input
5 */
7 #include <X11/Xos.h>
8 #include <X11/IntrinsicP.h>
9 #include <X11/StringDefs.h>
10 #include <stdio.h>
11 #include <ctype.h>
12 #include "DviP.h"
14 static int StopSeen = 0;
15 static ParseDrawFunction(), ParseDeviceControl();
16 static push_env(), pop_env();
18 #define HorizontalMove(dw, delta) ((dw)->dvi.state->x += (delta))
20 #define charWidth(fi,c) (\
21 (fi)->per_char ?\
22 (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
24 (fi)->max_bounds.width\
28 int charExists (fi, c)
29 XFontStruct *fi;
30 int c;
32 XCharStruct *p;
34 if (c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
35 return 0;
36 p = fi->per_char + (c - fi->min_char_or_byte2);
37 return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
38 || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
42 ParseInput(dw)
43 register DviWidget dw;
45 int n, k;
46 int c;
47 char Buffer[BUFSIZ];
48 int NextPage;
49 int prevFont;
50 int otherc;
52 StopSeen = 0;
55 * make sure some state exists
58 if (!dw->dvi.state)
59 push_env (dw);
60 for (;;) {
61 switch (DviGetC(dw, &c)) {
62 case '\n':
63 break;
64 case ' ': /* when input is text */
65 case 0: /* occasional noise creeps in */
66 break;
67 case '{': /* push down current environment */
68 push_env(dw);
69 break;
70 case '}':
71 pop_env(dw);
72 break;
74 * two motion digits plus a character
76 case '0': case '1': case '2': case '3': case '4':
77 case '5': case '6': case '7': case '8': case '9':
78 HorizontalMove(dw, (c-'0')*10 +
79 DviGetC(dw,&otherc)-'0');
80 /* fall through */
81 case 'c': /* single ascii character */
82 DviGetC(dw,&c);
83 if (c == ' ')
84 break;
85 Buffer[0] = c;
86 Buffer[1] = '\0';
87 goto FunnyCharacter;
89 case 'C':
90 GetWord(dw, Buffer, BUFSIZ);
91 FunnyCharacter:
92 prevFont = -1;
93 c = -1;
95 DviCharNameMap *map;
96 int i;
98 map = QueryFontMap (dw, dw->dvi.state->font_number);
99 if (map) {
100 c = DviCharIndex (map, Buffer);
101 if (c == -1) {
102 for (i = 1; map = QueryFontMap (dw, i); i++)
103 if (map->special)
104 if ((c = DviCharIndex (map, Buffer)) != -1) {
105 prevFont = dw->dvi.state->font_number;
106 dw->dvi.state->font_number = i;
107 break;
112 if (c == -1)
113 break;
114 NumberedCharacter:
116 * quick and dirty extents calculation:
118 if (dw->dvi.state->y + 24 >= dw->dvi.extents.y1 &&
119 dw->dvi.state->y - 24 <= dw->dvi.extents.y2 &&
120 dw->dvi.state->x + 24 >= dw->dvi.extents.x1 &&
121 dw->dvi.state->x - 24 <= dw->dvi.extents.x2)
123 register XFontStruct *font;
124 register XTextItem *text;
126 if (!dw->dvi.display_enable)
127 break;
129 if (dw->dvi.state->y != dw->dvi.cache.y ||
130 dw->dvi.cache.char_index >= DVI_CHAR_CACHE_SIZE)
131 FlushCharCache (dw);
133 * load a new font, if the current block is not empty,
134 * step to the next.
136 if (dw->dvi.cache.font_size != dw->dvi.state->font_size ||
137 dw->dvi.cache.font_number != dw->dvi.state->font_number)
139 dw->dvi.cache.font_size = dw->dvi.state->font_size;
140 dw->dvi.cache.font_number = dw->dvi.state->font_number;
141 dw->dvi.cache.font = QueryFont (dw,
142 dw->dvi.cache.font_number,
143 dw->dvi.cache.font_size);
144 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
145 ++dw->dvi.cache.index;
146 if (dw->dvi.cache.index >= dw->dvi.cache.max)
147 FlushCharCache (dw);
148 dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
151 if (dw->dvi.cache.x != dw->dvi.state->x) {
152 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
153 ++dw->dvi.cache.index;
154 if (dw->dvi.cache.index >= dw->dvi.cache.max)
155 FlushCharCache (dw);
156 dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
159 font = dw->dvi.cache.font;
160 text = &dw->dvi.cache.cache[dw->dvi.cache.index];
161 if (text->nchars == 0) {
162 text->chars = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index];
163 text->delta = dw->dvi.state->x - dw->dvi.cache.x;
164 if (font != dw->dvi.font) {
165 text->font = font->fid;
166 dw->dvi.font = font;
167 } else
168 text->font = None;
169 dw->dvi.cache.x += text->delta;
171 if (charExists(font, c)) {
172 dw->dvi.cache.char_cache[dw->dvi.cache.char_index++] = (char) c;
173 ++text->nchars;
174 dw->dvi.cache.x += charWidth(font,c);
177 if (prevFont != -1)
178 dw->dvi.state->font_number = prevFont;
179 break;
180 case 'D': /* draw function */
181 GetLine(dw, Buffer, BUFSIZ);
182 if (dw->dvi.display_enable)
183 ParseDrawFunction(dw, Buffer);
184 break;
185 case 's': /* ignore fractional sizes */
186 n = GetNumber(dw);
187 dw->dvi.state->font_size = n;
188 break;
189 case 'f':
190 n = GetNumber(dw);
191 dw->dvi.state->font_number = n;
192 break;
193 case 'H': /* absolute horizontal motion */
194 k = GetNumber(dw);
195 HorizontalGoto(dw, k);
196 break;
197 case 'h': /* relative horizontal motion */
198 k = GetNumber(dw);
199 HorizontalMove(dw, k);
200 break;
201 case 'w': /* word space */
202 break;
203 case 'V':
204 n = GetNumber(dw);
205 VerticalGoto(dw, n);
206 break;
207 case 'v':
208 n = GetNumber(dw);
209 VerticalMove(dw, n);
210 break;
211 case 'P': /* new spread */
212 break;
213 case 'p': /* new page */
214 (void) GetNumber(dw);
215 NextPage = dw->dvi.current_page + 1;
216 RememberPagePosition(dw, NextPage);
217 FlushCharCache (dw);
218 return(NextPage);
219 case 'N':
220 c = GetNumber(dw);
221 goto NumberedCharacter;
222 case 'n': /* end of line */
223 GetNumber(dw);
224 GetNumber(dw);
225 HorizontalGoto(dw, 0);
226 break;
227 case '+': /* continuation of X device control */
228 case '#': /* comment */
229 GetLine(dw, NULL, 0);
230 break;
231 case 'x': /* device control */
232 ParseDeviceControl(dw);
233 break;
234 case EOF:
235 dw->dvi.last_page = dw->dvi.current_page;
236 FlushCharCache (dw);
237 return dw->dvi.current_page;
238 default:
239 break;
244 static
245 push_env(dw)
246 DviWidget dw;
248 DviState *new;
250 new = (DviState *) malloc (sizeof (*new));
251 if (dw->dvi.state)
252 *new = *(dw->dvi.state);
253 else {
254 new->font_size = 10;
255 new->font_number = 1;
256 new->x = 0;
257 new->y = 0;
259 new->next = dw->dvi.state;
260 dw->dvi.state = new;
263 static
264 pop_env(dw)
265 DviWidget dw;
267 DviState *old;
269 old = dw->dvi.state;
270 dw->dvi.state = old->next;
271 free ((char *) old);
274 static
275 InitTypesetter (dw)
276 DviWidget dw;
278 while (dw->dvi.state)
279 pop_env (dw);
280 push_env (dw);
281 FlushCharCache (dw);
284 #define DRAW_ARGS_MAX 128
286 static
287 ParseDrawFunction(dw, buf)
288 DviWidget dw;
289 char *buf;
291 int v[DRAW_ARGS_MAX];
292 int i;
293 char *ptr;
295 v[0] = v[1] = v[2] = v[3] = 0;
297 if (buf[0] == '\0')
298 return;
299 ptr = buf+1;
301 for (i = 0; i < DRAW_ARGS_MAX; i++) {
302 if (sscanf(ptr, "%d", v + i) != 1)
303 break;
304 while (*ptr == ' ')
305 ptr++;
306 while (*ptr != '\0' && *ptr != ' ')
307 ptr++;
310 switch (buf[0]) {
311 case 'l': /* draw a line */
312 DrawLine(dw, v[0], v[1]);
313 break;
314 case 'c': /* circle */
315 DrawCircle(dw, v[0]);
316 break;
317 case 'C':
318 DrawFilledCircle(dw, v[0]);
319 break;
320 case 'e': /* ellipse */
321 DrawEllipse(dw, v[0], v[1]);
322 break;
323 case 'E':
324 DrawFilledEllipse(dw, v[0], v[1]);
325 break;
326 case 'a': /* arc */
327 DrawArc(dw, v[0], v[1], v[2], v[3]);
328 break;
329 case 'p':
330 DrawPolygon(dw, v, i);
331 break;
332 case 'P':
333 DrawFilledPolygon(dw, v, i);
334 break;
335 case '~': /* wiggly line */
336 DrawSpline(dw, v, i);
337 break;
338 case 't':
339 dw->dvi.line_thickness = v[0];
340 break;
341 case 'f':
342 if (i > 0 && v[0] >= 0 && v[0] <= DVI_FILL_MAX)
343 dw->dvi.fill = v[0];
344 break;
345 default:
346 #if 0
347 warning("unknown drawing function %s", buf);
348 #endif
349 break;
352 if (buf[0] == 'e') {
353 if (i > 0)
354 dw->dvi.state->x += v[0];
356 else {
357 while (--i >= 0) {
358 if (i & 1)
359 dw->dvi.state->y += v[i];
360 else
361 dw->dvi.state->x += v[i];
366 static
367 ParseDeviceControl(dw) /* Parse the x commands */
368 DviWidget dw;
370 char str[20], str1[50], buf[50];
371 int c, n;
372 extern int LastPage, CurrentPage;
374 GetWord (dw, str, 20);
375 switch (str[0]) { /* crude for now */
376 case 'T': /* output device */
377 GetWord(dw, str, 20);
378 break;
379 case 'i': /* initialize */
380 InitTypesetter (dw);
381 break;
382 case 't': /* trailer */
383 break;
384 case 'p': /* pause -- can restart */
385 break;
386 case 's': /* stop */
387 StopSeen = 1;
388 return;
389 case 'r': /* resolution when prepared */
390 SetDeviceResolution (dw, GetNumber (dw));
391 break;
392 case 'f': /* font used */
393 n = GetNumber(dw);
394 GetWord(dw, str, 20);
395 GetLine(dw, str1, 50);
396 SetFontPosition(dw, n, str, str1);
397 break;
398 case 'H': /* char height */
399 break;
400 case 'S': /* slant */
401 break;
403 while (DviGetC(dw,&c) != '\n') /* skip rest of input line */
404 if (c == EOF)
405 return;
406 return;
411 Local Variables:
412 c-indent-level: 8
413 c-continued-statement-offset: 8
414 c-brace-offset: -8
415 c-argdecl-indent: 8
416 c-label-offset: -8
417 c-tab-always-indent: nil
418 End: