parse.c revision f80a6dcd
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(dw) 75 DviWidget dw; 76{ 77 int n, k; 78 int c; 79 char Buffer[BUFSIZ]; 80 int NextPage; 81 int prevFont; 82 int otherc; 83 unsigned char tc; 84 85 /* 86 * make sure some state exists 87 */ 88 89 if (!dw->dvi.state) 90 push_env (dw); 91 for (;;) { 92 switch (DviGetC(dw, &c)) { 93 case '\n': 94 break; 95 case ' ': /* when input is text */ 96 case 0: /* occasional noise creeps in */ 97 break; 98 case '{': /* push down current environment */ 99 push_env(dw); 100 break; 101 case '}': 102 pop_env(dw); 103 break; 104 /* 105 * two motion digits plus a character 106 */ 107 case '0': case '1': case '2': case '3': case '4': 108 case '5': case '6': case '7': case '8': case '9': 109 HorizontalMove(dw, (c-'0')*10 + 110 DviGetC(dw,&otherc)-'0'); 111 /* fall through */ 112 case 'c': /* single ascii character */ 113 (void) DviGetC(dw,&c); 114 if (c == ' ') 115 break; 116 tc = c; 117 PutCharacters (dw, &tc, 1); 118 break; 119 case 'C': 120 GetWord(dw, Buffer, BUFSIZ); 121 { 122 DviCharNameMap *map; 123 int i; 124 unsigned char *ligature; 125 126 c = -1; 127 map = QueryFontMap (dw, dw->dvi.state->font_number); 128 if (map) 129 { 130 c = DviCharIndex (map, Buffer); 131 if (c == -1) 132 { 133 ligature = DviCharIsLigature (map, Buffer); 134 if (ligature) { 135 i = strlen ((char *) ligature); 136 PutCharacters (dw, ligature, i); 137 break; 138 } 139 } 140 } 141 prevFont = -1; 142 if (c == -1) { 143 for (i = 1; (map = QueryFontMap (dw, i)); i++) 144 if (map->special) 145 if ((c = DviCharIndex (map, Buffer)) != -1) { 146 prevFont = dw->dvi.state->font_number; 147 dw->dvi.state->font_number = i; 148 break; 149 } 150 } 151 if (c != -1) 152 { 153 tc = c; 154 PutCharacters (dw, &tc, 1); 155 } 156 if (prevFont != -1) 157 dw->dvi.state->font_number = prevFont; 158 } 159 break; 160 case 'D': /* draw function */ 161 GetLine(dw, Buffer, BUFSIZ); 162 ParseDrawFunction(dw, Buffer); 163 break; 164 case 's': /* ignore fractional sizes */ 165 n = GetNumber(dw); 166 if (!dw->dvi.size_scale) 167 { 168 static int guesses[] = { 1, 4, 100, 1000, 1 }; 169 int i; 170 171 for (i = 0; i < 4; i++) 172 if (8 <= n/guesses[i] && n/guesses[i] <= 24) 173 { 174 break; 175 } 176 dw->dvi.size_scale = guesses[i]; 177 } 178 dw->dvi.state->font_size = n; 179 dw->dvi.state->line_width = n * (dw->dvi.device_resolution / 180 (720 * dw->dvi.size_scale)); 181 break; 182 case 'f': 183 n = GetNumber(dw); 184 dw->dvi.state->font_number = n; 185 break; 186 case 'H': /* absolute horizontal motion */ 187 k = GetNumber(dw); 188 HorizontalGoto(dw, k); 189 break; 190 case 'h': /* relative horizontal motion */ 191 k = GetNumber(dw); 192 HorizontalMove(dw, k); 193 break; 194 case 'w': /* word space */ 195 break; 196 case 'V': 197 n = GetNumber(dw); 198 VerticalGoto(dw, n); 199 break; 200 case 'v': 201 n = GetNumber(dw); 202 VerticalMove(dw, n); 203 break; 204 case 'P': /* new spread */ 205 break; 206 case 'p': /* new page */ 207 (void) GetNumber(dw); 208 NextPage = dw->dvi.current_page + 1; 209 RememberPagePosition(dw, NextPage); 210 FlushCharCache (dw); 211 return(NextPage); 212 case 'n': /* end of line */ 213 GetNumber(dw); 214 GetNumber(dw); 215 HorizontalGoto(dw, 0); 216 break; 217 case '#': /* comment */ 218 case 'F': /* file info */ 219 GetLine(dw, NULL, 0); 220 break; 221 case 't': /* text */ 222 GetLine(dw, Buffer, BUFSIZ); 223 PutCharacters (dw, (unsigned char *)Buffer, 224 strlen (Buffer)); 225 dw->dvi.state->x = ToDevice (dw, dw->dvi.cache.x); 226 break; 227 case 'x': /* device control */ 228 ParseDeviceControl(dw); 229 break; 230 case EOF: 231 dw->dvi.last_page = dw->dvi.current_page; 232 FlushCharCache (dw); 233 return dw->dvi.current_page; 234 default: 235 GetLine (dw, Buffer, BUFSIZ); 236 fprintf (stderr, "Unknown command %s\n", Buffer); 237 break; 238 } 239 } 240} 241 242static void 243push_env(dw) 244 DviWidget dw; 245{ 246 DviState *new; 247 248 new = (DviState *) XtMalloc (sizeof (*new)); 249 if (dw->dvi.state) 250 *new = *(dw->dvi.state); 251 else { 252 new->font_size = 10 * dw->dvi.size_scale; 253 new->font_number = 1; 254 new->line_style = 0; 255 new->line_width = 10; 256 new->x = 0; 257 new->y = 0; 258 } 259 new->next = dw->dvi.state; 260 dw->dvi.state = new; 261} 262 263static void 264pop_env(dw) 265 DviWidget dw; 266{ 267 DviState *old; 268 269 old = dw->dvi.state; 270 dw->dvi.state = old->next; 271 XtFree ((char *) old); 272} 273 274static void 275InitTypesetter (DviWidget dw) 276{ 277 while (dw->dvi.state) 278 pop_env (dw); 279 dw->dvi.size_scale = dw->dvi.size_scale_set; 280 push_env (dw); 281 FlushCharCache (dw); 282} 283 284static void 285SetFont (DviWidget dw) 286{ 287 dw->dvi.cache.font_size = dw->dvi.state->font_size; 288 dw->dvi.cache.font_number = dw->dvi.state->font_number; 289 dw->dvi.cache.font = QueryFont (dw, 290 dw->dvi.cache.font_number, 291 dw->dvi.cache.font_size); 292} 293 294static void 295PutCharacters (dw, src, len) 296 DviWidget dw; 297 unsigned char *src; 298 int len; 299{ 300 int xx, yx; 301 int fx, fy; 302 char *dst; 303 int c; 304 305 xx = ToX(dw, dw->dvi.state->x); 306 yx = ToX(dw, dw->dvi.state->y); 307 fy = FontSizeInPixels (dw, dw->dvi.state->font_size); 308 fx = fy * len; 309 /* 310 * quick and dirty extents calculation: 311 */ 312 if (yx + fy >= dw->dvi.extents.y1 && 313 yx - fy <= dw->dvi.extents.y2 && 314 xx + fx >= dw->dvi.extents.x1 && 315 xx - fx <= dw->dvi.extents.x2) 316 { 317#ifdef USE_XFT 318 XftFont *font; 319 DviTextItem *text; 320#else 321 register XFontStruct *font; 322 register XTextItem *text; 323#endif 324 325 if (!dw->dvi.display_enable) 326 return; 327 328 if (yx != dw->dvi.cache.y || 329 dw->dvi.cache.char_index + len > DVI_CHAR_CACHE_SIZE) 330 FlushCharCache (dw); 331 /* 332 * load a new font, if the current block is not empty, 333 * step to the next. 334 */ 335 if (dw->dvi.cache.font_size != dw->dvi.state->font_size || 336 dw->dvi.cache.font_number != dw->dvi.state->font_number) 337 { 338 SetFont (dw); 339 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) { 340 ++dw->dvi.cache.index; 341 if (dw->dvi.cache.index >= dw->dvi.cache.max) 342 FlushCharCache (dw); 343 dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0; 344 } 345 } 346 if (xx != dw->dvi.cache.x) { 347 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) { 348 ++dw->dvi.cache.index; 349 if (dw->dvi.cache.index >= dw->dvi.cache.max) 350 FlushCharCache (dw); 351 dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0; 352 } 353 } 354 if (!dw->dvi.cache.font) 355 SetFont (dw); 356 text = &dw->dvi.cache.cache[dw->dvi.cache.index]; 357 font = dw->dvi.cache.font; 358 dst = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index]; 359 if (text->nchars == 0) { 360 text->chars = dst; 361#ifdef USE_XFT 362 text->x = xx; 363#else 364 text->delta = xx - dw->dvi.cache.x; 365#endif 366#ifdef USE_XFT 367 text->font = font; 368#endif 369 if (font != dw->dvi.font) { 370#ifndef USE_XFT 371 text->font = font->fid; 372#endif 373 dw->dvi.font = font; 374 } 375#ifndef USE_XFT 376 else 377 text->font = None; 378#endif 379 dw->dvi.cache.x = xx; 380 } 381 dw->dvi.cache.char_index += len; 382 text->nchars += len; 383 while (len--) 384 { 385 c = *src++; 386 *dst++ = c; 387 if (font) 388 dw->dvi.cache.x += charWidth(dw,font,c); 389 } 390 } 391} 392 393static void 394ParseDrawFunction(dw, buf) 395 DviWidget dw; 396 char *buf; 397{ 398 int n, m, n1, m1; 399 400 SetGCForDraw (dw); 401 switch (buf[0]) { 402 case 'l': /* draw a line */ 403 sscanf(buf+1, "%d %d", &n, &m); 404 DrawLine(dw, n, m); 405 break; 406 case 'c': /* circle */ 407 sscanf(buf+1, "%d", &n); 408 DrawCircle(dw, n); 409 break; 410 case 'e': /* ellipse */ 411 sscanf(buf+1, "%d %d", &m, &n); 412 DrawEllipse(dw, m, n); 413 break; 414 case 'a': /* arc */ 415 sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1); 416 DrawArc(dw, n, m, n1, m1); 417 break; 418 case '~': /* wiggly line */ 419 DrawSpline(dw, buf+1,1); 420 break; 421 case 't': /* line width */ 422 sscanf(buf+1, "%d", &n); 423 dw->dvi.state->line_width = n; 424 break; 425 case 's': /* line style */ 426 sscanf(buf+1, "%d", &n); 427 /* XXX */ 428 break; 429 default: 430 /* warning("unknown drawing function %s", buf); */ 431 break; 432 } 433} 434 435extern int LastPage, CurrentPage; 436 437static void 438ParseDeviceControl(dw) /* Parse the x commands */ 439 DviWidget dw; 440{ 441 char str[20], str1[50]; 442 int c, n; 443 444 GetWord (dw, str, 20); 445 switch (str[0]) { /* crude for now */ 446 case 'T': /* output device */ 447 GetWord(dw, str, 20); 448 break; 449 case 'i': /* initialize */ 450 InitTypesetter (dw); 451 break; 452 case 't': /* trailer */ 453 break; 454 case 'p': /* pause -- can restart */ 455 break; 456 case 's': /* stop */ 457 return; 458 case 'r': /* resolution when prepared */ 459 SetDeviceResolution (dw, GetNumber (dw)); 460 break; 461 case 'f': /* font used */ 462 n = GetNumber(dw); 463 GetWord(dw, str, 20); 464 GetLine(dw, str1, 50); 465 SetFontPosition(dw, n, str, str1); 466 break; 467 case 'H': /* char height */ 468 break; 469 case 'S': /* slant */ 470 break; 471 } 472 while (DviGetC(dw,&c) != '\n') /* skip rest of input line */ 473 if (c == EOF) 474 return; 475} 476