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