/*========================================================================*\ 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 * 4/1994 Added DPS support, bounding box * --Ricardo Telichevesky * and Luis Miguel Silveira, MIT RLE. * 2/1995 Added rulers support --Nelson H. F. Beebe * 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 /* Xlib and Xutil are already included */ #include #include #include #include #include /* needed for def. of XtNiconX */ #ifdef HAVE_X11_XMU_EDITRES_H # include #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 # include # include # include # include # include # include # include # include # include # include # include # include # include # 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 # include # include # include # include # include # include # include # include #endif /* MOTIF */ #include #include #include #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 unsigned long time_start=0, time_end=0; #endif #ifdef MOTIF #include #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] " }; 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) ":wheel(-0.2)\n: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 ", #else /* display */ "^-cr", "-display ", #endif /* geometry */ "^-cr", "-geometry ", /* icongeometry */ "geometry", /* iconic */ "^-icongeometry", "-iconic", /* font */ "^-icongeometry", "-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 # include /* 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, " [+[]]"); 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 : "", resource.remember_windowsize, resource.windowsize ? resource.windowsize : "")); 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 = \ "osfPageUp:back-page()\n" "osfPageDown:forward-page()\n" "CtrlosfBeginLine:goto-page(1)\n" "CtrlosfEndLine:goto-page()\n" "osfBeginLine:home-or-top()\n" "osfEndLine:end-or-bottom()\n" #if 0 /* AFAIK the following don't have any effect with Motif */ #ifdef XK_KP_Left "KP_Home:home()\n" "KP_End:down()\n" "KP_Prior:back-page()\n" "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 '[ ]* = linenumber, [ ]* = an arbitrary number of spaces, " "and = 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 , 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()\n"; static const char default_mouse_translations[] = ":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 : "", 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 ' 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("Return:set()notify()unset()\n" "q:set()notify()unset()\n" "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; }