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