Add groff 1.19.1, stripped down appropriately.
[dragonfly.git] / contrib / groff-1.19 / 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 /* font.c */
98 extern void ParseFontMap();
99 extern void DestroyFontMap();
100 extern void ForgetFonts();
101
102 /* page.c */
103 extern void DestroyFileMap();
104 extern long SearchPagePosition();
105 extern void FileSeek();
106 extern void ForgetPagePositions();
107
108 /* parse.c */
109 extern int ParseInput();
110
111 DviClassRec dviClassRec = {
112 {
113         &widgetClassRec,                /* superclass             */    
114         "Dvi",                          /* class_name             */
115         sizeof(DviRec),                 /* size                   */
116         ClassInitialize,                /* class_initialize       */
117         ClassPartInitialize,            /* class_part_initialize  */
118         FALSE,                          /* class_inited           */
119         Initialize,                     /* initialize             */
120         NULL,                           /* initialize_hook        */
121         Realize,                        /* realize                */
122         NULL,                           /* actions                */
123         0,                              /* num_actions            */
124         resources,                      /* resources              */
125         XtNumber(resources),            /* resource_count         */
126         NULLQUARK,                      /* xrm_class              */
127         FALSE,                          /* compress_motion        */
128         TRUE,                           /* compress_exposure      */
129         TRUE,                           /* compress_enterleave    */
130         FALSE,                          /* visible_interest       */
131         Destroy,                        /* destroy                */
132         NULL,                           /* resize                 */
133         Redisplay,                      /* expose                 */
134         SetValues,                      /* set_values             */
135         SetValuesHook,                  /* set_values_hook        */
136         NULL,                           /* set_values_almost      */
137         NULL,                           /* get_values_hook        */
138         NULL,                           /* accept_focus           */
139         XtVersion,                      /* version                */
140         NULL,                           /* callback_private       */
141         0,                              /* tm_table               */
142         QueryGeometry,                  /* query_geometry         */
143         NULL,                           /* display_accelerator    */
144         NULL                            /* extension              */
145 },{
146         SaveToFile,                     /* save    */
147 },
148 };
149
150 WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
151
152 static void ClassInitialize ()
153 {
154         XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
155                         NULL, 0 );
156 }
157
158 /****************************************************************
159  *
160  * Private Procedures
161  *
162  ****************************************************************/
163
164 /* ARGSUSED */
165 static void Initialize(request, new)
166         Widget request, new;
167 {
168         DviWidget       dw = (DviWidget) new;
169
170         dw->dvi.current_page = 0;
171         dw->dvi.font_map = 0;
172         dw->dvi.cache.index = 0;
173         dw->dvi.text_x_width = 0;
174         dw->dvi.text_device_width = 0;
175         dw->dvi.word_flag = 0;
176         dw->dvi.file = 0;
177         dw->dvi.tmpFile = 0;
178         dw->dvi.state = 0;
179         dw->dvi.readingTmp = 0;
180         dw->dvi.cache.char_index = 0;
181         dw->dvi.cache.font_size = -1;
182         dw->dvi.cache.font_number = -1;
183         dw->dvi.cache.adjustable[0] = 0;
184         dw->dvi.file_map = 0;
185         dw->dvi.fonts = 0;
186         dw->dvi.seek = False;
187         dw->dvi.device_resolution = dw->dvi.default_resolution;
188         dw->dvi.display_resolution = dw->dvi.default_resolution;
189         dw->dvi.paperlength = dw->dvi.default_resolution*11;
190         dw->dvi.paperwidth = (dw->dvi.default_resolution*8
191                               + dw->dvi.default_resolution/2);
192         dw->dvi.scale_factor = 1.0;
193         dw->dvi.sizescale = 1;
194         dw->dvi.line_thickness = -1;
195         dw->dvi.line_width = 1;
196         dw->dvi.fill = DVI_FILL_MAX;
197         dw->dvi.device_font = 0;
198         dw->dvi.device_font_number = -1;
199         dw->dvi.device = 0;
200         dw->dvi.native = 0;
201 }
202
203 #include "gray1.bm"
204 #include "gray2.bm"
205 #include "gray3.bm"
206 #include "gray4.bm"
207 #include "gray5.bm"
208 #include "gray6.bm"
209 #include "gray7.bm"
210 #include "gray8.bm"
211
212 static void
213 Realize (w, valueMask, attrs)
214         Widget                  w;
215         XtValueMask             *valueMask;
216         XSetWindowAttributes    *attrs;
217 {
218         DviWidget       dw = (DviWidget) w;
219         XGCValues       values;
220
221         if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
222                 attrs->backing_store = dw->dvi.backing_store;
223                 *valueMask |= CWBackingStore;
224         }
225         XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent,
226                         *valueMask, attrs);
227         values.foreground = dw->dvi.foreground;
228         values.cap_style = CapRound;
229         values.join_style = JoinRound;
230         values.line_width = dw->dvi.line_width;
231         dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w),
232                                        GCForeground|GCCapStyle|GCJoinStyle
233                                        |GCLineWidth,
234                                        &values);
235         dw->dvi.gray[0] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
236                                              gray1_bits,
237                                              gray1_width, gray1_height);
238         dw->dvi.gray[1] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
239                                              gray2_bits,
240                                              gray2_width, gray2_height);
241         dw->dvi.gray[2] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
242                                              gray3_bits,
243                                              gray3_width, gray3_height);
244         dw->dvi.gray[3] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
245                                              gray4_bits,
246                                              gray4_width, gray4_height);
247         dw->dvi.gray[4] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
248                                              gray5_bits,
249                                              gray5_width, gray5_height);
250         dw->dvi.gray[5] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
251                                              gray6_bits,
252                                              gray6_width, gray6_height);
253         dw->dvi.gray[6] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
254                                              gray7_bits,
255                                              gray7_width, gray7_height);
256         dw->dvi.gray[7] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
257                                              gray8_bits,
258                                              gray8_width, gray8_height);
259         values.background = dw->dvi.background;
260         values.stipple = dw->dvi.gray[5];
261         dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w),
262                                      GCForeground|GCBackground|GCStipple,
263                                      &values);
264
265         dw->dvi.fill_type = 9;
266
267         if (dw->dvi.file)
268                 OpenFile (dw);
269         ParseFontMap (dw);
270 }
271
272 static void
273 Destroy(w)
274         Widget w;
275 {
276         DviWidget       dw = (DviWidget) w;
277
278         XFreeGC (XtDisplay (w), dw->dvi.normal_GC);
279         XFreeGC (XtDisplay (w), dw->dvi.fill_GC);
280         XFreePixmap (XtDisplay (w), dw->dvi.gray[0]);
281         XFreePixmap (XtDisplay (w), dw->dvi.gray[1]);
282         XFreePixmap (XtDisplay (w), dw->dvi.gray[2]);
283         XFreePixmap (XtDisplay (w), dw->dvi.gray[3]);
284         XFreePixmap (XtDisplay (w), dw->dvi.gray[4]);
285         XFreePixmap (XtDisplay (w), dw->dvi.gray[5]);
286         XFreePixmap (XtDisplay (w), dw->dvi.gray[6]);
287         XFreePixmap (XtDisplay (w), dw->dvi.gray[7]);
288         DestroyFontMap (dw->dvi.font_map);
289         DestroyFileMap (dw->dvi.file_map);
290         device_destroy (dw->dvi.device);
291 }
292
293 /*
294  * Repaint the widget window
295  */
296
297 /* ARGSUSED */
298 static void
299 Redisplay(w, event, region)
300         Widget w;
301         XEvent *event;
302         Region region;
303 {
304         DviWidget       dw = (DviWidget) w;
305         XRectangle      extents;
306         
307         XClipBox (region, &extents);
308         dw->dvi.extents.x1 = extents.x;
309         dw->dvi.extents.y1 = extents.y;
310         dw->dvi.extents.x2 = extents.x + extents.width;
311         dw->dvi.extents.y2 = extents.y + extents.height;
312         ShowDvi (dw);
313 }
314
315 /*
316  * Set specified arguments into widget
317  */
318 /* ARGSUSED */
319 static Boolean
320 SetValues (current, request, new)
321         DviWidget current, request, new;
322 {
323         Boolean         redisplay = FALSE;
324         char            *new_map;
325         int             cur, req;
326
327         if (current->dvi.font_map_string != request->dvi.font_map_string) {
328                 new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1);
329                 if (new_map) {
330                         redisplay = TRUE;
331                         strcpy (new_map, request->dvi.font_map_string);
332                         new->dvi.font_map_string = new_map;
333                         if (current->dvi.font_map_string)
334                                 XtFree (current->dvi.font_map_string);
335                         current->dvi.font_map_string = 0;
336                         ParseFontMap (new);
337                 }
338         }
339
340         req = request->dvi.requested_page;
341         cur = current->dvi.requested_page;
342         if (cur != req) {
343                 if (!request->dvi.file)
344                     req = 0;
345                 else {
346                     if (req < 1)
347                             req = 1;
348                     if (current->dvi.last_page != 0 &&
349                         req > current->dvi.last_page)
350                             req = current->dvi.last_page;
351                 }
352                 if (cur != req)
353                     redisplay = TRUE;
354                 new->dvi.requested_page = req;
355                 if (current->dvi.last_page == 0 && req > cur)
356                         FindPage (new);
357         }
358
359         return redisplay;
360 }
361
362 /*
363  * use the set_values_hook entry to check when
364  * the file is set
365  */
366
367 static Boolean
368 SetValuesHook (dw, args, num_argsp)
369         DviWidget       dw;
370         ArgList         args;
371         Cardinal        *num_argsp;
372 {
373         Cardinal        i;
374
375         for (i = 0; i < *num_argsp; i++) {
376                 if (!strcmp (args[i].name, XtNfile)) {
377                         CloseFile (dw);
378                         OpenFile (dw);
379                         return TRUE;
380                 }
381         }
382         return FALSE;
383 }
384
385 static void CloseFile (dw)
386         DviWidget       dw;
387 {
388         if (dw->dvi.tmpFile)
389                 fclose (dw->dvi.tmpFile);
390         ForgetPagePositions (dw);
391 }
392
393 static void OpenFile (dw)
394         DviWidget       dw;
395 {
396         dw->dvi.tmpFile = 0;
397         if (!dw->dvi.seek)
398                 dw->dvi.tmpFile = tmpfile();
399         dw->dvi.requested_page = 1;
400         dw->dvi.last_page = 0;
401 }
402
403 static XtGeometryResult
404 QueryGeometry (w, request, geometry_return)
405         Widget                  w;
406         XtWidgetGeometry        *request, *geometry_return;
407 {
408         XtGeometryResult        ret;
409         DviWidget               dw = (DviWidget) w;
410
411         ret = XtGeometryYes;
412         if (((request->request_mode & CWWidth)
413              && request->width < MY_WIDTH(dw))
414             || ((request->request_mode & CWHeight)
415                 && request->height < MY_HEIGHT(dw)))
416                 ret = XtGeometryAlmost;
417         geometry_return->width = MY_WIDTH(dw);
418         geometry_return->height = MY_HEIGHT(dw);
419         geometry_return->request_mode = CWWidth|CWHeight;
420         return ret;
421 }
422
423 void
424 SetDevice (dw, name)
425         DviWidget       dw;
426         char            *name;
427 {
428         XtWidgetGeometry        request, reply;
429         XtGeometryResult ret;
430
431         ForgetFonts (dw);
432         dw->dvi.device = device_load (name);
433         if (!dw->dvi.device)
434                 return;
435         dw->dvi.sizescale = dw->dvi.device->sizescale;
436         dw->dvi.device_resolution = dw->dvi.device->res;
437         dw->dvi.native = dw->dvi.device->X11;
438         dw->dvi.paperlength = dw->dvi.device->paperlength;
439         dw->dvi.paperwidth = dw->dvi.device->paperwidth;
440         if (dw->dvi.native) {
441                 dw->dvi.display_resolution = dw->dvi.device_resolution;
442                 dw->dvi.scale_factor = 1.0;
443         }
444         else {
445                 dw->dvi.display_resolution = dw->dvi.default_resolution;
446                 dw->dvi.scale_factor = ((double)dw->dvi.display_resolution
447                                         / dw->dvi.device_resolution);
448         }
449         request.request_mode = CWWidth|CWHeight;
450         request.width = MY_WIDTH(dw);
451         request.height = MY_HEIGHT(dw);
452         ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply);
453         if (ret == XtGeometryAlmost
454             && reply.height >= request.height
455             && reply.width >= request.width) {
456                 request.width = reply.width;
457                 request.height = reply.height;
458                 XtMakeGeometryRequest ((Widget)dw, &request, &reply);
459         }
460 }
461
462 static void
463 ShowDvi (dw)
464         DviWidget       dw;
465 {
466         if (!dw->dvi.file) {
467                 static char Error[] = "No file selected";
468
469                 XSetFont (XtDisplay(dw), dw->dvi.normal_GC,
470                           dw->dvi.default_font->fid);
471                 XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
472                              20, 20, Error, strlen (Error));
473                 return;
474         }
475
476         FindPage (dw);
477         
478         dw->dvi.display_enable = 1;
479         ParseInput (dw);
480         if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page)
481                 dw->dvi.requested_page = dw->dvi.last_page;
482 }
483
484 static void
485 FindPage (dw)
486         DviWidget       dw;
487 {
488         int     i;
489         long    file_position;
490
491         if (dw->dvi.requested_page < 1)
492                 dw->dvi.requested_page = 1;
493
494         if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
495                 dw->dvi.requested_page = dw->dvi.last_page;
496
497         file_position = SearchPagePosition (dw, dw->dvi.requested_page);
498         if (file_position != -1) {
499                 FileSeek(dw, file_position);
500                 dw->dvi.current_page = dw->dvi.requested_page;
501         } else {
502                 for (i=dw->dvi.requested_page; i > 0; i--) {
503                         file_position = SearchPagePosition (dw, i);
504                         if (file_position != -1)
505                                 break;
506                 }
507                 if (file_position == -1)
508                         file_position = 0;
509                 FileSeek (dw, file_position);
510
511                 dw->dvi.current_page = i;
512                 
513                 dw->dvi.display_enable = 0;
514                 while (dw->dvi.current_page != dw->dvi.requested_page) {
515                         dw->dvi.current_page = ParseInput (dw);
516                         /*
517                          * at EOF, seek back to the beginning of this page.
518                          */
519                         if (!dw->dvi.readingTmp && feof (dw->dvi.file)) {
520                                 file_position = SearchPagePosition (dw,
521                                                 dw->dvi.current_page);
522                                 if (file_position != -1)
523                                         FileSeek (dw, file_position);
524                                 dw->dvi.requested_page = dw->dvi.current_page;
525                                 break;
526                         }
527                 }
528         }
529 }
530
531 void DviSaveToFile(w, fp)
532         Widget w;
533         FILE *fp;
534 {
535         XtCheckSubclass(w, dviWidgetClass, NULL);
536         (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
537 }
538
539 static
540 void SaveToFile(w, fp)
541         Widget w;
542         FILE *fp;
543 {
544         DviWidget dw = (DviWidget)w;
545         long pos;
546         int c;
547
548         if (dw->dvi.tmpFile) {
549                 pos = ftell(dw->dvi.tmpFile);
550                 if (dw->dvi.ungot) {
551                         pos--;
552                         dw->dvi.ungot = 0;
553                         /* The ungot character is in the tmpFile, so we don't
554                            want to read it from file. */
555                         (void)getc(dw->dvi.file);
556                 }
557         }
558         else
559                 pos = ftell(dw->dvi.file);
560         FileSeek(dw, 0L);
561         while (DviGetC(dw, &c) != EOF)
562                 if (putc(c, fp) == EOF) {
563                         /* XXX print error message */
564                         break;
565                 }
566         FileSeek(dw, pos);
567 }
568
569 static
570 void ClassPartInitialize(widget_class)
571         WidgetClass widget_class;
572 {
573         DviWidgetClass wc = (DviWidgetClass)widget_class;
574         DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass;
575         if (wc->command_class.save == InheritSaveToFile)
576                 wc->command_class.save = super->command_class.save;
577 }
578         
579 /*
580 Local Variables:
581 c-indent-level: 8
582 c-continued-statement-offset: 8
583 c-brace-offset: -8
584 c-argdecl-indent: 8
585 c-label-offset: -8
586 c-tab-always-indent: nil
587 End:
588 */