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