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