Dvi.c revision f80a6dcd
1/* $XConsortium: Dvi.c,v 1.21 94/04/17 20:43:34 keith Exp $ */ 2/* $XdotOrg: $ */ 3/* 4 5Copyright (c) 1991 X Consortium 6 7Permission is hereby granted, free of charge, to any person obtaining 8a copy of this software and associated documentation files (the 9"Software"), to deal in the Software without restriction, including 10without limitation the rights to use, copy, modify, merge, publish, 11distribute, sublicense, and/or sell copies of the Software, and to 12permit persons to whom the Software is furnished to do so, subject to 13the following conditions: 14 15The above copyright notice and this permission notice shall be included 16in all copies or substantial portions of the Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 22OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24OTHER DEALINGS IN THE SOFTWARE. 25 26Except as contained in this notice, the name of the X Consortium shall 27not be used in advertising or otherwise to promote the sale, use or 28other dealings in this Software without prior written authorization 29from the X Consortium. 30 31*/ 32/* $XFree86: xc/programs/xditview/Dvi.c,v 1.3 2001/08/01 00:45:03 tsi Exp $ */ 33 34 35/* 36 * Dvi.c - Dvi display widget 37 */ 38 39#ifdef HAVE_CONFIG_H 40# include "config.h" 41#endif 42 43#define XtStrlen(s) ((s) ? strlen(s) : 0) 44 45 /* The following are defined for the reader's convenience. Any 46 Xt..Field macro in this code just refers to some field in 47 one of the substructures of the WidgetRec. */ 48 49#include <X11/IntrinsicP.h> 50#include <X11/StringDefs.h> 51#include <X11/Xmu/Converters.h> 52#include <stdio.h> 53#include <stdlib.h> 54#include <unistd.h> 55#include <ctype.h> 56#include "DviP.h" 57 58/**************************************************************** 59 * 60 * Full class record constant 61 * 62 ****************************************************************/ 63 64/* Private Data */ 65/* Note: default_font_map was too long a token for some machines... 66 * therefor it has been split in to and assigned to resources 67 * in the ClassInitialize routine. 68 */ 69static char default_font_map_1[] = "\ 70R -*-times-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\ 71I -*-times-medium-i-normal--*-*-*-*-*-*-iso8859-1\n\ 72B -*-times-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\ 73F -*-times-bold-i-normal--*-*-*-*-*-*-iso8859-1\n\ 74TR -*-times-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\ 75TI -*-times-medium-i-normal--*-*-*-*-*-*-iso8859-1\n\ 76TB -*-times-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\ 77TF -*-times-bold-i-normal--*-*-*-*-*-*-iso8859-1\n\ 78BI -*-times-bold-i-normal--*-*-*-*-*-*-iso8859-1\n\ 79C -*-courier-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\ 80CO -*-courier-medium-o-normal--*-*-*-*-*-*-iso8859-1\n\ 81CB -*-courier-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\ 82CF -*-courier-bold-o-normal--*-*-*-*-*-*-iso8859-1\n\ 83H -*-helvetica-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\ 84HO -*-helvetica-medium-o-normal--*-*-*-*-*-*-iso8859-1\n\ 85HB -*-helvetica-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\ 86HF -*-helvetica-bold-o-normal--*-*-*-*-*-*-iso8859-1\n\ 87"; 88static char default_font_map_2[] = "\ 89N -*-new century schoolbook-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\ 90NI -*-new century schoolbook-medium-i-normal--*-*-*-*-*-*-iso8859-1\n\ 91NB -*-new century schoolbook-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\ 92NF -*-new century schoolbook-bold-i-normal--*-*-*-*-*-*-iso8859-1\n\ 93A -*-charter-medium-r-normal--*-*-*-*-*-*-iso8859-1\n\ 94AI -*-charter-medium-i-normal--*-*-*-*-*-*-iso8859-1\n\ 95AB -*-charter-bold-r-normal--*-*-*-*-*-*-iso8859-1\n\ 96AF -*-charter-bold-i-normal--*-*-*-*-*-*-iso8859-1\n\ 97S -*-symbol-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific\n\ 98S2 -*-symbol-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific\n\ 99"; 100 101#define offset(field) XtOffsetOf(DviRec, field) 102 103static XtResource resources[] = { 104 {XtNfontMap, XtCFontMap, XtRString, sizeof (char *), 105 offset(dvi.font_map_string), XtRString, NULL /* set in code */}, 106 {XtNforeground, XtCForeground, XtRPixel, sizeof (unsigned long), 107 offset(dvi.foreground), XtRString, XtDefaultForeground}, 108 {XtNpageNumber, XtCPageNumber, XtRInt, sizeof (int), 109 offset(dvi.requested_page), XtRImmediate, (XtPointer) 1}, 110 {XtNlastPageNumber, XtCLastPageNumber, XtRInt, sizeof (int), 111 offset (dvi.last_page), XtRImmediate, (XtPointer) 0}, 112 {XtNfile, XtCFile, XtRFile, sizeof (FILE *), 113 offset (dvi.file), XtRFile, (char *) 0}, 114 {XtNseek, XtCSeek, XtRBoolean, sizeof (Boolean), 115 offset(dvi.seek), XtRImmediate, (XtPointer) False}, 116 {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), 117 offset(dvi.default_font), XtRString, XtDefaultFont}, 118 {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int), 119 offset(dvi.backing_store), XtRString, "default"}, 120 {XtNnoPolyText, XtCNoPolyText, XtRBoolean, sizeof (Boolean), 121 offset(dvi.noPolyText), XtRImmediate, (XtPointer) False}, 122 {XtNscreenResolution, XtCScreenResolution, XtRInt, sizeof (int), 123 offset(dvi.screen_resolution), XtRImmediate, (XtPointer) 75}, 124 {XtNpageWidth, XtCPageWidth, XtRFloat, sizeof (float), 125 offset(dvi.page_width), XtRString, "8.5"}, 126 {XtNpageHeight, XtCPageHeight, XtRFloat, sizeof (float), 127 offset(dvi.page_height), XtRString, "11"}, 128 {XtNsizeScale, XtCSizeScale, XtRInt, sizeof (int), 129 offset(dvi.size_scale_set), XtRImmediate, (XtPointer) 0}, 130}; 131 132#undef offset 133 134static void ClassInitialize(void); 135static void Initialize(Widget, Widget, ArgList, Cardinal *); 136static void Realize(Widget, XtValueMask *, XSetWindowAttributes *); 137static void Destroy(Widget); 138static void Redisplay(Widget, XEvent *, Region); 139static Boolean SetValues(Widget, Widget, Widget, ArgList , Cardinal *); 140static Boolean SetValuesHook(Widget, ArgList, Cardinal *); 141static XtGeometryResult QueryGeometry(Widget, 142 XtWidgetGeometry *, XtWidgetGeometry *); 143static void RequestDesiredSize(DviWidget); 144static void ShowDvi(DviWidget); 145static void CloseFile(DviWidget); 146static void OpenFile(DviWidget); 147 148#define SuperClass ((SimpleWidgetClass)&simpleClassRec) 149 150DviClassRec dviClassRec = { 151{ 152 (WidgetClass) SuperClass, /* superclass */ 153 "Dvi", /* class_name */ 154 sizeof(DviRec), /* size */ 155 ClassInitialize, /* class_initialize */ 156 NULL, /* class_part_initialize */ 157 FALSE, /* class_inited */ 158 Initialize, /* initialize */ 159 NULL, /* initialize_hook */ 160 Realize, /* realize */ 161 NULL, /* actions */ 162 0, /* num_actions */ 163 resources, /* resources */ 164 XtNumber(resources), /* resource_count */ 165 NULLQUARK, /* xrm_class */ 166 FALSE, /* compress_motion */ 167 XtExposeCompressMaximal, /* compress_exposure */ 168 TRUE, /* compress_enterleave */ 169 FALSE, /* visible_interest */ 170 Destroy, /* destroy */ 171 NULL, /* resize */ 172 Redisplay, /* expose */ 173 SetValues, /* set_values */ 174 SetValuesHook, /* set_values_hook */ 175 XtInheritSetValuesAlmost, /* set_values_almost */ 176 NULL, /* get_values_hook */ 177 NULL, /* accept_focus */ 178 XtVersion, /* version */ 179 NULL, /* callback_private */ 180 0, /* tm_table */ 181 QueryGeometry, /* query_geometry */ 182 XtInheritDisplayAccelerator, /* display_accelerator */ 183 NULL, /* extension */ 184}, /* CoreClass fields initialization */ 185{ 186 XtInheritChangeSensitive /* change_sensitive */ 187}, /* SimpleClass fields initialization */ 188{ 189 0, /* field not used */ 190}, /* DviClass fields initialization */ 191}; 192 193WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec; 194 195static void 196ClassInitialize (void) 197{ 198 int len1 = strlen(default_font_map_1); 199 int len2 = strlen(default_font_map_2); 200 char *dfm = XtMalloc(len1 + len2 + 1); 201 char *ptr = dfm; 202 strcpy(ptr, default_font_map_1); ptr += len1; 203 strcpy(ptr, default_font_map_2); 204 resources[0].default_addr = dfm; 205 206 XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore, 207 NULL, 0 ); 208} 209 210/**************************************************************** 211 * 212 * Private Procedures 213 * 214 ****************************************************************/ 215 216/* ARGSUSED */ 217static void 218Initialize(request, new, args, num_args) 219 Widget request, new; 220 ArgList args; 221 Cardinal *num_args; 222{ 223 DviWidget dw = (DviWidget) new; 224 225 dw->dvi.tmpFile = 0; 226 dw->dvi.readingTmp = 0; 227 dw->dvi.ungot = 0; 228 dw->dvi.normal_GC = 0; 229 dw->dvi.file_map = 0; 230 dw->dvi.fonts = 0; 231 dw->dvi.font_map = 0; 232 dw->dvi.current_page = 0; 233 dw->dvi.font_size = 0; 234 dw->dvi.font_number = 0; 235 dw->dvi.device_resolution = 0; 236 dw->dvi.line_width = 0; 237 dw->dvi.line_style = 0; 238 dw->dvi.font = 0; 239 dw->dvi.display_enable = 0; 240 dw->dvi.scale = 0.0; 241 dw->dvi.state = 0; 242 dw->dvi.cache.index = 0; 243 dw->dvi.cache.font = 0; 244 dw->dvi.size_scale = 0; 245 dw->dvi.size_scale_set = 0; 246 RequestDesiredSize (dw); 247} 248 249static void 250Realize(w, valueMask, attrs) 251 Widget w; 252 XtValueMask *valueMask; 253 XSetWindowAttributes *attrs; 254{ 255 DviWidget dw = (DviWidget) w; 256 XGCValues values; 257 258 if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) { 259 attrs->backing_store = dw->dvi.backing_store; 260 *valueMask |= CWBackingStore; 261 } 262 XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent, 263 *valueMask, attrs); 264 values.foreground = dw->dvi.foreground; 265 dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w), 266 GCForeground, &values); 267#ifdef USE_XFT 268 { 269 int scr; 270 Visual *visual; 271 Colormap cmap; 272 XRenderColor black; 273 274 scr = XScreenNumberOfScreen (dw->core.screen); 275 visual = DefaultVisual (XtDisplay (w), scr); 276 cmap = DefaultColormap (XtDisplay (w), scr); 277 dw->dvi.draw = XftDrawCreate (XtDisplay (w), XtWindow (w), 278 visual, cmap); 279 280 black.red = black.green = black.blue = 0; 281 black.alpha = 0xffff; 282 XftColorAllocValue (XtDisplay (w), visual, cmap, 283 &black, &dw->dvi.black); 284 dw->dvi.default_font = XftFontOpenName (XtDisplay (w), 285 scr, 286 "serif-12"); 287 } 288#endif 289 if (dw->dvi.file) 290 OpenFile (dw); 291 ParseFontMap (dw); 292} 293 294static void 295Destroy(w) 296 Widget w; 297{ 298 DviWidget dw = (DviWidget) w; 299 300 XFreeGC (XtDisplay (w), dw->dvi.normal_GC); 301 DestroyFontMap (dw->dvi.font_map); 302 DestroyFileMap (dw->dvi.file_map); 303} 304 305/* 306 * Repaint the widget window 307 */ 308 309/* ARGSUSED */ 310static void 311Redisplay(w, event, region) 312 Widget w; 313 XEvent *event; 314 Region region; 315{ 316 DviWidget dw = (DviWidget) w; 317#ifndef USE_XFT 318 XRectangle extents; 319#endif 320 321#ifdef USE_XFT 322 XClearArea (XtDisplay (dw), 323 XtWindow (dw), 324 0, 0, 0, 0, False); 325 dw->dvi.extents.x1 = 0; 326 dw->dvi.extents.y1 = 0; 327 dw->dvi.extents.x2 = dw->core.width; 328 dw->dvi.extents.y2 = dw->core.height; 329#else 330 XClipBox (region, &extents); 331 dw->dvi.extents.x1 = extents.x; 332 dw->dvi.extents.y1 = extents.y; 333 dw->dvi.extents.x2 = extents.x + extents.width; 334 dw->dvi.extents.y2 = extents.y + extents.height; 335#endif 336 ShowDvi (dw); 337} 338 339static void 340RequestDesiredSize (dw) 341 DviWidget dw; 342{ 343 XtWidgetGeometry req, rep; 344 345 dw->dvi.desired_width = dw->dvi.page_width * 346 dw->dvi.screen_resolution; 347 dw->dvi.desired_height = dw->dvi.page_height * 348 dw->dvi.screen_resolution; 349 req.request_mode = CWWidth|CWHeight; 350 req.width = dw->dvi.desired_width; 351 req.height = dw->dvi.desired_height; 352 XtMakeGeometryRequest ((Widget) dw, &req, &rep); 353} 354 355/* 356 * Set specified arguments into widget 357 */ 358/* ARGSUSED */ 359static Boolean 360SetValues (wcurrent, wrequest, wnew, args, num_args) 361 Widget wcurrent, wrequest, wnew; 362 ArgList args; 363 Cardinal *num_args; 364{ 365 DviWidget current = (DviWidget) wcurrent; 366 DviWidget request = (DviWidget) wrequest; 367 DviWidget new = (DviWidget) wnew; 368 Boolean redisplay = FALSE; 369 char *new_map; 370 int cur, req; 371 372 req = request->dvi.requested_page; 373 cur = current->dvi.requested_page; 374 if (cur != req) { 375 if (req < 1) 376 req = 1; 377 if (request->dvi.file) 378 { 379 if (current->dvi.last_page != 0 && 380 req > current->dvi.last_page) 381 req = current->dvi.last_page; 382 } 383 if (cur != req) 384 redisplay = TRUE; 385 new->dvi.requested_page = req; 386 } 387 388 if (current->dvi.font_map_string != request->dvi.font_map_string) { 389 new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1); 390 if (new_map) { 391 redisplay = TRUE; 392 strcpy (new_map, request->dvi.font_map_string); 393 new->dvi.font_map_string = new_map; 394 if (current->dvi.font_map_string) 395 XtFree (current->dvi.font_map_string); 396 current->dvi.font_map_string = 0; 397 ParseFontMap (new); 398 } 399 } 400 if (current->dvi.screen_resolution != request->dvi.screen_resolution) 401 { 402 ResetFonts (new); 403 new->dvi.line_width = -1; 404 } 405 if (request->dvi.device_resolution) 406 new->dvi.scale = ((double) request->dvi.screen_resolution) / 407 ((double) request->dvi.device_resolution); 408 if (current->dvi.page_width != request->dvi.page_width || 409 current->dvi.page_height != request->dvi.page_height || 410 current->dvi.screen_resolution != request->dvi.screen_resolution) 411 { 412 RequestDesiredSize (new); 413 redisplay = TRUE; 414 } 415 return redisplay; 416} 417 418/* 419 * use the set_values_hook entry to check when 420 * the file is set 421 */ 422 423static Boolean 424SetValuesHook (widget, args, num_argsp) 425 Widget widget; 426 ArgList args; 427 Cardinal *num_argsp; 428{ 429 DviWidget dw = (DviWidget) widget; 430 Cardinal i; 431 432 for (i = 0; i < *num_argsp; i++) { 433 if (!strcmp (args[i].name, XtNfile)) { 434 CloseFile (dw); 435 OpenFile (dw); 436 return TRUE; 437 } 438 } 439 return FALSE; 440} 441 442static void 443CloseFile (dw) 444 DviWidget dw; 445{ 446 if (dw->dvi.tmpFile) 447 fclose (dw->dvi.tmpFile); 448 ForgetPagePositions (dw); 449} 450 451static void 452OpenFile (dw) 453 DviWidget dw; 454{ 455 char tmpName[sizeof ("/tmp/dviXXXXXX")]; 456#ifdef HAS_MKSTEMP 457 int fd; 458#endif 459 460 dw->dvi.tmpFile = 0; 461 if (!dw->dvi.seek) { 462 strcpy (tmpName, "/tmp/dviXXXXXX"); 463#ifndef HAS_MKSTEMP 464 mktemp (tmpName); 465 dw->dvi.tmpFile = fopen (tmpName, "w+"); 466#else 467 fd = mkstemp(tmpName); 468 dw->dvi.tmpFile = fdopen(fd, "w+"); 469#endif 470 unlink (tmpName); 471 } 472 if (dw->dvi.requested_page < 1) 473 dw->dvi.requested_page = 1; 474 dw->dvi.last_page = 0; 475} 476 477static XtGeometryResult 478QueryGeometry (w, request, geometry_return) 479 Widget w; 480 XtWidgetGeometry *request, *geometry_return; 481{ 482 XtGeometryResult ret; 483 DviWidget dw = (DviWidget) w; 484 485 ret = XtGeometryYes; 486 if ((int)request->width < dw->dvi.desired_width 487 || (int)request->height < dw->dvi.desired_height) 488 ret = XtGeometryAlmost; 489 geometry_return->width = dw->dvi.desired_width; 490 geometry_return->height = dw->dvi.desired_height; 491 geometry_return->request_mode = CWWidth|CWHeight; 492 return ret; 493} 494 495void 496SetDeviceResolution (dw, resolution) 497 DviWidget dw; 498 int resolution; 499{ 500 if (resolution != dw->dvi.device_resolution) { 501 dw->dvi.device_resolution = resolution; 502 dw->dvi.scale = ((double) dw->dvi.screen_resolution) / 503 ((double) resolution); 504 } 505} 506 507static void 508ShowDvi (dw) 509 DviWidget dw; 510{ 511 int i; 512 long file_position; 513 514 if (!dw->dvi.file) 515 return; 516 517 if (dw->dvi.requested_page < 1) 518 dw->dvi.requested_page = 1; 519 520 if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page) 521 dw->dvi.requested_page = dw->dvi.last_page; 522 523 file_position = SearchPagePosition (dw, dw->dvi.requested_page); 524 if (file_position != -1) { 525 FileSeek(dw, file_position); 526 dw->dvi.current_page = dw->dvi.requested_page; 527 } else { 528 for (i=dw->dvi.requested_page; i > 0; i--) { 529 file_position = SearchPagePosition (dw, i); 530 if (file_position != -1) 531 break; 532 } 533 if (file_position == -1) 534 file_position = 0; 535 FileSeek (dw, file_position); 536 537 dw->dvi.current_page = i; 538 539 dw->dvi.display_enable = 0; 540 while (dw->dvi.current_page != dw->dvi.requested_page) { 541 dw->dvi.current_page = ParseInput (dw); 542 /* 543 * at EOF, seek back to the begining of this page. 544 */ 545 if (feof (dw->dvi.file)) { 546 file_position = SearchPagePosition (dw, 547 dw->dvi.current_page); 548 if (file_position != -1) 549 FileSeek (dw, file_position); 550 break; 551 } 552 } 553 } 554 555 dw->dvi.display_enable = 1; 556 ParseInput (dw); 557 if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page) 558 dw->dvi.requested_page = dw->dvi.last_page; 559} 560