groff before CVS: release 1.10
[s-roff.git] / xditview / Dvi.c
blobfe4eee2c114ba61af126fc27a7a682ca065c1b21
1 #ifndef SABER
2 #ifndef lint
3 static char Xrcsid[] = "$XConsortium: Dvi.c,v 1.9 89/12/10 16:12:25 rws Exp $";
4 #endif /* lint */
5 #endif /* SABER */
7 /*
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>
21 #include <stdio.h>
22 #include <ctype.h>
23 #include "DviP.h"
25 /****************************************************************
27 * Full class record constant
29 ****************************************************************/
31 /* Private Data */
33 static char default_font_map[] = "\
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\
42 HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
43 HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
44 HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
45 HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
46 NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
47 NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
48 NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
49 NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
50 S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
51 SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
54 #define offset(field) XtOffset(DviWidget, field)
56 #define MY_WIDTH(dw) ((int)(dw->dvi.paperwidth * dw->dvi.scale_factor + .5))
57 #define MY_HEIGHT(dw) ((int)(dw->dvi.paperlength * dw->dvi.scale_factor + .5))
59 static XtResource resources[] = {
60 {XtNfontMap, XtCFontMap, XtRString, sizeof (char *),
61 offset(dvi.font_map_string), XtRString, default_font_map},
62 {XtNforeground, XtCForeground, XtRPixel, sizeof (unsigned long),
63 offset(dvi.foreground), XtRString, "XtDefaultForeground"},
64 {XtNbackground, XtCBackground, XtRPixel, sizeof (unsigned long),
65 offset(dvi.background), XtRString, "XtDefaultBackground"},
66 {XtNpageNumber, XtCPageNumber, XtRInt, sizeof (int),
67 offset(dvi.requested_page), XtRString, "1"},
68 {XtNlastPageNumber, XtCLastPageNumber, XtRInt, sizeof (int),
69 offset (dvi.last_page), XtRString, "0"},
70 {XtNfile, XtCFile, XtRFile, sizeof (FILE *),
71 offset (dvi.file), XtRFile, (char *) 0},
72 {XtNseek, XtCSeek, XtRBoolean, sizeof (Boolean),
73 offset(dvi.seek), XtRString, "false"},
74 {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
75 offset(dvi.default_font), XtRString, "xtdefaultfont"},
76 {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
77 offset(dvi.backing_store), XtRString, "default"},
78 {XtNnoPolyText, XtCNoPolyText, XtRBoolean, sizeof (Boolean),
79 offset(dvi.noPolyText), XtRString, "false"},
80 {XtNresolution, XtCResolution, XtRInt, sizeof(int),
81 offset(dvi.default_resolution), XtRString, "75"},
84 #undef offset
86 static void ClassInitialize ();
87 static void ClassPartInitialize();
88 static void Initialize(), Realize (), Destroy (), Redisplay ();
89 static Boolean SetValues (), SetValuesHook ();
90 static XtGeometryResult QueryGeometry ();
91 static void ShowDvi ();
92 static void CloseFile (), OpenFile ();
93 static void FindPage ();
95 static void SaveToFile ();
97 DviClassRec dviClassRec = {
99 &widgetClassRec, /* superclass */
100 "Dvi", /* class_name */
101 sizeof(DviRec), /* size */
102 ClassInitialize, /* class_initialize */
103 ClassPartInitialize, /* class_part_initialize */
104 FALSE, /* class_inited */
105 Initialize, /* initialize */
106 NULL, /* initialize_hook */
107 Realize, /* realize */
108 NULL, /* actions */
109 0, /* num_actions */
110 resources, /* resources */
111 XtNumber(resources), /* resource_count */
112 NULLQUARK, /* xrm_class */
113 FALSE, /* compress_motion */
114 TRUE, /* compress_exposure */
115 TRUE, /* compress_enterleave */
116 FALSE, /* visible_interest */
117 Destroy, /* destroy */
118 NULL, /* resize */
119 Redisplay, /* expose */
120 SetValues, /* set_values */
121 SetValuesHook, /* set_values_hook */
122 NULL, /* set_values_almost */
123 NULL, /* get_values_hook */
124 NULL, /* accept_focus */
125 XtVersion, /* version */
126 NULL, /* callback_private */
127 0, /* tm_table */
128 QueryGeometry, /* query_geometry */
129 NULL, /* display_accelerator */
130 NULL /* extension */
132 SaveToFile, /* save */
136 WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
138 static void ClassInitialize ()
140 XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
141 NULL, 0 );
144 /****************************************************************
146 * Private Procedures
148 ****************************************************************/
150 /* ARGSUSED */
151 static void Initialize(request, new)
152 Widget request, new;
154 DviWidget dw = (DviWidget) new;
156 dw->dvi.current_page = 0;
157 dw->dvi.font_map = 0;
158 dw->dvi.cache.index = 0;
159 dw->dvi.text_x_width = 0;
160 dw->dvi.text_device_width = 0;
161 dw->dvi.word_flag = 0;
162 dw->dvi.file = 0;
163 dw->dvi.tmpFile = 0;
164 dw->dvi.state = 0;
165 dw->dvi.readingTmp = 0;
166 dw->dvi.cache.char_index = 0;
167 dw->dvi.cache.font_size = -1;
168 dw->dvi.cache.font_number = -1;
169 dw->dvi.cache.adjustable[0] = 0;
170 dw->dvi.file_map = 0;
171 dw->dvi.fonts = 0;
172 dw->dvi.seek = False;
173 dw->dvi.device_resolution = dw->dvi.default_resolution;
174 dw->dvi.display_resolution = dw->dvi.default_resolution;
175 dw->dvi.paperlength = dw->dvi.default_resolution*11;
176 dw->dvi.paperwidth = (dw->dvi.default_resolution*8
177 + dw->dvi.default_resolution/2);
178 dw->dvi.scale_factor = 1.0;
179 dw->dvi.sizescale = 1;
180 dw->dvi.line_thickness = -1;
181 dw->dvi.line_width = 1;
182 dw->dvi.fill = DVI_FILL_MAX;
183 dw->dvi.device_font = 0;
184 dw->dvi.device_font_number = -1;
185 dw->dvi.device = 0;
186 dw->dvi.native = 0;
189 #include <X11/bitmaps/gray>
191 static void
192 Realize (w, valueMask, attrs)
193 Widget w;
194 XtValueMask *valueMask;
195 XSetWindowAttributes *attrs;
197 DviWidget dw = (DviWidget) w;
198 XGCValues values;
200 if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
201 attrs->backing_store = dw->dvi.backing_store;
202 *valueMask |= CWBackingStore;
204 XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent,
205 *valueMask, attrs);
206 values.foreground = dw->dvi.foreground;
207 values.cap_style = CapRound;
208 values.join_style = JoinRound;
209 values.line_width = dw->dvi.line_width;
210 dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w),
211 GCForeground|GCCapStyle|GCJoinStyle
212 |GCLineWidth,
213 &values);
214 dw->dvi.gray = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
215 gray_bits,
216 gray_width, gray_height);
217 values.background = dw->dvi.background;
218 values.stipple = dw->dvi.gray;
219 dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w),
220 GCForeground|GCBackground|GCStipple,
221 &values);
223 dw->dvi.fill_type = DVI_FILL_BLACK;
225 if (dw->dvi.file)
226 OpenFile (dw);
227 ParseFontMap (dw);
230 static void
231 Destroy(w)
232 Widget w;
234 DviWidget dw = (DviWidget) w;
236 XFreeGC (XtDisplay (w), dw->dvi.normal_GC);
237 XFreeGC (XtDisplay (w), dw->dvi.fill_GC);
238 XFreePixmap (XtDisplay (w), dw->dvi.gray);
239 DestroyFontMap (dw->dvi.font_map);
240 DestroyFileMap (dw->dvi.file_map);
241 device_destroy (dw->dvi.device);
245 * Repaint the widget window
248 /* ARGSUSED */
249 static void
250 Redisplay(w, event, region)
251 Widget w;
252 XEvent *event;
253 Region region;
255 DviWidget dw = (DviWidget) w;
256 XRectangle extents;
258 XClipBox (region, &extents);
259 dw->dvi.extents.x1 = extents.x;
260 dw->dvi.extents.y1 = extents.y;
261 dw->dvi.extents.x2 = extents.x + extents.width;
262 dw->dvi.extents.y2 = extents.y + extents.height;
263 ShowDvi (dw);
267 * Set specified arguments into widget
269 /* ARGSUSED */
270 static Boolean
271 SetValues (current, request, new)
272 DviWidget current, request, new;
274 Boolean redisplay = FALSE;
275 char *new_map;
276 int cur, req;
278 if (current->dvi.font_map_string != request->dvi.font_map_string) {
279 new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1);
280 if (new_map) {
281 redisplay = TRUE;
282 strcpy (new_map, request->dvi.font_map_string);
283 new->dvi.font_map_string = new_map;
284 if (current->dvi.font_map_string)
285 XtFree (current->dvi.font_map_string);
286 current->dvi.font_map_string = 0;
287 ParseFontMap (new);
291 req = request->dvi.requested_page;
292 cur = current->dvi.requested_page;
293 if (cur != req) {
294 if (!request->dvi.file)
295 req = 0;
296 else {
297 if (req < 1)
298 req = 1;
299 if (current->dvi.last_page != 0 &&
300 req > current->dvi.last_page)
301 req = current->dvi.last_page;
303 if (cur != req)
304 redisplay = TRUE;
305 new->dvi.requested_page = req;
306 if (current->dvi.last_page == 0 && req > cur)
307 FindPage (new);
310 return redisplay;
314 * use the set_values_hook entry to check when
315 * the file is set
318 static Boolean
319 SetValuesHook (dw, args, num_argsp)
320 DviWidget dw;
321 ArgList args;
322 Cardinal *num_argsp;
324 Cardinal i;
326 for (i = 0; i < *num_argsp; i++) {
327 if (!strcmp (args[i].name, XtNfile)) {
328 CloseFile (dw);
329 OpenFile (dw);
330 return TRUE;
333 return FALSE;
336 static void CloseFile (dw)
337 DviWidget dw;
339 if (dw->dvi.tmpFile)
340 fclose (dw->dvi.tmpFile);
341 ForgetPagePositions (dw);
344 static void OpenFile (dw)
345 DviWidget dw;
347 char tmpName[sizeof ("/tmp/dviXXXXXX")];
349 dw->dvi.tmpFile = 0;
350 if (!dw->dvi.seek) {
351 strcpy (tmpName, "/tmp/dviXXXXXX");
352 mktemp (tmpName);
353 dw->dvi.tmpFile = fopen (tmpName, "w+");
354 unlink (tmpName);
356 dw->dvi.requested_page = 1;
357 dw->dvi.last_page = 0;
360 static XtGeometryResult
361 QueryGeometry (w, request, geometry_return)
362 Widget w;
363 XtWidgetGeometry *request, *geometry_return;
365 XtGeometryResult ret;
366 DviWidget dw = (DviWidget) w;
368 ret = XtGeometryYes;
369 if (((request->request_mode & CWWidth)
370 && request->width < MY_WIDTH(dw))
371 || ((request->request_mode & CWHeight)
372 && request->height < MY_HEIGHT(dw)))
373 ret = XtGeometryAlmost;
374 geometry_return->width = MY_WIDTH(dw);
375 geometry_return->height = MY_HEIGHT(dw);
376 geometry_return->request_mode = CWWidth|CWHeight;
377 return ret;
380 SetDevice (dw, name)
381 DviWidget dw;
382 char *name;
384 XtWidgetGeometry request, reply;
385 XtGeometryResult ret;
387 ForgetFonts (dw);
388 dw->dvi.device = device_load (name);
389 if (!dw->dvi.device)
390 return;
391 dw->dvi.sizescale = dw->dvi.device->sizescale;
392 dw->dvi.device_resolution = dw->dvi.device->res;
393 dw->dvi.native = dw->dvi.device->X11;
394 dw->dvi.paperlength = dw->dvi.device->paperlength;
395 dw->dvi.paperwidth = dw->dvi.device->paperwidth;
396 if (dw->dvi.native) {
397 dw->dvi.display_resolution = dw->dvi.device_resolution;
398 dw->dvi.scale_factor = 1.0;
400 else {
401 dw->dvi.display_resolution = dw->dvi.default_resolution;
402 dw->dvi.scale_factor = ((double)dw->dvi.display_resolution
403 / dw->dvi.device_resolution);
405 request.request_mode = CWWidth|CWHeight;
406 request.width = MY_WIDTH(dw);
407 request.height = MY_HEIGHT(dw);
408 ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply);
409 if (ret == XtGeometryAlmost
410 && reply.height >= request.height
411 && reply.width >= request.width) {
412 request.width = reply.width;
413 request.height = reply.height;
414 XtMakeGeometryRequest ((Widget)dw, &request, &reply);
418 static void
419 ShowDvi (dw)
420 DviWidget dw;
422 if (!dw->dvi.file) {
423 static char Error[] = "No file selected";
425 XSetFont (XtDisplay(dw), dw->dvi.normal_GC,
426 dw->dvi.default_font->fid);
427 XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
428 20, 20, Error, strlen (Error));
429 return;
432 FindPage (dw);
434 dw->dvi.display_enable = 1;
435 ParseInput (dw);
436 if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page)
437 dw->dvi.requested_page = dw->dvi.last_page;
440 static void
441 FindPage (dw)
442 DviWidget dw;
444 int i;
445 long file_position;
447 if (dw->dvi.requested_page < 1)
448 dw->dvi.requested_page = 1;
450 if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
451 dw->dvi.requested_page = dw->dvi.last_page;
453 file_position = SearchPagePosition (dw, dw->dvi.requested_page);
454 if (file_position != -1) {
455 FileSeek(dw, file_position);
456 dw->dvi.current_page = dw->dvi.requested_page;
457 } else {
458 for (i=dw->dvi.requested_page; i > 0; i--) {
459 file_position = SearchPagePosition (dw, i);
460 if (file_position != -1)
461 break;
463 if (file_position == -1)
464 file_position = 0;
465 FileSeek (dw, file_position);
467 dw->dvi.current_page = i;
469 dw->dvi.display_enable = 0;
470 while (dw->dvi.current_page != dw->dvi.requested_page) {
471 dw->dvi.current_page = ParseInput (dw);
473 * at EOF, seek back to the beginning of this page.
475 if (!dw->dvi.readingTmp && feof (dw->dvi.file)) {
476 file_position = SearchPagePosition (dw,
477 dw->dvi.current_page);
478 if (file_position != -1)
479 FileSeek (dw, file_position);
480 dw->dvi.requested_page = dw->dvi.current_page;
481 break;
487 void DviSaveToFile(w, fp)
488 Widget w;
489 FILE *fp;
491 XtCheckSubclass(w, dviWidgetClass, NULL);
492 (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
495 static
496 void SaveToFile(w, fp)
497 Widget w;
498 FILE *fp;
500 DviWidget dw = (DviWidget)w;
501 long pos;
502 int c;
504 if (dw->dvi.tmpFile) {
505 pos = ftell(dw->dvi.tmpFile);
506 if (dw->dvi.ungot) {
507 pos--;
508 dw->dvi.ungot = 0;
509 /* The ungot character is in the tmpFile, so we don't
510 want to read it from file. */
511 (void)getc(dw->dvi.file);
514 else
515 pos = ftell(dw->dvi.file);
516 FileSeek(dw, 0L);
517 while (DviGetC(dw, &c) != EOF)
518 if (putc(c, fp) == EOF) {
519 /* XXX print error message */
520 break;
522 FileSeek(dw, pos);
525 static
526 void ClassPartInitialize(widget_class)
527 WidgetClass widget_class;
529 DviWidgetClass wc = (DviWidgetClass)widget_class;
530 DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass;
531 if (wc->command_class.save == InheritSaveToFile)
532 wc->command_class.save = super->command_class.save;
536 Local Variables:
537 c-indent-level: 8
538 c-continued-statement-offset: 8
539 c-brace-offset: -8
540 c-argdecl-indent: 8
541 c-label-offset: -8
542 c-tab-always-indent: nil
543 End: