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