#ifndef SABER #ifndef lint static char Xrcsid[] = "$XConsortium: Dvi.c,v 1.9 89/12/10 16:12:25 rws Exp $"; #endif /* lint */ #endif /* SABER */ /* * Dvi.c - Dvi display widget * */ #define XtStrlen(s) ((s) ? strlen(s) : 0) /* The following are defined for the reader's convenience. Any Xt..Field macro in this code just refers to some field in one of the substructures of the WidgetRec. */ #include #include #include #include #include #include "DviP.h" /**************************************************************** * * Full class record constant * ****************************************************************/ /* Private Data */ static char default_font_map[] = "\ TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\ TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\ CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\ CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\ HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\ HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\ NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\ NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\ S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\ SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\ "; #define offset(field) XtOffset(DviWidget, field) #define MY_WIDTH(dw) ((int)(dw->dvi.paperwidth * dw->dvi.scale_factor + .5)) #define MY_HEIGHT(dw) ((int)(dw->dvi.paperlength * dw->dvi.scale_factor + .5)) static XtResource resources[] = { {XtNfontMap, XtCFontMap, XtRString, sizeof (char *), offset(dvi.font_map_string), XtRString, default_font_map}, {XtNforeground, XtCForeground, XtRPixel, sizeof (unsigned long), offset(dvi.foreground), XtRString, "XtDefaultForeground"}, {XtNbackground, XtCBackground, XtRPixel, sizeof (unsigned long), offset(dvi.background), XtRString, "XtDefaultBackground"}, {XtNpageNumber, XtCPageNumber, XtRInt, sizeof (int), offset(dvi.requested_page), XtRString, "1"}, {XtNlastPageNumber, XtCLastPageNumber, XtRInt, sizeof (int), offset (dvi.last_page), XtRString, "0"}, {XtNfile, XtCFile, XtRFile, sizeof (FILE *), offset (dvi.file), XtRFile, (char *) 0}, {XtNseek, XtCSeek, XtRBoolean, sizeof (Boolean), offset(dvi.seek), XtRString, "false"}, {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), offset(dvi.default_font), XtRString, "xtdefaultfont"}, {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int), offset(dvi.backing_store), XtRString, "default"}, {XtNnoPolyText, XtCNoPolyText, XtRBoolean, sizeof (Boolean), offset(dvi.noPolyText), XtRString, "false"}, {XtNresolution, XtCResolution, XtRInt, sizeof(int), offset(dvi.default_resolution), XtRString, "75"}, }; #undef offset static void ClassInitialize (); static void ClassPartInitialize(); static void Initialize(), Realize (), Destroy (), Redisplay (); static Boolean SetValues (), SetValuesHook (); static XtGeometryResult QueryGeometry (); static void ShowDvi (); static void CloseFile (), OpenFile (); static void FindPage (); static void SaveToFile (); DviClassRec dviClassRec = { { &widgetClassRec, /* superclass */ "Dvi", /* class_name */ sizeof(DviRec), /* size */ ClassInitialize, /* class_initialize */ ClassPartInitialize, /* class_part_initialize */ FALSE, /* class_inited */ Initialize, /* initialize */ NULL, /* initialize_hook */ Realize, /* realize */ NULL, /* actions */ 0, /* num_actions */ resources, /* resources */ XtNumber(resources), /* resource_count */ NULLQUARK, /* xrm_class */ FALSE, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave */ FALSE, /* visible_interest */ Destroy, /* destroy */ NULL, /* resize */ Redisplay, /* expose */ SetValues, /* set_values */ SetValuesHook, /* set_values_hook */ NULL, /* set_values_almost */ NULL, /* get_values_hook */ NULL, /* accept_focus */ XtVersion, /* version */ NULL, /* callback_private */ 0, /* tm_table */ QueryGeometry, /* query_geometry */ NULL, /* display_accelerator */ NULL /* extension */ },{ SaveToFile, /* save */ }, }; WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec; static void ClassInitialize () { XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore, NULL, 0 ); } /**************************************************************** * * Private Procedures * ****************************************************************/ /* ARGSUSED */ static void Initialize(request, new) Widget request, new; { DviWidget dw = (DviWidget) new; dw->dvi.current_page = 0; dw->dvi.font_map = 0; dw->dvi.cache.index = 0; dw->dvi.text_x_width = 0; dw->dvi.text_device_width = 0; dw->dvi.word_flag = 0; dw->dvi.file = 0; dw->dvi.tmpFile = 0; dw->dvi.state = 0; dw->dvi.readingTmp = 0; dw->dvi.cache.char_index = 0; dw->dvi.cache.font_size = -1; dw->dvi.cache.font_number = -1; dw->dvi.cache.adjustable[0] = 0; dw->dvi.file_map = 0; dw->dvi.fonts = 0; dw->dvi.seek = False; dw->dvi.device_resolution = dw->dvi.default_resolution; dw->dvi.display_resolution = dw->dvi.default_resolution; dw->dvi.paperlength = dw->dvi.default_resolution*11; dw->dvi.paperwidth = (dw->dvi.default_resolution*8 + dw->dvi.default_resolution/2); dw->dvi.scale_factor = 1.0; dw->dvi.sizescale = 1; dw->dvi.line_thickness = -1; dw->dvi.line_width = 1; dw->dvi.fill = DVI_FILL_MAX; dw->dvi.device_font = 0; dw->dvi.device_font_number = -1; dw->dvi.device = 0; dw->dvi.native = 0; } #include static void Realize (w, valueMask, attrs) Widget w; XtValueMask *valueMask; XSetWindowAttributes *attrs; { DviWidget dw = (DviWidget) w; XGCValues values; if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) { attrs->backing_store = dw->dvi.backing_store; *valueMask |= CWBackingStore; } XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent, *valueMask, attrs); values.foreground = dw->dvi.foreground; values.cap_style = CapRound; values.join_style = JoinRound; values.line_width = dw->dvi.line_width; dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w), GCForeground|GCCapStyle|GCJoinStyle |GCLineWidth, &values); dw->dvi.gray = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), gray_bits, gray_width, gray_height); values.background = dw->dvi.background; values.stipple = dw->dvi.gray; dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w), GCForeground|GCBackground|GCStipple, &values); dw->dvi.fill_type = DVI_FILL_BLACK; if (dw->dvi.file) OpenFile (dw); ParseFontMap (dw); } static void Destroy(w) Widget w; { DviWidget dw = (DviWidget) w; XFreeGC (XtDisplay (w), dw->dvi.normal_GC); XFreeGC (XtDisplay (w), dw->dvi.fill_GC); XFreePixmap (XtDisplay (w), dw->dvi.gray); DestroyFontMap (dw->dvi.font_map); DestroyFileMap (dw->dvi.file_map); device_destroy (dw->dvi.device); } /* * Repaint the widget window */ /* ARGSUSED */ static void Redisplay(w, event, region) Widget w; XEvent *event; Region region; { DviWidget dw = (DviWidget) w; XRectangle extents; XClipBox (region, &extents); dw->dvi.extents.x1 = extents.x; dw->dvi.extents.y1 = extents.y; dw->dvi.extents.x2 = extents.x + extents.width; dw->dvi.extents.y2 = extents.y + extents.height; ShowDvi (dw); } /* * Set specified arguments into widget */ /* ARGSUSED */ static Boolean SetValues (current, request, new) DviWidget current, request, new; { Boolean redisplay = FALSE; char *new_map; int cur, req; if (current->dvi.font_map_string != request->dvi.font_map_string) { new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1); if (new_map) { redisplay = TRUE; strcpy (new_map, request->dvi.font_map_string); new->dvi.font_map_string = new_map; if (current->dvi.font_map_string) XtFree (current->dvi.font_map_string); current->dvi.font_map_string = 0; ParseFontMap (new); } } req = request->dvi.requested_page; cur = current->dvi.requested_page; if (cur != req) { if (!request->dvi.file) req = 0; else { if (req < 1) req = 1; if (current->dvi.last_page != 0 && req > current->dvi.last_page) req = current->dvi.last_page; } if (cur != req) redisplay = TRUE; new->dvi.requested_page = req; if (current->dvi.last_page == 0 && req > cur) FindPage (new); } return redisplay; } /* * use the set_values_hook entry to check when * the file is set */ static Boolean SetValuesHook (dw, args, num_argsp) DviWidget dw; ArgList args; Cardinal *num_argsp; { Cardinal i; for (i = 0; i < *num_argsp; i++) { if (!strcmp (args[i].name, XtNfile)) { CloseFile (dw); OpenFile (dw); return TRUE; } } return FALSE; } static void CloseFile (dw) DviWidget dw; { if (dw->dvi.tmpFile) fclose (dw->dvi.tmpFile); ForgetPagePositions (dw); } static void OpenFile (dw) DviWidget dw; { char tmpName[sizeof ("/tmp/dviXXXXXX")]; int fd; dw->dvi.tmpFile = 0; if (!dw->dvi.seek) { strcpy (tmpName, "/tmp/dviXXXXXX"); fd = mkstemp (tmpName); dw->dvi.tmpFile = fdopen (fd, "w+"); unlink (tmpName); } dw->dvi.requested_page = 1; dw->dvi.last_page = 0; } static XtGeometryResult QueryGeometry (w, request, geometry_return) Widget w; XtWidgetGeometry *request, *geometry_return; { XtGeometryResult ret; DviWidget dw = (DviWidget) w; ret = XtGeometryYes; if (((request->request_mode & CWWidth) && request->width < MY_WIDTH(dw)) || ((request->request_mode & CWHeight) && request->height < MY_HEIGHT(dw))) ret = XtGeometryAlmost; geometry_return->width = MY_WIDTH(dw); geometry_return->height = MY_HEIGHT(dw); geometry_return->request_mode = CWWidth|CWHeight; return ret; } SetDevice (dw, name) DviWidget dw; char *name; { XtWidgetGeometry request, reply; XtGeometryResult ret; ForgetFonts (dw); dw->dvi.device = device_load (name); if (!dw->dvi.device) return; dw->dvi.sizescale = dw->dvi.device->sizescale; dw->dvi.device_resolution = dw->dvi.device->res; dw->dvi.native = dw->dvi.device->X11; dw->dvi.paperlength = dw->dvi.device->paperlength; dw->dvi.paperwidth = dw->dvi.device->paperwidth; if (dw->dvi.native) { dw->dvi.display_resolution = dw->dvi.device_resolution; dw->dvi.scale_factor = 1.0; } else { dw->dvi.display_resolution = dw->dvi.default_resolution; dw->dvi.scale_factor = ((double)dw->dvi.display_resolution / dw->dvi.device_resolution); } request.request_mode = CWWidth|CWHeight; request.width = MY_WIDTH(dw); request.height = MY_HEIGHT(dw); ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply); if (ret == XtGeometryAlmost && reply.height >= request.height && reply.width >= request.width) { request.width = reply.width; request.height = reply.height; XtMakeGeometryRequest ((Widget)dw, &request, &reply); } } static void ShowDvi (dw) DviWidget dw; { if (!dw->dvi.file) { static char Error[] = "No file selected"; XSetFont (XtDisplay(dw), dw->dvi.normal_GC, dw->dvi.default_font->fid); XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC, 20, 20, Error, strlen (Error)); return; } FindPage (dw); dw->dvi.display_enable = 1; ParseInput (dw); if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page) dw->dvi.requested_page = dw->dvi.last_page; } static void FindPage (dw) DviWidget dw; { int i; long file_position; if (dw->dvi.requested_page < 1) dw->dvi.requested_page = 1; if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page) dw->dvi.requested_page = dw->dvi.last_page; file_position = SearchPagePosition (dw, dw->dvi.requested_page); if (file_position != -1) { FileSeek(dw, file_position); dw->dvi.current_page = dw->dvi.requested_page; } else { for (i=dw->dvi.requested_page; i > 0; i--) { file_position = SearchPagePosition (dw, i); if (file_position != -1) break; } if (file_position == -1) file_position = 0; FileSeek (dw, file_position); dw->dvi.current_page = i; dw->dvi.display_enable = 0; while (dw->dvi.current_page != dw->dvi.requested_page) { dw->dvi.current_page = ParseInput (dw); /* * at EOF, seek back to the beginning of this page. */ if (!dw->dvi.readingTmp && feof (dw->dvi.file)) { file_position = SearchPagePosition (dw, dw->dvi.current_page); if (file_position != -1) FileSeek (dw, file_position); dw->dvi.requested_page = dw->dvi.current_page; break; } } } } void DviSaveToFile(w, fp) Widget w; FILE *fp; { XtCheckSubclass(w, dviWidgetClass, NULL); (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp); } static void SaveToFile(w, fp) Widget w; FILE *fp; { DviWidget dw = (DviWidget)w; long pos; int c; if (dw->dvi.tmpFile) { pos = ftell(dw->dvi.tmpFile); if (dw->dvi.ungot) { pos--; dw->dvi.ungot = 0; /* The ungot character is in the tmpFile, so we don't want to read it from file. */ (void)getc(dw->dvi.file); } } else pos = ftell(dw->dvi.file); FileSeek(dw, 0L); while (DviGetC(dw, &c) != EOF) if (putc(c, fp) == EOF) { /* XXX print error message */ break; } FileSeek(dw, pos); } static void ClassPartInitialize(widget_class) WidgetClass widget_class; { DviWidgetClass wc = (DviWidgetClass)widget_class; DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass; if (wc->command_class.save == InheritSaveToFile) wc->command_class.save = super->command_class.save; } /* Local Variables: c-indent-level: 8 c-continued-statement-offset: 8 c-brace-offset: -8 c-argdecl-indent: 8 c-label-offset: -8 c-tab-always-indent: nil End: */