3 static char Xrcsid[] = "$XConsortium: Dvi.c,v 1.9 89/12/10 16:12:25 rws Exp $";
8 * Dvi.c - Dvi display widget
12 #define XtStrlen(s) ((s) ? strlen(s) : 0)
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. */
18 #include <X11/IntrinsicP.h>
19 #include <X11/StringDefs.h>
20 #include <X11/Xmu/Converters.h>
25 /****************************************************************
27 * Full class record constant
29 ****************************************************************/
33 static char default_font_map_1[] = "\
34 TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
35 TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
36 TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
37 TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
38 CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
39 CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
40 CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
41 CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
43 static char default_font_map_2[] = "\
44 HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
45 HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
46 HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
47 HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
49 static char default_font_map_3[] = "\
50 NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
51 NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
52 NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
53 NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
54 S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
55 SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
58 #define offset(field) XtOffset(DviWidget, field)
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))
63 static 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"},
101 static void ClassInitialize (void);
102 static void ClassPartInitialize(WidgetClass);
103 static void Initialize(Widget, Widget, ArgList, Cardinal *);
104 static void Realize (Widget, XtValueMask *, XSetWindowAttributes *);
105 static void Destroy (Widget);
106 static void Redisplay (Widget, XEvent *, Region);
107 static Boolean SetValues (Widget, Widget, Widget,
108 ArgList, Cardinal *);
109 static Boolean SetValuesHook (Widget, ArgList, Cardinal *);
110 static XtGeometryResult QueryGeometry (Widget, XtWidgetGeometry *,
112 static void ShowDvi (DviWidget);
113 static void CloseFile (DviWidget);
114 static void OpenFile (DviWidget);
115 static void FindPage (DviWidget);
117 static void SaveToFile (Widget, FILE *);
120 extern void ParseFontMap(DviWidget);
121 extern void DestroyFontMap(DviFontMap *);
122 extern void ForgetFonts(DviWidget);
125 extern void DestroyFileMap(DviFileMap *);
126 extern long SearchPagePosition(DviWidget, int);
127 extern void FileSeek(DviWidget, long);
128 extern void ForgetPagePositions(DviWidget);
131 extern int ParseInput(register DviWidget);
133 DviClassRec dviClassRec = {
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 */
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 */
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 */
164 QueryGeometry, /* query_geometry */
165 NULL, /* display_accelerator */
168 SaveToFile, /* save */
172 WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
174 static void ClassInitialize (void)
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);
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;
186 XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
190 /****************************************************************
194 ****************************************************************/
197 static void Initialize(Widget request, Widget new_wd,
198 ArgList args, Cardinal *num_args)
200 DviWidget dw = (DviWidget) new_wd;
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;
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;
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;
234 request = request; /* unused; suppress compiler warning */
249 Realize (Widget w, XtValueMask *valueMask, XSetWindowAttributes *attrs)
251 DviWidget dw = (DviWidget) w;
254 if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
255 attrs->backing_store = dw->dvi.backing_store;
256 *valueMask |= CWBackingStore;
258 XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent,
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
268 dw->dvi.gray[0] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
270 gray1_width, gray1_height);
271 dw->dvi.gray[1] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
273 gray2_width, gray2_height);
274 dw->dvi.gray[2] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
276 gray3_width, gray3_height);
277 dw->dvi.gray[3] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
279 gray4_width, gray4_height);
280 dw->dvi.gray[4] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
282 gray5_width, gray5_height);
283 dw->dvi.gray[5] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
285 gray6_width, gray6_height);
286 dw->dvi.gray[6] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
288 gray7_width, gray7_height);
289 dw->dvi.gray[7] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
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,
298 dw->dvi.fill_type = 9;
308 DviWidget dw = (DviWidget) w;
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);
326 * Repaint the widget window
331 Redisplay(Widget w, XEvent *event, Region region)
333 DviWidget dw = (DviWidget) w;
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;
343 event = event; /* unused; suppress compiler warning */
347 * Set specified arguments into widget
351 SetValues (Widget wcurrent, Widget wrequest, Widget wnew,
352 ArgList args, Cardinal *num_args)
354 Boolean redisplay = FALSE;
357 DviWidget current = (DviWidget)wcurrent;
358 DviWidget request = (DviWidget)wrequest;
359 DviWidget new_wd = (DviWidget)wnew;
361 if (current->dvi.font_map_string != request->dvi.font_map_string) {
362 new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1);
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);
374 req = request->dvi.requested_page;
375 cur = current->dvi.requested_page;
377 if (!request->dvi.file)
382 if (current->dvi.last_page != 0 &&
383 req > current->dvi.last_page)
384 req = current->dvi.last_page;
388 new_wd->dvi.requested_page = req;
389 if (current->dvi.last_page == 0 && req > cur)
393 args = args; /* unused; suppress compiler warning */
400 * use the set_values_hook entry to check when
405 SetValuesHook (Widget wdw, ArgList args, Cardinal *num_argsp)
408 DviWidget dw = (DviWidget)wdw;
410 for (i = 0; i < *num_argsp; i++) {
411 if (!strcmp (args[i].name, XtNfile)) {
420 static void CloseFile (DviWidget dw)
423 fclose (dw->dvi.tmpFile);
424 ForgetPagePositions (dw);
427 static void OpenFile (DviWidget dw)
431 dw->dvi.tmpFile = tmpfile();
432 dw->dvi.requested_page = 1;
433 dw->dvi.last_page = 0;
436 static XtGeometryResult
437 QueryGeometry (Widget w, XtWidgetGeometry *request,
438 XtWidgetGeometry *geometry_return)
440 XtGeometryResult ret;
441 DviWidget dw = (DviWidget) w;
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;
456 SetDevice (DviWidget dw, const char *name)
458 XtWidgetGeometry request, reply;
459 XtGeometryResult ret;
462 dw->dvi.device = device_load (name);
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;
475 dw->dvi.display_resolution = dw->dvi.default_resolution;
476 dw->dvi.scale_factor = ((double)dw->dvi.display_resolution
477 / dw->dvi.device_resolution);
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);
493 ShowDvi (DviWidget dw)
496 static char Error[] = "No file selected";
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));
507 dw->dvi.display_enable = 1;
509 if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page)
510 dw->dvi.requested_page = dw->dvi.last_page;
514 FindPage (DviWidget dw)
519 if (dw->dvi.requested_page < 1)
520 dw->dvi.requested_page = 1;
522 if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
523 dw->dvi.requested_page = dw->dvi.last_page;
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;
530 for (i=dw->dvi.requested_page; i > 0; i--) {
531 file_position = SearchPagePosition (dw, i);
532 if (file_position != -1)
535 if (file_position == -1)
537 FileSeek (dw, file_position);
539 dw->dvi.current_page = i;
541 dw->dvi.display_enable = 0;
542 while (dw->dvi.current_page != dw->dvi.requested_page) {
543 dw->dvi.current_page = ParseInput (dw);
545 * at EOF, seek back to the beginning of this page.
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;
559 void DviSaveToFile(Widget w, FILE *fp)
561 XtCheckSubclass(w, dviWidgetClass, NULL);
562 (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
566 void SaveToFile(Widget w, FILE *fp)
568 DviWidget dw = (DviWidget)w;
572 if (dw->dvi.tmpFile) {
573 pos = ftell(dw->dvi.tmpFile);
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);
583 pos = ftell(dw->dvi.file);
585 while (DviGetC(dw, &c) != EOF)
586 if (putc(c, fp) == EOF) {
587 /* XXX print error message */
594 void ClassPartInitialize(WidgetClass widget_class)
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;
605 c-continued-statement-offset: 8
609 c-tab-always-indent: nil