1/* $NetBSD$ */ 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 16static int StopSeen = 0; 17static void ParseDrawFunction(DviWidget, char *); 18static void ParseDeviceControl(DviWidget); 19static void push_env(DviWidget); 20static void pop_env(DviWidget); 21 22/* draw.c */ 23extern int PutCharacter(DviWidget, char *); 24extern int PutNumberedCharacter(DviWidget, int); 25extern void HorizontalGoto(DviWidget, int); 26extern void Word(DviWidget); 27extern void VerticalGoto(DviWidget, int); 28extern void VerticalMove(DviWidget, int); 29extern void FlushCharCache(DviWidget); 30extern void Newline(DviWidget); 31extern void DrawLine(DviWidget, int, int); 32extern void DrawCircle(DviWidget, int); 33extern void DrawFilledCircle(DviWidget, int); 34extern void DrawEllipse(DviWidget, int, int); 35extern void DrawFilledEllipse(DviWidget, int, int); 36extern void DrawArc(DviWidget, int, int, int, int); 37extern void DrawPolygon(DviWidget, int *, int); 38extern void DrawFilledPolygon(DviWidget, int *, int); 39extern void DrawSpline(DviWidget, int *, int); 40 41/* Dvi.c */ 42extern void SetDevice(DviWidget, const char *); 43 44/* page.c */ 45extern void RememberPagePosition(DviWidget, int); 46 47/* font.c */ 48extern void SetFontPosition(DviWidget, int, const char *, const char *); 49 50/* lex.c */ 51extern int GetNumber(DviWidget); 52 53#define HorizontalMove(dw, delta) ((dw)->dvi.state->x += (delta)) 54 55 56int 57ParseInput(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 196static void 197push_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 214static void 215pop_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 224static void 225InitTypesetter (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 235static void 236ParseDrawFunction(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 317static void 318ParseDeviceControl(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/* 360Local Variables: 361c-indent-level: 8 362c-continued-statement-offset: 8 363c-brace-offset: -8 364c-argdecl-indent: 8 365c-label-offset: -8 366c-tab-always-indent: nil 367End: 368*/ 369