1 /*
2 * parse.c
3 *
4 * parse dvi input
5 */
6
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 "config.h"
13 #include "DviP.h"
14 #include "encoding.h"
15
16 static int StopSeen = 0;
17 static void ParseDrawFunction(), ParseDeviceControl();
18 static void push_env(), pop_env();
19
20 /* draw.c */
21 extern int PutCharacter();
22 extern int PutNumberedCharacter();
23 extern void HorizontalGoto();
24 extern void Word();
25 extern void VerticalGoto();
26 extern void VerticalMove();
27 extern void FlushCharCache();
28 extern void Newline();
29 extern void DrawLine();
30 extern void DrawCircle();
31 extern void DrawFilledCircle();
32 extern void DrawEllipse();
33 extern void DrawFilledEllipse();
34 extern void DrawArc();
35 extern void DrawPolygon();
36 extern void DrawFilledPolygon();
37 extern void DrawSpline();
38
39 /* Dvi.c */
40 extern void SetDevice();
41
42 /* page.c */
43 extern void RememberPagePosition();
44
45 /* font.c */
46 extern void SetFontPosition();
47
48 /* lex.c */
49 extern int GetNumber();
50
51 #define HorizontalMove(dw, delta) ((dw)->dvi.state->x += (delta))
52
53
54 int
ParseInput(dw)55 ParseInput(dw)
56 register DviWidget dw;
57 {
58 int n, k;
59 int c;
60 char Buffer[BUFSIZ];
61 int NextPage;
62 int otherc;
63
64 StopSeen = 0;
65
66 /*
67 * make sure some state exists
68 */
69
70 if (!dw->dvi.state)
71 push_env (dw);
72 for (;;) {
73 switch (DviGetC(dw, &c)) {
74 case '\n':
75 break;
76 case ' ': /* when input is text */
77 case 0: /* occasional noise creeps in */
78 break;
79 case '{': /* push down current environment */
80 push_env(dw);
81 break;
82 case '}':
83 pop_env(dw);
84 break;
85 /*
86 * two motion digits plus a character
87 */
88 case '0': case '1': case '2': case '3': case '4':
89 case '5': case '6': case '7': case '8': case '9':
90 HorizontalMove(dw, (c-'0')*10 +
91 DviGetC(dw,&otherc)-'0');
92 /* fall through */
93 case 'c': /* single ascii character */
94 #ifdef ENABLE_MULTIBYTE
95 DviGetCharacter(dw, Buffer);
96 if (Buffer[0] == ' ')
97 break;
98 #else
99 DviGetC(dw,&c);
100 if (c == ' ')
101 break;
102 Buffer[0] = c;
103 Buffer[1] = '\0';
104 #endif
105 (void) PutCharacter (dw, Buffer);
106 break;
107 case 'C':
108 GetWord (dw, Buffer, BUFSIZ);
109 (void) PutCharacter (dw, Buffer);
110 break;
111 case 't':
112 #ifdef ENABLE_MULTIBYTE
113 while (DviGetCharacter(dw, Buffer) != EOF
114 && Buffer[0] != ' ' && Buffer[0] != '\n') {
115 #else
116 Buffer[1] = '\0';
117 while (DviGetC (dw, &c) != EOF
118 && c != ' ' && c != '\n') {
119 Buffer[0] = c;
120 #endif
121 HorizontalMove (dw, PutCharacter (dw, Buffer));
122 }
123 break;
124 case 'u':
125 n = GetNumber(dw);
126 Buffer[1] = '\0';
127 while (DviGetC (dw, &c) == ' ')
128 ;
129 while (c != EOF && c != ' ' && c != '\n') {
130 Buffer[0] = c;
131 HorizontalMove (dw,
132 PutCharacter (dw, Buffer) + n);
133 DviGetC (dw, &c);
134 }
135 break;
136
137 case 'D': /* draw function */
138 (void) GetLine(dw, Buffer, BUFSIZ);
139 if (dw->dvi.display_enable)
140 ParseDrawFunction(dw, Buffer);
141 break;
142 case 's': /* ignore fractional sizes */
143 n = GetNumber(dw);
144 dw->dvi.state->font_size = n;
145 break;
146 case 'f':
147 n = GetNumber(dw);
148 dw->dvi.state->font_number = n;
149 break;
150 case 'H': /* absolute horizontal motion */
151 k = GetNumber(dw);
152 HorizontalGoto(dw, k);
153 break;
154 case 'h': /* relative horizontal motion */
155 k = GetNumber(dw);
156 HorizontalMove(dw, k);
157 break;
158 case 'w': /* word space */
159 Word (dw);
160 break;
161 case 'V':
162 n = GetNumber(dw);
163 VerticalGoto(dw, n);
164 break;
165 case 'v':
166 n = GetNumber(dw);
167 VerticalMove(dw, n);
168 break;
169 case 'P': /* new spread */
170 break;
171 case 'p': /* new page */
172 (void) GetNumber(dw);
173 NextPage = dw->dvi.current_page + 1;
174 RememberPagePosition(dw, NextPage);
175 FlushCharCache (dw);
176 return(NextPage);
177 case 'N':
178 n = GetNumber(dw);
179 PutNumberedCharacter (dw, n);
180 break;
181 case 'n': /* end of line */
182 GetNumber(dw);
183 GetNumber(dw);
184 Newline (dw);
185 HorizontalGoto(dw, 0);
186 break;
187 case 'F': /* input files */
188 case '+': /* continuation of X device control */
189 case 'm': /* color */
190 case '#': /* comment */
191 GetLine(dw, NULL, 0);
192 break;
193 case 'x': /* device control */
194 ParseDeviceControl(dw);
195 break;
196 case EOF:
197 dw->dvi.last_page = dw->dvi.current_page;
198 FlushCharCache (dw);
199 return dw->dvi.current_page;
200 default:
201 break;
202 }
203 }
204 }
205
206 static void
push_env(dw)207 push_env(dw)
208 DviWidget dw;
209 {
210 DviState *new;
211
212 new = (DviState *) XtMalloc (sizeof (*new));
213 if (dw->dvi.state)
214 *new = *(dw->dvi.state);
215 else {
216 new->font_size = 10;
217 new->font_number = 1;
218 new->x = 0;
219 new->y = 0;
220 }
221 new->next = dw->dvi.state;
222 dw->dvi.state = new;
223 }
224
225 static void
pop_env(dw)226 pop_env(dw)
227 DviWidget dw;
228 {
229 DviState *old;
230
231 old = dw->dvi.state;
232 dw->dvi.state = old->next;
233 XtFree ((char *) old);
234 }
235
236 static void
InitTypesetter(dw)237 InitTypesetter (dw)
238 DviWidget dw;
239 {
240 while (dw->dvi.state)
241 pop_env (dw);
242 push_env (dw);
243 FlushCharCache (dw);
244 }
245
246 #define DRAW_ARGS_MAX 128
247
248 static void
ParseDrawFunction(dw,buf)249 ParseDrawFunction(dw, buf)
250 DviWidget dw;
251 char *buf;
252 {
253 int v[DRAW_ARGS_MAX];
254 int i, no_move = 0;
255 char *ptr;
256
257 v[0] = v[1] = v[2] = v[3] = 0;
258
259 if (buf[0] == '\0')
260 return;
261 ptr = buf+1;
262
263 for (i = 0; i < DRAW_ARGS_MAX; i++) {
264 if (sscanf(ptr, "%d", v + i) != 1)
265 break;
266 while (*ptr == ' ')
267 ptr++;
268 while (*ptr != '\0' && *ptr != ' ')
269 ptr++;
270 }
271
272 switch (buf[0]) {
273 case 'l': /* draw a line */
274 DrawLine(dw, v[0], v[1]);
275 break;
276 case 'c': /* circle */
277 DrawCircle(dw, v[0]);
278 break;
279 case 'C':
280 DrawFilledCircle(dw, v[0]);
281 break;
282 case 'e': /* ellipse */
283 DrawEllipse(dw, v[0], v[1]);
284 break;
285 case 'E':
286 DrawFilledEllipse(dw, v[0], v[1]);
287 break;
288 case 'a': /* arc */
289 DrawArc(dw, v[0], v[1], v[2], v[3]);
290 break;
291 case 'p':
292 DrawPolygon(dw, v, i);
293 break;
294 case 'P':
295 DrawFilledPolygon(dw, v, i);
296 break;
297 case '~': /* wiggly line */
298 DrawSpline(dw, v, i);
299 break;
300 case 't':
301 dw->dvi.line_thickness = v[0];
302 break;
303 case 'f':
304 if (i > 0 && v[0] >= 0 && v[0] <= DVI_FILL_MAX)
305 dw->dvi.fill = v[0];
306 no_move = 1;
307 break;
308 default:
309 #if 0
310 warning("unknown drawing function %s", buf);
311 #endif
312 no_move = 1;
313 break;
314 }
315
316 if (!no_move) {
317 if (buf[0] == 'e') {
318 if (i > 0)
319 dw->dvi.state->x += v[0];
320 }
321 else {
322 while (--i >= 0) {
323 if (i & 1)
324 dw->dvi.state->y += v[i];
325 else
326 dw->dvi.state->x += v[i];
327 }
328 }
329 }
330 }
331
332 static void
ParseDeviceControl(dw)333 ParseDeviceControl(dw) /* Parse the x commands */
334 DviWidget dw;
335 {
336 char str[20], str1[50];
337 int c, n;
338
339 GetWord (dw, str, 20);
340 switch (str[0]) { /* crude for now */
341 case 'T': /* output device */
342 GetWord (dw, str, 20);
343 SetDevice (dw, str);
344 break;
345 case 'i': /* initialize */
346 InitTypesetter (dw);
347 break;
348 case 't': /* trailer */
349 break;
350 case 'p': /* pause -- can restart */
351 break;
352 case 's': /* stop */
353 StopSeen = 1;
354 return;
355 case 'r': /* resolution when prepared */
356 break;
357 case 'f': /* font used */
358 n = GetNumber (dw);
359 GetWord (dw, str, 20);
360 GetLine (dw, str1, 50);
361 SetFontPosition (dw, n, str, str1);
362 break;
363 case 'H': /* char height */
364 break;
365 case 'S': /* slant */
366 break;
367 }
368 while (DviGetC (dw, &c) != '\n') /* skip rest of input line */
369 if (c == EOF)
370 return;
371 return;
372 }
373
374
375 /*
376 Local Variables:
377 c-indent-level: 8
378 c-continued-statement-offset: 8
379 c-brace-offset: -8
380 c-argdecl-indent: 8
381 c-label-offset: -8
382 c-tab-always-indent: nil
383 End:
384 */
385