* Dvi.c (OpenFile): Use tmpdir() for security reasons.
[s-roff.git] / src / xditview / Dvi.c
blob08eb810a7bc88516064a4bb154c8b772bde0f711
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 "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"
198 static void
199 Realize (w, valueMask, attrs)
200 Widget w;
201 XtValueMask *valueMask;
202 XSetWindowAttributes *attrs;
204 DviWidget dw = (DviWidget) w;
205 XGCValues values;
207 if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
208 attrs->backing_store = dw->dvi.backing_store;
209 *valueMask |= CWBackingStore;
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);
251 dw->dvi.fill_type = 9;
253 if (dw->dvi.file)
254 OpenFile (dw);
255 ParseFontMap (dw);
258 static void
259 Destroy(w)
260 Widget w;
262 DviWidget dw = (DviWidget) w;
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);
280 * Repaint the widget window
283 /* ARGSUSED */
284 static void
285 Redisplay(w, event, region)
286 Widget w;
287 XEvent *event;
288 Region region;
290 DviWidget dw = (DviWidget) w;
291 XRectangle extents;
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);
302 * Set specified arguments into widget
304 /* ARGSUSED */
305 static Boolean
306 SetValues (current, request, new)
307 DviWidget current, request, new;
309 Boolean redisplay = FALSE;
310 char *new_map;
311 int cur, req;
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);
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;
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);
345 return redisplay;
349 * use the set_values_hook entry to check when
350 * the file is set
353 static Boolean
354 SetValuesHook (dw, args, num_argsp)
355 DviWidget dw;
356 ArgList args;
357 Cardinal *num_argsp;
359 Cardinal i;
361 for (i = 0; i < *num_argsp; i++) {
362 if (!strcmp (args[i].name, XtNfile)) {
363 CloseFile (dw);
364 OpenFile (dw);
365 return TRUE;
368 return FALSE;
371 static void CloseFile (dw)
372 DviWidget dw;
374 if (dw->dvi.tmpFile)
375 fclose (dw->dvi.tmpFile);
376 ForgetPagePositions (dw);
379 static void OpenFile (dw)
380 DviWidget dw;
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;
389 static XtGeometryResult
390 QueryGeometry (w, request, geometry_return)
391 Widget w;
392 XtWidgetGeometry *request, *geometry_return;
394 XtGeometryResult ret;
395 DviWidget dw = (DviWidget) w;
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;
409 SetDevice (dw, name)
410 DviWidget dw;
411 char *name;
413 XtWidgetGeometry request, reply;
414 XtGeometryResult ret;
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;
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);
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);
447 static void
448 ShowDvi (dw)
449 DviWidget dw;
451 if (!dw->dvi.file) {
452 static char Error[] = "No file selected";
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;
461 FindPage (dw);
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;
469 static void
470 FindPage (dw)
471 DviWidget dw;
473 int i;
474 long file_position;
476 if (dw->dvi.requested_page < 1)
477 dw->dvi.requested_page = 1;
479 if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
480 dw->dvi.requested_page = dw->dvi.last_page;
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;
492 if (file_position == -1)
493 file_position = 0;
494 FileSeek (dw, file_position);
496 dw->dvi.current_page = i;
498 dw->dvi.display_enable = 0;
499 while (dw->dvi.current_page != dw->dvi.requested_page) {
500 dw->dvi.current_page = ParseInput (dw);
502 * at EOF, seek back to the beginning of this page.
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;
516 void DviSaveToFile(w, fp)
517 Widget w;
518 FILE *fp;
520 XtCheckSubclass(w, dviWidgetClass, NULL);
521 (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
524 static
525 void SaveToFile(w, fp)
526 Widget w;
527 FILE *fp;
529 DviWidget dw = (DviWidget)w;
530 long pos;
531 int c;
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);
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;
551 FileSeek(dw, pos);
554 static
555 void ClassPartInitialize(widget_class)
556 WidgetClass widget_class;
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;
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: