Logo Search packages:      
Sourcecode: texfam version File versions  Download package

xdvi.c

/*========================================================================*\

Copyright (c) 1990-1999  Paul Vojta

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 ANYONE ELSE BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.

NOTE: xdvi is based on prior work as noted in the modification history, below.

\*========================================================================*/

/*
 * DVI previewer for X.
 *
 * Eric Cooper, CMU, September 1985.
 *
 * Code derived from dvi-imagen.c.
 *
 * Modification history:
 * 1/1986   Modified for X.10 --Bob Scheifler, MIT LCS.
 * 7/1988   Modified for X.11 --Mark Eichin, MIT
 * 12/1988  Added 'R' option, toolkit, magnifying glass
 *                            --Paul Vojta, UC Berkeley.
 * 2/1989   Added tpic support      --Jeffrey Lee, U of Toronto
 * 4/1989   Modified for System V   --Donald Richardson, Clarkson Univ.
 * 3/1990   Added VMS support --Scott Allendorf, U of Iowa
 * 7/1990   Added reflection mode   --Michael Pak, Hebrew U of Jerusalem
 * 1/1992   Added greyscale code    --Till Brychcy, Techn. Univ. Muenchen
 *                              and Lee Hetherington, MIT
 * 7/1992       Added extra menu buttons--Nelson H. F. Beebe <beebe@math.utah.edu>
 * 4/1994   Added DPS support, bounding box
 *                            --Ricardo Telichevesky
 *                              and Luis Miguel Silveira, MIT RLE.
 * 2/1995       Added rulers support    --Nelson H. F. Beebe <beebe@math.utah.edu>
 *
 *    Compilation options:
 *    VMS   compile for VMS
 *    NOTOOL      compile without toolkit
 *    BUTTONS     compile with buttons on the side of the window (needs toolkit)
 *    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
 *    GRID  grid in magnification windows enabled
 *    HTEX  hypertex enabled.  EXPECT PROBLEMS IF USED WITH MOTIF!
 *          please send patches to janl@math.uio.no
 */

#if 0
static      char  copyright[] =
"@(#) Copyright (c) 1994-1999 Paul Vojta.  All rights reserved.\n";
#endif

#define     EXTERN
#define     INIT(x)     =x

#include "xdvi-config.h"
#include "c-openmx.h"
#include <kpathsea/c-ctype.h>
#include <kpathsea/c-fopen.h>
#include <kpathsea/c-pathch.h>
#include <kpathsea/c-stat.h>
#include <kpathsea/proginit.h>
#include <kpathsea/progname.h>
#include <kpathsea/tex-file.h>
#include <kpathsea/tex-hush.h>
#include <kpathsea/tex-make.h>

#ifdef HTEX
#include "wwwconf.h"
#include "WWWLib.h"
#include "WWWInit.h"
#include "WWWCache.h"
#include "HTEscape.h"
#endif

#ifndef     ALTFONT
#define     ALTFONT     "cmr10"
#endif

#ifndef     SHRINK
#define     SHRINK      8
#endif

#ifndef     BDPI
#define     BDPI  600
#endif

#ifndef     MFMODE
#define     MFMODE      NULL
#endif

#undef MKTEXPK
#define MKTEXPK MAKEPK

#if   defined(PS_GS) && !defined(GS_PATH)
#define     GS_PATH     "gs"
#endif

#if A4
#define     DEFAULT_PAPER           "a4"
#else
#define     DEFAULT_PAPER           "us"
#endif

#include "version.h"

#ifdef HTEX
/* Application name and version for w3c-libwww routines.  
   This is what will show up in httpd's agent_log files. 
*/
#ifdef Omega
char *HTAppName = "oxdvik";
#else
char *HTAppName = "xdvik";
#endif
char *HTAppVersion = XDVIVERSION;
#endif


#ifdef      X_NOT_STDC_ENV
#ifndef     atof
extern      double      atof ARGS((_Xconst char *));
#endif
#endif

/* Xlib and Xutil are already included */
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include "xdvi.icon"

#ifdef      TOOLKIT

#ifdef      OLD_X11_TOOLKIT
#include <X11/Atoms.h>
#else /* not OLD_X11_TOOLKIT */
#include <X11/Xatom.h>
#include <X11/StringDefs.h>
#endif /* not OLD_X11_TOOLKIT */

#include <X11/Shell.h>  /* needed for def. of XtNiconX */

#ifndef     XtSpecificationRelease
#define     XtSpecificationRelease  0
#endif
#if   XtSpecificationRelease >= 4

#ifndef MOTIF
#include <X11/Xaw/Viewport.h>
#ifdef HTEX
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Scrollbar.h>
#endif /* HTEX */
#define     VPORT_WIDGET_CLASS      viewportWidgetClass
#define     DRAW_WIDGET_CLASS drawWidgetClass
#else /* MOTIF */
#include <Xm/MainW.h>
#include <Xm/ToggleB.h>
#include <Xm/RowColumn.h>
#include <Xm/MenuShell.h>
#include <Xm/DrawingA.h>
#define     VPORT_WIDGET_CLASS      xmMainWindowWidgetClass
#define     DRAW_WIDGET_CLASS xmDrawingAreaWidgetClass
#endif /* MOTIF */

#ifdef      BUTTONS
#ifndef MOTIF
#include <X11/Xaw/Command.h>
#define     FORM_WIDGET_CLASS formWidgetClass
#else /* MOTIF */
#include <Xm/Form.h>
#define     FORM_WIDGET_CLASS xmFormWidgetClass
#endif /* MOTIF */
#endif /* BUTTONS */

#else /* XtSpecificationRelease < 4 */

#define     XtPointer caddr_t
#include <X11/Viewport.h>
#ifdef HTEX
#include <X11/AsciiText.h>
#include <X11/Box.h>
#include <X11/Command.h>
#include <X11/Dialog.h>
#include <X11/Form.h>
#include <X11/Paned.h>
#include <X11/Scroll.h>
#include <X11/VPaned.h>
#include <X11/Scrollbar.h>
#endif
#define     VPORT_WIDGET_CLASS      viewportWidgetClass
#define     DRAW_WIDGET_CLASS drawWidgetClass
#ifdef      BUTTONS
#include <X11/Command.h>
#define     FORM_WIDGET_CLASS formWidgetClass
#endif

#endif      /* XtSpecificationRelease */

#if   XtSpecificationRelease < 5
typedef     caddr_t           XPointer;
#endif

#else /* not TOOLKIT */

typedef     int         Position;

#endif      /* not TOOLKIT */

#ifdef      VMS
/*
 * Magnifying glass cursor
 *
 * Developed by Tom Sawyer, April 1990
 * Contibuted by Hunter Goatley, January 1991
 *
 */

#define mag_glass_width 16
#define mag_glass_height 16
#define mag_glass_x_hot 6
#define mag_glass_y_hot 6
static char mag_glass_bits[] = {
      0xf8, 0x03, 0x0c, 0x06, 0xe2, 0x09, 0x13, 0x1a, 0x01, 0x14, 0x01, 0x14,
      0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x03, 0x10, 0x02, 0x18, 0x0c, 0x34,
      0xf8, 0x6f, 0x00, 0xd8, 0x00, 0xb0, 0x00, 0xe0
};
#include <decw$cursor.h>      /* Include the DECWindows cursor symbols */
static      int   DECWCursorFont;   /* Space for the DECWindows cursor font  */
static      Pixmap      MagnifyPixmap;    /* Pixmap to hold our special mag-glass  */
#include <X11/Xresource.h>      /* Motif apparently needs this one */
#endif      /* VMS */

/*
 * Command line flags.
 */

static      Dimension   bwidth      = 2;

#define     fore_Pixel  resource._fore_Pixel
#define     back_Pixel  resource._back_Pixel
#ifdef      TOOLKIT
struct _resource  resource;
#define     brdr_Pixel  resource._brdr_Pixel
#define     hl_Pixel    resource._hl_Pixel
#define     cr_Pixel    resource._cr_Pixel
#ifdef GRID
#define grid1_Pixel     resource._grid1_Pixel
#define grid2_Pixel     resource._grid2_Pixel
#define grid3_Pixel     resource._grid3_Pixel
#endif /* GRID */
#else /* not TOOLKIT */
static      _Xconst char      *brdr_color;
static      _Xconst char      *high_color;
static      _Xconst char      *curs_color;
static      Pixel       hl_Pixel, cr_Pixel;
#ifdef GRID
static  Pixel           grid1_Pixel, grid2_Pixel, grid3_Pixel;
#endif /* GRID */
#endif      /* not TOOLKIT */

struct      mg_size_rec mg_size[5]  = {{200, 150}, {400, 250}, {700, 500},
                                 {1000, 800}, {1200, 1200}};

static      char  *curr_page;

struct WindowRec mane   = {(Window) 0, 1, 0, 0, 0, 0, MAXDIM, 0, MAXDIM, 0};
struct WindowRec alt    = {(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};

#ifdef      lint
#ifdef      TOOLKIT
WidgetClass widgetClass;
#ifndef MOTIF
WidgetClass viewportWidgetClass;
#ifdef      BUTTONS
WidgetClass formWidgetClass, compositeWidgetClass, commandWidgetClass;
#endif      /* BUTTONS */
#else /* MOTIF */
WidgetClass xmMainWindowWidgetClass, xmDrawingAreaWidgetClass;
#ifdef      BUTTONS
WidgetClass xmFormWidgetClass, xmBulletinBoardWidgetClass;
WidgetClass xmPushButtonWidgetClass;
#endif      /* BUTTONS */
#endif /* MOTIF */
#endif      /* TOOLKIT */
#endif      /* lint */

/*
 *    Data for options processing
 */

static      _Xconst     char  silent[] = " ";   /* flag value for usage() */

static      _Xconst     char  subst[]     = "x";      /* another flag value */

static      _Xconst char      *subst_val[] = {
#ifdef      BUTTONS
                              "-shrinkbutton[1-4] <shrink>",
#endif
                              "-mgs[n] <size>"};

#ifdef      TOOLKIT

static      XrmOptionDescRec  options[] = {
{"-s",          ".shrinkFactor", XrmoptionSepArg,       (caddr_t) SHRINK},
#ifndef     VMS
{"-S",            ".densityPercent", XrmoptionSepArg, (caddr_t) NULL},
#endif
{"-density",      ".densityPercent", XrmoptionSepArg, (caddr_t) NULL},
#ifdef      GREY
{"-nogrey", ".grey",    XrmoptionNoArg,         (caddr_t) "off"},
{"+nogrey", ".grey",    XrmoptionNoArg,         (caddr_t) "on"},
{"-gamma",  ".gamma",   XrmoptionSepArg,  (caddr_t) NULL},
{"-install",      ".install", XrmoptionNoArg,         (caddr_t) "on"},
{"-noinstall",    ".install", XrmoptionNoArg,         (caddr_t) "off"},
#endif
#ifdef GRID
{"-grid1",      ".grid1Color",  XrmoptionSepArg,        (caddr_t) NULL},
{"-grid2",      ".grid2Color",  XrmoptionSepArg,        (caddr_t) NULL},
{"-grid3",      ".grid3Color",  XrmoptionSepArg,        (caddr_t) NULL},
#endif /* GRID */
{"-p",            ".pixelsPerInch", XrmoptionSepArg,  (caddr_t) NULL},
{"-margins",      ".Margin",  XrmoptionSepArg,  (caddr_t) NULL},
{"-sidemargin",   ".sideMargin",    XrmoptionSepArg,  (caddr_t) NULL},
{"-topmargin",    ".topMargin",     XrmoptionSepArg,  (caddr_t) NULL},
{"-offsets",      ".Offset",  XrmoptionSepArg,  (caddr_t) NULL},
{"-xoffset",      ".xOffset", XrmoptionSepArg,  (caddr_t) NULL},
{"-yoffset",      ".yOffset", XrmoptionSepArg,  (caddr_t) NULL},
{"-paper",  ".paper",   XrmoptionSepArg,  (caddr_t) NULL},
{"-altfont",      ".altFont", XrmoptionSepArg,  (caddr_t) NULL},
#ifdef MKTEXPK
{"-nomakepk",     ".makePk",  XrmoptionNoArg,         (caddr_t) "off"},
{"+nomakepk",     ".makePk",  XrmoptionNoArg,         (caddr_t) "on"},
#endif
{"-mfmode",     ".mfMode",      XrmoptionSepArg,        (caddr_t) MFMODE},
{"-l",            ".listFonts",     XrmoptionNoArg,         (caddr_t) "on"},
{"+l",            ".listFonts",     XrmoptionNoArg,         (caddr_t) "off"},
#ifdef      BUTTONS
{"-expert", ".expert",  XrmoptionNoArg,         (caddr_t) "on"},
{"+expert", ".expert",  XrmoptionNoArg,         (caddr_t) "off"},
{"-shrinkbutton1",".shrinkButton1",XrmoptionSepArg,   (caddr_t) NULL},
{"-shrinkbutton2",".shrinkButton2",XrmoptionSepArg,   (caddr_t) NULL},
{"-shrinkbutton3",".shrinkButton3",XrmoptionSepArg,   (caddr_t) NULL},
{"-shrinkbutton4",".shrinkButton4",XrmoptionSepArg,   (caddr_t) NULL},
#endif
{"-mgs",    ".magnifierSize1",XrmoptionSepArg,  (caddr_t) NULL},
{"-mgs1",   ".magnifierSize1",XrmoptionSepArg,  (caddr_t) NULL},
{"-mgs2",   ".magnifierSize2",XrmoptionSepArg,  (caddr_t) NULL},
{"-mgs3",   ".magnifierSize3",XrmoptionSepArg,  (caddr_t) NULL},
{"-mgs4",   ".magnifierSize4",XrmoptionSepArg,  (caddr_t) NULL},
{"-mgs5",   ".magnifierSize5",XrmoptionSepArg,  (caddr_t) NULL},
{"-warnspecials", ".warnSpecials", XrmoptionNoArg,    (caddr_t) "on"},
{"+warnspecials", ".warnSpecials", XrmoptionNoArg,    (caddr_t) "off"},
{"-hush",   ".Hush",    XrmoptionNoArg,         (caddr_t) "on"},
{"+hush",   ".Hush",    XrmoptionNoArg,         (caddr_t) "off"},
{"-hushchars",    ".hushLostChars", XrmoptionNoArg,   (caddr_t) "on"},
{"+hushchars",    ".hushLostChars", XrmoptionNoArg,   (caddr_t) "off"},
{"-hushchecksums", ".hushChecksums", XrmoptionNoArg,  (caddr_t) "on"},
{"+hushchecksums", ".hushChecksums", XrmoptionNoArg,  (caddr_t) "off"},
{"-safer",  ".safer",   XrmoptionNoArg,         (caddr_t) "on"},
{"+safer",  ".safer",   XrmoptionNoArg,         (caddr_t) "off"},
{"-fg",           ".foreground",    XrmoptionSepArg,  (caddr_t) NULL},
{"-foreground",   ".foreground",    XrmoptionSepArg,  (caddr_t) NULL},
{"-bg",           ".background",    XrmoptionSepArg,  (caddr_t) NULL},
{"-background",   ".background",    XrmoptionSepArg,  (caddr_t) NULL},
{"-hl",           ".highlight",     XrmoptionSepArg,  (caddr_t) NULL},
{"-cr",           ".cursorColor",   XrmoptionSepArg,  (caddr_t) NULL},
{"-icongeometry",".iconGeometry",XrmoptionSepArg,     (caddr_t) NULL},
{"-keep",   ".keepPosition",XrmoptionNoArg,           (caddr_t) "on"},
{"+keep",   ".keepPosition",XrmoptionNoArg,           (caddr_t) "off"},
{"-copy",   ".copy",    XrmoptionNoArg,         (caddr_t) "on"},
{"+copy",   ".copy",    XrmoptionNoArg,         (caddr_t) "off"},
{"-thorough",     ".thorough",      XrmoptionNoArg,         (caddr_t) "on"},
{"+thorough",     ".thorough",      XrmoptionNoArg,         (caddr_t) "off"},
#if   PS
{"-nopostscript",".postscript",     XrmoptionNoArg,         (caddr_t) "off"},
{"+nopostscript",".postscript",     XrmoptionNoArg,         (caddr_t) "on"},
{"-noscan", ".prescan", XrmoptionNoArg,         (caddr_t) "off"},
{"+noscan", ".prescan", XrmoptionNoArg,         (caddr_t) "on"},
{"-allowshell",   ".allowShell",    XrmoptionNoArg,         (caddr_t) "on"},
{"+allowshell",   ".allowShell",    XrmoptionNoArg,         (caddr_t) "off"},
#ifdef      PS_DPS
{"-nodps",  ".dps",           XrmoptionNoArg,         (caddr_t) "off"},
{"+nodps",  ".dps",           XrmoptionNoArg,         (caddr_t) "on"},
#endif
#ifdef      PS_NEWS
{"-nonews", ".news",    XrmoptionNoArg,         (caddr_t) "off"},
{"+nonews", ".news",    XrmoptionNoArg,         (caddr_t) "on"},
#endif
#ifdef      PS_GS
{"-noghostscript",".ghostscript", XrmoptionNoArg,     (caddr_t) "off"},
{"+noghostscript",".ghostscript", XrmoptionNoArg,     (caddr_t) "on"},
{"-nogssafer",    ".gsSafer", XrmoptionNoArg,         (caddr_t) "off"},
{"+nogssafer",    ".gsSafer", XrmoptionNoArg,         (caddr_t) "on"},
{"-gsalpha",      ".gsAlpha", XrmoptionNoArg,         (caddr_t) "on"},
{"+gsalpha",      ".gsAlpha", XrmoptionNoArg,         (caddr_t) "off"},
{"-interpreter",".interpreter",     XrmoptionSepArg,  (caddr_t) NULL},
{"-gspalette",    ".palette", XrmoptionSepArg,  (caddr_t) NULL},
#endif
#endif      /* PS */
{"-debug",  ".debugLevel",    XrmoptionSepArg,  (caddr_t) NULL},
{"-version",      ".version", XrmoptionNoArg,         (caddr_t) "on"},
{"+version",      ".version", XrmoptionNoArg,         (caddr_t) "off"},
#ifdef HTEX
{"-underlink",  ".underLink",   XrmoptionNoArg,         (caddr_t) "on"},
{"+underlink",  ".underLink",   XrmoptionNoArg,         (caddr_t) "off"},
{"-browser",    ".wwwBrowser",  XrmoptionSepArg,        (caddr_t) NULL},
{"-base",       ".urlBase",     XrmoptionSepArg,        (caddr_t) NULL},
#endif
};

#define     offset(field)     XtOffsetOf(struct _resource, field)

static int  base_tick_length = 4;

static      char  XtRBool3[]  = "Bool3";  /* resource for Bool3 */

static      XtResource  application_resources[] = {
#if CFGFILE
{"name", "Name", XtRString, sizeof(char *),
  offset(progname), XtRString, (caddr_t) NULL},
#endif
{"shrinkFactor", "ShrinkFactor", XtRInt, sizeof(int),
  offset(shrinkfactor), XtRImmediate, (XtPointer) SHRINK},
/*  offset(shrinkfactor), XtRString, SHRINK}, */
{"delayRulers", "DelayRulers", XtRBoolean, sizeof(Boolean),
  offset(_delay_rulers), XtRString, "true"},
{"densityPercent", "DensityPercent", XtRInt, sizeof(int),
  offset(_density), XtRString, "40"},
#ifdef      GREY
{"gamma", "Gamma", XtRFloat, sizeof(float),
  offset(_gamma), XtRString, "1"},
#endif
{"pixelsPerInch", "PixelsPerInch", XtRInt, sizeof(int),
  offset(_pixels_per_inch), XtRImmediate, (XtPointer) BDPI},
{"sideMargin", "Margin", XtRString, sizeof(char *),
  offset(sidemargin), XtRString, (caddr_t) NULL},
{"tickLength", "TickLength", XtRInt, sizeof(int),
  offset(_tick_length), XtRInt, (caddr_t) &base_tick_length},
{"tickUnits", "TickUnits", XtRString, sizeof(char *),
  offset(_tick_units), XtRString, "pt"},
{"topMargin", "Margin", XtRString, sizeof(char *),
  offset(topmargin), XtRString, (caddr_t) NULL},
{"xOffset", "Offset", XtRString, sizeof(char *),
  offset(xoffset), XtRString, (caddr_t) NULL},
{"yOffset", "Offset", XtRString, sizeof(char *),
  offset(yoffset), XtRString, (caddr_t) NULL},
{"paper", "Paper", XtRString, sizeof(char *),
  offset(paper), XtRString, (caddr_t) DEFAULT_PAPER},
{"altFont", "AltFont", XtRString, sizeof(char *),
  offset(_alt_font), XtRString, (caddr_t) ALTFONT},
{"makePk", "MakePk", XtRBoolean, sizeof(Boolean),
  offset(makepk), XtRString,
#if MAKE_TEX_PK_BY_DEFAULT
  "true"
#else
  "false"
#endif
  },
{"mfMode", "MfMode", XtRString, sizeof(char *),
  offset(mfmode), XtRString, MFMODE},
{"listFonts", "ListFonts", XtRBoolean, sizeof(Boolean),
  offset(_list_fonts), XtRString, "false"},
{"reverseVideo", "ReverseVideo", XtRBoolean, sizeof(Boolean),
  offset(reverse), XtRString, "false"},
{"warnSpecials", "WarnSpecials", XtRBoolean, sizeof(Boolean),
  offset(_warn_spec), XtRString, "false"},
{"hushLostChars", "Hush", XtRBoolean, sizeof(Boolean),
  offset(_hush_chars), XtRString, "false"},
{"hushChecksums", "Hush", XtRBoolean, sizeof(Boolean),
  offset(_hush_chk), XtRString, "false"},
{"safer", "Safer", XtRBoolean, sizeof(Boolean),
  offset(safer), XtRString, "false"},
#ifdef VMS
{"foreground", "Foreground", XtRString, sizeof(char *),
  offset(fore_color), XtRString, (caddr_t) NULL},
{"background", "Background", XtRString, sizeof(char *),
  offset(back_color), XtRString, (caddr_t) NULL},
#endif
{"iconGeometry", "IconGeometry", XtRString, sizeof(char *),
  offset(icon_geometry), XtRString, (caddr_t) NULL},
{"keepPosition", "KeepPosition", XtRBoolean, sizeof(Boolean),
  offset(keep_flag), XtRString, "false"},
#if   PS
{"postscript", "Postscript", XtRBoolean, sizeof(Boolean),
  offset(_postscript), XtRString, "true"},
{"prescan", "Prescan", XtRBoolean, sizeof(Boolean),
  offset(prescan), XtRString, "true"},
{"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, (caddr_t) GS_PATH},
{"palette", "Palette", XtRString, sizeof(char *),
  offset(gs_palette), XtRString, (caddr_t) "Color"},
#endif
#endif      /* PS */
{"copy", "Copy", XtRBoolean, sizeof(Boolean),
  offset(copy), XtRString, "false"},
{"thorough", "Thorough", XtRBoolean, sizeof(Boolean),
  offset(thorough), XtRString, "false"},
{"debugLevel", "DebugLevel", XtRString, sizeof(char *),
  offset(debug_arg), XtRString, (caddr_t) NULL},
{"version", "Version", XtRBoolean, sizeof(Boolean),
  offset(version_flag), XtRString, "false"},
#ifdef      BUTTONS
{"expert", "Expert", XtRBoolean, sizeof(Boolean),
  offset(expert), XtRString, "false"},
{"shrinkButton1", "ShrinkButton1", XtRInt, sizeof(int),
  offset(shrinkbutton[0]), XtRImmediate, (XtPointer) 0},
{"shrinkButton2", "ShrinkButton2", XtRInt, sizeof(int),
  offset(shrinkbutton[1]), XtRImmediate, (XtPointer) 0},
{"shrinkButton3", "ShrinkButton3", XtRInt, sizeof(int),
  offset(shrinkbutton[2]), XtRImmediate, (XtPointer) 0},
{"shrinkButton4", "ShrinkButton4", XtRInt, sizeof(int),
  offset(shrinkbutton[3]), XtRImmediate, (XtPointer) 0},
#endif
{"magnifierSize1", "MagnifierSize", XtRString, sizeof(char *),
  offset(mg_arg[0]), XtRString, (caddr_t) NULL},
{"magnifierSize2", "MagnifierSize", XtRString, sizeof(char *),
  offset(mg_arg[1]), XtRString, (caddr_t) NULL},
{"magnifierSize3", "MagnifierSize", XtRString, sizeof(char *),
  offset(mg_arg[2]), XtRString, (caddr_t) NULL},
{"magnifierSize4", "MagnifierSize", XtRString, sizeof(char *),
  offset(mg_arg[3]), XtRString, (caddr_t) NULL},
{"magnifierSize5", "MagnifierSize", XtRString, sizeof(char *),
  offset(mg_arg[4]), XtRString, (caddr_t) NULL},
#ifdef      GREY
{"grey", "Grey", XtRBoolean, sizeof(Boolean),
  offset(_use_grey), XtRString, "true"},
{"install", "Install", XtRBool3, sizeof(Bool3),
  offset(install), XtRString, "maybe"},
#endif
#ifdef GRID
{"grid1Color", "Grid1Color", XtRPixel, sizeof(Pixel),
  offset(_grid1_Pixel), XtRPixel, (caddr_t) &resource._grid1_Pixel},
{"grid1Color", "Grid1Color", XtRString, sizeof(char *),
  offset(grid1_color), XtRString, (caddr_t) NULL},
{"grid2Color", "Grid2Color", XtRPixel, sizeof(Pixel),
  offset(_grid2_Pixel), XtRPixel, (caddr_t) &resource._grid2_Pixel},
{"grid2Color", "Grid2Color", XtRString, sizeof(char *),
  offset(grid2_color), XtRString, (caddr_t) NULL},
{"grid3Color", "Grid3Color", XtRPixel, sizeof(Pixel),
  offset(_grid3_Pixel), XtRPixel, (caddr_t) &resource._grid3_Pixel},
{"grid3Color", "Grid3Color", XtRString, sizeof(char *),
  offset(grid3_color), XtRString, (caddr_t) NULL},
#endif /* GRID */
#ifdef HTEX
{"underLink", "UnderLink", XtRBoolean, sizeof(Boolean),
  offset(_underline_link), XtRString, (caddr_t) "true"},
{"wwwBrowser", "WWWBrowser", XtRString, sizeof(char *),
  offset(_browser), XtRString, (caddr_t) NULL},
{"urlBase", "URLBase", XtRString, sizeof(char *),
  offset(_URLbase), XtRString, (caddr_t) NULL},
#endif
#ifdef      GREY
};

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, (caddr_t) &resource._fore_Pixel},
{"highlight", "Highlight", XtRPixel, sizeof(Pixel),
  offset(_hl_Pixel), XtRPixel, (caddr_t) &resource._fore_Pixel},
{"cursorColor", "CursorColor", XtRPixel, sizeof(Pixel),
  offset(_cr_Pixel), XtRPixel, (caddr_t) &resource._fore_Pixel},
};
#undef      offset

static      _Xconst     char  *usagestr[] = {
      /* shrinkFactor */      "shrink",
#ifndef     VMS
      /* S */                 "density",
      /* density */           silent,
#else
      /* density */           "density",
#endif
#ifdef      GREY
      /* gamma */       "g",
#endif
#ifdef GRID
        /* grid1 */             "color",
        /* grid2 */             "color",
        /* grid3 */             "color",
#endif /* GRID */
      /* p */                 "pixels",
      /* margins */           "dimen",
      /* sidemargin */  "dimen",
      /* topmargin */         "dimen",
      /* offsets */           "dimen",
      /* xoffset */           "dimen",
      /* yoffset */           "dimen",
      /* paper */       "papertype",
      /* altfont */           "font",
      /* mfmode */            "mode-def",
      /* rv */          "^-l", "-rv",
#ifdef      BUTTONS
      /* shrinkbutton1 */     subst,
      /* shrinkbutton2 */     silent,
      /* shrinkbutton3 */     silent,
      /* shrinkbutton4 */     silent,
#endif
      /* mgs */         subst,
      /* mgs1 */        silent,
      /* mgs2 */        silent,
      /* mgs3 */        silent,
      /* mgs4 */        silent,
      /* mgs5 */        silent,
      /* bw */          "^-safer", "-bw <width>",
      /* fg */          "color",
      /* foreground */  silent,
      /* bg */          "color",
      /* background */  silent,
      /* hl */          "color",
      /* bd */          "^-hl", "-bd <color>",
      /* cr */          "color",
#ifndef VMS
      /* display */           "^-cr", "-display <host:display>",
#else
      /* display */           "^-cr", "-display <host::display>",
#endif
      /* geometry */          "^-cr", "-geometry <geometry>",
      /* icongeometry */      "geometry",
      /* iconic */            "^-icongeometry", "-iconic",
#ifdef      BUTTONS
      /* font */        "^-icongeometry", "-font <font>",
#endif
#ifdef      PS_GS
      /* interpreter */ "path",
      /* gspalette */         "monochrome|grayscale|color",
#endif
      /* debug */       "bitmask",
#ifdef HTEX
        /* browser */           "WWWbrowser",
        /* URLbase */           "base URL",
#endif
      /* [dummy] */           "z"
};

static char *TmpDir=NULL;

#ifndef MOTIF

#ifdef      NOQUERY
#define     drawWidgetClass   widgetClass
#else

/* ARGSUSED */
static      XtGeometryResult
QueryGeometry(w, constraints, reply)
      Widget      w;
      XtWidgetGeometry *constraints, *reply;
{
      reply->request_mode = CWWidth | CWHeight;
      reply->width = page_w;
      reply->height = page_h;
      return XtGeometryAlmost;
}

#include <X11/IntrinsicP.h>
#include <X11/CoreP.h>

#ifdef      lint
WidgetClassRec    widgetClassRec;
#endif

      /* 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 /* MOTIF */

static      Arg   vport_args[] = {
#ifndef MOTIF
#ifdef      BUTTONS
      {XtNborderWidth,  (XtArgVal) 0},
      {XtNtop,          (XtArgVal) XtChainTop},
      {XtNbottom,       (XtArgVal) XtChainBottom},
      {XtNleft,         (XtArgVal) XtChainLeft},
      {XtNright,        (XtArgVal) XtChainRight},
#endif
      {XtNallowHoriz,         (XtArgVal) True},
      {XtNallowVert,          (XtArgVal) True},
#else /* MOTIF */
      {XmNscrollingPolicy,    (XtArgVal) XmAUTOMATIC},
      {XmNborderWidth,  (XtArgVal) 0},
      {XmNleftAttachment,     (XtArgVal) XmATTACH_FORM},
      {XmNtopAttachment,      (XtArgVal) XmATTACH_FORM},
      {XmNbottomAttachment,   (XtArgVal) XmATTACH_FORM},
      {XmNrightAttachment,    (XtArgVal) XmATTACH_FORM},
#endif /* MOTIF */
};

static      Arg   draw_args[] = {
#ifndef MOTIF
      {XtNwidth,        (XtArgVal) 0},
      {XtNheight,       (XtArgVal) 0},
      {XtNx,                  (XtArgVal) 0},
      {XtNy,                  (XtArgVal) 0},
      {XtNlabel,        (XtArgVal) ""},
#else /* MOTIF */
      {XmNwidth,        (XtArgVal) 0},
      {XmNheight,       (XtArgVal) 0},
      {XmNbottomAttachment,   (XtArgVal) XmATTACH_WIDGET},
#endif /* MOTIF */
};

#ifdef      BUTTONS
static      Arg   form_args[] = {
#ifndef MOTIF
      {XtNdefaultDistance, (XtArgVal) 0},
#else /* MOTIF */
      {XmNhorizontalSpacing, (XtArgVal) 0},
      {XmNverticalSpacing, (XtArgVal) 0},
#endif /* MOTIF */
};
#endif

#ifdef HTEX

static Arg      pane_args[] = {
        {XtNorientation,        (XtArgVal) XtorientVertical},
};

/* Create the anchor information stuff at the bottom of the page */

/* Anchor search: a dialog box */
char anchorsearchstring[1024];
char anchorask[] = "Access new URL:";
static  Arg     anchorsearch_args[] = {
        {XtNwidth,      (XtArgVal) 500},
        {XtNheight,     (XtArgVal) 70},
        {XtNlabel,      (XtArgVal) anchorask},
        {XtNvalue,      (XtArgVal) anchorsearchstring},
        {XtNmin,        (XtArgVal) 70},
        {XtNscrollHorizontal,   (XtArgVal) XawtextScrollWhenNeeded},
};

/* anchorinfo = Ascii text widget */
static  Arg     anchorinfo_args[] = {
        {XtNwidth,      (XtArgVal) 500},
        {XtNheight,     (XtArgVal) 20},
        {XtNstring,     (XtArgVal) ""},
        {XtNmin,        (XtArgVal) 20},
        {XtNscrollVertical,     (XtArgVal) XawtextScrollWhenNeeded},
        {XtNscrollHorizontal,   (XtArgVal) XawtextScrollWhenNeeded},
};

#endif

#else /* not TOOLKIT */

static      char  *display;
static      char  *geometry;
static      char  *margins;
static      char  *offsets;
static      Boolean     hush;
static      Boolean     iconic      = False;

#define     ADDR(x)     (caddr_t) &resource.x

static      struct option {
      _Xconst     char  *name;
      _Xconst     char  *resource;
      enum {FalseArg, TrueArg, StickyArg, SepArg}
                  argclass;
      enum {BooleanArg, Bool3Arg, StringArg, NumberArg, FloatArg}
                  argtype;
      int         classcount;
      _Xconst     char  *usagestr;
      caddr_t           address;
}     options[] = {
{"+",       NULL,       StickyArg, StringArg, 1,
  NULL,           (caddr_t) &curr_page},
{"-s",            "shrinkFactor", SepArg, NumberArg, 1,
  "shrink", (caddr_t) &shrink_factor},
#ifndef VMS
{"-S",            NULL,       SepArg, NumberArg, 2,
  "density",      ADDR(_density)},
{"-density",      "densityPercent", SepArg, NumberArg, 1,
  silent,   ADDR(_density)},
#else
{"-density",      "densityPercent", SepArg, NumberArg, 1,
  "density",      ADDR(_density)},
#endif
#ifdef      GREY
{"-nogrey", NULL,       FalseArg, BooleanArg, 2,
  NULL,           ADDR(_use_grey)},
{"+nogrey", "grey",           TrueArg, BooleanArg, 1,
  NULL,           ADDR(_use_grey)},
{"-gamma",  "gamma",    SepArg,     FloatArg, 1,
  "g",            ADDR(_gamma)},
{"-install",      NULL,       TrueArg, Bool3Arg, 2,
  NULL,           ADDR(install)},
{"-noinstall",    "install",  FalseArg, Bool3Arg, 1,
  NULL,           ADDR(install)},
#endif
#ifdef GRID
{"-grid1",      "grid1Color",   SepArg, StringArg, 1,
  "color",      ADDR(grid1_color)},
{"-grid2",      "grid2Color",   SepArg, StringArg, 1,
  "color",      ADDR(grid2_color)},
{"-grid3",      "grid3Color",   SepArg, StringArg, 1,
  "color",      ADDR(grid3_color)},
#endif /* GRID */
{"-p",            "pixelsPerInch", SepArg, NumberArg, 1,
  "pixels", ADDR(_pixels_per_inch)},
{"-margins",      "Margin",   SepArg,     StringArg, 3,
  "dimen",  (caddr_t) &margins},
{"-sidemargin",   "sideMargin",     SepArg,     StringArg, 1,
  "dimen",  ADDR(sidemargin)},
{"-topmargin",    "topMargin",      SepArg,     StringArg, 1,
  "dimen",  ADDR(topmargin)},
{"-offsets",      "Offset",   SepArg,     StringArg, 3,
  "dimen",  (caddr_t) &offsets},
{"-xoffset",      "xOffset",  SepArg,     StringArg, 1,
  "dimen",  ADDR(xoffset)},
{"-yoffset",      "yOffset",  SepArg,     StringArg, 1,
  "dimen",  ADDR(yoffset)},
{"-paper",  "paper",    SepArg,     StringArg, 1,
  "papertype",    ADDR(paper)},
{"-altfont",      "altFont",  SepArg,     StringArg, 1,
  "font",   ADDR(_alt_font)},
{"-nomakepk",     "makePk",   FalseArg, BooleanArg, 2,
  NULL,           ADDR(makepk)},
{"+nomakepk",     "makePk",   TrueArg, BooleanArg, 1,
  NULL,           ADDR(makepk)},
{"-mfmode", "mfMode",   SepArg,     StringArg, 1,
  "mode-def",     ADDR(mfmode)},
{"-l",            NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(_list_fonts)},
{"+l",            "listFonts",      FalseArg, BooleanArg, 1,
  NULL,           ADDR(_list_fonts)},
{"-rv",           NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(reverse)},
{"+rv",           "reverseVideo",   FalseArg, BooleanArg, 1,
  NULL,           ADDR(reverse)},
{"-mgs",    NULL,       SepArg, StringArg, 2,
  subst,    ADDR(mg_arg[0])},
{"-mgs1",   "magnifierSize1",SepArg, StringArg, 1,
  silent,   ADDR(mg_arg[0])},
{"-mgs2",   "magnifierSize2",SepArg, StringArg, 1,
  silent,   ADDR(mg_arg[1])},
{"-mgs3",   "magnifierSize3",SepArg, StringArg, 1,
  silent,   ADDR(mg_arg[2])},
{"-mgs4",   "magnifierSize4",SepArg, StringArg, 1,
  silent,   ADDR(mg_arg[3])},
{"-mgs5",   "magnifierSize5",SepArg, StringArg, 1,
  silent,   ADDR(mg_arg[4])},
{"-warnspecials", NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(_warn_spec)},
{"+warnspecials", "warnSpecials", FalseArg, BooleanArg, 1,
  NULL,           ADDR(_warn_spec)},
{"-hush",   NULL,       TrueArg, BooleanArg, 6,
  NULL,           (caddr_t) &hush},
{"+hush",   "Hush",           FalseArg, BooleanArg, 5,
  NULL,           (caddr_t) &hush},
{"-hushchars",    NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(_hush_chars)},
{"+hushchars",    "hushLostChars", FalseArg, BooleanArg, 1,
  NULL,           ADDR(_hush_chars)},
{"-hushchecksums", NULL,      TrueArg, BooleanArg, 2,
  NULL,           ADDR(_hush_chk)},
{"+hushchecksums","hushChecksums", FalseArg, BooleanArg, 1,
  NULL,           ADDR(_hush_chk)},
{"-safer",  NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(safer)},
{"+safer",  "safer",    FalseArg, BooleanArg, 1,
  NULL,           ADDR(safer)},
{"-bw",           NULL,       SepArg,     NumberArg, 2,
  "width",  (caddr_t) &bwidth},
{"-borderwidth", "borderWidth",     SepArg,     NumberArg, 1,
  silent,   (caddr_t) &bwidth},
{"-fg",           NULL,       SepArg,     StringArg, 2,
  "color",  ADDR(fore_color)},
{"-foreground",   "foreground",     SepArg,     StringArg, 1,
  silent,   ADDR(fore_color)},
{"-bg",           NULL,       SepArg,     StringArg, 2,
  "color",  ADDR(back_color)},
{"-background",   "background",     SepArg,     StringArg, 1,
  silent,   ADDR(back_color)},
{"-hl",           "highlight",      SepArg,     StringArg, 1,
  "color",  (caddr_t) &high_color},
{"-bd",           NULL,       SepArg,     StringArg, 2,
  "color",  (caddr_t) &brdr_color},
{"-bordercolor","borderColor",      SepArg,     StringArg, 1,
  silent,   (caddr_t) &brdr_color},
{"-cr",           "cursorColor",    SepArg,     StringArg, 1,
  "color",  (caddr_t) &curs_color},
#ifndef VMS
{"-display",      NULL,       SepArg,     StringArg, 1,
  "host:display", (caddr_t) &display},
#else
{"-display",      NULL,       SepArg,     StringArg, 1,
  "host::display", (caddr_t) &display},
#endif
{"-geometry",     "geometry", SepArg,     StringArg, 1,
  "geometry",     (caddr_t) &geometry},
{"-icongeometry","iconGeometry",StickyArg, StringArg, 1,
  "geometry",     ADDR(icon_geometry)},
{"-iconic", NULL,       TrueArg, BooleanArg, 2,
  NULL,           (caddr_t) &iconic},
{"+iconic", "iconic",   FalseArg, BooleanArg, 1,
  NULL,           (caddr_t) &iconic},
{"-keep",   NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(keep_flag)},
{"+keep",   "keepPosition",   FalseArg, BooleanArg, 1,
  NULL,           ADDR(keep_flag)},
{"-copy",   NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(copy)},
{"+copy",   "copy",           FalseArg, BooleanArg, 1,
  NULL,           ADDR(copy)},
{"-thorough",     NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(thorough)},
{"+thorough",     "thorough", FalseArg, BooleanArg, 1,
  NULL,           ADDR(thorough)},
#if   PS
{"-nopostscript", NULL,       FalseArg, BooleanArg, 2,
  NULL,           ADDR(_postscript)},
{"+nopostscript", "postscript",     TrueArg, BooleanArg, 1,
  NULL,           ADDR(_postscript)},
{"-noscan", NULL,       FalseArg, BooleanArg, 2,
  NULL,           ADDR(prescan)},
{"+noscan", "prescan",  TrueArg, BooleanArg, 1,
  NULL,           ADDR(prescan)},
{"-allowshell",   NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(allow_shell)},
{"+allowshell",   "allowShell",     FalseArg, BooleanArg, 1,
  NULL,           ADDR(allow_shell)},
#ifdef      PS_DPS
{"-nodps",  NULL,       FalseArg, BooleanArg, 2,
  NULL,           ADDR(useDPS)},
{"+nodps",  "dps",            TrueArg, BooleanArg, 1,
  NULL,           ADDR(useDPS)},
#endif
#ifdef      PS_NEWS
{"-nonews", NULL,       FalseArg, BooleanArg, 2,
  NULL,           ADDR(useNeWS)},
{"+nonews", "news",           TrueArg, BooleanArg, 1,
  NULL,           ADDR(useNeWS)},
#endif
#ifdef      PS_GS
{"-noghostscript",NULL,       FalseArg, BooleanArg, 2,
  NULL,           ADDR(useGS)},
{"+noghostscript","ghostscript", TrueArg, BooleanArg, 1,
  NULL,           ADDR(useGS)},
{"-nogssafer",    NULL,       FalseArg, BooleanArg, 2,
  NULL,           ADDR(gs_safer)},
{"+nogssafer",    "gsSafer",  TrueArg, BooleanArg, 1,
  NULL,           ADDR(gs_safer)},
{"-nogsalpha",    NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(gs_alpha)},
{"+nogsalpha",    "gsAlpha",  FalseArg, BooleanArg, 1,
  NULL,           ADDR(gs_alpha)},
{"-interpreter", "interpreter",     SepArg,     StringArg, 1,
  "path",   ADDR(gs_path)},
{"-gspalette",    "palette",  SepArg,     StringArg, 1,
  "monochrome|grayscale|color",     ADDR(gs_palette)},
#endif
#endif      /* PS */
{"-debug",  "debugLevel",     SepArg,     StringArg, 1,
  "bitmask",      ADDR(debug_arg)},
{"-version",      NULL,       TrueArg, BooleanArg, 2,
  NULL,           ADDR(version_flag)},
{"+version",      "version",  FalseArg, BooleanArg, 1,
  NULL,           ADDR(version_flag)},
#ifdef HTEX
{"-underlink",  "underLink",    TrueArg, BooleanArg, 2,
  NULL,         ADDR(_underline_link)},
{"+underlink",  "underLink",    FalseArg, BooleanArg, 1,
  NULL,         ADDR(_underline_link)},
{"-browser",    "wwwBrowser",   SepArg, StringArg, 1,   ADDR(_browser)},
{"-base",       "urlBase",      SepArg, StringArg, 1,   ADDR(_URLbase)},
#endif
};

#endif      /* not TOOLKIT */

static      NORETURN void
usage() {
#ifdef      TOOLKIT
      XrmOptionDescRec *opt;
      _Xconst     char  **usageptr = usagestr;
#else
      struct option     *opt;
#endif
      _Xconst char      **sv  = subst_val;
      _Xconst char      *str1;
      _Xconst char      *str2;
      int         col   = 23;
      int         n;

#ifdef Omega
        Fputs("Usage: oxdvi [+[<page>]]", stderr);
#else
      Fputs("Usage: xdvi [+[<page>]]", stderr);
#endif
      for (opt = options; opt < options + XtNumber(options); ++opt) {
#ifdef      TOOLKIT
          str1 = opt->option;
          if (*str1 != '-') continue;
          str2 = NULL;
          if (opt->argKind != XrmoptionNoArg) {
            str2 = *usageptr++;
            if (str2 == silent) continue;
            if (str2 == subst) {
                str1 = *sv++;
                str2 = NULL;
            }
          }
          for (;;) {
            n = strlen(str1) + 3;
            if (str2 != NULL) n += strlen(str2) + 3;
            if (col + n < 80) Putc(' ', stderr);
            else {
                Fputs("\n\t", stderr);
                col = 8 - 1;
            }
            if (str2 == NULL)
                Fprintf(stderr, "[%s]", str1);
            else
                Fprintf(stderr, "[%s <%s>]", str1, str2);
            col += n;
            if (**usageptr != '^'
                   || strcmp(*usageptr + 1, opt->option) != 0) break;
            ++usageptr;
            str1 = *usageptr++;
            str2 = NULL;
          }
#else /* not TOOLKIT */
          str1 = opt->name;
          str2 = opt->usagestr;
          if (*str1 != '-' || str2 == silent) continue;
          if (str2 == subst) {
            str1 = *sv++;
            str2 = NULL;
          }
          n = strlen(str1) + 3;
          if (str2 != NULL) n += strlen(str2) + 3;
          if (col + n < 80) Putc(' ', stderr);
          else {
            Fputs("\n\t", stderr);
            col = 8 - 1;
          }
          if (str2 == NULL)
            Fprintf(stderr, "[%s]", str1);
          else
            Fprintf(stderr, "[%s <%s>]", str1, str2);
          col += n;
#endif /* not TOOLKIT */
      }
      if (col + 9 < 80) Putc(' ', stderr);
      else Fputs("\n\t", stderr);
#ifdef SELFILE
        Fputs("[dvi_file]\n", stderr);
#else
      Fputs("dvi_file\n", stderr);
#endif
      exit(1);
}

static      int
atopix(arg)
      _Xconst     char  *arg;
{
      int         len   = strlen(arg);
      _Xconst char      *arg_end = arg;
      char        tmp[11];
      double            factor;

      while ((*arg_end >= '0' && *arg_end <= '9') || *arg_end == '.')
          if (arg_end >= arg + XtNumber(tmp) - 1) return 0;
          else ++arg_end;
      bcopy(arg, tmp, arg_end - arg);
      tmp[arg_end - arg] = '\0';

#if A4
      factor = 1.0 / 2.54;    /* cm */
#else
      factor = 1.0;           /* inches */
#endif
      if (len > 2)
          switch (arg[len - 2] << 8 | arg[len - 1]) {
#if A4
            case 'i' << 8 | 'n':  factor = 1.0;             break;
#else
            case 'c' << 8 | 'm':  factor = 1.0 / 2.54;            break;
#endif
            case 'm' << 8 | 'm':  factor = 1.0 / 25.4;            break;
            case 'p' << 8 | 't':  factor = 1.0 / 72.27;           break;
            case 'p' << 8 | 'c':  factor = 12.0 / 72.27;          break;
            case 'b' << 8 | 'p':  factor = 1.0 / 72.0;            break;
            case 'd' << 8 | 'd':  factor = 1238.0 / 1157.0 / 72.27;     break;
            case 'c' << 8 | 'c':  factor = 12 * 1238.0 / 1157.0 / 72.27;
                                                      break;
            case 's' << 8 | 'p':  factor = 1.0 / 72.27 / 65536;   break;
          }

      return factor * atof(tmp) * pixels_per_inch + 0.5;
}

#ifdef GRID
/* extract the unit used in paper size specification */
/* the information is used to decide the initial grid separation */
static  int
atopixunit(arg)
        _Xconst char    *arg;
{
        int     len     = strlen(arg);

        return (len > 2 && arg[len - 2] == 'c' && arg[len - 1] == 'm' ?
                1.0 / 2.54 : 1.0) * pixels_per_inch + 0.5;
}
#endif /* GRID */

/**
 **   Main programs start here.
 **/

#ifdef      TOOLKIT

#ifdef GREY
static      Arg   temp_args1[] = {
      {XtNdepth,  (XtArgVal) 0},
      {XtNvisual, (XtArgVal) 0},
      {XtNcolormap,     (XtArgVal) 0},
};
#define     temp_args1a (temp_args1 + 2)
#endif

static      Arg   temp_args2[] = {
      {XtNiconX,  (XtArgVal) 0},
      {XtNiconY,  (XtArgVal) 0},
};

static      Arg   temp_args3 = {XtNborderWidth, (XtArgVal) &bwidth};

static      Pixmap      icon_pm;
static      Arg   temp_args4 = {XtNiconPixmap,  (XtArgVal) &icon_pm};

static      Arg   temp_args5[] = {
      {XtNtitle,  (XtArgVal) 0},
      {XtNiconName,     (XtArgVal) 0},
      {XtNinput,  (XtArgVal) True},
};

static      Arg   set_wh_args[] = {
      {XtNwidth,  (XtArgVal) 0},
      {XtNheight, (XtArgVal) 0},
};


#ifdef GREY

/*
 *    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).
 */

#if XtSpecificationRelease >= 5

/*ARGSUSED*/
static      Boolean
XdviCvtStringToPixel(dpy, args, num_args, fromVal, toVal, closure_ret)
      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))
        || (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);
}

#else /* XtSpecificationRelease < 5 */

/*
 *    Copied from the X11R4 source code.
 */

#define     done(type, value) \
      {                                         \
          if (toVal->addr != NULL) {                        \
            if (toVal->size < sizeof(type)) {         \
                toVal->size = sizeof(type);                 \
                return False;                   \
            }                                   \
            *(type*)(toVal->addr) = (value);          \
          }                                     \
          else {                                \
            static type static_val;                   \
            static_val = (value);                     \
            toVal->addr = (XtPointer)&static_val;           \
          }                                     \
          toVal->size = sizeof(type);                       \
          return True;                          \
      }

static      Boolean
XdviCvtStringToPixel(dpy, args, num_args, fromVal, toVal, closure_ret)
    Display*      dpy;
    XrmValuePtr args;
    Cardinal    *num_args;
    XrmValuePtr   fromVal;
    XrmValuePtr   toVal;
    XtPointer     *closure_ret;
{
    String      str = (String)fromVal->addr;
    XColor      screenColor;
    XColor      exactColor;
    Screen      *screen;
    Colormap          colormap;
    Status      status;
    String          params[1];
    Cardinal          num_params=1;

    if (*num_args != 2)
     XtErrorMsg("wrongParameters", "cvtStringToPixel",
               "XtToolkitError",
      "String to pixel conversion needs screen and colormap arguments",
        (String *)NULL, (Cardinal *)NULL);

    screen = *((Screen **) args[0].addr);
    colormap = *((Colormap *) args[1].addr);

    if (strcmp(str, XtDefaultBackground) == 0) {
      *closure_ret = False;
      str = (resource.reverse ? "black" : "white");
    }
    else if (strcmp(str, XtDefaultForeground) == 0) {
      *closure_ret = False;
      str = (resource.reverse ? "white" : "black");
    }

    if (*str == '#') {  /* some color rgb definition */

        status = XParseColor(DisplayOfScreen(screen), colormap,
                       (char*)str, &screenColor);

        if (status != 0)
           status = XAllocColor(DisplayOfScreen(screen), colormap,
                                &screenColor);
    } else  /* some color name */

        status = XAllocNamedColor(DisplayOfScreen(screen), colormap,
                                  (char*)str, &screenColor, &exactColor);
    if (status == 0) {
      params[0] = str;
      XtWarningMsg("noColormap", "cvtStringToPixel",
                  "XtToolkitError",
                 "Cannot allocate colormap entry for \"%s\"",
                  params,&num_params);
      return False;
    } else {
      *closure_ret = (char*)True;
        done(Pixel, screenColor.pixel);
    }
}
#undef      done

#endif /* XtSpecificationRelease < 5 */

/*
 *    Convert string to yes/no/maybe.  Adapted from the X toolkit.
 */

/*ARGSUSED*/
Boolean XdviCvtStringToBool3(dpy, args, num_args, fromVal, toVal, closure_ret)
      Display           *dpy;
      XrmValuePtr args;
      Cardinal    *num_args;
      XrmValuePtr fromVal;
      XrmValuePtr toVal;
      XtPointer   *closure_ret;
{
      String            str   = (String)fromVal->addr;
      static Bool3      value;

      if (   memicmp(str, "true", 5) == 0
          || memicmp(str, "yes", 4) == 0
          || memicmp(str, "on", 3) == 0
          || memicmp(str, "1", 2) == 0)   value = True;

      else if (memicmp(str, "false", 6) == 0
          ||   memicmp(str, "no", 3) == 0
          ||   memicmp(str, "off", 4) == 0
          ||   memicmp(str, "0", 2) == 0) value = False;

      else if (memicmp(str, "maybe", 6) == 0)   value = Maybe;

      else {
          XtDisplayStringConversionWarning(dpy, str, XtRBoolean);
          return False;
      }

      if (toVal->addr != NULL) {
          if (toVal->size < sizeof(Bool3)) {
            toVal->size = sizeof(Bool3);
            return False;
          }
          *(Bool3 *)(toVal->addr) = value;
      }
      else toVal->addr = (XPointer) &value;

      toVal->size = sizeof(Bool3);
      return True;
}

#endif /* GREY */

#else /* not TOOLKIT */

struct _resource  resource = {
      /* density        */    40,
#ifdef      GREY
      /* gamma          */    1.0,
#endif
      /* pixels_per_inch      */    BDPI,
        /* _delay_rulers      */    True,
      /* _tick_length         */    4,
      /* _tick_units          */    "pt",
      /* sidemargin           */    NULL,
      /* topmargin            */    NULL,
      /* xoffset        */    NULL,
      /* yoffset        */    NULL,
      /* paper          */    DEFAULT_PAPER,
      /* alt_font       */    ALTFONT,
      /* makepk         */    MAKE_TEX_PK_BY_DEFAULT,
      /* mfmode         */    MFMODE,
      /* list_fonts           */    False,
      /* reverse        */    False,
      /* warn_spec            */    False,
      /* hush_chars           */    False,
      /* hush_chk       */    False,
      /* safer          */    False,
      /* fore_color           */    NULL,
      /* back_color           */    NULL,
      /* fore_Pixel           */    (Pixel) 0,
      /* back_Pixel           */    (Pixel) 0,
      /* icon_geometry  */    NULL,
      /* keep_flag            */    False,
      /* copy                 */    False,
      /* thorough       */    False,
#if   PS
      /* postscript           */    True,
      /* prescan        */    True,
      /* allow_shell          */    False,
#ifdef      PS_DPS
      /* useDPS         */    True,
#endif
#ifdef      PS_NEWS
      /* useNeWS        */    True,
#endif
#ifdef      PS_GS
      /* useGS          */    True,
      /* gs_safer       */    True,
      /* gs_alpha       */    False,
      /* gs_path        */    GS_PATH,
      /* gs_palette           */    "Color",
#endif
#endif      /* PS */
      /* debug_arg            */    NULL,
      /* version_flag         */    False,
      /* mg_arg         */    {NULL, NULL, NULL, NULL, NULL},
#ifdef      GREY
      /* use_grey       */    True,
      /* install        */    Maybe,
#endif
#ifdef GRID
        /* grid_mode            */      0,
        /* grid1_color          */      NULL,
        /* grid2_color          */      NULL,
        /* grid3_color          */      NULL,
#endif /* GRID */                                       
#ifdef HTEX
        /* _underline_link      */      True,
        /* _browser             */      (char *) NULL,
        /* _URLbase             */      (char *) NULL,
#endif
};

static      Pixel
string_to_pixel(strp)         /* adapted from the toolkit */
      char  **strp;
{
      char  *str = *strp;
      Status      status;
      XColor      color, junk;

      if (*str == '#') {      /* an rgb definition */
          status = XParseColor(DISP, our_colormap, str, &color);
          if (status != 0)
            status = XAllocColor(DISP, our_colormap, &color);
      }
      else  /* a name */
          status = XAllocNamedColor(DISP, our_colormap, str, &color, &junk);
      if (status == 0) {
          Fprintf(stderr, "Cannot allocate colormap entry for \"%s\"\n", str);
          *strp = NULL;
          return (Pixel) 0;
      }
      return color.pixel;
}

/*
 *    Process the option table.  This is not guaranteed for all possible
 *    option tables, but at least it works for this one.
 */

static      void
parse_options(argc, argv)
      int argc;
      char **argv;
{
      char  **arg;
      char  **argvend = argv + argc;
      char  *optstring;
      caddr_t     addr;
      struct option *opt, *lastopt, *candidate;
      int   len1, len2, matchlen;

      /*
       * Step 1.  Process command line options.
       */
      for (arg = argv + 1; arg < argvend; ++arg) {
          len1 = strlen(*arg);
          candidate = NULL;
          matchlen = 0;
          for (opt = options; opt < options + XtNumber(options); ++opt) {
            len2 = strlen(opt->name);
            if (opt->argclass == StickyArg) {
                if (matchlen <= len2 && !strncmp(*arg, opt->name, len2)) {
                  candidate = opt;
                  matchlen = len2;
                }
            }
            else if (len1 <= len2 && matchlen <= len1 &&
                !strncmp(*arg, opt->name, len1)) {
                if (len1 == len2) {
                  candidate = opt;
                  break;
                }
                if (matchlen < len1) candidate = opt;
                else if (candidate && candidate->argclass != StickyArg)
                  candidate = NULL;
                matchlen = len1;
            }
          }
          if (candidate == NULL) {
            if (**arg == '-' || dvi_name) usage();
            else {
                    /* need to make sure that dvi_name can be freed safely */
                    dvi_name = xmalloc((unsigned) strlen(*arg)+1);
                    Strcpy(dvi_name, *arg);
                continue;
            }
          }
            /* flag it for subsequent processing */
          candidate->resource = (char *) candidate;
            /* store the value */
          addr = candidate->address;
          switch (candidate->argclass) {
            case FalseArg:    *((Boolean *) addr) = False; continue;
            case TrueArg:     *((Boolean *) addr) = True; continue;
            case StickyArg:   optstring = *arg + strlen(candidate->name);
                break;
            case SepArg:
                ++arg;
                if (arg >= argvend) usage();
                optstring = *arg;
                break;
          }
          switch (candidate->argtype) {
            case StringArg:   *((char **) addr) = optstring; break;
            case NumberArg:   *((int *) addr) = atoi(optstring); break;
            case FloatArg:  *((float *) addr) = atof(optstring); break;
            default:  ;
          }
      }
      /*
       * Step 2.  Propagate classes for command line arguments.  Backwards.
       */
      for (opt = options + XtNumber(options) - 1; opt >= options; --opt)
          if (opt->resource == (char *) opt) {
            addr = opt->address;
            lastopt = opt + opt->classcount;
            for (candidate = opt; candidate < lastopt; ++candidate) {
                if (candidate->resource != NULL) {
                  switch (opt->argtype) {
                      case BooleanArg:
                      case Bool3Arg:      /* same type as Boolean */
                        *((Boolean *) candidate->address) =
                            *((Boolean *) addr);
                        break;
                      case StringArg:
                        *((char **) candidate->address) =
                            *((char **) addr);
                        break;
                      case NumberArg:
                        *((int *) candidate->address) = *((int *) addr);
                        break;
                      case FloatArg:
                        *((float *) candidate->address) =
                            *((float *) addr);
                        break;
                  }
                  candidate->resource = NULL;
                }
            }
          }

      if ((DISP = XOpenDisplay(display)) == NULL)
          oops("Can't open display");
      SCRN = DefaultScreenOfDisplay(DISP);
      /*
       * Step 3.  Handle resources (including classes).
       */
      for (opt = options; opt < options + XtNumber(options); ++opt)
          if (opt->resource &&
                ((optstring = XGetDefault(DISP, prog, opt->resource)) ||
                (optstring = XGetDefault(DISP, "XDvi", opt->resource))))
            {
                lastopt = opt + opt->classcount;
                for (candidate = opt; candidate < lastopt; ++candidate)
                  if (candidate->resource != NULL) switch (opt->argtype) {
                      case Bool3Arg:
                        if (       memicmp(optstring, "maybe", 6) == 0)
                        {
                            * (Bool3 *) candidate->address = Maybe;
                            break;
                        }
                        /* otherwise, fall through; the underlying */
                        /* types of Bool3 and Boolean are the same. */
                      case BooleanArg:
                        * (Boolean *) candidate->address =
                            (  memicmp(optstring, "true", 5) == 0
                            || memicmp(optstring, "yes", 4) == 0
                            || memicmp(optstring, "on", 3) == 0
                            || memicmp(optstring, "1", 2) == 0);
                        break;
                      case StringArg:
                        * (char **) candidate->address = optstring;
                        break;
                      case NumberArg:
                        * (int *) candidate->address = atoi(optstring);
                        break;
                      case FloatArg:
                        * (float *) candidate->address =
                            atof(optstring);
                  }
            }
}

#endif      /* not TOOLKIT */

static      _Xconst     char  *paper_types[] = {
      "us",       "8.5x11in",
      "usr",            "11x8.5in",
      "legal",    "8.5x14in",
      "foolscap", "13.5x17.0in",    /* ??? */

      /* ISO `A' formats, Portrait */
      "a1",       "59.4x84.0cm",
      "a2",       "42.0x59.4cm",
      "a3",       "29.7x42.0cm",
      "a4",       "21.0x29.7cm",
      "a5",       "14.85x21.0cm",
      "a6",       "10.5x14.85cm",
      "a7",       "7.42x10.5cm",

      /* ISO `A' formats, Landscape */
      "a1r",            "84.0x59.4cm",
      "a2r",            "59.4x42.0cm",
      "a3r",            "42.0x29.7cm",
      "a4r",            "29.7x21.0cm",
      "a5r",            "21.0x14.85cm",
      "a6r",            "14.85x10.5cm",
      "a7r",            "10.5x7.42cm",

      /* ISO `B' formats, Portrait */
      "b1",       "70.6x100.0cm",
      "b2",       "50.0x70.6cm",
      "b3",       "35.3x50.0cm",
      "b4",       "25.0x35.3cm",
      "b5",       "17.6x25.0cm",
      "b6",       "13.5x17.6cm",
      "b7",       "8.8x13.5cm",

      /* ISO `B' formats, Landscape */
      "b1r",            "100.0x70.6cm",
      "b2r",            "70.6x50.0cm",
      "b3r",            "50.0x35.3cm",
      "b4r",            "35.3x25.0cm",
      "b5r",            "25.0x17.6cm",
      "b6r",            "17.6x13.5cm",
      "b7r",            "13.5x8.8cm",

      /* ISO `C' formats, Portrait */
      "c1",       "64.8x91.6cm",
      "c2",       "45.8x64.8cm",
      "c3",       "32.4x45.8cm",
      "c4",       "22.9x32.4cm",
      "c5",       "16.2x22.9cm",
      "c6",       "11.46x16.2cm",
      "c7",       "8.1x11.46cm",

      /* ISO `C' formats, Landscape */
      "c1r",            "91.6x64.8cm",
      "c2r",            "64.8x45.8cm",
      "c3r",            "45.8x32.4cm",
      "c4r",            "32.4x22.9cm",
      "c5r",            "22.9x16.2cm",
      "c6r",            "16.2x11.46cm",
      "c7r",            "11.46x8.1cm",
};

static      Boolean
set_paper_type() {
      _Xconst     char  *arg, *arg1;
      char  temp[21];
      _Xconst     char  **p;
      char  *q;

      if (strlen(resource.paper) > sizeof(temp) - 1) return False;
      arg = resource.paper;
      q = temp;
      for (;;) {  /* convert to lower case */
          char c = *arg++;
          if (c >= 'A' && c <= 'Z') c ^= ('a' ^ 'A');
          *q++ = c;
          if (c == '\0') break;
      }
      arg = temp;
      /* perform substitutions */
      for (p = paper_types; p < paper_types + XtNumber(paper_types); p += 2)
          if (strcmp(temp, *p) == 0) {
            arg = p[1];
            break;
          }
        arg1 = strchr(arg, 'x');
      if (arg1 == NULL) return False;
      unshrunk_paper_w = atopix(arg);
      unshrunk_paper_h = atopix(arg1 + 1);
#ifdef GRID
        unshrunk_paper_unit = atopixunit(arg);
#endif /* GRID */
      return (unshrunk_paper_w != 0 && unshrunk_paper_h != 0);
}

/* Set the icon name and title name standard properties on `top_level'
   (which we don't pass in because it is a different type for TOOLKIT
   !and TOOLKIT).  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.  */

void
set_icon_and_title (dvi_name, icon_ret, title_ret, set_std)
    char *dvi_name;
    char **icon_ret;
    char **title_ret;
    int set_std;
{
  /* Use basename of DVI file for name in icon and title.  */
  unsigned baselen;
  char *icon_name, *title_name;

        icon_name = strrchr(dvi_name, '/');
        if (icon_name != NULL) ++icon_name; else icon_name = dvi_name;
        baselen = strlen(icon_name);
        if (baselen >= sizeof(".dvi")
                && strcmp(icon_name + baselen - sizeof(".dvi") + 1, ".dvi")
                == 0) {         /* remove the .dvi */
            char *p;

            baselen -= sizeof(".dvi") - 1;
            p = xmalloc(baselen + 1);
            (void) strncpy(p, icon_name, (int) baselen);
            p[baselen] = '\0';
            icon_name = p;
        }
#ifdef Omega
        title_name = xmalloc(baselen + sizeof("(Omega) OXdvi:  "));
        Strcpy(title_name, "(Omega) OXdvi:  ");
#else
        title_name = xmalloc(baselen + sizeof("Xdvi:  "));
        Strcpy(title_name, "Xdvi:  ");
#endif
        Strcat(title_name, icon_name);

  if (icon_ret) *icon_ret = icon_name;
  if (title_ret) *title_ret = title_name;
  if (set_std) {
    Window top_window =
#ifdef TOOLKIT
      XtWindow (top_level);
#else
      top_level;
#endif

    XSetStandardProperties(DISP, top_window, title_name, icon_name,
                         (Pixmap) 0, NULL, 0, NULL);
  }
}


static void remove_temporary_dir(void)

{
  int err;

  if (TmpDir!=NULL) {
    err=rmdir(TmpDir);
    if (err!=0 && errno!=ENOENT) {
      char *buffer=malloc(160);
      if (buffer==NULL) oops("Please buy more RAM");
      sprintf(buffer,"xdvik: Warning: Could not remove temporary directory %s",
            TmpDir);
      perror(buffer);
    }
  }
}

/* Create a temporary directory where we can write files from this program */
static void
make_temporary_dir(tmpdir)
char **tmpdir;
{
  int ret;

  *tmpdir = tempnam(NULL,"xdvi");

  if (*tmpdir == NULL)
    oops("Out of memory. Exiting.");

  if (debug & DBG_HYPER)
    fprintf(stderr,"Making temporary directory %s\n",*tmpdir);

  ret = mkdir(*tmpdir, 0700);

  /* The use of atexit and one variable to store the directory name
     makes this procedure a oneoff.  Enforce it */
  if (TmpDir!=NULL)
    oops("make_temporary_dir called twice!\n");

  TmpDir=xstrdup(*tmpdir);

  /* SunOS does not have atexit, but on_exit instead. */
#ifdef HAVE_ATEXIT
  atexit(remove_temporary_dir);
#else
  on_exit(remove_temporary_dir, 0);
#endif

  if (ret != 0)
    /* Didn't work, PANIC! */
    oops("Could not create temporary directory. Exiting.");

}


/*
 *    main program
 */

int
main(argc, argv)
      int argc;
      char **argv;
{

#ifndef     TOOLKIT
      XSizeHints  size_hints;
      XWMHints    wmhints;
      int         flag;
      int         x_thick     = 0;
      int         y_thick     = 0;
#endif      /* TOOLKIT */
#ifdef MOTIF
      Widget            menubar;
      Widget            scale_menu;
#endif
      Dimension   screen_w, screen_h;
      char        *title_name;
      char        *icon_name;
      int         i;

      /*
       *    Step 1:  Process command-line options and resources.
       */

      /* This has to be a special case, for now. */

      if (argc == 2 && (strcmp(argv[1], "-version") == 0 ||
                    strcmp(argv[1], "--version") == 0 ||
                    strcmp(argv[1], "+version") == 0
                    ))
      {
          Printf("xdvi(k) version %s\n", TVERSION);
          Printf("Copyright (C) 1990-1999 Paul Vojta.\n\
Primary author of Xdvi: Paul Vojta;\n\
Xdvi-k maintainer: janl@math.uio.no.\n\
\n\
xdvi itself is licensed under the X Consortium license.  xdvik relies\n\
on the kpathsea library which is covered by the GNU LIBRARY General\n\
Public License (see COPYING.LIB for full details) and libwww which is\n\
copyrighted by the World Wide Web Consortium and CERN (see COPYRIGH for\n\
full details).\n\
\n\
There is NO WARRANTY of anything.\n");
          exit(0);
      }

        if (argc == 2 && ((strcmp (argv[1], "-help") == 0)
                         || (strcmp (argv[1], "+help") == 0)
                         || (strcmp (argv[1], "--help") == 0)
                         ))
          {
            extern char *kpse_bug_address;
          Printf("xdvi(k) version %s\n", TVERSION);
            Printf("Preview a DVI file under the X window system.\n%s\n",
               kpse_bug_address);
            usage (); /* Unfortunately this exits with status 1.  */
          }


#ifndef     VMS
      prog = strrchr(*argv, '/');
#else
      prog = strrchr(*argv, ']');
#endif
      if (prog != NULL) ++prog; else prog = *argv;

#ifdef      VMS
      if (strchr(prog, '.') != NULL) *strchr(prog, '.') = '\0';
#endif

        /* We can't initialize this at compile time, because it might be
           the result of a function call under POSIX. */
        n_files_left = OPEN_MAX;

        kpse_set_program_name (argv[0], "xdvi");
        kpse_set_program_enabled (kpse_any_glyph_format,
                                  MAKE_TEX_PK_BY_DEFAULT, kpse_src_compile);


#if   CFGFILE
      /* get the debug value (if any) from the environment */
      /* (it's too early to get it from the command line) */
      {
          _Xconst char *dbg_str;

          dbg_str = getenv("XDVIDEBUG");
          if (dbg_str != NULL)
            debug = atoi(dbg_str);
      }
#ifdef      SELFAUTO
      argv0 = argv[0];
#endif
#ifndef     CFG2RES
      readconfig();           /* read config file(s). */
#else /* CFG2RES */
      {
          static _Xconst struct cfg2res cfg2reslist[] = {
            {"MFMODE",        "mfMode",         False},
            {"PIXELSPERINCH", "pixelsPerInch",  True},
            {"SHRINKFACTOR",  "shrinkFactor",         True},
#ifdef      BUTTONS
            {"SHRINKBUTTON1", "shrinkButton1",  True},
            {"SHRINKBUTTON2", "shrinkButton2",  True},
            {"SHRINKBUTTON3", "shrinkButton3",  True},
            {"SHRINKBUTTON4", "shrinkButton4",  True},
#endif
            {"PAPER",         "paper",          False},
          };

          readconfig(cfg2reslist, cfg2reslist + XtNumber(cfg2reslist),
            application_resources,
            application_resources + XtNumber(application_resources));
      }
#endif      /* CFG2RES */
#endif      /* CFGFILE */

#ifdef      TOOLKIT

      top_level = XtInitialize(prog, "XDvi", options, XtNumber(options),
        &argc, argv);
      while (--argc > 0) {
          if (*(*++argv) == '+')
            if (curr_page != NULL) usage();
            else curr_page = *argv + 1;
          else if (dvi_name != NULL) usage();
                else {
                    /* need to make sure that dvi_name can be freed safely */
                    dvi_name = xmalloc((unsigned) strlen(*argv)+1);
                    Strcpy(dvi_name, *argv);
                }
      }

      DISP = XtDisplay(top_level);
      SCRN = XtScreen(top_level);

#ifdef GREY
      XtSetTypeConverter(XtRString, XtRBool3, XdviCvtStringToBool3,
        NULL, 0, XtCacheNone, NULL);
#endif

      XtGetApplicationResources(top_level, (XtPointer) &resource,
        application_resources, XtNumber(application_resources),
        (ArgList) NULL, 0);
      shrink_factor = resource.shrinkfactor;

#if CFGFILE
      if (resource.progname != NULL)
          prog = resource.progname;
#endif

#else /* not TOOLKIT */

      parse_options(argc, argv);

#endif /* not TOOLKIT */

      if (resource.mfmode != NULL) {
          char *p;

          p = strrchr(resource.mfmode, ':');
          if (p != NULL) {
            unsigned int      len;
            char        *p1;

            ++p;
            len = p - resource.mfmode;
            p1 = xmalloc(len);
            bcopy(resource.mfmode, p1, len - 1);
            p1[len - 1] = '\0';
            resource.mfmode = p1;
            pixels_per_inch = atoi(p);
          }
      }
      if (shrink_factor < 0 || density <= 0 || pixels_per_inch <= 0
#ifndef SELFILE
          || dvi_name == NULL
#endif
          ) usage();
      if (shrink_factor > 1) {
          bak_shrink = shrink_factor;
          mane.shrinkfactor = shrink_factor;    /* otherwise it's 1 */
      }
      if (resource.debug_arg != NULL) {
          debug = isdigit(*resource.debug_arg) ? atoi(resource.debug_arg)
            : DBG_ALL;
          if (debug & DBG_OPEN) KPSE_DEBUG_SET (KPSE_DEBUG_FOPEN);
          if (debug & DBG_STAT) KPSE_DEBUG_SET (KPSE_DEBUG_STAT);
          if (debug & DBG_HASH) KPSE_DEBUG_SET (KPSE_DEBUG_HASH);
          if (debug & DBG_PATHS) KPSE_DEBUG_SET (KPSE_DEBUG_PATHS);
          if (debug & DBG_EXPAND) KPSE_DEBUG_SET (KPSE_DEBUG_EXPAND);
          if (debug & DBG_SEARCH) KPSE_DEBUG_SET (KPSE_DEBUG_SEARCH);
      }

      if (resource.sidemargin) home_x = atopix(resource.sidemargin);
      if (resource.topmargin) home_y = atopix(resource.topmargin);
      offset_x = resource.xoffset ? atopix(resource.xoffset)
          : pixels_per_inch;
      offset_y = resource.yoffset ? atopix(resource.yoffset)
          : pixels_per_inch;
      if (!set_paper_type())
          oops("Don't recognize paper type %s", resource.paper);
      for (i = 0; i < 5; ++i)
          if (resource.mg_arg[i] != NULL) {
            char  *s;

            mg_size[i].w = mg_size[i].h = atoi(resource.mg_arg[i]);
                s = strchr(resource.mg_arg[i], 'x');
            if (s != NULL) {
                mg_size[i].h = atoi(s + 1);
                if (mg_size[i].h <= 0) mg_size[i].w = 0;
            }
          }
#if   PS
      if (resource.safer) {
          resource.allow_shell = False;
#ifdef      PS_GS
          resource.gs_safer = True;
#endif
      }
#endif      /* PS */
#ifdef      PS_GS
      {
          _Xconst char *CGMcgm = "CGMcgm";
          _Xconst char *cgmp;

          cgmp = strchr(CGMcgm, resource.gs_palette[0]);
          if (cgmp == NULL)
            oops("Invalid value %s for gs palette option",
                resource.gs_palette);
          if (cgmp >= CGMcgm + 3) {
            static      char  gsp[] = "x";

            gsp[0] = *(cgmp - 3);
            resource.gs_palette = gsp;
          }
      }
#endif

        if (resource.version_flag)
            Printf("xdvi version %s\n", TVERSION);

        kpse_init_prog ("XDVI", pixels_per_inch, resource.mfmode, alt_font);

      if (debug) {
        fprintf(stderr,"XDVI %d/%d/%s/%s\n", pixels_per_inch, shrink_factor,
            resource.mfmode, alt_font);
        fprintf(stderr,"Paper %s\n", 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 GREY

      screen_number = 0;      /* yyuucchh */
      while (SCRN != ScreenOfDisplay(DISP, screen_number)) ++screen_number;

      our_depth = DefaultDepthOfScreen(SCRN);
      our_visual = DefaultVisualOfScreen(SCRN);
      our_colormap = DefaultColormapOfScreen(SCRN);
      copyGC = DefaultGCOfScreen(SCRN);

      if (resource.install != False && our_visual->class == PseudoColor) {
          /* look for a TrueColor visual with more bits */
          XVisualInfo   template;
          XVisualInfo   *list;
          int           nitems_return;

          template.screen = screen_number;
          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)
                if (list1->depth > our_depth
                  && (best == NULL || list1->depth > best->depth))
                  best = list1;
            if (best != NULL) {
                our_depth = best->depth;
                our_visual = best->visual;
                our_colormap = XCreateColormap(DISP,
                  RootWindowOfScreen(SCRN), our_visual, AllocNone);
                XInstallColormap(DISP, our_colormap);
                copyGC = NULL;
#ifdef TOOLKIT
                temp_args1[0].value = (XtArgVal) our_depth;
                temp_args1[1].value = (XtArgVal) our_visual;
                temp_args1[2].value = (XtArgVal) our_colormap;
                XtSetValues(top_level, temp_args1, XtNumber(temp_args1));
                XtSetTypeConverter(XtRString, XtRPixel,
                  XdviCvtStringToPixel,
                  (XtConvertArgList) colorConvertArgs, 2,
                  XtCacheByDisplay, NULL);
#else
                /* Can't use {Black,White}PixelOfScreen() any more */
                if (!resource.fore_color)
                  resource.fore_color =
                    (resource.reverse ? "white" : "black");
                if (!resource.back_color)
                  resource.back_color =
                    (resource.reverse ? "black" : "white");
#endif
            }
            XFree(list);
          }
      }

      if (resource.install == True && our_visual->class == PseudoColor) {
          XColor tmp_color;

          /* 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, our_colormap, &tmp_color);
          XAllocColor(DISP, our_colormap, &tmp_color);

          tmp_color.pixel = WhitePixelOfScreen(SCRN);
          XQueryColor(DISP, our_colormap, &tmp_color);
          XAllocColor(DISP, our_colormap, &tmp_color);

          our_colormap = XCopyColormapAndFree(DISP, our_colormap);
#ifdef TOOLKIT
          temp_args1a[0].value = (XtArgVal) our_colormap;
          XtSetValues(top_level, temp_args1a, 1);
#endif
      }

#ifdef TOOLKIT
      XtGetApplicationResources(top_level, (XtPointer) &resource,
        app_pixel_resources, XtNumber(app_pixel_resources),
        (ArgList) NULL, 0);
#endif

#endif /* GREY */

#ifndef TOOLKIT
      fore_Pixel = (resource.fore_color
        ? string_to_pixel(&resource.fore_color)
        : (resource.reverse ? WhitePixelOfScreen(SCRN)
          : BlackPixelOfScreen(SCRN)));
      back_Pixel = (resource.back_color
        ? string_to_pixel(&resource.back_color)
        : (resource.reverse ? BlackPixelOfScreen(SCRN)
          : WhitePixelOfScreen(SCRN)));
      brdr_Pixel = (brdr_color ? string_to_pixel(&brdr_color) : fore_Pixel);
      hl_Pixel = (high_color ? string_to_pixel(&high_color) : fore_Pixel);
      cr_Pixel = (curs_color ? string_to_pixel(&curs_color) : fore_Pixel);

#ifdef GRID
        if (resource.grid1_color)
            grid1_Pixel = string_to_pixel(&resource.grid1_color);
        if (resource.grid2_color)
            grid2_Pixel = string_to_pixel(&resource.grid2_color);
        if (resource.grid3_color)
            grid3_Pixel = string_to_pixel(&resource.grid3_color);
#endif /* GRID */

#endif      /* not TOOLKIT */

#ifdef      GREY
      if (our_depth == 1)
          use_grey = False;

      if (use_grey && our_visual->class != TrueColor) {
          fore_color_data.pixel = fore_Pixel;
          XQueryColor(DISP, our_colormap, &fore_color_data);
          back_color_data.pixel = back_Pixel;
          XQueryColor(DISP, our_colormap, &back_color_data);
          init_plane_masks();
          if (!copy) {
            back_color_data.pixel = back_Pixel;
            XStoreColor(DISP, our_colormap, &back_color_data);
          }
      }
#endif

      /*
       *    Step 3:  Open the dvi file and set titles.
       */

#ifdef SELFILE
        /* If no filename by here, so pop up a selection box. */
        if (dvi_name == NULL)
          {
            extern FILE *select_filename ();
            (void) select_filename(False, False) ;
          /* User might have cancled  -janl */
          if (dvi_name == NULL) exit(1);
          }
#endif  /* SELFILE */

        make_temporary_dir(&temporary_dir); /* For storing temporary files.. */

#ifdef HTEX
        {
            char *cp = getenv("WWWBROWSER"); 
            if (cp) browser = cp;
        }
        HTProfile_newPreemptiveClient(HTAppName, HTAppVersion); 
        HTCacheMode_setEnabled(NO);

#if 0
        /* Optionally, turn on tracing of WWW library calls. */
        if (debug & DBG_HYPER) {
            WWWTRACE = SHOW_STREAM_TRACE; 
        }
#endif

      /* Open the input file.  Turn filename into URL first if needed */
        URL_aware = TRUE;

        if (!(URLbase || htex_is_url(dvi_name))) {
        char *new_name;
        int n;

        n = strlen(dvi_name);
        new_name = dvi_name;
        /* Find the right filename */
        if (n < sizeof(".dvi")
            || strcmp(dvi_name + n - sizeof(".dvi") + 1, ".dvi") != 0) {
          dvi_name = xmalloc((unsigned) n + sizeof(".dvi"));
          Strcpy(dvi_name, new_name);
          Strcat(dvi_name, ".dvi");
          /* Atempt $dvi_name.dvi */
          dvi_file = xfopen(dvi_name, OPEN_MODE);
          if (dvi_file == NULL) {
            /* Didn't work, revert to original $dvi_name */
            free(dvi_name);
            dvi_name = new_name;
          }
        }

        /* Turn filename into URL */
        /* Escape dangers, esp. # from emacs */
        new_name=HTEscape(dvi_name,URL_PATH);
        free(dvi_name);
        dvi_name = xmalloc((unsigned) strlen(new_name)+6);
        strcat(strcpy(dvi_name,"file:"),new_name);
        /* Now we have the right filename, in a URL */
      }
      
      detach_anchor();
      if (!open_www_file()) {
        fprintf(stderr,"Could not open dvi file. Exiting.\n");
        exit(1);
      }

        URL_aware = FALSE;
#else
        open_dvi_file();
#endif /* not HTEX */

      if (curr_page) {
            current_page = (*curr_page ? atoi(curr_page) : total_pages) - 1;
            if (current_page < 0 || current_page >= total_pages) usage();
      }
        set_icon_and_title (dvi_name, &icon_name, &title_name, 0);

      /*
       *    Step 4:  Set initial window size.
       *    This needs to be done before colors are assigned because if
       *    -s 0 is specified, then we need to compute the shrink factor
       *    (which in turn affects whether init_pix is called).
       */

#ifdef      TOOLKIT

            /* The following code is lifted from Xterm */
      if (resource.icon_geometry != NULL) {
#ifndef GREY
          int screen_number;
#endif
          int junk;

#ifndef GREY
          for (screen_number = 0;   /* yyuucchh */
            SCRN != ScreenOfDisplay(DISP, screen_number);
            ++screen_number);
#endif

          (void) XGeometry(DISP, screen_number, resource.icon_geometry, "",
                  0, 0, 0, 0, 0,
                  (int *) &temp_args2[0].value,
                  (int *) &temp_args2[1].value, &junk, &junk);
          XtSetValues(top_level, temp_args2, XtNumber(temp_args2));
      }
            /* Set icon pixmap */
      XtGetValues(top_level, &temp_args4, 1);
      if (icon_pm == (Pixmap) 0) {
          temp_args4.value = (XtArgVal) (XCreateBitmapFromData(DISP,
            RootWindowOfScreen(SCRN), (_Xconst char *) xdvi_bits,
            xdvi_width, xdvi_height));
          XtSetValues(top_level, &temp_args4, 1);
      }
      temp_args5[0].value = (XtArgVal) title_name;
      temp_args5[1].value = (XtArgVal) icon_name;
      XtSetValues(top_level, temp_args5, XtNumber(temp_args5));

#ifdef      BUTTONS
      form_widget = XtCreateManagedWidget("form", FORM_WIDGET_CLASS,
        top_level, form_args, XtNumber(form_args));
#define     form_or_top form_widget /* for calls later on */
#define     form_or_vport     form_widget
#else /* !BUTTONS */
#define     form_or_top top_level   /* for calls later on */
#define     form_or_vport     vport_widget
#endif      /* BUTTONS */

      vport_widget = XtCreateManagedWidget("vport", VPORT_WIDGET_CLASS,
        form_or_top, vport_args, XtNumber(vport_args));

#ifndef MOTIF

      clip_widget = XtNameToWidget(vport_widget, "clip");

#else /* MOTIF */

      menubar = XmVaCreateSimpleMenuBar(vport_widget, "menubar",
        XmNdepth, (XtArgVal) our_depth,
        XmNvisual, (XtArgVal) our_visual,
        XmNcolormap, (XtArgVal) our_colormap,
        XmVaCASCADEBUTTON, (XtArgVal) XmCvtCTToXmString("File"), 0,
        XmVaCASCADEBUTTON, (XtArgVal) XmCvtCTToXmString("Navigate"), 0,
        XmVaCASCADEBUTTON, (XtArgVal) XmCvtCTToXmString("Scale"), 0,
        0);
      XmVaCreateSimplePulldownMenu(menubar,
        "file_pulldown", 0, file_pulldown_callback,
        XmNtearOffModel, (XtArgVal) XmTEAR_OFF_ENABLED,
        XmNdepth, (XtArgVal) our_depth,
        XmNvisual, (XtArgVal) our_visual,
        XmNcolormap, (XtArgVal) our_colormap,
        XmVaPUSHBUTTON, (XtArgVal) XmCvtCTToXmString("Reload"), 0, 0, 0,
        XmVaSEPARATOR,
        XmVaPUSHBUTTON, (XtArgVal) XmCvtCTToXmString("Quit"), 0, 0, 0,
        0);
      XmVaCreateSimplePulldownMenu(menubar,
        "navigate_pulldown", 1, navigate_pulldown_callback,
        XmNtearOffModel, (XtArgVal) XmTEAR_OFF_ENABLED,
        XmVaPUSHBUTTON, (XtArgVal) XmCvtCTToXmString("Page-10"), 0, 0, 0,
        XmVaPUSHBUTTON, (XtArgVal) XmCvtCTToXmString("Page-5"), 0, 0, 0,
        XmVaPUSHBUTTON, (XtArgVal) XmCvtCTToXmString("Prev"), 0, 0, 0,
        XmVaSEPARATOR,
        XmVaPUSHBUTTON, (XtArgVal) XmCvtCTToXmString("Next"), 0, 0, 0,
        XmVaPUSHBUTTON, (XtArgVal) XmCvtCTToXmString("Page+5"), 0, 0, 0,
        XmVaPUSHBUTTON, (XtArgVal) XmCvtCTToXmString("Page+10"), 0, 0, 0,
        0);
      scale_menu = XmVaCreateSimplePulldownMenu(menubar,
        "scale_pulldown", 2, scale_pulldown_callback,
        XmNradioBehavior, (XtArgVal) True,
        XmNtearOffModel, (XtArgVal) XmTEAR_OFF_ENABLED,
        XmVaRADIOBUTTON, (XtArgVal) XmCvtCTToXmString("Shrink1"), 0, 0, 0,
        XmVaRADIOBUTTON, (XtArgVal) XmCvtCTToXmString("Shrink2"), 0, 0, 0,
        XmVaRADIOBUTTON, (XtArgVal) XmCvtCTToXmString("Shrink3"), 0, 0, 0,
        XmVaRADIOBUTTON, (XtArgVal) XmCvtCTToXmString("Shrink4"), 0, 0, 0,
        0);
      shrink_button[0] = XtNameToWidget(scale_menu, "button_0");
      shrink_button[1] = XtNameToWidget(scale_menu, "button_1");
      shrink_button[2] = XtNameToWidget(scale_menu, "button_2");
      shrink_button[3] = XtNameToWidget(scale_menu, "button_3");

      x_bar = XtNameToWidget(vport_widget, "HorScrollBar");
      y_bar = XtNameToWidget(vport_widget, "VertScrollBar");

#endif /* MOTIF */

      draw_args[0].value = (XtArgVal) page_w;
      draw_args[1].value = (XtArgVal) page_h;
      draw_widget = XtCreateManagedWidget("drawing", DRAW_WIDGET_CLASS,
        vport_widget, draw_args, XtNumber(draw_args));

#ifdef MOTIF
      XtVaSetValues(vport_widget, XmNworkWindow, draw_widget,
        XmNmenuBar, menubar, NULL);
      XtManageChild(menubar);
      XtVaGetValues(vport_widget, XmNclipWindow, &clip_widget, NULL);
#endif /* MOTIF */

      {     /* set default window size */
#ifdef      BUTTONS
          int xtra_wid = resource.expert ? 0 : XTRA_WID;
#else
#define     xtra_wid    0
#endif
          XtWidgetGeometry constraints;
          XtWidgetGeometry reply;

          XtGetValues(top_level, &temp_args3, 1);     /* get border width */
          screen_w = WidthOfScreen(SCRN) - 2 * bwidth - xtra_wid;
          screen_h = HeightOfScreen(SCRN) - 2 * bwidth;
          for (;;) {    /* actually, at most two passes */
            constraints.request_mode = reply.request_mode = 0;
            constraints.width = page_w;
            if (page_w > screen_w) {
                constraints.request_mode = CWWidth;
                constraints.width = screen_w;
            }
            constraints.height = page_h;
            if (page_h > screen_h) {
                constraints.request_mode |= CWHeight;
                constraints.height = screen_h;
            }
            if (constraints.request_mode != 0
                  && constraints.request_mode != (CWWidth | CWHeight))
                (void) XtQueryGeometry(vport_widget, &constraints, &reply);
            if (!(reply.request_mode & CWWidth))
                reply.width = constraints.width;
            if (reply.width >= screen_w)
                reply.width = screen_w;
            if (!(reply.request_mode & CWHeight))
                reply.height = constraints.height;
            if (reply.height >= screen_h)
                reply.height = screen_h;

            /* now reply.{width,height} contain max. usable window size */

            if (shrink_factor != 0)
                break;

            shrink_factor = ROUNDUP(unshrunk_page_w, reply.width - 2);
            i = ROUNDUP(unshrunk_page_h, reply.height - 2);
            if (i >= shrink_factor) shrink_factor = i;
            if (shrink_factor > 1) bak_shrink = shrink_factor;
            mane.shrinkfactor = shrink_factor;
            init_page();
            set_wh_args[0].value = (XtArgVal) page_w;
            set_wh_args[1].value = (XtArgVal) page_h;
            XtSetValues(draw_widget, set_wh_args, XtNumber(set_wh_args));
          }
          set_wh_args[0].value = (XtArgVal) (reply.width + xtra_wid);
          set_wh_args[1].value = (XtArgVal) reply.height;
          XtSetValues(top_level, set_wh_args, XtNumber(set_wh_args));
#ifdef      BUTTONS
          set_wh_args[0].value -= xtra_wid;
          XtSetValues(vport_widget, set_wh_args, XtNumber(set_wh_args));
#endif      /* BUTTONS */
      }
#ifdef MOTIF
      set_shrink_factor(mane.shrinkfactor);
#endif

#else /* not TOOLKIT */

      screen_w = WidthOfScreen(SCRN) - 2*bwidth;
      screen_h = HeightOfScreen(SCRN) - 2*bwidth;

      size_hints.flags = PMinSize;
      size_hints.min_width = size_hints.min_height = 50;
      size_hints.x = size_hints.y = 0;

      /* compute largest possible window */
      flag = 0;
      if (geometry != NULL) {
          flag = XParseGeometry(geometry, &size_hints.x, &size_hints.y,
            &window_w, &window_h);
          if (flag & (XValue | YValue))
            size_hints.flags |= USPosition;
          if (flag & (WidthValue | HeightValue))
            size_hints.flags |= USSize;
      }
      if (!(flag & WidthValue)) window_w = screen_w;
      if (!(flag & HeightValue)) window_h = screen_h;

      if (shrink_factor == 0) {
          /* compute best shrink factor based on window_w and window_h */
          shrink_factor = ROUNDUP(unshrunk_page_w, window_w - 2);
          i = ROUNDUP(unshrunk_page_h, window_h - 2);
          if (i >= shrink_factor) shrink_factor = i;
          if (shrink_factor > 1) bak_shrink = shrink_factor;
          mane.shrinkfactor = shrink_factor;
          init_page();
      }

      if (window_w < page_w) x_thick = BAR_THICK;
      if (window_h < page_h + x_thick) y_thick = BAR_THICK;
      if (!(flag & WidthValue)) {
          window_w = page_w + y_thick;
          if (window_w > screen_w) {
            x_thick = BAR_THICK;
            window_w = screen_w;
          }
          size_hints.flags |= PSize;
      }
      if (!(flag & HeightValue)) {
          window_h = page_h + x_thick;
          if (window_h > screen_h) window_h = screen_h;
          size_hints.flags |= PSize;
      }

      if (flag & XNegative) size_hints.x += screen_w - window_w;
      if (flag & YNegative) size_hints.y += screen_h - window_h;

#endif      /* not TOOLKIT */

      /*
       *    Step 5:  Realize the widgets (or windows).
       */

#ifdef      TOOLKIT

      {
          static Arg back_args = {XtNbackground, (XtArgVal) 0};

          back_args.value = back_Pixel;
          XtSetValues(draw_widget, &back_args, 1);
          XtSetValues(clip_widget, &back_args, 1);
      }

#ifdef BUTTONS
      if (!resource.expert)
          create_buttons(set_wh_args[1].value);
#endif
#ifdef HTEX
        pane_widget = XtCreateManagedWidget("pane", panedWidgetClass,
                top_level, pane_args, XtNumber(pane_args));
      /* Set up anchor search and information widgets: */
        anchor_search = XtCreateManagedWidget("anchorsearch", 
                dialogWidgetClass, pane_widget, anchorsearch_args,
            XtNumber(anchorsearch_args));
        XawDialogAddButton(anchor_search, "Open", search_callback, NULL);
        anchor_info = XtCreateManagedWidget("anchorinfo", asciiTextWidgetClass,
                pane_widget, anchorinfo_args, XtNumber(anchorinfo_args));
      /* Eliminate the silly caret */
        XawTextDisplayCaret(anchor_info, False);
#endif

#ifndef MOTIF
      XtAddEventHandler(form_or_vport, KeyPressMask, False,
        handle_key, (caddr_t) NULL);
#else /* MOTIF */
      XtSetSensitive(draw_widget, TRUE);
      XtAddEventHandler(draw_widget, KeyPressMask, False,
        handle_key, (caddr_t) NULL);
#endif /* MOTIF */
      XtAddEventHandler(vport_widget, StructureNotifyMask, False,
        handle_resize, (caddr_t) NULL);
      XtAddEventHandler(draw_widget, ExposureMask, False, handle_exp,
        (caddr_t) &mane);
      XtAddEventHandler(draw_widget, ButtonPressMask, False, handle_button,
        (caddr_t) NULL);
      XtAddEventHandler(draw_widget, ButtonMotionMask, False, handle_motion,
        (caddr_t) NULL);
      XtAddEventHandler(draw_widget, ButtonReleaseMask, False, handle_release,
        (caddr_t) NULL);
      XtRealizeWidget(top_level);
#ifdef MOTIF
      XmProcessTraversal(draw_widget, XmTRAVERSE_CURRENT);
#endif

      currwin.win = mane.win = XtWindow(draw_widget);

      {
          XWindowAttributes attrs;

          (void) XGetWindowAttributes(DISP, mane.win, &attrs);
          backing_store = attrs.backing_store;
      }

#else /* not TOOLKIT */

      size_hints.width = window_w;
      size_hints.height = window_h;
#ifndef GREY
      top_level = XCreateSimpleWindow(DISP, RootWindowOfScreen(SCRN),
        size_hints.x, size_hints.y, window_w, window_h, bwidth,
        brdr_Pixel, back_Pixel);
#else
      {
          XSetWindowAttributes attr;

          attr.border_pixel = brdr_Pixel;
          attr.background_pixel = back_Pixel;
          attr.colormap = our_colormap;
          top_level = XCreateWindow(DISP, RootWindowOfScreen(SCRN),
            size_hints.x, size_hints.y, window_w, window_h, bwidth,
            our_depth, InputOutput, our_visual,
            CWBorderPixel | CWBackPixel | CWColormap, &attr);
      }
#endif
      XSetStandardProperties(DISP, top_level, title_name, icon_name,
            (Pixmap) 0, argv, argc, &size_hints);

      wmhints.flags = InputHint | StateHint | IconPixmapHint;
      wmhints.input = True;   /* window manager must direct input */
      wmhints.initial_state = iconic ? IconicState : NormalState;
      wmhints.icon_pixmap = XCreateBitmapFromData(DISP,
          RootWindowOfScreen(SCRN), (_Xconst char *) xdvi_bits,
          xdvi_width, xdvi_height);
      if (resource.icon_geometry != NULL) {
          int junk;

          wmhints.flags |= IconPositionHint;
          (void) XGeometry(DISP, DefaultScreen(DISP), resource.icon_geometry,
            "", 0, 0, 0, 0, 0, &wmhints.icon_x, &wmhints.icon_y,
            &junk, &junk);
      }
      XSetWMHints(DISP, top_level, &wmhints);

      XSelectInput(DISP, top_level, KeyPressMask | StructureNotifyMask);
      XMapWindow(DISP, top_level);
      XFlush(DISP);

#endif      /* not TOOLKIT */

{
          static KeySym list[2] = {XK_Caps_Lock, XK_Num_Lock};

#define     rebindkey(ks, str)      XRebindKeysym(DISP, (KeySym) ks, \
              (KeySym *) NULL, 0, (_Xconst ubyte *) str, 1); \
            XRebindKeysym(DISP, (KeySym) ks, \
              list, 1, (_Xconst ubyte *) str, 1); \
            XRebindKeysym(DISP, (KeySym) ks, \
              list + 1, 1, (_Xconst ubyte *) str, 1); \
            XRebindKeysym(DISP, (KeySym) ks, \
              list, 2, (_Xconst ubyte *) str, 1);

          rebindkey(XK_Help, "?");
          rebindkey(XK_Cancel, "q");
          rebindkey(XK_Redo, "A");
          rebindkey(XK_Home, "^");
          rebindkey(XK_Left, "l");
          rebindkey(XK_Up, "u");
          rebindkey(XK_Right, "r");
          rebindkey(XK_Down, "d");
          rebindkey(XK_End, "g");
#ifdef  XK_Page_Up
          rebindkey(XK_Page_Up, "b");
          rebindkey(XK_Page_Down, "f");
#endif
#ifdef      XK_KP_Left
          rebindkey(XK_KP_Home, "^");
          rebindkey(XK_KP_Left, "l");
          rebindkey(XK_KP_Up, "u");
          rebindkey(XK_KP_Right, "r");
          rebindkey(XK_KP_Down, "d");
          rebindkey(XK_KP_Prior, "b");
          rebindkey(XK_KP_Next, "f");
          rebindkey(XK_KP_Delete, "\177");
#ifdef  XK_KP_Page_Up
          rebindkey(XK_KP_Page_Up, "b");
          rebindkey(XK_KP_Page_Down, "f");
#endif  /* XK_KP_Page_Up */
#endif      /* XK_KP_Left */
}
#undef      rebindkey

      image = XCreateImage(DISP, our_visual, 1, XYBitmap, 0,
                       (char *) NULL, 0, 0, BMBITS, 0);
      image->bitmap_unit = BMBITS;
#ifdef      WORDS_BIGENDIAN
      image->bitmap_bit_order = MSBFirst;
#else
      image->bitmap_bit_order = LSBFirst;
#endif
      {
          short endian = MSBFirst << 8 | LSBFirst;
          image->byte_order = *((char *) &endian);
      }

      /*
       *    Step 6:  Assign colors and GCs.
       *           Because of the latter, this has to go after Step 5.
       */

#ifndef TOOLKIT
#define     XtWindow(win)     win
#endif

#define     MakeGC(fcn, fg, bg)     (values.function = fcn, \
        values.foreground=fg, values.background=bg, \
        XCreateGC(DISP, XtWindow(top_level), \
          GCFunction | GCForeground | GCBackground, &values))

#ifdef GRID
       if (!resource.grid1_color) grid1_Pixel = fore_Pixel;
       if (!resource.grid2_color) grid2_Pixel = grid1_Pixel;
       if (!resource.grid3_color) grid3_Pixel = grid1_Pixel;
#endif /* GRID */


#ifdef      GREY
      if (resource._gamma == 0.0)
          resource._gamma = 1.0;

#endif

      copy = resource.copy;

      init_colors();

      {
          XGCValues     values;

          highGC = ruleGC;
          if (hl_Pixel != fore_Pixel
#ifdef GREY
            || (!copy && our_visual != DefaultVisualOfScreen(SCRN))
#endif
            )
#ifdef GREY
            copyGC =
#endif
            highGC = MakeGC(GXcopy, hl_Pixel, back_Pixel);

#ifdef GRID
              grid1GC = MakeGC(GXcopy, grid1_Pixel, fore_Pixel);
            grid2GC = MakeGC(GXcopy, grid2_Pixel, fore_Pixel);
            grid3GC = MakeGC(GXcopy, grid3_Pixel, fore_Pixel);
#endif /* GRID */

      }

#ifndef     VMS
      ready_cursor = XCreateFontCursor(DISP, XC_cross);
      redraw_cursor = XCreateFontCursor(DISP, XC_watch);
#else
      DECWCursorFont = XLoadFont(DISP, "DECW$CURSOR");
      XSetFont(DISP, foreGC, DECWCursorFont);
      redraw_cursor = XCreateGlyphCursor(DISP, DECWCursorFont, DECWCursorFont,
            decw$c_wait_cursor, decw$c_wait_cursor + 1,
            &resource.fore_color, &resource.back_color);
      MagnifyPixmap = XCreateBitmapFromData(DISP, RootWindowOfScreen(SCRN),
            mag_glass_bits, mag_glass_width, mag_glass_height);
      ready_cursor = XCreatePixmapCursor(DISP, MagnifyPixmap, MagnifyPixmap,
            &resource.back_color, &resource.fore_color,
            mag_glass_x_hot, mag_glass_y_hot);
#endif      /* VMS */

      {
          XColor bg_Color, cr_Color;

          bg_Color.pixel = back_Pixel;
          XQueryColor(DISP, our_colormap, &bg_Color);
          cr_Color.pixel = cr_Pixel;
          XQueryColor(DISP, our_colormap, &cr_Color);
          XRecolorCursor(DISP, ready_cursor, &cr_Color, &bg_Color);
          XRecolorCursor(DISP, redraw_cursor, &cr_Color, &bg_Color);
      }

      do_pages();
      return 0;   /* do_pages() returns if DBG_BATCH is specified */
}

Generated by  Doxygen 1.6.0   Back to index