Merge from vendor branch OPENSSH:
[dragonfly.git] / contrib / groff / src / xditview / Dvi.c
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 */
6
7 /*
8  * Dvi.c - Dvi display widget
9  *
10  */
11
12 #define XtStrlen(s)     ((s) ? strlen(s) : 0)
13
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.  */
17
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"
24
25 /****************************************************************
26  *
27  * Full class record constant
28  *
29  ****************************************************************/
30
31 /* Private Data */
32
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\
52 ";
53
54 #define offset(field) XtOffset(DviWidget, field)
55
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))
58
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"},
82 };
83
84 #undef offset
85
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 ();
94
95 static void             SaveToFile ();
96
97 DviClassRec dviClassRec = {
98 {
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              */
131 },{
132         SaveToFile,                     /* save    */
133 },
134 };
135
136 WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
137
138 static void ClassInitialize ()
139 {
140         XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
141                         NULL, 0 );
142 }
143
144 /****************************************************************
145  *
146  * Private Procedures
147  *
148  ****************************************************************/
149
150 /* ARGSUSED */
151 static void Initialize(request, new)
152         Widget request, new;
153 {
154         DviWidget       dw = (DviWidget) new;
155
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;
187 }
188
189 #include "gray1.bm"
190 #include "gray2.bm"
191 #include "gray3.bm"
192 #include "gray4.bm"
193 #include "gray5.bm"
194 #include "gray6.bm"
195 #include "gray7.bm"
196 #include "gray8.bm"
197
198 static void
199 Realize (w, valueMask, attrs)
200         Widget                  w;
201         XtValueMask             *valueMask;
202         XSetWindowAttributes    *attrs;
203 {
204         DviWidget       dw = (DviWidget) w;
205         XGCValues       values;
206
207         if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
208                 attrs->backing_store = dw->dvi.backing_store;
209                 *valueMask |= CWBackingStore;
210         }
211         XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent,
212                         *valueMask, attrs);
213         values.foreground = dw->dvi.foreground;
214         values.cap_style = CapRound;
215         values.join_style = JoinRound;
216         values.line_width = dw->dvi.line_width;
217         dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w),
218                                        GCForeground|GCCapStyle|GCJoinStyle
219                                        |GCLineWidth,
220                                        &values);
221         dw->dvi.gray[0] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
222                                              gray1_bits,
223                                              gray1_width, gray1_height);
224         dw->dvi.gray[1] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
225                                              gray2_bits,
226                                              gray2_width, gray2_height);
227         dw->dvi.gray[2] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
228                                              gray3_bits,
229                                              gray3_width, gray3_height);
230         dw->dvi.gray[3] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
231                                              gray4_bits,
232                                              gray4_width, gray4_height);
233         dw->dvi.gray[4] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
234                                              gray5_bits,
235                                              gray5_width, gray5_height);
236         dw->dvi.gray[5] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
237                                              gray6_bits,
238                                              gray6_width, gray6_height);
239         dw->dvi.gray[6] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
240                                              gray7_bits,
241                                              gray7_width, gray7_height);
242         dw->dvi.gray[7] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
243                                              gray8_bits,
244                                              gray8_width, gray8_height);
245         values.background = dw->dvi.background;
246         values.stipple = dw->dvi.gray[5];
247         dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w),
248                                      GCForeground|GCBackground|GCStipple,
249                                      &values);
250
251         dw->dvi.fill_type = 9;
252
253         if (dw->dvi.file)
254                 OpenFile (dw);
255         ParseFontMap (dw);
256 }
257
258 static void
259 Destroy(w)
260         Widget w;
261 {
262         DviWidget       dw = (DviWidget) w;
263
264         XFreeGC (XtDisplay (w), dw->dvi.normal_GC);
265         XFreeGC (XtDisplay (w), dw->dvi.fill_GC);
266         XFreePixmap (XtDisplay (w), dw->dvi.gray[0]);
267         XFreePixmap (XtDisplay (w), dw->dvi.gray[1]);
268         XFreePixmap (XtDisplay (w), dw->dvi.gray[2]);
269         XFreePixmap (XtDisplay (w), dw->dvi.gray[3]);
270         XFreePixmap (XtDisplay (w), dw->dvi.gray[4]);
271         XFreePixmap (XtDisplay (w), dw->dvi.gray[5]);
272         XFreePixmap (XtDisplay (w), dw->dvi.gray[6]);
273         XFreePixmap (XtDisplay (w), dw->dvi.gray[7]);
274         DestroyFontMap (dw->dvi.font_map);
275         DestroyFileMap (dw->dvi.file_map);
276         device_destroy (dw->dvi.device);
277 }
278
279 /*
280  * Repaint the widget window
281  */
282
283 /* ARGSUSED */
284 static void
285 Redisplay(w, event, region)
286         Widget w;
287         XEvent *event;
288         Region region;
289 {
290         DviWidget       dw = (DviWidget) w;
291         XRectangle      extents;
292         
293         XClipBox (region, &extents);
294         dw->dvi.extents.x1 = extents.x;
295         dw->dvi.extents.y1 = extents.y;
296         dw->dvi.extents.x2 = extents.x + extents.width;
297         dw->dvi.extents.y2 = extents.y + extents.height;
298         ShowDvi (dw);
299 }
300
301 /*
302  * Set specified arguments into widget
303  */
304 /* ARGSUSED */
305 static Boolean
306 SetValues (current, request, new)
307         DviWidget current, request, new;
308 {
309         Boolean         redisplay = FALSE;
310         char            *new_map;
311         int             cur, req;
312
313         if (current->dvi.font_map_string != request->dvi.font_map_string) {
314                 new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1);
315                 if (new_map) {
316                         redisplay = TRUE;
317                         strcpy (new_map, request->dvi.font_map_string);
318                         new->dvi.font_map_string = new_map;
319                         if (current->dvi.font_map_string)
320                                 XtFree (current->dvi.font_map_string);
321                         current->dvi.font_map_string = 0;
322                         ParseFontMap (new);
323                 }
324         }
325
326         req = request->dvi.requested_page;
327         cur = current->dvi.requested_page;
328         if (cur != req) {
329                 if (!request->dvi.file)
330                     req = 0;
331                 else {
332                     if (req < 1)
333                             req = 1;
334                     if (current->dvi.last_page != 0 &&
335                         req > current->dvi.last_page)
336                             req = current->dvi.last_page;
337                 }
338                 if (cur != req)
339                     redisplay = TRUE;
340                 new->dvi.requested_page = req;
341                 if (current->dvi.last_page == 0 && req > cur)
342                         FindPage (new);
343         }
344
345         return redisplay;
346 }
347
348 /*
349  * use the set_values_hook entry to check when
350  * the file is set
351  */
352
353 static Boolean
354 SetValuesHook (dw, args, num_argsp)
355         DviWidget       dw;
356         ArgList         args;
357         Cardinal        *num_argsp;
358 {
359         Cardinal        i;
360
361         for (i = 0; i < *num_argsp; i++) {
362                 if (!strcmp (args[i].name, XtNfile)) {
363                         CloseFile (dw);
364                         OpenFile (dw);
365                         return TRUE;
366                 }
367         }
368         return FALSE;
369 }
370
371 static void CloseFile (dw)
372         DviWidget       dw;
373 {
374         if (dw->dvi.tmpFile)
375                 fclose (dw->dvi.tmpFile);
376         ForgetPagePositions (dw);
377 }
378
379 static void OpenFile (dw)
380         DviWidget       dw;
381 {
382         dw->dvi.tmpFile = 0;
383         if (!dw->dvi.seek)
384                 dw->dvi.tmpFile = tmpfile();
385         dw->dvi.requested_page = 1;
386         dw->dvi.last_page = 0;
387 }
388
389 static XtGeometryResult
390 QueryGeometry (w, request, geometry_return)
391         Widget                  w;
392         XtWidgetGeometry        *request, *geometry_return;
393 {
394         XtGeometryResult        ret;
395         DviWidget               dw = (DviWidget) w;
396
397         ret = XtGeometryYes;
398         if (((request->request_mode & CWWidth)
399              && request->width < MY_WIDTH(dw))
400             || ((request->request_mode & CWHeight)
401                 && request->height < MY_HEIGHT(dw)))
402                 ret = XtGeometryAlmost;
403         geometry_return->width = MY_WIDTH(dw);
404         geometry_return->height = MY_HEIGHT(dw);
405         geometry_return->request_mode = CWWidth|CWHeight;
406         return ret;
407 }
408
409 SetDevice (dw, name)
410         DviWidget       dw;
411         char            *name;
412 {
413         XtWidgetGeometry        request, reply;
414         XtGeometryResult ret;
415
416         ForgetFonts (dw);
417         dw->dvi.device = device_load (name);
418         if (!dw->dvi.device)
419                 return;
420         dw->dvi.sizescale = dw->dvi.device->sizescale;
421         dw->dvi.device_resolution = dw->dvi.device->res;
422         dw->dvi.native = dw->dvi.device->X11;
423         dw->dvi.paperlength = dw->dvi.device->paperlength;
424         dw->dvi.paperwidth = dw->dvi.device->paperwidth;
425         if (dw->dvi.native) {
426                 dw->dvi.display_resolution = dw->dvi.device_resolution;
427                 dw->dvi.scale_factor = 1.0;
428         }
429         else {
430                 dw->dvi.display_resolution = dw->dvi.default_resolution;
431                 dw->dvi.scale_factor = ((double)dw->dvi.display_resolution
432                                         / dw->dvi.device_resolution);
433         }
434         request.request_mode = CWWidth|CWHeight;
435         request.width = MY_WIDTH(dw);
436         request.height = MY_HEIGHT(dw);
437         ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply);
438         if (ret == XtGeometryAlmost
439             && reply.height >= request.height
440             && reply.width >= request.width) {
441                 request.width = reply.width;
442                 request.height = reply.height;
443                 XtMakeGeometryRequest ((Widget)dw, &request, &reply);
444         }
445 }
446
447 static void
448 ShowDvi (dw)
449         DviWidget       dw;
450 {
451         if (!dw->dvi.file) {
452                 static char Error[] = "No file selected";
453
454                 XSetFont (XtDisplay(dw), dw->dvi.normal_GC,
455                           dw->dvi.default_font->fid);
456                 XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
457                              20, 20, Error, strlen (Error));
458                 return;
459         }
460
461         FindPage (dw);
462         
463         dw->dvi.display_enable = 1;
464         ParseInput (dw);
465         if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page)
466                 dw->dvi.requested_page = dw->dvi.last_page;
467 }
468
469 static void
470 FindPage (dw)
471         DviWidget       dw;
472 {
473         int     i;
474         long    file_position;
475
476         if (dw->dvi.requested_page < 1)
477                 dw->dvi.requested_page = 1;
478
479         if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
480                 dw->dvi.requested_page = dw->dvi.last_page;
481
482         file_position = SearchPagePosition (dw, dw->dvi.requested_page);
483         if (file_position != -1) {
484                 FileSeek(dw, file_position);
485                 dw->dvi.current_page = dw->dvi.requested_page;
486         } else {
487                 for (i=dw->dvi.requested_page; i > 0; i--) {
488                         file_position = SearchPagePosition (dw, i);
489                         if (file_position != -1)
490                                 break;
491                 }
492                 if (file_position == -1)
493                         file_position = 0;
494                 FileSeek (dw, file_position);
495
496                 dw->dvi.current_page = i;
497                 
498                 dw->dvi.display_enable = 0;
499                 while (dw->dvi.current_page != dw->dvi.requested_page) {
500                         dw->dvi.current_page = ParseInput (dw);
501                         /*
502                          * at EOF, seek back to the beginning of this page.
503                          */
504                         if (!dw->dvi.readingTmp && feof (dw->dvi.file)) {
505                                 file_position = SearchPagePosition (dw,
506                                                 dw->dvi.current_page);
507                                 if (file_position != -1)
508                                         FileSeek (dw, file_position);
509                                 dw->dvi.requested_page = dw->dvi.current_page;
510                                 break;
511                         }
512                 }
513         }
514 }
515
516 void DviSaveToFile(w, fp)
517         Widget w;
518         FILE *fp;
519 {
520         XtCheckSubclass(w, dviWidgetClass, NULL);
521         (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
522 }
523
524 static
525 void SaveToFile(w, fp)
526         Widget w;
527         FILE *fp;
528 {
529         DviWidget dw = (DviWidget)w;
530         long pos;
531         int c;
532
533         if (dw->dvi.tmpFile) {
534                 pos = ftell(dw->dvi.tmpFile);
535                 if (dw->dvi.ungot) {
536                         pos--;
537                         dw->dvi.ungot = 0;
538                         /* The ungot character is in the tmpFile, so we don't
539                            want to read it from file. */
540                         (void)getc(dw->dvi.file);
541                 }
542         }
543         else
544                 pos = ftell(dw->dvi.file);
545         FileSeek(dw, 0L);
546         while (DviGetC(dw, &c) != EOF)
547                 if (putc(c, fp) == EOF) {
548                         /* XXX print error message */
549                         break;
550                 }
551         FileSeek(dw, pos);
552 }
553
554 static
555 void ClassPartInitialize(widget_class)
556         WidgetClass widget_class;
557 {
558         DviWidgetClass wc = (DviWidgetClass)widget_class;
559         DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass;
560         if (wc->command_class.save == InheritSaveToFile)
561                 wc->command_class.save = super->command_class.save;
562 }
563         
564 /*
565 Local Variables:
566 c-indent-level: 8
567 c-continued-statement-offset: 8
568 c-brace-offset: -8
569 c-argdecl-indent: 8
570 c-label-offset: -8
571 c-tab-always-indent: nil
572 End:
573 */