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>
29 /****************************************************************
31 * Full class record constant
33 ****************************************************************/
37 static char default_font_map_1[] = "\
38 TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
39 TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
40 TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
41 TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
42 CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
43 CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
44 CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
45 CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
47 static char default_font_map_2[] = "\
48 HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
49 HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
50 HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
51 HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
53 static char default_font_map_3[] = "\
54 NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
55 NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
56 NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
57 NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
58 S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
59 SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
62 #define offset(field) XtOffset(DviWidget, field)
64 #define MY_WIDTH(dw) ((int)(dw->dvi.paperwidth * dw->dvi.scale_factor + .5))
65 #define MY_HEIGHT(dw) ((int)(dw->dvi.paperlength * dw->dvi.scale_factor + .5))
67 static XtResource resources[] = {
68 {(String)XtNfontMap, (String)XtCFontMap, (String)XtRString,
69 sizeof (char *), offset(dvi.font_map_string),
70 (String)XtRString, NULL /* set in code */},
71 {(String)XtNforeground, (String)XtCForeground, (String)XtRPixel,
72 sizeof (unsigned long), offset(dvi.foreground),
73 (String)XtRString, (XtPointer)"XtDefaultForeground"},
74 {(String)XtNbackground, (String)XtCBackground, (String)XtRPixel,
75 sizeof (unsigned long), offset(dvi.background),
76 (String)XtRString, (XtPointer)"XtDefaultBackground"},
77 {(String)XtNpageNumber, (String)XtCPageNumber, (String)XtRInt,
78 sizeof (int), offset(dvi.requested_page),
79 (String)XtRString, (XtPointer)"1"},
80 {(String)XtNlastPageNumber, (String)XtCLastPageNumber, (String)XtRInt,
81 sizeof (int), offset (dvi.last_page),
82 (String)XtRString, (XtPointer)"0"},
83 {(String)XtNfile, (String)XtCFile, (String)XtRFile,
84 sizeof (FILE *), offset (dvi.file),
85 (String)XtRFile, (XtPointer)0},
86 {(String)XtNseek, (String)XtCSeek, (String)XtRBoolean,
87 sizeof (Boolean), offset(dvi.seek),
88 (String)XtRString, (XtPointer)"false"},
89 {(String)XtNfont, (String)XtCFont, (String)XtRFontStruct,
90 sizeof (XFontStruct *), offset(dvi.default_font),
91 (String)XtRString, (XtPointer)"xtdefaultfont"},
92 {(String)XtNbackingStore, (String)XtCBackingStore, (String)XtRBackingStore,
93 sizeof (int), offset(dvi.backing_store),
94 (String)XtRString, (XtPointer)"default"},
95 {(String)XtNnoPolyText, (String)XtCNoPolyText, (String)XtRBoolean,
96 sizeof (Boolean), offset(dvi.noPolyText),
97 (String)XtRString, (XtPointer)"false"},
98 {(String)XtNresolution, (String)XtCResolution, (String)XtRInt,
99 sizeof(int), offset(dvi.default_resolution),
100 (String)XtRString, (XtPointer)"75"},
105 static void ClassInitialize (void);
106 static void ClassPartInitialize(WidgetClass);
107 static void Initialize(Widget, Widget, ArgList, Cardinal *);
108 static void Realize (Widget, XtValueMask *, XSetWindowAttributes *);
109 static void Destroy (Widget);
110 static void Redisplay (Widget, XEvent *, Region);
111 static Boolean SetValues (Widget, Widget, Widget,
112 ArgList, Cardinal *);
113 static Boolean SetValuesHook (Widget, ArgList, Cardinal *);
114 static XtGeometryResult QueryGeometry (Widget, XtWidgetGeometry *,
116 static void ShowDvi (DviWidget);
117 static void CloseFile (DviWidget);
118 static void OpenFile (DviWidget);
119 static void FindPage (DviWidget);
121 static void SaveToFile (Widget, FILE *);
123 DviClassRec dviClassRec = {
125 &widgetClassRec, /* superclass */
126 (String)"Dvi", /* class_name */
127 sizeof(DviRec), /* size */
128 ClassInitialize, /* class_initialize */
129 ClassPartInitialize, /* class_part_initialize */
130 FALSE, /* class_inited */
131 Initialize, /* initialize */
132 NULL, /* initialize_hook */
133 Realize, /* realize */
136 resources, /* resources */
137 XtNumber(resources), /* resource_count */
138 NULLQUARK, /* xrm_class */
139 FALSE, /* compress_motion */
140 TRUE, /* compress_exposure */
141 TRUE, /* compress_enterleave */
142 FALSE, /* visible_interest */
143 Destroy, /* destroy */
145 Redisplay, /* expose */
146 SetValues, /* set_values */
147 SetValuesHook, /* set_values_hook */
148 NULL, /* set_values_almost */
149 NULL, /* get_values_hook */
150 NULL, /* accept_focus */
151 XtVersion, /* version */
152 NULL, /* callback_private */
154 QueryGeometry, /* query_geometry */
155 NULL, /* display_accelerator */
158 SaveToFile, /* save */
162 WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
164 static void ClassInitialize (void)
166 int len1 = strlen(default_font_map_1);
167 int len2 = strlen(default_font_map_2);
168 int len3 = strlen(default_font_map_3);
169 char *dfm = XtMalloc(len1 + len2 + len3 + 1);
171 strcpy(ptr, default_font_map_1); ptr += len1;
172 strcpy(ptr, default_font_map_2); ptr += len2;
173 strcpy(ptr, default_font_map_3);
174 resources[0].default_addr = dfm;
176 XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
180 /****************************************************************
184 ****************************************************************/
187 static void Initialize(Widget request, Widget new_wd,
188 ArgList args, Cardinal *num_args)
190 DviWidget dw = (DviWidget) new_wd;
192 dw->dvi.current_page = 0;
193 dw->dvi.font_map = 0;
194 dw->dvi.cache.index = 0;
195 dw->dvi.text_x_width = 0;
196 dw->dvi.text_device_width = 0;
197 dw->dvi.word_flag = 0;
201 dw->dvi.readingTmp = 0;
202 dw->dvi.cache.char_index = 0;
203 dw->dvi.cache.font_size = -1;
204 dw->dvi.cache.font_number = -1;
205 dw->dvi.cache.adjustable[0] = 0;
206 dw->dvi.file_map = 0;
208 dw->dvi.seek = False;
209 dw->dvi.device_resolution = dw->dvi.default_resolution;
210 dw->dvi.display_resolution = dw->dvi.default_resolution;
211 dw->dvi.paperlength = dw->dvi.default_resolution*11;
212 dw->dvi.paperwidth = (dw->dvi.default_resolution*8
213 + dw->dvi.default_resolution/2);
214 dw->dvi.scale_factor = 1.0;
215 dw->dvi.sizescale = 1;
216 dw->dvi.line_thickness = -1;
217 dw->dvi.line_width = 1;
218 dw->dvi.fill = DVI_FILL_MAX;
219 dw->dvi.device_font = 0;
220 dw->dvi.device_font_number = -1;
224 request = request; /* unused; suppress compiler warning */
239 Realize (Widget w, XtValueMask *valueMask, XSetWindowAttributes *attrs)
241 DviWidget dw = (DviWidget) w;
244 if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
245 attrs->backing_store = dw->dvi.backing_store;
246 *valueMask |= CWBackingStore;
248 XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent,
250 values.foreground = dw->dvi.foreground;
251 values.cap_style = CapRound;
252 values.join_style = JoinRound;
253 values.line_width = dw->dvi.line_width;
254 dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w),
255 GCForeground|GCCapStyle|GCJoinStyle
258 dw->dvi.gray[0] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
260 gray1_width, gray1_height);
261 dw->dvi.gray[1] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
263 gray2_width, gray2_height);
264 dw->dvi.gray[2] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
266 gray3_width, gray3_height);
267 dw->dvi.gray[3] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
269 gray4_width, gray4_height);
270 dw->dvi.gray[4] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
272 gray5_width, gray5_height);
273 dw->dvi.gray[5] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
275 gray6_width, gray6_height);
276 dw->dvi.gray[6] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
278 gray7_width, gray7_height);
279 dw->dvi.gray[7] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
281 gray8_width, gray8_height);
282 values.background = dw->dvi.background;
283 values.stipple = dw->dvi.gray[5];
284 dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w),
285 GCForeground|GCBackground|GCStipple,
288 dw->dvi.fill_type = 9;
298 DviWidget dw = (DviWidget) w;
300 XFreeGC (XtDisplay (w), dw->dvi.normal_GC);
301 XFreeGC (XtDisplay (w), dw->dvi.fill_GC);
302 XFreePixmap (XtDisplay (w), dw->dvi.gray[0]);
303 XFreePixmap (XtDisplay (w), dw->dvi.gray[1]);
304 XFreePixmap (XtDisplay (w), dw->dvi.gray[2]);
305 XFreePixmap (XtDisplay (w), dw->dvi.gray[3]);
306 XFreePixmap (XtDisplay (w), dw->dvi.gray[4]);
307 XFreePixmap (XtDisplay (w), dw->dvi.gray[5]);
308 XFreePixmap (XtDisplay (w), dw->dvi.gray[6]);
309 XFreePixmap (XtDisplay (w), dw->dvi.gray[7]);
310 DestroyFontMap (dw->dvi.font_map);
311 DestroyFileMap (dw->dvi.file_map);
312 device_destroy (dw->dvi.device);
316 * Repaint the widget window
321 Redisplay(Widget w, XEvent *event, Region region)
323 DviWidget dw = (DviWidget) w;
326 XClipBox (region, &extents);
327 dw->dvi.extents.x1 = extents.x;
328 dw->dvi.extents.y1 = extents.y;
329 dw->dvi.extents.x2 = extents.x + extents.width;
330 dw->dvi.extents.y2 = extents.y + extents.height;
333 event = event; /* unused; suppress compiler warning */
337 * Set specified arguments into widget
341 SetValues (Widget wcurrent, Widget wrequest, Widget wnew,
342 ArgList args, Cardinal *num_args)
344 Boolean redisplay = FALSE;
347 DviWidget current = (DviWidget)wcurrent;
348 DviWidget request = (DviWidget)wrequest;
349 DviWidget new_wd = (DviWidget)wnew;
351 if (current->dvi.font_map_string != request->dvi.font_map_string) {
352 new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1);
355 strcpy (new_map, request->dvi.font_map_string);
356 new_wd->dvi.font_map_string = new_map;
357 if (current->dvi.font_map_string)
358 XtFree (current->dvi.font_map_string);
359 current->dvi.font_map_string = 0;
360 ParseFontMap (new_wd);
364 req = request->dvi.requested_page;
365 cur = current->dvi.requested_page;
367 if (!request->dvi.file)
372 if (current->dvi.last_page != 0 &&
373 req > current->dvi.last_page)
374 req = current->dvi.last_page;
378 new_wd->dvi.requested_page = req;
379 if (current->dvi.last_page == 0 && req > cur)
383 args = args; /* unused; suppress compiler warning */
390 * use the set_values_hook entry to check when
395 SetValuesHook (Widget wdw, ArgList args, Cardinal *num_argsp)
398 DviWidget dw = (DviWidget)wdw;
400 for (i = 0; i < *num_argsp; i++) {
401 if (!strcmp (args[i].name, XtNfile)) {
410 static void CloseFile (DviWidget dw)
413 fclose (dw->dvi.tmpFile);
414 ForgetPagePositions (dw);
417 static void OpenFile (DviWidget dw)
421 dw->dvi.tmpFile = tmpfile();
422 dw->dvi.requested_page = 1;
423 dw->dvi.last_page = 0;
426 static XtGeometryResult
427 QueryGeometry (Widget w, XtWidgetGeometry *request,
428 XtWidgetGeometry *geometry_return)
430 XtGeometryResult ret;
431 DviWidget dw = (DviWidget) w;
434 if (((request->request_mode & CWWidth)
435 && request->width < MY_WIDTH(dw))
436 || ((request->request_mode & CWHeight)
437 && request->height < MY_HEIGHT(dw)))
438 ret = XtGeometryAlmost;
439 geometry_return->width = MY_WIDTH(dw);
440 geometry_return->height = MY_HEIGHT(dw);
441 geometry_return->request_mode = CWWidth|CWHeight;
446 SetDevice (DviWidget dw, const char *name)
448 XtWidgetGeometry request, reply;
449 XtGeometryResult ret;
452 dw->dvi.device = device_load (name);
455 dw->dvi.sizescale = dw->dvi.device->sizescale;
456 dw->dvi.device_resolution = dw->dvi.device->res;
457 dw->dvi.native = dw->dvi.device->X11;
458 dw->dvi.paperlength = dw->dvi.device->paperlength;
459 dw->dvi.paperwidth = dw->dvi.device->paperwidth;
460 if (dw->dvi.native) {
461 dw->dvi.display_resolution = dw->dvi.device_resolution;
462 dw->dvi.scale_factor = 1.0;
465 dw->dvi.display_resolution = dw->dvi.default_resolution;
466 dw->dvi.scale_factor = ((double)dw->dvi.display_resolution
467 / dw->dvi.device_resolution);
469 request.request_mode = CWWidth|CWHeight;
470 request.width = MY_WIDTH(dw);
471 request.height = MY_HEIGHT(dw);
472 ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply);
473 if (ret == XtGeometryAlmost
474 && reply.height >= request.height
475 && reply.width >= request.width) {
476 request.width = reply.width;
477 request.height = reply.height;
478 XtMakeGeometryRequest ((Widget)dw, &request, &reply);
483 ShowDvi (DviWidget dw)
486 static char Error[] = "No file selected";
488 XSetFont (XtDisplay(dw), dw->dvi.normal_GC,
489 dw->dvi.default_font->fid);
490 XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
491 20, 20, Error, strlen (Error));
497 dw->dvi.display_enable = 1;
499 if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page)
500 dw->dvi.requested_page = dw->dvi.last_page;
504 FindPage (DviWidget dw)
509 if (dw->dvi.requested_page < 1)
510 dw->dvi.requested_page = 1;
512 if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
513 dw->dvi.requested_page = dw->dvi.last_page;
515 file_position = SearchPagePosition (dw, dw->dvi.requested_page);
516 if (file_position != -1) {
517 FileSeek(dw, file_position);
518 dw->dvi.current_page = dw->dvi.requested_page;
520 for (i=dw->dvi.requested_page; i > 0; i--) {
521 file_position = SearchPagePosition (dw, i);
522 if (file_position != -1)
525 if (file_position == -1)
527 FileSeek (dw, file_position);
529 dw->dvi.current_page = i;
531 dw->dvi.display_enable = 0;
532 while (dw->dvi.current_page != dw->dvi.requested_page) {
533 dw->dvi.current_page = ParseInput (dw);
535 * at EOF, seek back to the beginning of this page.
537 if (!dw->dvi.readingTmp && feof (dw->dvi.file)) {
538 file_position = SearchPagePosition (dw,
539 dw->dvi.current_page);
540 if (file_position != -1)
541 FileSeek (dw, file_position);
542 dw->dvi.requested_page = dw->dvi.current_page;
549 void DviSaveToFile(Widget w, FILE *fp)
551 XtCheckSubclass(w, dviWidgetClass, NULL);
552 (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
556 void SaveToFile(Widget w, FILE *fp)
558 DviWidget dw = (DviWidget)w;
562 if (dw->dvi.tmpFile) {
563 pos = ftell(dw->dvi.tmpFile);
567 /* The ungot character is in the tmpFile, so we don't
568 want to read it from file. */
569 (void)getc(dw->dvi.file);
573 pos = ftell(dw->dvi.file);
575 while (DviGetC(dw, &c) != EOF)
576 if (putc(c, fp) == EOF) {
577 /* XXX print error message */
584 void ClassPartInitialize(WidgetClass widget_class)
586 DviWidgetClass wc = (DviWidgetClass)widget_class;
587 DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass;
588 if (wc->command_class.save == InheritSaveToFile)
589 wc->command_class.save = super->command_class.save;
595 c-continued-statement-offset: 8
599 c-tab-always-indent: nil