1/* $NetBSD$ */ 2 3#ifndef SABER 4#ifndef lint 5static 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 35static char default_font_map_1[] = "\ 36TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ 37TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\ 38TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ 39TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\ 40CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ 41CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\ 42CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ 43CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\ 44"; 45static char default_font_map_2[] = "\ 46HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ 47HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\ 48HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ 49HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\ 50"; 51static char default_font_map_3[] = "\ 52NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ 53NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\ 54NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ 55NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\ 56S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\ 57SS -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 65static 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 103static void ClassInitialize (void); 104static void ClassPartInitialize(WidgetClass); 105static void Initialize(Widget, Widget, ArgList, Cardinal *); 106static void Realize (Widget, XtValueMask *, XSetWindowAttributes *); 107static void Destroy (Widget); 108static void Redisplay (Widget, XEvent *, Region); 109static Boolean SetValues (Widget, Widget, Widget, 110 ArgList, Cardinal *); 111static Boolean SetValuesHook (Widget, ArgList, Cardinal *); 112static XtGeometryResult QueryGeometry (Widget, XtWidgetGeometry *, 113 XtWidgetGeometry *); 114static void ShowDvi (DviWidget); 115static void CloseFile (DviWidget); 116static void OpenFile (DviWidget); 117static void FindPage (DviWidget); 118 119static void SaveToFile (Widget, FILE *); 120 121/* font.c */ 122extern void ParseFontMap(DviWidget); 123extern void DestroyFontMap(DviFontMap *); 124extern void ForgetFonts(DviWidget); 125 126/* page.c */ 127extern void DestroyFileMap(DviFileMap *); 128extern long SearchPagePosition(DviWidget, int); 129extern void FileSeek(DviWidget, long); 130extern void ForgetPagePositions(DviWidget); 131 132/* parse.c */ 133extern int ParseInput(register DviWidget); 134 135DviClassRec 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 174WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec; 175 176static 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 */ 199static 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 250static void 251Realize (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 307static void 308Destroy(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 */ 332static void 333Redisplay(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 */ 352static Boolean 353SetValues (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 406static Boolean 407SetValuesHook (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 422static void CloseFile (DviWidget dw) 423{ 424 if (dw->dvi.tmpFile) 425 fclose (dw->dvi.tmpFile); 426 ForgetPagePositions (dw); 427} 428 429static 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 438static XtGeometryResult 439QueryGeometry (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 457void 458SetDevice (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 494static void 495ShowDvi (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 515static void 516FindPage (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 561void DviSaveToFile(Widget w, FILE *fp) 562{ 563 XtCheckSubclass(w, dviWidgetClass, NULL); 564 (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp); 565} 566 567static 568void 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 595static 596void 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/* 605Local Variables: 606c-indent-level: 8 607c-continued-statement-offset: 8 608c-brace-offset: -8 609c-argdecl-indent: 8 610c-label-offset: -8 611c-tab-always-indent: nil 612End: 613*/ 614