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