1 /* $NetBSD: Dvi.c,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $ */ 2 3 #ifndef SABER 4 #ifndef lint 5 static char Xrcsid[] = "$XConsortium: Dvi.c,v 1.9 89/12/10 16:12:25 rws Exp $"; 6 #endif /* lint */ 7 #endif /* SABER */ 8 9 /* 10 * Dvi.c - Dvi display widget 11 * 12 */ 13 14 #define XtStrlen(s) ((s) ? strlen(s) : 0) 15 16 /* The following are defined for the reader's convenience. Any 17 Xt..Field macro in this code just refers to some field in 18 one of the substructures of the WidgetRec. */ 19 20 #include <X11/IntrinsicP.h> 21 #include <X11/StringDefs.h> 22 #include <X11/Xmu/Converters.h> 23 #include <stdio.h> 24 #include <ctype.h> 25 #include "DviP.h" 26 27 /**************************************************************** 28 * 29 * Full class record constant 30 * 31 ****************************************************************/ 32 33 /* Private Data */ 34 35 static char default_font_map_1[] = "\ 36 TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ 37 TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\ 38 TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ 39 TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\ 40 CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ 41 CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\ 42 CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ 43 CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\ 44 "; 45 static char default_font_map_2[] = "\ 46 HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ 47 HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\ 48 HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ 49 HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\ 50 "; 51 static char default_font_map_3[] = "\ 52 NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ 53 NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\ 54 NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ 55 NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\ 56 S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\ 57 SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\ 58 "; 59 60 #define offset(field) XtOffset(DviWidget, field) 61 62 #define MY_WIDTH(dw) ((int)(dw->dvi.paperwidth * dw->dvi.scale_factor + .5)) 63 #define MY_HEIGHT(dw) ((int)(dw->dvi.paperlength * dw->dvi.scale_factor + .5)) 64 65 static XtResource resources[] = { 66 {(String)XtNfontMap, (String)XtCFontMap, (String)XtRString, 67 sizeof (char *), offset(dvi.font_map_string), 68 (String)XtRString, NULL /* set in code */}, 69 {(String)XtNforeground, (String)XtCForeground, (String)XtRPixel, 70 sizeof (unsigned long), offset(dvi.foreground), 71 (String)XtRString, (XtPointer)"XtDefaultForeground"}, 72 {(String)XtNbackground, (String)XtCBackground, (String)XtRPixel, 73 sizeof (unsigned long), offset(dvi.background), 74 (String)XtRString, (XtPointer)"XtDefaultBackground"}, 75 {(String)XtNpageNumber, (String)XtCPageNumber, (String)XtRInt, 76 sizeof (int), offset(dvi.requested_page), 77 (String)XtRString, (XtPointer)"1"}, 78 {(String)XtNlastPageNumber, (String)XtCLastPageNumber, (String)XtRInt, 79 sizeof (int), offset (dvi.last_page), 80 (String)XtRString, (XtPointer)"0"}, 81 {(String)XtNfile, (String)XtCFile, (String)XtRFile, 82 sizeof (FILE *), offset (dvi.file), 83 (String)XtRFile, (XtPointer)0}, 84 {(String)XtNseek, (String)XtCSeek, (String)XtRBoolean, 85 sizeof (Boolean), offset(dvi.seek), 86 (String)XtRString, (XtPointer)"false"}, 87 {(String)XtNfont, (String)XtCFont, (String)XtRFontStruct, 88 sizeof (XFontStruct *), offset(dvi.default_font), 89 (String)XtRString, (XtPointer)"xtdefaultfont"}, 90 {(String)XtNbackingStore, (String)XtCBackingStore, (String)XtRBackingStore, 91 sizeof (int), offset(dvi.backing_store), 92 (String)XtRString, (XtPointer)"default"}, 93 {(String)XtNnoPolyText, (String)XtCNoPolyText, (String)XtRBoolean, 94 sizeof (Boolean), offset(dvi.noPolyText), 95 (String)XtRString, (XtPointer)"false"}, 96 {(String)XtNresolution, (String)XtCResolution, (String)XtRInt, 97 sizeof(int), offset(dvi.default_resolution), 98 (String)XtRString, (XtPointer)"75"}, 99 }; 100 101 #undef offset 102 103 static void ClassInitialize (void); 104 static void ClassPartInitialize(WidgetClass); 105 static void Initialize(Widget, Widget, ArgList, Cardinal *); 106 static void Realize (Widget, XtValueMask *, XSetWindowAttributes *); 107 static void Destroy (Widget); 108 static void Redisplay (Widget, XEvent *, Region); 109 static Boolean SetValues (Widget, Widget, Widget, 110 ArgList, Cardinal *); 111 static Boolean SetValuesHook (Widget, ArgList, Cardinal *); 112 static XtGeometryResult QueryGeometry (Widget, XtWidgetGeometry *, 113 XtWidgetGeometry *); 114 static void ShowDvi (DviWidget); 115 static void CloseFile (DviWidget); 116 static void OpenFile (DviWidget); 117 static void FindPage (DviWidget); 118 119 static void SaveToFile (Widget, FILE *); 120 121 /* font.c */ 122 extern void ParseFontMap(DviWidget); 123 extern void DestroyFontMap(DviFontMap *); 124 extern void ForgetFonts(DviWidget); 125 126 /* page.c */ 127 extern void DestroyFileMap(DviFileMap *); 128 extern long SearchPagePosition(DviWidget, int); 129 extern void FileSeek(DviWidget, long); 130 extern void ForgetPagePositions(DviWidget); 131 132 /* parse.c */ 133 extern int ParseInput(register DviWidget); 134 135 DviClassRec dviClassRec = { 136 { 137 &widgetClassRec, /* superclass */ 138 (String)"Dvi", /* class_name */ 139 sizeof(DviRec), /* size */ 140 ClassInitialize, /* class_initialize */ 141 ClassPartInitialize, /* class_part_initialize */ 142 FALSE, /* class_inited */ 143 Initialize, /* initialize */ 144 NULL, /* initialize_hook */ 145 Realize, /* realize */ 146 NULL, /* actions */ 147 0, /* num_actions */ 148 resources, /* resources */ 149 XtNumber(resources), /* resource_count */ 150 NULLQUARK, /* xrm_class */ 151 FALSE, /* compress_motion */ 152 TRUE, /* compress_exposure */ 153 TRUE, /* compress_enterleave */ 154 FALSE, /* visible_interest */ 155 Destroy, /* destroy */ 156 NULL, /* resize */ 157 Redisplay, /* expose */ 158 SetValues, /* set_values */ 159 SetValuesHook, /* set_values_hook */ 160 NULL, /* set_values_almost */ 161 NULL, /* get_values_hook */ 162 NULL, /* accept_focus */ 163 XtVersion, /* version */ 164 NULL, /* callback_private */ 165 0, /* tm_table */ 166 QueryGeometry, /* query_geometry */ 167 NULL, /* display_accelerator */ 168 NULL /* extension */ 169 },{ 170 SaveToFile, /* save */ 171 }, 172 }; 173 174 WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec; 175 176 static void ClassInitialize (void) 177 { 178 int len1 = strlen(default_font_map_1); 179 int len2 = strlen(default_font_map_2); 180 int len3 = strlen(default_font_map_3); 181 char *dfm = XtMalloc(len1 + len2 + len3 + 1); 182 char *ptr = dfm; 183 strcpy(ptr, default_font_map_1); ptr += len1; 184 strcpy(ptr, default_font_map_2); ptr += len2; 185 strcpy(ptr, default_font_map_3); 186 resources[0].default_addr = dfm; 187 188 XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore, 189 NULL, 0 ); 190 } 191 192 /**************************************************************** 193 * 194 * Private Procedures 195 * 196 ****************************************************************/ 197 198 /* ARGSUSED */ 199 static void Initialize(Widget request, Widget new_wd, 200 ArgList args, Cardinal *num_args) 201 { 202 DviWidget dw = (DviWidget) new_wd; 203 204 dw->dvi.current_page = 0; 205 dw->dvi.font_map = 0; 206 dw->dvi.cache.index = 0; 207 dw->dvi.text_x_width = 0; 208 dw->dvi.text_device_width = 0; 209 dw->dvi.word_flag = 0; 210 dw->dvi.file = 0; 211 dw->dvi.tmpFile = 0; 212 dw->dvi.state = 0; 213 dw->dvi.readingTmp = 0; 214 dw->dvi.cache.char_index = 0; 215 dw->dvi.cache.font_size = -1; 216 dw->dvi.cache.font_number = -1; 217 dw->dvi.cache.adjustable[0] = 0; 218 dw->dvi.file_map = 0; 219 dw->dvi.fonts = 0; 220 dw->dvi.seek = False; 221 dw->dvi.device_resolution = dw->dvi.default_resolution; 222 dw->dvi.display_resolution = dw->dvi.default_resolution; 223 dw->dvi.paperlength = dw->dvi.default_resolution*11; 224 dw->dvi.paperwidth = (dw->dvi.default_resolution*8 225 + dw->dvi.default_resolution/2); 226 dw->dvi.scale_factor = 1.0; 227 dw->dvi.sizescale = 1; 228 dw->dvi.line_thickness = -1; 229 dw->dvi.line_width = 1; 230 dw->dvi.fill = DVI_FILL_MAX; 231 dw->dvi.device_font = 0; 232 dw->dvi.device_font_number = -1; 233 dw->dvi.device = 0; 234 dw->dvi.native = 0; 235 236 request = request; /* unused; suppress compiler warning */ 237 args = args; 238 num_args = num_args; 239 } 240 241 #include "gray1.bm" 242 #include "gray2.bm" 243 #include "gray3.bm" 244 #include "gray4.bm" 245 #include "gray5.bm" 246 #include "gray6.bm" 247 #include "gray7.bm" 248 #include "gray8.bm" 249 250 static void 251 Realize (Widget w, XtValueMask *valueMask, XSetWindowAttributes *attrs) 252 { 253 DviWidget dw = (DviWidget) w; 254 XGCValues values; 255 256 if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) { 257 attrs->backing_store = dw->dvi.backing_store; 258 *valueMask |= CWBackingStore; 259 } 260 XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent, 261 *valueMask, attrs); 262 values.foreground = dw->dvi.foreground; 263 values.cap_style = CapRound; 264 values.join_style = JoinRound; 265 values.line_width = dw->dvi.line_width; 266 dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w), 267 GCForeground|GCCapStyle|GCJoinStyle 268 |GCLineWidth, 269 &values); 270 dw->dvi.gray[0] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), 271 gray1_bits, 272 gray1_width, gray1_height); 273 dw->dvi.gray[1] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), 274 gray2_bits, 275 gray2_width, gray2_height); 276 dw->dvi.gray[2] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), 277 gray3_bits, 278 gray3_width, gray3_height); 279 dw->dvi.gray[3] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), 280 gray4_bits, 281 gray4_width, gray4_height); 282 dw->dvi.gray[4] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), 283 gray5_bits, 284 gray5_width, gray5_height); 285 dw->dvi.gray[5] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), 286 gray6_bits, 287 gray6_width, gray6_height); 288 dw->dvi.gray[6] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), 289 gray7_bits, 290 gray7_width, gray7_height); 291 dw->dvi.gray[7] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), 292 gray8_bits, 293 gray8_width, gray8_height); 294 values.background = dw->dvi.background; 295 values.stipple = dw->dvi.gray[5]; 296 dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w), 297 GCForeground|GCBackground|GCStipple, 298 &values); 299 300 dw->dvi.fill_type = 9; 301 302 if (dw->dvi.file) 303 OpenFile (dw); 304 ParseFontMap (dw); 305 } 306 307 static void 308 Destroy(Widget w) 309 { 310 DviWidget dw = (DviWidget) w; 311 312 XFreeGC (XtDisplay (w), dw->dvi.normal_GC); 313 XFreeGC (XtDisplay (w), dw->dvi.fill_GC); 314 XFreePixmap (XtDisplay (w), dw->dvi.gray[0]); 315 XFreePixmap (XtDisplay (w), dw->dvi.gray[1]); 316 XFreePixmap (XtDisplay (w), dw->dvi.gray[2]); 317 XFreePixmap (XtDisplay (w), dw->dvi.gray[3]); 318 XFreePixmap (XtDisplay (w), dw->dvi.gray[4]); 319 XFreePixmap (XtDisplay (w), dw->dvi.gray[5]); 320 XFreePixmap (XtDisplay (w), dw->dvi.gray[6]); 321 XFreePixmap (XtDisplay (w), dw->dvi.gray[7]); 322 DestroyFontMap (dw->dvi.font_map); 323 DestroyFileMap (dw->dvi.file_map); 324 device_destroy (dw->dvi.device); 325 } 326 327 /* 328 * Repaint the widget window 329 */ 330 331 /* ARGSUSED */ 332 static void 333 Redisplay(Widget w, XEvent *event, Region region) 334 { 335 DviWidget dw = (DviWidget) w; 336 XRectangle extents; 337 338 XClipBox (region, &extents); 339 dw->dvi.extents.x1 = extents.x; 340 dw->dvi.extents.y1 = extents.y; 341 dw->dvi.extents.x2 = extents.x + extents.width; 342 dw->dvi.extents.y2 = extents.y + extents.height; 343 ShowDvi (dw); 344 345 event = event; /* unused; suppress compiler warning */ 346 } 347 348 /* 349 * Set specified arguments into widget 350 */ 351 /* ARGSUSED */ 352 static Boolean 353 SetValues (Widget wcurrent, Widget wrequest, Widget wnew, 354 ArgList args, Cardinal *num_args) 355 { 356 Boolean redisplay = FALSE; 357 char *new_map; 358 int cur, req; 359 DviWidget current = (DviWidget)wcurrent; 360 DviWidget request = (DviWidget)wrequest; 361 DviWidget new_wd = (DviWidget)wnew; 362 363 if (current->dvi.font_map_string != request->dvi.font_map_string) { 364 new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1); 365 if (new_map) { 366 redisplay = TRUE; 367 strcpy (new_map, request->dvi.font_map_string); 368 new_wd->dvi.font_map_string = new_map; 369 if (current->dvi.font_map_string) 370 XtFree (current->dvi.font_map_string); 371 current->dvi.font_map_string = 0; 372 ParseFontMap (new_wd); 373 } 374 } 375 376 req = request->dvi.requested_page; 377 cur = current->dvi.requested_page; 378 if (cur != req) { 379 if (!request->dvi.file) 380 req = 0; 381 else { 382 if (req < 1) 383 req = 1; 384 if (current->dvi.last_page != 0 && 385 req > current->dvi.last_page) 386 req = current->dvi.last_page; 387 } 388 if (cur != req) 389 redisplay = TRUE; 390 new_wd->dvi.requested_page = req; 391 if (current->dvi.last_page == 0 && req > cur) 392 FindPage (new_wd); 393 } 394 395 args = args; /* unused; suppress compiler warning */ 396 num_args = num_args; 397 398 return redisplay; 399 } 400 401 /* 402 * use the set_values_hook entry to check when 403 * the file is set 404 */ 405 406 static Boolean 407 SetValuesHook (Widget wdw, ArgList args, Cardinal *num_argsp) 408 { 409 Cardinal i; 410 DviWidget dw = (DviWidget)wdw; 411 412 for (i = 0; i < *num_argsp; i++) { 413 if (!strcmp (args[i].name, XtNfile)) { 414 CloseFile (dw); 415 OpenFile (dw); 416 return TRUE; 417 } 418 } 419 return FALSE; 420 } 421 422 static void CloseFile (DviWidget dw) 423 { 424 if (dw->dvi.tmpFile) 425 fclose (dw->dvi.tmpFile); 426 ForgetPagePositions (dw); 427 } 428 429 static void OpenFile (DviWidget dw) 430 { 431 dw->dvi.tmpFile = 0; 432 if (!dw->dvi.seek) 433 dw->dvi.tmpFile = tmpfile(); 434 dw->dvi.requested_page = 1; 435 dw->dvi.last_page = 0; 436 } 437 438 static XtGeometryResult 439 QueryGeometry (Widget w, XtWidgetGeometry *request, 440 XtWidgetGeometry *geometry_return) 441 { 442 XtGeometryResult ret; 443 DviWidget dw = (DviWidget) w; 444 445 ret = XtGeometryYes; 446 if (((request->request_mode & CWWidth) 447 && request->width < MY_WIDTH(dw)) 448 || ((request->request_mode & CWHeight) 449 && request->height < MY_HEIGHT(dw))) 450 ret = XtGeometryAlmost; 451 geometry_return->width = MY_WIDTH(dw); 452 geometry_return->height = MY_HEIGHT(dw); 453 geometry_return->request_mode = CWWidth|CWHeight; 454 return ret; 455 } 456 457 void 458 SetDevice (DviWidget dw, const char *name) 459 { 460 XtWidgetGeometry request, reply; 461 XtGeometryResult ret; 462 463 ForgetFonts (dw); 464 dw->dvi.device = device_load (name); 465 if (!dw->dvi.device) 466 return; 467 dw->dvi.sizescale = dw->dvi.device->sizescale; 468 dw->dvi.device_resolution = dw->dvi.device->res; 469 dw->dvi.native = dw->dvi.device->X11; 470 dw->dvi.paperlength = dw->dvi.device->paperlength; 471 dw->dvi.paperwidth = dw->dvi.device->paperwidth; 472 if (dw->dvi.native) { 473 dw->dvi.display_resolution = dw->dvi.device_resolution; 474 dw->dvi.scale_factor = 1.0; 475 } 476 else { 477 dw->dvi.display_resolution = dw->dvi.default_resolution; 478 dw->dvi.scale_factor = ((double)dw->dvi.display_resolution 479 / dw->dvi.device_resolution); 480 } 481 request.request_mode = CWWidth|CWHeight; 482 request.width = MY_WIDTH(dw); 483 request.height = MY_HEIGHT(dw); 484 ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply); 485 if (ret == XtGeometryAlmost 486 && reply.height >= request.height 487 && reply.width >= request.width) { 488 request.width = reply.width; 489 request.height = reply.height; 490 XtMakeGeometryRequest ((Widget)dw, &request, &reply); 491 } 492 } 493 494 static void 495 ShowDvi (DviWidget dw) 496 { 497 if (!dw->dvi.file) { 498 static char Error[] = "No file selected"; 499 500 XSetFont (XtDisplay(dw), dw->dvi.normal_GC, 501 dw->dvi.default_font->fid); 502 XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC, 503 20, 20, Error, strlen (Error)); 504 return; 505 } 506 507 FindPage (dw); 508 509 dw->dvi.display_enable = 1; 510 ParseInput (dw); 511 if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page) 512 dw->dvi.requested_page = dw->dvi.last_page; 513 } 514 515 static void 516 FindPage (DviWidget dw) 517 { 518 int i; 519 long file_position; 520 521 if (dw->dvi.requested_page < 1) 522 dw->dvi.requested_page = 1; 523 524 if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page) 525 dw->dvi.requested_page = dw->dvi.last_page; 526 527 file_position = SearchPagePosition (dw, dw->dvi.requested_page); 528 if (file_position != -1) { 529 FileSeek(dw, file_position); 530 dw->dvi.current_page = dw->dvi.requested_page; 531 } else { 532 for (i=dw->dvi.requested_page; i > 0; i--) { 533 file_position = SearchPagePosition (dw, i); 534 if (file_position != -1) 535 break; 536 } 537 if (file_position == -1) 538 file_position = 0; 539 FileSeek (dw, file_position); 540 541 dw->dvi.current_page = i; 542 543 dw->dvi.display_enable = 0; 544 while (dw->dvi.current_page != dw->dvi.requested_page) { 545 dw->dvi.current_page = ParseInput (dw); 546 /* 547 * at EOF, seek back to the beginning of this page. 548 */ 549 if (!dw->dvi.readingTmp && feof (dw->dvi.file)) { 550 file_position = SearchPagePosition (dw, 551 dw->dvi.current_page); 552 if (file_position != -1) 553 FileSeek (dw, file_position); 554 dw->dvi.requested_page = dw->dvi.current_page; 555 break; 556 } 557 } 558 } 559 } 560 561 void DviSaveToFile(Widget w, FILE *fp) 562 { 563 XtCheckSubclass(w, dviWidgetClass, NULL); 564 (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp); 565 } 566 567 static 568 void SaveToFile(Widget w, FILE *fp) 569 { 570 DviWidget dw = (DviWidget)w; 571 long pos; 572 int c; 573 574 if (dw->dvi.tmpFile) { 575 pos = ftell(dw->dvi.tmpFile); 576 if (dw->dvi.ungot) { 577 pos--; 578 dw->dvi.ungot = 0; 579 /* The ungot character is in the tmpFile, so we don't 580 want to read it from file. */ 581 (void)getc(dw->dvi.file); 582 } 583 } 584 else 585 pos = ftell(dw->dvi.file); 586 FileSeek(dw, 0L); 587 while (DviGetC(dw, &c) != EOF) 588 if (putc(c, fp) == EOF) { 589 /* XXX print error message */ 590 break; 591 } 592 FileSeek(dw, pos); 593 } 594 595 static 596 void ClassPartInitialize(WidgetClass widget_class) 597 { 598 DviWidgetClass wc = (DviWidgetClass)widget_class; 599 DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass; 600 if (wc->command_class.save == InheritSaveToFile) 601 wc->command_class.save = super->command_class.save; 602 } 603 604 /* 605 Local Variables: 606 c-indent-level: 8 607 c-continued-statement-offset: 8 608 c-brace-offset: -8 609 c-argdecl-indent: 8 610 c-label-offset: -8 611 c-tab-always-indent: nil 612 End: 613 */ 614