/*========================================================================*\ Copyright (c) 1990-2014 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" /* 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 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/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 "translations.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 "hypertex.h" #include "xaw_menu.h" #include "xdvi-debug.h" #include "pagehist.h" #include "filehist.h" #include "print-internal.h" #include "exit-handlers.h" #include "xm_prefsP.h" /* for Xdvi_PREFS_BROWSER_DEFAULTS and Xdvi_PREFS_EDITOR_DEFAULTS */ #if FREETYPE # include "font-open.h" /* for init_t1_lookup() */ #endif #ifdef VMS # include "pixmaps/hand.xbm" # include "pixmaps/hand_mask.xbm" #endif #include "pixmaps/magglass.xbm" #include "pixmaps/magglass_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 */ #if HAVE_X11_INTRINSICI_H # include #else /* Taken from in libXt-1.1.3 (June 2012) */ typedef struct _LateBindings { unsigned int knot:1; unsigned int pair:1; unsigned short ref_count; /* garbage collection */ KeySym keysym; } LateBindings, *LateBindingsPtr; #endif /* not HAVE_X11_INTRINSICI_H */ struct mouse_acts *mouse_actions; 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; #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 static Dimension bwidth = 2; struct x_resources resource; struct program_globals globals; /* color of cursor */ static XColor m_cursor_color; 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 }; #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}, {"mouseTranslations", "MouseTranslations", XtRString, sizeof(char *), offset(mouse_translations), XtRString, (XtPointer) NULL }, {"wheelUnit", "WheelUnit", XtRInt, sizeof(int), offset(wheel_unit), XtRImmediate, (XtPointer) 80}, {"mouseMode", "MouseMode", XtRInt, sizeof(int), offset(mouse_mode), XtRImmediate, (XtPointer) MOUSE_MODE1 }, {"mouseMode1Name", "MouseMode1Name", XtRString, sizeof(char *), offset(mouse_mode1_name), XtRString, (XtPointer) "Magnifier"}, {"mouseMode1Description", "MouseMode1Description", XtRString, sizeof(char *), offset(mouse_mode1_description), XtRString, (XtPointer) "click to enlarge text"}, {"mouseMode1Cursor", "MouseMode1Cursor", XtRInt, sizeof(int), offset(mouse_mode1_cursor), XtRImmediate, (XtPointer) -1}, {"mouseMode2Name", "MouseMode2Name", XtRString, sizeof(char *), offset(mouse_mode2_name), XtRString, (XtPointer) "Text Selection"}, {"mouseMode2Description", "MouseMode2Description", XtRString, sizeof(char *), offset(mouse_mode2_description), XtRString, (XtPointer) "click and drag to select a region of text"}, {"mouseMode2Cursor", "MouseMode2Cursor", XtRInt, sizeof(int), offset(mouse_mode2_cursor), XtRImmediate, (XtPointer) XC_cross }, {"mouseMode3Name", "MouseMode3Name", XtRString, sizeof(char *), offset(mouse_mode3_name), XtRString, (XtPointer) "Ruler"}, {"mouseMode3Description", "MouseMode3Description", XtRString, sizeof(char *), offset(mouse_mode3_description), XtRString, (XtPointer) "click and drag to set/move ruler"}, {"mouseMode3Cursor", "MouseMode3Cursor", XtRInt, sizeof(int), offset(mouse_mode3_cursor), XtRImmediate, (XtPointer) XC_crosshair }, #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}, #if FREETYPE {"type1", "Type1", XtRBoolean, sizeof(Boolean), offset(freetype), XtRString, "true"}, #endif #if HAVE_XI21 {"xi2Scrolling", "Xi2Scrolling", XtRBoolean, sizeof(Boolean), offset(xi2scrolling), 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"}, {"hush", "Hush", XtRBoolean, sizeof(Boolean), offset(hush), XtRString, "false"}, {"hushLostChars", "HushLostChars", XtRBoolean, sizeof(Boolean), offset(hush_chars), XtRString, "false"}, {"hushChecksums", "HushChecksums", XtRBoolean, sizeof(Boolean), offset(hush_chk), XtRString, "false"}, {"hushStdout", "HushStdout", XtRBoolean, sizeof(Boolean), offset(hush_stdout), XtRString, "false"}, {"hushBell", "HushBell", XtRBoolean, sizeof(Boolean), offset(hush_bell), 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}, /* only used if menus consist of buttons only */ {"buttonBetweenExtra", "ButtonSpacing", XtRDimension, sizeof(Dimension), offset(btn_between_extra), XtRImmediate, (XtPointer)16}, {"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 }, # if USE_COMBOBOX {"searchHistory", "SearchHistory", XtRString, sizeof(char *), offset(search_history), XtRString, (XtPointer)NULL }, {"searchHistorySize", "SearchHistorySize", XtRInt, sizeof(int), offset(search_history_size), XtRImmediate, (XtPointer)20}, # endif #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}, /* whether to open file in new window from file selector (only for DVI files) */ {"fileselOpenNewWindow", "FileselOpenNewWindow", XtRBoolean, sizeof(Boolean), offset(filesel_open_new_window), XtRString, "False"}, /* 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}, }; 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 #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; 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 */ int atopix(const char *arg) { int len = strlen(arg); const char *arg_end = arg; char tmp[16]; double factor, val; while ((*arg_end >= '0' && *arg_end <= '9') || *arg_end == '.') ++arg_end; if (arg_end >= arg + XtNumber(tmp) - 1) { /* should be rare */ char *tmp_var = xstrndup(arg, arg_end - arg); val = atof(tmp_var); free(tmp_var); } else { memcpy(tmp, arg, arg_end - arg); tmp[arg_end - arg] = '\0'; val = atof(tmp); } #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 * val * resource.pixels_per_inch + 0.5; } int atopix_signed(const char *arg) { return *arg == '-' ? -atopix(arg + 1) : atopix(arg); } #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 #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); } #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 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) { constraints.request_mode |= CWWidth; constraints.width = screen_w; } /* fprintf(stderr, "setting constraints.height to %d; screen_h = %d\n", globals.page.h, screen_h); */ constraints.height = globals.page.h; if (constraints.height > screen_h) { constraints.request_mode |= CWHeight; constraints.height = screen_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 } /* fprintf(stderr, "reply height: %d; screen_h: %d; add_h: %d\n", reply->height, screen_h, *add_h); */ 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 - 2 * bwidth; } if (reply->height + *add_h >= screen_h) { reply->height = screen_h #ifdef MOTIF - 1.5 #else - 2 #endif * *add_h - 2 * bwidth; } } 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 - get_statusline_height() - 6; */ screen_h = HeightOfScreen(SCRN) - 2 * bwidth; 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); TRACE_GUI((stderr, "w: %d, h: %d, add_h: %d, reply: %d x %d", screen_w, screen_h, add_h, reply.width, reply.height)); } 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_GUI((stderr, "width: %u, 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_GUI((stderr, "height: %u, bwidth: %hu, add_h: %d", height, bwidth, add_h)); reply.height = height - 2 * bwidth - add_h; } else { reply.height = height; } } TRACE_GUI((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 + 2 * bwidth; /* + (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 get_statusline_height(). */ 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_GUI((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); } /* * 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 */ /* return an empty cursor. Lifted from unclutter.c */ static Cursor h_get_empty_cursor(Display *display, Window root) { Pixmap cursormask; XGCValues xgc; GC gc; XColor dummycolour; Cursor cursor; cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); xgc.function = GXclear; gc = XCreateGC(display, cursormask, GCFunction, &xgc); XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); dummycolour.pixel = 0; dummycolour.red = 0; dummycolour.flags = 04; cursor = XCreatePixmapCursor(display, cursormask, cursormask, &dummycolour, &dummycolour, 0, 0); XFreePixmap(display, cursormask); XFreeGC(display, gc); return cursor; } 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 */ globals.cursor.wait = XCreateFontCursor(DISP, XC_watch); if (resource.mouse_mode1_cursor == -1) { /* Use default ready cursor (custom bitmap) */ 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.mode1 = XCreatePixmapCursor(DISP, temp, mask, &m_cursor_color, &bg_Color, magglass_x_hot, magglass_y_hot); XFreePixmap(DISP, temp); XFreePixmap(DISP, mask); } else { globals.cursor.mode1 = XCreateFontCursor(DISP, resource.mouse_mode1_cursor); } globals.cursor.corrupted = XCreateFontCursor(DISP, XC_watch); /* empty cursor */ globals.cursor.empty = h_get_empty_cursor(DISP, RootWindowOfScreen(SCRN)); #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 */ globals.cursor.drag_v = XCreateFontCursor(DISP, XC_sb_v_double_arrow); globals.cursor.drag_h = XCreateFontCursor(DISP, XC_sb_h_double_arrow); globals.cursor.drag_a = XCreateFontCursor(DISP, XC_fleur); #ifdef VMS globals.cursor.link = globals.cursor.ready; globals.cursor.mode2 = globals.cursor.ready; globals.cursor.mode3 = globals.cursor.ready; #else globals.cursor.link = XCreateFontCursor(DISP, XC_hand2); globals.cursor.mode2 = XCreateFontCursor(DISP, resource.mouse_mode2_cursor); globals.cursor.mode3 = XCreateFontCursor(DISP, resource.mouse_mode3_cursor); /* globals.cursor.text = XCreateFontCursor(DISP, XC_tcross); */ #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; } } /* * Routines for compile_mouse_actions */ struct modifierinf { int len; const char *name; Modifiers mask; KeySym keysym; }; /* Allowed modifiers, sorted by length and then lexicographically. */ static struct modifierinf modifiers[] = { {1, "a", 0, XK_Alt_L}, {1, "c", ControlMask, 0}, {1, "h", 0, XK_Hyper_L}, {1, "l", LockMask, 0}, {1, "m", 0, XK_Meta_L}, {1, "s", ShiftMask, 0}, {2, "su", 0, XK_Super_L}, {3, "Alt", 0, XK_Alt_L}, {4, "Ctrl", ControlMask, 0}, {4, "Lock", LockMask, 0}, {4, "Meta", 0, XK_Meta_L}, {4, "Mod1", Mod1Mask, 0}, {4, "Mod2", Mod2Mask, 0}, {4, "Mod3", Mod3Mask, 0}, {4, "Mod4", Mod4Mask, 0}, {4, "Mod5", Mod5Mask, 0}, {5, "Hyper", 0, XK_Hyper_L}, {5, "Shift", ShiftMask, 0}, {5, "Super", 0, XK_Super_L}, {7, "Button1", Button1Mask, 0}, {7, "Button2", Button2Mask, 0}, {7, "Button3", Button3Mask, 0}, {7, "Button4", Button4Mask, 0}, {7, "Button5", Button5Mask, 0}, }; #define MODSCTRLINDEX 1 /* index of "c" in the above array */ #define MODSMETAINDEX 4 /* index of "m" */ static Boolean compile_modifiers(const char **pp, struct mouse_acts *mactp) { const char *p = *pp; const char *p1; LateBindingsPtr latep = NULL; int nlate = 3; while (*p == ' ' || *p == '\t') ++p; p1 = p; while (isalpha((int) *p1)) ++p1; if (p1 - p == 3 && memcmp(p, "Any", 3) == 0) { mactp->mask = mactp->value = 0; p = p1; while (*p == ' ' || *p == '\t') ++p; if (*p != '<') return False; } else if (p1 - p == 4 && memcmp(p, "None", 4) == 0) { mactp->mask = ~0; mactp->value = 0; p = p1; while (*p == ' ' || *p == '\t') ++p; if (*p != '<') return False; } else { if (*p == '!') { do { ++p; } while (*p == ' ' || *p == '\t'); } for (;;) { Boolean negated = False; struct modifierinf *mp; if (*p == '<') break; if (*p == '~') { negated = True; ++p; } if (*p == '^') { mp = &modifiers[MODSCTRLINDEX]; ++p; } else if (*p == '$') { mp = &modifiers[MODSMETAINDEX]; ++p; } else { int min, max; p1 = p; while (isalnum((int) *p)) ++p; /* do binary search */ min = -1; max = XtNumber(modifiers); for (;;) { int i, diff; i = (min + max) / 2; if (i == min) return False; /* if not found */ mp = &modifiers[i]; diff = (p - p1) - mp->len; if (diff == 0) diff = memcmp(p1, mp->name, p - p1); if (diff == 0) break; if (diff > 0) min = i; else max = i; } } if (mp->mask) { mactp->mask |= mp->mask; if (!negated) mactp->value |= mp->mask; } else { LateBindingsPtr lp1; if (latep == NULL) { /* nlate = 3; (done earlier to avoid compiler warning) */ latep = xmalloc(3 * sizeof(LateBindings)); latep->ref_count = 1; } else { nlate += 2; latep = xrealloc(latep, nlate * sizeof(LateBindings)); } lp1 = &latep[nlate - 3]; lp1->knot = lp1[1].knot = negated; lp1->pair = True; lp1->keysym = mp->keysym; ++lp1; lp1->pair = False; lp1->ref_count = 0; lp1->keysym = mp->keysym + 1; ++lp1; lp1->knot = lp1->pair = False; lp1->ref_count = 0; lp1->keysym = 0; } while (*p == ' ' || *p == '\t') ++p; } } mactp->late_bindings = latep; *pp = p; return True; } static Boolean compile_evtype(const char **pp, unsigned int *buttonp) { const char *p = *pp; const char *p0; ++p; /* already assumed to be '<' */ while (*p == ' ' || *p == '\t') ++p; p0 = p; while (isalpha((int) *p) && p - p0 < 3) ++p; if (p - p0 != 3 || memcmp(p0, "Btn", 3) != 0) return False; if (*p >= '1' && *p <= '9') { unsigned int n = *p - '0'; while (*++p >= '0' && *p <= '9') n = n * 10 + (*p - '0'); *buttonp = n; } p0 = p; while (isalpha((int) *p)) ++p; if (p - p0 != 4 || memcmp(p0, "Down", 4) != 0) return False; while (*p == ' ' || *p == '\t') ++p; if (*p++ != '>') return False; while (*p == ' ' || *p == '\t') ++p; if (*p++ != ':') return False; *pp = p; return True; } static void compile_mouse_actions(void) { struct mouse_acts **mactpp; struct mouse_acts *mactp; const char *p = resource.mouse_translations; const char *p_end; const char *p_base = base_mouse_translations; struct mouse_acts mact; mactpp = &mouse_actions; if (p == NULL) { p = p_base; p_base = NULL; } do { /* loop over translations strings */ p_end = p + strlen(p); for (;;) { while (*p == ' ' || *p == '\t') ++p; if (*p == '\n') continue; if (*p == '\0') break; mact.mask = mact.value = 0; mact.button = 0; if (!compile_modifiers(&p, &mact) || !compile_evtype(&p, &mact.button)) { XDVI_WARNING((stderr, "syntax error in wheel translations")); } else if (compile_action(p, &mact.action) || mact.action != NULL) { mactp = xmalloc(sizeof(struct mouse_acts)); *mactp = mact; *mactpp = mactp; mactpp = &mactp->next; } p = memchr(p, '\n', p_end - p); if (p == NULL) break; ++p; } p = p_base; p_base = NULL; } while (p != NULL); *mactpp = NULL; } #if HAVE_XI21 void xi2_init_valuators(struct xi2_slave *sp, XIAnyClassInfo **classes, int num_classes) { unsigned int flags; int i; sp->flags = flags = 0; sp->btn_mask = 0; sp->vert.number = sp->horiz.number = -1; for (i = 0; i < num_classes; ++i) if (classes[i]->type == XIScrollClass) { XIScrollClassInfo *scroll = (XIScrollClassInfo *) classes[i]; if (scroll->scroll_type == XIScrollTypeVertical) { sp->vert.number = scroll->number; sp->vert.increment = scroll->increment; flags |= XI2_SLAVE_VERT; } else if (scroll->scroll_type == XIScrollTypeHorizontal) { sp->horiz.number = scroll->number; sp->horiz.increment = scroll->increment; flags |= XI2_SLAVE_HORIZ; } } if (flags == 0) { TRACE_EVENTS((stderr, "No scroll valuators found for slave device %d", sp->id)); return; } TRACE_EVENTS((stderr, "Found XI2 device %d with one or more scroll valuators:", sp->id)); if (flags & XI2_SLAVE_VERT) TRACE_EVENTS((stderr, " Vertical valuator %d has increment %.2f", sp->vert.number, sp->vert.increment)); if (flags & XI2_SLAVE_HORIZ) TRACE_EVENTS((stderr, " Horizontal valuator %d has increment %.2f", sp->horiz.number, sp->horiz.increment)); for (i = 0; i < num_classes; ++i) if (classes[i]->type == XIValuatorClass) { XIValuatorClassInfo *valuator; valuator = (XIValuatorClassInfo *) classes[i]; /* The min and max fields have been seen to be 0 and -1, */ /* respectively (what do those mean)? */ if (flags & XI2_SLAVE_VERT && valuator->number == sp->vert.number) { sp->vert.lastval = valuator->value; sp->vert.lastexact = valuator->value; sp->vert.factor = 0; sp->vert.serial = LastKnownRequestProcessed(DISP); sp->flags |= XI2_SLAVE_VERT; sp->btn_mask |= (1<<4) | (1<<5); } else if (flags & XI2_SLAVE_HORIZ && valuator->number == sp->horiz.number) { sp->horiz.lastval = valuator->value; sp->horiz.lastexact = valuator->value; sp->horiz.factor = 0; sp->horiz.serial = LastKnownRequestProcessed(DISP); sp->flags |= XI2_SLAVE_HORIZ; sp->btn_mask |= (1<<6) | (1<<7); } } if (sp->flags != flags) TRACE_EVENTS((stderr, "For slave device %d, valuator class(es) missing (%x vs. %x)", sp->id, sp->flags, flags)); } void xi2_activate(void) { XIEventMask eventmask; unsigned char mask[2] = {0, 0}; /* the actual event mask */ struct xi2_master *mp; mask[0] = mask[1] = 0; eventmask.mask = mask; eventmask.mask_len = sizeof mask; XISetMask(mask, XI_Motion); XISetMask(mask, XI_Enter); for (mp = xi2_masters; mp != NULL; mp = mp->next) { eventmask.deviceid = mp->id; XISelectEvents(DISP, XtWindow(globals.widgets.draw_widget), &eventmask, 1); # if MOTIF XISelectEvents(DISP, XtWindow(globals.widgets.clip_widget), &eventmask, 1); # endif } xi2_active = True; xi2_current = xi2_masters; /* this is just an optimization */ } static void xi2_init(void) { int event, error; int major, minor; XIEventMask eventmask; unsigned char mask[2] = {0, 0}; /* the actual event mask */ XIDeviceInfo *info; int ndevices; struct xi2_master **mpp; struct xi2_master *mp; struct xi2_slave **spp; struct xi2_slave *sp; unsigned int all_flags; int i; /* Check for user turning it off */ if (!resource.xi2scrolling) { TRACE_EVENTS((stderr, "X Input extension turned off at user request.")); return; } /* Check for extension */ if (!XQueryExtension(DISP, "XInputExtension", &xi2_opcode, &event, &error)) { TRACE_EVENTS((stderr, "X Input extension not available.")); return; } /* Check XI2 version number */ major = 2; minor = 1; if (XIQueryVersion(DISP, &major, &minor) == BadRequest) { TRACE_EVENTS((stderr, "XI2 not available.")); return; } if (major == 2 && minor < 1) { TRACE_EVENTS((stderr, "XI2 version 2.1 is not supported.")); return; } TRACE_EVENTS((stderr, "Found XI2 extension version %d.%d.", major, minor)); XISetMask(mask, XI_HierarchyChanged); XISetMask(mask, XI_DeviceChanged); eventmask.deviceid = XIAllDevices; eventmask.mask_len = sizeof(mask); eventmask.mask = mask; XISelectEvents(DISP, DefaultRootWindow(DISP), &eventmask, 1); info = XIQueryDevice(DISP, XIAllDevices, &ndevices); # if XIAllDevices != 0 xi2_no_slave.id = XIAllDevices; # endif /* Find slave devices */ all_flags = 0; spp = &xi2_slaves; /* link for next slave device */ for (i = 0; i < ndevices; ++i) if (info[i].use == XISlavePointer || info[i].use == XIFloatingSlave) { sp = xmalloc(sizeof (struct xi2_slave)); sp->id = info[i].deviceid; sp->enabled = info[i].enabled; xi2_init_valuators(sp, info[i].classes, info[i].num_classes); all_flags |= sp->flags; *spp = sp; spp = &sp->next; } *spp = NULL; /* Find master devices */ mpp = &xi2_masters; /* link for next master device */ for (i = 0; i < ndevices; ++i) if (info[i].use == XIMasterPointer || info[i].use == XIMasterKeyboard) { mp = xmalloc(sizeof (struct xi2_master)); mp->id = info[i].deviceid; mp->slave = &xi2_no_slave; *mpp = mp; mpp = &mp->next; } *mpp = NULL; XIFreeDeviceInfo(info); if (xi2_masters == NULL) { TRACE_EVENTS((stderr, "No master pointers found (!!); not using XI2.")); return; } if (!all_flags) { TRACE_EVENTS((stderr, "No scroll valuators found; not using XI2 (for now).")); return; } xi2_activate(); } #endif /* HAVE_XI21 */ 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) { #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_error(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. */ { XtTranslations xlats; xlats = XtParseTranslationTable(base_key_translations); XtOverrideTranslations(globals.widgets.main_row, xlats); /* XtOverrideTranslations(globals.widgets.menu_bar, xlats); */ XtOverrideTranslations(tool_bar, xlats); XtOverrideTranslations(page_list, xlats); XtOverrideTranslations(globals.widgets.main_window, xlats); XtOverrideTranslations(globals.widgets.clip_widget, xlats); XtOverrideTranslations(globals.widgets.draw_widget, xlats); xlats = XtParseTranslationTable(": press()\n" ": motion()\n" ": release()\n"); XtOverrideTranslations(globals.widgets.clip_widget, xlats); XtOverrideTranslations(globals.widgets.draw_widget, xlats); } if (resource.main_translations != NULL) { XtTranslations xlats = XtParseTranslationTable(resource.main_translations); XtOverrideTranslations(globals.widgets.draw_widget, xlats); XtOverrideTranslations(globals.widgets.clip_widget, xlats); XtOverrideTranslations(globals.widgets.main_row, xlats); XtOverrideTranslations(globals.widgets.menu_bar, xlats); XtOverrideTranslations(globals.widgets.main_window, xlats); /* don't do it for the page list, otherwise mouse customizations will break the default list bindings too. */ /* XtOverrideTranslations(page_list, xlats); */ } compile_mouse_actions(); #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)); if (resource.main_translations != NULL) { XtOverrideTranslations(globals.widgets.form_widget, XtParseTranslationTable(resource.main_translations)); } { XtTranslations xlats = XtParseTranslationTable(": press()\n" ": motion()\n" ": release()\n"); XtOverrideTranslations(globals.widgets.form_widget, xlats); XtOverrideTranslations(globals.widgets.draw_widget, xlats); } compile_mouse_actions(); /* 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 */ create_menu_buttons(globals.widgets.form_widget, add_w); #endif /* MOTIF */ /* activate expert mode and related settings */ toggle_statusline(); toggle_scrollbars(); #ifdef MOTIF toggle_pagelist(); toggle_toolbar(); toggle_menubar(); #else if ((resource.expert_mode & XPRT_SHOW_BUTTONS) == 0) toggle_buttons(); #endif *add_h = 0; #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); */ /* if (globals.widgets.x_bar != NULL) */ /* add_h += xm_get_width(globals.widgets.x_bar); */ 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); #else /* add_w has been initialized by create_menu_buttons() call above. Reset to 0 if we're in expert mode. */ if (!(resource.expert_mode & XPRT_SHOW_BUTTONS)) { *add_w = 0; } if (resource.expert_mode & XPRT_SHOW_STATUSLINE) { /* FIXME: Unfortunately the statusline hasn't been created at this point for Xaw, so the value is still the built-in default. */ *add_h += get_statusline_height(); } #endif } static void realize_widgets(Dimension main_win_w, Dimension main_win_h, int add_w) { /* * Realize the widgets (or windows). */ #ifndef MOTIF realize_button_panel(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, ""); #ifdef USE_PANNER XtAddEventHandler(globals.widgets.x_bar, ButtonPressMask | ButtonReleaseMask, False, handle_x_scroll, NULL); XtAddEventHandler(globals.widgets.y_bar, ButtonPressMask | ButtonReleaseMask, False, handle_y_scroll, NULL); #endif 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 #if !DELAYED_MKTEXPK 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); /* fprintf(stderr, "+++++++++++++++ create_font_popup\n"); */ if (m_font_popup_id) { if (*curr_timeout > 0) { XtRemoveTimeOut(m_font_popup_id); m_font_popup_id = XtAppAddTimeOut(globals.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); } } } 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; /* fprintf(stderr, "+++++++++++++++ registered font popup\n"); */ m_font_popup_id = XtAppAddTimeOut(globals.app, 100, create_font_popup, (XtPointer)&new_timeout); } void unregister_font_popup(void) { /* fprintf(stderr, "+++++++++++++++ unregister_font_popup\n"); */ 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(globals.app, 1, remove_font_popup, (XtPointer)NULL); */ remove_font_popup(NULL, NULL); } } #endif /* !DELAYED_MKTEXPK */ /* revert resources */ void load_app_resources(Boolean also_pixels) { /* /\* 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); if (also_pixels) { XtGetApplicationResources(globals.widgets.top_level, (XtPointer)&resource, app_pixel_resources, XtNumber(app_pixel_resources), (ArgList)NULL, 0); } /* fprintf(stderr, "gamma: %f\n", resource.gamma); */ } /* * 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. */ void run_dvi_file(const char *filename, void *data) { Boolean tried_dvi_ext = False; struct startup_info *cb = (struct startup_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 = 0, add_h = 0; 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); xdvi_assert(XDVI_VERSION_INFO, __FILE__, __LINE__, globals.dvi_file.dirname != NULL, "globals.dvi_name (%s) must contain a dir component", globals.dvi_name); 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 instance, same file: reload */ w2 = w1; set_string_property("", atom_reload(), w2); } else { /* another xdvi instance, different file: load new file */ set_string_property(globals.dvi_name, atom_newdoc(), w2); } if (cb->page_arg != NULL) { /* switch to different page */ 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); } } else { /* if page_arg is empty, go to 1st page so that this page is inserted into the page history (fix for #1044891) */ set_string_property("1", atom_newpage(), w2); } /* in all cases, raise the window of the other instance */ 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); } 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 (resource.main_translations != NULL) { XtOverrideTranslations(form, XtParseTranslationTable(resource.main_translations)); } #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. */ #if FREETYPE /* At this point DISP, G_visual, G_depth and G_colormap must be defined. Also, init_t1_lookup() 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.freetype) { if (!init_t1_lookup()) { /* nag 'em with a popup so that they'll do something about this */ popup_message(globals.widgets.top_level, MSG_ERR, "Direct Type 1 font rendering via FreeType gives you " "many benefits, such as:\n" " - quicker startup time, since no bitmap fonts need " "to be generated;\n" " - saving disk space for storing the bitmap fonts.\n" "To fix this error, check that the file `ps2pk.map' " "is located somewhere in your XDVIINPUTS path. " "Have a look at the xdvi wrapper shell script " "(type \"which xdvi\" to locate that shell script) " "for the current setting of XDVIINPUTS.", "Could not load any of the map files listed in xdvi.cfg " "- disabling FreeType."); resource.freetype = False; } } #endif /* FREETYPE */ #if DELAYED_MKTEXPK /* Open and initialize the DVI file. First, disable creation of PK fonts * so that we can count the missing fonts that are to be generated. */ kpse_set_program_enabled(kpse_any_glyph_format, False, kpse_src_compile); #endif setup_signal_handlers(False); #if !DELAYED_MKTEXPK /* Notify users that fonts are being created. This is just a hack and no replacement for true asynchronous font creation since it doesn't give details (is just invoked if startup takes somewhat longer) and freezes during font creation. */ register_font_popup(); #endif /* open and initialize the DVI file, but don't read the fonts yet */ if (!internal_open_dvi(globals.dvi_name, &errflag, True #if DELAYED_MKTEXPK , False /* read fonts, but don't initialize data structures */ #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))); } } #if DELAYED_MKTEXPK fprintf(stderr, "after opening ...\n"); /* Now re-enable PK creation and read the postamble for a second time. * FIXME: Actually we don't need this re-reading, could as well read the * entire thing in the first run, not quit early and correctly initialize * the fonts without creating them. */ kpse_set_program_enabled(kpse_any_glyph_format, resource.makepk, kpse_src_compile); if (!internal_open_dvi(globals.dvi_name, &errflag, True, True)) { 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))); } } #else unregister_font_popup(); #endif 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, True); } } else { page_history_insert(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_GUI((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); if (resource.main_translations != NULL) { XtOverrideTranslations(tool_bar, XtParseTranslationTable(resource.main_translations)); } #endif create_widgets( #ifdef MOTIF tool_bar, form, #endif &add_w, &add_h); TRACE_GUI((stderr, "add_w = %d, add_h = %d\n", 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 get_xdvi_window_id(). */ { long data = XtWindow(globals.widgets.top_level); XChangeProperty(DISP, DefaultRootWindow(DISP), atom_xdvi_windows(), atom_xdvi_windows(), 32, PropModePrepend, (unsigned char *)&data, 1); set_dvi_property(); } #if HAVE_XI21 xi2_init(); /* Set up hi-res (smooth) scrolling */ #endif /* * Step 5: Assign colors and GCs. * Because of the latter, this has to go after the widgets are realized. */ create_gcs(); create_cursors(); #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(); { String args[1]; char mmode[LENGTH_OF_INT]; snprintf(mmode, LENGTH_OF_INT, "%d", resource.mouse_mode); args[0] = mmode; XtCallActionProc(globals.widgets.top_level, "switch-mode", NULL, args, 1); } /* go to home position on first page to honor -(side|top)margin flags */ if (!resource.keep_flag) home(False); do_pages(); }