parse.c revision 65912f00
1/* $XConsortium: parse.c,v 1.13 94/04/17 20:43:36 keith Exp $ */ 2/* 3 4Copyright (c) 1991 X Consortium 5 6Permission is hereby granted, free of charge, to any person obtaining 7a copy of this software and associated documentation files (the 8"Software"), to deal in the Software without restriction, including 9without limitation the rights to use, copy, modify, merge, publish, 10distribute, sublicense, and/or sell copies of the Software, and to 11permit persons to whom the Software is furnished to do so, subject to 12the following conditions: 13 14The above copyright notice and this permission notice shall be included 15in all copies or substantial portions of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 21OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23OTHER DEALINGS IN THE SOFTWARE. 24 25Except as contained in this notice, the name of the X Consortium shall 26not be used in advertising or otherwise to promote the sale, use or 27other dealings in this Software without prior written authorization 28from the X Consortium. 29 30*/ 31/* $XFree86: xc/programs/xditview/parse.c,v 1.5tsi Exp $ */ 32 33/* 34 * parse.c 35 * 36 * parse dvi input 37 */ 38 39#include <X11/Xos.h> 40#include <X11/IntrinsicP.h> 41#include <X11/StringDefs.h> 42#include <stdio.h> 43#include <ctype.h> 44#include "DviP.h" 45 46static void ParseDrawFunction(DviWidget dw, char *buf); 47static void ParseDeviceControl(DviWidget dw); 48static void PutCharacters(DviWidget dw, unsigned char *src, int len); 49static void push_env(DviWidget dw); 50static void pop_env(DviWidget dw); 51 52#define HorizontalMove(dw, delta) ((dw)->dvi.state->x += (delta)) 53 54#ifdef USE_XFT 55static int 56charWidth (DviWidget dw, XftFont *font, char c) 57{ 58 XGlyphInfo extents; 59 60 XftTextExtents8 (XtDisplay (dw), font, 61 (unsigned char *) &c, 1, &extents); 62 return extents.xOff; 63} 64#else 65#define charWidth(dw,fi,c) (\ 66 (fi)->per_char ?\ 67 (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\ 68 :\ 69 (fi)->max_bounds.width\ 70) 71#endif 72 73int 74ParseInput(DviWidget dw) 75{ 76 int n, k; 77 int c; 78 char Buffer[BUFSIZ]; 79 int NextPage; 80 int prevFont; 81 int otherc; 82 unsigned char tc; 83 84 /* 85 * make sure some state exists 86 */ 87 88 if (!dw->dvi.state) 89 push_env (dw); 90 for (;;) { 91 switch (DviGetC(dw, &c)) { 92 case '\n': 93 break; 94 case ' ': /* when input is text */ 95 case 0: /* occasional noise creeps in */ 96 break; 97 case '{': /* push down current environment */ 98 push_env(dw); 99 break; 100 case '}': 101 pop_env(dw); 102 break; 103 /* 104 * two motion digits plus a character 105 */ 106 case '0': case '1': case '2': case '3': case '4': 107 case '5': case '6': case '7': case '8': case '9': 108 HorizontalMove(dw, (c-'0')*10 + 109 DviGetC(dw,&otherc)-'0'); 110 /* fall through */ 111 case 'c': /* single ascii character */ 112 (void) DviGetC(dw,&c); 113 if (c == ' ') 114 break; 115 tc = c; 116 PutCharacters (dw, &tc, 1); 117 break; 118 case 'C': 119 GetWord(dw, Buffer, BUFSIZ); 120 { 121 DviCharNameMap *map; 122 int i; 123 unsigned char *ligature; 124 125 c = -1; 126 map = QueryFontMap (dw, dw->dvi.state->font_number); 127 if (map) 128 { 129 c = DviCharIndex (map, Buffer); 130 if (c == -1) 131 { 132 ligature = DviCharIsLigature (map, Buffer); 133 if (ligature) { 134 i = strlen ((char *) ligature); 135 PutCharacters (dw, ligature, i); 136 break; 137 } 138 } 139 } 140 prevFont = -1; 141 if (c == -1) { 142 for (i = 1; (map = QueryFontMap (dw, i)); i++) 143 if (map->special) 144 if ((c = DviCharIndex (map, Buffer)) != -1) { 145 prevFont = dw->dvi.state->font_number; 146 dw->dvi.state->font_number = i; 147 break; 148 } 149 } 150 if (c != -1) 151 { 152 tc = c; 153 PutCharacters (dw, &tc, 1); 154 } 155 if (prevFont != -1) 156 dw->dvi.state->font_number = prevFont; 157 } 158 break; 159 case 'D': /* draw function */ 160 GetLine(dw, Buffer, BUFSIZ); 161 ParseDrawFunction(dw, Buffer); 162 break; 163 case 's': /* ignore fractional sizes */ 164 n = GetNumber(dw); 165 if (!dw->dvi.size_scale) 166 { 167 static int guesses[] = { 1, 4, 100, 1000, 1 }; 168 int i; 169 170 for (i = 0; i < 4; i++) 171 if (8 <= n/guesses[i] && n/guesses[i] <= 24) 172 { 173 break; 174 } 175 dw->dvi.size_scale = guesses[i]; 176 } 177 dw->dvi.state->font_size = n; 178 dw->dvi.state->line_width = n * (dw->dvi.device_resolution / 179 (720 * dw->dvi.size_scale)); 180 break; 181 case 'f': 182 n = GetNumber(dw); 183 dw->dvi.state->font_number = n; 184 break; 185 case 'H': /* absolute horizontal motion */ 186 k = GetNumber(dw); 187 HorizontalGoto(dw, k); 188 break; 189 case 'h': /* relative horizontal motion */ 190 k = GetNumber(dw); 191 HorizontalMove(dw, k); 192 break; 193 case 'w': /* word space */ 194 break; 195 case 'V': 196 n = GetNumber(dw); 197 VerticalGoto(dw, n); 198 break; 199 case 'v': 200 n = GetNumber(dw); 201 VerticalMove(dw, n); 202 break; 203 case 'P': /* new spread */ 204 break; 205 case 'p': /* new page */ 206 (void) GetNumber(dw); 207 NextPage = dw->dvi.current_page + 1; 208 RememberPagePosition(dw, NextPage); 209 FlushCharCache (dw); 210 return(NextPage); 211 case 'n': /* end of line */ 212 GetNumber(dw); 213 GetNumber(dw); 214 HorizontalGoto(dw, 0); 215 break; 216 case '#': /* comment */ 217 case 'F': /* file info */ 218 GetLine(dw, NULL, 0); 219 break; 220 case 't': /* text */ 221 GetLine(dw, Buffer, BUFSIZ); 222 PutCharacters (dw, (unsigned char *)Buffer, 223 strlen (Buffer)); 224 dw->dvi.state->x = ToDevice (dw, dw->dvi.cache.x); 225 break; 226 case 'x': /* device control */ 227 ParseDeviceControl(dw); 228 break; 229 case EOF: 230 dw->dvi.last_page = dw->dvi.current_page; 231 FlushCharCache (dw); 232 return dw->dvi.current_page; 233 default: 234 GetLine (dw, Buffer, BUFSIZ); 235 fprintf (stderr, "Unknown command %s\n", Buffer); 236 break; 237 } 238 } 239} 240 241static void 242push_env(DviWidget dw) 243{ 244 DviState *new; 245 246 new = (DviState *) XtMalloc (sizeof (*new)); 247 if (dw->dvi.state) 248 *new = *(dw->dvi.state); 249 else { 250 new->font_size = 10 * dw->dvi.size_scale; 251 new->font_number = 1; 252 new->line_style = 0; 253 new->line_width = 10; 254 new->x = 0; 255 new->y = 0; 256 } 257 new->next = dw->dvi.state; 258 dw->dvi.state = new; 259} 260 261static void 262pop_env(DviWidget dw) 263{ 264 DviState *old; 265 266 old = dw->dvi.state; 267 dw->dvi.state = old->next; 268 XtFree ((char *) old); 269} 270 271static void 272InitTypesetter (DviWidget dw) 273{ 274 while (dw->dvi.state) 275 pop_env (dw); 276 dw->dvi.size_scale = dw->dvi.size_scale_set; 277 push_env (dw); 278 FlushCharCache (dw); 279} 280 281static void 282SetFont (DviWidget dw) 283{ 284 dw->dvi.cache.font_size = dw->dvi.state->font_size; 285 dw->dvi.cache.font_number = dw->dvi.state->font_number; 286 dw->dvi.cache.font = QueryFont (dw, 287 dw->dvi.cache.font_number, 288 dw->dvi.cache.font_size); 289} 290 291static void 292PutCharacters (DviWidget dw, unsigned char *src, int len) 293{ 294 int xx, yx; 295 int fx, fy; 296 char *dst; 297 int c; 298 299 xx = ToX(dw, dw->dvi.state->x); 300 yx = ToX(dw, dw->dvi.state->y); 301 fy = FontSizeInPixels (dw, dw->dvi.state->font_size); 302 fx = fy * len; 303 /* 304 * quick and dirty extents calculation: 305 */ 306 if (yx + fy >= dw->dvi.extents.y1 && 307 yx - fy <= dw->dvi.extents.y2 && 308 xx + fx >= dw->dvi.extents.x1 && 309 xx - fx <= dw->dvi.extents.x2) 310 { 311#ifdef USE_XFT 312 XftFont *font; 313 DviTextItem *text; 314#else 315 register XFontStruct *font; 316 register XTextItem *text; 317#endif 318 319 if (!dw->dvi.display_enable) 320 return; 321 322 if (yx != dw->dvi.cache.y || 323 dw->dvi.cache.char_index + len > DVI_CHAR_CACHE_SIZE) 324 FlushCharCache (dw); 325 /* 326 * load a new font, if the current block is not empty, 327 * step to the next. 328 */ 329 if (dw->dvi.cache.font_size != dw->dvi.state->font_size || 330 dw->dvi.cache.font_number != dw->dvi.state->font_number) 331 { 332 SetFont (dw); 333 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) { 334 ++dw->dvi.cache.index; 335 if (dw->dvi.cache.index >= dw->dvi.cache.max) 336 FlushCharCache (dw); 337 dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0; 338 } 339 } 340 if (xx != dw->dvi.cache.x) { 341 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) { 342 ++dw->dvi.cache.index; 343 if (dw->dvi.cache.index >= dw->dvi.cache.max) 344 FlushCharCache (dw); 345 dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0; 346 } 347 } 348 if (!dw->dvi.cache.font) 349 SetFont (dw); 350 text = &dw->dvi.cache.cache[dw->dvi.cache.index]; 351 font = dw->dvi.cache.font; 352 dst = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index]; 353 if (text->nchars == 0) { 354 text->chars = dst; 355#ifdef USE_XFT 356 text->x = xx; 357#else 358 text->delta = xx - dw->dvi.cache.x; 359#endif 360#ifdef USE_XFT 361 text->font = font; 362#endif 363 if (font != dw->dvi.font) { 364#ifndef USE_XFT 365 text->font = font->fid; 366#endif 367 dw->dvi.font = font; 368 } 369#ifndef USE_XFT 370 else 371 text->font = None; 372#endif 373 dw->dvi.cache.x = xx; 374 } 375 dw->dvi.cache.char_index += len; 376 text->nchars += len; 377 while (len--) 378 { 379 c = *src++; 380 *dst++ = c; 381 if (font) 382 dw->dvi.cache.x += charWidth(dw,font,c); 383 } 384 } 385} 386 387static void 388ParseDrawFunction(DviWidget dw, char *buf) 389{ 390 int n, m, n1, m1; 391 392 SetGCForDraw (dw); 393 switch (buf[0]) { 394 case 'l': /* draw a line */ 395 sscanf(buf+1, "%d %d", &n, &m); 396 DrawLine(dw, n, m); 397 break; 398 case 'c': /* circle */ 399 sscanf(buf+1, "%d", &n); 400 DrawCircle(dw, n); 401 break; 402 case 'e': /* ellipse */ 403 sscanf(buf+1, "%d %d", &m, &n); 404 DrawEllipse(dw, m, n); 405 break; 406 case 'a': /* arc */ 407 sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1); 408 DrawArc(dw, n, m, n1, m1); 409 break; 410 case '~': /* wiggly line */ 411 DrawSpline(dw, buf+1,1); 412 break; 413 case 't': /* line width */ 414 sscanf(buf+1, "%d", &n); 415 dw->dvi.state->line_width = n; 416 break; 417 case 's': /* line style */ 418 sscanf(buf+1, "%d", &n); 419 /* XXX */ 420 break; 421 default: 422 /* warning("unknown drawing function %s", buf); */ 423 break; 424 } 425} 426 427extern int LastPage, CurrentPage; 428 429static void 430ParseDeviceControl(DviWidget dw) /* Parse the x commands */ 431{ 432 char str[20], str1[50]; 433 int c, n; 434 435 GetWord (dw, str, 20); 436 switch (str[0]) { /* crude for now */ 437 case 'T': /* output device */ 438 GetWord(dw, str, 20); 439 break; 440 case 'i': /* initialize */ 441 InitTypesetter (dw); 442 break; 443 case 't': /* trailer */ 444 break; 445 case 'p': /* pause -- can restart */ 446 break; 447 case 's': /* stop */ 448 return; 449 case 'r': /* resolution when prepared */ 450 SetDeviceResolution (dw, GetNumber (dw)); 451 break; 452 case 'f': /* font used */ 453 n = GetNumber(dw); 454 GetWord(dw, str, 20); 455 GetLine(dw, str1, 50); 456 SetFontPosition(dw, n, str, str1); 457 break; 458 case 'H': /* char height */ 459 break; 460 case 'S': /* slant */ 461 break; 462 } 463 while (DviGetC(dw,&c) != '\n') /* skip rest of input line */ 464 if (c == EOF) 465 return; 466} 467