summaryrefslogtreecommitdiff
path: root/Build/source/texk/xdvik/xdvi.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/xdvik/xdvi.c')
-rw-r--r--Build/source/texk/xdvik/xdvi.c4342
1 files changed, 4342 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/xdvi.c b/Build/source/texk/xdvik/xdvi.c
new file mode 100644
index 00000000000..3a73f678394
--- /dev/null
+++ b/Build/source/texk/xdvik/xdvi.c
@@ -0,0 +1,4342 @@
+/*========================================================================*\
+
+Copyright (c) 1990-2004 Paul Vojta and others
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL PAUL
+VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+NOTE: xdvi is based on prior work as noted in the modification history, below.
+
+\*========================================================================*/
+
+/*
+ * DVI previewer for X.
+ *
+ * Eric Cooper, CMU, September 1985.
+ *
+ * Code derived from dvi-imagen.c.
+ *
+ * Modification history:
+ * 1/1986 Modified for X.10 --Bob Scheifler, MIT LCS.
+ * 7/1988 Modified for X.11 --Mark Eichin, MIT
+ * 12/1988 Added 'R' option, toolkit, magnifying glass
+ * --Paul Vojta, UC Berkeley.
+ * 2/1989 Added tpic support --Jeffrey Lee, U of Toronto
+ * 4/1989 Modified for System V --Donald Richardson, Clarkson Univ.
+ * 3/1990 Added VMS support --Scott Allendorf, U of Iowa
+ * 7/1990 Added reflection mode --Michael Pak, Hebrew U of Jerusalem
+ * 1/1992 Added greyscale code --Till Brychcy, Techn. Univ. Muenchen
+ * and Lee Hetherington, MIT
+ * 7/1992 Added extra menu buttons--Nelson H. F. Beebe <beebe@math.utah.edu>
+ * 4/1994 Added DPS support, bounding box
+ * --Ricardo Telichevesky
+ * and Luis Miguel Silveira, MIT RLE.
+ * 2/1995 Added rulers support --Nelson H. F. Beebe <beebe@math.utah.edu>
+ * 1/2001 Added source specials --including ideas from Stefan Ulrich,
+ * U Munich
+ *
+ * Compilation options:
+ *
+ * VMS compile for VMS
+ * WORDS_BIGENDIAN store bitmaps internally with most significant bit first
+ * BMTYPE store bitmaps in unsigned BMTYPE
+ * BMBYTES sizeof(unsigned BMTYPE)
+ * ALTFONT default for -altfont option
+ * SHRINK default for -s option (shrink factor)
+ * MFMODE default for -mfmode option
+ * A4 use European size paper, and change default dimension to cm
+ * TEXXET support reflection dvi codes (right-to-left typesetting)
+ * GREY use grey levels to shrink fonts
+ * PS_GS use Ghostscript to render pictures/bounding boxes
+ * PS_DPS use display postscript to render pictures/bounding boxes
+ * PS_NEWS use the NeWS server to render pictures/bounding boxes
+ * GS_PATH path to call the Ghostscript interpreter by
+ * MAGICK use ImageMagick to render (external) image files
+ */
+
+
+#include "xdvi-config.h"
+#include "xdvi.h"
+#include "version.h"
+
+#include <locale.h>
+
+/* Xlib and Xutil are already included */
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h> /* needed for def. of XtNiconX */
+
+#ifdef HAVE_X11_XMU_EDITRES_H
+# include <X11/Xmu/Editres.h>
+#endif
+
+/* to allow one common dependency file for Xaw/Motif,
+ we always include all the headers and have
+ #ifdef MOTIF
+ tests inside the headers.
+*/
+#if defined(NEW_MENU_CREATION) || defined(MOTIF)
+#include "menu.h"
+#else
+#include "xm_menu.h"
+#include "xaw_menu.h"
+#endif /* NEW_MENU_CREATION */
+#include "xm_toolbar.h"
+
+#ifdef T1LIB
+#include "t1lib.h"
+#endif /* T1LIB */
+
+#ifdef MOTIF
+
+# include <Xm/Xm.h>
+# include <Xm/Frame.h>
+# include <Xm/PushB.h>
+# include <Xm/MainW.h>
+# include <Xm/ToggleB.h>
+# include <Xm/RowColumn.h>
+# include <Xm/ScrolledW.h>
+# include <Xm/MenuShell.h>
+# include <Xm/DrawingA.h>
+# include <Xm/Form.h>
+# include <Xm/PanedW.h>
+# include <Xm/List.h>
+# include <Xm/Protocols.h>
+
+# include <Xm/Display.h>
+
+# ifdef MOTIF11 /* FIXME: We'll probably need a config check for this? */
+/* used to set up XmStrings */
+XmStringCharSet G_charset = (XmStringCharSet)XmSTRING_DEFAULT_CHARSET;
+# else
+XmStringCharSet G_charset = XmFONTLIST_DEFAULT_TAG;
+# endif
+
+#else /* MOTIF */
+
+# include <X11/Xaw/Viewport.h>
+# include <X11/Xaw/AsciiText.h>
+# include <X11/Xaw/Box.h>
+# include <X11/Xaw/Command.h>
+# include <X11/Xaw/Dialog.h>
+# include <X11/Xaw/Form.h>
+# include <X11/Xaw/Paned.h>
+# include <X11/Xaw/Scrollbar.h>
+# include <X11/Xaw/Command.h>
+
+#endif /* MOTIF */
+
+#include <signal.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "xserver-info.h"
+
+#include "kpathsea/c-fopen.h"
+#include "kpathsea/c-pathch.h"
+#include "kpathsea/c-stat.h"
+#include "kpathsea/proginit.h"
+#include "kpathsea/progname.h"
+#include "kpathsea/tex-file.h"
+#include "kpathsea/tex-hush.h"
+#include "kpathsea/tex-make.h"
+#include "string-utils.h"
+#include "kpathsea/c-errno.h"
+#include "kpathsea/expand.h"
+
+#include "translations.h"
+#include "dvi-init.h"
+#include "c-openmx.h"
+#include "xicon.h"
+#include "x_util.h"
+#include "message-window.h"
+#include "events.h"
+#include "mag.h"
+#include "pagesel.h"
+#include "dvi-draw.h"
+#include "statusline.h"
+#include "util.h"
+#include "my-snprintf.h"
+#include "hypertex.h"
+#include "xaw_menu.h"
+#include "xdvi-debug.h"
+#include "pagehist.h"
+#include "filehist.h"
+#include "sfSelFile.h"
+#include "print-internal.h"
+#include "xm_prefsP.h" /* for Xdvi_PREFS_BROWSER_DEFAULTS and Xdvi_PREFS_EDITOR_DEFAULTS */
+
+#include "pixmaps/time16.xbm"
+#include "pixmaps/time16_mask.xbm"
+#ifdef VMS
+# include "pixmaps/hand.xbm"
+# include "pixmaps/hand_mask.xbm"
+#endif
+#include "pixmaps/magglass.xbm"
+#include "pixmaps/magglass_mask.xbm"
+#include "pixmaps/drag_vert.xbm"
+#include "pixmaps/drag_vert_mask.xbm"
+#include "pixmaps/drag_horiz.xbm"
+#include "pixmaps/drag_horiz_mask.xbm"
+#include "pixmaps/drag_omni.xbm"
+#include "pixmaps/drag_omni_mask.xbm"
+
+#ifdef DEBUG
+#include<asm/msr.h>
+unsigned long time_start=0, time_end=0;
+#endif
+
+
+#ifdef MOTIF
+#include <Xm/MwmUtil.h>
+
+#else /* MOTIF */
+
+/* need to fake it */
+
+/* bit definitions for MwmHints.flags */
+#define MWM_HINTS_FUNCTIONS (1L << 0)
+#define MWM_HINTS_DECORATIONS (1L << 1)
+#define MWM_HINTS_INPUT_MODE (1L << 2)
+#define MWM_HINTS_STATUS (1L << 3)
+
+/* bit definitions for MwmHints.decorations */
+#define MWM_DECOR_ALL (1L << 0)
+#define MWM_DECOR_BORDER (1L << 1)
+#define MWM_DECOR_RESIZEH (1L << 2)
+#define MWM_DECOR_TITLE (1L << 3)
+#define MWM_DECOR_MENU (1L << 4)
+#define MWM_DECOR_MINIMIZE (1L << 5)
+#define MWM_DECOR_MAXIMIZE (1L << 6)
+
+struct PropMotifWmHints {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long inputMode;
+ unsigned long status;
+};
+
+#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
+
+#endif /* MOTIF */
+
+char *dvi_property; /* for setting in window */
+size_t dvi_property_length; /* length of above, for efficiency */
+XImage *G_image;
+int G_backing_store;
+Display *DISP;
+Screen *SCRN;
+XtAccelerators G_accels_cr;
+
+#ifdef GREY
+Visual *G_visual;
+unsigned int G_depth;
+Colormap G_colormap;
+#else
+# define G_depth (unsigned int) DefaultDepthOfScreen(SCRN)
+# define G_visual DefaultVisualOfScreen(SCRN)
+# define G_colormap DefaultColormapOfScreen(SCRN)
+#endif
+
+/* global widgets */
+
+#if defined(MOTIF)
+Widget page_list, page_list_scroll;
+#if USE_XAW_PANNER
+#include "Panner.h"
+Widget panner;
+static Dimension g_save_shadow_thickness;
+#endif
+#endif
+
+static Atom mainDeleteWindow;
+
+#ifndef MOTIF
+static Atom wmProtocols;
+static void
+handle_delete_message(Widget widget, XtPointer closure, XEvent *event, Boolean *cont)
+{
+ UNUSED(cont);
+ UNUSED(widget);
+
+ ASSERT(closure == NULL, "handle_delete_message doesn't accept a non-NULL closure argument");
+ if (event->type == ClientMessage
+ && event->xclient.message_type == wmProtocols
+ && (unsigned)(event->xclient.data.l[0]) == mainDeleteWindow) {
+ /* non-k xdvi also evaluates closure, but we don't, since it's a function pointer
+ which isn't convertible to void * in ANSI C */
+ xdvi_exit(EXIT_SUCCESS);
+ }
+}
+#endif
+
+#ifdef TEST_SCROLLING
+#warning ========== compiling with TEST_SCROLLING ==========
+#endif
+
+
+/* for measuring distance from the ruler */
+int g_ruler_pos_x, g_ruler_pos_y;
+
+Boolean ignore_papersize_specials = False;
+
+#ifndef ALTFONT
+# define ALTFONT "cmr10"
+#endif
+
+#ifndef SHRINK
+# define SHRINK 8
+#endif
+
+#ifndef MFMODE
+# define MFMODE NULL
+#endif
+
+#undef MKTEXPK
+#define MKTEXPK MAKEPK
+
+#if defined(PS_GS) && !defined(GS_PATH)
+# define GS_PATH "gs"
+#endif
+
+#if A4
+# define DEFAULT_PAPER "a4"
+#else
+# define DEFAULT_PAPER "us"
+#endif
+
+/*
+ * Main application context, used for Xt event processing.
+ */
+XtAppContext app = NULL;
+
+static Dimension bwidth = 2;
+
+struct x_resources resource;
+
+struct program_globals globals;
+
+/* color of cursor */
+static XColor m_cursor_color;
+
+/* default magnifier dimensions */
+static struct mg_size_rec {
+ int w;
+ int h;
+} mg_size[] = {
+ {200, 150}, {400, 250}, {700, 500}, {1000, 800}, {1200, 1200}
+};
+
+size_t get_magglass_items(void) {
+ return XtNumber(mg_size);
+}
+
+int get_magglass_width(int idx) {
+ return mg_size[idx].w;
+}
+
+int get_magglass_height(int idx) {
+ return mg_size[idx].h;
+}
+
+struct WindowRec mane = { (Window) 0, 1, 0, 0, 0, 0, MAXDIM, 0, MAXDIM, 0 };
+
+/* currwin is temporary storage except for within redraw() */
+struct WindowRec currwin = { (Window) 0, 1, 0, 0, 0, 0, MAXDIM, 0, MAXDIM, 0 };
+
+/*
+ * Data for options processing.
+ */
+static const char SILENT[] = " "; /* flag value for usage() */
+
+static const char SUBST[] = "x"; /* another flag value */
+
+static const char USAGESTR_END_MARKER[] = "__USAGE_END_MARKER__"; /* end marker */
+
+static const char *SUBST_VAL[] = { "-mgs[n] <size>" };
+
+static XrmOptionDescRec options[] = {
+ {"-q", ".noInitFile", XrmoptionNoArg, (XPointer)"on" },
+ {"+q", ".noInitFile", XrmoptionNoArg, (XPointer)"off" },
+ {"-geometry", ".geometry", XrmoptionSepArg, (XPointer)NULL },
+#ifdef MOTIF
+ /* to make `-font' and `-fn' options work, make them an alias for `fontList' */
+ { "-font", "*fontList", XrmoptionSepArg, (XPointer)NULL },
+ { "-fn", "*fontList", XrmoptionSepArg, (XPointer)NULL },
+#endif
+ {"-s", ".shrinkFactor", XrmoptionSepArg, (XPointer)NULL },
+#ifndef VMS
+ {"-S", ".densityPercent", XrmoptionSepArg, (XPointer)NULL },
+#endif
+ {"-density", ".densityPercent", XrmoptionSepArg, (XPointer)NULL },
+ {"-noomega", ".omega", XrmoptionNoArg, (XPointer)"off" },
+ {"+noomega", ".omega", XrmoptionNoArg, (XPointer)"on" },
+#if COLOR
+ {"-nocolor", ".color", XrmoptionNoArg, (XPointer)"off" },
+ {"+nocolor", ".color", XrmoptionNoArg, (XPointer)"on" },
+#endif
+#ifdef GREY
+ {"-nogrey", ".grey", XrmoptionNoArg, (XPointer)"off" },
+ {"+nogrey", ".grey", XrmoptionNoArg, (XPointer)"on" },
+ {"-gamma", ".gamma", XrmoptionSepArg, (XPointer)NULL },
+ {"-nomatchinverted",".matchInverted", XrmoptionNoArg, (XPointer)"off" },
+ {"+nomatchinverted",".matchInverted", XrmoptionNoArg, (XPointer)"on" },
+/* {"-invertedfactor", ".invertedFactor", XrmoptionSepArg, (XPointer)NULL }, */
+ {"-install", ".install", XrmoptionNoArg, (XPointer)"on" },
+ {"-noinstall", ".install", XrmoptionNoArg, (XPointer)"off" },
+#endif
+ {"-rulecolor", ".ruleColor", XrmoptionSepArg, (XPointer)NULL },
+ {"-p", ".pixelsPerInch", XrmoptionSepArg, (XPointer)NULL },
+ {"-margins", ".Margin", XrmoptionSepArg, (XPointer)NULL },
+ {"-sidemargin", ".sideMargin", XrmoptionSepArg, (XPointer)NULL },
+ {"-topmargin", ".topMargin", XrmoptionSepArg, (XPointer)NULL },
+ {"-offsets", ".Offset", XrmoptionSepArg, (XPointer)NULL },
+ {"-xoffset", ".xOffset", XrmoptionSepArg, (XPointer)NULL },
+ {"-yoffset", ".yOffset", XrmoptionSepArg, (XPointer)NULL },
+ {"-paper", ".paper", XrmoptionSepArg, (XPointer)NULL },
+ {"-altfont", ".altFont", XrmoptionSepArg, (XPointer)NULL },
+#ifdef MKTEXPK
+ {"-nomakepk", ".makePk", XrmoptionNoArg, (XPointer)"off" },
+ {"+nomakepk", ".makePk", XrmoptionNoArg, (XPointer)"on" },
+#endif
+ {"-mfmode", ".mfMode", XrmoptionSepArg, (XPointer)NULL },
+ {"-editor", ".editor", XrmoptionSepArg, (XPointer)NULL },
+#ifdef T1LIB
+ {"-not1lib", ".t1lib", XrmoptionNoArg, (XPointer)"off" },
+ {"+not1lib", ".t1lib", XrmoptionNoArg, (XPointer)"on" },
+#endif
+ {"-sourceposition", ".sourcePosition", XrmoptionSepArg, (XPointer)NULL },
+ {"-findstring", ".findString", XrmoptionSepArg, (XPointer)NULL },
+ {"-text-encoding", ".textEncoding", XrmoptionSepArg, (XPointer)NULL },
+ {"-unique", ".unique", XrmoptionNoArg, (XPointer)"on" },
+ {"+unique", ".unique", XrmoptionNoArg, (XPointer)"off" },
+ {"-nofork", ".fork", XrmoptionNoArg, (XPointer)"off" },
+ {"+nofork", ".fork", XrmoptionNoArg, (XPointer)"on" },
+#ifdef RGB_ANTI_ALIASING
+ {"-subpixels", ".subPixels", XrmoptionSepArg, (XPointer)NULL },
+#endif
+ {"-l", ".listFonts", XrmoptionNoArg, (XPointer)"on" },
+ {"+l", ".listFonts", XrmoptionNoArg, (XPointer)"off" },
+ {"-watchfile", ".watchFile", XrmoptionSepArg, (XPointer)NULL },
+ {"-expertmode", ".expertMode", XrmoptionSepArg, (XPointer)NULL },
+ {"-expert", ".expert", XrmoptionNoArg, (XPointer)"on" },
+ {"+expert", ".expert", XrmoptionNoArg, (XPointer)"off" },
+ {"+statusline", ".statusline", XrmoptionNoArg, (XPointer)"off" },
+ {"-statusline", ".statusline", XrmoptionNoArg, (XPointer)"on" },
+ {"+useTeXpages", ".useTeXPages", XrmoptionNoArg, (XPointer)"off" },
+ {"-useTeXpages", ".useTeXPages", XrmoptionNoArg, (XPointer)"on" },
+ {"-mgs", ".magnifierSize1", XrmoptionSepArg, (XPointer)NULL },
+ {"-mgs1", ".magnifierSize1", XrmoptionSepArg, (XPointer)NULL },
+ {"-mgs2", ".magnifierSize2", XrmoptionSepArg, (XPointer)NULL },
+ {"-mgs3", ".magnifierSize3", XrmoptionSepArg, (XPointer)NULL },
+ {"-mgs4", ".magnifierSize4", XrmoptionSepArg, (XPointer)NULL },
+ {"-mgs5", ".magnifierSize5", XrmoptionSepArg, (XPointer)NULL },
+ {"-warnspecials", ".warnSpecials", XrmoptionNoArg, (XPointer)"on" },
+ {"+warnspecials", ".warnSpecials", XrmoptionNoArg, (XPointer)"off" },
+ {"-hush", ".Hush", XrmoptionNoArg, (XPointer)"on" },
+ {"+hush", ".Hush", XrmoptionNoArg, (XPointer)"off" },
+ {"-hushchars", ".hushLostChars", XrmoptionNoArg, (XPointer)"on" },
+ {"+hushchars", ".hushLostChars", XrmoptionNoArg, (XPointer)"off" },
+ {"-hushchecksums", ".hushChecksums", XrmoptionNoArg, (XPointer)"on" },
+ {"+hushchecksums", ".hushChecksums", XrmoptionNoArg, (XPointer)"off" },
+ {"-hushstdout", ".hushStdout", XrmoptionNoArg, (XPointer)"on" },
+ {"+hushstdout", ".hushStdout", XrmoptionNoArg, (XPointer)"off" },
+ {"-safer", ".safer", XrmoptionNoArg, (XPointer)"on" },
+ {"+safer", ".safer", XrmoptionNoArg, (XPointer)"off" },
+ {"-fg", ".foreground", XrmoptionSepArg, (XPointer)NULL },
+ {"-foreground", ".foreground", XrmoptionSepArg, (XPointer)NULL },
+ {"-bg", ".background", XrmoptionSepArg, (XPointer)NULL },
+ {"-background", ".background", XrmoptionSepArg, (XPointer)NULL },
+ {"-hl", ".highlight", XrmoptionSepArg, (XPointer)NULL },
+ {"-cr", ".cursorColor", XrmoptionSepArg, (XPointer)NULL },
+ {"-icongeometry", ".iconGeometry", XrmoptionSepArg, (XPointer)NULL },
+ {"-keep", ".keepPosition", XrmoptionNoArg, (XPointer)"on" },
+ {"+keep", ".keepPosition", XrmoptionNoArg, (XPointer)"off" },
+ {"-copy", ".copy", XrmoptionNoArg, (XPointer)"on" },
+ {"+copy", ".copy", XrmoptionNoArg, (XPointer)"off" },
+ {"-thorough", ".thorough", XrmoptionNoArg, (XPointer)"on" },
+ {"+thorough", ".thorough", XrmoptionNoArg, (XPointer)"off" },
+ {"-fullscreen", ".fullscreen", XrmoptionNoArg, (XPointer)"on" },
+ {"+fullscreen", ".fullscreen", XrmoptionNoArg, (XPointer)"off" },
+ {"-pause", ".pause", XrmoptionNoArg, (XPointer)"on" },
+ {"+pause", ".pause", XrmoptionNoArg, (XPointer)"off" },
+ {"-pausespecial", ".pauseSpecial", XrmoptionSepArg, (XPointer)NULL },
+ {"-wheelunit", ".wheelUnit", XrmoptionSepArg, (XPointer)NULL },
+ {"-mousemode", ".mouseMode", XrmoptionSepArg, (XPointer)NULL },
+#ifdef PS
+ {"-postscript", ".postscript", XrmoptionSepArg, (XPointer)NULL },
+ {"-allowshell", ".allowShell", XrmoptionNoArg, (XPointer)"on" },
+ {"+allowshell", ".allowShell", XrmoptionNoArg, (XPointer)"off" },
+# ifdef PS_DPS
+ {"-nodps", ".dps", XrmoptionNoArg, (XPointer)"off" },
+ {"+nodps", ".dps", XrmoptionNoArg, (XPointer)"on" },
+# endif
+# ifdef PS_NEWS
+ {"-nonews", ".news", XrmoptionNoArg, (XPointer)"off" },
+ {"+nonews", ".news", XrmoptionNoArg, (XPointer)"on" },
+# endif
+# ifdef PS_GS
+ {"-noghostscript", ".ghostscript", XrmoptionNoArg, (XPointer)"off" },
+ {"+noghostscript", ".ghostscript", XrmoptionNoArg, (XPointer)"on" },
+ {"-nogssafer", ".gsSafer", XrmoptionNoArg, (XPointer)"off" },
+ {"+nogssafer", ".gsSafer", XrmoptionNoArg, (XPointer)"on" },
+ {"-gsalpha", ".gsAlpha", XrmoptionNoArg, (XPointer)"on" },
+ {"+gsalpha", ".gsAlpha", XrmoptionNoArg, (XPointer)"off" },
+ {"-interpreter", ".interpreter", XrmoptionSepArg, (XPointer)NULL },
+ {"-gspalette", ".palette", XrmoptionSepArg, (XPointer)NULL },
+# endif
+# ifdef MAGICK
+ {"-magick", ".ImageMagick", XrmoptionNoArg, (XPointer)"on" },
+ {"+magick", ".ImageMagick", XrmoptionNoArg, (XPointer)"off" },
+ {"-magick_cache", ".MagickCache", XrmoptionSepArg, (XPointer)NULL },
+# endif
+#endif /* PS */
+ {"-noscan", ".prescan", XrmoptionNoArg, (XPointer)"off" },
+ {"+noscan", ".prescan", XrmoptionNoArg, (XPointer)"on" },
+ {"-notempfile", ".tempFile", XrmoptionNoArg, (XPointer)"off" },
+ {"+notempfile", ".tempFile", XrmoptionNoArg, (XPointer)"on" },
+ {"-dvipspath", ".dvipsPath", XrmoptionSepArg, (XPointer)NULL },
+ {"-ps2pdfpath", ".ps2pdfPath", XrmoptionSepArg, (XPointer)NULL },
+ {"-debug", ".debugLevel", XrmoptionSepArg, (XPointer)NULL },
+ {"-linkstyle", ".linkStyle", XrmoptionSepArg, (XPointer)NULL },
+ {"-linkcolor", ".linkColor", XrmoptionSepArg, (XPointer)NULL },
+ {"-visitedlinkcolor",".visitedLinkColor", XrmoptionSepArg, (XPointer)NULL },
+ {"-browser", ".wwwBrowser", XrmoptionSepArg, (XPointer)NULL },
+ {"-anchorposition", ".anchorPosition", XrmoptionSepArg, (XPointer)NULL },
+};
+
+
+#define offset(field) XtOffsetOf(struct x_resources, field)
+static int base_tick_length = 4;
+
+static char XtRBool3[] = "Bool3"; /* resource for Bool3 */
+
+static XtResource application_resources[] = {
+ {"regression", "Regression", XtRBoolean, sizeof(Boolean),
+ offset(regression), XtRString, "false"},
+ {"geometry", "Geometry", XtRString, sizeof(char *),
+ offset(geometry), XtRString, (XtPointer) NULL},
+ {"windowSize", "WindowSize", XtRString, sizeof(char *),
+ offset(windowsize), XtRString, (XtPointer) NULL},
+ {"rememberWindowSize", "RememberWindowSize", XtRBoolean, sizeof(Boolean),
+ offset(remember_windowsize), XtRString, "false"},
+ /* used to check whether app-defaults file is out of sync. Initialize
+ to a low default value (one before the resource was introduced) */
+ {"appDefaultsFileVersion", "AppDefaultsFileVersion", XtRInt, sizeof(int),
+ offset(app_defaults_fileversion), XtRImmediate, (XtPointer)20030302 },
+ {"shrinkFactor", "ShrinkFactor", XtRInt, sizeof(int),
+ offset(shrinkfactor), XtRImmediate, (XtPointer) SHRINK},
+ {"delayRulers", "DelayRulers", XtRBoolean, sizeof(Boolean),
+ offset(delay_rulers), XtRString, "true"},
+ {"useTeXPages", "UseTeXPages", XtRBoolean, sizeof(Boolean),
+ offset(use_tex_pages), XtRString, "false"},
+ {"densityPercent", "DensityPercent", XtRInt, sizeof(int),
+ offset(density), XtRString, "40"},
+ {"omega", "Omega", XtRBoolean, sizeof(Boolean),
+ offset(omega), XtRString, "true"},
+ {"mainTranslations", "MainTranslations", XtRString, sizeof(char *),
+ offset(main_translations), XtRString, (XtPointer) NULL},
+ {"wheelTranslations", "WheelTranslations", XtRString, sizeof(char *),
+ offset(wheel_translations), XtRString, (XtPointer) "<Btn4Down>:wheel(-0.2)\n<Btn5Down>:wheel(0.2)"},
+ {"wheelUnit", "WheelUnit", XtRInt, sizeof(int),
+ offset(wheel_unit), XtRImmediate, (XtPointer) 80},
+ {"mouseMode", "MouseMode", XtRInt, sizeof(int),
+ offset(mouse_mode), XtRImmediate, (XtPointer)MOUSE_MAGNIFIER_MODE},
+#ifdef GREY
+ {"gamma", "Gamma", XtRFloat, sizeof(float),
+ offset(gamma), XtRString, "1"},
+/* {"invertedFactor", "InvertedFactor", XtRFloat, sizeof(float), */
+/* offset(inverted_factor), XtRString, "3.0"}, */
+#endif
+ {"pixelsPerInch", "PixelsPerInch", XtRInt, sizeof(int),
+ offset(pixels_per_inch), XtRImmediate, (XtPointer) BDPI},
+ {"sideMargin", "Margin", XtRString, sizeof(char *),
+ offset(sidemargin), XtRString, (XtPointer) NULL},
+ {"tickLength", "TickLength", XtRInt, sizeof(int),
+ offset(tick_length), XtRInt, (XtPointer) & base_tick_length},
+ {"tickUnits", "TickUnits", XtRString, sizeof(char *),
+ offset(tick_units), XtRString, "mm"},
+ {"topMargin", "Margin", XtRString, sizeof(char *),
+ offset(topmargin), XtRString, (XtPointer) NULL},
+ {"xOffset", "Offset", XtRString, sizeof(char *),
+ offset(xoffset), XtRString, (XtPointer) NULL},
+ {"yOffset", "Offset", XtRString, sizeof(char *),
+ offset(yoffset), XtRString, (XtPointer) NULL},
+ {"useCurrentOffset", "UseCurrentOffset", XtRBoolean, sizeof(Boolean),
+ offset(use_current_offset), XtRString, "False" },
+ {"paper", "Paper", XtRString, sizeof(char *),
+ offset(paper), XtRString, (XtPointer) DEFAULT_PAPER},
+ {"paperLandscape", "PaperLandscape", XtRBoolean, sizeof(Boolean),
+ offset(paper_landscape), XtRString, "false"},
+ {"altFont", "AltFont", XtRString, sizeof(char *),
+ offset(alt_font), XtRString, (XtPointer) ALTFONT},
+ {"makePk", "MakePk", XtRBoolean, sizeof(Boolean),
+ offset(makepk), XtRString,
+#ifdef MAKE_TEX_PK_BY_DEFAULT
+ "true"
+#else
+ "false"
+#endif
+ },
+ {"mfMode", "MfMode", XtRString, sizeof(char *),
+ offset(mfmode), XtRString, MFMODE},
+ {"editor", "Editor", XtRString, sizeof(char *),
+ offset(editor), XtRString, (XtPointer) NULL},
+#ifdef T1LIB
+ {"t1lib", "T1lib", XtRBoolean, sizeof(Boolean),
+ offset(t1lib), XtRString, "true"},
+#endif
+ {"sourcePosition", "SourcePosition", XtRString, sizeof(char *),
+ offset(src_pos), XtRString, (XtPointer) NULL},
+ {"findString", "FindString", XtRString, sizeof(char *),
+ offset(find_string), XtRString, (XtPointer) NULL},
+ {"textEncoding", "TextEncoding", XtRString, sizeof(char *),
+ offset(text_encoding), XtRString, (XtPointer) NULL},
+ {"fork", "Fork", XtRBoolean, sizeof(Boolean),
+ offset(src_fork), XtRString, "true"},
+#ifdef RGB_ANTI_ALIASING
+ {"subPixels", "SubPixels", XtRString, sizeof(char *),
+ offset(sub_pixels), XtRString, "Unknown"},
+#endif
+ {"noFileArgUseHistory", "NoFileArgUseHistory", XtRBoolean, sizeof(Boolean),
+ offset(no_file_arg_use_history), XtRString, "true"},
+ {"fileHistory", "FileHistory", XtRString, sizeof(char *),
+ offset(file_history), XtRString, (XtPointer) NULL},
+ {"fileHistorySize", "FileHistorySize", XtRInt, sizeof(int),
+ offset(file_history_size), XtRImmediate, (XtPointer)20},
+ {"unique", "Unique", XtRBoolean, sizeof(Boolean),
+ offset(unique), XtRString, "false"},
+ {"listFonts", "ListFonts", XtRBoolean, sizeof(Boolean),
+ offset(list_fonts), XtRString, "false"},
+ {"reverseVideo", "ReverseVideo", XtRBoolean, sizeof(Boolean),
+ offset(reverse), XtRString, "false"},
+ {"warnSpecials", "WarnSpecials", XtRBoolean, sizeof(Boolean),
+ offset(warn_spec), XtRString, "false"},
+ {"hushLostChars", "Hush", XtRBoolean, sizeof(Boolean),
+ offset(hush_chars), XtRString, "false"},
+ {"hushChecksums", "Hush", XtRBoolean, sizeof(Boolean),
+ offset(hush_chk), XtRString, "false"},
+ {"hushStdout", "HushStdout", XtRBoolean, sizeof(Boolean),
+ offset(hush_stdout), XtRString, "false"},
+ {"safer", "Safer", XtRBoolean, sizeof(Boolean),
+ offset(safer), XtRString, "false"},
+#ifdef VMS
+ {"foreground", "Foreground", XtRString, sizeof(char *),
+ offset(fore_color), XtRString, (XtPointer) NULL},
+ {"background", "Background", XtRString, sizeof(char *),
+ offset(back_color), XtRString, (XtPointer) NULL},
+#endif
+ {"iconGeometry", "IconGeometry", XtRString, sizeof(char *),
+ offset(icon_geometry), XtRString, (XtPointer) NULL},
+ {"keepPosition", "KeepPosition", XtRBoolean, sizeof(Boolean),
+ offset(keep_flag), XtRString, "false"},
+#ifdef PS
+ {"postscript", "Postscript", XtRInt, sizeof(int),
+ offset(postscript), XtRImmediate, (XtPointer)1},
+ {"allowShell", "AllowShell", XtRBoolean, sizeof(Boolean),
+ offset(allow_shell), XtRString, "false"},
+# ifdef PS_DPS
+ {"dps", "DPS", XtRBoolean, sizeof(Boolean),
+ offset(useDPS), XtRString, "true"},
+# endif
+# ifdef PS_NEWS
+ {"news", "News", XtRBoolean, sizeof(Boolean),
+ offset(useNeWS), XtRString, "true"},
+# endif
+# ifdef PS_GS
+ {"ghostscript", "Ghostscript", XtRBoolean, sizeof(Boolean),
+ offset(useGS), XtRString, "true"},
+ {"gsSafer", "Safer", XtRBoolean, sizeof(Boolean),
+ offset(gs_safer), XtRString, "true"},
+ {"gsAlpha", "Alpha", XtRBoolean, sizeof(Boolean),
+ offset(gs_alpha), XtRString, "false"},
+ {"interpreter", "Interpreter", XtRString, sizeof(char *),
+ offset(gs_path), XtRString, (XtPointer) GS_PATH},
+ {"palette", "Palette", XtRString, sizeof(char *),
+ offset(gs_palette), XtRString, (XtPointer) "Color"},
+ {"gsTimeout", "GSTimeout", XtRInt, sizeof(int),
+ offset(gs_timeout), XtRImmediate, (XtPointer)3000},
+# endif /* PS_GS */
+# ifdef MAGICK
+ {"magick", "ImageMagick", XtRBoolean, sizeof(Boolean),
+ offset(useMAGICK), XtRString, "true"},
+ {"magick_cache", "MagickCache", XtRString, sizeof(char *),
+ offset(magick_cache), XtRString, (XtPointer) NULL},
+# endif
+#endif /* PS */
+ {"prescan", "Prescan", XtRBoolean, sizeof(Boolean),
+ offset(prescan), XtRString, "true"},
+ {"tempFile", "TempFile", XtRBoolean, sizeof(Boolean),
+ offset(use_temp_fp), XtRString, "true"},
+ {"copy", "Copy", XtRBoolean, sizeof(Boolean),
+ offset(copy), XtRString, "false"},
+ {"thorough", "Thorough", XtRBoolean, sizeof(Boolean),
+ offset(thorough), XtRString, "false"},
+ {"fullscreen", "Fullscreen", XtRBoolean, sizeof(Boolean),
+ offset(fullscreen), XtRString, "false"},
+ {"pause", "Pause", XtRBoolean, sizeof(Boolean),
+ offset(pause), XtRString, "false"},
+ {"pauseSpecial", "PauseSpecial", XtRString, sizeof(char *),
+ offset(pause_special), XtRString, (XtPointer)"xdvi:pause"},
+ {"debugLevel", "DebugLevel", XtRString, sizeof(char *),
+ offset(debug_arg), XtRString, (XtPointer) NULL},
+ {"menuTranslations", "MenuTranslations", XtRString, sizeof(char *),
+ offset(menu_translations), XtRString, (XtPointer) default_menu_config},
+ {"watchFile", "WatchFile", XtRFloat, sizeof(float),
+ offset(watch_file), XtRString, "0"},
+ {"expert", "Expert", XtRBoolean, sizeof(Boolean),
+ offset(expert), XtRString, (XtPointer) NULL},
+ {"expertMode", "ExpertMode", XtRInt, sizeof(int),
+ offset(expert_mode), XtRImmediate, (XtPointer)31 /* everything on */ },
+#ifndef MOTIF
+ {"buttonSideSpacing", "ButtonSpacing", XtRDimension, sizeof(Dimension),
+ offset(btn_side_spacing), XtRImmediate, (XtPointer) 8},
+ {"buttonTopSpacing", "ButtonSpacing", XtRDimension, sizeof(Dimension),
+ offset(btn_top_spacing), XtRImmediate, (XtPointer) 16},
+ {"buttonBetweenSpacing", "ButtonSpacing", XtRDimension, sizeof(Dimension),
+ offset(btn_between_spacing), XtRImmediate, (XtPointer) 8},
+ /* ignored; only for backwards compatibility */
+ {"buttonBetweenExtra", "ButtonSpacing", XtRDimension, sizeof(Dimension),
+ offset(btn_between_extra), XtRImmediate, (XtPointer)0},
+ {"buttonBorderWidth", "BorderWidth", XtRDimension, sizeof(Dimension),
+ offset(btn_border_width), XtRImmediate, (XtPointer) 1},
+#endif /* MOTIF */
+ {"statusline", "Statusline", XtRBoolean, sizeof(Boolean),
+ offset(statusline), XtRString, (XtPointer) NULL},
+#ifdef MOTIF
+ {"toolbarTranslations", "ToolbarTranslations", XtRString, sizeof(char *),
+ offset(toolbar_translations), XtRString, (XtPointer) default_toolbar_translations},
+ {"toolbarPixmapFile", "ToolbarPixmapFile", XtRString, sizeof(char *),
+ offset(toolbar_pixmap_file), XtRString, (XtPointer) "toolbar.xpm"},
+ {"toolbarButtonsRaised", "ToolbarButtonsRaised", XtRBoolean, sizeof(Boolean),
+ offset(toolbar_buttons_raised), XtRString, "True"},
+ {"tooltipsInStatusline", "TooltipsInStatusline", XtRBoolean, sizeof(Boolean),
+ offset(tooltips_in_statusline), XtRString, "True"},
+ {"showTooltips", "ShowTooltips", XtRBoolean, sizeof(Boolean),
+ offset(show_tooltips), XtRString, "True"},
+#endif /* MOTIF */
+ {"pageListHighlightCurrent", "PageListHighlightCurrent", XtRBoolean, sizeof(Boolean),
+ offset(pagelist_highlight_current), XtRString, "True"},
+ {"pageListWidth", "PageListWidth", XtRDimension, sizeof(Dimension),
+ offset(pagelist_width), XtRImmediate, (XtPointer) 80},
+ {"magnifierSize1", "MagnifierSize", XtRString, sizeof(char *),
+ offset(mg_arg[0]), XtRString, (XtPointer) NULL},
+ {"magnifierSize2", "MagnifierSize", XtRString, sizeof(char *),
+ offset(mg_arg[1]), XtRString, (XtPointer) NULL},
+ {"magnifierSize3", "MagnifierSize", XtRString, sizeof(char *),
+ offset(mg_arg[2]), XtRString, (XtPointer) NULL},
+ {"magnifierSize4", "MagnifierSize", XtRString, sizeof(char *),
+ offset(mg_arg[3]), XtRString, (XtPointer) NULL},
+ {"magnifierSize5", "MagnifierSize", XtRString, sizeof(char *),
+ offset(mg_arg[4]), XtRString, (XtPointer) NULL},
+#if COLOR
+ {"color", "Color", XtRBoolean, sizeof(Boolean),
+ offset(use_color), XtRString, "true"},
+#endif /* COLOR */
+ {"dvipsPath", "DvipsPath", XtRString, sizeof(char *),
+ offset(dvips_path), XtRString, (XtPointer)DEFAULT_DVIPS_PATH},
+ {"ps2pdfPath", "Ps2PdfPath", XtRString, sizeof(char *),
+ offset(ps2pdf_path), XtRString, (XtPointer)DEFAULT_PS2PDF_PATH},
+ {"dvipsHangTime", "DvipsHangTime", XtRInt, sizeof(int),
+ offset(dvips_hang), XtRImmediate, (XtPointer) -1500},
+ {"dvipsFailHangTime", "DvipsFailHangTime", XtRInt, sizeof(int),
+ offset(dvips_fail_hang), XtRImmediate, (XtPointer) -5000},
+ {"dvipsPrinterString", "DvipsPrinterString", XtRString, sizeof(char *),
+ offset(dvips_printer_str), XtRString, (XtPointer)NULL},
+ {"dvipsOptionsString", "DvipsOptionsString", XtRString, sizeof(char *),
+ offset(dvips_options_str), XtRString, (XtPointer)NULL},
+ {"defaultSavingFormat", "DefaultSavingFormat", XtRInt, sizeof(int),
+ offset(default_saving_format), XtRImmediate, (XtPointer)0},
+ {"defaultPrintingTarget", "DefaultPrintingTarget", XtRInt, sizeof(int),
+ offset(default_printing_target), XtRImmediate, (XtPointer)1},
+#ifdef GREY
+ {"grey", "Grey", XtRBoolean, sizeof(Boolean),
+ offset(use_grey), XtRString, "true"},
+ {"install", "Install", XtRBool3, sizeof(Bool3),
+ offset(install), XtRString, "maybe"},
+#endif /* GREY */
+ {"matchInverted", "MatchInverted", XtRBoolean, sizeof(Boolean),
+ offset(match_highlight_inverted), XtRString, "true"},
+ {"ruleColor", "RuleColor", XtRPixel, sizeof(Pixel),
+ offset(rule_pixel), XtRPixel, (XtPointer) &resource.rule_pixel},
+ {"ruleColor", "RuleColor", XtRString, sizeof(char *),
+ offset(rule_color), XtRString, (XtPointer) NULL},
+ /* linkStyle: style for presenting links:
+ link_style is a bitsmask `xy' with x = color, y = underline, viz.:
+ 0: no highlighting at all
+ 1: underline with linkColor
+ 2: no underlining, text with linkColor
+ 3: underlining and text with linkColor
+ */
+ {"linkStyle", "LinkStyle", XtRInt, sizeof(int),
+ offset(link_style), XtRImmediate, (XtPointer) 3},
+ {"linkColor", "LinkColor", XtRString, sizeof(char *),
+ offset(link_color), XtRString, (XtPointer)LINK_COLOR_FALLBACK},
+ {"visitedLinkColor", "VisitedLinkColor", XtRString, sizeof(char *),
+ offset(visited_link_color), XtRString, (XtPointer)VISITED_LINK_COLOR_FALLBACK},
+ {"wwwBrowser", "WWWBrowser", XtRString, sizeof(char *),
+ offset(browser), XtRString, (XtPointer) NULL},
+#ifdef MOTIF
+ {"prefsBrowserList", "PrefsBrowserList", XtRString, sizeof(char *),
+ offset(prefs_browser_list), XtRString, (XtPointer)Xdvi_PREFS_BROWSER_DEFAULTS },
+ {"prefsEditorList", "PrefsEditorList", XtRString, sizeof(char *),
+ offset(prefs_editor_list), XtRString, (XtPointer)Xdvi_PREFS_EDITOR_DEFAULTS },
+#endif
+ /* defaults for unknown mime types */
+ {"unknownMimeSuffix", "UnknownMimeSuffix", XtRString, sizeof(char *),
+ offset(unknown_mime_suffix), XtRString, "application/x-unknown"},
+ {"noMimeSuffix", "NoMimeSuffix", XtRString, sizeof(char *),
+ offset(no_mime_suffix), XtRString, "application/x-unknown"},
+ {"anchorPosition", "AnchorPosition", XtRString, sizeof(char *),
+ offset(anchor_pos), XtRString, (XtPointer) NULL},
+ /* bitmask for current search window settings; only used internally! */
+ {"searchWindowDefaults", "SearchWindowDefaults", XtRInt, sizeof(int),
+ offset(search_window_defaults), XtRImmediate, (XtPointer)0},
+ /* resources for help text */
+ {"helpGeneral", "HelpGeneral", XtRString, sizeof(char *),
+ offset(help_general), XtRString, NULL},
+ {"helpHypertex", "HelpHypertex", XtRString, sizeof(char *),
+ offset(help_hypertex), XtRString, NULL},
+ {"helpOthercommands", "HelpOthercommands", XtRString, sizeof(char *),
+ offset(help_othercommands), XtRString, NULL},
+ {"helpMarking", "HelpMarking", XtRString, sizeof(char *),
+ offset(help_marking), XtRString, NULL},
+ {"helpPagemotion", "HelpPagemotion", XtRString, sizeof(char *),
+ offset(help_pagemotion), XtRString, NULL},
+ {"helpMousebuttons", "HelpMousebuttons", XtRString, sizeof(char *),
+ offset(help_mousebuttons), XtRString, NULL},
+ {"helpModes", "HelpModes", XtRString, sizeof(char *),
+ offset(help_modes), XtRString, NULL},
+ {"helpSearch", "HelpSearch", XtRString, sizeof(char *),
+ offset(help_search), XtRString, NULL},
+ {"helpSourcespecials", "HelpSoucespecials", XtRString, sizeof(char *),
+ offset(help_sourcespecials), XtRString, NULL},
+#ifdef GREY
+ {"pageHistorySize", "PageHistorySize", XtRInt, sizeof(int),
+ offset(page_history_size), XtRImmediate, (XtPointer)1000},
+};
+
+/* get these before setting `application_resources' */
+static XtResource xdvirc_resources[] = {
+ {"noInitFile", "NoInitFile", XtRBoolean, sizeof(Boolean),
+ offset(no_init_file), XtRString, "false"},
+};
+
+static XtResource app_pixel_resources[] = { /* get these later */
+#endif /* GREY */
+ {"foreground", "Foreground", XtRPixel, sizeof(Pixel),
+ offset(fore_Pixel), XtRString, XtDefaultForeground},
+ {"background", "Background", XtRPixel, sizeof(Pixel),
+ offset(back_Pixel), XtRString, XtDefaultBackground},
+/* {"borderColor", "BorderColor", XtRPixel, sizeof(Pixel), */
+/* offset(brdr_Pixel), XtRPixel, (XtPointer) &resource.fore_Pixel}, */
+ {"highlight", "Highlight", XtRPixel, sizeof(Pixel),
+ offset(hl_Pixel), XtRPixel, (XtPointer) &resource.fore_Pixel},
+ {"cursorColor", "CursorColor", XtRPixel, sizeof(Pixel),
+ offset(cr_Pixel), XtRImmediate, (XtPointer)ULONG_MAX},
+};
+#undef offset
+
+/* Here, list usage values for options that have `XrmoptionSepArg' set.
+ TODO: what does the `^' stand for?
+ */
+static const char *usagestr[] = {
+ /* geometry */ SILENT,
+#ifdef MOTIF
+ /* font */ SILENT,
+ /* f */ SILENT,
+#endif
+ /* shrinkFactor */ "shrink",
+#ifndef VMS
+ /* S */ "density",
+ /* density */ SILENT,
+#else
+ /* density */ "density",
+#endif
+#ifdef GREY
+ /* gamma */ "float",
+#endif
+ /* rulecolor */ "color",
+ /* p */ "pixels",
+ /* margins */ "dimen",
+ /* sidemargin */ "dimen",
+ /* topmargin */ "dimen",
+ /* offsets */ "dimen",
+ /* xoffset */ "dimen",
+ /* yoffset */ "dimen",
+ /* paper */ "papertype",
+ /* altfont */ "font",
+ /* mfmode */ "mode-def",
+ /* editor */ "editor",
+ /* sourceposition */ "linenumber[ ]*filename",
+ /* findstring */ "string",
+ /* textencoding */ "charset",
+#ifdef RGB_ANTI_ALIASING
+ /* subpixels */ "{rgb,bgr}[ i1 i2 i3]",
+#endif
+ /* rv */ "^-l", "-rv",
+ /* watchfile */ "secs",
+ /* expertmode */ "flag",
+ /* mgs */ SUBST,
+ /* mgs1 */ SILENT,
+ /* mgs2 */ SILENT,
+ /* mgs3 */ SILENT,
+ /* mgs4 */ SILENT,
+ /* mgs5 */ SILENT,
+ /* fg */ "color",
+ /* foreground */ SILENT,
+ /* bg */ "color",
+ /* background */ SILENT,
+ /* hl */ "color",
+ /* cr */ "color",
+#ifndef VMS
+ /* display */ "^-cr", "-display <host:display>",
+#else
+ /* display */ "^-cr", "-display <host::display>",
+#endif
+ /* geometry */ "^-cr", "-geometry <geometry>",
+ /* icongeometry */ "geometry",
+ /* iconic */ "^-icongeometry", "-iconic",
+ /* font */ "^-icongeometry", "-font <font>",
+ /* pausespecial */ "string",
+ /* wheelunit */ "pixels",
+ /* mousemode */ "0|1|2",
+#ifdef PS
+ /* postscript */ "0|1|2",
+# ifdef PS_GS
+ /* interpreter */ "path",
+ /* gspalette */ "monochrome|grayscale|color",
+# endif
+# ifdef MAGICK
+ /* magick_cache */ "size[k|K|m|M|g|G]",
+# endif
+#endif
+ /* dvipspath */ "path",
+ /* ps2pdfpath */ "path",
+ /* debug */ "bitmask|string[,string ...]",
+ /* linkstyle */ "0|1|2|3",
+ /* linkcolor */ "color",
+ /* visitedlinkcolor */ "color",
+ /* browser */ "WWWbrowser",
+ /* anchorposition */ "anchor",
+ /* [end marker] */ USAGESTR_END_MARKER
+};
+
+#ifndef MOTIF
+
+# ifdef NOQUERY
+# define drawWidgetClass widgetClass
+# else
+
+static XtGeometryResult
+QueryGeometry(Widget w,
+ XtWidgetGeometry *constraints,
+ XtWidgetGeometry *reply)
+{
+ UNUSED(w);
+ UNUSED(constraints);
+ reply->request_mode = CWWidth | CWHeight;
+ reply->width = globals.page.w;
+ reply->height = globals.page.h + global_statusline_h;
+
+ return XtGeometryAlmost;
+}
+
+# include <X11/IntrinsicP.h>
+# include <X11/CoreP.h>
+
+/* if the following gives you trouble, just compile with -DNOQUERY */
+static WidgetClassRec drawingWidgetClass = {
+ {
+ /* superclass */ &widgetClassRec,
+ /* class_name */ "Draw",
+ /* widget_size */ sizeof(WidgetRec),
+ /* class_initialize */ NULL,
+ /* class_part_initialize */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ NULL,
+ /* initialize_hook */ NULL,
+ /* realize */ XtInheritRealize,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ FALSE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterleave */ FALSE,
+ /* visible_interest */ FALSE,
+ /* destroy */ NULL,
+ /* resize */ XtInheritResize,
+ /* expose */ XtInheritExpose,
+ /* set_values */ NULL,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ XtInheritAcceptFocus,
+ /* version */ XtVersion,
+ /* callback_offsets */ NULL,
+ /* tm_table */ XtInheritTranslations,
+ /* query_geometry */ QueryGeometry,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ }
+};
+
+# define drawWidgetClass &drawingWidgetClass
+
+# endif /* NOQUERY */
+#endif /* not MOTIF */
+
+static int
+compare_strings(const void *s, const void *t)
+{
+ const char **ss = (const char**)s;
+ const char **tt = (const char**)t;
+
+ return memicmp(*ss, *tt, strlen(*tt) + 1); /* also check for final 0 */
+}
+
+static void
+usage(int exitval)
+{
+ XrmOptionDescRec *opt;
+ const char **usageptr = usagestr;
+ const char **sv = SUBST_VAL;
+ const char *str1;
+ const char *str2;
+ const char *sorted_options[XtNumber(options)];
+ char buf[256];
+ char *s;
+ int col, n;
+ size_t nopt = 0, k;
+
+ for (opt = options; opt < options + XtNumber(options); ++opt) {
+ str1 = opt->option;
+ if (*str1 != '-')
+ continue;
+
+ ASSERT(*usageptr != USAGESTR_END_MARKER, "Too few elements in usageptr[]");
+
+ str2 = NULL;
+ if (opt->argKind != XrmoptionNoArg) {
+ str2 = *usageptr++;
+ if (str2 == SILENT)
+ continue;
+ if (str2 == SUBST) {
+ str1 = *sv++;
+ str2 = NULL;
+ }
+ }
+#if 0
+ fprintf(stderr, "str1: %s, str2: %s\n", str1, str2);
+#endif
+ for (;;) {
+ if (str2 == NULL)
+ sprintf(buf, "[%.80s]", str1);
+ else
+ sprintf(buf, "[%.80s <%.80s>]", str1, str2);
+
+/* fprintf(stderr, "number of options: %d; len of usagestr: %d\n", */
+/* XtNumber(options), XtNumber(usagestr)); */
+ ASSERT(nopt < XtNumber(options), "index out of range");
+/* fprintf(stderr, "sorted: %d=%s\n", nopt, buf); */
+ sorted_options[nopt++] = xstrdup(buf);
+
+ if (**usageptr != '^' || strcmp(*usageptr + 1, opt->option) != 0)
+ break;
+ ++usageptr;
+ str1 = *usageptr++;
+ str2 = NULL;
+ }
+ }
+
+ ASSERT(*usageptr == USAGESTR_END_MARKER, "Too many elements in usageptr[]");
+
+/* fprintf(stderr, "elems in sorted options: %d\n", nopt); */
+ qsort((void*)sorted_options,
+ nopt,
+ sizeof(sorted_options[0]),
+ compare_strings);
+
+ s = xstrdup("Usage: ");
+ s = xstrcat(s, XDVI_PROGNAME); /* use `xdvi' here, not `xdvik' or `xdvi-xaw.bin' or ... */
+ s = xstrcat(s, " [+[<page>]]");
+
+ col = strlen(s);
+ fputs(s, stdout);
+
+ for (k = 0; k < nopt; ++k) {
+ n = strlen(sorted_options[k]);
+ if (col + n < 80)
+ putc(' ', stdout);
+ else {
+ fputs("\n\t", stdout);
+ col = 8 - 1;
+ }
+ fputs(sorted_options[k], stdout);
+ col += n + 1;
+ }
+
+ /* put this in an extra line, to emphasize that it must come last */
+ fputs("\n\t[dvi_file]\n", stdout);
+
+ xdvi_exit(exitval);
+}
+
+int
+atopix(const char *arg, Boolean allow_minus)
+{
+ int len = strlen(arg);
+ const char *arg_end = arg;
+ char tmp[11];
+ double factor;
+
+ if (allow_minus && *arg_end == '-')
+ ++arg_end;
+ while ((*arg_end >= '0' && *arg_end <= '9') || *arg_end == '.')
+ if (arg_end >= arg + XtNumber(tmp) - 1)
+ return 0;
+ else
+ ++arg_end;
+ memcpy(tmp, arg, arg_end - arg);
+ tmp[arg_end - arg] = '\0';
+
+#if A4
+ factor = 1.0 / 2.54; /* cm */
+#else
+ factor = 1.0; /* inches */
+#endif
+ if (len > 2)
+ switch (arg[len - 2] << 8 | arg[len - 1]) {
+#if A4
+ case 'i' << 8 | 'n':
+ factor = 1.0;
+ break;
+#else
+ case 'c' << 8 | 'm':
+ factor = 1.0 / 2.54;
+ break;
+#endif
+ case 'm' << 8 | 'm':
+ factor = 1.0 / 25.4;
+ break;
+ case 'p' << 8 | 't':
+ factor = 1.0 / 72.27;
+ break;
+ case 'p' << 8 | 'c':
+ factor = 12.0 / 72.27;
+ break;
+ case 'b' << 8 | 'p':
+ factor = 1.0 / 72.0;
+ break;
+ case 'd' << 8 | 'd':
+ factor = 1238.0 / 1157.0 / 72.27;
+ break;
+ case 'c' << 8 | 'c':
+ factor = 12 * 1238.0 / 1157.0 / 72.27;
+ break;
+ case 's' << 8 | 'p':
+ factor = 1.0 / 72.27 / 65536;
+ break;
+ }
+
+ return factor * atof(tmp) * resource.pixels_per_inch + 0.5;
+}
+
+#if CHECK_APP_FILEVERSION
+static void
+check_app_defaults_fileversion(void)
+{
+ /* update this when new essential resources are introduced */
+ static const int required_version = 20030303;
+
+ if (resource.app_defaults_fileversion < required_version) {
+ const char *filename = kpse_find_file("XDvi", kpse_program_text_format, 0);
+ if (filename == NULL)
+ filename = "XDvi";
+
+ fprintf(stderr, "filename: %d\n", resource.app_defaults_fileversion);
+ popup_message(globals.widgets.top_level,
+ MSG_WARN,
+ NULL,
+ "Your application defaults file `%s' is outdated. "
+ "This version of xdvi requires a file "
+ "with date >= %d. Your file is older, or doesn't have a date.\n"
+ "Please obtain a new version of the file `XDvi', e.g. from:\n"
+ "http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/xdvi/xdvik/texk/xdvik/texmf/\n"
+ "and copy it to a directory in your $XDVIINPUTS path.",
+ filename, required_version);
+ }
+}
+#endif
+
+
+static void
+warn_about_prerelease_versions(void)
+{
+ int unstable_version = 0;
+ if (strstr(XDVI_VERSION_INFO, "-cvs") != NULL)
+ unstable_version = 1;
+ else if (strstr(XDVI_VERSION_INFO, "-beta") != NULL)
+ unstable_version = 2;
+
+ if (unstable_version > 0) {
+ printf("\n**********************************************************************\n");
+ printf("%s version %s,\n%s version.\n\n", XDVIK_PROGNAME, XDVI_VERSION_INFO,
+ unstable_version == 1 ? "an unstable development" : "a beta testing");
+ printf("Want a stable version instead?\n"
+ " -> please visit one of:\n"
+ " http://xdvi.sourceforge.net/cvs-upgrade.html\n"
+ " http://sourceforge.net/project/showfiles.php?group_id=23164\n\n"
+ "Found a bug?\n"
+ " -> please report it to:\n"
+ " http://sourceforge.net/tracker/?group_id=23164&atid=377580\n\n"
+ "Thanks for your support!\n");
+ printf("**********************************************************************\n");
+ }
+}
+
+
+#ifdef GREY
+static Arg temp_args1[] = {
+ {XtNdepth, (XtArgVal) 0},
+ {XtNvisual, (XtArgVal) 0},
+ {XtNcolormap, (XtArgVal) 0},
+};
+
+/*
+ * Alternate routine to convert color name to Pixel (needed to substitute
+ * "black" or "white" for BlackPixelOfScreen, etc., since a different visual
+ * and colormap are in use).
+ */
+
+static Boolean
+XdviCvtStringToPixel(Display *dpy,
+ XrmValuePtr args, Cardinal *num_args,
+ XrmValuePtr fromVal, XrmValuePtr toVal,
+ XtPointer *closure_ret)
+{
+ XrmValue replacement_val;
+ Boolean default_is_fg;
+
+ if ((strcmp((String) fromVal->addr, XtDefaultForeground) == 0
+ && (default_is_fg = True, True))
+ || (strcmp((String) fromVal->addr, XtDefaultBackground) == 0
+ && ((default_is_fg = False), True))) {
+ replacement_val.size = sizeof(String);
+ replacement_val.addr = (default_is_fg == resource.reverse)
+ ? "white" : "black";
+ fromVal = &replacement_val;
+ }
+
+ return XtCvtStringToPixel(dpy, args, num_args, fromVal, toVal, closure_ret);
+}
+
+/*
+ * Convert string to yes/no/maybe. Adapted from the X toolkit.
+ */
+
+static Boolean
+XdviCvtStringToBool3(Display *dpy,
+ XrmValuePtr args, Cardinal *num_args,
+ XrmValuePtr fromVal, XrmValuePtr toVal,
+ XtPointer *closure_ret)
+{
+ String str = (String) fromVal->addr;
+ static Bool3 value;
+
+ UNUSED(args);
+ UNUSED(num_args);
+ UNUSED(closure_ret);
+
+ if (memicmp(str, "true", 5) == 0
+ || memicmp(str, "yes", 4) == 0
+ || memicmp(str, "on", 3) == 0 || memicmp(str, "1", 2) == 0)
+ value = True;
+
+ else if (memicmp(str, "false", 6) == 0
+ || memicmp(str, "no", 3) == 0
+ || memicmp(str, "off", 4) == 0 || memicmp(str, "0", 2) == 0)
+ value = False;
+
+ else if (memicmp(str, "maybe", 6) == 0)
+ value = Maybe;
+
+ else {
+ XtDisplayStringConversionWarning(dpy, str, XtRBoolean);
+ return False;
+ }
+
+ if (toVal->addr != NULL) {
+ if (toVal->size < sizeof(Bool3)) {
+ toVal->size = sizeof(Bool3);
+ return False;
+ }
+ *(Bool3 *) (toVal->addr) = value;
+ }
+ else
+ toVal->addr = (XPointer) & value;
+
+ toVal->size = sizeof(Bool3);
+ return True;
+}
+
+#endif
+
+
+/*
+ * Set the `sourceposition' propery of the window `w' to `source_str'.
+ * This is usually done in `client' mode to notify the instance of
+ * xdvi running in window `w' to start a forward search. After this,
+ * the client usually exits normally.
+ */
+static void
+set_sourceposition_property(const char *source_str, Window win)
+{
+ /* parse the special in order to expand the filename */
+ struct src_parsed_special data;
+ char *new_special = NULL;
+ char *expanded_filename = NULL;
+
+ data.filename_len = 0;
+ data.filename = NULL;
+
+ src_parse(source_str, strlen(source_str), &data);
+
+ if (data.filename_len == 0) {
+ /* can't give a GUI warning in `client' mode - just exit with error */
+ XDVI_FATAL((stderr,
+ "Filename missing in -sourceposition argument (%s)!",
+ source_str));
+ }
+
+ TRACE_CLIENT((stderr, "got data: line %d, col %d, file |%s|, len %lu\n",
+ data.line, data.col, data.filename, (unsigned long)data.filename_len));
+
+ /* expand -sourceposition argument if it contains a path component.
+ We don't use REALPATH here, because `tex -src' doesn't expand
+ symlinks either. Instead, use canonicalize_path() to expand
+ `../' and './' manually. */
+ if (strchr(data.filename, '/') != NULL
+ && (expanded_filename = expand_filename(data.filename, USE_CWD_PATH)) != NULL) {
+ char *tmp = canonicalize_path(expanded_filename);
+ free(data.filename);
+ free(expanded_filename);
+ expanded_filename = tmp;
+ }
+ else
+ expanded_filename = data.filename;
+
+ TRACE_CLIENT((stderr, "expanded1: |%s|\n", expanded_filename));
+
+ new_special = xmalloc(2 * LENGTH_OF_INT + 2 /* 2 for `:' and separating space */
+ + strlen(expanded_filename) + 1);
+ sprintf(new_special, "%d:%d %s", data.line, data.col, expanded_filename);
+ free(expanded_filename);
+
+ TRACE_CLIENT((stderr, "matched!"));
+ set_string_property(new_special, atom_src_goto(), win);
+ free(new_special);
+ set_string_property("", atom_raise(), win);
+}
+
+static void
+set_stringsearch_property(const char *str, Window win)
+{
+ set_string_property(str, atom_find_string(), win);
+ set_string_property("", atom_raise(), win);
+}
+
+
+
+/* Translation of valid paper types to dimensions,
+ which are used internally. The newline characters are a hack
+ to format the list neatly for error messages.
+ A* series measures are taken from
+ http://www.cl.cam.ac.uk/~mgk25/iso-paper.html
+*/
+static const char *paper_types[] = {
+ "us", "8.5x11in",
+ "letter", "8.5x11in", /* dvips compatibility */
+ "ledger", "17x11in", /* dvips compatibility */
+ "tabloid", "11x17in", /* dvips compatibility */
+ "usr", "11x8.5in",
+ "legal", "8.5x14in",
+ "legalr", "14x8.5in",
+ "foolscap", "13.5x17.0in", /* ??? */
+ "foolscapr", "17.0x13.5in",
+ "", "0",
+
+ /* ISO `A' formats, Portrait */
+ "a0", "841x1189mm",
+ "a1", "594x841mm",
+ "a2", "420x594mm",
+ "a3", "297x420mm",
+ "a4", "210x297mm",
+ "a5", "148x210mm",
+ "a6", "105x148mm",
+ "a7", "74x105mm",
+ "a8", "52x74mm",
+ "a9", "37x52mm",
+ "a10","26x37mm",
+ "", "0",
+
+ /* ISO `A' formats, Landscape */
+ "a0r", "1189x841mm",
+ "a1r", "841x594mm",
+ "a2r", "594x420mm",
+ "a3r", "420x297mm",
+ "a4r", "297x210mm",
+ "a5r", "210x148mm",
+ "a6r", "148x105mm",
+ "a7r", "105x74mm",
+ "a8r", "74x52mm",
+ "a9r", "52x37mm",
+ "a10r","37x26mm",
+ "", "0",
+
+ /* ISO `B' formats, Portrait */
+ "b0", "1000x1414mm",
+ "b1", "707x1000mm",
+ "b2", "500x707mm",
+ "b3", "353x500mm",
+ "b4", "250x353mm",
+ "b5", "176x250mm",
+ "b6", "125x176mm",
+ "b7", "88x125mm",
+ "b8", "62x88mm",
+ "b9", "44x62mm",
+ "b10","31x44mm",
+ "", "0",
+
+ /* ISO `B' formats, Landscape */
+ "b0r", "1414x1000mm",
+ "b1r", "1000x707mm",
+ "b2r", "707x500mm",
+ "b3r", "500x353mm",
+ "b4r", "353x250mm",
+ "b5r", "250x176mm",
+ "b6r", "176x125mm",
+ "b7r", "125x88mm",
+ "b8r", "88x62mm",
+ "b9r", "62x44mm",
+ "b10r","44x31mm",
+ "", "0",
+
+ /* ISO `C' formats, Portrait */
+ "c0", "917x1297mm",
+ "c1", "648x917mm",
+ "c2", "458x648mm",
+ "c3", "324x458mm",
+ "c4", "229x324mm",
+ "c5", "162x229mm",
+ "c6", "114x162mm",
+ "c7", "81x114mm",
+ "c8", "57x81mm",
+ "c9", "40x57mm",
+ "c10","28x40mm",
+ "", "0",
+
+ /* ISO `C' formats, Landscape */
+ "c0r", "1297x917mm",
+ "c1r", "917x648mm",
+ "c2r", "648x458mm",
+ "c3r", "458x324mm",
+ "c4r", "324x229mm",
+ "c5r", "229x162mm",
+ "c6r", "162x114mm",
+ "c7r", "114x81mm",
+ "c8r", "81x57mm",
+ "c9r", "57x40mm",
+ "c10r","40x28mm",
+};
+
+/* access methods for paper_types */
+const char **get_paper_types(void) {
+ return paper_types;
+}
+
+size_t get_paper_types_size(void) {
+ return XtNumber(paper_types);
+}
+
+/* Set the icon name and title name standard properties on `globals.widgets.top_level'.
+ * We use the basename of the DVI file (without the .dvi), so different xdvi
+ * invocations can be distinguished, yet do not use up too much real estate.
+ *
+ * This function returns freshly allocated memory in *icon_name and *title_name
+ * which the caller is responsible for free()ing again.
+ */
+void
+get_icon_and_title(const char *filename, char **icon_name, char **title_name)
+{
+ /* Use basename of DVI file for name in icon and title. */
+ const char *ptr;
+ char *ptr2;
+
+ /* SU 2000/12/16: added page number information */
+ const char *const title_name_fmt = "%s: %s (%d page%s)";
+
+ MYTRACE((stderr, "get_icon_and_title called with: |%s|", filename));
+
+ ptr = strrchr(filename, '/');
+ if (ptr != NULL)
+ ++ptr;
+ else {
+ ptr = filename;
+ }
+
+ /*
+ * Remove the `file:' prefix from the icon name; since some windowmanagers
+ * only display a prefix in window lists etc., it's more significant this
+ * way.
+ */
+
+ if (memcmp(ptr, "file:", 5) == 0) {
+ ptr += 5;
+ }
+ *icon_name = xstrdup(ptr);
+
+ MYTRACE((stderr, "before chopping: icon_name: |%s|", *icon_name));
+ if ((ptr2 = strstr(*icon_name, ".dvi")) != NULL) {
+ /* chop off .dvi extension */
+ *ptr2 = '\0';
+ }
+ MYTRACE((stderr, "after chopping: icon_name: |%s|", *icon_name));
+
+ *title_name = xmalloc(strlen(title_name_fmt)
+ + strlen(XDVIK_PROGNAME)
+ + strlen(*icon_name)
+ + LENGTH_OF_INT
+ + 2); /* 2 for additional plural `s' */
+ MYTRACE((stderr, "total_pages: %d", total_pages));
+ sprintf(*title_name, title_name_fmt, XDVIK_PROGNAME, *icon_name, total_pages,
+ (total_pages > 1) ? "s" : "");
+
+ MYTRACE((stderr, "title_name, icon_name: |%s|%s|", *title_name, *icon_name));
+}
+
+void
+set_icon_and_title(const char *icon_name, const char *title_name)
+{
+ if (!XtIsRealized(globals.widgets.top_level)) {
+ MYTRACE((stderr, "set_icon_and_title: returning"));
+ return;
+ }
+ XtVaSetValues(globals.widgets.top_level, XtNtitle, (XtArgVal) title_name, XtNiconName, (XtArgVal) icon_name, NULL);
+ XSetStandardProperties(DISP, XtWindow(globals.widgets.top_level), title_name, icon_name,
+ (Pixmap) 0, NULL, 0, NULL);
+}
+
+static void
+display_version_info(void)
+{
+ printf("%s version %s ", XDVIK_PROGNAME, XDVI_VERSION);
+#ifdef MOTIF
+ printf("(%s, runtime version %d.%d)\n",
+ /* XmVERSION, XmREVISION, XmUPDATE_LEVEL, */
+ XmVERSION_STRING,
+ xmUseVersion / 1000, xmUseVersion % 1000);
+#else
+ printf("%s\n", XDVI_GUI);
+#endif
+ printf("Libraries: %s, T1lib version %s\n", kpathsea_version_string, T1LIB_VERSIONSTRING);
+}
+
+static void
+display_bug_reporting_info(void)
+{
+ printf("Please send bug reports, feature requests etc. to one of:\n"
+ " http://sourceforge.net/tracker/?group_id=23164&atid=377580\n"
+ " tex-k@tug.org (http://tug.org/mailman/listinfo/tex-k)\n\n"
+ "\n");
+}
+
+static void
+display_licensing_info(void)
+{
+ fputs("Licenses: X Consortium license, GNU Library General Public\n"
+ "License, GNU General Public License (use option `-license'\n"
+ "for more details). There is NO WARRANTY of anything.\n\n", stdout);
+}
+
+static void
+display_long_licensing_info(void)
+{
+ fputs("The major parts of Xdvik are licensed under the X Consortium license.\n"
+ "Parts (encoding.c) are licensed under the GNU General Public License.\n"
+ "Xdvik uses the following libraries:\n"
+ "- The kpathsea library, licensed in part under the GNU General Public\n"
+ " License, in part under the GNU Library General Public License.\n"
+ "- t1lib, licensed in parts under the GNU Library General Public License,\n"
+ " in parts under the X Consortium license.\n"
+ "There is NO WARRANTY of anything.\n\n", stdout);
+}
+
+static void
+get_window_constraints(XtWidgetGeometry *reply,
+ Dimension screen_w, Dimension screen_h,
+ int add_h)
+{
+ XtWidgetGeometry constraints;
+
+ constraints.request_mode = reply->request_mode = 0;
+
+ /* fprintf(stderr, "setting constraints.width to %d\n", globals.page.w); */
+ constraints.width = globals.page.w;
+ if (globals.page.w > screen_w) {
+ /* fprintf(stderr, "setting CWWidth constraint\n"); */
+ constraints.request_mode |= CWWidth;
+ constraints.width = screen_w;
+ }
+
+ /* fprintf(stderr, "setting constraints.height to %d\n", globals.page.h + global_statusline_h); */
+ constraints.height = globals.page.h + global_statusline_h;
+ if (constraints.height > screen_h) {
+ /* fprintf(stderr, "setting CWHeight constraint\n"); */
+ constraints.request_mode |= CWHeight;
+ /* if window too large, need to subtract height of toolbar etc. again */
+ constraints.height = screen_h - add_h;
+ }
+
+ if (constraints.request_mode != 0
+ && constraints.request_mode != (CWWidth | CWHeight)) {
+#ifdef MOTIF
+ (void)XtQueryGeometry(globals.widgets.main_window, &constraints, reply);
+#else
+ (void)XtQueryGeometry(globals.widgets.vport_widget, &constraints, reply);
+#endif
+ }
+ if (!(reply->request_mode & CWWidth))
+ reply->width = constraints.width;
+ if (reply->width >= screen_w)
+ reply->width = screen_w;
+ if (!(reply->request_mode & CWHeight))
+ reply->height = constraints.height;
+ if (reply->height >= screen_h)
+ reply->height = screen_h;
+ /* fprintf(stderr, "width now: %d\n", reply.width); */
+
+}
+
+void
+set_windowsize(Dimension *ret_w, Dimension *ret_h, int add_w, int add_h, Boolean override)
+{
+ static Arg set_wh_args[] = {
+ {XtNwidth, (XtArgVal) 0},
+ {XtNheight, (XtArgVal) 0},
+ };
+ Dimension screen_w, screen_h;
+
+ const char *test_geometry = resource.geometry;
+
+ if (resource.fullscreen) {
+ Dimension w = WidthOfScreen(SCRN), h = HeightOfScreen(SCRN);
+
+ if (currwin.shrinkfactor == 0) { /* if not set by user */
+ Dimension height_factor = ROUNDUP(globals.page.unshrunk_h, h);
+ currwin.shrinkfactor = ROUNDUP(globals.page.unshrunk_w, w);
+ if (height_factor >= currwin.shrinkfactor)
+ currwin.shrinkfactor = height_factor;
+/* fprintf(stderr, "factor was 0, using %d\n", currwin.shrinkfactor); */
+ }
+/* else */
+/* fprintf(stderr, "factor != 0, using %d\n", currwin.shrinkfactor); */
+
+ mane.shrinkfactor = currwin.shrinkfactor;
+ init_page();
+ set_wh_args[0].value = (XtArgVal)w;
+ set_wh_args[1].value = (XtArgVal)h;
+ *ret_w = w;
+ *ret_h = h;
+#ifdef MOTIF
+#if USE_XAW_PANNER
+ XtVaGetValues(globals.widgets.main_window, XmNshadowThickness, &g_save_shadow_thickness, NULL);
+#endif
+ XtVaSetValues(globals.widgets.main_window, XmNshadowThickness, 0, NULL);
+#endif
+ XtSetValues(globals.widgets.top_level, set_wh_args, XtNumber(set_wh_args));
+ }
+ else if (override) {
+ set_wh_args[0].value = (XtArgVal)*ret_w;
+ set_wh_args[1].value = (XtArgVal)*ret_h;
+ XtSetValues(globals.widgets.top_level, set_wh_args, XtNumber(set_wh_args));
+ }
+ else { /* determine a window size that fits the current shrink factor */
+ Arg temp_args3 = { XtNborderWidth, (XtArgVal)&bwidth };
+ XtWidgetGeometry reply;
+
+ XtGetValues(globals.widgets.top_level, &temp_args3, 1); /* get border width */
+ screen_w = WidthOfScreen(SCRN) - 2 * bwidth;
+
+ screen_w -= add_w;
+ screen_h = HeightOfScreen(SCRN) - 2 * bwidth - global_statusline_h - 6;
+ for (;;) { /* actually, at most two passes */
+ Dimension height_factor;
+
+ TRACE_GUI((stderr, "geometry: |%s|; remember: %d, windowsize: %s",
+ resource.geometry ? resource.geometry : "<NULL>",
+ resource.remember_windowsize,
+ resource.windowsize ? resource.windowsize : "<NULL>"));
+
+ if (resource.geometry == NULL && !resource.remember_windowsize) {
+ /* geometry not set by user, try to find geometry that fits the shrink factor */
+ get_window_constraints(&reply, screen_w, screen_h, add_h);
+ }
+ else {
+ int x, y;
+ unsigned int width, height;
+ int flags;
+
+ if (resource.remember_windowsize && resource.windowsize != NULL)
+ test_geometry = resource.windowsize;
+ else
+ test_geometry = resource.geometry;
+ flags = XParseGeometry(test_geometry, &x, &y, &width, &height);
+
+ if (!(flags & WidthValue) || !(flags & HeightValue)) {
+ /* no geometry specified, use fallback */
+ get_window_constraints(&reply, screen_w, screen_h, add_h);
+ }
+
+ /* warn about bad values */
+ if (flags & WidthValue) {
+ if (width > (unsigned int)(2 * bwidth + add_w)) {
+ TRACE_FILES((stderr, "width: %hu, bwidth: %hu, add_w: %d",
+ width, bwidth, add_w));
+ reply.width = width - 2 * bwidth - add_w;
+ }
+ else {
+ reply.width = width;
+ }
+ }
+ if (flags & HeightValue) {
+ if (height > (unsigned int)(2 * bwidth + add_h)) {
+ TRACE_FILES((stderr, "height: %hu, bwidth: %hu, add_h: %d",
+ height, bwidth, add_h));
+ reply.height = height - 2 * bwidth - add_h;
+ }
+ else {
+ reply.height = height;
+ }
+ }
+ TRACE_FILES((stderr, "setting geometry: %dx%d", (int)reply.width, (int)reply.height));
+ }
+
+ /* now reply.{width,height} contain max. usable window size */
+
+ /* User didn't use `-s 0', use either default or other user-specified value */
+ if (currwin.shrinkfactor != 0) {
+/* fprintf(stderr, "factor != 0, using %d\n", currwin.shrinkfactor); */
+ break;
+ }
+/* else { */
+/* fprintf(stderr, "factor was 0, using %d\n", currwin.shrinkfactor); */
+/* } */
+
+ /* else, try to find a suitable shrink factor: */
+ currwin.shrinkfactor = ROUNDUP(globals.page.unshrunk_w, reply.width - 2);
+/* fprintf(stderr, "factor w: %d\n", currwin.shrinkfactor); */
+
+ height_factor = ROUNDUP(globals.page.unshrunk_h, reply.height - 2);
+/* fprintf(stderr, "factor h: %d\n", height_factor); */
+ if (height_factor >= currwin.shrinkfactor)
+ currwin.shrinkfactor = height_factor;
+
+/* fprintf(stderr, "factor now is: %d\n", currwin.shrinkfactor); */
+
+ mane.shrinkfactor = currwin.shrinkfactor;
+ init_page();
+ set_wh_args[0].value = (XtArgVal)globals.page.w;
+ set_wh_args[1].value = (XtArgVal)globals.page.h;
+ *ret_w = globals.page.w;
+ *ret_h = globals.page.h;
+ XtSetValues(globals.widgets.draw_widget, set_wh_args, XtNumber(set_wh_args));
+ }
+#ifdef MOTIF
+ /*
+ SU 2002/11/23: Added scrollbar width to height computation.
+ Otherwise, when the vertical space isn't sufficient, a
+ vertical scrollbar will be added, but since this makes the
+ display narrower, a horizontal scrollbar will be added as
+ well, even if this wouldn't be neccessary.
+
+ SU 2003/09/30: Apparently the size computation works now, even
+ though I'm not sure why (scrollbar value isn't in add_w). Investigate.
+ */
+ /* HACK ALERT: 4 for window decoration borders - FIXME: get actual values?? */
+ set_wh_args[0].value = reply.width + add_w + (test_geometry == NULL ? 4 : 0);
+ set_wh_args[1].value = reply.height + add_h - (test_geometry == NULL ? 4 : 0);
+ XtSetValues(globals.widgets.top_level, set_wh_args, XtNumber(set_wh_args));
+
+#else /* MOTIF */
+
+ set_wh_args[0].value = reply.width + add_w + (test_geometry == NULL ? 15 : (2 * bwidth));
+ /*
+ FIXME: use real height of statusline here
+ Somehow I didn't manage to use XtVaCreateWidget in a call to
+ create_statusline() above, and XtManageChild() below.
+ In that case, we could do without global_statusline_h.
+ */
+ set_wh_args[1].value = reply.height + (test_geometry == NULL ? (2 * bwidth + add_h) : 0);
+ XtSetValues(globals.widgets.top_level, set_wh_args, XtNumber(set_wh_args));
+ set_wh_args[0].value -= add_w;
+ XtSetValues(globals.widgets.vport_widget, set_wh_args, XtNumber(set_wh_args));
+
+#endif /* MOTIF */
+ *ret_w = set_wh_args[0].value;
+ *ret_h = set_wh_args[1].value;
+ TRACE_FILES((stderr, "returning: w=%d, h=%d", *ret_w, *ret_h));
+ }
+}
+
+static void
+net_wm_toggle_fullscreen(int flag)
+{
+ Atom NET_WM_FULLSCREEN = XInternAtom(DISP, "_NET_WM_STATE_FULLSCREEN", True);
+
+ if (NET_WM_FULLSCREEN) {
+ XEvent ev;
+ Atom NET_WM_STATE = XInternAtom(DISP, "_NET_WM_STATE", False);
+
+/* XDVI_INFO((stdout, "trying _NET_WM_STATE_FULLSCREEN ...")); */
+
+ ev.type = ClientMessage;
+ ev.xclient.serial = 0;
+ ev.xclient.send_event = True;
+ ev.xclient.display = DISP;
+ ev.xclient.window = XtWindow(globals.widgets.top_level);
+ ev.xclient.message_type = NET_WM_STATE;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = flag; /* _NET_WM_STATE_REMOVE (0) or _NET_WM_STATE_ADD (1) */
+ ev.xclient.data.l[1] = NET_WM_FULLSCREEN;
+ ev.xclient.data.l[2] = 0L;
+
+ XSendEvent(DISP, DefaultRootWindow(DISP), False,
+ SubstructureNotifyMask, &ev);
+ }
+ else {
+ XDVI_INFO((stdout, "_NET_WM_STATE_FULLSCREEN not supported by this window manager."));
+ }
+}
+
+void
+reconfigure_window(Boolean fullscreen, Dimension width, Dimension height,
+ Boolean save_position)
+{
+ static int x_old = 5, y_old = 15;
+#ifdef SIZECONFIGURE_WORKS
+ int sizeconfiguremask;
+ XWindowChanges sizeconfigure;
+#endif /* SIZECONFIGURE_WORKS */
+#ifdef MOTIF
+ static int save_wm_decorations;
+#else
+ static struct PropMotifWmHints MWMHints = {MWM_HINTS_DECORATIONS, 0, 0, 0, 0};
+ Atom WM_HINTS = XInternAtom(DISP, "_MOTIF_WM_HINTS", True);
+#endif
+ int x, y;
+
+#ifdef SIZECONFIGURE_WORKS
+ sizeconfiguremask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
+ sizeconfigure.width = width;
+ sizeconfigure.height = height;
+#endif /* SIZECONFIGURE_WORKS */
+
+ if (fullscreen) {
+#if 0
+ static Boolean first_time = True;
+ /* offsets between the raw window and the decorated window */
+ static int wm_x_offset = 0;
+ static int wm_y_offset = 0;
+#endif
+ Window dummy;
+
+#ifdef SIZECONFIGURE_WORKS
+ sizeconfigure.x = 0;
+ sizeconfigure.y = 0;
+ sizeconfigure.border_width = 0;
+#endif /* SIZECONFIGURE_WORKS */
+
+ /* Note ZLB: avoid to call XTranslateCoordinates if the window is
+ not yet mapped since XTranslateCoordinates implicitly maps the
+ window (note: calling the function XGetWindowAttributes also
+ makes the window mapped).
+
+ This effectively eliminates the flashing effect when xdvik is
+ started in fullscreen mode for the Motif version. For the Xaw
+ version we still get flashing effect (seems that the window is
+ already mapped). */
+
+ if (save_position) {
+ /* save current window coordinates so that we can change them back */
+ (void)XTranslateCoordinates(DISP, XtWindow(globals.widgets.top_level),
+ RootWindowOfScreen(SCRN),
+ 0, 0,
+ &x_old, &y_old,
+ &dummy);
+#if 0
+ if (first_time) {
+ first_time = False;
+ /* This is a hack for finding out wm_x_offset, wm_y_offset */
+ XMoveWindow(DISP, XtWindow(globals.widgets.top_level), 0, 0);
+ XSync(DISP, False);
+ (void)XTranslateCoordinates(DISP, XtWindow(globals.widgets.top_level),
+ RootWindowOfScreen(SCRN),
+ 0, 0, &wm_x_offset, &wm_y_offset,
+ &dummy);
+ fprintf(stderr, "wm offset = (%d,%d)\n",
+ wm_x_offset, wm_y_offset);
+ }
+ x_old -= wm_x_offset;
+ y_old -= wm_y_offset;
+#endif
+ }
+
+ x = y = 0;
+
+#ifdef MOTIF
+ XtVaGetValues(globals.widgets.top_level, XmNmwmDecorations, &save_wm_decorations, NULL);
+ /* FIXME: this doesn't work e.g. with KDE */
+ XtVaSetValues(globals.widgets.top_level,
+ XmNmwmDecorations, 0,
+ XmNgeometry, "+0+0",
+ NULL);
+ XtVaSetValues(globals.widgets.main_window, XmNshadowThickness, 0, NULL);
+#else
+ MWMHints.decorations = 0;
+ if (WM_HINTS != None) {
+ XChangeProperty(DISP, XtWindow(globals.widgets.top_level),
+ WM_HINTS, WM_HINTS, 32,
+ PropModeReplace, (unsigned char *)&MWMHints,
+ sizeof(MWMHints) / 4);
+ }
+#endif
+ /* SU: apparently some new standard that is supposed to work
+ with some WMs ... but it doesn't with my versions of Gnome and KDE. */
+ net_wm_toggle_fullscreen(1);
+
+#ifdef SIZECONFIGURE_WORKS
+ XConfigureWindow(DISP, XtWindow(globals.widgets.top_level), sizeconfiguremask, &sizeconfigure);
+#endif /* SIZECONFIGURE_WORKS */
+ }
+ else {
+#ifdef SIZECONFIGURE_WORKS
+ sizeconfiguremask = CWWidth | CWHeight | CWX | CWY;
+ sizeconfigure.x = x_old;
+ sizeconfigure.y = y_old;
+ sizeconfigure.border_width = 20;
+#endif /* SIZECONFIGURE_WORKS */
+ XtVaSetValues(globals.widgets.top_level, XtNx, x_old, XtNy, y_old, NULL);
+#ifdef MOTIF
+ XtVaSetValues(globals.widgets.top_level, XmNmwmDecorations, save_wm_decorations, NULL);
+#if USE_XAW_PANNER
+ XtVaSetValues(globals.widgets.main_window, XmNshadowThickness, g_save_shadow_thickness, NULL);
+#endif
+#else
+ MWMHints.decorations = MWM_DECOR_ALL;
+ if (WM_HINTS != None) {
+ XChangeProperty(DISP, XtWindow(globals.widgets.top_level),
+ WM_HINTS, WM_HINTS, 32,
+ PropModeReplace, (unsigned char *)&MWMHints,
+ sizeof(MWMHints) / 4);
+ }
+#endif
+ net_wm_toggle_fullscreen(0);
+
+ x = x_old;
+ y = y_old;
+ }
+
+#if 1
+#if 0
+ XUnmapWindow(DISP, XtWindow(globals.widgets.top_level));
+#else
+ XWithdrawWindow(DISP, XtWindow(globals.widgets.top_level), XScreenNumberOfScreen(SCRN));
+#endif
+
+ /* Note ZLB: Placing XResizeWindow before XUnmapWindow or after XMapWindow
+ makes the fullscreen window size smaller than the screen size when
+ using `mwm' of Lesstif */
+ XSetWindowBorderWidth(DISP, XtWindow(globals.widgets.top_level), 0);
+ XResizeWindow(DISP, XtWindow(globals.widgets.top_level), width, height);
+
+ XMapRaised(DISP, XtWindow(globals.widgets.top_level));
+
+ /* Note ZLB: XMapWindow might change the window position with some WMs
+ (like Sawfish), so we place the window position after it's mapped. */
+ XMoveWindow(DISP, XtWindow(globals.widgets.top_level), x, y);
+#endif /* 0 */
+
+ /* need to redraw the page to avoid artifacts */
+ globals.ev.flags |= EV_NEWPAGE;
+ XFlush(DISP);
+}
+
+/*
+ a custom error handler that makes it easier to catch X errors in the debugger
+ (by setting a breakpoint to this function, plus using the -sync option).
+ There was an X error reported by Svend Tollak Munkejord when running remotly
+ on OSF1/V5.1 alpha with display on SuSE 9.1, after selecting some text with the
+ mouse and releasing the mouse button, which I couldn't track down:
+
+ X Error of failed request: BadValue (integer parameter out of range for operation)
+ Major opcode of failed request: 18 (X_ChangeProperty)
+ Value in failed request: 0x40
+ Serial number of failed request: 518
+ Current serial number in output stream: 519
+
+ From the trace:
+
+ signal IOT/Abort trap at >*[__kill, 0x3ff800e8908] beq a3, 0x3ff800e8920
+ (dbx) where
+ > 0 __kill(0x0, 0x5, 0x3ff00000000, 0x11fffb188, 0x3ff801a9c14) [0x3ff800e8908]
+ 1 (unknown)() [0x3ff801ee108]
+ 2 __tis_raise(0x3ff801a9c14, 0x11fffb620, 0x3ff801229d8, 0x3ff00000006, 0x3ff801869b4) [0x3ff801229d4]
+ 3 raise(0x3ff801229d8, 0x3ff00000006, 0x3ff801869b4, 0x0, 0x3ff801a9c44) [0x3ff801869b0]
+ 4 abort(0x12006f858, 0x406f28ae75776627, 0x0, 0x0, 0x100000000) [0x3ff801a9c40]
+ 5 do_abort() ["util.c":442, 0x12006f854]
+ 6 x_error_handler(display = 0x140088800, error = 0x11fffb620) ["xdvi.c":1972, 0x1200764c8]
+ 7 (unknown)() [0x3ff8086caf0]
+ 8 _XError(0x11fffb758, 0x0, 0x36c, 0x24, 0x20) [0x3ff8044f7f0]
+ 9 _XReply(0x0, 0x3, 0x0, 0x11fffba40, 0x100000000) [0x3ff8044cec8]
+ 10 XSync(0x14019ea40, 0x40036b0200, 0x19170b000120000, 0x12, 0x43197900000000) [0x3ff80444910]
+ 11 _XSyncFunction(0x19170b000120000, 0x12, 0x43197900000000, 0x0, 0x3ff80408994) [0x3ff804449f0]
+ 12 XChangeProperty(0x3ff8086c9c0, 0x0, 0x2c, 0xb6, 0x4) [0x3ff80408990]
+ 13 (unknown)() [0x3ff8086d2d0]
+ 14 (unknown)() [0x3ff8086d654]
+ 15 XtDispatchEventToWidget(0x3ff80852834, 0x11fffbde8, 0x3ff80852974, 0x11fffbde8, 0x0) [0x3ff80852060]
+ 16 (unknown)() [0x3ff80852990]
+ 17 XtDispatchEvent(0x801, 0x4, 0x11fffc018, 0x0, 0x100000000) [0x3ff80852fb0]
+ 18 read_events(ret_mask = 131070) ["events.c":5048, 0x120046fa4]
+ 19 do_pages() ["events.c":5290, 0x120047e58]
+ 20 run_dvi_file(filename = 0x14005f370 = "/auto/home/vsl175/a/svendm/latex/a.dvi", data = 0x14005f778)
+ ["xdvi.c":3852, 0x12007a5e8]
+ 21 main(argc = 2, argv = 0x11fffc018) ["xdvi.c":4231, 0x12007b780]
+
+ Since it seemed to work regardless of this error, I decided to enable the custom
+ error handler by default, at least until we've figured this problem out.
+*/
+static int
+x_error_handler(Display *display, XErrorEvent *error)
+{
+ char buf[1024], req_buf[1024];
+
+ if (error->request_code < 128) {
+ char num[LENGTH_OF_INT];
+ sprintf(num, "%d", error->request_code);
+ XGetErrorDatabaseText(display, "XRequest", num, "", req_buf, 1024);
+ }
+ else {
+ req_buf[0] = '\0';
+ }
+
+ XGetErrorText(display, error->error_code, buf, sizeof buf);
+ /* XtCloseDisplay(DISP); */
+ if (error->error_code == BadWindow
+ || error->error_code == BadPixmap
+ || error->error_code == BadCursor
+ || error->error_code == BadFont
+ || error->error_code == BadDrawable
+ || error->error_code == BadColor
+ || error->error_code == BadGC
+ || error->error_code == BadIDChoice
+ || error->error_code == BadValue
+ || error->error_code == BadAtom) {
+ XDVI_WARNING((stderr, "X protocol error: %s\n X Request %d (%s), Value=0x%x.",
+ buf, error->request_code, req_buf, (unsigned int)error->resourceid));
+ }
+ else {
+ XDVI_WARNING((stderr, "X protocol error: %s\n X Request %d (%s).",
+ buf, error->request_code, req_buf));
+ }
+ return 0;
+}
+
+
+/*
+ * Parse colors from resource.{visited_}link_color, saving them
+ * to g_{visited_}link_color and {visited_}link_pix.
+*/
+static void
+get_link_colors(Pixel *link_pix, Pixel *visited_link_pix)
+{
+ XrmValue from1, from2, to1, to2;
+
+ XColor exact, approx;
+ double r, g, b;
+ double factor = 65535.0;
+ int ret;
+
+ /* get rgb values from color for links */
+ if ((ret = XLookupColor(DISP, G_colormap,
+ resource.link_color,
+ &exact, &approx)) != 0) {
+ }
+ else {
+ XDVI_WARNING((stderr, "XLookupColor failed for resource.link_color \"%s\"\n"
+ "- using fallback color \"%s\".",
+ resource.visited_link_color, LINK_COLOR_FALLBACK));
+ XLookupColor(DISP, G_colormap, LINK_COLOR_FALLBACK, &exact, &approx);
+ }
+
+#if 0
+ fprintf(stderr, "lookup color for %s returned: %d, %d, %d\n",
+ resource.link_color, exact.red, exact.green, exact.blue);
+#endif
+ r = exact.red / factor;
+ g = exact.green / factor;
+ b = exact.blue / factor;
+ g_link_color_rgb = xmalloc(strlen("push rgb 0.00 0.00 0.00") + 1);
+ sprintf(g_link_color_rgb, "push rgb %.2f %.2f %.2f", r, g, b);
+
+ /* same for visited links */
+ if ((ret = XLookupColor(DISP, G_colormap,
+ resource.visited_link_color,
+ &exact, &approx)) != 0) {
+ }
+ else {
+ XDVI_WARNING((stderr, "XLookupColor failed for resource.visited_link_color \"%s\"\n"
+ "- using fallback color \"%s\".",
+ resource.visited_link_color, VISITED_LINK_COLOR_FALLBACK));
+ XLookupColor(DISP, G_colormap, VISITED_LINK_COLOR_FALLBACK, &exact, &approx);
+ }
+
+#if 0
+ fprintf(stderr, "lookup color for %s returned: %d, %d, %d\n",
+ resource.visited_link_color, exact.red, exact.green, exact.blue);
+#endif
+ r = exact.red / factor;
+ g = exact.green / factor;
+ b = exact.blue / factor;
+ g_visited_link_color_rgb = xmalloc(strlen("push rgb 0.00 0.00 0.00") + 1);
+ sprintf(g_visited_link_color_rgb, "push rgb %.2f %.2f %.2f", r, g, b);
+
+ /* 2nd part: Create CG for the underlines. */
+ from1.addr = resource.link_color;
+ from1.size = strlen(from1.addr) + 1;
+ to1.addr = (XtPointer)link_pix;
+ to1.size = sizeof(Pixel);
+ if (!XtConvertAndStore(globals.widgets.top_level, XtRString, &from1, XtRPixel, &to1)) {
+ XDVI_WARNING((stderr, "String to pixel conversion failed for resource.link_color \"%s\"\n"
+ "- using fallback color \"%s\".",
+ resource.link_color, LINK_COLOR_FALLBACK));
+ from1.addr = LINK_COLOR_FALLBACK;
+ from1.size = strlen(from1.addr) + 1;
+ to1.addr = (XtPointer)link_pix;
+ to1.size = sizeof(Pixel);
+ XtConvertAndStore(globals.widgets.top_level, XtRString, &from1, XtRPixel, &to1);
+ }
+ from2.addr = resource.visited_link_color;
+ from2.size = strlen(from2.addr) + 1;
+ to2.addr = (XtPointer)visited_link_pix;
+ to2.size = sizeof(Pixel);
+ if (!XtConvertAndStore(globals.widgets.top_level, XtRString, &from2, XtRPixel, &to2)) {
+ XDVI_WARNING((stderr, "String to pixel conversion failed for resource.visited_link_color \"%s\"\n"
+ "- using fallback color \"%s\".",
+ resource.visited_link_color, VISITED_LINK_COLOR_FALLBACK));
+ from2.addr = VISITED_LINK_COLOR_FALLBACK;
+ from2.size = strlen(from2.addr) + 1;
+ to2.addr = (XtPointer)visited_link_pix;
+ to2.size = sizeof(Pixel);
+ XtConvertAndStore(globals.widgets.top_level, XtRString, &from2, XtRPixel, &to2);
+ }
+}
+
+/* Widget globals.widgets.main_row, globals.widgets.menu_bar; */
+
+
+#ifdef MOTIF
+/* make sure the translations for the drawing area are properly set
+ (Motif 2.x seems to somehow overwrite them somewhere in the
+ initialization phase; bug #610206).
+*/
+void
+motif_translations_hack(void)
+{
+ static XtTranslations xlats = NULL;
+ const char *const translations = \
+ "<Key>osfPageUp:back-page()\n"
+ "<Key>osfPageDown:forward-page()\n"
+ "Ctrl<Key>osfBeginLine:goto-page(1)\n"
+ "Ctrl<Key>osfEndLine:goto-page()\n"
+ "<Key>osfBeginLine:home-or-top()\n"
+ "<Key>osfEndLine:end-or-bottom()\n"
+#if 0
+ /* AFAIK the following don't have any effect with Motif */
+#ifdef XK_KP_Left
+ "<Key>KP_Home:home()\n"
+ "<Key>KP_End:down()\n"
+ "<Key>KP_Prior:back-page()\n"
+ "<Key>KP_Next:forward-page()\n"
+#endif
+#endif
+ ;
+
+ if (xlats == NULL) {
+ xlats = XtParseTranslationTable(translations);
+ }
+
+ ASSERT(globals.widgets.clip_widget != NULL, "globals.widgets.clip_widget must have been initialized");
+ ASSERT(globals.widgets.draw_widget != NULL, "globals.widgets.draw_widget must have been initialized");
+ XtOverrideTranslations(globals.widgets.clip_widget, xlats);
+}
+#endif /* MOTIF */
+
+
+/*
+ Initialize internal data (most of them global ...) according to the values
+ of resources/command-line arguments, warning user about illegal values
+ etc.
+*/
+static void
+init_check_resources(void)
+{
+ size_t i;
+
+ if (resource.mfmode != NULL) {
+ char *p;
+
+ p = strrchr(resource.mfmode, ':');
+ if (p != NULL) {
+ unsigned int len;
+ char *p1;
+
+ ++p;
+ len = p - resource.mfmode;
+ p1 = xmalloc(len);
+ memcpy(p1, resource.mfmode, len - 1);
+ p1[len - 1] = '\0';
+ resource.mfmode = p1;
+ resource.pixels_per_inch = atoi(p);
+ }
+ }
+ if (currwin.shrinkfactor < 0) {
+ XDVI_ERROR((stderr, "Invalid shrink factor: %d.", currwin.shrinkfactor));
+ usage(EXIT_FAILURE);
+ }
+ if (resource.density <= 0) {
+ XDVI_ERROR((stderr, "Invalid shrink density: %d.", resource.density));
+ usage(EXIT_FAILURE);
+ }
+ if (resource.pixels_per_inch <= 0) {
+ XDVI_ERROR((stderr, "Invalid dpi value: %d.", resource.pixels_per_inch));
+ usage(EXIT_FAILURE);
+ }
+ if (resource.link_style < 0 || resource.link_style > 3) {
+ XDVI_ERROR((stderr, "Unrecognized value %d for resource \"linkstyle\" (valid range is 0 - 3); assuming 3.",
+ resource.link_style));
+ resource.link_style = 3;
+ }
+ if (currwin.shrinkfactor > 1) {
+ mane.shrinkfactor = currwin.shrinkfactor; /* otherwise it's 1 */
+ }
+
+#ifdef RGB_ANTI_ALIASING
+#warning Note: RGB Anti-aliasing enabled
+ /* subpixel rendering */
+ resource.subpixel_order = SUBPIXEL_NONE;
+ if (resource.sub_pixels != NULL) {
+ int sum;
+
+ if (memicmp(resource.sub_pixels, "rgb", 3) == 0)
+ resource.subpixel_order = SUBPIXEL_RGB;
+ else if (memicmp(resource.sub_pixels, "bgr", 3) == 0)
+ resource.subpixel_order = SUBPIXEL_BGR;
+ else if (memicmp(resource.sub_pixels, "none", 3) == 0)
+ resource.subpixel_order = SUBPIXEL_NONE;
+ else {
+ XDVI_ERROR((stderr,
+ "Unrecognized value \"%s\" for resource subpixels\n"
+ "(possible values are: \"rgb\" or \"bgr\").",
+ resource.sub_pixels));
+ xdvi_exit(EXIT_FAILURE);
+ }
+ /* get the energy distribution */
+ if (resource.subpixel_order == SUBPIXEL_RGB || resource.subpixel_order == SUBPIXEL_BGR) {
+ const char *ptr = resource.sub_pixels + 3;
+ while (isspace(*ptr))
+ ptr++;
+ fprintf(stderr, "ptr: |%s|\n", ptr);
+ resource.subpixel_energy[0] = 33.333;
+ resource.subpixel_energy[1] = 33.333;
+ resource.subpixel_energy[2] = 0.0;
+ if (*ptr != '\0') {
+ if (sscanf(ptr, "%f %f %f",
+ &(resource.subpixel_energy[0]),
+ &(resource.subpixel_energy[1]),
+ &(resource.subpixel_energy[2]))
+ != 3) {
+ XDVI_ERROR((stderr,
+ "Illegal color mask `%s' for resource subpixels (should be: `n n n')\n",
+ ptr));
+ }
+ }
+
+ sum = (int)(resource.subpixel_energy[0] +
+ 2 * resource.subpixel_energy[1] +
+ 2 * resource.subpixel_energy[2]);
+ if (sum < 99 || sum > 100) {
+ XDVI_WARNING((stderr, "energy values %f + 2 * %f + 2 * %f don't sum up to 100%%!\n",
+ resource.subpixel_energy[0], resource.subpixel_energy[1], resource.subpixel_energy[2]));
+ exit(1);
+ }
+
+ resource.subpixel_energy[0] /= 100.0;
+ resource.subpixel_energy[1] /= 100.0;
+ resource.subpixel_energy[2] /= 100.0;
+ fprintf(stderr, "subpixel order: %s = %d; [%f %f %f]\n",
+ resource.sub_pixels, resource.subpixel_order,
+ resource.subpixel_energy[0], resource.subpixel_energy[1], resource.subpixel_energy[2]);
+ }
+ }
+#endif
+
+ /* margins */
+ if (resource.sidemargin)
+ resource.sidemargin_int = atopix(resource.sidemargin, False);
+ if (resource.topmargin)
+ resource.topmargin_int = atopix(resource.topmargin, False);
+ resource.xoffset_int = resource.xoffset ? atopix(resource.xoffset, True)
+ : resource.pixels_per_inch;
+ resource.yoffset_int = resource.yoffset ? atopix(resource.yoffset, True)
+ : resource.pixels_per_inch;
+
+ /* paper type */
+ if (!set_paper_type(resource.paper)) {
+ const char **p;
+ char *helpmsg = xstrdup("Possible paper types are:\n ");
+ for (p = paper_types; p < paper_types + XtNumber(paper_types); p += 2) {
+ if (**p == '\0') { /* next line of list */
+ helpmsg = xstrcat(helpmsg, "\n ");
+ }
+ else {
+ helpmsg = xstrcat(helpmsg, *p);
+ helpmsg = xstrcat(helpmsg, " ");
+ }
+ }
+ helpmsg = xstrcat(helpmsg,
+ "\n(the names ending with `r' are `rotated' or `landscape' variants).\n"
+ "Alternatively, you can specify the dimensions as `WIDTHxHEIGHT', followed "
+ "by a dimension unit (one of: pt pc in bp cm mm dd cc sp).");
+ /* also dump it to stderr ... */
+ fprintf(stderr,
+ "Unrecognized value `%s' for paper type option; using a4 instead.\n%s\n",
+ resource.paper, helpmsg);
+
+ popup_message(globals.widgets.top_level,
+ MSG_WARN, helpmsg,
+ "Unrecognized value `%s' for paper type option; using a4 instead.", resource.paper);
+ set_paper_type("a4");
+ }
+
+ /* magnifier sizes */
+ for (i = 0; i < get_magglass_items(); ++i) {
+ if (resource.mg_arg[i] != NULL) {
+ char *s;
+
+ mg_size[i].w = mg_size[i].h = atoi(resource.mg_arg[i]);
+ s = strchr(resource.mg_arg[i], 'x');
+ if (s != NULL) {
+ mg_size[i].h = atoi(s + 1);
+ if (mg_size[i].h <= 0)
+ mg_size[i].w = 0;
+ }
+ }
+ }
+
+#ifdef PS
+ if (resource.safer) {
+ resource.allow_shell = False;
+# ifdef PS_GS
+ resource.gs_safer = True;
+# endif /* PS_GS */
+ }
+# ifdef PS_GS
+ {
+ const char *CGMcgm = "CGMcgm";
+ const char *cgmp;
+
+ cgmp = strchr(CGMcgm, resource.gs_palette[0]);
+ if (cgmp == NULL)
+ XDVI_FATAL((stderr, "Invalid value %s for gs palette option", resource.gs_palette));
+ if (cgmp >= CGMcgm + 3) {
+ static char gsp[] = "x";
+
+ gsp[0] = *(cgmp - 3);
+ resource.gs_palette = gsp;
+ }
+ }
+# endif /* PS_GS */
+#endif /* PS */
+
+ /* The old `-expert' flag overrides resource.expert_mode, `+expert' (or not
+ setting it) just uses expert_mode.
+ */
+ if (resource.expert)
+ resource.expert_mode = XPRT_SHOW_NONE;
+/* fprintf(stderr, "++++++++ initializing resource.expert_mode: %d\n", resource.expert_mode); */
+ update_expert_mode();
+}
+
+static void
+create_cursors(void)
+{
+ XColor bg_Color;
+ Pixmap temp;
+ Pixmap mask;
+
+ /* first try colors by name, as fix for #804294; fall back on
+ WhitePixelOfScreen() etc. if this fails:
+ */
+ if (resource.cr_Pixel != (Pixel)ULONG_MAX) {
+ m_cursor_color.pixel = resource.cr_Pixel;
+ XQueryColor(DISP, G_colormap, &m_cursor_color);
+ }
+ else {
+ if (XParseColor(DISP, G_colormap, "black", &m_cursor_color) == 0) { /* lookup failure */
+ m_cursor_color.pixel = BlackPixelOfScreen(SCRN);
+ XQueryColor(DISP, G_colormap, &m_cursor_color);
+ }
+ }
+ if (XParseColor(DISP, G_colormap, "white", &bg_Color) == 0) { /* lookup failure */
+ bg_Color.pixel = WhitePixelOfScreen(SCRN);
+ XQueryColor(DISP, G_colormap, &bg_Color);
+ }
+
+ /* wait cursor */
+#if 0 /* this makes no big difference for #804294 */
+ temp = XCreatePixmapFromBitmapData(DISP, RootWindowOfScreen(SCRN),
+ (char *)time16_bits,
+ time16_width, time16_height,
+ 1, 0, 1);
+ mask = XCreatePixmapFromBitmapData(DISP, RootWindowOfScreen(SCRN),
+ (char *)time16_mask_bits,
+ time16_mask_width, time16_mask_height,
+ 1, 0, 1);
+#else
+ temp = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)time16_bits,
+ time16_width, time16_height);
+ mask = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)time16_mask_bits,
+ time16_mask_width, time16_mask_height);
+#endif
+ globals.cursor.wait = XCreatePixmapCursor(DISP, temp, mask,
+ &m_cursor_color, &bg_Color,
+ time16_width / 2, time16_height / 2);
+ XFreePixmap(DISP, temp);
+ XFreePixmap(DISP, mask);
+
+ /* ready cursor, magnifier by default */
+ temp = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)magglass_bits,
+ magglass_width, magglass_height);
+ mask = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)magglass_mask_bits,
+ magglass_mask_width, magglass_mask_height);
+
+ globals.cursor.ready = XCreatePixmapCursor(DISP, temp, mask,
+ &m_cursor_color, &bg_Color,
+ magglass_x_hot, magglass_y_hot);
+ XFreePixmap(DISP, temp);
+ XFreePixmap(DISP, mask);
+
+ globals.cursor.corrupted = XCreateFontCursor(DISP, XC_watch);
+
+#if !COLOR
+ XRecolorCursor(DISP, globals.cursor.ready, &m_cursor_color, &bg_Color);
+ XRecolorCursor(DISP, globals.cursor.wait, &m_cursor_color, &bg_Color);
+#endif
+ /* Cursor when page is paused */
+#ifdef VMS
+ temp = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)hand_bits, hand_width, hand_height);
+ mask = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)hand_mask_bits, hand_mask_width, hand_mask_height);
+ globals.cursor.pause = XCreatePixmapCursor(DISP, temp, mask,
+ &m_cursor_color, &bg_Color, 6, 6);
+ XFreePixmap(DISP, temp);
+ XFreePixmap(DISP, mask);
+#else
+ globals.cursor.pause = XCreateFontCursor(DISP, XC_watch);
+#endif
+
+ /* cursors indicating dragging direction */
+ temp = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)drag_vert_bits,
+ drag_vert_width, drag_vert_height);
+ mask = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)drag_vert_mask_bits,
+ drag_vert_mask_width, drag_vert_mask_height);
+ globals.cursor.drag_v = XCreatePixmapCursor(DISP, temp, mask,
+ &m_cursor_color, &bg_Color,
+ drag_vert_x_hot, drag_vert_y_hot);
+ XFreePixmap(DISP, temp);
+ XFreePixmap(DISP, mask);
+
+ temp = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)drag_horiz_bits,
+ drag_horiz_width, drag_horiz_height);
+ mask = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)drag_horiz_mask_bits,
+ drag_horiz_width, drag_horiz_height);
+ globals.cursor.drag_h = XCreatePixmapCursor(DISP, temp, mask,
+ &m_cursor_color, &bg_Color,
+ drag_horiz_x_hot, drag_horiz_y_hot);
+ XFreePixmap(DISP, temp);
+ XFreePixmap(DISP, mask);
+
+ temp = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)drag_omni_bits,
+ drag_omni_width, drag_omni_height);
+ mask = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
+ (char *)drag_omni_mask_bits,
+ drag_omni_mask_width, drag_omni_mask_height);
+ globals.cursor.drag_a = XCreatePixmapCursor(DISP, temp, mask,
+ &m_cursor_color, &bg_Color,
+ drag_omni_x_hot, drag_omni_y_hot);
+ XFreePixmap(DISP, temp);
+ XFreePixmap(DISP, mask);
+
+#ifdef VMS
+ globals.cursor.link = globals.cursor.ready;
+ globals.cursor.rule = globals.cursor.ready;
+ globals.cursor.mag = globals.cursor.ready;
+ globals.cursor.text = globals.cursor.ready;
+#else
+ globals.cursor.link = XCreateFontCursor(DISP, XC_hand2);
+ globals.cursor.rule = XCreateFontCursor(DISP, XC_crosshair);
+ globals.cursor.mag = XCreateFontCursor(DISP, XC_crosshair);
+ globals.cursor.text = XCreateFontCursor(DISP, XC_cross);
+ /* globals.cursor.text = XCreateFontCursor(DISP, XC_tcross); */
+ XRecolorCursor(DISP, globals.cursor.mag, &m_cursor_color, &bg_Color);
+#endif
+}
+
+/* Initialize a forward search if the source_position argument is not NULL. */
+static void
+do_forward_search(const char *source_position)
+{
+ /* parse the special to expand the filename */
+ struct src_parsed_special data;
+ char *new_special = NULL;
+ char *expanded_filename = NULL;
+
+ if (source_position == NULL) /* nothing to do */
+ return;
+
+ data.filename_len = 0;
+ data.filename = NULL;
+
+ src_parse(source_position, strlen(source_position), &data);
+
+ if (data.filename_len == 0) { /* malformed argument: tell user, and ignore it */
+ popup_message(globals.widgets.top_level,
+ MSG_ERR,
+ /* helptext */
+ "The format of the -sourceposition argument should be:\n"
+ "-sourceposition '<nn>[ ]*<filename'\n"
+ "with <nn> = linenumber, [ ]* = an arbitrary number of spaces, "
+ "and <filename> = TeX source file.",
+ /* error message */
+ "Filename missing in `-sourceposition' argument \"%s\". "
+ "Could not perform forward search.",
+ source_position);
+ }
+ else {
+ TRACE_CLIENT((stderr, "got data: line %d, col %d, file |%s|, len %lu\n",
+ data.line, data.col, data.filename, (unsigned long)data.filename_len));
+
+ /* expand -sourceposition argument if it contains a path component, like above */
+ if (strchr(data.filename, '/') != NULL
+ && (expanded_filename = expand_filename(data.filename, USE_CWD_PATH)) != NULL) {
+ char *tmp = canonicalize_path(expanded_filename);
+ free(data.filename);
+ free(expanded_filename);
+ expanded_filename = tmp;
+ }
+ else
+ expanded_filename = data.filename;
+
+ TRACE_CLIENT((stderr, "expanded source_position: |%s|\n", expanded_filename));
+
+ new_special = xmalloc(2 * LENGTH_OF_INT + 2 /* 2 for `:' and separating space */
+ + strlen(expanded_filename) + 1);
+ sprintf(new_special, "%d:%d %s", data.line, data.col, expanded_filename);
+ free(expanded_filename);
+ globals.src.fwd_string = new_special;
+ globals.ev.flags |= EV_SRC;
+ }
+}
+
+static void
+check_early_arguments(int argc, char **argv)
+{
+ /* This checks arguments that need to work before the X machinery is
+ * started (e.g. if no display is available, or for information that is
+ * needed before the X defaults are evaluated), so the `options' structure
+ * can't be used for them.
+ *
+ * We need to loop through all arguments in case xdvi is aliased,
+ * or called via a shell script (like in teTeX) that adds things
+ * like `-name' at the beginning of the arglist.
+ */
+ int i;
+ Boolean install_err_handler = True;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-help") == 0
+ || strcmp(argv[i], "-h") == 0
+ || strcmp(argv[i], "+help") == 0
+ || strcmp(argv[i], "--help") == 0) {
+ printf("%s version %s\n", XDVIK_PROGNAME, XDVI_VERSION_INFO);
+ printf("A DVI file previewer for the X window system.\n\n");
+ display_licensing_info();
+ display_bug_reporting_info();
+ usage(0);
+ }
+ else if (strcmp(argv[i], "-license") == 0) {
+ display_long_licensing_info();
+ xdvi_exit(EXIT_SUCCESS);
+ }
+ else if (strcmp(argv[i], "--version") == 0
+ || strcmp(argv[i], "-version") == 0
+ || strcmp(argv[i], "-v") == 0) {
+ display_version_info();
+ xdvi_exit(EXIT_SUCCESS);
+ }
+ else if (strcmp(argv[i], "--default-xerr-handler") == 0) { /* hook to disable custom handler */
+ install_err_handler = False;
+ }
+ }
+
+ if (install_err_handler) {
+ (void)XSetErrorHandler(x_error_handler);
+ }
+}
+
+static void
+create_colormaps(void)
+{
+#ifdef GREY
+ G_depth = (unsigned int)DefaultDepthOfScreen(SCRN);
+ G_visual = DefaultVisualOfScreen(SCRN);
+ G_colormap = DefaultColormapOfScreen(SCRN);
+#ifdef XSERVER_INFO
+ if (globals.debug & DBG_ALL)
+ fprintf(stdout, "--- G_depth: %d\n", G_depth);
+#endif
+
+ if (resource.install != False && G_visual->class == PseudoColor) {
+ /* look for a TrueColor visual with more bits */
+ XVisualInfo template;
+ XVisualInfo *list;
+ int nitems_return;
+#ifdef XSERVER_INFO
+ if (globals.debug & DBG_ALL)
+ fprintf(stdout, "--- looking for a better TrueColor visual\n");
+#endif
+
+ template.screen = XScreenNumberOfScreen(SCRN);
+ template.class = TrueColor;
+ list = XGetVisualInfo(DISP, VisualScreenMask | VisualClassMask,
+ &template, &nitems_return);
+ if (list != NULL) {
+ XVisualInfo *list1;
+ XVisualInfo *best = NULL;
+
+ for (list1 = list; list1 < list + nitems_return; ++list1) {
+#ifdef XSERVER_INFO
+ if (globals.debug & DBG_ALL)
+ fprintf(stdout, "--- checking %d\n", list1->depth);
+#endif
+ if ((unsigned int)list1->depth > G_depth
+# if PS_GS
+ /* patch by Toni Ronkko <tronkko@hytti.uku.fi>, fixes bug #458057:
+ * SGI supports additional depths of 12 and 30, but
+ * these are not supported by ghostscript (see
+ * xdev->vinfo->depth in gdevxcmp.c (ghostscript-6.51)),
+ * so we restrict the values to those supported by gs.
+ */
+ && (list1->depth == 1 || list1->depth == 2
+ || list1->depth == 4 || list1->depth == 8
+ || list1->depth == 15 || list1->depth == 16
+ || list1->depth == 24 || list1->depth == 32)
+# endif
+ && (best == NULL || list1->depth > best->depth))
+ best = list1;
+ }
+ if (best != NULL) {
+#ifdef XSERVER_INFO
+ if (globals.debug & DBG_ALL)
+ fprintf(stdout, "--- best depth: %d\n", best->depth);
+#endif
+ G_depth = best->depth;
+ G_visual = best->visual;
+ G_colormap = XCreateColormap(DISP,
+ RootWindowOfScreen(SCRN),
+ G_visual, AllocNone);
+ XInstallColormap(DISP, G_colormap);
+ temp_args1[0].value = (XtArgVal) G_depth;
+ temp_args1[1].value = (XtArgVal) G_visual;
+ temp_args1[2].value = (XtArgVal) G_colormap;
+ XtSetValues(globals.widgets.top_level, temp_args1, XtNumber(temp_args1));
+ XtSetTypeConverter(XtRString, XtRPixel,
+ XdviCvtStringToPixel,
+ (XtConvertArgList) colorConvertArgs, 2,
+ XtCacheByDisplay, NULL);
+ {
+ /* This is needed so that popup windows have the right
+ visual and colormap. It is unnecessary for newer
+ versions of Motif (Motif 2.1.0, Solaris 9) but
+ needed for older versions (Motif 1.2.5, Solaris 2.6),
+ and for Xaw.
+ */
+ XrmDatabase db = XtScreenDatabase(SCRN);
+ XrmValue val;
+
+ val.size = sizeof G_visual;
+ val.addr = (XtPointer) &G_visual;
+ XrmPutResource(&db, "XDvi*visual", XtRVisual, &val);
+
+ val.size = sizeof G_colormap;
+ val.addr = (XtPointer) &G_colormap;
+ XrmPutResource(&db, "XDvi*colormap", XtRColormap, &val);
+ }
+ }
+ XFree(list);
+ }
+ }
+
+#ifdef MOTIF
+ if (globals.debug & DBG_GUI) {
+ printf("Compiled with %s, runtime version %d.%d\n",
+ /* XmVERSION, XmREVISION, XmUPDATE_LEVEL, */
+ XmVERSION_STRING,
+ xmUseVersion / 1000, xmUseVersion % 1000);
+ }
+#endif
+
+ if (resource.install == True && G_visual->class == PseudoColor) {
+ XColor tmp_color;
+#ifdef XSERVER_INFO
+ if (globals.debug & DBG_ALL)
+ fprintf(stdout, "--- PseudoColor, trying to install colormap\n");
+#endif
+
+ /* This next bit makes sure that the standard black and white pixels
+ are allocated in the new colormap. */
+ tmp_color.pixel = BlackPixelOfScreen(SCRN);
+ XQueryColor(DISP, G_colormap, &tmp_color);
+ XAllocColor(DISP, G_colormap, &tmp_color);
+
+ tmp_color.pixel = WhitePixelOfScreen(SCRN);
+ XQueryColor(DISP, G_colormap, &tmp_color);
+ XAllocColor(DISP, G_colormap, &tmp_color);
+
+ G_colormap = XCopyColormapAndFree(DISP, G_colormap);
+ temp_args1[2].value = (XtArgVal) G_colormap;
+ XtSetValues(globals.widgets.top_level, temp_args1 + 2, 1);
+ }
+
+ XtGetApplicationResources(globals.widgets.top_level, (XtPointer)&resource,
+ app_pixel_resources, XtNumber(app_pixel_resources),
+ (ArgList)NULL, 0);
+
+#endif /* GREY */
+
+ globals.gc.do_copy = resource.copy;
+
+#if GREY || COLOR
+ color_data[0].pixel = resource.fore_Pixel;
+ color_data[1].pixel = resource.back_Pixel;
+ XQueryColors(DISP, G_colormap, color_data, 2);
+#endif
+
+#if COLOR
+ fg_initial.r = color_data[0].red;
+ fg_initial.g = color_data[0].green;
+ fg_initial.b = color_data[0].blue;
+ bg_initial.r = color_data[1].red;
+ bg_initial.g = color_data[1].green;
+ bg_initial.b = color_data[1].blue;
+
+#endif
+
+#if GREY
+ if (G_depth == 1) {
+#ifdef XSERVER_INFO
+ if (globals.debug & DBG_ALL)
+ fprintf(stdout, "--- using depth 1\n");
+#endif
+ resource.use_grey = False;
+ }
+ if (resource.use_grey && G_visual->class != TrueColor) {
+#ifdef XSERVER_INFO
+ if (globals.debug & DBG_ALL)
+ fprintf(stdout, "--- using grey, but not TrueColor\n");
+#endif
+ init_plane_masks();
+ if (!globals.gc.do_copy) {
+ /* Retain color_data[1].pixel for psgs.c. */
+ XColor tmp_color;
+#ifdef XSERVER_INFO
+ if (globals.debug & DBG_ALL)
+ fprintf(stdout, "--- not using copy\n");
+#endif
+
+ tmp_color = color_data[1];
+ tmp_color.pixel = resource.back_Pixel;
+ XStoreColor(DISP, G_colormap, &tmp_color);
+ }
+ }
+#endif
+}
+
+static void
+create_widgets(
+#ifdef MOTIF
+ Widget tool_bar, Widget form,
+#endif
+ int *add_w, int *add_h)
+{
+ static const char default_key_translations[] =
+ "\"0\":digit(0)\n"
+ "\"1\":digit(1)\n"
+ "\"2\":digit(2)\n"
+ "\"3\":digit(3)\n"
+ "\"4\":digit(4)\n"
+ "\"5\":digit(5)\n"
+ "\"6\":digit(6)\n"
+ "\"7\":digit(7)\n"
+ "\"8\":digit(8)\n"
+ "\"9\":digit(9)\n"
+ /* "\"-\":minus()\n" */
+ "<Motion>:motion()\n";
+
+ static const char default_mouse_translations[] =
+ "<BtnUp>:release()";
+
+#ifdef MOTIF
+ Widget status_line;
+
+#if 0
+ {
+ int i, n, longest_page = 0;
+ Dimension width, height;
+ char tmpbuf[1024];
+ char *fontname;
+ XmString tmpstring;
+ Widget dummy_list;
+ XmRendition rendition;
+ XmRenderTable rtable;
+ Arg args[10];
+ /*
+ * Try to determine width of longest page string:
+ */
+ for (i = 0; i < total_pages; i++) {
+ int curr = abs(pageinfo_get_number(i));
+ if (curr > longest_page)
+ longest_page = curr;
+ }
+ fprintf(stderr, "longest page number: %d\n", longest_page);
+ sprintf(tmpbuf, "* %d", longest_page);
+ tmpstring = XmStringCreateLocalized(tmpbuf);
+ dummy_list = XtCreateWidget("PageList", xmListWidgetClass, form, NULL, 0);
+ fprintf(stderr, "rendition table\n");
+ n = 0;
+/* XtVaGetValues(globals.widgets.top_level, XmNfontList, &fontname, NULL); */
+/* fprintf(stderr, "fontname: |%s|\n", fontname); */
+ XtSetArg(args[n], XmNfontName, "8x16"); n++;
+ XtSetArg(args[n], XmNfontType, XmFONT_IS_FONT); n++;
+ rendition = XmRenditionCreate(dummy_list, XmFONTLIST_DEFAULT_TAG, args, n);
+ rtable = XmRenderTableAddRenditions(NULL, &rendition, 1, XmMERGE_REPLACE);
+ XtVaSetValues(dummy_list, XmNrenderTable, rtable, NULL);
+
+ /* rendition = XmRenditionCreate(globals.widgets.top_level, XmFONTLIST_DEFAULT_TAG, NULL, 0); */
+ fprintf(stderr, "extent\n");
+ XmStringExtent(rtable, tmpstring, &width, &height);
+ fprintf(stderr, "string %s has width %d, height %d\n", tmpbuf, width, height);
+ XtDestroyWidget(dummy_list);
+ XmRenditionFree(rendition);
+ XmStringFree(tmpstring);
+ }
+#endif
+ {
+#define ARG_LEN 20
+ int n = 0;
+ Arg list_args[ARG_LEN];
+
+ XtSetArg(list_args[n], XmNlistSizePolicy, XmVARIABLE); n++;
+ XtSetArg(list_args[n], XmNwidth, resource.pagelist_width); n++;
+#if defined(USE_PANNER) && USE_XAW_PANNER
+ XtSetArg(list_args[n], XmNheight, globals.page.h - 62); n++;
+#else
+ XtSetArg(list_args[n], XmNheight, globals.page.h); n++;
+#endif
+/* XtSetArg(list_args[n], XmNspacing, 10); n++; */
+#if defined(USE_PANNER) && USE_XAW_PANNER
+ XtSetArg(list_args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
+ XtSetArg(list_args[n], XmNtopWidget, panner); n++;
+#else
+ XtSetArg(list_args[n], XmNtopAttachment, XmATTACH_FORM); n++;
+#endif
+ XtSetArg(list_args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
+ XtSetArg(list_args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+ XtSetArg(list_args[n], XmNrightAttachment, XmATTACH_OPPOSITE_FORM); n++;
+ XtSetArg(list_args[n], XmNrightOffset, -resource.pagelist_width); n++;
+ XtSetArg(list_args[n], XmNresizable, True); n++;
+ XtSetArg(list_args[n], XmNtopOffset, 2); n++;
+ XtSetArg(list_args[n], XmNleftOffset, 2); n++;
+ ASSERT(n < ARG_LEN, "list_args too short");
+#undef ARG_LEN
+ /* TODO: Find a smart way to determine size of pagelist instead of using resource.pagelist_width,
+ and find a smart way of resizing it when switching to a file with larger page numbers!
+ */
+ page_list = XmCreateScrolledList(form, "PageList", list_args, n);
+ }
+
+ if (resource.expert_mode == XPRT_SHOW_NONE) {
+ XtUnmanageChild(XtParent(page_list));
+ XtUnmanageChild(page_list);
+ }
+
+ globals.widgets.main_window = XtVaCreateManagedWidget("mainWindow",
+ xmScrolledWindowWidgetClass, form,
+ XmNscrollingPolicy, XmAUTOMATIC,
+ XmNleftAttachment, XmATTACH_WIDGET,
+ /* lesstif balks if we just use page_list, so use its parent,
+ the xmScrolledWindow, for alignment: */
+ XmNleftWidget, XtParent(page_list),
+ XmNallowResize, True,
+/* XmNtopOffset, 2, */
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ /* XmNleftOffset, 10, */
+ XmNresizable, True,
+ XmNborderWidth, 0,
+ NULL);
+ XtManageChild(form);
+
+ globals.widgets.x_bar = XtNameToWidget(globals.widgets.main_window, "HorScrollBar");
+ globals.widgets.y_bar = XtNameToWidget(globals.widgets.main_window, "VertScrollBar");
+
+
+#ifdef TEST_SCROLLING
+ /* TODO: try the following to prevent `flashing' effect - still breaks
+ scrolling in its current form though */
+ globals.widgets.draw_background = XtVaCreateManagedWidget("drawing_bg",
+ xmFormWidgetClass, globals.widgets.main_window,
+ XmNwidth, globals.page.w,
+ XmNheight, globals.page.h,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNhighlightThickness, 0,
+ XmNbackground, resource.back_Pixel,
+ XmNrubberPositioning, True,
+ NULL);
+#endif
+ globals.widgets.draw_widget = XtVaCreateWidget("drawing",
+ xmDrawingAreaWidgetClass,
+#ifdef TEST_SCROLLING
+ globals.widgets.draw_background,
+#else
+ globals.widgets.main_window,
+#endif
+ XmNwidth, globals.page.w,
+ XmNheight, globals.page.h,
+ XmNhighlightThickness, 0,
+ XmNrubberPositioning, True,
+ XtNbackground, resource.back_Pixel,
+ NULL);
+
+#if !FIXED_FLUSHING_PAGING
+ ASSERT(XtParent(globals.widgets.draw_widget) != NULL, "");
+ XtVaSetValues(XtParent(globals.widgets.draw_widget), XtNbackground, resource.back_Pixel, NULL);
+#endif
+
+#ifdef TEST_SCROLLING
+ fprintf(stderr, "globals.widgets.draw_widget is: %p\n", globals.widgets.draw_widget);
+#endif
+ XtVaGetValues(globals.widgets.main_window, XmNclipWindow, &globals.widgets.clip_widget, NULL);
+
+ XtVaSetValues(globals.widgets.main_row,
+ XmNmenuBar, globals.widgets.menu_bar,
+ XmNcommandWindow, XtParent(tool_bar),
+ XmNworkWindow, form,
+ NULL);
+
+ XtVaSetValues(globals.widgets.main_window,
+ XmNworkWindow, globals.widgets.draw_widget,
+ NULL);
+
+ XtManageChild(globals.widgets.draw_widget);
+
+ status_line = create_statusline(globals.widgets.main_row);
+ XtVaSetValues(globals.widgets.main_row,
+ XmNmessageWindow, status_line,
+ NULL);
+ if ((resource.expert_mode & XPRT_SHOW_STATUSLINE) == 0) {
+ XtUnmanageChild(status_line);
+ }
+
+ XtManageChild(globals.widgets.main_row);
+
+ if ((resource.expert_mode & XPRT_SHOW_TOOLBAR) != 0) {
+ if (resource.toolbar_unusable)
+ statusline_print(STATUS_LONG,
+ "Error creating the toolbar pixmaps - toolbar is disabled!");
+ else
+ XtManageChild(XtParent(tool_bar));
+ }
+
+ if ((resource.expert_mode & XPRT_SHOW_MENUBAR) != 0)
+ XtManageChild(globals.widgets.menu_bar);
+
+ XmAddTabGroup(globals.widgets.draw_widget);
+
+ /*
+ note: a few more custom translations for page_list are defined in
+ pagesel.c, since the actions are only known there.
+ */
+ {
+ size_t i, k = 0;
+#define WIDGETS_SIZE 10
+ Widget widgets[WIDGETS_SIZE];
+
+ widgets[k++] = globals.widgets.main_row;
+/* widgets[k++] = globals.widgets.menu_bar; */
+ widgets[k++] = tool_bar;
+ widgets[k++] = page_list;
+ widgets[k++] = globals.widgets.main_window;
+ widgets[k++] = globals.widgets.draw_widget;
+ widgets[k++] = globals.widgets.clip_widget;
+
+ ASSERT(k < WIDGETS_SIZE, "widgets list too short");
+#undef WIDGETS_SIZE
+ for (i = 0; i < k; i++) {
+ XtOverrideTranslations(widgets[i], XtParseTranslationTable(base_key_translations));
+ XtOverrideTranslations(widgets[i], XtParseTranslationTable(default_key_translations));
+ if (i > 3) { /* widgets for which we want to use our own mouse translations */
+ XtOverrideTranslations(widgets[i], XtParseTranslationTable(base_mouse_translations));
+ XtOverrideTranslations(widgets[i], XtParseTranslationTable(default_mouse_translations));
+ }
+ }
+ }
+
+ if (resource.main_translations != NULL) {
+ XtOverrideTranslations(globals.widgets.draw_widget, XtParseTranslationTable(resource.main_translations));
+ XtOverrideTranslations(globals.widgets.clip_widget, XtParseTranslationTable(resource.main_translations));
+ /* don't do it for the page list, otherwise mouse customizations will break
+ the default list bindings too. */
+ /* XtOverrideTranslations(page_list, XtParseTranslationTable(resource.main_translations)); */
+ }
+ /* widgets for which wheel mouse should scroll the drawing area */
+ if (resource.wheel_unit != 0 && resource.wheel_translations != NULL) {
+ XtOverrideTranslations(globals.widgets.main_row, XtParseTranslationTable(resource.wheel_translations));
+ XtOverrideTranslations(tool_bar, XtParseTranslationTable(resource.wheel_translations));
+ XtOverrideTranslations(globals.widgets.main_window, XtParseTranslationTable(resource.wheel_translations));
+ XtOverrideTranslations(globals.widgets.draw_widget, XtParseTranslationTable(resource.wheel_translations));
+/* XtOverrideTranslations(globals.widgets.draw_background, XtParseTranslationTable(resource.wheel_translations)); */
+ }
+
+#else /* MOTIF */
+
+ globals.widgets.form_widget = XtVaCreateManagedWidget("form", formWidgetClass, globals.widgets.top_level,
+ XtNdefaultDistance, 0,
+ NULL);
+ globals.widgets.vport_widget = XtVaCreateManagedWidget("vport", viewportWidgetClass,
+ globals.widgets.form_widget,
+ XtNborderWidth, 0,
+ XtNtop, XtChainTop,
+ XtNbottom, XtChainBottom,
+ XtNleft, XtChainLeft,
+ XtNright, XtChainRight,
+ XtNallowHoriz, True,
+ XtNallowVert, True,
+ NULL);
+ globals.widgets.clip_widget = XtNameToWidget(globals.widgets.vport_widget, "clip");
+
+ globals.widgets.draw_widget = XtVaCreateManagedWidget("drawing", drawWidgetClass, globals.widgets.vport_widget,
+ XtNwidth, globals.page.w,
+ XtNheight, globals.page.h,
+ XtNx, 0,
+ XtNy, 0,
+ XtNlabel, "",
+ NULL);
+
+ XtOverrideTranslations(globals.widgets.form_widget, XtParseTranslationTable(base_key_translations));
+ XtOverrideTranslations(globals.widgets.form_widget, XtParseTranslationTable(base_mouse_translations));
+ XtOverrideTranslations(globals.widgets.form_widget, XtParseTranslationTable(default_key_translations));
+ XtOverrideTranslations(globals.widgets.form_widget, XtParseTranslationTable(default_mouse_translations));
+
+ if (resource.wheel_unit != 0 && resource.wheel_translations != NULL)
+ XtOverrideTranslations(globals.widgets.form_widget, XtParseTranslationTable(resource.wheel_translations));
+
+ if (resource.main_translations != NULL) {
+ XtOverrideTranslations(globals.widgets.form_widget, XtParseTranslationTable(resource.main_translations));
+ }
+
+
+ /* set background colors of the drawing widget */
+ XtVaSetValues(globals.widgets.draw_widget, XtNbackground, resource.back_Pixel, NULL);
+
+#if !FIXED_FLUSHING_PAGING
+ XtVaSetValues(globals.widgets.clip_widget, XtNbackground, resource.back_Pixel, NULL);
+#endif
+
+ /* initialize add_w with width of button panel */
+ if ((resource.expert_mode & XPRT_SHOW_BUTTONS) != 0)
+ create_menu_buttons(globals.widgets.form_widget, add_w);
+ else
+ *add_w = 0;
+#endif /* MOTIF */
+
+ /* activate expert mode and related settings */
+ toggle_statusline();
+ toggle_scrollbars();
+#ifdef MOTIF
+ toggle_pagelist();
+ toggle_toolbar();
+ toggle_menubar();
+#else
+ toggle_buttons();
+#endif
+
+#ifdef MOTIF
+ *add_w = 0;
+ if (resource.expert_mode & XPRT_SHOW_PAGELIST)
+ *add_w += xm_get_width(page_list);
+/* if (globals.widgets.y_bar != NULL) */
+/* add_w += xm_get_width(globals.widgets.y_bar); */
+ *add_h = 0;
+ if (resource.expert_mode & XPRT_SHOW_MENUBAR)
+ *add_h += xm_get_height(globals.widgets.menu_bar);
+ if (resource.expert_mode & XPRT_SHOW_TOOLBAR)
+ *add_h += xm_get_height(tool_bar);
+ if (resource.expert_mode & XPRT_SHOW_STATUSLINE)
+ *add_h += xm_get_height(status_line);
+/* if (globals.widgets.x_bar != NULL) */
+/* add_h += xm_get_width(globals.widgets.x_bar); */
+#else
+ /* add_w has been initialized by create_menu_buttons() call above */
+ *add_h = 0;
+#endif
+}
+
+
+static void
+realize_widgets(Dimension main_win_w, Dimension main_win_h, int add_w)
+{
+ /*
+ * Realize the widgets (or windows).
+ */
+
+#ifndef MOTIF
+ if ((resource.expert_mode & XPRT_SHOW_BUTTONS) != 0) {
+ set_button_panel_height(main_win_h);
+ }
+#endif
+ XtAddEventHandler(
+#ifdef MOTIF
+ globals.widgets.clip_widget,
+#else
+ globals.widgets.vport_widget,
+#endif
+ StructureNotifyMask, False,
+ handle_resize, (XtPointer) NULL);
+
+ XtAddEventHandler(globals.widgets.top_level, PropertyChangeMask, False,
+ handle_property_change, (XtPointer) NULL);
+ XtAddEventHandler(globals.widgets.draw_widget, ExposureMask, False, handle_expose,
+ (XtPointer) &mane);
+ XtRealizeWidget(globals.widgets.top_level);
+
+ mainDeleteWindow = XInternAtom(DISP, "WM_DELETE_WINDOW", False);
+
+#ifdef MOTIF
+ /* for Xaw, event handlers for scrollbars are added inside get_geom(), events.c */
+ ASSERT(globals.widgets.x_bar != NULL, "");
+ ASSERT(globals.widgets.y_bar != NULL, "");
+ XtAddEventHandler(globals.widgets.x_bar, ButtonPressMask | ButtonReleaseMask, False, handle_x_scroll, NULL);
+ XtAddEventHandler(globals.widgets.y_bar, ButtonPressMask | ButtonReleaseMask, False, handle_y_scroll, NULL);
+ XmAddWMProtocolCallback(globals.widgets.top_level, mainDeleteWindow, xdvi_exit_callback, NULL);
+#else
+ wmProtocols = XInternAtom(DISP, "WM_PROTOCOLS", False);
+ XSetWMProtocols(DISP, XtWindow(globals.widgets.top_level), &mainDeleteWindow, 1);
+ XtAddEventHandler(globals.widgets.top_level, NoEventMask, True, handle_delete_message, NULL);
+#endif
+
+ /* check whether we want to run in fullscreen mode */
+ if (resource.fullscreen) {
+ reconfigure_window(resource.fullscreen, main_win_w + add_w, main_win_h, False);
+ }
+
+#ifdef MOTIF
+ XmProcessTraversal(globals.widgets.draw_widget, XmTRAVERSE_CURRENT);
+ TRACE_GUI((stderr, "toplevel: %p", (void *)globals.widgets.top_level));
+ create_tips(globals.widgets.top_level);
+#else
+ if ((resource.expert_mode & XPRT_SHOW_STATUSLINE) != 0) {
+ create_statusline();
+ }
+#endif
+
+ currwin.win = mane.win = XtWindow(globals.widgets.draw_widget);
+
+ {
+ XWindowAttributes attrs;
+
+ (void)XGetWindowAttributes(DISP, mane.win, &attrs);
+ G_backing_store = attrs.backing_store;
+ }
+
+#ifdef HAVE_X11_XMU_EDITRES_H
+ /*
+ * Enable editres protocol (see "man editres").
+ * Usually will need to add -lXmu to the linker line as well.
+ */
+ XtAddEventHandler(globals.widgets.top_level, (EventMask)0, True, _XEditResCheckMessages,
+ (XtPointer)NULL);
+#endif
+}
+
+/*
+ * Create colors and GCs.
+ * In color mode, color changes affect globals.gc.fore, globals.gc.fore2,
+ * and globals.gc.rule, but not globals.gc.copy or globals.gc.high.
+ */
+static void
+create_gcs(void)
+{
+
+#if GREY
+ if (resource.gamma == 0.0)
+ resource.gamma = 1.0;
+#endif
+
+ if (!resource.rule_color)
+ resource.rule_pixel = resource.fore_Pixel;
+
+#if !COLOR
+
+#if GREY
+ if (resource.use_grey)
+ init_pix();
+ else
+#endif
+ { /* not #defined GREY, or not resource.use_grey */
+ XGCValues values;
+ Pixel set_bits = (Pixel) (resource.fore_Pixel & ~resource.back_Pixel);
+ Pixel clr_bits = (Pixel) (resource.back_Pixel & ~resource.fore_Pixel);
+ Boolean copy_tmp = resource.copy;
+
+ globals.gc.copy = set_or_make_gc(NULL, GXcopy, resource.fore_Pixel, resource.back_Pixel);
+ if (copy_tmp || (set_bits && clr_bits)) {
+ globals.gc.rule = globals.gc.copy;
+ if (!resource.thorough)
+ copy_tmp = True;
+ }
+ if (copy_tmp) {
+ globals.gc.fore = globals.gc.rule;
+ if (!resource.copy) {
+ warn_overstrike();
+ }
+ }
+ else {
+ if (set_bits) {
+ globals.gc.fore = set_or_make_gc(NULL, GXor, set_bits, 0);
+ }
+ if (clr_bits || !set_bits)
+ *(globals.gc.fore ? &globals.gc.fore2 : &globals.gc.fore) = set_or_make_gc(NULL, GXandInverted, clr_bits, 0);
+ if (!globals.gc.rule)
+ globals.gc.rule = globals.gc.fore;
+ }
+ }
+#endif /* !COLOR */
+
+ {
+ Pixel link_pix, visited_link_pix;
+ get_link_colors(&link_pix, &visited_link_pix);
+ globals.gc.linkcolor = set_or_make_gc(NULL, GXcopy, link_pix, resource.back_Pixel);
+ globals.gc.visited_linkcolor = set_or_make_gc(NULL, GXcopy, visited_link_pix, resource.back_Pixel);
+ }
+
+#if COLOR
+ /* Not affected by color changes. */
+ globals.gc.copy = set_or_make_gc(NULL, GXcopy, resource.fore_Pixel, resource.back_Pixel);
+#endif
+ globals.gc.high = set_or_make_gc(NULL, GXcopy, resource.hl_Pixel, resource.back_Pixel);
+
+ globals.gc.ruler = set_or_make_gc(NULL, GXcopy, resource.rule_pixel, resource.fore_Pixel);
+
+#if XAW
+ /*
+ * There's a bug in the Xaw toolkit, in which it uses the
+ * DefaultGCOfScreen to do vertical scrolling in the Text widget.
+ * This leads to a BadMatch error if our visual is not the default one.
+ * The following kludge works around this.
+ */
+ DefaultGCOfScreen(SCRN) = globals.gc.copy;
+#endif
+}
+
+static void
+do_fork(void)
+{
+ TRACE_CLIENT((stderr, "no other instance of xdvi found, forking ..."));
+ /*
+ * No suitable xdvi found, so we start one by
+ * self-backgrounding.
+ */
+ /* flush output buffers to avoid double buffering (i.e. data
+ waiting in the output buffer being written twice, by the parent
+ and the child) */
+ fflush(stdout);
+ fflush(stderr);
+ XFlush(DISP);
+ if (fork()) /* if initial process (do NOT use vfork()!) */
+ _exit(0);
+}
+
+#if defined(MOTIF) && defined(USE_PANNER) && USE_XAW_PANNER
+static void
+panner_cb(Widget widget, XtPointer closure, XtPointer report_ptr)
+{
+ fprintf(stderr, "panner_cb called!\n");
+}
+#endif
+
+
+static XtIntervalId m_font_popup_id = 0;
+static Widget m_font_popup = 0;
+
+static void
+remove_font_popup(XtPointer client_data, XtIntervalId *id)
+{
+ UNUSED(client_data);
+ UNUSED(id);
+
+ if (m_font_popup != 0) {
+ kill_message_window(m_font_popup);
+ }
+}
+
+static void
+remove_font_popup_exit_cb(XtPointer arg)
+{
+ UNUSED(arg);
+ xdvi_exit(EXIT_SUCCESS);
+}
+
+static void
+create_font_popup(XtPointer client_data, XtIntervalId *id)
+{
+ int *curr_timeout = (int *)client_data;
+ static int new_timeout = 0;
+
+ UNUSED(client_data);
+ UNUSED(id);
+
+ if (m_font_popup_id) {
+ if (*curr_timeout > 0) {
+ XtRemoveTimeOut(m_font_popup_id);
+ m_font_popup_id = XtAppAddTimeOut(app, *curr_timeout, create_font_popup, (XtPointer)&new_timeout);
+ }
+ else {
+ m_font_popup = choice_dialog(globals.widgets.top_level,
+ MSG_INFO, NULL,
+#ifndef MOTIF
+ NULL,
+#endif
+ NULL, NULL, /* no pre_callbacks */
+ NULL, NULL, NULL, /* default arguments for `OK' */
+ "Exit Xdvi", remove_font_popup_exit_cb, (XtPointer)NULL,
+ "Loading %s\n(may take some time creating fonts ...)",
+ globals.dvi_name);
+ }
+ }
+}
+
+static void
+register_font_popup(void)
+{
+ /* Use a two-step process, so that when the timeout is removed by unregister_font_popup(),
+ it will occur before new_timeout. create_font_popup() will call XtAppAddTimeOut() again
+ with new_timeout = 0.
+ */
+ static int new_timeout = 50;
+ m_font_popup_id = XtAppAddTimeOut(app, 700, create_font_popup, (XtPointer)&new_timeout);
+}
+
+static void
+unregister_font_popup(void)
+{
+ if (m_font_popup_id) {
+ XtRemoveTimeOut(m_font_popup_id);
+ m_font_popup_id = 0;
+ /* FIXME: calling this directly crashes xdvi?? */
+ /* m_font_popup_id = XtAppAddTimeOut(app, 1, remove_font_popup, (XtPointer)NULL); */
+ remove_font_popup(NULL, NULL);
+ }
+}
+
+/* initialize global variables with default values. */
+static void
+init_globals(void) {
+ globals.program_name = NULL;
+ globals.dvi_name = NULL;
+ globals.xdvi_dir = xgetcwd();
+ globals.orig_locale = NULL;
+ globals.debug = 0L;
+ globals.pageno_correct = 1;
+
+ globals.curr_paper = NULL;
+ globals.curr_editor = NULL;
+ globals.curr_browser = NULL;
+
+ globals.ev.flags = EV_IDLE;
+ globals.ev.ctr = 0;
+
+ globals.pausing.num = 0;
+ globals.pausing.num_save = NULL;
+ globals.pausing.flag = False;
+
+ globals.win_expose.min_x = 0;
+ globals.win_expose.max_x = 0;
+ globals.win_expose.min_y = 0;
+ globals.win_expose.max_y = 0;
+
+ globals.gc.rule = NULL;
+ globals.gc.fore = NULL;
+ globals.gc.inverted = NULL;
+ globals.gc.high = NULL;
+ globals.gc.linkcolor = NULL;
+ globals.gc.visited_linkcolor = NULL;
+ globals.gc.fore2 = NULL;
+ globals.gc.fore2_bak = NULL;
+ globals.gc.fore2_bak1 = NULL;
+ globals.gc.copy = NULL;
+ globals.gc.ruler = NULL;
+
+ globals.gc.do_copy = False;
+
+ globals.cursor.flags = 0;
+
+ globals.src.fwd_box_page = -1; /* -1 means no box */
+ globals.src.fwd_string = NULL;
+
+ globals.widgets.top_level = 0;
+ globals.widgets.draw_widget = 0;
+ globals.widgets.draw_background = 0;
+ globals.widgets.clip_widget = 0;
+ globals.widgets.x_bar = 0;
+ globals.widgets.y_bar = 0;
+#ifdef MOTIF
+ globals.widgets.main_window = 0;
+ globals.widgets.main_row = 0;
+ globals.widgets.tool_bar = 0;
+ globals.widgets.top_row = 0;
+ globals.widgets.menu_bar = 0;
+#else
+ globals.widgets.vport_widget = 0;
+ globals.widgets.form_widget = 0;
+ globals.widgets.paned = 0;
+#endif
+
+ globals.page.w = 0;
+ globals.page.h = 0;
+ globals.page.unshrunk_w = 0;
+ globals.page.unshrunk_h = 0;
+
+ globals.dvi_file.dirname = NULL;
+ globals.dvi_file.dirlen = 0;
+ globals.dvi_file.bak_fp = NULL;
+ globals.dvi_file.time = 0;
+
+#if defined(LESSTIF_VERSION)
+ globals.broken_motif_event_handling = True;
+#elif defined(MOTIF) /* was: && XmVersion <= 1002 - better use runtime information:*/
+ if (xmUseVersion <= 1002)
+ globals.broken_motif_event_handling = True;
+ else
+ globals.broken_motif_event_handling = False;
+#else
+ globals.broken_motif_event_handling = False;
+#endif
+
+}
+
+/* revert resources */
+void
+reload_app_resources(void)
+{
+/* /\* reset some resources to built-in defaults *\/ */
+/* resource.browser = NULL; */
+/* resource.editor = NULL; */
+/* resource.gamma = 1; */
+/* resource.link_style = 3; */
+/* resource.link_color = LINK_COLOR_FALLBACK; */
+/* resource.visited_link_color = VISITED_LINK_COLOR_FALLBACK; */
+/* resource.expert_mode = 31; */
+/* resource.use_color = True; */
+/* resource.match_highlight_inverted = True; */
+
+ XtGetApplicationResources(globals.widgets.top_level, (XtPointer)&resource,
+ application_resources, XtNumber(application_resources),
+ (ArgList)NULL, 0);
+ XtGetApplicationResources(globals.widgets.top_level, (XtPointer)&resource,
+ app_pixel_resources, XtNumber(app_pixel_resources),
+ (ArgList)NULL, 0);
+/* fprintf(stderr, "gamma: %f\n", resource.gamma); */
+}
+
+struct filehist_info {
+ int file_idx;
+ char *page_arg;
+};
+
+
+/*
+ * Unfortunately this must be a callback, for the file selector ...
+ * This is the second part of Main: Create all widgets, initialize the DVI file,
+ * and enter the main event loop.
+ */
+static void
+run_dvi_file(const char *filename, void *data)
+{
+ Boolean tried_dvi_ext = False;
+ struct filehist_info *cb = (struct filehist_info *)data;
+
+#ifdef MOTIF
+ Widget tool_bar = 0;
+ Widget form = 0;
+#endif
+
+ char *title_name = NULL;
+ char *icon_name = NULL;
+ dviErrFlagT errflag = NO_ERROR;
+
+ int add_w, add_h;
+ Dimension main_win_w, main_win_h;
+
+ UNUSED(data);
+ ASSERT(filename != NULL, "filename must have been initialized here!");
+
+ globals.dvi_name = xstrdup(filename);
+ file_history_push(globals.dvi_name);
+
+ TRACE_FILES((stderr, "globals.dvi_name is: |%s| %p\n", globals.dvi_name, globals.dvi_name));
+
+ globals.dvi_file.dirname = get_dir_component(globals.dvi_name);
+ ASSERT(globals.dvi_file.dirname != NULL, "dvi_name must contain a dir component");
+ globals.dvi_file.dirlen = strlen(globals.dvi_file.dirname);
+
+ form_dvi_property();
+
+ /*
+ If `unique' is active, we may need to pass the file
+ to a different instance of xdvi:
+ */
+ if (resource.unique) {
+ Window w1 = 0, w2 = 0;
+ if ((w1 = get_xdvi_window_id(True, NULL)) != 0 || (w2 = get_xdvi_window_id(False, NULL)) != 0) {
+ if (w1 != 0) { /* another xdvi, and same file: reload and raise */
+ w2 = w1;
+ set_string_property("", atom_reload(), w2);
+ set_string_property("", atom_raise(), w2);
+ }
+ else { /* another xdvi, and different file: load new file and raise */
+ set_string_property(globals.dvi_name, atom_newdoc(), w2);
+ set_string_property("", atom_raise(), w2);
+ }
+ if (cb->page_arg != NULL) { /* switch to different page and raise */
+ if (strlen(cb->page_arg) == 0) /* special case: treat `+' as last page */
+ set_string_property("+", atom_newpage(), w2);
+ else
+ set_string_property(cb->page_arg, atom_newpage(), w2);
+ set_string_property("", atom_raise(), w2);
+ }
+ xdvi_exit(EXIT_SUCCESS);
+ }
+ else if (resource.src_fork) {
+ do_fork();
+ }
+ }
+
+ /*
+ Similar for forward search or string search:
+ */
+ if (resource.src_pos != NULL || resource.find_string != NULL) {
+ Window w;
+ if ((w = get_xdvi_window_id(True, NULL)) != 0) {
+ /* another instance of xdvi running, displaying the same file */
+ TRACE_CLIENT((stderr, "Match; changing property of client and exiting ..."));
+ if (resource.src_pos != NULL)
+ set_sourceposition_property(resource.src_pos, w);
+ else
+ set_stringsearch_property(resource.find_string, w);
+ xdvi_exit(EXIT_SUCCESS);
+ }
+ else if (resource.src_fork) {
+ do_fork();
+ }
+ }
+
+ /* Needed for source specials and for calling ghostscript. */
+ xputenv("DISPLAY", XDisplayString(DISP));
+
+
+ if (globals.debug) {
+ fprintf(stderr, "%s %s, kpathsea: %s\n", XDVIK_PROGNAME, XDVI_VERSION_INFO, kpathsea_version_string);
+ fprintf(stderr,
+ "configured with: ppi=%d shrink=%d mfmode=%s alt_font=%s paper=%s\n",
+ resource.pixels_per_inch,
+ currwin.shrinkfactor,
+ resource.mfmode ? resource.mfmode : "<NONE>",
+ resource.alt_font,
+ resource.paper);
+ }
+
+#ifdef T1LIB
+ /* needed so that T1lib can produce tfm's e.g. for cm-super */
+ kpse_set_program_enabled(kpse_tfm_format, True, kpse_src_compile);
+#endif
+ kpse_set_program_enabled(kpse_any_glyph_format, resource.makepk, kpse_src_compile);
+ /* janl 16/11/98: I have changed this. The above line used to
+ say the settings in resource.makepk was supplied on the
+ commandline, resulting in it overriding _all other_
+ settings, derived from the environment or texmf.cnf, no
+ matter what the value. The value in resource.makepk could
+ be the compile-time default...
+
+ Personaly I like the environment/texmf.cnf to override
+ resources and thus changed the 'level' of this setting to
+ kpse_src_compile so the environment/texmf.cnf will override
+ the values derived by Xt.
+
+ Previous comment here:
+
+ ``Let true values as an X resource/command line override false
+ values in texmf.cnf/envvar.'' */
+
+ /*
+ * Step 2: Settle colormap issues. This should be done before
+ * other widgets are created, so that they get the right
+ * pixel values. (The top-level widget won't have the right
+ * values, but I don't think that makes any difference.)
+ */
+
+#ifdef XSERVER_INFO
+ print_xserver_info();
+#endif
+
+ create_colormaps();
+
+
+#ifdef TESTING_OPEN_FILES
+ fprintf(stderr, "open_max: %ld\n", OPEN_MAX);
+ for (i = 0; i < OPEN_MAX - 10; i++) {
+ FILE *fp;
+ if ((fp = fopen("/tmp/foo", "r")) == NULL) {
+ perror("fopen");
+ xdvi_exit(EXIT_FAILURE);
+ }
+ }
+ fprintf(stderr, "opened %d files.\n", i);
+#endif
+
+
+ /* toolbar code may open files, but we have no check close_a_file() in
+ the toolbar code; so do this before prescan() possibly opens lots of files.
+ */
+#ifdef MOTIF
+ globals.widgets.main_row = XmCreateMainWindow(globals.widgets.top_level, "main", NULL, 0);
+
+ create_menu_buttons(globals.widgets.main_row, &globals.widgets.menu_bar);
+
+ /* seems to be needed for enabling `XmNhighlightOnEnter' for the toolbar buttons
+ - is this the correct place to do it? */
+ XtVaSetValues(globals.widgets.top_level, XmNkeyboardFocusPolicy, (XtArgVal)XmPOINTER, NULL);
+
+ form = XtVaCreateWidget("form", xmFormWidgetClass, globals.widgets.main_row,
+ XmNshadowThickness, 0,
+ NULL);
+#if defined(USE_PANNER) && USE_XAW_PANNER
+ panner = XtVaCreateWidget("panner", pannerWidgetClass, form,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 20,
+ XmNrightAttachment, XmATTACH_OPPOSITE_FORM,
+ XmNrightOffset, -resource.pagelist_width + 20,
+ XmNtopOffset, 2,
+ XmNleftOffset, 2,
+ XtNheight, 60,
+ XtNwidth, resource.pagelist_width - 50,
+ XtNsliderX, 5,
+ XtNsliderY, 7,
+ XtNinternalSpace, 0,
+ XtNshadowThickness, 0,
+ NULL);
+#endif
+#endif
+
+ /* use bounding box for highlighting if our visual isn't TrueColor
+ (not worth the trouble ...) */
+ if (G_visual->class != TrueColor) {
+ resource.match_highlight_inverted = False;
+ }
+
+ /*
+ * Step 3: Initialize the dvi file and set titles.
+ */
+
+#ifdef T1LIB
+ /*
+ At this point DISP, G_visual, G_depth and G_colormap must
+ be defined. Also, init_t1() must go before internal_open_dvi(), since
+ read_postamble will define some fonts and insert them into
+ fontmaps_hash, but we need a clean fontmaps_hash for detecting
+ duplicate entries in the map file.
+ */
+
+ if (resource.t1lib) {
+ init_t1();
+ }
+#endif /* T1LIB */
+
+
+ setup_signal_handlers();
+
+ /* Notify users that fonts are being created. This is just a hack
+ and no replacement for true asynchronous font creation (see
+ EXPERIMENTAL_DELAYED_MTKEXPK in font-open.c for that approach)
+ since it doesn't give details (is just invoked if startup takes
+ somewhat longer) and freezes during font creation.
+ */
+ register_font_popup();
+
+ /* open and initialize the DVI file, but don't read the fonts yet */
+ if (!internal_open_dvi(globals.dvi_name, &errflag,
+#ifdef EXPERIMENTAL_DELAYED_MTKEXPK
+ False
+#else
+ True
+#endif
+ )) {
+ if (tried_dvi_ext)
+ XDVI_FATAL((stderr, "Could not open %s: %s, and %s.dvi doesn't exist either - exiting.",
+ globals.dvi_name, get_dvi_error(errflag), globals.dvi_name));
+ else
+ XDVI_FATAL((stderr, "Could not open %s: %s.",
+ globals.dvi_name, get_dvi_error(errflag)));
+ }
+
+ unregister_font_popup();
+
+ if (cb->page_arg != NULL) {
+ if (cb->page_arg[0] == '\0') { /* empty page_arg -> goto last page */
+ current_page = total_pages - 1;
+ page_history_insert(current_page);
+ }
+ else {
+ char *testptr;
+ current_page = strtoul(cb->page_arg, &testptr, 10) - 1;
+ if (*testptr != '\0') {
+ XDVI_FATAL((stderr, "Invalid page number: `%s'.", cb->page_arg));
+ }
+ current_page = check_goto_page(current_page);
+ }
+ }
+
+ file_history_set_page(current_page);
+
+ ASSERT(globals.dvi_file.bak_fp != NULL, "Backup file pointer must have been initialized here");
+ if (resource.prescan) {
+ prescan(globals.dvi_file.bak_fp);
+ }
+
+ globals.page.unshrunk_w = pageinfo_get_page_width(current_page);
+ globals.page.unshrunk_h = pageinfo_get_page_height(current_page);
+ TRACE_FILES((stderr, "globals.page.unshrunk_w: %d, h: %d; window: %d, %d",
+ globals.page.unshrunk_w, globals.page.unshrunk_h,
+ pageinfo_get_window_width(current_page),
+ pageinfo_get_window_height(current_page)));
+
+ init_page();
+
+ /*
+ * Step 4: Create widgets, and set initial window size.
+ */
+
+ /* currently these override expert mode - using this is deprecated
+ in favour of `-expertmode'; inform user about this: */
+ if (resource.statusline) {
+ XDVI_WARNING((stderr, "The option/X resource `statusline' is obsolete; "
+ "use `-expertmode <flag>' instead, e.g. `-expertmode 1'\n"
+ "to switch on the status line, or `-expertmode 6'\n"
+ "to switch it off. See the xdvi man page for details."));
+ resource.expert_mode |= XPRT_SHOW_STATUSLINE;
+ }
+
+/* XtRealizeWidget(globals.widgets.top_level); */
+
+#ifdef MOTIF
+ tool_bar = create_toolbar(globals.widgets.main_row, globals.widgets.menu_bar);
+#endif
+
+ create_widgets(
+#ifdef MOTIF
+ tool_bar, form,
+#endif
+ &add_w, &add_h);
+
+ /* fprintf(stderr, "geometry xdvirc: |%s|, orig: |%s|\n", resource.xdvirc_geometry, resource.geometry); */
+
+
+ /*
+ * Set initial window size.
+ * This needs to be done before colors are assigned because if
+ * -s 0 is specified, we need to compute the shrink factor
+ * (which in turn affects whether init_pix is called).
+ */
+ set_windowsize(&main_win_w, &main_win_h, add_w, add_h, False);
+
+ realize_widgets(main_win_w, main_win_h, add_w);
+
+ /* this needs to be done after total_pages is known (via internal_open_dvi) */
+ get_icon_and_title(globals.dvi_name, &icon_name, &title_name);
+ add_icon(globals.widgets.top_level, title_name, icon_name);
+ /* this needs to be done after the widgets have been created */
+ set_icon_and_title(icon_name, title_name);
+ free(icon_name);
+ free(title_name);
+ icon_name = title_name = NULL;
+
+
+ G_image = XCreateImage(DISP, G_visual, 1, XYBitmap, 0,
+ (char *)NULL, 0, 0, BMBITS, 0);
+ G_image->bitmap_unit = BMBITS;
+#ifdef WORDS_BIGENDIAN
+ G_image->bitmap_bit_order = MSBFirst;
+#else
+ G_image->bitmap_bit_order = LSBFirst;
+#endif
+ {
+ short endian = MSBFirst << 8 | LSBFirst;
+ G_image->byte_order = *((char *)&endian);
+ }
+
+ /* Store window id for use by src_client_check(). */
+ {
+#ifndef WORD64
+ xuint32 data = XtWindow(globals.widgets.top_level);
+ XChangeProperty(DISP, DefaultRootWindow(DISP),
+ atom_xdvi_windows(), atom_xdvi_windows(), 32,
+ PropModePrepend, (unsigned char *)&data, 1);
+#else
+ unsigned char data[4];
+ set_window_id(XtWindow(globals.widgets.top_level), data);
+ XChangeProperty(DISP, DefaultRootWindow(DISP),
+ atom_xdvi_windows(), atom_xdvi_windows(), 32,
+ PropModePrepend, data, 1);
+#endif
+ set_dvi_property();
+ }
+
+ /*
+ * Step 5: Assign colors and GCs.
+ * Because of the latter, this has to go after the widgets are realized.
+ */
+
+ create_gcs();
+
+ create_cursors();
+
+#ifdef EXPERIMENTAL_DELAYED_MTKEXPK
+ /* Only now, we initialize the fonts. First update the window: */
+ force_statusline_update();
+ printlog_create("test", "Close", NULL, NULL, NULL, NULL);
+ printlog_popup();
+
+ printlog_append_str("\nTrying to create font(s)\n");
+ if (!find_postamble(globals.dvi_file.bak_fp, &errflag) || !read_postamble(globals.dvi_file.bak_fp, &errflag, True)) {
+ XDVI_ERROR((stderr, "Couldn't read fonts from postamble: %s\n", get_dvi_error(errflag)));
+ }
+#endif /* EXPERIMENTAL_DELAYED_MTKEXPK */
+
+#ifdef MOTIF
+#if defined(USE_PANNER) && USE_XAW_PANNER
+ XtVaSetValues(panner, XtNsliderWidth, globals.page.w / 2,
+ XtNsliderHeight, globals.page.h / 2,
+ XtNcanvasWidth, globals.page.w,
+ XtNcanvasHeight, globals.page.h,
+ NULL);
+ XtManageChild(panner);
+ XtAddCallback(panner, XtNreportCallback, panner_cb, (XtPointer)NULL);
+#endif
+ create_pagelist();
+#endif
+
+ /* trigger forward search */
+ do_forward_search(resource.src_pos);
+
+ /* trigger string search */
+ if (resource.find_string != NULL) {
+ globals.ev.flags |= EV_FIND;
+ }
+
+ /* trigger anchor search */
+ if (resource.anchor_pos != NULL) {
+ g_anchor_pos = xstrdup(resource.anchor_pos);
+ g_anchor_len = strlen(g_anchor_pos);
+ globals.ev.flags |= EV_ANCHOR;
+ }
+
+#if defined(MOTIF) && HAVE_XPM
+ tb_check_navigation_sensitivity(current_page);
+#endif
+
+#if CHECK_APP_FILEVERSION
+ check_app_defaults_fileversion();
+#endif
+
+ /* can do this only after scrollbars have been realized */
+ if (!BROKEN_RECONFIG && (resource.expert_mode & XPRT_SHOW_SCROLLBARS) == 0) {
+ toggle_scrollbars();
+ }
+
+ /* initialize file watching */
+ if (resource.watch_file > 0.0) {
+#if XDVI_XT_TIMER_HACK
+ watch_file_cb(NULL, NULL);
+#else
+ XDVI_WARNING((stderr, "Could not redefine XtAppAddTimeOut(); `watchfile' not available."));
+#endif
+ }
+
+ /* raise `early' message windows */
+ raise_message_windows();
+
+ if (resource.mouse_mode == MOUSE_RULER_MODE) {
+ show_ruler(NULL);
+ }
+
+ /* insert this page into the history */
+ globals.ev.flags |= EV_PAGEHIST_INSERT;
+
+ do_pages();
+}
+
+static char *
+is_good_dvi_file(const char *filename, Boolean from_history)
+{
+ static char canonical_path[MAXPATHLEN + 1];
+ Boolean tried_dvi_extension = False;
+ /* following allocates real_filename */
+ char *real_filename = find_dvi_file(filename, &tried_dvi_extension, from_history);
+ char *ret;
+ FILE *f = NULL;
+ dviErrFlagT errflag;
+
+ if (real_filename == NULL)
+ return NULL;
+
+ if ((ret = REALPATH(real_filename, canonical_path)) == NULL) {
+ /* REALPATH failed, use real_filename */
+ strncpy(canonical_path, real_filename, MAXPATHLEN);
+ canonical_path[MAXPATHLEN] = '\0';
+ ret = canonical_path;
+ }
+ free(real_filename);
+
+ /* check for correct DVI files */
+ if ((f = XFOPEN(ret, OPEN_MODE)) != NULL) {
+ TRACE_EVENTS((stderr, "watching: new file opened successfully."));
+ if (process_preamble(f, &errflag)
+ && find_postamble(f, &errflag)
+ && read_postamble(f, &errflag, False)) {
+ fclose(f);
+ return ret;
+ }
+ fclose(f);
+ if (!from_history)
+ XDVI_FATAL((stderr, "%s: %s.", filename, get_dvi_error(errflag)));
+ return NULL;
+ }
+ else {
+ if (!from_history)
+ XDVI_FATAL((stderr, "Could not open `%s': %s.", filename, strerror(errno)));
+ return NULL;
+ }
+}
+
+static char *
+get_filename_from_history(int *pageno)
+{
+ size_t i;
+ /* loop through history, trying to get a good file */
+ for (i = 0; i < file_history_size(); i++) {
+ char *ret, *test;
+
+ if ((test = file_history_get_elem(i, pageno)) == NULL)
+ return NULL;
+ TRACE_FILES((stderr, "HISTORY %lu: |%s|", (unsigned long)i, test));
+ if ((ret = is_good_dvi_file(test, True)) != NULL) {
+ TRACE_FILES((stderr, "SUCCESS: |%s|", test));
+ return ret;
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ ************************************************************
+ ************************************************************
+ main routine
+ ************************************************************
+ ************************************************************
+*/
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ static struct filehist_info info;
+ const char *file_name = NULL;
+ const char *file_name2 = NULL;
+
+ /* Hack to have command-line options override ~/.xdvirc stuff:
+ * Parse and merge them again from argv_bak, a copy of the command-line options,
+ * via XrmParseCommand(). I think the only alternative would be to merge in all
+ * resources manually instead of using XtInitialize(), similar to what's done in gv,
+ * but that looks like too much trouble.
+ */
+#define COMMANDLINE_OVERRIDE_HACK 1
+
+#if COMMANDLINE_OVERRIDE_HACK
+ int argc_bak;
+ char **argv_bak;
+#endif
+
+ info.file_idx = 0;
+ info.page_arg = NULL;
+
+ /* BEGIN_TIMER_LOOP; */
+
+ init_globals();
+
+ /*
+ * Step 1: Process command-line options and resources.
+ */
+
+ globals.program_name = xstrdup(argv[0]);
+ { /* get filename from program_name if it contains a path */
+ char sep;
+ char *ptr;
+#ifdef VMS
+ sep = ']';
+#else
+ sep = '/';
+#endif
+ if ((ptr = strrchr(globals.program_name, sep)) != NULL) {
+ globals.program_name = ++ptr;
+ }
+#ifdef VMS
+ if ((ptr = strchr(globals.program_name, '.')) != NULL)
+ *ptr = '\0';
+#endif
+ }
+
+#if COMMANDLINE_OVERRIDE_HACK
+ /* create a copy of argv[] */
+ argc_bak = argc;
+ argv_bak = xmalloc((1 + argc_bak) * sizeof *argv_bak);
+ for (i = 0; i < argc_bak; i++) {
+ argv_bak[i] = xstrdup(argv[i]);
+ }
+ argv_bak[i] = NULL;
+#endif
+
+ /*
+ Arguments that need to be checked early, like `help', `version' and `sync'.
+ The former don't even require an X connection.
+ */
+ check_early_arguments(argc, argv);
+
+ warn_about_prerelease_versions();
+
+ /* We need to set up SIGALRM before calling XtAppAddTimeOut() (inside sfSelFile, or
+ called from XtInitialize() in Motif), else and we'll die with the error message
+ `Alarm clock'. However, we mustn't install SIGPOLL before the forking is done
+ below, else xdvi may hang forever waiting for input. So the signal handler setup
+ is split in 2 parts: setup_sigalarm(), and setup_signal_handlers() below.
+ */
+ setup_sigalarm();
+
+ /* get the debug value (if any) from the environment
+ (it's too early to get it from the command line) */
+ globals.debug = parse_debugging_option(getenv("XDVIDEBUG"));
+
+ /* to make input of non-latin characters work */
+ XtSetLanguageProc(NULL, (XtLanguageProc)NULL, NULL);
+ globals.widgets.top_level = XtInitialize(globals.program_name, "XDvi", options, XtNumber(options),
+ &argc, argv);
+
+ app = XtWidgetToApplicationContext(globals.widgets.top_level);
+
+ XtAppAddActions(app, get_actions(), get_num_actions());
+
+ create_magnifier();
+
+ if ((globals.orig_locale = setlocale(LC_ALL, "")) != NULL)
+ globals.orig_locale = xstrdup(globals.orig_locale); /* note: never free'd */
+ else /* fallback */
+ globals.orig_locale = xstrdup(setlocale(LC_ALL, NULL));
+
+ /* Override LC_NUMERIC, else sscanf(), strtod() etc. will stop working on floats
+ inside specials for locales like LANG=de_DE which uses `,' not `.'
+ as fractional part separator. (Strangely, using
+ LC_CTYPE | LC_COLLATE
+ above doesn't work?)
+ Regression:
+ xdvik/regression/special-pics/pictest.dvi
+ */
+ setlocale(LC_NUMERIC, "C");
+
+ /* at this point, all known options will have been consumed; so the
+ only ones remaining should be: +pageno, and the dvi name. Exit with
+ usage message if this is not the case. The following rather complicated
+ looping logic ensures that the first unknown option is regarded as dvi_name,
+ unless it's followed by another option, in which case it will result in an
+ `Unrecognized option' error.
+ */
+ for (i = 0; i < argc - 1; i++) { /* argc - 1 because we're going to look at
+ argv[i + 1] to skip argv[0] */
+ if (*(argv[i + 1]) == '+') {
+ if (info.page_arg != NULL) {
+ XDVI_ERROR((stderr, "Unrecognized option `%s'.", argv[i + 1]));
+ usage(EXIT_FAILURE);
+ }
+ else {
+ info.page_arg = argv[i + 1] + 1;
+ }
+ }
+ else if (file_name == NULL) {
+ file_name = xstrdup(argv[i + 1]); /* LEAK */
+ }
+ else {
+ XDVI_ERROR((stderr, "Unrecognized option `%s'.", argv[i]));
+ usage(EXIT_FAILURE);
+ }
+ }
+
+ DISP = XtDisplay(globals.widgets.top_level);
+ SCRN = XtScreen(globals.widgets.top_level);
+
+#ifdef GREY
+ XtSetTypeConverter(XtRString, XtRBool3, XdviCvtStringToBool3,
+ NULL, 0, XtCacheNone, NULL);
+#endif
+
+#ifdef MOTIF
+ /* we'll take care of that ourselves */
+ XtVaSetValues(globals.widgets.top_level, XmNdeleteResponse, XmDO_NOTHING, NULL);
+
+ {
+ /* Hack to work around #884290 (drag&drop freezes file selector, see comment
+ in xm_filesel.c): Disable drag&drop altogether (we don't need it).
+ Could also be done via Xdefaults as follows:
+ XDvi*dragInitiatorProtocolStyle: XmDRAG_NONE
+ XDvi*dragReceiverProtocolStyle: XmDRAG_NONE
+ */
+ Widget display = XmGetXmDisplay(DISP);
+ XtVaSetValues(display,
+ XmNdragInitiatorProtocolStyle, XmDRAG_NONE,
+ XmNdragReceiverProtocolStyle, XmDRAG_NONE,
+ NULL);
+ }
+#else
+ G_accels_cr = XtParseAcceleratorTable("<Key>Return:set()notify()unset()\n"
+ "<Key>q:set()notify()unset()\n"
+ "<Key>Escape: set()notify()unset()");
+#endif
+
+ /* get the no_init_file resource first: This needs to be done
+ * before the call to XtGetApplicationResources() below, which populates
+ * the `resource' struct with the actual application resources (which
+ * may be merged from ~/.xdvirc). */
+ XtGetApplicationResources(globals.widgets.top_level, (XtPointer)&resource,
+ xdvirc_resources, XtNumber(xdvirc_resources),
+ (ArgList)NULL, 0);
+
+ if (!resource.no_init_file) { /* Read user preferences from ~/.xdvirc. */
+ read_user_preferences(globals.widgets.top_level, ".xdvirc");
+ }
+
+#if COMMANDLINE_OVERRIDE_HACK /* see above */
+ {
+ XrmDatabase cmdline_db = XrmGetDatabase(DISP);
+ XrmParseCommand(&cmdline_db, options, XtNumber(options),
+ "xdvi", &argc_bak, argv_bak);
+
+ for (i = 0; i < argc_bak; i++) {
+ free(argv_bak[i]);
+ }
+ free(argv_bak);
+ argc_bak = 0;
+ }
+#endif /* COMMANDLINE_OVERRIDE_HACK */
+
+ XtGetApplicationResources(globals.widgets.top_level, (XtPointer)&resource,
+ application_resources, XtNumber(application_resources),
+ (ArgList)NULL, 0);
+
+ if (resource.shrinkfactor == 0) /* protect against division by 0 */
+ resource.shrinkfactor = 1;
+ currwin.shrinkfactor = resource.shrinkfactor;
+ globals.curr_use_color = resource.use_color;
+ globals.curr_gamma = resource.gamma;
+ globals.curr_paper = xstrdup(resource.paper); /* never free()d */
+ globals.curr_editor = NULL;
+ globals.curr_browser = NULL;
+
+ /* Initialize `globals.debug' as early as possible. Note: earlier
+ * calls to TRACE_* or tests for `if (globals.debug)' will only work if the
+ * XDVIDEBUG environment variable is set!
+ */
+ globals.debug |= parse_debugging_option(resource.debug_arg);
+ kpathsea_debug = globals.debug / DBG_STAT;
+
+ if (globals.debug)
+ fprintf(stderr, "KPATHSEA_DEBUG = %d\n", kpathsea_debug);
+
+ kpse_init_prog("XDVI", resource.pixels_per_inch, resource.mfmode, resource.alt_font);
+
+ kpse_set_program_name(argv[0], "xdvi");
+
+
+ if (globals.debug & DBG_EXPAND) {
+ const char *texmfcnf = kpse_path_expand("$TEXMFCNF");
+ const char *texmfmain = kpse_path_expand("$TEXMFMAIN");
+ fprintf(stderr, "\n%s:%d: KPATHSEA variables:\n", __FILE__, __LINE__);
+ fprintf(stderr, "%s:%d: SELFAUTOLOC=\"%s\"\n", __FILE__, __LINE__, getenv("SELFAUTOLOC"));
+ fprintf(stderr, "%s:%d: SELFAUTODIR=\"%s\"\n", __FILE__, __LINE__, getenv("SELFAUTODIR"));
+ fprintf(stderr, "%s:%d: SELFAUTOPARENT=\"%s\"\n", __FILE__, __LINE__, getenv("SELFAUTOPARENT"));
+ fprintf(stderr, "%s:%d: TEXMFCNF=\"%s\"\n", __FILE__, __LINE__, texmfcnf);
+ fprintf(stderr, "%s:%d: TEXMFMAIN=\"%s\"\n\n", __FILE__, __LINE__, texmfmain);
+ }
+
+ if (resource.regression) {
+ /* currently it just turns on everything; what we'd like here is
+ output that's usable for automatic diffs (e.g. independent
+ of window manager state) */
+ globals.debug = DBG_ALL;
+ }
+
+ /* Check early for whether to pass off to a different xdvi process
+ * (-sourceposition argument for reverse source special lookup).
+ */
+ property_initialize();
+
+#if 0 /* def RGB_ANTI_ALIASING */
+ /* error checking and setting of resources according to command line arguments */
+ if (resource.sub_pixels != NULL && memicmp(resource.sub_pixels, "unknown", 4) == 0) {
+#ifdef __GNUC__
+#warning TODO: implement callbacks
+#endif
+ choice_dialog_sized(globals.widgets.top_level,
+ MSG_QUESTION,
+ SIZE_MEDIUM,
+ NULL,
+#ifndef MOTIF
+ NULL, /* TODO: xaw ret_action_str */
+#endif
+ NULL, NULL, /* pre callback */
+ "Enable", NULL, NULL,
+ "Disable", NULL, NULL,
+ "This version of xdvi can optimize the anti-aliased font display "
+ "when running on an LCD monitor, such as a notebook screen or a TFT flat screen."
+ "\n\n"
+ "If you are using such a monitor, click `Enable' to enable optimized display; otherwise click `Disable'."
+ "\n\n"
+ "You can change this setting later via the Menu `Options -> Anti-Aliasing'.");
+ /* enter event loop */
+ do_pages();
+ }
+ else {
+#endif
+ init_check_resources();
+
+ TRACE_FILES((stderr, "file history: |%s|", resource.file_history));
+ file_history_init();
+
+ if (file_name == NULL) { /* no filename argument */
+
+ if (resource.no_file_arg_use_history) {
+ static char buf[LENGTH_OF_INT]; /* so that we can pass its address */
+ int pageno;
+ if ((file_name = get_filename_from_history(&pageno)) != NULL) {
+ SNPRINTF(buf, LENGTH_OF_INT, "%d", pageno + 1); /* pageno is 0-based */
+ info.page_arg = buf;
+ }
+ }
+
+ TRACE_FILES((stderr, "got from history: |%s|", file_name));
+
+ if (file_name != NULL) {
+ run_dvi_file(file_name, &info);
+ }
+ else { /* get filename from file selector */
+ static struct filesel_callback cb; /* static so that we can pass its address */
+ cb.title = "Xdvi: Open file";
+ cb.prompt = "Open file:";
+ cb.ok = "OK";
+ cb.cancel = "Cancel";
+ cb.init_path = NULL;
+ cb.filemask = "*.dvi";
+ cb.must_exist = True;
+ cb.exit_on_cancel = True;
+ cb.func_ptr = run_dvi_file;
+ cb.data = &info;
+
+ XsraSelFile(globals.widgets.top_level, &cb);
+ /* enter event loop */
+ do_pages();
+ }
+ }
+ else if ((file_name2 = is_good_dvi_file(file_name, False)) != NULL) {
+ run_dvi_file(file_name2, &info);
+ }
+#if 0 /* def RGB_ANTI_ALIASING */
+ }
+#endif
+ /* notreached */
+ return 0;
+}
+
+