1151497Sru/*
2151497Sru * parse.c
3151497Sru *
4151497Sru * parse dvi input
5151497Sru */
6151497Sru
7151497Sru#include <X11/Xos.h>
8151497Sru#include <X11/IntrinsicP.h>
9151497Sru#include <X11/StringDefs.h>
10151497Sru#include <stdio.h>
11151497Sru#include <ctype.h>
12151497Sru#include "DviP.h"
13151497Sru
14151497Srustatic int StopSeen = 0;
15151497Srustatic void ParseDrawFunction(DviWidget, char *);
16151497Srustatic void ParseDeviceControl(DviWidget);
17151497Srustatic void push_env(DviWidget);
18151497Srustatic void pop_env(DviWidget);
19151497Sru
20151497Sru/* draw.c */
21151497Sruextern int PutCharacter(DviWidget, char *);
22151497Sruextern int PutNumberedCharacter(DviWidget, int);
23151497Sruextern void HorizontalGoto(DviWidget, int);
24151497Sruextern void Word(DviWidget);
25151497Sruextern void VerticalGoto(DviWidget, int);
26151497Sruextern void VerticalMove(DviWidget, int);
27151497Sruextern void FlushCharCache(DviWidget);
28151497Sruextern void Newline(DviWidget);
29151497Sruextern void DrawLine(DviWidget, int, int);
30151497Sruextern void DrawCircle(DviWidget, int);
31151497Sruextern void DrawFilledCircle(DviWidget, int);
32151497Sruextern void DrawEllipse(DviWidget, int, int);
33151497Sruextern void DrawFilledEllipse(DviWidget, int, int);
34151497Sruextern void DrawArc(DviWidget, int, int, int, int);
35151497Sruextern void DrawPolygon(DviWidget, int *, int);
36151497Sruextern void DrawFilledPolygon(DviWidget, int *, int);
37151497Sruextern void DrawSpline(DviWidget, int *, int);
38151497Sru
39151497Sru/* Dvi.c */
40151497Sruextern void SetDevice(DviWidget, const char *);
41151497Sru
42151497Sru/* page.c */
43151497Sruextern void RememberPagePosition(DviWidget, int);
44151497Sru
45151497Sru/* font.c */
46151497Sruextern void SetFontPosition(DviWidget, int, const char *, const char *);
47151497Sru
48151497Sru/* lex.c */
49151497Sruextern int GetNumber(DviWidget);
50151497Sru
51151497Sru#define HorizontalMove(dw, delta)	((dw)->dvi.state->x += (delta))
52151497Sru
53151497Sru
54151497Sruint
55151497SruParseInput(register DviWidget dw)
56151497Sru{
57151497Sru	int		n, k;
58151497Sru	int		c;
59151497Sru	char		Buffer[BUFSIZ];
60151497Sru	int		NextPage;
61151497Sru	int		otherc;
62151497Sru
63151497Sru	StopSeen = 0;
64151497Sru
65151497Sru	/*
66151497Sru	 * make sure some state exists
67151497Sru	 */
68151497Sru
69151497Sru	if (!dw->dvi.state)
70151497Sru	    push_env (dw);
71151497Sru	for (;;) {
72151497Sru		switch (DviGetC(dw, &c)) {
73151497Sru		case '\n':
74151497Sru			break;
75151497Sru		case ' ':	/* when input is text */
76151497Sru		case 0:		/* occasional noise creeps in */
77151497Sru			break;
78151497Sru		case '{':	/* push down current environment */
79151497Sru			push_env(dw);
80151497Sru			break;
81151497Sru		case '}':
82151497Sru			pop_env(dw);
83151497Sru			break;
84151497Sru		/*
85151497Sru		 * two motion digits plus a character
86151497Sru		 */
87151497Sru		case '0': case '1': case '2': case '3': case '4':
88151497Sru		case '5': case '6': case '7': case '8': case '9':
89151497Sru			HorizontalMove(dw, (c-'0')*10 +
90151497Sru					   DviGetC(dw,&otherc)-'0');
91151497Sru			/* fall through */
92151497Sru		case 'c':	/* single ascii character */
93151497Sru			DviGetC(dw,&c);
94151497Sru		    	if (c == ' ')
95151497Sru			    break;
96151497Sru			Buffer[0] = c;
97151497Sru			Buffer[1] = '\0';
98151497Sru			(void) PutCharacter (dw, Buffer);
99151497Sru			break;
100151497Sru		case 'C':
101151497Sru			GetWord (dw, Buffer, BUFSIZ);
102151497Sru			(void) PutCharacter (dw, Buffer);
103151497Sru			break;
104151497Sru		case 't':
105151497Sru			Buffer[1] = '\0';
106151497Sru			while (DviGetC (dw, &c) != EOF
107151497Sru			       && c != ' ' && c != '\n') {
108151497Sru				Buffer[0] = c;
109151497Sru				HorizontalMove (dw, PutCharacter (dw, Buffer));
110151497Sru			}
111151497Sru			break;
112151497Sru		case 'u':
113151497Sru			n = GetNumber(dw);
114151497Sru			Buffer[1] = '\0';
115151497Sru			while (DviGetC (dw, &c) == ' ')
116151497Sru				;
117151497Sru			while (c != EOF && c != ' ' && c != '\n') {
118151497Sru				Buffer[0] = c;
119151497Sru				HorizontalMove (dw,
120151497Sru						PutCharacter (dw, Buffer) + n);
121151497Sru				DviGetC (dw, &c);
122151497Sru			}
123151497Sru			break;
124151497Sru
125151497Sru		case 'D':	/* draw function */
126151497Sru			(void) GetLine(dw, Buffer, BUFSIZ);
127151497Sru			if (dw->dvi.display_enable)
128151497Sru				ParseDrawFunction(dw, Buffer);
129151497Sru			break;
130151497Sru		case 's':	/* ignore fractional sizes */
131151497Sru			n = GetNumber(dw);
132151497Sru			dw->dvi.state->font_size = n;
133151497Sru			break;
134151497Sru		case 'f':
135151497Sru			n = GetNumber(dw);
136151497Sru			dw->dvi.state->font_number = n;
137151497Sru			break;
138151497Sru		case 'H':	/* absolute horizontal motion */
139151497Sru			k = GetNumber(dw);
140151497Sru			HorizontalGoto(dw, k);
141151497Sru			break;
142151497Sru		case 'h':	/* relative horizontal motion */
143151497Sru			k = GetNumber(dw);
144151497Sru			HorizontalMove(dw, k);
145151497Sru			break;
146151497Sru		case 'w':	/* word space */
147151497Sru			Word (dw);
148151497Sru			break;
149151497Sru		case 'V':
150151497Sru			n = GetNumber(dw);
151151497Sru			VerticalGoto(dw, n);
152151497Sru			break;
153151497Sru		case 'v':
154151497Sru			n = GetNumber(dw);
155151497Sru			VerticalMove(dw, n);
156151497Sru			break;
157151497Sru		case 'P':	/* new spread */
158151497Sru			break;
159151497Sru		case 'p':	/* new page */
160151497Sru			(void) GetNumber(dw);
161151497Sru			NextPage = dw->dvi.current_page + 1;
162151497Sru			RememberPagePosition(dw, NextPage);
163151497Sru			FlushCharCache (dw);
164151497Sru			return(NextPage);
165151497Sru		case 'N':
166151497Sru			n = GetNumber(dw);
167151497Sru			PutNumberedCharacter (dw, n);
168151497Sru			break;
169151497Sru		case 'n':	/* end of line */
170151497Sru			GetNumber(dw);
171151497Sru			GetNumber(dw);
172151497Sru			Newline (dw);
173151497Sru			HorizontalGoto(dw, 0);
174151497Sru			break;
175151497Sru		case 'F':       /* input files */
176151497Sru		case '+':	/* continuation of X device control */
177151497Sru		case 'm':	/* color */
178151497Sru		case '#':	/* comment */
179151497Sru			GetLine(dw, NULL, 0);
180151497Sru			break;
181151497Sru		case 'x':	/* device control */
182151497Sru			ParseDeviceControl(dw);
183151497Sru			break;
184151497Sru		case EOF:
185151497Sru			dw->dvi.last_page = dw->dvi.current_page;
186151497Sru			FlushCharCache (dw);
187151497Sru			return dw->dvi.current_page;
188151497Sru		default:
189151497Sru			break;
190151497Sru		}
191151497Sru	}
192151497Sru}
193151497Sru
194151497Srustatic void
195151497Srupush_env(DviWidget dw)
196151497Sru{
197151497Sru	DviState	*new_state;
198151497Sru
199151497Sru	new_state = (DviState *) XtMalloc (sizeof (*new_state));
200151497Sru	if (dw->dvi.state)
201151497Sru		*new_state = *(dw->dvi.state);
202151497Sru	else {
203151497Sru		new_state->font_size = 10;
204151497Sru		new_state->font_number = 1;
205151497Sru		new_state->x = 0;
206151497Sru		new_state->y = 0;
207151497Sru	}
208151497Sru	new_state->next = dw->dvi.state;
209151497Sru	dw->dvi.state = new_state;
210151497Sru}
211151497Sru
212151497Srustatic void
213151497Srupop_env(DviWidget dw)
214151497Sru{
215151497Sru	DviState	*old;
216151497Sru
217151497Sru	old = dw->dvi.state;
218151497Sru	dw->dvi.state = old->next;
219151497Sru	XtFree ((char *) old);
220151497Sru}
221151497Sru
222151497Srustatic void
223151497SruInitTypesetter (DviWidget dw)
224151497Sru{
225151497Sru	while (dw->dvi.state)
226151497Sru		pop_env (dw);
227151497Sru	push_env (dw);
228151497Sru	FlushCharCache (dw);
229151497Sru}
230151497Sru
231151497Sru#define DRAW_ARGS_MAX 128
232151497Sru
233151497Srustatic void
234151497SruParseDrawFunction(DviWidget dw, char *buf)
235151497Sru{
236151497Sru	int v[DRAW_ARGS_MAX];
237151497Sru	int i, no_move = 0;
238151497Sru	char *ptr;
239151497Sru
240151497Sru	v[0] = v[1] = v[2] = v[3] = 0;
241151497Sru
242151497Sru	if (buf[0] == '\0')
243151497Sru		return;
244151497Sru	ptr = buf+1;
245151497Sru
246151497Sru	for (i = 0; i < DRAW_ARGS_MAX; i++) {
247151497Sru		if (sscanf(ptr, "%d", v + i) != 1)
248151497Sru			break;
249151497Sru		while (*ptr == ' ')
250151497Sru			ptr++;
251151497Sru		while (*ptr != '\0' && *ptr != ' ')
252151497Sru			ptr++;
253151497Sru	}
254151497Sru
255151497Sru	switch (buf[0]) {
256151497Sru	case 'l':				/* draw a line */
257151497Sru		DrawLine(dw, v[0], v[1]);
258151497Sru		break;
259151497Sru	case 'c':				/* circle */
260151497Sru		DrawCircle(dw, v[0]);
261151497Sru		break;
262151497Sru	case 'C':
263151497Sru		DrawFilledCircle(dw, v[0]);
264151497Sru		break;
265151497Sru	case 'e':				/* ellipse */
266151497Sru		DrawEllipse(dw, v[0], v[1]);
267151497Sru		break;
268151497Sru	case 'E':
269151497Sru		DrawFilledEllipse(dw, v[0], v[1]);
270151497Sru		break;
271151497Sru	case 'a':				/* arc */
272151497Sru		DrawArc(dw, v[0], v[1], v[2], v[3]);
273151497Sru		break;
274151497Sru	case 'p':
275151497Sru		DrawPolygon(dw, v, i);
276151497Sru		break;
277151497Sru	case 'P':
278151497Sru		DrawFilledPolygon(dw, v, i);
279151497Sru		break;
280151497Sru	case '~':				/* wiggly line */
281151497Sru		DrawSpline(dw, v, i);
282151497Sru		break;
283151497Sru	case 't':
284151497Sru		dw->dvi.line_thickness = v[0];
285151497Sru		break;
286151497Sru	case 'f':
287151497Sru		if (i > 0 && v[0] >= 0 && v[0] <= DVI_FILL_MAX)
288151497Sru			dw->dvi.fill = v[0];
289151497Sru		no_move = 1;
290151497Sru		break;
291151497Sru	default:
292151497Sru#if 0
293151497Sru		warning("unknown drawing function %s", buf);
294151497Sru#endif
295151497Sru		no_move = 1;
296151497Sru		break;
297151497Sru	}
298151497Sru
299151497Sru	if (!no_move) {
300151497Sru		if (buf[0] == 'e') {
301151497Sru			if (i > 0)
302151497Sru				dw->dvi.state->x += v[0];
303151497Sru		}
304151497Sru		else {
305151497Sru			while (--i >= 0) {
306151497Sru				if (i & 1)
307151497Sru					dw->dvi.state->y += v[i];
308151497Sru				else
309151497Sru					dw->dvi.state->x += v[i];
310151497Sru			}
311151497Sru		}
312151497Sru	}
313151497Sru}
314151497Sru
315151497Srustatic void
316151497SruParseDeviceControl(DviWidget dw)		/* Parse the x commands */
317151497Sru{
318151497Sru        char str[20], str1[50];
319151497Sru	int c, n;
320151497Sru
321151497Sru	GetWord (dw, str, 20);
322151497Sru	switch (str[0]) {			/* crude for now */
323151497Sru	case 'T':				/* output device */
324151497Sru		GetWord (dw, str, 20);
325151497Sru		SetDevice (dw, str);
326151497Sru		break;
327151497Sru	case 'i':				/* initialize */
328151497Sru		InitTypesetter (dw);
329151497Sru		break;
330151497Sru	case 't':				/* trailer */
331151497Sru		break;
332151497Sru	case 'p':				/* pause -- can restart */
333151497Sru		break;
334151497Sru	case 's':				/* stop */
335151497Sru		StopSeen = 1;
336151497Sru		return;
337151497Sru	case 'r':				/* resolution when prepared */
338151497Sru		break;
339151497Sru	case 'f':				/* font used */
340151497Sru		n = GetNumber (dw);
341151497Sru		GetWord (dw, str, 20);
342151497Sru		GetLine (dw, str1, 50);
343151497Sru		SetFontPosition (dw, n, str, str1);
344151497Sru		break;
345151497Sru	case 'H':				/* char height */
346151497Sru		break;
347151497Sru	case 'S':				/* slant */
348151497Sru		break;
349151497Sru	}
350151497Sru	while (DviGetC (dw, &c) != '\n')	/* skip rest of input line */
351151497Sru		if (c == EOF)
352151497Sru			return;
353151497Sru	return;
354151497Sru}
355151497Sru
356151497Sru
357151497Sru/*
358151497SruLocal Variables:
359151497Sruc-indent-level: 8
360151497Sruc-continued-statement-offset: 8
361151497Sruc-brace-offset: -8
362151497Sruc-argdecl-indent: 8
363151497Sruc-label-offset: -8
364151497Sruc-tab-always-indent: nil
365151497SruEnd:
366151497Sru*/
367