1 /*========================================================================*\
2 
3 Copyright (c) 1990-2014  Paul Vojta and others
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to
7 deal in the Software without restriction, including without limitation the
8 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 sell copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11 
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL PAUL
18 VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 THE SOFTWARE.
22 
23 NOTE: xdvi is based on prior work as noted in the modification history, below.
24 
25 \*========================================================================*/
26 
27 /*
28  * DVI previewer for X.
29  *
30  * Eric Cooper, CMU, September 1985.
31  *
32  * Code derived from dvi-imagen.c.
33  *
34  * Modification history:
35  * 1/1986	Modified for X.10	--Bob Scheifler, MIT LCS.
36  * 7/1988	Modified for X.11	--Mark Eichin, MIT
37  * 12/1988	Added 'R' option, toolkit, magnifying glass
38  *					--Paul Vojta, UC Berkeley.
39  * 2/1989	Added tpic support	--Jeffrey Lee, U of Toronto
40  * 4/1989	Modified for System V	--Donald Richardson, Clarkson Univ.
41  * 3/1990	Added VMS support	--Scott Allendorf, U of Iowa
42  * 7/1990	Added reflection mode	--Michael Pak, Hebrew U of Jerusalem
43  * 1/1992	Added greyscale code	--Till Brychcy, Techn. Univ. Muenchen
44  *					  and Lee Hetherington, MIT
45  * 7/1992       Added extra menu buttons--Nelson H. F. Beebe <beebe@math.utah.edu>
46  * 4/1994	Added DPS support, bounding box
47  *					--Ricardo Telichevesky
48  *					  and Luis Miguel Silveira, MIT RLE.
49  * 2/1995       Added rulers support    --Nelson H. F. Beebe <beebe@math.utah.edu>
50  * 1/2001	Added source specials	--including ideas from Stefan Ulrich,
51  *					  U Munich
52  *
53  * Compilation options:
54  *
55  * VMS		    compile for VMS
56  * WORDS_BIGENDIAN  store bitmaps internally with most significant bit first
57  * BMTYPE	    store bitmaps in unsigned BMTYPE
58  * BMBYTES	    sizeof(unsigned BMTYPE)
59  * ALTFONT	    default for -altfont option
60  * SHRINK	    default for -s option (shrink factor)
61  * MFMODE	    default for -mfmode option
62  * A4		    use European size paper, and change default dimension to cm
63  * TEXXET	    support reflection dvi codes (right-to-left typesetting)
64  * GREY		    use grey levels to shrink fonts
65  * PS_GS	    use Ghostscript to render pictures/bounding boxes
66  * PS_DPS	    use display postscript to render pictures/bounding boxes
67  * PS_NEWS	    use the NeWS server to render pictures/bounding boxes
68  * GS_PATH	    path to call the Ghostscript interpreter by
69  * MAGICK	    use ImageMagick to render (external) image files
70  */
71 
72 
73 #include "xdvi-config.h"
74 #include "xdvi.h"
75 #include "version.h"
76 
77 /* Xlib and Xutil are already included */
78 #include <X11/cursorfont.h>
79 #include <X11/keysym.h>
80 #include <X11/Xatom.h>
81 #include <X11/StringDefs.h>
82 #include <X11/Shell.h>	/* needed for def. of XtNiconX */
83 
84 #ifdef HAVE_X11_XMU_EDITRES_H
85 # include <X11/Xmu/Editres.h>
86 #endif
87 
88 /* to allow one common dependency file for Xaw/Motif,
89    we always include all the headers and have
90    #ifdef MOTIF
91    tests inside the headers.
92 */
93 #if defined(NEW_MENU_CREATION) || defined(MOTIF)
94 #include "menu.h"
95 #else
96 #include "xm_menu.h"
97 #include "xaw_menu.h"
98 #endif /* NEW_MENU_CREATION */
99 #include "xm_toolbar.h"
100 
101 #ifdef MOTIF
102 
103 # include <Xm/Xm.h>
104 # include <Xm/Frame.h>
105 # include <Xm/PushB.h>
106 # include <Xm/MainW.h>
107 # include <Xm/ToggleB.h>
108 # include <Xm/RowColumn.h>
109 # include <Xm/ScrolledW.h>
110 # include <Xm/MenuShell.h>
111 # include <Xm/DrawingA.h>
112 # include <Xm/Form.h>
113 # include <Xm/PanedW.h>
114 # include <Xm/List.h>
115 # include <Xm/Protocols.h>
116 
117 # include <Xm/Display.h>
118 
119 # ifdef MOTIF11 /* FIXME: We'll probably need a config check for this? */
120 /* used to set up XmStrings */
121 XmStringCharSet G_charset = (XmStringCharSet)XmSTRING_DEFAULT_CHARSET;
122 # else
123 XmStringCharSet G_charset = XmFONTLIST_DEFAULT_TAG;
124 # endif
125 
126 #else /* MOTIF */
127 
128 # include <X11/Xaw/Viewport.h>
129 # include <X11/Xaw/AsciiText.h>
130 # include <X11/Xaw/Box.h>
131 # include <X11/Xaw/Command.h>
132 # include <X11/Xaw/Dialog.h>
133 # include <X11/Xaw/Form.h>
134 # include <X11/Xaw/Paned.h>
135 # include <X11/Xaw/Scrollbar.h>
136 # include <X11/Xaw/Command.h>
137 
138 #endif /* MOTIF */
139 
140 #include <signal.h>
141 #include <stdlib.h>
142 #include <ctype.h>
143 
144 #include "xserver-info.h"
145 
146 #include "kpathsea/c-fopen.h"
147 #include "kpathsea/c-pathch.h"
148 #include "kpathsea/c-stat.h"
149 #include "kpathsea/progname.h"
150 #include "kpathsea/tex-file.h"
151 #include "kpathsea/tex-hush.h"
152 #include "kpathsea/tex-make.h"
153 #include "string-utils.h"
154 #include "kpathsea/c-errno.h"
155 
156 #include "translations.h"
157 #include "c-openmx.h"
158 #include "xicon.h"
159 #include "x_util.h"
160 #include "message-window.h"
161 #include "events.h"
162 #include "mag.h"
163 #include "pagesel.h"
164 #include "dvi-draw.h"
165 #include "statusline.h"
166 #include "util.h"
167 #include "hypertex.h"
168 #include "xaw_menu.h"
169 #include "xdvi-debug.h"
170 #include "pagehist.h"
171 #include "filehist.h"
172 #include "print-internal.h"
173 #include "exit-handlers.h"
174 #include "xm_prefsP.h" /* for Xdvi_PREFS_BROWSER_DEFAULTS and Xdvi_PREFS_EDITOR_DEFAULTS */
175 
176 #if FREETYPE
177 # include "font-open.h"	/* for init_t1_lookup() */
178 #endif
179 
180 #ifdef VMS
181 #  include "pixmaps/hand.xbm"
182 #  include "pixmaps/hand_mask.xbm"
183 #endif
184 #include "pixmaps/magglass.xbm"
185 #include "pixmaps/magglass_mask.xbm"
186 
187 #ifdef DEBUG
188 #include<asm/msr.h>
189 unsigned long time_start=0, time_end=0;
190 #endif
191 
192 
193 #ifdef MOTIF
194 #include <Xm/MwmUtil.h>
195 
196 #else /* MOTIF */
197 
198 /* need to fake it */
199 
200 /* bit definitions for MwmHints.flags */
201 #define MWM_HINTS_FUNCTIONS (1L << 0)
202 #define MWM_HINTS_DECORATIONS (1L << 1)
203 #define MWM_HINTS_INPUT_MODE (1L << 2)
204 #define MWM_HINTS_STATUS (1L << 3)
205 
206 /* bit definitions for MwmHints.decorations */
207 #define MWM_DECOR_ALL  (1L << 0)
208 #define MWM_DECOR_BORDER (1L << 1)
209 #define MWM_DECOR_RESIZEH (1L << 2)
210 #define MWM_DECOR_TITLE  (1L << 3)
211 #define MWM_DECOR_MENU  (1L << 4)
212 #define MWM_DECOR_MINIMIZE (1L << 5)
213 #define MWM_DECOR_MAXIMIZE (1L << 6)
214 
215 struct PropMotifWmHints {
216     unsigned long flags;
217     unsigned long functions;
218     unsigned long decorations;
219     long          inputMode;
220     unsigned long status;
221 };
222 
223 #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
224 
225 #endif /* MOTIF */
226 
227 #if HAVE_X11_INTRINSICI_H
228 # include <X11/IntrinsicI.h>
229 #else
230 
231 /* Taken from <X11/TranslateI.h> in libXt-1.1.3 (June 2012) */
232 typedef struct _LateBindings {
233     unsigned int knot:1;
234     unsigned int pair:1;
235     unsigned short ref_count;	/* garbage collection */
236     KeySym keysym;
237 } LateBindings, *LateBindingsPtr;
238 
239 #endif /* not HAVE_X11_INTRINSICI_H */
240 
241 struct mouse_acts	*mouse_actions;
242 
243 char *dvi_property;		/* for setting in window */
244 size_t dvi_property_length;	/* length of above, for efficiency */
245 XImage *G_image;
246 int G_backing_store;
247 Display *DISP;
248 Screen *SCRN;
249 XtAccelerators G_accels_cr;
250 
251 #ifdef GREY
252 Visual		*G_visual;
253 unsigned int	G_depth;
254 Colormap	G_colormap;
255 #else
256 # define G_depth	(unsigned int) DefaultDepthOfScreen(SCRN)
257 # define G_visual	DefaultVisualOfScreen(SCRN)
258 # define G_colormap	DefaultColormapOfScreen(SCRN)
259 #endif
260 
261 /* global widgets */
262 
263 #if defined(MOTIF)
264 Widget page_list;
265 #if USE_XAW_PANNER
266 #include "Panner.h"
267 Widget panner;
268 static Dimension g_save_shadow_thickness;
269 #endif
270 #endif
271 
272 static Atom mainDeleteWindow;
273 
274 #ifndef MOTIF
275 static Atom wmProtocols;
276 static void
handle_delete_message(Widget widget,XtPointer closure,XEvent * event,Boolean * cont)277 handle_delete_message(Widget widget, XtPointer closure, XEvent *event, Boolean *cont)
278 {
279     UNUSED(cont);
280     UNUSED(widget);
281 
282     ASSERT(closure == NULL, "handle_delete_message doesn't accept a non-NULL closure argument");
283     if (event->type == ClientMessage
284 	&& event->xclient.message_type == wmProtocols
285 	&& (unsigned)(event->xclient.data.l[0]) == mainDeleteWindow) {
286 	/* non-k xdvi also evaluates closure, but we don't, since it's a function pointer
287 	   which isn't convertible to void * in ANSI C */
288 	xdvi_exit(EXIT_SUCCESS);
289     }
290 }
291 #endif
292 
293 #ifdef TEST_SCROLLING
294 #warning ========== compiling with TEST_SCROLLING ==========
295 #endif
296 
297 
298 /* for measuring distance from the ruler */
299 int g_ruler_pos_x, g_ruler_pos_y;
300 
301 Boolean ignore_papersize_specials = False;
302 
303 #ifndef	ALTFONT
304 # define ALTFONT    "cmr10"
305 #endif
306 
307 #ifndef	SHRINK
308 # define SHRINK	    8
309 #endif
310 
311 #ifndef	MFMODE
312 # define MFMODE	    NULL
313 #endif
314 
315 #undef MKTEXPK
316 #define MKTEXPK MAKEPK
317 
318 #if defined(PS_GS) && !defined(GS_PATH)
319 # define GS_PATH "gs"
320 #endif
321 
322 static Dimension bwidth = 2;
323 
324 struct x_resources resource;
325 
326 struct program_globals globals;
327 
328 /* color of cursor */
329 static XColor m_cursor_color;
330 
331 
332 struct WindowRec mane = { (Window) 0, 1, 0, 0, 0, 0, MAXDIM, 0, MAXDIM, 0 };
333 
334 /* currwin is temporary storage except for within redraw() */
335 struct WindowRec currwin = { (Window) 0, 1, 0, 0, 0, 0, MAXDIM, 0, MAXDIM, 0 };
336 
337 #define	offset(field)	XtOffsetOf(struct x_resources, field)
338 static int base_tick_length = 4;
339 
340 static char XtRBool3[] = "Bool3";	/* resource for Bool3 */
341 
342 static XtResource application_resources[] = {
343     {"regression", "Regression", XtRBoolean, sizeof(Boolean),
344      offset(regression), XtRString, "false"},
345     {"geometry", "Geometry", XtRString, sizeof(char *),
346      offset(geometry), XtRString, (XtPointer) NULL},
347     {"windowSize", "WindowSize", XtRString, sizeof(char *),
348      offset(windowsize), XtRString, (XtPointer) NULL},
349     {"rememberWindowSize", "RememberWindowSize", XtRBoolean, sizeof(Boolean),
350      offset(remember_windowsize), XtRString, "false"},
351     /* used to check whether app-defaults file is out of sync. Initialize
352        to a low default value (one before the resource was introduced) */
353     {"appDefaultsFileVersion", "AppDefaultsFileVersion", XtRInt, sizeof(int),
354      offset(app_defaults_fileversion), XtRImmediate, (XtPointer)20030302 },
355     {"shrinkFactor", "ShrinkFactor", XtRInt, sizeof(int),
356      offset(shrinkfactor), XtRImmediate, (XtPointer) SHRINK},
357     {"delayRulers", "DelayRulers", XtRBoolean, sizeof(Boolean),
358      offset(delay_rulers), XtRString, "true"},
359     {"useTeXPages", "UseTeXPages", XtRBoolean, sizeof(Boolean),
360      offset(use_tex_pages), XtRString, "false"},
361     {"densityPercent", "DensityPercent", XtRInt, sizeof(int),
362      offset(density), XtRString, "40"},
363     {"omega", "Omega", XtRBoolean, sizeof(Boolean),
364      offset(omega), XtRString, "true"},
365     {"mainTranslations", "MainTranslations", XtRString, sizeof(char *),
366      offset(main_translations), XtRString, (XtPointer) NULL},
367     {"mouseTranslations", "MouseTranslations", XtRString, sizeof(char *),
368      offset(mouse_translations), XtRString, (XtPointer) NULL },
369     {"wheelUnit", "WheelUnit", XtRInt, sizeof(int),
370      offset(wheel_unit), XtRImmediate, (XtPointer) 80},
371     {"mouseMode", "MouseMode", XtRInt, sizeof(int),
372      offset(mouse_mode), XtRImmediate, (XtPointer) MOUSE_MODE1 },
373     {"mouseMode1Name", "MouseMode1Name", XtRString, sizeof(char *),
374      offset(mouse_mode1_name), XtRString, (XtPointer) "Magnifier"},
375     {"mouseMode1Description", "MouseMode1Description", XtRString, sizeof(char *),
376      offset(mouse_mode1_description), XtRString, (XtPointer) "click to enlarge text"},
377     {"mouseMode1Cursor", "MouseMode1Cursor", XtRInt, sizeof(int),
378      offset(mouse_mode1_cursor), XtRImmediate, (XtPointer) -1},
379     {"mouseMode2Name", "MouseMode2Name", XtRString, sizeof(char *),
380      offset(mouse_mode2_name), XtRString, (XtPointer) "Text Selection"},
381     {"mouseMode2Description", "MouseMode2Description", XtRString, sizeof(char *),
382      offset(mouse_mode2_description), XtRString, (XtPointer) "click and drag to select a region of text"},
383     {"mouseMode2Cursor", "MouseMode2Cursor", XtRInt, sizeof(int),
384      offset(mouse_mode2_cursor), XtRImmediate, (XtPointer) XC_cross },
385     {"mouseMode3Name", "MouseMode3Name", XtRString, sizeof(char *),
386      offset(mouse_mode3_name), XtRString, (XtPointer) "Ruler"},
387     {"mouseMode3Description", "MouseMode3Description", XtRString, sizeof(char *),
388      offset(mouse_mode3_description), XtRString, (XtPointer) "click and drag to set/move ruler"},
389     {"mouseMode3Cursor", "MouseMode3Cursor", XtRInt, sizeof(int),
390      offset(mouse_mode3_cursor), XtRImmediate, (XtPointer) XC_crosshair },
391 #ifdef GREY
392     {"gamma", "Gamma", XtRFloat, sizeof(float),
393      offset(gamma), XtRString, "1"},
394     /*     {"invertedFactor", "InvertedFactor", XtRFloat, sizeof(float), */
395     /*      offset(inverted_factor), XtRString, "3.0"}, */
396 #endif
397     {"pixelsPerInch", "PixelsPerInch", XtRInt, sizeof(int),
398      offset(pixels_per_inch), XtRImmediate, (XtPointer) BDPI},
399     {"sideMargin", "Margin", XtRString, sizeof(char *),
400      offset(sidemargin), XtRString, (XtPointer) NULL},
401     {"tickLength", "TickLength", XtRInt, sizeof(int),
402      offset(tick_length), XtRInt, (XtPointer) &base_tick_length},
403     {"tickUnits", "TickUnits", XtRString, sizeof(char *),
404      offset(tick_units), XtRString, "mm"},
405     {"topMargin", "Margin", XtRString, sizeof(char *),
406      offset(topmargin), XtRString, (XtPointer) NULL},
407     {"xOffset", "Offset", XtRString, sizeof(char *),
408      offset(xoffset), XtRString, (XtPointer) NULL},
409     {"yOffset", "Offset", XtRString, sizeof(char *),
410      offset(yoffset), XtRString, (XtPointer) NULL},
411     {"useCurrentOffset", "UseCurrentOffset", XtRBoolean, sizeof(Boolean),
412      offset(use_current_offset), XtRString, "False" },
413     {"paper", "Paper", XtRString, sizeof(char *),
414      offset(paper), XtRString, (XtPointer) DEFAULT_PAPER},
415     {"paperLandscape", "PaperLandscape", XtRBoolean, sizeof(Boolean),
416      offset(paper_landscape), XtRString, "false"},
417     {"altFont", "AltFont", XtRString, sizeof(char *),
418      offset(alt_font), XtRString, (XtPointer) ALTFONT},
419     {"makePk", "MakePk", XtRBoolean, sizeof(Boolean),
420      offset(makepk), XtRString,
421 #ifdef MAKE_TEX_PK_BY_DEFAULT
422      "true"
423 #else
424      "false"
425 #endif
426     },
427     {"mfMode", "MfMode", XtRString, sizeof(char *),
428      offset(mfmode), XtRString, MFMODE},
429     {"editor", "Editor", XtRString, sizeof(char *),
430      offset(editor), XtRString, (XtPointer) NULL},
431 #if FREETYPE
432     {"type1", "Type1", XtRBoolean, sizeof(Boolean),
433      offset(freetype), XtRString, "true"},
434 #endif
435 #if HAVE_XI21
436     {"xi2Scrolling", "Xi2Scrolling", XtRBoolean, sizeof(Boolean),
437      offset(xi2scrolling), XtRString, "true"},
438 #endif
439     {"sourcePosition", "SourcePosition", XtRString, sizeof(char *),
440      offset(src_pos), XtRString, (XtPointer) NULL},
441     {"findString", "FindString", XtRString, sizeof(char *),
442      offset(find_string), XtRString, (XtPointer) NULL},
443     {"textEncoding", "TextEncoding", XtRString, sizeof(char *),
444      offset(text_encoding), XtRString, (XtPointer) NULL},
445     {"fork", "Fork", XtRBoolean, sizeof(Boolean),
446      offset(src_fork), XtRString, "true"},
447 #ifdef RGB_ANTI_ALIASING
448     {"subPixels", "SubPixels", XtRString, sizeof(char *),
449      offset(sub_pixels), XtRString, "Unknown"},
450 #endif
451     {"noFileArgUseHistory", "NoFileArgUseHistory", XtRBoolean, sizeof(Boolean),
452      offset(no_file_arg_use_history), XtRString, "true"},
453     {"fileHistory", "FileHistory", XtRString, sizeof(char *),
454      offset(file_history), XtRString, (XtPointer) NULL},
455     {"fileHistorySize", "FileHistorySize", XtRInt, sizeof(int),
456      offset(file_history_size), XtRImmediate, (XtPointer)20},
457     {"unique", "Unique", XtRBoolean, sizeof(Boolean),
458      offset(unique), XtRString, "false"},
459     {"listFonts", "ListFonts", XtRBoolean, sizeof(Boolean),
460      offset(list_fonts), XtRString, "false"},
461     {"reverseVideo", "ReverseVideo", XtRBoolean, sizeof(Boolean),
462      offset(reverse), XtRString, "false"},
463     {"warnSpecials", "WarnSpecials", XtRBoolean, sizeof(Boolean),
464      offset(warn_spec), XtRString, "false"},
465     {"hush", "Hush", XtRBoolean, sizeof(Boolean),
466      offset(hush), XtRString, "false"},
467     {"hushLostChars", "HushLostChars", XtRBoolean, sizeof(Boolean),
468      offset(hush_chars), XtRString, "false"},
469     {"hushChecksums", "HushChecksums", XtRBoolean, sizeof(Boolean),
470      offset(hush_chk), XtRString, "false"},
471     {"hushStdout", "HushStdout", XtRBoolean, sizeof(Boolean),
472      offset(hush_stdout), XtRString, "false"},
473     {"hushBell", "HushBell", XtRBoolean, sizeof(Boolean),
474      offset(hush_bell), XtRString, "false"},
475     {"safer", "Safer", XtRBoolean, sizeof(Boolean),
476      offset(safer), XtRString, "false"},
477 #ifdef VMS
478     {"foreground", "Foreground", XtRString, sizeof(char *),
479      offset(fore_color), XtRString, (XtPointer) NULL},
480     {"background", "Background", XtRString, sizeof(char *),
481      offset(back_color), XtRString, (XtPointer) NULL},
482 #endif
483     {"iconGeometry", "IconGeometry", XtRString, sizeof(char *),
484      offset(icon_geometry), XtRString, (XtPointer) NULL},
485     {"keepPosition", "KeepPosition", XtRBoolean, sizeof(Boolean),
486      offset(keep_flag), XtRString, "false"},
487 #ifdef PS
488     {"postscript", "Postscript", XtRInt, sizeof(int),
489      offset(postscript), XtRImmediate, (XtPointer)1},
490     {"allowShell", "AllowShell", XtRBoolean, sizeof(Boolean),
491      offset(allow_shell), XtRString, "false"},
492 # ifdef	PS_DPS
493     {"dps", "DPS", XtRBoolean, sizeof(Boolean),
494      offset(useDPS), XtRString, "true"},
495 # endif
496 # ifdef	PS_NEWS
497     {"news", "News", XtRBoolean, sizeof(Boolean),
498      offset(useNeWS), XtRString, "true"},
499 # endif
500 # ifdef	PS_GS
501     {"ghostscript", "Ghostscript", XtRBoolean, sizeof(Boolean),
502      offset(useGS), XtRString, "true"},
503     {"gsSafer", "Safer", XtRBoolean, sizeof(Boolean),
504      offset(gs_safer), XtRString, "true"},
505     {"gsAlpha", "Alpha", XtRBoolean, sizeof(Boolean),
506      offset(gs_alpha), XtRString, "false"},
507     {"interpreter", "Interpreter", XtRString, sizeof(char *),
508      offset(gs_path), XtRString, (XtPointer) GS_PATH},
509     {"palette", "Palette", XtRString, sizeof(char *),
510      offset(gs_palette), XtRString, (XtPointer) "Color"},
511     {"gsTimeout", "GSTimeout", XtRInt, sizeof(int),
512      offset(gs_timeout), XtRImmediate, (XtPointer)3000},
513 # endif /* PS_GS */
514 # ifdef	MAGICK
515     {"magick", "ImageMagick", XtRBoolean, sizeof(Boolean),
516      offset(useMAGICK), XtRString, "true"},
517     {"magick_cache", "MagickCache", XtRString, sizeof(char *),
518      offset(magick_cache), XtRString, (XtPointer) NULL},
519 # endif
520 #endif /* PS */
521     {"prescan", "Prescan", XtRBoolean, sizeof(Boolean),
522      offset(prescan), XtRString, "true"},
523     {"tempFile", "TempFile", XtRBoolean, sizeof(Boolean),
524      offset(use_temp_fp), XtRString, "true"},
525     {"copy", "Copy", XtRBoolean, sizeof(Boolean),
526      offset(copy), XtRString, "false"},
527     {"thorough", "Thorough", XtRBoolean, sizeof(Boolean),
528      offset(thorough), XtRString, "false"},
529     {"fullscreen", "Fullscreen", XtRBoolean, sizeof(Boolean),
530      offset(fullscreen), XtRString, "false"},
531     {"pause", "Pause", XtRBoolean, sizeof(Boolean),
532      offset(pause), XtRString, "false"},
533     {"pauseSpecial", "PauseSpecial", XtRString, sizeof(char *),
534      offset(pause_special), XtRString, (XtPointer)"xdvi:pause"},
535     {"debugLevel", "DebugLevel", XtRString, sizeof(char *),
536      offset(debug_arg), XtRString, (XtPointer) NULL},
537     {"menuTranslations", "MenuTranslations", XtRString, sizeof(char *),
538      offset(menu_translations), XtRString, (XtPointer) default_menu_config},
539     {"watchFile", "WatchFile", XtRFloat, sizeof(float),
540      offset(watch_file), XtRString, "0"},
541     {"expert", "Expert", XtRBoolean, sizeof(Boolean),
542      offset(expert), XtRString, (XtPointer) NULL},
543     {"expertMode", "ExpertMode", XtRInt, sizeof(int),
544      offset(expert_mode), XtRImmediate, (XtPointer)31 /* everything on */ },
545 #ifndef MOTIF
546     {"buttonSideSpacing", "ButtonSpacing", XtRDimension, sizeof(Dimension),
547      offset(btn_side_spacing), XtRImmediate, (XtPointer) 8},
548     {"buttonTopSpacing", "ButtonSpacing", XtRDimension, sizeof(Dimension),
549      offset(btn_top_spacing), XtRImmediate, (XtPointer) 16},
550     {"buttonBetweenSpacing", "ButtonSpacing", XtRDimension, sizeof(Dimension),
551      offset(btn_between_spacing), XtRImmediate, (XtPointer) 8},
552     /* only used if menus consist of buttons only */
553     {"buttonBetweenExtra", "ButtonSpacing", XtRDimension, sizeof(Dimension),
554      offset(btn_between_extra), XtRImmediate, (XtPointer)16},
555     {"buttonBorderWidth", "BorderWidth", XtRDimension, sizeof(Dimension),
556      offset(btn_border_width), XtRImmediate, (XtPointer) 1},
557 #endif /* MOTIF */
558     {"statusline", "Statusline", XtRBoolean, sizeof(Boolean),
559      offset(statusline), XtRString, (XtPointer) NULL},
560 #ifdef MOTIF
561     {"toolbarTranslations", "ToolbarTranslations", XtRString, sizeof(char *),
562      offset(toolbar_translations), XtRString, (XtPointer) default_toolbar_translations},
563     {"toolbarPixmapFile", "ToolbarPixmapFile", XtRString, sizeof(char *),
564      offset(toolbar_pixmap_file), XtRString, (XtPointer) "toolbar.xpm"},
565     {"toolbarButtonsRaised", "ToolbarButtonsRaised", XtRBoolean, sizeof(Boolean),
566      offset(toolbar_buttons_raised), XtRString, "True"},
567     {"tooltipsInStatusline", "TooltipsInStatusline", XtRBoolean, sizeof(Boolean),
568      offset(tooltips_in_statusline), XtRString, "True"},
569     {"showTooltips", "ShowTooltips", XtRBoolean, sizeof(Boolean),
570      offset(show_tooltips), XtRString, "True"},
571 #endif /* MOTIF */
572     {"pageListHighlightCurrent", "PageListHighlightCurrent", XtRBoolean, sizeof(Boolean),
573      offset(pagelist_highlight_current), XtRString, "True"},
574     {"pageListWidth", "PageListWidth", XtRDimension, sizeof(Dimension),
575      offset(pagelist_width), XtRImmediate, (XtPointer) 80},
576     {"magnifierSize1", "MagnifierSize", XtRString, sizeof(char *),
577      offset(mg_arg[0]), XtRString, (XtPointer) NULL},
578     {"magnifierSize2", "MagnifierSize", XtRString, sizeof(char *),
579      offset(mg_arg[1]), XtRString, (XtPointer) NULL},
580     {"magnifierSize3", "MagnifierSize", XtRString, sizeof(char *),
581      offset(mg_arg[2]), XtRString, (XtPointer) NULL},
582     {"magnifierSize4", "MagnifierSize", XtRString, sizeof(char *),
583      offset(mg_arg[3]), XtRString, (XtPointer) NULL},
584     {"magnifierSize5", "MagnifierSize", XtRString, sizeof(char *),
585      offset(mg_arg[4]), XtRString, (XtPointer) NULL},
586 #if COLOR
587     {"color", "Color", XtRBoolean, sizeof(Boolean),
588      offset(use_color), XtRString, "true"},
589 #endif /* COLOR */
590     {"dvipsPath", "DvipsPath", XtRString, sizeof(char *),
591      offset(dvips_path), XtRString, (XtPointer)DEFAULT_DVIPS_PATH},
592     {"ps2pdfPath", "Ps2PdfPath", XtRString, sizeof(char *),
593      offset(ps2pdf_path), XtRString, (XtPointer)DEFAULT_PS2PDF_PATH},
594     {"dvipsHangTime", "DvipsHangTime", XtRInt, sizeof(int),
595      offset(dvips_hang), XtRImmediate, (XtPointer) -1500},
596     {"dvipsFailHangTime", "DvipsFailHangTime", XtRInt, sizeof(int),
597      offset(dvips_fail_hang), XtRImmediate, (XtPointer) -5000},
598     {"dvipsPrinterString", "DvipsPrinterString", XtRString, sizeof(char *),
599      offset(dvips_printer_str), XtRString, (XtPointer)NULL},
600     {"dvipsOptionsString", "DvipsOptionsString", XtRString, sizeof(char *),
601      offset(dvips_options_str), XtRString, (XtPointer)NULL},
602     {"defaultSavingFormat", "DefaultSavingFormat", XtRInt, sizeof(int),
603      offset(default_saving_format), XtRImmediate, (XtPointer)0},
604     {"defaultPrintingTarget", "DefaultPrintingTarget", XtRInt, sizeof(int),
605      offset(default_printing_target), XtRImmediate, (XtPointer)1},
606 #ifdef GREY
607     {"grey", "Grey", XtRBoolean, sizeof(Boolean),
608      offset(use_grey), XtRString, "true"},
609     {"install", "Install", XtRBool3, sizeof(Bool3),
610      offset(install), XtRString, "maybe"},
611 #endif /* GREY */
612     {"matchInverted", "MatchInverted", XtRBoolean, sizeof(Boolean),
613      offset(match_highlight_inverted), XtRString, "true"},
614     {"ruleColor", "RuleColor", XtRPixel, sizeof(Pixel),
615      offset(rule_pixel), XtRPixel, (XtPointer) &resource.rule_pixel},
616     {"ruleColor", "RuleColor", XtRString, sizeof(char *),
617      offset(rule_color), XtRString, (XtPointer) NULL},
618     /* linkStyle: style for presenting links:
619        link_style is a bitsmask `xy' with x = color, y = underline, viz.:
620        0: no highlighting at all
621        1: underline with linkColor
622        2: no underlining, text with linkColor
623        3: underlining and text with linkColor
624     */
625     {"linkStyle", "LinkStyle", XtRInt, sizeof(int),
626      offset(link_style), XtRImmediate, (XtPointer) 3},
627     {"linkColor", "LinkColor", XtRString, sizeof(char *),
628      offset(link_color), XtRString, (XtPointer)LINK_COLOR_FALLBACK},
629     {"visitedLinkColor", "VisitedLinkColor", XtRString, sizeof(char *),
630      offset(visited_link_color), XtRString, (XtPointer)VISITED_LINK_COLOR_FALLBACK},
631     {"wwwBrowser", "WWWBrowser", XtRString, sizeof(char *),
632      offset(browser), XtRString, (XtPointer) NULL},
633 #ifdef MOTIF
634     {"prefsBrowserList", "PrefsBrowserList", XtRString, sizeof(char *),
635      offset(prefs_browser_list), XtRString, (XtPointer)Xdvi_PREFS_BROWSER_DEFAULTS },
636     {"prefsEditorList", "PrefsEditorList", XtRString, sizeof(char *),
637      offset(prefs_editor_list), XtRString, (XtPointer)Xdvi_PREFS_EDITOR_DEFAULTS },
638 #  if USE_COMBOBOX
639     {"searchHistory", "SearchHistory", XtRString, sizeof(char *),
640      offset(search_history), XtRString, (XtPointer)NULL },
641     {"searchHistorySize", "SearchHistorySize", XtRInt, sizeof(int),
642      offset(search_history_size), XtRImmediate, (XtPointer)20},
643 #  endif
644 #endif
645     /* defaults for unknown mime types */
646     {"unknownMimeSuffix", "UnknownMimeSuffix", XtRString, sizeof(char *),
647      offset(unknown_mime_suffix), XtRString, "application/x-unknown"},
648     {"noMimeSuffix", "NoMimeSuffix", XtRString, sizeof(char *),
649      offset(no_mime_suffix), XtRString, "application/x-unknown"},
650     {"anchorPosition", "AnchorPosition", XtRString, sizeof(char *),
651      offset(anchor_pos), XtRString, (XtPointer) NULL},
652     /* bitmask for current search window settings; only used internally! */
653     {"searchWindowDefaults", "SearchWindowDefaults", XtRInt, sizeof(int),
654      offset(search_window_defaults), XtRImmediate, (XtPointer)0},
655     /* whether to open file in new window from file selector (only for DVI files) */
656     {"fileselOpenNewWindow", "FileselOpenNewWindow", XtRBoolean, sizeof(Boolean),
657      offset(filesel_open_new_window), XtRString, "False"},
658     /* resources for help text */
659     {"helpGeneral", "HelpGeneral", XtRString, sizeof(char *),
660      offset(help_general), XtRString, NULL},
661     {"helpHypertex", "HelpHypertex", XtRString, sizeof(char *),
662      offset(help_hypertex), XtRString, NULL},
663     {"helpOthercommands", "HelpOthercommands", XtRString, sizeof(char *),
664      offset(help_othercommands), XtRString, NULL},
665     {"helpMarking", "HelpMarking", XtRString, sizeof(char *),
666      offset(help_marking), XtRString, NULL},
667     {"helpPagemotion", "HelpPagemotion", XtRString, sizeof(char *),
668      offset(help_pagemotion), XtRString, NULL},
669     {"helpMousebuttons", "HelpMousebuttons", XtRString, sizeof(char *),
670      offset(help_mousebuttons), XtRString, NULL},
671     {"helpModes", "HelpModes", XtRString, sizeof(char *),
672      offset(help_modes), XtRString, NULL},
673     {"helpSearch", "HelpSearch", XtRString, sizeof(char *),
674      offset(help_search), XtRString, NULL},
675     {"helpSourcespecials", "HelpSoucespecials", XtRString, sizeof(char *),
676      offset(help_sourcespecials), XtRString, NULL},
677 #ifdef GREY
678     {"pageHistorySize", "PageHistorySize", XtRInt, sizeof(int),
679      offset(page_history_size), XtRImmediate, (XtPointer)1000},
680 };
681 
682 static XtResource app_pixel_resources[] = {	/* get these later */
683 #endif /* GREY */
684     {"foreground", "Foreground", XtRPixel, sizeof(Pixel),
685      offset(fore_Pixel), XtRString, XtDefaultForeground},
686     {"background", "Background", XtRPixel, sizeof(Pixel),
687      offset(back_Pixel), XtRString, XtDefaultBackground},
688     /*     {"borderColor", "BorderColor", XtRPixel, sizeof(Pixel), */
689     /*      offset(brdr_Pixel), XtRPixel, (XtPointer) &resource.fore_Pixel}, */
690     {"highlight", "Highlight", XtRPixel, sizeof(Pixel),
691      offset(hl_Pixel), XtRPixel, (XtPointer) &resource.fore_Pixel},
692     {"cursorColor", "CursorColor", XtRPixel, sizeof(Pixel),
693      offset(cr_Pixel), XtRImmediate, (XtPointer)ULONG_MAX},
694 };
695 #undef offset
696 
697 
698 #ifndef MOTIF
699 
700 # ifdef	NOQUERY
701 #  define drawWidgetClass widgetClass
702 # else
703 
704 static XtGeometryResult
QueryGeometry(Widget w,XtWidgetGeometry * constraints,XtWidgetGeometry * reply)705 QueryGeometry(Widget w,
706 	      XtWidgetGeometry *constraints,
707 	      XtWidgetGeometry *reply)
708 {
709     UNUSED(w);
710     UNUSED(constraints);
711     reply->request_mode = CWWidth | CWHeight;
712     reply->width = globals.page.w;
713     reply->height = globals.page.h;
714 
715     return XtGeometryAlmost;
716 }
717 
718 # include <X11/IntrinsicP.h>
719 # include <X11/CoreP.h>
720 
721 /* if the following gives you trouble, just compile with -DNOQUERY */
722 static WidgetClassRec drawingWidgetClass = {
723     {
724 	/* superclass		*/ &widgetClassRec,
725 	/* class_name		*/ "Draw",
726 	/* widget_size		*/ sizeof(WidgetRec),
727 	/* class_initialize	*/ NULL,
728 	/* class_part_initialize	*/ NULL,
729 	/* class_inited		*/ FALSE,
730 	/* initialize		*/ NULL,
731 	/* initialize_hook		*/ NULL,
732 	/* realize			*/ XtInheritRealize,
733 	/* actions			*/ NULL,
734 	/* num_actions		*/ 0,
735 	/* resources		*/ NULL,
736 	/* num_resources		*/ 0,
737 	/* xrm_class		*/ NULLQUARK,
738 	/* compress_motion		*/ FALSE,
739 	/* compress_exposure	*/ TRUE,
740 	/* compress_enterleave	*/ FALSE,
741 	/* visible_interest	*/ FALSE,
742 	/* destroy			*/ NULL,
743 	/* resize			*/ XtInheritResize,
744 	/* expose			*/ XtInheritExpose,
745 	/* set_values		*/ NULL,
746 	/* set_values_hook		*/ NULL,
747 	/* set_values_almost	*/ XtInheritSetValuesAlmost,
748 	/* get_values_hook		*/ NULL,
749 	/* accept_focus		*/ XtInheritAcceptFocus,
750 	/* version			*/ XtVersion,
751 	/* callback_offsets	*/ NULL,
752 	/* tm_table		*/ XtInheritTranslations,
753 	/* query_geometry		*/ QueryGeometry,
754 	/* display_accelerator	*/ XtInheritDisplayAccelerator,
755 	/* extension		*/ NULL
756     }
757 };
758 
759 #  define drawWidgetClass &drawingWidgetClass
760 
761 # endif /* NOQUERY */
762 #endif /* not MOTIF */
763 
764 
765 int
atopix(const char * arg,Boolean allow_minus)766 atopix(const char *arg, Boolean allow_minus)
767 {
768     int len = strlen(arg);
769     const char *arg_end = arg;
770     char tmp[11];
771     double factor;
772 
773     if (allow_minus && *arg_end == '-')
774 	++arg_end;
775     while ((*arg_end >= '0' && *arg_end <= '9') || *arg_end == '.')
776 	if (arg_end >= arg + XtNumber(tmp) - 1)
777 	    return 0;
778 	else
779 	    ++arg_end;
780     memcpy(tmp, arg, arg_end - arg);
781     tmp[arg_end - arg] = '\0';
782 
783 #if A4
784     factor = 1.0 / 2.54;	/* cm */
785 #else
786     factor = 1.0;	/* inches */
787 #endif
788     if (len > 2)
789 	switch (arg[len - 2] << 8 | arg[len - 1]) {
790 #if A4
791 	case 'i' << 8 | 'n':
792 	    factor = 1.0;
793 	    break;
794 #else
795 	case 'c' << 8 | 'm':
796 	    factor = 1.0 / 2.54;
797 	    break;
798 #endif
799 	case 'm' << 8 | 'm':
800 	    factor = 1.0 / 25.4;
801 	    break;
802 	case 'p' << 8 | 't':
803 	    factor = 1.0 / 72.27;
804 	    break;
805 	case 'p' << 8 | 'c':
806 	    factor = 12.0 / 72.27;
807 	    break;
808 	case 'b' << 8 | 'p':
809 	    factor = 1.0 / 72.0;
810 	    break;
811 	case 'd' << 8 | 'd':
812 	    factor = 1238.0 / 1157.0 / 72.27;
813 	    break;
814 	case 'c' << 8 | 'c':
815 	    factor = 12 * 1238.0 / 1157.0 / 72.27;
816 	    break;
817 	case 's' << 8 | 'p':
818 	    factor = 1.0 / 72.27 / 65536;
819 	    break;
820 	}
821 
822     return factor * atof(tmp) * resource.pixels_per_inch + 0.5;
823 }
824 
825 #if CHECK_APP_FILEVERSION
826 static void
check_app_defaults_fileversion(void)827 check_app_defaults_fileversion(void)
828 {
829     /* update this when new essential resources are introduced */
830     static const int required_version = 20030303;
831 
832     if (resource.app_defaults_fileversion < required_version) {
833 	const char *filename = kpse_find_file("XDvi", kpse_program_text_format, 0);
834 	if (filename == NULL)
835 	    filename = "XDvi";
836 
837 	fprintf(stderr, "filename: %d\n", resource.app_defaults_fileversion);
838 	popup_message(globals.widgets.top_level,
839 		      MSG_WARN,
840 		      NULL,
841 		      "Your application defaults file `%s' is outdated. "
842 		      "This version of xdvi requires a file "
843 		      "with date >= %d. Your file is older, or doesn't have a date.\n"
844 		      "Please obtain a new version of the file `XDvi', e.g. from:\n"
845 		      "http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/xdvi/xdvik/texk/xdvik/texmf/\n"
846 		      "and copy it to a directory in your $XDVIINPUTS path.",
847 		      filename, required_version);
848     }
849 }
850 #endif
851 
852 
853 
854 #ifdef GREY
855 static Arg temp_args1[] = {
856     {XtNdepth, (XtArgVal) 0},
857     {XtNvisual, (XtArgVal) 0},
858     {XtNcolormap, (XtArgVal) 0},
859 };
860 
861 /*
862  * Alternate routine to convert color name to Pixel (needed to substitute
863  * "black" or "white" for BlackPixelOfScreen, etc., since a different visual
864  * and colormap are in use).
865  */
866 
867 static Boolean
XdviCvtStringToPixel(Display * dpy,XrmValuePtr args,Cardinal * num_args,XrmValuePtr fromVal,XrmValuePtr toVal,XtPointer * closure_ret)868 XdviCvtStringToPixel(Display *dpy,
869 		     XrmValuePtr args, Cardinal *num_args,
870 		     XrmValuePtr fromVal, XrmValuePtr toVal,
871 		     XtPointer *closure_ret)
872 {
873     XrmValue replacement_val;
874     Boolean default_is_fg;
875 
876     if ((strcmp((String) fromVal->addr, XtDefaultForeground) == 0
877 	 && (default_is_fg = True, True))
878 	|| (strcmp((String) fromVal->addr, XtDefaultBackground) == 0
879 	    && ((default_is_fg = False), True))) {
880 	replacement_val.size = sizeof(String);
881 	replacement_val.addr = (default_is_fg == resource.reverse)
882 	    ? "white" : "black";
883 	fromVal = &replacement_val;
884     }
885 
886     return XtCvtStringToPixel(dpy, args, num_args, fromVal, toVal, closure_ret);
887 }
888 
889 #endif
890 
891 
892 /*
893  * Set the `sourceposition' propery of the window `w' to `source_str'.
894  * This is usually done in `client' mode to notify the instance of
895  * xdvi running in window `w' to start a forward search. After this,
896  * the client usually exits normally.
897  */
898 static void
set_sourceposition_property(const char * source_str,Window win)899 set_sourceposition_property(const char *source_str, Window win)
900 {
901     /* parse the special in order to expand the filename */
902     struct src_parsed_special data;
903     char *new_special = NULL;
904     char *expanded_filename = NULL;
905 
906     data.filename_len = 0;
907     data.filename = NULL;
908 
909     src_parse(source_str, strlen(source_str), &data);
910 
911     if (data.filename_len == 0) {
912 	/* can't give a GUI warning in `client' mode - just exit with error */
913 	XDVI_FATAL((stderr,
914 		    "Filename missing in -sourceposition argument (%s)!",
915 		    source_str));
916     }
917 
918     TRACE_CLIENT((stderr, "got data: line %d, col %d, file |%s|, len %lu\n",
919 		  data.line, data.col, data.filename, (unsigned long)data.filename_len));
920 
921     /* expand -sourceposition argument if it contains a path component.
922        We don't use REALPATH here, because `tex -src' doesn't expand
923        symlinks either. Instead, use canonicalize_path() to expand
924        `../' and './' manually. */
925     if (strchr(data.filename, '/') != NULL
926 	&& (expanded_filename = expand_filename(data.filename, USE_CWD_PATH)) != NULL) {
927 	char *tmp = canonicalize_path(expanded_filename);
928 	free(data.filename);
929 	free(expanded_filename);
930 	expanded_filename = tmp;
931     }
932     else
933 	expanded_filename = data.filename;
934 
935     TRACE_CLIENT((stderr, "expanded1: |%s|\n", expanded_filename));
936 
937     new_special = xmalloc(2 * LENGTH_OF_INT + 2 /* 2 for `:' and separating space */
938 			  + strlen(expanded_filename) + 1);
939     sprintf(new_special, "%d:%d %s", data.line, data.col, expanded_filename);
940     free(expanded_filename);
941 
942     TRACE_CLIENT((stderr, "matched!"));
943     set_string_property(new_special, atom_src_goto(), win);
944     free(new_special);
945     set_string_property("", atom_raise(), win);
946 }
947 
948 static void
set_stringsearch_property(const char * str,Window win)949 set_stringsearch_property(const char *str, Window win)
950 {
951     set_string_property(str, atom_find_string(), win);
952     set_string_property("", atom_raise(), win);
953 }
954 
955 
956 
957 /* Translation of valid paper types to dimensions,
958    which are used internally. The newline characters are a hack
959    to format the list neatly for error messages.
960    A* series measures are taken from
961    http://www.cl.cam.ac.uk/~mgk25/iso-paper.html
962 */
963 static const char *paper_types[] = {
964     "us", "8.5x11in",
965     "letter", "8.5x11in",	/* dvips compatibility */
966     "ledger", "17x11in",	/* dvips compatibility */
967     "tabloid", "11x17in",	/* dvips compatibility */
968     "usr", "11x8.5in",
969     "legal", "8.5x14in",
970     "legalr", "14x8.5in",
971     "foolscap", "13.5x17.0in",	/* ??? */
972     "foolscapr", "17.0x13.5in",
973     "", "0",
974 
975     /* ISO `A' formats, Portrait */
976     "a0", "841x1189mm",
977     "a1", "594x841mm",
978     "a2", "420x594mm",
979     "a3", "297x420mm",
980     "a4", "210x297mm",
981     "a5", "148x210mm",
982     "a6", "105x148mm",
983     "a7", "74x105mm",
984     "a8", "52x74mm",
985     "a9", "37x52mm",
986     "a10","26x37mm",
987     "", "0",
988 
989     /* ISO `A' formats, Landscape */
990     "a0r", "1189x841mm",
991     "a1r", "841x594mm",
992     "a2r", "594x420mm",
993     "a3r", "420x297mm",
994     "a4r", "297x210mm",
995     "a5r", "210x148mm",
996     "a6r", "148x105mm",
997     "a7r", "105x74mm",
998     "a8r", "74x52mm",
999     "a9r", "52x37mm",
1000     "a10r","37x26mm",
1001     "", "0",
1002 
1003     /* ISO `B' formats, Portrait */
1004     "b0", "1000x1414mm",
1005     "b1", "707x1000mm",
1006     "b2", "500x707mm",
1007     "b3", "353x500mm",
1008     "b4", "250x353mm",
1009     "b5", "176x250mm",
1010     "b6", "125x176mm",
1011     "b7", "88x125mm",
1012     "b8", "62x88mm",
1013     "b9", "44x62mm",
1014     "b10","31x44mm",
1015     "", "0",
1016 
1017     /* ISO `B' formats, Landscape */
1018     "b0r", "1414x1000mm",
1019     "b1r", "1000x707mm",
1020     "b2r", "707x500mm",
1021     "b3r", "500x353mm",
1022     "b4r", "353x250mm",
1023     "b5r", "250x176mm",
1024     "b6r", "176x125mm",
1025     "b7r", "125x88mm",
1026     "b8r", "88x62mm",
1027     "b9r", "62x44mm",
1028     "b10r","44x31mm",
1029     "", "0",
1030 
1031     /* ISO `C' formats, Portrait */
1032     "c0", "917x1297mm",
1033     "c1", "648x917mm",
1034     "c2", "458x648mm",
1035     "c3", "324x458mm",
1036     "c4", "229x324mm",
1037     "c5", "162x229mm",
1038     "c6", "114x162mm",
1039     "c7", "81x114mm",
1040     "c8", "57x81mm",
1041     "c9", "40x57mm",
1042     "c10","28x40mm",
1043     "", "0",
1044 
1045     /* ISO `C' formats, Landscape */
1046     "c0r", "1297x917mm",
1047     "c1r", "917x648mm",
1048     "c2r", "648x458mm",
1049     "c3r", "458x324mm",
1050     "c4r", "324x229mm",
1051     "c5r", "229x162mm",
1052     "c6r", "162x114mm",
1053     "c7r", "114x81mm",
1054     "c8r", "81x57mm",
1055     "c9r", "57x40mm",
1056     "c10r","40x28mm",
1057 };
1058 
1059 /* access methods for paper_types */
get_paper_types(void)1060 const char **get_paper_types(void) {
1061     return paper_types;
1062 }
1063 
get_paper_types_size(void)1064 size_t get_paper_types_size(void) {
1065     return XtNumber(paper_types);
1066 }
1067 
1068 /* Set the icon name and title name standard properties on `globals.widgets.top_level'.
1069  * We use the basename of the DVI file (without the .dvi), so different xdvi
1070  * invocations can be distinguished, yet do not use up too much real estate.
1071  *
1072  * This function returns freshly allocated memory in *icon_name and *title_name
1073  * which the caller is responsible for free()ing again.
1074  */
1075 void
get_icon_and_title(const char * filename,char ** icon_name,char ** title_name)1076 get_icon_and_title(const char *filename, char **icon_name, char **title_name)
1077 {
1078     /* Use basename of DVI file for name in icon and title.  */
1079     const char *ptr;
1080     char *ptr2;
1081 
1082     /* SU 2000/12/16: added page number information */
1083     const char *const title_name_fmt = "%s:  %s   (%d page%s)";
1084 
1085     MYTRACE((stderr, "get_icon_and_title called with: |%s|", filename));
1086 
1087     ptr = strrchr(filename, '/');
1088     if (ptr != NULL)
1089 	++ptr;
1090     else {
1091 	ptr = filename;
1092     }
1093 
1094     /*
1095      * Remove the `file:' prefix from the icon name; since some windowmanagers
1096      * only display a prefix in window lists etc., it's more significant this
1097      * way.
1098      */
1099 
1100     if (memcmp(ptr, "file:", 5) == 0) {
1101 	ptr += 5;
1102     }
1103     *icon_name = xstrdup(ptr);
1104 
1105     MYTRACE((stderr, "before chopping: icon_name: |%s|", *icon_name));
1106     if ((ptr2 = strstr(*icon_name, ".dvi")) != NULL) {
1107 	/* chop off .dvi extension */
1108 	*ptr2 = '\0';
1109     }
1110     MYTRACE((stderr, "after chopping: icon_name: |%s|", *icon_name));
1111 
1112     *title_name = xmalloc(strlen(title_name_fmt)
1113 			  + strlen(XDVIK_PROGNAME)
1114 			  + strlen(*icon_name)
1115 			  + LENGTH_OF_INT
1116 			  + 2);	/* 2 for additional plural `s' */
1117     MYTRACE((stderr, "total_pages: %d", total_pages));
1118     sprintf(*title_name, title_name_fmt, XDVIK_PROGNAME, *icon_name, total_pages,
1119 	    (total_pages > 1) ? "s" : "");
1120 
1121     MYTRACE((stderr, "title_name, icon_name: |%s|%s|", *title_name, *icon_name));
1122 }
1123 
1124 void
set_icon_and_title(const char * icon_name,const char * title_name)1125 set_icon_and_title(const char *icon_name, const char *title_name)
1126 {
1127     if (!XtIsRealized(globals.widgets.top_level)) {
1128 	MYTRACE((stderr, "set_icon_and_title: returning"));
1129 	return;
1130     }
1131     XtVaSetValues(globals.widgets.top_level, XtNtitle, (XtArgVal) title_name, XtNiconName, (XtArgVal) icon_name, NULL);
1132     XSetStandardProperties(DISP, XtWindow(globals.widgets.top_level), title_name, icon_name,
1133 			   (Pixmap) 0, NULL, 0, NULL);
1134 }
1135 
1136 static void
get_window_constraints(XtWidgetGeometry * reply,Dimension screen_w,Dimension screen_h,int * add_h)1137 get_window_constraints(XtWidgetGeometry *reply,
1138 		       Dimension screen_w, Dimension screen_h,
1139 		       int *add_h)
1140 {
1141     XtWidgetGeometry constraints;
1142 
1143     constraints.request_mode = reply->request_mode = 0;
1144 
1145     /* fprintf(stderr, "setting constraints.width to %d\n", globals.page.w); */
1146     constraints.width = globals.page.w;
1147     if (globals.page.w > screen_w) {
1148 	constraints.request_mode |= CWWidth;
1149 	constraints.width = screen_w;
1150     }
1151 
1152 /*     fprintf(stderr, "setting constraints.height to %d; screen_h = %d\n", globals.page.h, screen_h); */
1153     constraints.height = globals.page.h;
1154     if (constraints.height > screen_h) {
1155 	constraints.request_mode |= CWHeight;
1156 	constraints.height = screen_h;
1157     }
1158 
1159     if (constraints.request_mode != 0
1160 	&& constraints.request_mode != (CWWidth | CWHeight)) {
1161 #ifdef MOTIF
1162 	(void)XtQueryGeometry(globals.widgets.main_window, &constraints, reply);
1163 #else
1164 	(void)XtQueryGeometry(globals.widgets.vport_widget, &constraints, reply);
1165 #endif
1166     }
1167 /*     fprintf(stderr, "reply height: %d; screen_h: %d; add_h: %d\n", reply->height, screen_h, *add_h); */
1168     if (!(reply->request_mode & CWWidth))
1169 	reply->width = constraints.width;
1170     if (reply->width >= screen_w)
1171 	reply->width = screen_w;
1172     if (!(reply->request_mode & CWHeight)) {
1173 	reply->height = constraints.height - 2 * bwidth;
1174     }
1175 
1176     if (reply->height + *add_h >= screen_h) {
1177 	reply->height = screen_h
1178 #ifdef MOTIF
1179 	    - 1.5
1180 #else
1181 	    - 2
1182 #endif
1183 	    * *add_h - 2 * bwidth;
1184     }
1185 }
1186 
1187 void
set_windowsize(Dimension * ret_w,Dimension * ret_h,int add_w,int add_h,Boolean override)1188 set_windowsize(Dimension *ret_w, Dimension *ret_h, int add_w, int add_h, Boolean override)
1189 {
1190     static Arg set_wh_args[] = {
1191 	{XtNwidth, (XtArgVal) 0},
1192 	{XtNheight, (XtArgVal) 0},
1193     };
1194     Dimension screen_w, screen_h;
1195 
1196     const char *test_geometry = resource.geometry;
1197 
1198     if (resource.fullscreen) {
1199 	Dimension w = WidthOfScreen(SCRN), h = HeightOfScreen(SCRN);
1200 
1201 	if (currwin.shrinkfactor == 0) { /* if not set by user */
1202 	    Dimension height_factor = ROUNDUP(globals.page.unshrunk_h, h);
1203 	    currwin.shrinkfactor = ROUNDUP(globals.page.unshrunk_w, w);
1204 	    if (height_factor >= currwin.shrinkfactor)
1205 		currwin.shrinkfactor = height_factor;
1206 	    /*  	    fprintf(stderr, "factor was 0, using %d\n", currwin.shrinkfactor); */
1207 	}
1208 	/*  	else */
1209 	/*  	    fprintf(stderr, "factor != 0, using %d\n", currwin.shrinkfactor); */
1210 
1211 	mane.shrinkfactor = currwin.shrinkfactor;
1212 	init_page();
1213 	set_wh_args[0].value = (XtArgVal)w;
1214 	set_wh_args[1].value = (XtArgVal)h;
1215 	*ret_w = w;
1216 	*ret_h = h;
1217 #ifdef MOTIF
1218 #if USE_XAW_PANNER
1219 	XtVaGetValues(globals.widgets.main_window, XmNshadowThickness, &g_save_shadow_thickness, NULL);
1220 #endif
1221 	XtVaSetValues(globals.widgets.main_window, XmNshadowThickness, 0, NULL);
1222 #endif
1223 	XtSetValues(globals.widgets.top_level, set_wh_args, XtNumber(set_wh_args));
1224     }
1225     else if (override) {
1226 	set_wh_args[0].value = (XtArgVal)*ret_w;
1227 	set_wh_args[1].value = (XtArgVal)*ret_h;
1228 	XtSetValues(globals.widgets.top_level, set_wh_args, XtNumber(set_wh_args));
1229     }
1230     else { /* determine a window size that fits the current shrink factor */
1231 	Arg temp_args3 = { XtNborderWidth, (XtArgVal)&bwidth };
1232 	XtWidgetGeometry reply;
1233 
1234 	XtGetValues(globals.widgets.top_level, &temp_args3, 1);	/* get border width */
1235 	screen_w = WidthOfScreen(SCRN) - 2 * bwidth;
1236 
1237 	screen_w -= add_w;
1238 	/* screen_h = HeightOfScreen(SCRN) - 2 * bwidth - get_statusline_height() - 6; */
1239 	screen_h = HeightOfScreen(SCRN) - 2 * bwidth;
1240 	for (;;) {	/* actually, at most two passes */
1241 	    Dimension height_factor;
1242 
1243 	    TRACE_GUI((stderr, "geometry: |%s|; remember: %d, windowsize: %s",
1244 		       resource.geometry ? resource.geometry : "<NULL>",
1245 		       resource.remember_windowsize,
1246 		       resource.windowsize ? resource.windowsize : "<NULL>"));
1247 
1248 	    if (resource.geometry == NULL && !resource.remember_windowsize) {
1249 		/* geometry not set by user, try to find geometry that fits the shrink factor */
1250 		get_window_constraints(&reply, screen_w, screen_h, &add_h);
1251 		TRACE_GUI((stderr, "w: %d, h: %d, add_h: %d, reply: %d x %d",
1252 			   screen_w, screen_h, add_h, reply.width, reply.height));
1253 	    }
1254 	    else {
1255 		int x, y;
1256 		unsigned int width, height;
1257 		int flags;
1258 
1259 		if (resource.remember_windowsize && resource.windowsize != NULL)
1260 		    test_geometry = resource.windowsize;
1261 		else
1262 		    test_geometry = resource.geometry;
1263 		flags = XParseGeometry(test_geometry, &x, &y, &width, &height);
1264 
1265 		if (!(flags & WidthValue) || !(flags & HeightValue)) {
1266 		    /* no geometry specified, use fallback */
1267 		    get_window_constraints(&reply, screen_w, screen_h, &add_h);
1268 		}
1269 
1270 		/* warn about bad values */
1271 		if (flags & WidthValue) {
1272 		    if (width > (unsigned int)(2 * bwidth + add_w)) {
1273 			TRACE_GUI((stderr, "width: %hu, bwidth: %hu, add_w: %d",
1274 				   width, bwidth, add_w));
1275 			reply.width = width - 2 * bwidth - add_w;
1276 		    }
1277 		    else {
1278 			reply.width = width;
1279 		    }
1280 		}
1281 		if (flags & HeightValue) {
1282 		    if (height > (unsigned int)(2 * bwidth + add_h)) {
1283 			TRACE_GUI((stderr, "height: %hu, bwidth: %hu, add_h: %d",
1284 				   height, bwidth, add_h));
1285 			reply.height = height - 2 * bwidth - add_h;
1286 		    }
1287 		    else {
1288 			reply.height = height;
1289 		    }
1290 		}
1291 		TRACE_GUI((stderr, "setting geometry: %dx%d", (int)reply.width, (int)reply.height));
1292 	    }
1293 
1294 	    /* now reply.{width,height} contain max. usable window size */
1295 
1296 	    /* User didn't use `-s 0', use either default or other user-specified value */
1297 	    if (currwin.shrinkfactor != 0) {
1298 		/*  		fprintf(stderr, "factor != 0, using %d\n", currwin.shrinkfactor); */
1299 		break;
1300 	    }
1301 	    /*  	    else { */
1302 	    /*  		fprintf(stderr, "factor was 0, using %d\n", currwin.shrinkfactor); */
1303 	    /*  	    } */
1304 
1305 	    /* else, try to find a suitable shrink factor: */
1306 	    currwin.shrinkfactor = ROUNDUP(globals.page.unshrunk_w, reply.width - 2);
1307 	    /*  	    fprintf(stderr, "factor w: %d\n", currwin.shrinkfactor); */
1308 
1309 	    height_factor = ROUNDUP(globals.page.unshrunk_h, reply.height - 2);
1310 	    /*  	    fprintf(stderr, "factor h: %d\n", height_factor); */
1311 	    if (height_factor >= currwin.shrinkfactor)
1312 		currwin.shrinkfactor = height_factor;
1313 
1314 	    /*  	    fprintf(stderr, "factor now is: %d\n", currwin.shrinkfactor); */
1315 
1316 	    mane.shrinkfactor = currwin.shrinkfactor;
1317 	    init_page();
1318 	    set_wh_args[0].value = (XtArgVal)globals.page.w;
1319 	    set_wh_args[1].value = (XtArgVal)globals.page.h;
1320 	    *ret_w = globals.page.w;
1321 	    *ret_h = globals.page.h;
1322 	    XtSetValues(globals.widgets.draw_widget, set_wh_args, XtNumber(set_wh_args));
1323 	}
1324 #ifdef MOTIF
1325 	/*
1326 	  SU 2002/11/23: Added scrollbar width to height computation.
1327 	  Otherwise, when the vertical space isn't sufficient, a
1328 	  vertical scrollbar will be added, but since this makes the
1329 	  display narrower, a horizontal scrollbar will be added as
1330 	  well, even if this wouldn't be neccessary.
1331 
1332 	  SU 2003/09/30: Apparently the size computation works now, even
1333 	  though I'm not sure why (scrollbar value isn't in add_w). Investigate.
1334 	*/
1335 	/* HACK ALERT: 4 for window decoration borders - FIXME: get actual values?? */
1336 	set_wh_args[0].value = reply.width + add_w + (test_geometry == NULL ? 4 : 0);
1337 	set_wh_args[1].value = reply.height + add_h + (test_geometry == NULL ? 4 : 0);
1338 	XtSetValues(globals.widgets.top_level, set_wh_args, XtNumber(set_wh_args));
1339 
1340 #else /* MOTIF */
1341 
1342 	set_wh_args[0].value = reply.width + add_w + 2 * bwidth; /*  + (test_geometry == NULL ? 15 : (2 * bwidth)); */
1343 	/*
1344 	  FIXME: use real height of statusline here
1345 	  Somehow I didn't manage to use XtVaCreateWidget in a call to
1346 	  create_statusline() above, and XtManageChild() below.
1347 	  In that case, we could do without get_statusline_height().
1348 	*/
1349 	set_wh_args[1].value = reply.height + (test_geometry == NULL ? (2 * bwidth + add_h) : 0);
1350 	XtSetValues(globals.widgets.top_level, set_wh_args, XtNumber(set_wh_args));
1351 	set_wh_args[0].value -= add_w;
1352 	XtSetValues(globals.widgets.vport_widget, set_wh_args, XtNumber(set_wh_args));
1353 
1354 #endif /* MOTIF */
1355 	*ret_w = set_wh_args[0].value;
1356 	*ret_h = set_wh_args[1].value;
1357 	TRACE_GUI((stderr, "returning: w=%d, h=%d", *ret_w, *ret_h));
1358     }
1359 }
1360 
1361 static void
net_wm_toggle_fullscreen(int flag)1362 net_wm_toggle_fullscreen(int flag)
1363 {
1364     Atom NET_WM_FULLSCREEN = XInternAtom(DISP, "_NET_WM_STATE_FULLSCREEN", True);
1365 
1366     if (NET_WM_FULLSCREEN) {
1367 	XEvent ev;
1368 	Atom NET_WM_STATE = XInternAtom(DISP, "_NET_WM_STATE", False);
1369 
1370 	/* 	XDVI_INFO((stdout, "trying _NET_WM_STATE_FULLSCREEN ...")); */
1371 
1372 	ev.type = ClientMessage;
1373 	ev.xclient.serial = 0;
1374 	ev.xclient.send_event = True;
1375 	ev.xclient.display = DISP;
1376 	ev.xclient.window = XtWindow(globals.widgets.top_level);
1377 	ev.xclient.message_type = NET_WM_STATE;
1378 	ev.xclient.format = 32;
1379 	ev.xclient.data.l[0] = flag; /* _NET_WM_STATE_REMOVE (0) or _NET_WM_STATE_ADD (1) */
1380 	ev.xclient.data.l[1] = NET_WM_FULLSCREEN;
1381 	ev.xclient.data.l[2] = 0L;
1382 
1383 	XSendEvent(DISP, DefaultRootWindow(DISP), False,
1384 		   SubstructureNotifyMask, &ev);
1385     }
1386     else {
1387 	XDVI_INFO((stdout, "_NET_WM_STATE_FULLSCREEN not supported by this window manager."));
1388     }
1389 }
1390 
1391 void
reconfigure_window(Boolean fullscreen,Dimension width,Dimension height,Boolean save_position)1392 reconfigure_window(Boolean fullscreen, Dimension width, Dimension height,
1393 		   Boolean save_position)
1394 {
1395     static int x_old = 5, y_old = 15;
1396 #ifdef SIZECONFIGURE_WORKS
1397     int sizeconfiguremask;
1398     XWindowChanges sizeconfigure;
1399 #endif /* SIZECONFIGURE_WORKS */
1400 #ifdef MOTIF
1401     static int save_wm_decorations;
1402 #else
1403     static struct PropMotifWmHints MWMHints = {MWM_HINTS_DECORATIONS, 0, 0, 0, 0};
1404     Atom WM_HINTS = XInternAtom(DISP, "_MOTIF_WM_HINTS", True);
1405 #endif
1406     int x, y;
1407 
1408 #ifdef SIZECONFIGURE_WORKS
1409     sizeconfiguremask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
1410     sizeconfigure.width = width;
1411     sizeconfigure.height = height;
1412 #endif /* SIZECONFIGURE_WORKS */
1413 
1414     if (fullscreen) {
1415 #if 0
1416 	static Boolean first_time = True;
1417 	/* offsets between the raw window and the decorated window */
1418 	static int wm_x_offset = 0;
1419 	static int wm_y_offset = 0;
1420 #endif
1421 	Window dummy;
1422 
1423 #ifdef SIZECONFIGURE_WORKS
1424 	sizeconfigure.x = 0;
1425 	sizeconfigure.y = 0;
1426 	sizeconfigure.border_width = 0;
1427 #endif /* SIZECONFIGURE_WORKS */
1428 
1429 	/* Note ZLB: avoid to call XTranslateCoordinates if the window is
1430 	   not yet mapped since XTranslateCoordinates implicitly maps the
1431 	   window (note: calling the function XGetWindowAttributes also
1432 	   makes the window mapped).
1433 
1434 	   This effectively eliminates the flashing effect when xdvik is
1435 	   started in fullscreen mode for the Motif version. For the Xaw
1436 	   version we still get flashing effect (seems that the window is
1437 	   already mapped). */
1438 
1439         if (save_position) {
1440 	    /* save current window coordinates so that we can change them back */
1441 	    (void)XTranslateCoordinates(DISP, XtWindow(globals.widgets.top_level),
1442 					RootWindowOfScreen(SCRN),
1443 					0, 0,
1444 					&x_old, &y_old,
1445 					&dummy);
1446 #if 0
1447             if (first_time) {
1448 		first_time = False;
1449 		/* This is a hack for finding out wm_x_offset, wm_y_offset */
1450 		XMoveWindow(DISP, XtWindow(globals.widgets.top_level), 0, 0);
1451 		XSync(DISP, False);
1452 		(void)XTranslateCoordinates(DISP, XtWindow(globals.widgets.top_level),
1453 					    RootWindowOfScreen(SCRN),
1454 					    0, 0, &wm_x_offset, &wm_y_offset,
1455 					    &dummy);
1456 		fprintf(stderr, "wm offset = (%d,%d)\n",
1457 			wm_x_offset, wm_y_offset);
1458 	    }
1459 	    x_old -= wm_x_offset;
1460 	    y_old -= wm_y_offset;
1461 #endif
1462         }
1463 
1464 	x = y = 0;
1465 
1466 #ifdef MOTIF
1467 	XtVaGetValues(globals.widgets.top_level, XmNmwmDecorations, &save_wm_decorations, NULL);
1468 	/* FIXME: this doesn't work e.g. with KDE */
1469 	XtVaSetValues(globals.widgets.top_level,
1470 		      XmNmwmDecorations, 0,
1471 		      XmNgeometry, "+0+0",
1472 		      NULL);
1473 	XtVaSetValues(globals.widgets.main_window, XmNshadowThickness, 0, NULL);
1474 #else
1475 	MWMHints.decorations = 0;
1476 	if (WM_HINTS != None) {
1477 	    XChangeProperty(DISP, XtWindow(globals.widgets.top_level),
1478 			    WM_HINTS, WM_HINTS, 32,
1479 			    PropModeReplace, (unsigned char *)&MWMHints,
1480 			    sizeof(MWMHints) / 4);
1481 	}
1482 #endif
1483 	/* SU: apparently some new standard that is supposed to work
1484 	   with some WMs ... but it doesn't with my versions of Gnome and KDE. */
1485 	net_wm_toggle_fullscreen(1);
1486 
1487 #ifdef SIZECONFIGURE_WORKS
1488 	XConfigureWindow(DISP, XtWindow(globals.widgets.top_level), sizeconfiguremask, &sizeconfigure);
1489 #endif /* SIZECONFIGURE_WORKS */
1490     }
1491     else {
1492 #ifdef SIZECONFIGURE_WORKS
1493 	sizeconfiguremask = CWWidth | CWHeight | CWX | CWY;
1494 	sizeconfigure.x = x_old;
1495 	sizeconfigure.y = y_old;
1496 	sizeconfigure.border_width = 20;
1497 #endif /* SIZECONFIGURE_WORKS */
1498 	XtVaSetValues(globals.widgets.top_level, XtNx, x_old, XtNy, y_old, NULL);
1499 #ifdef MOTIF
1500 	XtVaSetValues(globals.widgets.top_level, XmNmwmDecorations, save_wm_decorations, NULL);
1501 #if USE_XAW_PANNER
1502 	XtVaSetValues(globals.widgets.main_window, XmNshadowThickness, g_save_shadow_thickness, NULL);
1503 #endif
1504 #else
1505 	MWMHints.decorations = MWM_DECOR_ALL;
1506 	if (WM_HINTS != None) {
1507 	    XChangeProperty(DISP, XtWindow(globals.widgets.top_level),
1508 			    WM_HINTS, WM_HINTS, 32,
1509 			    PropModeReplace, (unsigned char *)&MWMHints,
1510 			    sizeof(MWMHints) / 4);
1511 	}
1512 #endif
1513 	net_wm_toggle_fullscreen(0);
1514 
1515 	x = x_old;
1516 	y = y_old;
1517     }
1518 
1519 #if 1
1520 #if 0
1521     XUnmapWindow(DISP, XtWindow(globals.widgets.top_level));
1522 #else
1523     XWithdrawWindow(DISP, XtWindow(globals.widgets.top_level), XScreenNumberOfScreen(SCRN));
1524 #endif
1525 
1526     /* Note ZLB: Placing XResizeWindow before XUnmapWindow or after XMapWindow
1527        makes the fullscreen window size smaller than the screen size when
1528        using `mwm' of Lesstif */
1529     XSetWindowBorderWidth(DISP, XtWindow(globals.widgets.top_level), 0);
1530     XResizeWindow(DISP, XtWindow(globals.widgets.top_level), width, height);
1531 
1532     XMapRaised(DISP, XtWindow(globals.widgets.top_level));
1533 
1534     /* Note ZLB: XMapWindow might change the window position with some WMs
1535        (like Sawfish), so we place the window position after it's mapped. */
1536     XMoveWindow(DISP, XtWindow(globals.widgets.top_level), x, y);
1537 #endif /* 0 */
1538 
1539     /* need to redraw the page to avoid artifacts */
1540     globals.ev.flags |= EV_NEWPAGE;
1541     XFlush(DISP);
1542 }
1543 
1544 
1545 /*
1546  * Parse colors from resource.{visited_}link_color, saving them
1547  * to g_{visited_}link_color and {visited_}link_pix.
1548  */
1549 static void
get_link_colors(Pixel * link_pix,Pixel * visited_link_pix)1550 get_link_colors(Pixel *link_pix, Pixel *visited_link_pix)
1551 {
1552     XrmValue from1, from2, to1, to2;
1553 
1554     XColor exact, approx;
1555     double r, g, b;
1556     double factor = 65535.0;
1557     int ret;
1558 
1559     /* get rgb values from color for links */
1560     if ((ret = XLookupColor(DISP, G_colormap,
1561 			    resource.link_color,
1562 			    &exact, &approx)) != 0) {
1563     }
1564     else {
1565 	XDVI_WARNING((stderr, "XLookupColor failed for resource.link_color \"%s\"\n"
1566 		      "- using fallback color \"%s\".",
1567 		      resource.visited_link_color, LINK_COLOR_FALLBACK));
1568 	XLookupColor(DISP, G_colormap, LINK_COLOR_FALLBACK, &exact, &approx);
1569     }
1570 
1571 #if 0
1572     fprintf(stderr, "lookup color for %s returned: %d, %d, %d\n",
1573 	    resource.link_color, exact.red, exact.green, exact.blue);
1574 #endif
1575     r = exact.red / factor;
1576     g = exact.green / factor;
1577     b = exact.blue / factor;
1578     g_link_color_rgb = xmalloc(strlen("push rgb 0.00 0.00 0.00") + 1);
1579     sprintf(g_link_color_rgb, "push rgb %.2f %.2f %.2f", r, g, b);
1580 
1581     /* same for visited links */
1582     if ((ret = XLookupColor(DISP, G_colormap,
1583 			    resource.visited_link_color,
1584 			    &exact, &approx)) != 0) {
1585     }
1586     else {
1587 	XDVI_WARNING((stderr, "XLookupColor failed for resource.visited_link_color \"%s\"\n"
1588 		      "- using fallback color \"%s\".",
1589 		      resource.visited_link_color, VISITED_LINK_COLOR_FALLBACK));
1590 	XLookupColor(DISP, G_colormap, VISITED_LINK_COLOR_FALLBACK, &exact, &approx);
1591     }
1592 
1593 #if 0
1594     fprintf(stderr, "lookup color for %s returned: %d, %d, %d\n",
1595 	    resource.visited_link_color, exact.red, exact.green, exact.blue);
1596 #endif
1597     r = exact.red / factor;
1598     g = exact.green / factor;
1599     b = exact.blue / factor;
1600     g_visited_link_color_rgb = xmalloc(strlen("push rgb 0.00 0.00 0.00") + 1);
1601     sprintf(g_visited_link_color_rgb, "push rgb %.2f %.2f %.2f", r, g, b);
1602 
1603     /* 2nd part: Create CG for the underlines. */
1604     from1.addr = resource.link_color;
1605     from1.size = strlen(from1.addr) + 1;
1606     to1.addr = (XtPointer)link_pix;
1607     to1.size = sizeof(Pixel);
1608     if (!XtConvertAndStore(globals.widgets.top_level, XtRString, &from1, XtRPixel, &to1)) {
1609 	XDVI_WARNING((stderr, "String to pixel conversion failed for resource.link_color \"%s\"\n"
1610 		      "- using fallback color \"%s\".",
1611 		      resource.link_color, LINK_COLOR_FALLBACK));
1612 	from1.addr = LINK_COLOR_FALLBACK;
1613 	from1.size = strlen(from1.addr) + 1;
1614 	to1.addr = (XtPointer)link_pix;
1615 	to1.size = sizeof(Pixel);
1616 	XtConvertAndStore(globals.widgets.top_level, XtRString, &from1, XtRPixel, &to1);
1617     }
1618     from2.addr = resource.visited_link_color;
1619     from2.size = strlen(from2.addr) + 1;
1620     to2.addr = (XtPointer)visited_link_pix;
1621     to2.size = sizeof(Pixel);
1622     if (!XtConvertAndStore(globals.widgets.top_level, XtRString, &from2, XtRPixel, &to2)) {
1623 	XDVI_WARNING((stderr, "String to pixel conversion failed for resource.visited_link_color \"%s\"\n"
1624 		      "- using fallback color \"%s\".",
1625 		      resource.visited_link_color, VISITED_LINK_COLOR_FALLBACK));
1626 	from2.addr = VISITED_LINK_COLOR_FALLBACK;
1627 	from2.size = strlen(from2.addr) + 1;
1628 	to2.addr = (XtPointer)visited_link_pix;
1629 	to2.size = sizeof(Pixel);
1630 	XtConvertAndStore(globals.widgets.top_level, XtRString, &from2, XtRPixel, &to2);
1631     }
1632 }
1633 
1634 /*  Widget globals.widgets.main_row, globals.widgets.menu_bar; */
1635 
1636 
1637 #ifdef MOTIF
1638 /* make sure the translations for the drawing area are properly set
1639    (Motif 2.x seems to somehow overwrite them somewhere in the
1640    initialization phase; bug #610206).
1641 */
1642 void
motif_translations_hack(void)1643 motif_translations_hack(void)
1644 {
1645     static XtTranslations xlats = NULL;
1646     const char *const translations = \
1647 	"<Key>osfPageUp:back-page()\n"
1648 	"<Key>osfPageDown:forward-page()\n"
1649 	"Ctrl<Key>osfBeginLine:goto-page(1)\n"
1650 	"Ctrl<Key>osfEndLine:goto-page()\n"
1651 	"<Key>osfBeginLine:home-or-top()\n"
1652 	"<Key>osfEndLine:end-or-bottom()\n"
1653 #if 0
1654 	/* AFAIK the following don't have any effect with Motif */
1655 #ifdef XK_KP_Left
1656 	"<Key>KP_Home:home()\n"
1657 	"<Key>KP_End:down()\n"
1658 	"<Key>KP_Prior:back-page()\n"
1659 	"<Key>KP_Next:forward-page()\n"
1660 #endif
1661 #endif
1662 	;
1663 
1664     if (xlats == NULL) {
1665 	xlats = XtParseTranslationTable(translations);
1666     }
1667 
1668     ASSERT(globals.widgets.clip_widget != NULL, "globals.widgets.clip_widget must have been initialized");
1669     ASSERT(globals.widgets.draw_widget != NULL, "globals.widgets.draw_widget must have been initialized");
1670     XtOverrideTranslations(globals.widgets.clip_widget, xlats);
1671 }
1672 #endif /* MOTIF */
1673 
1674 /* return an empty cursor. Lifted from unclutter.c */
1675 static Cursor
h_get_empty_cursor(Display * display,Window root)1676 h_get_empty_cursor(Display *display, Window root)
1677 {
1678     Pixmap cursormask;
1679     XGCValues xgc;
1680     GC gc;
1681     XColor dummycolour;
1682     Cursor cursor;
1683 
1684     cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
1685     xgc.function = GXclear;
1686     gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
1687     XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
1688     dummycolour.pixel = 0;
1689     dummycolour.red = 0;
1690     dummycolour.flags = 04;
1691     cursor = XCreatePixmapCursor(display,
1692 				 cursormask, cursormask,
1693 				 &dummycolour, &dummycolour,
1694 				 0, 0);
1695     XFreePixmap(display, cursormask);
1696     XFreeGC(display, gc);
1697     return cursor;
1698 }
1699 
1700 
1701 
1702 static void
create_cursors(void)1703 create_cursors(void)
1704 {
1705     XColor bg_Color;
1706     Pixmap temp;
1707     Pixmap mask;
1708 
1709     /* first try colors by name, as fix for #804294; fall back on
1710        WhitePixelOfScreen() etc. if this fails:
1711     */
1712     if (resource.cr_Pixel != (Pixel)ULONG_MAX) {
1713 	m_cursor_color.pixel = resource.cr_Pixel;
1714 	XQueryColor(DISP, G_colormap, &m_cursor_color);
1715     }
1716     else {
1717 	if (XParseColor(DISP, G_colormap, "black", &m_cursor_color) == 0) { /* lookup failure */
1718 	    m_cursor_color.pixel = BlackPixelOfScreen(SCRN);
1719 	    XQueryColor(DISP, G_colormap, &m_cursor_color);
1720 	}
1721     }
1722     if (XParseColor(DISP, G_colormap, "white", &bg_Color) == 0) { /* lookup failure */
1723 	bg_Color.pixel = WhitePixelOfScreen(SCRN);
1724 	XQueryColor(DISP, G_colormap, &bg_Color);
1725     }
1726 
1727     /* wait cursor */
1728     globals.cursor.wait = XCreateFontCursor(DISP, XC_watch);
1729 
1730     if (resource.mouse_mode1_cursor == -1) { /* Use default ready cursor (custom bitmap) */
1731 	temp = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
1732 				     (char *)magglass_bits,
1733 				     magglass_width, magglass_height);
1734 	mask = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
1735 				     (char *)magglass_mask_bits,
1736 				     magglass_mask_width, magglass_mask_height);
1737 
1738 	globals.cursor.mode1 = XCreatePixmapCursor(DISP, temp, mask,
1739 						   &m_cursor_color, &bg_Color,
1740 						   magglass_x_hot, magglass_y_hot);
1741 	XFreePixmap(DISP, temp);
1742 	XFreePixmap(DISP, mask);
1743     }
1744     else {
1745 	globals.cursor.mode1 = XCreateFontCursor(DISP, resource.mouse_mode1_cursor);
1746     }
1747 
1748     globals.cursor.corrupted = XCreateFontCursor(DISP, XC_watch);
1749 
1750     /* empty cursor */
1751     globals.cursor.empty = h_get_empty_cursor(DISP, RootWindowOfScreen(SCRN));
1752 
1753 #if !COLOR
1754     XRecolorCursor(DISP, globals.cursor.ready, &m_cursor_color, &bg_Color);
1755     XRecolorCursor(DISP, globals.cursor.wait, &m_cursor_color, &bg_Color);
1756 #endif
1757     /* Cursor when page is paused */
1758 #ifdef VMS
1759     temp = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
1760 				 (char *)hand_bits, hand_width, hand_height);
1761     mask = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
1762 				 (char *)hand_mask_bits, hand_mask_width, hand_mask_height);
1763     globals.cursor.pause = XCreatePixmapCursor(DISP, temp, mask,
1764 					       &m_cursor_color, &bg_Color, 6, 6);
1765     XFreePixmap(DISP, temp);
1766     XFreePixmap(DISP, mask);
1767 #else
1768     globals.cursor.pause = XCreateFontCursor(DISP, XC_watch);
1769 #endif
1770 
1771     /* cursors indicating dragging direction */
1772     globals.cursor.drag_v = XCreateFontCursor(DISP, XC_sb_v_double_arrow);
1773 
1774     globals.cursor.drag_h = XCreateFontCursor(DISP, XC_sb_h_double_arrow);
1775 
1776     globals.cursor.drag_a = XCreateFontCursor(DISP, XC_fleur);
1777 
1778 #ifdef VMS
1779     globals.cursor.link = globals.cursor.ready;
1780     globals.cursor.mode2 = globals.cursor.ready;
1781     globals.cursor.mode3 = globals.cursor.ready;
1782 #else
1783     globals.cursor.link = XCreateFontCursor(DISP, XC_hand2);
1784     globals.cursor.mode2 = XCreateFontCursor(DISP, resource.mouse_mode2_cursor);
1785     globals.cursor.mode3 = XCreateFontCursor(DISP, resource.mouse_mode3_cursor);
1786     /*  globals.cursor.text = XCreateFontCursor(DISP, XC_tcross); */
1787 #endif
1788 }
1789 
1790 /* Initialize a forward search if the source_position argument is not NULL. */
1791 static void
do_forward_search(const char * source_position)1792 do_forward_search(const char *source_position)
1793 {
1794     /* parse the special to expand the filename */
1795     struct src_parsed_special data;
1796     char *new_special = NULL;
1797     char *expanded_filename = NULL;
1798 
1799     if (source_position == NULL) /* nothing to do */
1800 	return;
1801 
1802     data.filename_len = 0;
1803     data.filename = NULL;
1804 
1805     src_parse(source_position, strlen(source_position), &data);
1806 
1807     if (data.filename_len == 0) { /* malformed argument: tell user, and ignore it */
1808 	popup_message(globals.widgets.top_level,
1809 		      MSG_ERR,
1810 		      /* helptext */
1811 		      "The format of the -sourceposition argument should be:\n"
1812 		      "-sourceposition '<nn>[ ]*<filename'\n"
1813 		      "with <nn> = linenumber, [ ]* = an arbitrary number of spaces, "
1814 		      "and <filename> = TeX source file.",
1815 		      /* error message */
1816 		      "Filename missing in `-sourceposition' argument \"%s\". "
1817 		      "Could not perform forward search.",
1818 		      source_position);
1819     }
1820     else {
1821 	TRACE_CLIENT((stderr, "got data: line %d, col %d, file |%s|, len %lu\n",
1822 		      data.line, data.col, data.filename, (unsigned long)data.filename_len));
1823 
1824 	/* expand -sourceposition argument if it contains a path component, like above */
1825 	if (strchr(data.filename, '/') != NULL
1826 	    && (expanded_filename = expand_filename(data.filename, USE_CWD_PATH)) != NULL) {
1827 	    char *tmp = canonicalize_path(expanded_filename);
1828 	    free(data.filename);
1829 	    free(expanded_filename);
1830 	    expanded_filename = tmp;
1831 	}
1832 	else
1833 	    expanded_filename = data.filename;
1834 
1835 	TRACE_CLIENT((stderr, "expanded source_position: |%s|\n", expanded_filename));
1836 
1837 	new_special = xmalloc(2 * LENGTH_OF_INT + 2 /* 2 for `:' and separating space */
1838 			      + strlen(expanded_filename) + 1);
1839 	sprintf(new_special, "%d:%d %s", data.line, data.col, expanded_filename);
1840 	free(expanded_filename);
1841 	globals.src.fwd_string = new_special;
1842 	globals.ev.flags |= EV_SRC;
1843     }
1844 }
1845 
1846 
1847 /*
1848  *	Routines for compile_mouse_actions
1849  */
1850 
1851 struct modifierinf {
1852     int		len;
1853     const char	*name;
1854     Modifiers	mask;
1855     KeySym	keysym;
1856 };
1857 
1858 /* Allowed modifiers, sorted by length and then lexicographically.  */
1859 
1860 static	struct modifierinf	modifiers[] = {
1861     {1,		"a",		0,		XK_Alt_L},
1862     {1,		"c",		ControlMask,	0},
1863     {1,		"h",		0,		XK_Hyper_L},
1864     {1,		"l",		LockMask,	0},
1865     {1,		"m",		0,		XK_Meta_L},
1866     {1,		"s",		ShiftMask,	0},
1867     {2,		"su",		0,		XK_Super_L},
1868     {3,		"Alt",		0,		XK_Alt_L},
1869     {4,		"Ctrl",		ControlMask,	0},
1870     {4,		"Lock",		LockMask,	0},
1871     {4,		"Meta",		0,		XK_Meta_L},
1872     {4,		"Mod1",		Mod1Mask,	0},
1873     {4,		"Mod2",		Mod2Mask,	0},
1874     {4,		"Mod3",		Mod3Mask,	0},
1875     {4,		"Mod4",		Mod4Mask,	0},
1876     {4,		"Mod5",		Mod5Mask,	0},
1877     {5,		"Hyper",	0,		XK_Hyper_L},
1878     {5,		"Shift",	ShiftMask,	0},
1879     {5,		"Super",	0,		XK_Super_L},
1880     {7,		"Button1",	Button1Mask,	0},
1881     {7,		"Button2",	Button2Mask,	0},
1882     {7,		"Button3",	Button3Mask,	0},
1883     {7,		"Button4",	Button4Mask,	0},
1884     {7,		"Button5",	Button5Mask,	0},
1885 };
1886 
1887 #define	MODSCTRLINDEX	1	/* index of "c" in the above array */
1888 #define	MODSMETAINDEX	4	/* index of "m" */
1889 
1890 
1891 static Boolean
compile_modifiers(const char ** pp,struct mouse_acts * mactp)1892 compile_modifiers(const char **pp, struct mouse_acts *mactp)
1893 {
1894     const char		*p = *pp;
1895     const char		*p1;
1896     Boolean			exclusive = False;
1897     LateBindingsPtr		latep = NULL;
1898     int			nlate;
1899 
1900     while (*p == ' ' || *p == '\t')
1901 	++p;
1902 
1903     p1 = p;
1904     while (isalpha((int) *p1))
1905 	++p1;
1906 
1907     if (p1 - p == 3 && memcmp(p, "Any", 3) == 0) {
1908 	mactp->mask = mactp->value = 0;
1909 	p = p1;
1910 	while (*p == ' ' || *p == '\t')
1911 	    ++p;
1912 	if (*p != '<')
1913 	    return False;
1914     }
1915     else if (p1 - p == 4 && memcmp(p, "None", 4) == 0) {
1916 	mactp->mask = ~0;
1917 	mactp->value = 0;
1918 	p = p1;
1919 	while (*p == ' ' || *p == '\t')
1920 	    ++p;
1921 	if (*p != '<')
1922 	    return False;
1923     }
1924     else {
1925 	if (*p == '!') {
1926 	    exclusive = True;
1927 	    do {
1928 		++p;
1929 	    } while (*p == ' ' || *p == '\t');
1930 	}
1931 
1932 	for (;;) {
1933 	    Boolean negated = False;
1934 	    struct modifierinf *mp;
1935 
1936 	    if (*p == '<')
1937 		break;
1938 
1939 	    if (*p == '~') {
1940 		negated = True;
1941 		++p;
1942 	    }
1943 
1944 	    if (*p == '^') {
1945 		mp = &modifiers[MODSCTRLINDEX];
1946 		++p;
1947 	    }
1948 	    else if (*p == '$') {
1949 		mp = &modifiers[MODSMETAINDEX];
1950 		++p;
1951 	    }
1952 	    else {
1953 		int min, max;
1954 
1955 		p1 = p;
1956 		while (isalnum((int) *p))
1957 		    ++p;
1958 
1959 		/* do binary search */
1960 		min = -1;
1961 		max = XtNumber(modifiers);
1962 		for (;;) {
1963 		    int i, diff;
1964 
1965 		    i = (min + max) / 2;
1966 		    if (i == min)
1967 			return False;	/* if not found */
1968 		    mp = &modifiers[i];
1969 
1970 		    diff = (p - p1) - mp->len;
1971 		    if (diff == 0)
1972 			diff = memcmp(p1, mp->name, p - p1);
1973 
1974 		    if (diff == 0)
1975 			break;
1976 		    if (diff > 0) min = i;
1977 		    else max = i;
1978 		}
1979 	    }
1980 	    if (mp->mask) {
1981 		mactp->mask |= mp->mask;
1982 		if (!negated) mactp->value |= mp->mask;
1983 	    }
1984 	    else {
1985 		LateBindingsPtr lp1;
1986 
1987 		if (latep == NULL) {
1988 		    nlate = 3;
1989 		    latep = xmalloc(3 * sizeof(LateBindings));
1990 		    latep->ref_count = 1;
1991 		}
1992 		else {
1993 		    nlate += 2;
1994 		    latep = xrealloc(latep, nlate * sizeof(LateBindings));
1995 		}
1996 		lp1 = &latep[nlate - 3];
1997 		lp1->knot = lp1[1].knot = negated;
1998 		lp1->pair = True;
1999 		lp1->keysym = mp->keysym;
2000 		++lp1;
2001 		lp1->pair = False;
2002 		lp1->ref_count = 0;
2003 		lp1->keysym = mp->keysym + 1;
2004 		++lp1;
2005 		lp1->knot = lp1->pair = False;
2006 		lp1->ref_count = 0;
2007 		lp1->keysym = 0;
2008 	    }
2009 
2010 	    while (*p == ' ' || *p == '\t')
2011 		++p;
2012 	}
2013     }
2014 
2015     mactp->late_bindings = latep;
2016     *pp = p;
2017 
2018     return True;
2019 }
2020 
2021 static Boolean
compile_evtype(const char ** pp,unsigned int * buttonp)2022 compile_evtype(const char **pp, unsigned int *buttonp)
2023 {
2024     const char		*p = *pp;
2025     const char		*p0;
2026 
2027     ++p;	/* already assumed to be '<' */
2028     while (*p == ' ' || *p == '\t')
2029 	++p;
2030 
2031     p0 = p;
2032     while (isalpha((int) *p) && p - p0 < 3)
2033 	++p;
2034 
2035     if (p - p0 != 3 || memcmp(p0, "Btn", 3) != 0)
2036 	return False;
2037 
2038     if (*p >= '1' && *p <= '9') {
2039 	unsigned int n = *p - '0';
2040 
2041 	while (*++p >= '0' && *p <= '9')
2042 	    n = n * 10 + (*p - '0');
2043 
2044 	*buttonp = n;
2045     }
2046 
2047     p0 = p;
2048     while (isalpha((int) *p))
2049 	++p;
2050 
2051     if (p - p0 != 4 || memcmp(p0, "Down", 4) != 0)
2052 	return False;
2053 
2054     while (*p == ' ' || *p == '\t')
2055 	++p;
2056 
2057     if (*p++ != '>')
2058 	return False;
2059 
2060     while (*p == ' ' || *p == '\t')
2061 	++p;
2062 
2063     if (*p++ != ':')
2064 	return False;
2065 
2066     *pp = p;
2067 
2068     return True;
2069 }
2070 
2071 static void
compile_mouse_actions(void)2072 compile_mouse_actions(void)
2073 {
2074     struct mouse_acts	**mactpp;
2075     struct mouse_acts	*mactp;
2076     const char		*p = resource.mouse_translations;
2077     const char		*p_end;
2078     const char		*p_base = base_mouse_translations;
2079     struct mouse_acts	mact;
2080 
2081     mactpp = &mouse_actions;
2082 
2083     if (p == NULL) {
2084 	p = p_base;
2085 	p_base = NULL;
2086     }
2087 
2088     do {	/* loop over translations strings */
2089 	p_end = p + strlen(p);
2090 	for (;;) {
2091 	    while (*p == ' ' || *p == '\t')
2092 		++p;
2093 
2094 	    if (*p == '\n') continue;
2095 	    if (*p == '\0') break;
2096 
2097 	    mact.mask = mact.value = 0;
2098 	    mact.button = 0;
2099 
2100 	    if (!compile_modifiers(&p, &mact)
2101 	      || !compile_evtype(&p, &mact.button)) {
2102 		XDVI_WARNING((stderr, "syntax error in wheel translations"));
2103 	    }
2104 	    else if (compile_action(p, &mact.action) || mact.action != NULL) {
2105 		mactp = xmalloc(sizeof(struct mouse_acts));
2106 		*mactp = mact;
2107 
2108 		*mactpp = mactp;
2109 		mactpp = &mactp->next;
2110 	    }
2111 
2112 	    p = memchr(p, '\n', p_end - p);
2113 	    if (p == NULL) break;
2114 	    ++p;
2115 	}
2116 
2117 	p = p_base;
2118 	p_base = NULL;
2119     }
2120     while (p != NULL);
2121 
2122     *mactpp = NULL;
2123 }
2124 
2125 
2126 #if HAVE_XI21
2127 
2128 void
xi2_init_valuators(struct xi2_slave * sp,XIAnyClassInfo ** classes,int num_classes)2129 xi2_init_valuators(struct xi2_slave *sp, XIAnyClassInfo **classes,
2130 	int num_classes)
2131 {
2132 	unsigned int	flags;
2133 	int		i;
2134 
2135 	sp->flags = flags = 0;
2136 	sp->btn_mask = 0;
2137 	sp->vert.number = sp->horiz.number = -1;
2138 
2139 	for (i = 0; i < num_classes; ++i)
2140 	    if (classes[i]->type == XIScrollClass) {
2141 		XIScrollClassInfo *scroll = (XIScrollClassInfo *) classes[i];
2142 
2143 		if (scroll->scroll_type == XIScrollTypeVertical) {
2144 		    sp->vert.number = scroll->number;
2145 		    sp->vert.increment = scroll->increment;
2146 		    flags |= XI2_SLAVE_VERT;
2147 		}
2148 		else if (scroll->scroll_type == XIScrollTypeHorizontal) {
2149 		    sp->horiz.number = scroll->number;
2150 		    sp->horiz.increment = scroll->increment;
2151 		    flags |= XI2_SLAVE_HORIZ;
2152 		}
2153 	    }
2154 
2155 	if (flags == 0) {
2156 	    TRACE_EVENTS((stderr,
2157 		"No scroll valuators found for slave device %d", sp->id));
2158 	    return;
2159 	}
2160 
2161 	TRACE_EVENTS((stderr,
2162 	    "Found XI2 device %d with one or more scroll valuators:", sp->id));
2163 	if (flags & XI2_SLAVE_VERT)
2164 	    TRACE_EVENTS((stderr, "  Vertical valuator %d has increment %.2f",
2165 	      sp->vert.number, sp->vert.increment));
2166 	if (flags & XI2_SLAVE_HORIZ)
2167 	    TRACE_EVENTS((stderr, "  Horizontal valuator %d has increment %.2f",
2168 	      sp->horiz.number, sp->horiz.increment));
2169 
2170 	for (i = 0; i < num_classes; ++i)
2171 	    if (classes[i]->type == XIValuatorClass) {
2172 		XIValuatorClassInfo *valuator;
2173 		valuator = (XIValuatorClassInfo *) classes[i];
2174 
2175 		/* The min and max fields have been seen to be 0 and -1, */
2176 		/* respectively (what do those mean)? */
2177 		if (flags & XI2_SLAVE_VERT
2178 		  && valuator->number == sp->vert.number) {
2179 		    sp->vert.lastval = valuator->value;
2180 		    sp->vert.lastexact = valuator->value;
2181 		    sp->vert.factor = 0;
2182 		    sp->vert.serial = LastKnownRequestProcessed(DISP);
2183 		    sp->flags |= XI2_SLAVE_VERT;
2184 		    sp->btn_mask |= (1<<4) | (1<<5);
2185 		}
2186 		else if (flags & XI2_SLAVE_HORIZ
2187 		  && valuator->number == sp->horiz.number) {
2188 		    sp->horiz.lastval = valuator->value;
2189 		    sp->horiz.lastexact = valuator->value;
2190 		    sp->horiz.factor = 0;
2191 		    sp->horiz.serial = LastKnownRequestProcessed(DISP);
2192 		    sp->flags |= XI2_SLAVE_HORIZ;
2193 		    sp->btn_mask |= (1<<6) | (1<<7);
2194 		}
2195 	    }
2196 
2197 	if (sp->flags != flags)
2198 	    TRACE_EVENTS((stderr,
2199 	      "For slave device %d, valuator class(es) missing (%x vs. %x)",
2200 	      sp->id, sp->flags, flags));
2201 }
2202 
2203 void
xi2_activate(void)2204 xi2_activate(void)
2205 {
2206 	XIEventMask eventmask;
2207 	unsigned char mask[2] = {0, 0};	/* the actual event mask */
2208 	struct xi2_master *mp;
2209 
2210 	mask[0] = mask[1] = 0;
2211 	eventmask.mask = mask;
2212 	eventmask.mask_len = sizeof mask;
2213 	XISetMask(mask, XI_Motion);
2214 	XISetMask(mask, XI_Enter);
2215 
2216 	for (mp = xi2_masters; mp != NULL; mp = mp->next) {
2217 	    eventmask.deviceid = mp->id;
2218 	    XISelectEvents(DISP, XtWindow(globals.widgets.draw_widget),
2219 	      &eventmask, 1);
2220 # if MOTIF
2221 	    XISelectEvents(DISP, XtWindow(globals.widgets.clip_widget),
2222 	      &eventmask, 1);
2223 # endif
2224 	}
2225 
2226 	xi2_active = True;
2227 	xi2_current = xi2_masters;	/* this is just an optimization */
2228 }
2229 
2230 static void
xi2_init(void)2231 xi2_init(void)
2232 {
2233 	int	event, error;
2234 	int	major, minor;
2235 	XIEventMask eventmask;
2236 	unsigned char mask[2] = {0, 0};	/* the actual event mask */
2237 	XIDeviceInfo *info;
2238 	int	ndevices;
2239 	struct xi2_master **mpp;
2240 	struct xi2_master *mp;
2241 	struct xi2_slave **spp;
2242 	struct xi2_slave *sp;
2243 	unsigned int all_flags;
2244 	int	i;
2245 
2246 	/* Check for user turning it off */
2247 
2248 	if (!resource.xi2scrolling) {
2249 	    TRACE_EVENTS((stderr,
2250 	      "X Input extension turned off at user request."));
2251 	    return;
2252 	}
2253 
2254 	/* Check for extension */
2255 
2256 	if (!XQueryExtension(DISP, "XInputExtension", &xi2_opcode, &event,
2257 	  &error)) {
2258 	    TRACE_EVENTS((stderr, "X Input extension not available."));
2259 	    return;
2260 	}
2261 
2262 	/* Check XI2 version number */
2263 	major = 2;
2264 	minor = 1;
2265 	if (XIQueryVersion(DISP, &major, &minor) == BadRequest) {
2266 	    TRACE_EVENTS((stderr, "XI2 not available."));
2267 	    return;
2268 	}
2269 	if (major == 2 && minor < 1) {
2270 	    TRACE_EVENTS((stderr, "XI2 version 2.1 is not supported."));
2271 	    return;
2272 	}
2273 
2274 	TRACE_EVENTS((stderr, "Found XI2 extension version %d.%d.",
2275 	  major, minor));
2276 
2277 	XISetMask(mask, XI_HierarchyChanged);
2278 	XISetMask(mask, XI_DeviceChanged);
2279 	eventmask.deviceid = XIAllDevices;
2280 	eventmask.mask_len = sizeof(mask);
2281 	eventmask.mask = mask;
2282 
2283 	XISelectEvents(DISP, DefaultRootWindow(DISP), &eventmask, 1);
2284 
2285 	info = XIQueryDevice(DISP, XIAllDevices, &ndevices);
2286 
2287 # if XIAllDevices != 0
2288 	xi2_no_slave.id = XIAllDevices;
2289 # endif
2290 
2291 	/* Find slave devices */
2292 
2293 	all_flags = 0;
2294 	spp = &xi2_slaves;	/* link for next slave device */
2295 
2296 	for (i = 0; i < ndevices; ++i)
2297 	    if (info[i].use == XISlavePointer || info[i].use == XIFloatingSlave)
2298 	    {
2299 		sp = xmalloc(sizeof (struct xi2_slave));
2300 		sp->id = info[i].deviceid;
2301 		sp->enabled = info[i].enabled;
2302 		xi2_init_valuators(sp, info[i].classes, info[i].num_classes);
2303 		all_flags |= sp->flags;
2304 		*spp = sp;
2305 		spp = &sp->next;
2306 	    }
2307 	*spp = NULL;
2308 
2309 	/* Find master devices */
2310 
2311 	mpp = &xi2_masters;	/* link for next master device */
2312 
2313 	for (i = 0; i < ndevices; ++i)
2314 	    if (info[i].use == XIMasterPointer
2315 	      || info[i].use == XIMasterKeyboard) {
2316 		mp = xmalloc(sizeof (struct xi2_master));
2317 		mp->id = info[i].deviceid;
2318 		mp->slave = &xi2_no_slave;
2319 		*mpp = mp;
2320 		mpp = &mp->next;
2321 	    }
2322 	*mpp = NULL;
2323 
2324 	XIFreeDeviceInfo(info);
2325 
2326 	if (xi2_masters == NULL) {
2327 	    TRACE_EVENTS((stderr,
2328 	      "No master pointers found (!!); not using XI2."));
2329 	    return;
2330 	}
2331 
2332 	if (!all_flags) {
2333 	    TRACE_EVENTS((stderr,
2334 	      "No scroll valuators found; not using XI2 (for now)."));
2335 	    return;
2336 	}
2337 
2338 	xi2_activate();
2339 }
2340 
2341 #endif /* HAVE_XI21 */
2342 
2343 
2344 static void
create_colormaps(void)2345 create_colormaps(void)
2346 {
2347 #ifdef GREY
2348     G_depth = (unsigned int)DefaultDepthOfScreen(SCRN);
2349     G_visual = DefaultVisualOfScreen(SCRN);
2350     G_colormap = DefaultColormapOfScreen(SCRN);
2351 #ifdef XSERVER_INFO
2352     if (globals.debug & DBG_ALL)
2353 	fprintf(stdout, "--- G_depth: %d\n", G_depth);
2354 #endif
2355 
2356     if (resource.install != False && G_visual->class == PseudoColor) {
2357 	/* look for a TrueColor visual with more bits */
2358 	XVisualInfo template;
2359 	XVisualInfo *list;
2360 	int nitems_return;
2361 #ifdef XSERVER_INFO
2362 	if (globals.debug & DBG_ALL)
2363 	    fprintf(stdout, "--- looking for a better TrueColor visual\n");
2364 #endif
2365 
2366 	template.screen = XScreenNumberOfScreen(SCRN);
2367 	template.class = TrueColor;
2368 	list = XGetVisualInfo(DISP, VisualScreenMask | VisualClassMask,
2369 			      &template, &nitems_return);
2370 	if (list != NULL) {
2371 	    XVisualInfo *list1;
2372 	    XVisualInfo *best = NULL;
2373 
2374 	    for (list1 = list; list1 < list + nitems_return; ++list1) {
2375 #ifdef XSERVER_INFO
2376 		if (globals.debug & DBG_ALL)
2377 		    fprintf(stdout, "--- checking %d\n", list1->depth);
2378 #endif
2379 		if ((unsigned int)list1->depth > G_depth
2380 # if PS_GS
2381 		    /* patch by Toni Ronkko <tronkko@hytti.uku.fi>, fixes bug #458057:
2382 		     * SGI supports additional depths of 12 and 30, but
2383 		     * these are not supported by ghostscript (see
2384 		     * xdev->vinfo->depth in gdevxcmp.c (ghostscript-6.51)),
2385 		     * so we restrict the values to those supported by gs.
2386 		     */
2387 		    && (list1->depth == 1 || list1->depth == 2
2388 			|| list1->depth == 4 || list1->depth == 8
2389 			|| list1->depth == 15 || list1->depth == 16
2390 			|| list1->depth == 24 || list1->depth == 32)
2391 # endif
2392 		    && (best == NULL || list1->depth > best->depth))
2393 		    best = list1;
2394 	    }
2395 	    if (best != NULL) {
2396 #ifdef XSERVER_INFO
2397 		if (globals.debug & DBG_ALL)
2398 		    fprintf(stdout, "--- best depth: %d\n", best->depth);
2399 #endif
2400 		G_depth = best->depth;
2401 		G_visual = best->visual;
2402 		G_colormap = XCreateColormap(DISP,
2403 					     RootWindowOfScreen(SCRN),
2404 					     G_visual, AllocNone);
2405 		XInstallColormap(DISP, G_colormap);
2406 		temp_args1[0].value = (XtArgVal) G_depth;
2407 		temp_args1[1].value = (XtArgVal) G_visual;
2408 		temp_args1[2].value = (XtArgVal) G_colormap;
2409 		XtSetValues(globals.widgets.top_level, temp_args1, XtNumber(temp_args1));
2410 		XtSetTypeConverter(XtRString, XtRPixel,
2411 				   XdviCvtStringToPixel,
2412 				   (XtConvertArgList) colorConvertArgs, 2,
2413 				   XtCacheByDisplay, NULL);
2414 		{
2415 		    /* This is needed so that popup windows have the right
2416 		       visual and colormap.  It is unnecessary for newer
2417 		       versions of Motif (Motif 2.1.0, Solaris 9) but
2418 		       needed for older versions (Motif 1.2.5, Solaris 2.6),
2419 		       and for Xaw.
2420 		    */
2421 		    XrmDatabase	db = XtScreenDatabase(SCRN);
2422 		    XrmValue	val;
2423 
2424 		    val.size = sizeof G_visual;
2425 		    val.addr = (XtPointer) &G_visual;
2426 		    XrmPutResource(&db, "XDvi*visual", XtRVisual, &val);
2427 
2428 		    val.size = sizeof G_colormap;
2429 		    val.addr = (XtPointer) &G_colormap;
2430 		    XrmPutResource(&db, "XDvi*colormap", XtRColormap, &val);
2431 		}
2432 	    }
2433 	    XFree(list);
2434 	}
2435     }
2436 
2437 #ifdef MOTIF
2438     if (globals.debug & DBG_GUI) {
2439 	printf("Compiled with %s, runtime version %d.%d\n",
2440 	       /* 	   XmVERSION, XmREVISION, XmUPDATE_LEVEL, */
2441 	       XmVERSION_STRING,
2442 	       xmUseVersion / 1000, xmUseVersion % 1000);
2443     }
2444 #endif
2445 
2446     if (resource.install == True && G_visual->class == PseudoColor) {
2447 	XColor tmp_color;
2448 #ifdef XSERVER_INFO
2449 	if (globals.debug & DBG_ALL)
2450 	    fprintf(stdout, "--- PseudoColor, trying to install colormap\n");
2451 #endif
2452 
2453 	/* This next bit makes sure that the standard black and white pixels
2454 	   are allocated in the new colormap. */
2455 	tmp_color.pixel = BlackPixelOfScreen(SCRN);
2456 	XQueryColor(DISP, G_colormap, &tmp_color);
2457 	XAllocColor(DISP, G_colormap, &tmp_color);
2458 
2459 	tmp_color.pixel = WhitePixelOfScreen(SCRN);
2460 	XQueryColor(DISP, G_colormap, &tmp_color);
2461 	XAllocColor(DISP, G_colormap, &tmp_color);
2462 
2463 	G_colormap = XCopyColormapAndFree(DISP, G_colormap);
2464 	temp_args1[2].value = (XtArgVal) G_colormap;
2465 	XtSetValues(globals.widgets.top_level, temp_args1 + 2, 1);
2466     }
2467 
2468     XtGetApplicationResources(globals.widgets.top_level, (XtPointer)&resource,
2469 			      app_pixel_resources, XtNumber(app_pixel_resources),
2470 			      (ArgList)NULL, 0);
2471 
2472 #endif /* GREY */
2473 
2474     globals.gc.do_copy = resource.copy;
2475 
2476 #if GREY || COLOR
2477     color_data[0].pixel = resource.fore_Pixel;
2478     color_data[1].pixel = resource.back_Pixel;
2479     XQueryColors(DISP, G_colormap, color_data, 2);
2480 #endif
2481 
2482 #if COLOR
2483     fg_initial.r = color_data[0].red;
2484     fg_initial.g = color_data[0].green;
2485     fg_initial.b = color_data[0].blue;
2486     bg_initial.r = color_data[1].red;
2487     bg_initial.g = color_data[1].green;
2488     bg_initial.b = color_data[1].blue;
2489 
2490 #endif
2491 
2492 #if GREY
2493     if (G_depth == 1) {
2494 #ifdef XSERVER_INFO
2495 	if (globals.debug & DBG_ALL)
2496 	    fprintf(stdout, "--- using depth 1\n");
2497 #endif
2498 	resource.use_grey = False;
2499     }
2500     if (resource.use_grey && G_visual->class != TrueColor) {
2501 #ifdef XSERVER_INFO
2502 	if (globals.debug & DBG_ALL)
2503 	    fprintf(stdout, "--- using grey, but not TrueColor\n");
2504 #endif
2505 	init_plane_masks();
2506 	if (!globals.gc.do_copy) {
2507 	    /* Retain color_data[1].pixel for psgs.c.  */
2508 	    XColor tmp_color;
2509 #ifdef XSERVER_INFO
2510 	    if (globals.debug & DBG_ALL)
2511 		fprintf(stdout, "--- not using copy\n");
2512 #endif
2513 
2514 	    tmp_color = color_data[1];
2515 	    tmp_color.pixel = resource.back_Pixel;
2516 	    XStoreColor(DISP, G_colormap, &tmp_color);
2517 	}
2518     }
2519 #endif
2520 }
2521 
2522 static void
create_widgets(Widget tool_bar,Widget form,int * add_w,int * add_h)2523 create_widgets(
2524 #ifdef MOTIF
2525 	       Widget tool_bar, Widget form,
2526 #endif
2527 	       int *add_w, int *add_h)
2528 {
2529 
2530 #ifdef MOTIF
2531     Widget status_line;
2532 
2533 #if 0
2534     {
2535 	int i, n, longest_page = 0;
2536 	Dimension width, height;
2537 	char tmpbuf[1024];
2538 	char *fontname;
2539 	XmString tmpstring;
2540 	Widget dummy_list;
2541 	XmRendition rendition;
2542 	XmRenderTable rtable;
2543 	Arg args[10];
2544 	/*
2545 	 * Try to determine width of longest page string:
2546 	 */
2547 	for (i = 0; i < total_pages; i++) {
2548 	    int curr = abs(pageinfo_get_number(i));
2549 	    if (curr > longest_page)
2550 		longest_page = curr;
2551 	}
2552 	fprintf(stderr, "longest page number: %d\n", longest_page);
2553 	sprintf(tmpbuf, "* %d", longest_page);
2554 	tmpstring = XmStringCreateLocalized(tmpbuf);
2555 	dummy_list = XtCreateWidget("PageList", xmListWidgetClass, form, NULL, 0);
2556 	fprintf(stderr, "rendition table\n");
2557 	n = 0;
2558 	/*     XtVaGetValues(globals.widgets.top_level, XmNfontList, &fontname, NULL); */
2559 	/*     fprintf(stderr, "fontname: |%s|\n", fontname); */
2560 	XtSetArg(args[n], XmNfontName, "8x16"); n++;
2561 	XtSetArg(args[n], XmNfontType, XmFONT_IS_FONT); n++;
2562 	rendition = XmRenditionCreate(dummy_list, XmFONTLIST_DEFAULT_TAG, args, n);
2563 	rtable = XmRenderTableAddRenditions(NULL, &rendition, 1, XmMERGE_REPLACE);
2564 	XtVaSetValues(dummy_list, XmNrenderTable, rtable, NULL);
2565 
2566 	/* 	rendition = XmRenditionCreate(globals.widgets.top_level, XmFONTLIST_DEFAULT_TAG, NULL, 0); */
2567 	fprintf(stderr, "extent\n");
2568 	XmStringExtent(rtable, tmpstring, &width, &height);
2569 	fprintf(stderr, "string %s has width %d, height %d\n", tmpbuf, width, height);
2570 	XtDestroyWidget(dummy_list);
2571 	XmRenditionFree(rendition);
2572 	XmStringFree(tmpstring);
2573     }
2574 #endif
2575     {
2576 #define ARG_LEN 20
2577 	int n = 0;
2578 	Arg list_args[ARG_LEN];
2579 
2580 	XtSetArg(list_args[n], XmNlistSizePolicy, XmVARIABLE);			n++;
2581 	XtSetArg(list_args[n], XmNwidth, resource.pagelist_width);		n++;
2582 #if defined(USE_PANNER) && USE_XAW_PANNER
2583 	XtSetArg(list_args[n], XmNheight, globals.page.h - 62);			n++;
2584 #else
2585 	XtSetArg(list_args[n], XmNheight, globals.page.h);			n++;
2586 #endif
2587 	/* 	XtSetArg(list_args[n], XmNspacing, 10);					n++; */
2588 #if defined(USE_PANNER) && USE_XAW_PANNER
2589 	XtSetArg(list_args[n], XmNtopAttachment, XmATTACH_WIDGET);		n++;
2590 	XtSetArg(list_args[n], XmNtopWidget, panner);				n++;
2591 #else
2592 	XtSetArg(list_args[n], XmNtopAttachment, XmATTACH_FORM);		n++;
2593 #endif
2594 	XtSetArg(list_args[n], XmNbottomAttachment, XmATTACH_FORM);		n++;
2595 	XtSetArg(list_args[n], XmNleftAttachment, XmATTACH_FORM);		n++;
2596 	XtSetArg(list_args[n], XmNrightAttachment, XmATTACH_OPPOSITE_FORM);	n++;
2597 	XtSetArg(list_args[n], XmNrightOffset, -resource.pagelist_width);	n++;
2598 	XtSetArg(list_args[n], XmNresizable, True);				n++;
2599 	XtSetArg(list_args[n], XmNtopOffset, 2);				n++;
2600 	XtSetArg(list_args[n], XmNleftOffset, 2);				n++;
2601 	ASSERT(n < ARG_LEN, "list_args too short");
2602 #undef ARG_LEN
2603 	/* TODO: Find a smart way to determine size of pagelist instead of using resource.pagelist_width,
2604 	   and find a smart way of resizing it when switching to a file with larger page numbers!
2605 	*/
2606 	page_list = XmCreateScrolledList(form, "PageList", list_args, n);
2607     }
2608 
2609     if (resource.expert_mode == XPRT_SHOW_NONE) {
2610 	XtUnmanageChild(XtParent(page_list));
2611 	XtUnmanageChild(page_list);
2612     }
2613 
2614     globals.widgets.main_window = XtVaCreateManagedWidget("mainWindow",
2615 							  xmScrolledWindowWidgetClass, form,
2616 							  XmNscrollingPolicy, XmAUTOMATIC,
2617 							  XmNleftAttachment, XmATTACH_WIDGET,
2618 							  /* lesstif balks if we just use page_list, so use its parent,
2619 							     the xmScrolledWindow, for alignment: */
2620 							  XmNleftWidget, XtParent(page_list),
2621 							  XmNallowResize, True,
2622 							  /* 					  XmNtopOffset, 2, */
2623 							  XmNtopAttachment, XmATTACH_FORM,
2624 							  XmNbottomAttachment, XmATTACH_FORM,
2625 							  XmNrightAttachment, XmATTACH_FORM,
2626 							  /* 					      XmNleftOffset, 10, */
2627 							  XmNresizable, True,
2628 							  XmNborderWidth, 0,
2629 							  NULL);
2630     XtManageChild(form);
2631 
2632     globals.widgets.x_bar = XtNameToWidget(globals.widgets.main_window, "HorScrollBar");
2633     globals.widgets.y_bar = XtNameToWidget(globals.widgets.main_window, "VertScrollBar");
2634 
2635 
2636 #ifdef TEST_SCROLLING
2637     /* TODO: try the following to prevent `flashing' effect - still breaks
2638        scrolling in its current form though */
2639     globals.widgets.draw_background = XtVaCreateManagedWidget("drawing_bg",
2640 							      xmFormWidgetClass, globals.widgets.main_window,
2641 							      XmNwidth, globals.page.w,
2642 							      XmNheight, globals.page.h,
2643 							      XmNtopAttachment, XmATTACH_FORM,
2644 							      XmNbottomAttachment, XmATTACH_FORM,
2645 							      XmNrightAttachment, XmATTACH_FORM,
2646 							      XmNleftAttachment, XmATTACH_FORM,
2647 							      XmNhighlightThickness, 0,
2648 							      XmNbackground, resource.back_Pixel,
2649 							      XmNrubberPositioning, True,
2650 							      NULL);
2651 #endif
2652     globals.widgets.draw_widget = XtVaCreateWidget("drawing",
2653 						   xmDrawingAreaWidgetClass,
2654 #ifdef TEST_SCROLLING
2655 						   globals.widgets.draw_background,
2656 #else
2657 						   globals.widgets.main_window,
2658 #endif
2659 						   XmNwidth, globals.page.w,
2660 						   XmNheight, globals.page.h,
2661 						   XmNhighlightThickness, 0,
2662 						   XmNrubberPositioning, True,
2663 						   XtNbackground, resource.back_Pixel,
2664 						   NULL);
2665 
2666 #if !FIXED_FLUSHING_PAGING
2667     ASSERT(XtParent(globals.widgets.draw_widget) != NULL, "");
2668     XtVaSetValues(XtParent(globals.widgets.draw_widget), XtNbackground, resource.back_Pixel, NULL);
2669 #endif
2670 
2671 #ifdef TEST_SCROLLING
2672     fprintf(stderr, "globals.widgets.draw_widget is: %p\n", globals.widgets.draw_widget);
2673 #endif
2674     XtVaGetValues(globals.widgets.main_window, XmNclipWindow, &globals.widgets.clip_widget, NULL);
2675 
2676     XtVaSetValues(globals.widgets.main_row,
2677 		  XmNmenuBar, globals.widgets.menu_bar,
2678 		  XmNcommandWindow, XtParent(tool_bar),
2679 		  XmNworkWindow, form,
2680 		  NULL);
2681 
2682     XtVaSetValues(globals.widgets.main_window,
2683 		  XmNworkWindow, globals.widgets.draw_widget,
2684 		  NULL);
2685 
2686     XtManageChild(globals.widgets.draw_widget);
2687 
2688     status_line = create_statusline(globals.widgets.main_row);
2689     XtVaSetValues(globals.widgets.main_row,
2690 		  XmNmessageWindow, status_line,
2691 		  NULL);
2692     if ((resource.expert_mode & XPRT_SHOW_STATUSLINE) == 0) {
2693 	XtUnmanageChild(status_line);
2694     }
2695 
2696     XtManageChild(globals.widgets.main_row);
2697 
2698     if ((resource.expert_mode & XPRT_SHOW_TOOLBAR) != 0) {
2699 	if (resource.toolbar_unusable)
2700 	    statusline_error(STATUS_LONG,
2701 			     "Error creating the toolbar pixmaps - toolbar is disabled!");
2702 	else
2703 	    XtManageChild(XtParent(tool_bar));
2704     }
2705 
2706     if ((resource.expert_mode & XPRT_SHOW_MENUBAR) != 0)
2707 	XtManageChild(globals.widgets.menu_bar);
2708 
2709     XmAddTabGroup(globals.widgets.draw_widget);
2710 
2711     /*
2712       note: a few more custom translations for page_list are defined in
2713       pagesel.c, since the actions are only known there.
2714     */
2715     {
2716 	XtTranslations xlats;
2717 
2718 	xlats = XtParseTranslationTable(base_key_translations);
2719 
2720 	XtOverrideTranslations(globals.widgets.main_row, xlats);
2721 	/* XtOverrideTranslations(globals.widgets.menu_bar, xlats); */
2722 	XtOverrideTranslations(tool_bar, xlats);
2723 	XtOverrideTranslations(page_list, xlats);
2724 	XtOverrideTranslations(globals.widgets.main_window, xlats);
2725 	XtOverrideTranslations(globals.widgets.clip_widget, xlats);
2726 	XtOverrideTranslations(globals.widgets.draw_widget, xlats);
2727 
2728 	xlats = XtParseTranslationTable("<BtnDown>: press()\n"
2729 					"<Motion>: motion()\n"
2730 					"<BtnUp>: release()\n");
2731 
2732 	XtOverrideTranslations(globals.widgets.clip_widget, xlats);
2733 	XtOverrideTranslations(globals.widgets.draw_widget, xlats);
2734     }
2735 
2736     if (resource.main_translations != NULL) {
2737 	XtTranslations xlats = XtParseTranslationTable(resource.main_translations);
2738 	XtOverrideTranslations(globals.widgets.draw_widget, xlats);
2739 	XtOverrideTranslations(globals.widgets.clip_widget, xlats);
2740 	XtOverrideTranslations(globals.widgets.main_row, xlats);
2741 	XtOverrideTranslations(globals.widgets.menu_bar, xlats);
2742 	XtOverrideTranslations(globals.widgets.main_window, xlats);
2743 	/* don't do it for the page list, otherwise mouse customizations will
2744 	   break the default list bindings too. */
2745 	/* XtOverrideTranslations(page_list, xlats); */
2746     }
2747 
2748     compile_mouse_actions();
2749 
2750 #else /* MOTIF */
2751 
2752     globals.widgets.form_widget = XtVaCreateManagedWidget("form", formWidgetClass, globals.widgets.top_level,
2753 							  XtNdefaultDistance, 0,
2754 							  NULL);
2755     globals.widgets.vport_widget = XtVaCreateManagedWidget("vport", viewportWidgetClass,
2756 							   globals.widgets.form_widget,
2757 							   XtNborderWidth, 0,
2758 							   XtNtop, XtChainTop,
2759 							   XtNbottom, XtChainBottom,
2760 							   XtNleft, XtChainLeft,
2761 							   XtNright, XtChainRight,
2762 							   XtNallowHoriz, True,
2763 							   XtNallowVert, True,
2764 							   NULL);
2765     globals.widgets.clip_widget = XtNameToWidget(globals.widgets.vport_widget, "clip");
2766 
2767     globals.widgets.draw_widget = XtVaCreateManagedWidget("drawing", drawWidgetClass, globals.widgets.vport_widget,
2768 							  XtNwidth, globals.page.w,
2769 							  XtNheight, globals.page.h,
2770 							  XtNx, 0,
2771 							  XtNy, 0,
2772 							  XtNlabel, "",
2773 							  NULL);
2774 
2775     XtOverrideTranslations(globals.widgets.form_widget, XtParseTranslationTable(base_key_translations));
2776 
2777     if (resource.main_translations != NULL) {
2778 	XtOverrideTranslations(globals.widgets.form_widget, XtParseTranslationTable(resource.main_translations));
2779     }
2780 
2781     {
2782 	XtTranslations xlats = XtParseTranslationTable("<BtnDown>: press()\n"
2783 						       "<Motion>: motion()\n"
2784 						       "<BtnUp>: release()\n");
2785 	XtOverrideTranslations(globals.widgets.form_widget, xlats);
2786 	XtOverrideTranslations(globals.widgets.draw_widget, xlats);
2787     }
2788 
2789     compile_mouse_actions();
2790 
2791 
2792     /* set background colors of the drawing widget */
2793     XtVaSetValues(globals.widgets.draw_widget, XtNbackground, resource.back_Pixel, NULL);
2794 
2795 #if !FIXED_FLUSHING_PAGING
2796     XtVaSetValues(globals.widgets.clip_widget, XtNbackground, resource.back_Pixel, NULL);
2797 #endif
2798 
2799     /* initialize add_w with width of button panel */
2800     create_menu_buttons(globals.widgets.form_widget, add_w);
2801 
2802 #endif /* MOTIF */
2803 
2804     /* activate expert mode and related settings */
2805     toggle_statusline();
2806     toggle_scrollbars();
2807 #ifdef MOTIF
2808     toggle_pagelist();
2809     toggle_toolbar();
2810     toggle_menubar();
2811 #else
2812     if ((resource.expert_mode & XPRT_SHOW_BUTTONS) == 0)
2813 	toggle_buttons();
2814 #endif
2815 
2816     *add_h = 0;
2817 #ifdef MOTIF
2818     *add_w = 0;
2819     if (resource.expert_mode & XPRT_SHOW_PAGELIST)
2820 	*add_w += xm_get_width(page_list);
2821 /*     if (globals.widgets.y_bar != NULL) */
2822 /*      	add_w += xm_get_width(globals.widgets.y_bar); */
2823 /*     if (globals.widgets.x_bar != NULL) */
2824 /*      	add_h += xm_get_width(globals.widgets.x_bar); */
2825     if (resource.expert_mode & XPRT_SHOW_MENUBAR)
2826 	*add_h += xm_get_height(globals.widgets.menu_bar);
2827     if (resource.expert_mode & XPRT_SHOW_TOOLBAR)
2828 	*add_h += xm_get_height(tool_bar);
2829     if (resource.expert_mode & XPRT_SHOW_STATUSLINE)
2830 	*add_h += xm_get_height(status_line);
2831 #else
2832     /* add_w has been initialized by create_menu_buttons() call above.
2833        Reset to 0 if we're in expert mode. */
2834     if (!(resource.expert_mode & XPRT_SHOW_BUTTONS)) {
2835 	*add_w = 0;
2836     }
2837     if (resource.expert_mode & XPRT_SHOW_STATUSLINE) {
2838 	/* FIXME: Unfortunately the statusline hasn't been created at this point for Xaw,
2839 	   so the value is still the built-in default.
2840 	*/
2841 	*add_h += get_statusline_height();
2842     }
2843 #endif
2844 }
2845 
2846 
2847 static void
realize_widgets(Dimension main_win_w,Dimension main_win_h,int add_w)2848 realize_widgets(Dimension main_win_w, Dimension main_win_h, int add_w)
2849 {
2850     /*
2851      *	Realize the widgets (or windows).
2852      */
2853 
2854 #ifndef MOTIF
2855     realize_button_panel(main_win_h);
2856 #endif
2857 
2858     XtAddEventHandler(
2859 #ifdef MOTIF
2860 		      globals.widgets.clip_widget,
2861 #else
2862 		      globals.widgets.vport_widget,
2863 #endif
2864 		      StructureNotifyMask, False,
2865 		      handle_resize, (XtPointer) NULL);
2866 
2867     XtAddEventHandler(globals.widgets.top_level, PropertyChangeMask, False,
2868 		      handle_property_change, (XtPointer) NULL);
2869     XtAddEventHandler(globals.widgets.draw_widget, ExposureMask, False, handle_expose,
2870 		      (XtPointer) &mane);
2871     XtRealizeWidget(globals.widgets.top_level);
2872 
2873     mainDeleteWindow = XInternAtom(DISP, "WM_DELETE_WINDOW", False);
2874 
2875 #ifdef MOTIF
2876     /* for Xaw, event handlers for scrollbars are added inside get_geom(), events.c */
2877     ASSERT(globals.widgets.x_bar != NULL, "");
2878     ASSERT(globals.widgets.y_bar != NULL, "");
2879 #ifdef USE_PANNER
2880     XtAddEventHandler(globals.widgets.x_bar, ButtonPressMask | ButtonReleaseMask, False, handle_x_scroll, NULL);
2881     XtAddEventHandler(globals.widgets.y_bar, ButtonPressMask | ButtonReleaseMask, False, handle_y_scroll, NULL);
2882 #endif
2883     XmAddWMProtocolCallback(globals.widgets.top_level, mainDeleteWindow, xdvi_exit_callback, NULL);
2884 #else
2885     wmProtocols = XInternAtom(DISP, "WM_PROTOCOLS", False);
2886     XSetWMProtocols(DISP, XtWindow(globals.widgets.top_level), &mainDeleteWindow, 1);
2887     XtAddEventHandler(globals.widgets.top_level, NoEventMask, True, handle_delete_message, NULL);
2888 #endif
2889 
2890     /* check whether we want to run in fullscreen mode */
2891     if (resource.fullscreen) {
2892 	reconfigure_window(resource.fullscreen, main_win_w + add_w, main_win_h, False);
2893     }
2894 
2895 #ifdef MOTIF
2896     XmProcessTraversal(globals.widgets.draw_widget, XmTRAVERSE_CURRENT);
2897     TRACE_GUI((stderr, "toplevel: %p", (void *)globals.widgets.top_level));
2898     create_tips(globals.widgets.top_level);
2899 #else
2900     if ((resource.expert_mode & XPRT_SHOW_STATUSLINE) != 0) {
2901 	create_statusline();
2902     }
2903 #endif
2904 
2905     currwin.win = mane.win = XtWindow(globals.widgets.draw_widget);
2906 
2907     {
2908 	XWindowAttributes attrs;
2909 
2910 	(void)XGetWindowAttributes(DISP, mane.win, &attrs);
2911 	G_backing_store = attrs.backing_store;
2912     }
2913 
2914 #ifdef HAVE_X11_XMU_EDITRES_H
2915     /*
2916      * Enable editres protocol (see "man editres").
2917      * Usually will need to add -lXmu to the linker line as well.
2918      */
2919     XtAddEventHandler(globals.widgets.top_level, (EventMask)0, True, _XEditResCheckMessages,
2920 		      (XtPointer)NULL);
2921 #endif
2922 }
2923 
2924 /*
2925  * Create colors and GCs.
2926  * In color mode, color changes affect globals.gc.fore, globals.gc.fore2,
2927  * and globals.gc.rule, but not globals.gc.copy or globals.gc.high.
2928  */
2929 static void
create_gcs(void)2930 create_gcs(void)
2931 {
2932 
2933 #if GREY
2934     if (resource.gamma == 0.0)
2935 	resource.gamma = 1.0;
2936 #endif
2937 
2938     if (!resource.rule_color)
2939 	resource.rule_pixel = resource.fore_Pixel;
2940 
2941 #if !COLOR
2942 
2943 #if GREY
2944     if (resource.use_grey)
2945 	init_pix();
2946     else
2947 #endif
2948     { /* not #defined GREY, or not resource.use_grey */
2949 	XGCValues values;
2950 	Pixel set_bits = (Pixel) (resource.fore_Pixel & ~resource.back_Pixel);
2951 	Pixel clr_bits = (Pixel) (resource.back_Pixel & ~resource.fore_Pixel);
2952 	Boolean copy_tmp = resource.copy;
2953 
2954 	globals.gc.copy = set_or_make_gc(NULL, GXcopy, resource.fore_Pixel, resource.back_Pixel);
2955 	if (copy_tmp || (set_bits && clr_bits)) {
2956 	    globals.gc.rule = globals.gc.copy;
2957 	    if (!resource.thorough)
2958 		copy_tmp = True;
2959 	}
2960 	if (copy_tmp) {
2961 	    globals.gc.fore = globals.gc.rule;
2962 	    if (!resource.copy) {
2963 		warn_overstrike();
2964 	    }
2965 	}
2966 	else {
2967 	    if (set_bits) {
2968 		globals.gc.fore = set_or_make_gc(NULL, GXor, set_bits, 0);
2969 	    }
2970 	    if (clr_bits || !set_bits)
2971 		*(globals.gc.fore ? &globals.gc.fore2 : &globals.gc.fore) = set_or_make_gc(NULL, GXandInverted, clr_bits, 0);
2972 	    if (!globals.gc.rule)
2973 		globals.gc.rule = globals.gc.fore;
2974 	}
2975     }
2976 #endif /* !COLOR */
2977 
2978     {
2979 	Pixel link_pix, visited_link_pix;
2980 	get_link_colors(&link_pix, &visited_link_pix);
2981 	globals.gc.linkcolor = set_or_make_gc(NULL, GXcopy, link_pix, resource.back_Pixel);
2982 	globals.gc.visited_linkcolor = set_or_make_gc(NULL, GXcopy, visited_link_pix, resource.back_Pixel);
2983     }
2984 
2985 #if COLOR
2986     /* Not affected by color changes.  */
2987     globals.gc.copy = set_or_make_gc(NULL, GXcopy, resource.fore_Pixel, resource.back_Pixel);
2988 #endif
2989     globals.gc.high = set_or_make_gc(NULL, GXcopy, resource.hl_Pixel, resource.back_Pixel);
2990 
2991     globals.gc.ruler = set_or_make_gc(NULL, GXcopy, resource.rule_pixel, resource.fore_Pixel);
2992 
2993 #if XAW
2994     /*
2995      * There's a bug in the Xaw toolkit, in which it uses the
2996      * DefaultGCOfScreen to do vertical scrolling in the Text widget.
2997      * This leads to a BadMatch error if our visual is not the default one.
2998      * The following kludge works around this.
2999      */
3000     DefaultGCOfScreen(SCRN) = globals.gc.copy;
3001 #endif
3002 }
3003 
3004 static void
do_fork(void)3005 do_fork(void)
3006 {
3007     TRACE_CLIENT((stderr, "no other instance of xdvi found, forking ..."));
3008     /*
3009      * No suitable xdvi found, so we start one by
3010      * self-backgrounding.
3011      */
3012     /* flush output buffers to avoid double buffering (i.e. data
3013        waiting in the output buffer being written twice, by the parent
3014        and the child) */
3015     fflush(stdout);
3016     fflush(stderr);
3017     XFlush(DISP);
3018     if (fork())	/* if initial process (do NOT use vfork()!) */
3019 	_exit(0);
3020 }
3021 
3022 #if defined(MOTIF) && defined(USE_PANNER) && USE_XAW_PANNER
3023 static void
panner_cb(Widget widget,XtPointer closure,XtPointer report_ptr)3024 panner_cb(Widget widget, XtPointer closure, XtPointer report_ptr)
3025 {
3026     fprintf(stderr, "panner_cb called!\n");
3027 }
3028 #endif
3029 
3030 #if !DELAYED_MKTEXPK
3031 
3032 static XtIntervalId m_font_popup_id = 0;
3033 static Widget m_font_popup = 0;
3034 
3035 static void
remove_font_popup(XtPointer client_data,XtIntervalId * id)3036 remove_font_popup(XtPointer client_data, XtIntervalId *id)
3037 {
3038     UNUSED(client_data);
3039     UNUSED(id);
3040 
3041     if (m_font_popup != 0) {
3042 	kill_message_window(m_font_popup);
3043     }
3044 }
3045 
3046 static void
remove_font_popup_exit_cb(XtPointer arg)3047 remove_font_popup_exit_cb(XtPointer arg)
3048 {
3049     UNUSED(arg);
3050     xdvi_exit(EXIT_SUCCESS);
3051 }
3052 
3053 static void
create_font_popup(XtPointer client_data,XtIntervalId * id)3054 create_font_popup(XtPointer client_data, XtIntervalId *id)
3055 {
3056     int *curr_timeout = (int *)client_data;
3057     static int new_timeout = 0;
3058 
3059     UNUSED(client_data);
3060     UNUSED(id);
3061 
3062 /*     fprintf(stderr, "+++++++++++++++ create_font_popup\n"); */
3063 
3064     if (m_font_popup_id) {
3065 	if (*curr_timeout > 0) {
3066 	    XtRemoveTimeOut(m_font_popup_id);
3067 	    m_font_popup_id = XtAppAddTimeOut(globals.app, *curr_timeout, create_font_popup, (XtPointer)&new_timeout);
3068 	}
3069 	else {
3070 	    m_font_popup = choice_dialog(globals.widgets.top_level,
3071 					 MSG_INFO, NULL,
3072 #ifndef MOTIF
3073 					 NULL,
3074 #endif
3075 					 NULL, NULL, /* no pre_callbacks */
3076 					 NULL, NULL, NULL, /* default arguments for `OK' */
3077 					 "Exit Xdvi", remove_font_popup_exit_cb, (XtPointer)NULL,
3078 					 "Loading %s\n(may take some time creating fonts ...)",
3079 					 globals.dvi_name);
3080 	}
3081     }
3082 }
3083 
3084 void
register_font_popup(void)3085 register_font_popup(void)
3086 {
3087     /* Use a two-step process, so that when the timeout is removed by unregister_font_popup(),
3088        it will occur before new_timeout. create_font_popup() will call XtAppAddTimeOut() again
3089        with new_timeout = 0.
3090     */
3091     static int new_timeout = 50;
3092 /*     fprintf(stderr, "+++++++++++++++ registered font popup\n"); */
3093     m_font_popup_id = XtAppAddTimeOut(globals.app, 100, create_font_popup, (XtPointer)&new_timeout);
3094 }
3095 
3096 void
unregister_font_popup(void)3097 unregister_font_popup(void)
3098 {
3099 /*     fprintf(stderr, "+++++++++++++++ unregister_font_popup\n"); */
3100     if (m_font_popup_id) {
3101 	XtRemoveTimeOut(m_font_popup_id);
3102 	m_font_popup_id = 0;
3103 	/* FIXME: calling this directly crashes xdvi?? */
3104 	/*  	m_font_popup_id = XtAppAddTimeOut(globals.app, 1, remove_font_popup, (XtPointer)NULL); */
3105 	remove_font_popup(NULL, NULL);
3106     }
3107 }
3108 #endif /* !DELAYED_MKTEXPK */
3109 
3110 /* revert resources */
3111 void
load_app_resources(Boolean also_pixels)3112 load_app_resources(Boolean also_pixels)
3113 {
3114     /*     /\* reset some resources to built-in defaults *\/ */
3115     /*     resource.browser = NULL; */
3116     /*     resource.editor = NULL; */
3117     /*     resource.gamma = 1; */
3118     /*     resource.link_style = 3; */
3119     /*     resource.link_color = LINK_COLOR_FALLBACK; */
3120     /*     resource.visited_link_color = VISITED_LINK_COLOR_FALLBACK; */
3121     /*     resource.expert_mode = 31; */
3122     /*     resource.use_color = True; */
3123     /*     resource.match_highlight_inverted = True; */
3124 
3125     XtGetApplicationResources(globals.widgets.top_level, (XtPointer)&resource,
3126 			      application_resources, XtNumber(application_resources),
3127 			      (ArgList)NULL, 0);
3128 
3129     if (also_pixels) {
3130 	XtGetApplicationResources(globals.widgets.top_level, (XtPointer)&resource,
3131 				  app_pixel_resources, XtNumber(app_pixel_resources),
3132 				  (ArgList)NULL, 0);
3133     }
3134     /*      fprintf(stderr, "gamma: %f\n", resource.gamma); */
3135 }
3136 
3137 /*
3138  * Unfortunately this must be a callback, for the file selector ...
3139  * This is the second part of Main: Create all widgets, initialize the DVI file,
3140  * and enter the main event loop.
3141  */
3142 void
run_dvi_file(const char * filename,void * data)3143 run_dvi_file(const char *filename, void *data)
3144 {
3145     Boolean tried_dvi_ext = False;
3146     struct startup_info *cb = (struct startup_info *)data;
3147 
3148 #ifdef MOTIF
3149     Widget tool_bar = 0;
3150     Widget form = 0;
3151 #endif
3152 
3153     char *title_name = NULL;
3154     char *icon_name = NULL;
3155     dviErrFlagT errflag = NO_ERROR;
3156 
3157     int add_w = 0, add_h = 0;
3158     Dimension main_win_w, main_win_h;
3159 
3160     UNUSED(data);
3161     ASSERT(filename != NULL, "filename must have been initialized here!");
3162 
3163     globals.dvi_name = xstrdup(filename);
3164     file_history_push(globals.dvi_name);
3165 
3166     TRACE_FILES((stderr, "globals.dvi_name is: |%s| %p\n", globals.dvi_name, globals.dvi_name));
3167 
3168     globals.dvi_file.dirname = get_dir_component(globals.dvi_name);
3169     xdvi_assert(XDVI_VERSION_INFO, __FILE__, __LINE__,
3170 		globals.dvi_file.dirname != NULL,
3171 		"globals.dvi_name (%s) must contain a dir component",
3172 		globals.dvi_name);
3173     globals.dvi_file.dirlen = strlen(globals.dvi_file.dirname);
3174 
3175     form_dvi_property();
3176 
3177     /*
3178       If `unique' is active, we may need to pass the file to a different instance of xdvi:
3179     */
3180     if (resource.unique) {
3181 	Window w1 = 0, w2 = 0;
3182 	if ((w1 = get_xdvi_window_id(True, NULL)) != 0 || (w2 = get_xdvi_window_id(False, NULL)) != 0) {
3183 	    if (w1 != 0) { /* another xdvi instance, same file: reload */
3184 		w2 = w1;
3185 		set_string_property("", atom_reload(), w2);
3186 	    }
3187 	    else { /* another xdvi instance, different file: load new file */
3188 		set_string_property(globals.dvi_name, atom_newdoc(), w2);
3189 	    }
3190 	    if (cb->page_arg != NULL) { /* switch to different page */
3191 		if (strlen(cb->page_arg) == 0) { /* special case: treat `+' as last page */
3192 		    set_string_property("+", atom_newpage(), w2);
3193 		}
3194 		else {
3195 		    set_string_property(cb->page_arg, atom_newpage(), w2);
3196 		}
3197 	    }
3198 	    else {
3199 		/* if page_arg is empty, go to 1st page so that this page is
3200 		   inserted into the page history (fix for #1044891) */
3201 		set_string_property("1", atom_newpage(), w2);
3202 	    }
3203 	    /* in all cases, raise the window of the other instance */
3204 	    set_string_property("", atom_raise(), w2);
3205 	    xdvi_exit(EXIT_SUCCESS);
3206 	}
3207 	else if (resource.src_fork) {
3208 	    do_fork();
3209 	}
3210     }
3211 
3212     /*
3213       Similar for forward search or string search:
3214     */
3215     if (resource.src_pos != NULL || resource.find_string != NULL) {
3216 	Window w;
3217 	if ((w = get_xdvi_window_id(True, NULL)) != 0) {
3218 	    /* another instance of xdvi running, displaying the same file */
3219 	    TRACE_CLIENT((stderr, "Match; changing property of client and exiting ..."));
3220 	    if (resource.src_pos != NULL)
3221 		set_sourceposition_property(resource.src_pos, w);
3222 	    else
3223 		set_stringsearch_property(resource.find_string, w);
3224 	    xdvi_exit(EXIT_SUCCESS);
3225 	}
3226 	else if (resource.src_fork) {
3227 	    do_fork();
3228 	}
3229     }
3230 
3231     /* Needed for source specials and for calling ghostscript. */
3232     xputenv("DISPLAY", XDisplayString(DISP));
3233 
3234 
3235     if (globals.debug) {
3236 	fprintf(stderr, "%s %s, kpathsea: %s\n", XDVIK_PROGNAME, XDVI_VERSION_INFO, kpathsea_version_string);
3237 	fprintf(stderr,
3238 		"configured with: ppi=%d shrink=%d mfmode=%s alt_font=%s paper=%s\n",
3239 		resource.pixels_per_inch,
3240 		currwin.shrinkfactor,
3241 		resource.mfmode ? resource.mfmode : "<NONE>",
3242 		resource.alt_font,
3243 		resource.paper);
3244     }
3245 
3246     kpse_set_program_enabled(kpse_any_glyph_format, resource.makepk, kpse_src_compile);
3247     /* janl 16/11/98: I have changed this. The above line used to
3248        say the settings in resource.makepk was supplied on the
3249        commandline, resulting in it overriding _all other_
3250        settings, derived from the environment or texmf.cnf, no
3251        matter what the value. The value in resource.makepk could
3252        be the compile-time default...
3253 
3254        Personaly I like the environment/texmf.cnf to override
3255        resources and thus changed the 'level' of this setting to
3256        kpse_src_compile so the environment/texmf.cnf will override
3257        the values derived by Xt.
3258 
3259        Previous comment here:
3260 
3261        ``Let true values as an X resource/command line override false
3262        values in texmf.cnf/envvar.''  */
3263 
3264     /*
3265      *		Step 2:  Settle colormap issues.  This should be done before
3266      *		other widgets are created, so that they get the right
3267      *		pixel values.  (The top-level widget won't have the right
3268      *		values, but I don't think that makes any difference.)
3269      */
3270 
3271 #ifdef XSERVER_INFO
3272     print_xserver_info();
3273 #endif
3274 
3275     create_colormaps();
3276 
3277 
3278 #ifdef TESTING_OPEN_FILES
3279     fprintf(stderr, "open_max: %ld\n", OPEN_MAX);
3280     for (i = 0; i < OPEN_MAX - 10; i++) {
3281 	FILE *fp;
3282 	if ((fp = fopen("/tmp/foo", "r")) == NULL) {
3283 	    perror("fopen");
3284 	    xdvi_exit(EXIT_FAILURE);
3285 	}
3286     }
3287     fprintf(stderr, "opened %d files.\n", i);
3288 #endif
3289 
3290 
3291     /* toolbar code may open files, but we have no check close_a_file() in
3292        the toolbar code; so do this before prescan() possibly opens lots of files.
3293     */
3294 #ifdef MOTIF
3295     globals.widgets.main_row = XmCreateMainWindow(globals.widgets.top_level, "main", NULL, 0);
3296 
3297     create_menu_buttons(globals.widgets.main_row, &globals.widgets.menu_bar);
3298 
3299     /* seems to be needed for enabling `XmNhighlightOnEnter' for the toolbar buttons
3300        - is this the correct place to do it? */
3301     XtVaSetValues(globals.widgets.top_level, XmNkeyboardFocusPolicy, (XtArgVal)XmPOINTER, NULL);
3302 
3303     form = XtVaCreateWidget("form", xmFormWidgetClass, globals.widgets.main_row,
3304 			    XmNshadowThickness, 0,
3305 			    NULL);
3306 
3307     if (resource.main_translations != NULL) {
3308 	XtOverrideTranslations(form, XtParseTranslationTable(resource.main_translations));
3309     }
3310 
3311 
3312 #if defined(USE_PANNER) && USE_XAW_PANNER
3313     panner = XtVaCreateWidget("panner", pannerWidgetClass, form,
3314 			      XmNtopAttachment, XmATTACH_FORM,
3315 			      XmNleftAttachment, XmATTACH_FORM,
3316 			      XmNleftOffset, 20,
3317 			      XmNrightAttachment, XmATTACH_OPPOSITE_FORM,
3318 			      XmNrightOffset, -resource.pagelist_width + 20,
3319 			      XmNtopOffset, 2,
3320 			      XmNleftOffset, 2,
3321 			      XtNheight, 60,
3322 			      XtNwidth, resource.pagelist_width - 50,
3323 			      XtNsliderX, 5,
3324 			      XtNsliderY, 7,
3325 			      XtNinternalSpace, 0,
3326 			      XtNshadowThickness, 0,
3327 			      NULL);
3328 #endif
3329 #endif
3330 
3331     /* use bounding box for highlighting if our visual isn't TrueColor
3332        (not worth the trouble ...) */
3333     if (G_visual->class != TrueColor) {
3334 	resource.match_highlight_inverted = False;
3335     }
3336 
3337     /*
3338      *		Step 3:  Initialize the dvi file and set titles.
3339      */
3340 
3341 #if FREETYPE
3342     /*
3343       At this point DISP, G_visual, G_depth and G_colormap must
3344       be defined. Also, init_t1_lookup() must go before internal_open_dvi(),
3345       since read_postamble will define some fonts and insert them into
3346       fontmaps_hash, but we need a clean fontmaps_hash for detecting
3347       duplicate entries in the map file.
3348     */
3349 
3350     if (resource.freetype) {
3351 	if (!init_t1_lookup()) {
3352 	    /* nag 'em with a popup so that they'll do something about this */
3353 	    popup_message(globals.widgets.top_level,
3354 		      MSG_ERR,
3355 		      "Direct Type 1 font rendering via FreeType gives you "
3356 		      "many benefits, such as:\n"
3357 		      " - quicker startup time, since no bitmap fonts need "
3358 		      "to be generated;\n"
3359 		      " - saving disk space for storing the bitmap fonts.\n"
3360 		      "To fix this error, check that the file `ps2pk.map' "
3361 		      "is located somewhere in your XDVIINPUTS path.  "
3362 		      "Have a look at the xdvi wrapper shell script "
3363 		      "(type \"which xdvi\" to locate that shell script) "
3364 		      "for the current setting of XDVIINPUTS.",
3365 		      "Could not load any of the map files listed in xdvi.cfg "
3366 		      "- disabling FreeType.");
3367 	    resource.freetype = False;
3368 	}
3369     }
3370 #endif /* FREETYPE */
3371 
3372 #if DELAYED_MKTEXPK
3373     /* Open and initialize the DVI file. First, disable creation of PK fonts
3374      * so that we can count the missing fonts that are to be generated. */
3375     kpse_set_program_enabled(kpse_any_glyph_format, False, kpse_src_compile);
3376 #endif
3377 
3378     setup_signal_handlers(False);
3379 
3380 #if !DELAYED_MKTEXPK
3381     /* Notify users that fonts are being created. This is just a hack
3382        and no replacement for true asynchronous font creation since it
3383        doesn't give details (is just invoked if startup takes somewhat
3384        longer) and freezes during font creation.
3385     */
3386     register_font_popup();
3387 #endif
3388 
3389     /* open and initialize the DVI file, but don't read the fonts yet */
3390     if (!internal_open_dvi(globals.dvi_name, &errflag, True
3391 #if DELAYED_MKTEXPK
3392 			   , False /* read fonts, but don't initialize data structures */
3393 #endif
3394 			   )) {
3395 	if (tried_dvi_ext) {
3396 	    XDVI_FATAL((stderr, "Could not open %s: %s, and %s.dvi doesn't exist either - exiting.",
3397 			globals.dvi_name, get_dvi_error(errflag), globals.dvi_name));
3398 	}
3399 	else {
3400 	    XDVI_FATAL((stderr, "Could not open %s: %s.",
3401 			globals.dvi_name, get_dvi_error(errflag)));
3402 	}
3403     }
3404 
3405 #if DELAYED_MKTEXPK
3406     fprintf(stderr, "after opening ...\n");
3407     /* Now re-enable PK creation and read the postamble for a second time.
3408      * FIXME: Actually we don't need this re-reading, could as well read the
3409      * entire thing in the first run, not quit early and correctly initialize
3410      * the fonts without creating them. */
3411     kpse_set_program_enabled(kpse_any_glyph_format, resource.makepk, kpse_src_compile);
3412 
3413     if (!internal_open_dvi(globals.dvi_name, &errflag, True, True)) {
3414 	if (tried_dvi_ext) {
3415 	    XDVI_FATAL((stderr, "Could not open %s: %s, and %s.dvi doesn't exist either - exiting.",
3416 			globals.dvi_name, get_dvi_error(errflag), globals.dvi_name));
3417 	}
3418 	else {
3419 	    XDVI_FATAL((stderr, "Could not open %s: %s.",
3420 			globals.dvi_name, get_dvi_error(errflag)));
3421 	}
3422     }
3423 #else
3424     unregister_font_popup();
3425 #endif
3426 
3427     if (cb->page_arg != NULL) {
3428 	if (cb->page_arg[0] == '\0') { /* empty page_arg -> goto last page */
3429 	    current_page = total_pages - 1;
3430 	    page_history_insert(current_page);
3431 	}
3432 	else {
3433 	    char *testptr;
3434 	    current_page = strtoul(cb->page_arg, &testptr, 10) - 1;
3435 	    if (*testptr != '\0') {
3436 		XDVI_FATAL((stderr, "Invalid page number: `%s'.", cb->page_arg));
3437 	    }
3438 	    current_page = check_goto_page(current_page, True);
3439 	}
3440     }
3441     else {
3442 	page_history_insert(current_page);
3443     }
3444     file_history_set_page(current_page);
3445 
3446     ASSERT(globals.dvi_file.bak_fp != NULL, "Backup file pointer must have been initialized here");
3447     if (resource.prescan) {
3448 	prescan(globals.dvi_file.bak_fp);
3449     }
3450 
3451     globals.page.unshrunk_w = pageinfo_get_page_width(current_page);
3452     globals.page.unshrunk_h = pageinfo_get_page_height(current_page);
3453     TRACE_GUI((stderr, "globals.page.unshrunk_w: %d, h: %d; window: %d, %d",
3454 	       globals.page.unshrunk_w, globals.page.unshrunk_h,
3455 	       pageinfo_get_window_width(current_page),
3456 	       pageinfo_get_window_height(current_page)));
3457 
3458     init_page();
3459 
3460     /*
3461      *		Step 4:  Create widgets, and set initial window size.
3462      */
3463 
3464     /* currently these override expert mode - using this is deprecated
3465        in favour of `-expertmode'; inform user about this: */
3466     if (resource.statusline) {
3467 	XDVI_WARNING((stderr, "The option/X resource `statusline' is obsolete; "
3468 		      "use `-expertmode <flag>' instead, e.g. `-expertmode 1'\n"
3469 		      "to switch on the status line, or `-expertmode 6'\n"
3470 		      "to switch it off. See the xdvi man page for details."));
3471 	resource.expert_mode |= XPRT_SHOW_STATUSLINE;
3472     }
3473 
3474     /*      XtRealizeWidget(globals.widgets.top_level); */
3475 
3476 #ifdef MOTIF
3477     tool_bar = create_toolbar(globals.widgets.main_row, globals.widgets.menu_bar);
3478     if (resource.main_translations != NULL) {
3479 	XtOverrideTranslations(tool_bar, XtParseTranslationTable(resource.main_translations));
3480     }
3481 #endif
3482 
3483     create_widgets(
3484 #ifdef MOTIF
3485 		   tool_bar, form,
3486 #endif
3487 		   &add_w, &add_h);
3488 
3489     TRACE_GUI((stderr, "add_w = %d, add_h = %d\n", add_w, add_h));
3490     /*  fprintf(stderr, "geometry xdvirc: |%s|, orig: |%s|\n", resource.xdvirc_geometry, resource.geometry); */
3491 
3492     /*
3493      *	Set initial window size.
3494      *	This needs to be done before colors are assigned because if
3495      *	-s 0 is specified, we need to compute the shrink factor
3496      *	(which in turn affects whether init_pix is called).
3497      */
3498     set_windowsize(&main_win_w, &main_win_h, add_w, add_h, False);
3499 
3500     realize_widgets(main_win_w, main_win_h, add_w);
3501 
3502     /* this needs to be done after total_pages is known (via internal_open_dvi) */
3503     get_icon_and_title(globals.dvi_name, &icon_name, &title_name);
3504     add_icon(globals.widgets.top_level, title_name, icon_name);
3505     /* this needs to be done after the widgets have been created */
3506     set_icon_and_title(icon_name, title_name);
3507     free(icon_name);
3508     free(title_name);
3509     icon_name = title_name = NULL;
3510 
3511 
3512     G_image = XCreateImage(DISP, G_visual, 1, XYBitmap, 0,
3513 			   (char *)NULL, 0, 0, BMBITS, 0);
3514     G_image->bitmap_unit = BMBITS;
3515 #ifdef	WORDS_BIGENDIAN
3516     G_image->bitmap_bit_order = MSBFirst;
3517 #else
3518     G_image->bitmap_bit_order = LSBFirst;
3519 #endif
3520     {
3521 	short endian = MSBFirst << 8 | LSBFirst;
3522 	G_image->byte_order = *((char *)&endian);
3523     }
3524 
3525     /* Store window id for use by get_xdvi_window_id().  */
3526     {
3527 	long data = XtWindow(globals.widgets.top_level);
3528 
3529 	XChangeProperty(DISP, DefaultRootWindow(DISP),
3530 			atom_xdvi_windows(), atom_xdvi_windows(), 32,
3531 			PropModePrepend, (unsigned char *)&data, 1);
3532 	set_dvi_property();
3533     }
3534 
3535 
3536 #if HAVE_XI21
3537     xi2_init();	/* Set up hi-res (smooth) scrolling */
3538 #endif
3539 
3540     /*
3541      *	Step 5:  Assign colors and GCs.
3542      *		 Because of the latter, this has to go after the widgets are realized.
3543      */
3544 
3545     create_gcs();
3546 
3547     create_cursors();
3548 
3549 #ifdef MOTIF
3550 #if defined(USE_PANNER) && USE_XAW_PANNER
3551     XtVaSetValues(panner, XtNsliderWidth, globals.page.w / 2,
3552 		  XtNsliderHeight, globals.page.h / 2,
3553 		  XtNcanvasWidth, globals.page.w,
3554 		  XtNcanvasHeight, globals.page.h,
3555 		  NULL);
3556     XtManageChild(panner);
3557     XtAddCallback(panner, XtNreportCallback, panner_cb, (XtPointer)NULL);
3558 #endif
3559     create_pagelist();
3560 #endif
3561 
3562     /* trigger forward search */
3563     do_forward_search(resource.src_pos);
3564 
3565     /* trigger string search */
3566     if (resource.find_string != NULL) {
3567 	globals.ev.flags |= EV_FIND;
3568     }
3569 
3570     /* trigger anchor search */
3571     if (resource.anchor_pos != NULL) {
3572 	g_anchor_pos = xstrdup(resource.anchor_pos);
3573 	g_anchor_len = strlen(g_anchor_pos);
3574 	globals.ev.flags |= EV_ANCHOR;
3575     }
3576 
3577 #if defined(MOTIF) && HAVE_XPM
3578     tb_check_navigation_sensitivity(current_page);
3579 #endif
3580 
3581 #if CHECK_APP_FILEVERSION
3582     check_app_defaults_fileversion();
3583 #endif
3584 
3585     /* can do this only after scrollbars have been realized */
3586     if (!BROKEN_RECONFIG && (resource.expert_mode & XPRT_SHOW_SCROLLBARS) == 0) {
3587 	toggle_scrollbars();
3588     }
3589 
3590     /* initialize file watching */
3591     if (resource.watch_file > 0.0) {
3592 #if XDVI_XT_TIMER_HACK
3593 	watch_file_cb(NULL, NULL);
3594 #else
3595 	XDVI_WARNING((stderr, "Could not redefine XtAppAddTimeOut(); `watchfile' not available."));
3596 #endif
3597     }
3598 
3599     /* raise `early' message windows */
3600     raise_message_windows();
3601 
3602     {
3603 	String args[1];
3604 	char mmode[LENGTH_OF_INT];
3605 	snprintf(mmode, LENGTH_OF_INT, "%d", resource.mouse_mode);
3606 	args[0] = mmode;
3607 	XtCallActionProc(globals.widgets.top_level, "switch-mode", NULL, args, 1);
3608     }
3609 
3610     /* go to home position on first page to honor -(side|top)margin flags */
3611     if (!resource.keep_flag)
3612     	home(False);
3613 
3614     do_pages();
3615 }
3616