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

Copyright (c) 1990-2004  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 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
	in xdvi.c.

\*========================================================================*/
 /* helbig changed this file to make it work on Mac OS X */
 /* it defined XOPEN_SOURCE,  which causes NSIG to be not defined,
    which breaks signal.h included by event.c */

/*
 *	Written by Eric C. Cooper, CMU
 */

#ifndef	XDVI_H
#define	XDVI_H

/********************************
 *	The C environment	*
 *******************************/

#ifdef __hpux
/* On HP-UX 10.10 B and 20.10, compiling with _XOPEN_SOURCE + ..._EXTENDED
 * leads to poll() not realizing that a file descriptor is writable in psgs.c.
 */
#define	_HPUX_SOURCE	1
#else
#undef _XOPEN_SOURCE		/* needed because of imake */
#define	_XOPEN_SOURCE_EXTENDED	1
#define	__EXTENSIONS__	1	/* needed to get struct timeval on SunOS 5.5 */
#define	_SVID_SOURCE	1	/* needed to get S_IFLNK in glibc */
#define	_BSD_SOURCE	1	/* needed to get F_SETOWN in glibc-2.1.3 */
#endif

#include "config.h"

/* Some O/S dependent kludges. */
#ifdef _AIX
#define _ALL_SOURCE 1
#endif

/* If xmkmf is broken and there's a symlink from /usr/include/X11 to the right
 * place, then there will be no -I... argument on the cc command line for the
 * X include files.  Since gcc version 3 and higher sets __STDC__ to 0 when
 * including system header files on some platforms, we may end up with
 * NeedFunctionPrototypes set to 0 when it should be 1.  So, let's force the
 * issue.
 */

#if __STDC__ && !defined(FUNCPROTO)
# define FUNCPROTO (-1)
#endif

#if STDC_HEADERS
# include <stddef.h>
# include <stdlib.h>
	/* the following works around the wchar_t problem */
# include <X11/X.h>
# if HAVE_X11_XOSDEFS_H
#  include <X11/Xosdefs.h>
# endif
# ifdef X_NOT_STDC_ENV
#  undef X_NOT_STDC_ENV
#  undef X_WCHAR
#  include <X11/Xlib.h>
#  define X_NOT_STDC_ENV
# endif
#endif

#include <X11/Xlib.h>	/* include Xfuncs.h, if available */
#include <X11/Xutil.h>	/* needed for XDestroyImage */
#include <X11/Xos.h>

#if	XlibSpecificationRelease >= 5
#include <X11/Xfuncs.h>
#endif

#undef	TOOLKIT

#if XAW || MOTIF

#define	TOOLKIT	1
#include <X11/Intrinsic.h>
#if (defined(VMS) && (XtSpecificationRelease <= 4)) || defined(lint)
# include <X11/IntrinsicP.h>
#endif
#if MOTIF
# include <Xm/Xm.h>
# ifndef MOTIF_TIMERS	/* see comment in events.c */
#  define MOTIF_TIMERS (XmVERSION >= 2)
# endif
#endif

#else /* not TOOLKIT */

#define	XtNumber(arr)	(sizeof(arr)/sizeof(arr[0]))
#define	XtWindow(win)	(win)
typedef	unsigned long	Pixel;
typedef	char		Boolean;
typedef	unsigned int	Dimension;
#undef	BUTTONS
#undef	EXTRA_APP_DEFAULTS

#endif /* not TOOLKIT */

#if EXTRA_APP_DEFAULTS && !SELFAUTO
#define	SELFAUTO 1
#endif

#if SELFAUTO && !defined(DEFAULT_CONFIG_PATH)
#define	DEFAULT_CONFIG_PATH	\
		".:$SELFAUTOLOC:$SELFAUTODIR:$SELFAUTOPARENT:$SELFAUTODIR/share/texmf/web2c:$SELFAUTOPARENT/share/texmf/web2c:$SELFAUTODIR/texmf/web2c:$SELFAUTOPARENT/texmf/web2c:$TETEXDIR:$TEXMF/web2c"
#endif

#undef CFGFILE				/* no cheating */

#if defined(DEFAULT_CONFIG_PATH)
#define	CFGFILE	1
#endif

typedef	char		Bool3;		/* Yes/No/Maybe */

#define	True	1
#define	False	0
#define	Maybe	2

#ifdef	VMS
#include <string.h>
#define	index	strchr
#define	rindex	strrchr
#define	bzero(a, b)	(void) memset ((void *) (a), 0, (size_t) (b))
#define bcopy(a, b, c)  (void) memmove ((void *) (b), (void *) (a), (size_t) (c))
#endif

#include <stdio.h>
#include <setjmp.h>

#if HAVE_UNISTD_H
#include <unistd.h>
#endif

#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# if HAVE_SYS_NDIR_H
#  include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
#  include <sys/dir.h>
# endif
# if HAVE_NDIR_H
#  include <ndir.h>
# endif
#endif

#ifndef	NeedFunctionPrototypes
#if	__STDC__
#define	NeedFunctionPrototypes	1
#else	/* STDC */
#define	NeedFunctionPrototypes	0
#endif	/* STDC */
#endif	/* NeedFunctionPrototypes */

#if	NeedFunctionPrototypes
#define	ARGS(x)	x
#else
#define	ARGS(x)	()
#endif

#ifndef KPATHSEA

/* These macros munge function declarations to make them work in both
   cases.  The P?H macros are used for declarations, the P?C for
   definitions.  See <ansidecl.h> from the GNU C library.  P1H(void)
   also works for definitions of routines which take no args.  */

#if NeedFunctionPrototypes	/* Don't use __STDC__ here (gcc + SunOS 4) */

#define	P1H(p1) (p1)
#define	P2H(p1, p2) (p1, p2)

#define	P1C(t1,n1)(t1 n1)
#define	P2C(t1,n1, t2,n2)(t1 n1, t2 n2)
#define	P3C(t1,n1, t2,n2, t3,n3)(t1 n1, t2 n2, t3 n3)
#define	P4C(t1,n1, t2,n2, t3,n3, t4,n4)(t1 n1, t2 n2, t3 n3, t4 n4)

#else /* not NeedFunctionPrototypes */

#define	P1H(p1) ()
#define	P2H(p1, p2) ()

#define	P1C(t1,n1) (n1) t1 n1;
#define	P2C(t1,n1, t2,n2) (n1,n2) t1 n1; t2 n2;
#define	P3C(t1,n1, t2,n2, t3,n3) (n1,n2,n3) t1 n1; t2 n2; t3 n3;
#define	P4C(t1,n1, t2,n2, t3,n3, t4,n4) (n1,n2,n3,n4) \
		t1 n1; t2 n2; t3 n3; t4 n4;

#endif /* not NeedFunctionPrototypes */

#endif /* not KPATHSEA */

#ifndef	NeedWidePrototypes
#define	NeedWidePrototypes	NeedFunctionPrototypes
#endif

#ifndef	NeedVarargsPrototypes
#define	NeedVarargsPrototypes	NeedFunctionPrototypes
#endif

#if NeedVarargsPrototypes
#define	VARGS(x)	x
#else
#define	VARGS(x)	()
#endif

#ifndef	_XFUNCPROTOBEGIN
#define	_XFUNCPROTOBEGIN
#define	_XFUNCPROTOEND
#endif

#ifndef	_Xconst
#if	__STDC__
#define	_Xconst	const
#else	/* STDC */
#define	_Xconst
#endif	/* STDC */
#endif	/* _Xconst */

#ifndef	VOLATILE
#if	__STDC__ || (defined(__stdc__) && defined(__convex__))
#define	VOLATILE	volatile
#else
#define	VOLATILE	/* nothing */
#endif
#endif

#ifndef	NORETURN
# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5)
#  define NORETURN	__attribute__((__noreturn__))
# else
#  define NORETURN	/* nothing */
# endif
#endif

#ifndef UNUSED
# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
#  define UNUSED	__attribute__((__unused__))
# else
#  define UNUSED	/* nothing */
# endif
#endif

#ifndef	OPEN_MODE
#ifndef	VMS
#define	OPEN_MODE	"r"
#else	/* VMS */
#define	OPEN_MODE	"r", "ctx=stm"
#endif	/* VMS */
#endif	/* OPEN_MODE */

#ifndef	VMS
#define	OPEN_MODE_ARGS	_Xconst char *
#else
#define	OPEN_MODE_ARGS	_Xconst char *, _Xconst char *
#endif

#define	Printf	(void) printf
#define	Puts	(void) puts
#define	Fprintf	(void) fprintf
#define	Sprintf	(void) sprintf
#define	Fseek	(void) fseek
#define	Fread	(void) fread
#define	Fputs	(void) fputs
#define	Putc	(void) putc
#define	Putchar	(void) putchar
#define	Fclose	(void) fclose
#define	Fflush	(void) fflush
#define	Strcat	(void) strcat
#define	Strcpy	(void) strcpy

/********************************
 *	 Types and data		*
 *******************************/

#ifndef	EXTERN
#define	EXTERN	extern
#define	INIT(x)
#endif

#define	MAXDIM		32767

typedef	unsigned char	ubyte;

#if	NeedWidePrototypes
typedef	unsigned int	wide_ubyte;
typedef	int		wide_bool;
#define	WIDENINT	(int)
#else
typedef	ubyte		wide_ubyte;
typedef	Boolean		wide_bool;
#define	WIDENINT
#endif

#if defined(MAKETEXPK) && !defined(MKTEXPK)
#define	MKTEXPK 1
#endif

/*
 *	pixel_conv is currently used only for converting absolute positions
 *	to pixel values; although normally it should be
 *		((int) ((x) / shrink_factor + (1 << 15) >> 16)),
 *	the rounding is achieved instead by moving the constant 1 << 15 to
 *	PAGE_OFFSET in dvi-draw.c.
 */
#define	pixel_conv(x)		((int) ((x) / shrink_factor >> 16))
#define	pixel_round(x)		((int) ROUNDUP(x, shrink_factor << 16))
#define	spell_conv0(n, f)	((long) (n * f))
#define	spell_conv(n)		spell_conv0(n, dimconv)

#define	BMUNIT			unsigned BMTYPE
#define	BMBITS			(8 * BMBYTES)

#define	ADD(a, b)	((BMUNIT *) (((char *) a) + b))
#define	SUB(a, b)	((BMUNIT *) (((char *) a) - b))

extern	BMUNIT	bit_masks[BMBITS + 1];

struct frame {
	struct framedata {
		long dvi_h, dvi_v, w, x, y, z;
		int pxl_v;
	} data;
	struct frame *next, *prev;
};

#ifndef	TEXXET
typedef	long	(*set_char_proc) ARGS((wide_ubyte));
#else
typedef	void	(*set_char_proc) ARGS((wide_ubyte, wide_ubyte));
#endif

typedef	void	(*home_proc) ARGS((wide_bool));

struct drawinf {	/* this information is saved when using virtual fonts */
	struct framedata data;
	struct font	*fontp;
	set_char_proc	set_char_p;
	int		tn_table_len;
	struct font	**tn_table;
	struct tn	*tn_head;
	ubyte		*pos, *end;
	struct font	*virtual;
#ifdef	TEXXET
	int		dir;
#endif
};

EXTERN	struct drawinf	currinf;

/* entries below with the characters 'dvi' in them are actually stored in
   scaled pixel units */

#define DVI_H   currinf.data.dvi_h
#define PXL_H   pixel_conv(currinf.data.dvi_h)
#define DVI_V   currinf.data.dvi_v
#define PXL_V   currinf.data.pxl_v
#define WW      currinf.data.w
#define XX      currinf.data.x
#define YY      currinf.data.y
#define ZZ      currinf.data.z
#define ROUNDUP(x,y) (((x)+(y)-1)/(y))

EXTERN	int	current_page;
EXTERN	int	total_pages;
EXTERN	int	pageno_correct	INIT(1);
EXTERN	long	magnification;
EXTERN	double	dimconv;
EXTERN	double	tpic_conv;
EXTERN	int	n_files_left	INIT(32767);	/* for LRU closing of fonts */
EXTERN	unsigned int	page_w, page_h;

#if	defined(GS_PATH) && !defined(PS_GS)
#define	PS_GS	1
#endif

#if	defined(PS_DPS) || defined(PS_NEWS) || defined(PS_GS)
#define	PS	1
#else
#define	PS	0
#endif

EXTERN	int	scanned_page;		/* last page prescanned */

#if PS
EXTERN	int	scanned_page_ps;	/* last page scanned for PS specials */
EXTERN	int	scanned_page_ps_bak;	/* save the above if PS is turned off */
#endif

#if COLOR
EXTERN	int	scanned_page_color;	/* last page scanned for color spcls */
#endif

EXTERN	int	scanned_page_reset;	/* number to reset the above to */

/*
 * The following is set when we're prescanning before opening up the windows,
 * and we hit a PostScript header file.  We can't start up gs until we get
 * a window to associate the process to, so we have to prescan twice.
 */
#if PS_GS
EXTERN	Boolean	gs_postpone_prescan	INIT(False);
#endif

/*
 * Per-page data in DVI file, indexed by page number - 1.
 * Offset is initialized in prepare_pages().
 * Page size is initialized while prescanning.
 */
struct per_page {
	long	offset;
	unsigned int	pw, ph;	/* page size */
	unsigned int	ww, wh;	/* window size */
};

EXTERN	struct per_page		*page_info;

/*
 * Set if the -paper option overrides papersize specials.
 */
EXTERN	Boolean			ignore_papersize_specials	INIT(False);

/*
 * Mechanism for reducing repeated warning about specials, lost characters, etc.
 */
EXTERN	Boolean	warn_spec_now;

/*
 * If we're in the middle of a PSFIG special.
 */
EXTERN	Boolean	psfig_begun	INIT(False);

/*
 * Page on which to draw box from forward source special searching.
 */
EXTERN	int	source_fwd_box_page	INIT(-1);	/* -1 means no box */

/*
 * Information on deferred source operation.  See do_pages() for meaning.
 */
EXTERN	_Xconst char	*source_forward_string	INIT(NULL);
EXTERN	int		source_reverse_x, source_reverse_y;
EXTERN	int		source_show_all;


/*
 * Bitmap structure for raster ops.
 */
struct bitmap {
	unsigned short	w, h;		/* width and height in pixels */
	short		bytes_wide;	/* scan-line width in bytes */
	char		*bits;		/* pointer to the bits */
};

/*
 * Per-character information.
 * There is one of these for each character in a font (raster fonts only).
 * All fields are filled in at font definition time,
 * except for the bitmap, which is "faulted in"
 * when the character is first referenced.
 */
struct glyph {
	long addr;		/* address of bitmap in font file */
	long dvi_adv;		/* DVI units to move reference point */
	short x, y;		/* x and y offset in pixels */
	struct bitmap bitmap;	/* bitmap for character */
	short x2, y2;		/* x and y offset in pixels (shrunken bitmap) */
#if GREY
# if COLOR
	struct fgrec *fg;	/* fgrec for which these pixmaps are valid */
# endif
	XImage *image2;
	char *pixmap2;
	char *pixmap2_t;
#endif /* GREY */
	struct bitmap bitmap2;	/* shrunken bitmap for character */
};

/*
 * Per-character information for virtual fonts
 */
struct macro {
	ubyte	*pos;		/* address of first byte of macro */
	ubyte	*end;		/* address of last+1 byte */
	long	dvi_adv;	/* DVI units to move reference point */
	Boolean	free_me;	/* if free(pos) should be called when */
				/* freeing space */
};

/*
 * The layout of a font information block.
 * There is one of these for every loaded font or magnification thereof.
 * Duplicates are eliminated:  this is necessary because of possible recursion
 * in virtual fonts.
 *
 * Also note the strange units.  The design size is in 1/2^20 point
 * units (also called micro-points), and the individual character widths
 * are in the TFM file in 1/2^20 ems units, i.e., relative to the design size.
 *
 * We then change the sizes to SPELL units (unshrunk pixel / 2^16).
 */

#define	NOMAGSTP (-29999)

typedef	void (*read_char_proc) ARGS((struct font *, wide_ubyte));

struct font {
	struct font *next;		/* link to next font info block */
	char *fontname;			/* name of font */
	float fsize;			/* size information (dots per inch) */
	int magstepval;			/* magstep number * two, or NOMAGSTP */
	FILE *file;			/* open font file or NULL */
	char *filename;			/* name of font file */
	long checksum;			/* checksum */
	unsigned short timestamp;	/* for LRU management of fonts */
	ubyte flags;			/* flags byte (see values below) */
	ubyte maxchar;			/* largest character code */
	double dimconv;			/* size conversion factor */
	set_char_proc set_char_p;	/* proc used to set char */
		/* these fields are used by (loaded) raster fonts */
	read_char_proc read_char;	/* function to read bitmap */
	struct glyph *glyph;
		/* these fields are used by (loaded) virtual fonts */
	struct font **vf_table;		/* list of fonts used by this vf */
	struct tn *vf_chain;		/* ditto, if TeXnumber >= VFTABLELEN */
	struct font *first_font;	/* first font defined */
	struct macro *macro;
		/* I suppose the above could be put into a union, but we */
		/* wouldn't save all that much space. */
};

#define	FONT_IN_USE	1	/* used for housekeeping */
#define	FONT_LOADED	2	/* if font file has been read */
#define	FONT_VIRTUAL	4	/* if font is virtual */

#define	TNTABLELEN	30	/* length of TeXnumber array (dvi file) */
#define	VFTABLELEN	5	/* length of TeXnumber array (virtual fonts) */

struct tn {
	struct tn *next;		/* link to next TeXnumber info block */
	int TeXnumber;			/* font number (in DVI file) */
	struct font *fontp;		/* pointer to the rest of the info */
};

EXTERN	struct font	*tn_table[TNTABLELEN];
EXTERN	struct font	*font_head	INIT(NULL);
EXTERN	struct tn	*tn_head	INIT(NULL);
EXTERN	ubyte		maxchar;
EXTERN	unsigned short	current_timestamp INIT(0);

/*
 *	Command line flags.
 */

extern	struct _resource {
#if TOOLKIT && CFGFILE
	_Xconst char	*progname;
#endif
#if TOOLKIT
	int		shrinkfactor;
	_Xconst char	*main_translations;
	_Xconst char	*wheel_translations;
	int		dvips_hang;
	int		dvips_fail_hang;
#endif
	int		wheel_unit;
	int		_density;
#ifdef	GREY
	float		_gamma;
#endif
	int		_pixels_per_inch;
	_Xconst	char	*sidemargin;
	_Xconst	char	*topmargin;
	_Xconst	char	*xoffset;
	_Xconst	char	*yoffset;
	_Xconst	char	*paper;
	_Xconst	char	*_alt_font;
#ifdef MKTEXPK
	Boolean		makepk;
#endif
	_Xconst	char	*mfmode;
	_Xconst char	*editor;
	_Xconst char	*src_pos;
	Boolean		src_fork;
	Boolean		_list_fonts;
	Boolean		reverse;
	Boolean		_warn_spec;
	Boolean		_hush_chars;
	Boolean		_hush_chk;
	Boolean		safer;
#if defined(VMS) || !defined(TOOLKIT)
	_Xconst	char	*fore_color;
	_Xconst	char	*back_color;
#endif
	Pixel		_fore_Pixel;
	Pixel		_back_Pixel;
#ifdef TOOLKIT
	Pixel		_brdr_Pixel;
	Pixel		_hl_Pixel;
	Pixel		_cr_Pixel;
#endif
	_Xconst	char	*icon_geometry;
	Boolean		keep_flag;
	Boolean		copy;
	Boolean		thorough;
#if PS
	/* default is to use DPS, then NEWS, then GhostScript;
	 * we will figure out later on which one we will use */
	Boolean		_postscript;
	Boolean		allow_shell;
#ifdef	PS_DPS
	Boolean		useDPS;
#endif
#ifdef	PS_NEWS
	Boolean		useNeWS;
#endif
#ifdef	PS_GS
	Boolean		useGS;
	Boolean		gs_safer;
	Boolean		gs_alpha;
	_Xconst	char	*gs_path;
	_Xconst	char	*gs_palette;
#endif
#endif	/* PS */
	Boolean		prescan;
	_Xconst	char	*debug_arg;
	Boolean		version_flag;
#if BUTTONS
	Boolean		expert;
	_Xconst char	*button_translations;
	int		shrinkbutton[9];
	Dimension	btn_side_spacing;
	Dimension	btn_top_spacing;
	Dimension	btn_between_spacing;
	Dimension	btn_between_extra;
	Dimension	btn_border_width;
#endif
	_Xconst	char	*mg_arg[5];
#if COLOR
	Boolean		_use_color;
#endif
#ifdef	GREY
	Boolean		_use_grey;
	Bool3		install;
#endif
#if TOOLKIT
	_Xconst char	*dvips_path;
#endif
} resource;

/* As a convenience, we define the field names without leading underscores
 * to point to the field of the above record.  Here are the global ones;
 * the local ones are defined in each module.  */

#define	density		resource._density
#define	pixels_per_inch	resource._pixels_per_inch
#define	alt_font	resource._alt_font
#define	list_fonts	resource._list_fonts
#define	warn_spec	resource._warn_spec
#define	hush_chars	resource._hush_chars
#define	hush_chk	resource._hush_chk
#if COLOR
#define	use_color	resource._use_color
#endif
#ifdef  GREY
#define	use_grey	resource._use_grey
#endif

#ifndef TOOLKIT
EXTERN	Pixel		brdr_Pixel;
#endif

#if GREY
EXTERN	Pixel		plane_masks[4];
#endif

#if GREY || COLOR
EXTERN	XColor		color_data[2];
#define	fore_color_data		color_data[0]
#define	back_color_data		color_data[1]
#endif

#if COLOR

struct rgb {
	unsigned short	r, g, b;
};

struct pagecolor {
	struct rgb	bg;
	unsigned int	stacksize;
	_Xconst struct rgb *colorstack;
};

/* Information on background color and initial color stack for each page.  */
EXTERN	struct pagecolor	*page_colors	INIT(NULL);

/* The initial color stack is gotten from the pagecolor record for a page.  */
EXTERN	_Xconst struct rgb	*color_bottom;
EXTERN	unsigned int		color_bot_size;	/* number of entries */

/* Additions to the runtime color stack on a given page are stored in a linked
   list.  "struct colorframe" is defined in special.c.  */
EXTERN	struct colorframe	*rcs_top;

/* Color states.  */
EXTERN	struct rgb	fg_initial;	/* Initial fg (from command line) */
EXTERN	struct rgb	bg_initial;	/* Initial bg */

/*
 * For each (foreground, background) color pair, we keep information (depending
 * on the color model).  It is organized as a linked list of linked lists,
 * with background color more significant.
 */

struct bgrec {
	struct bgrec	*next;
	struct rgb	color;
	struct fgrec	*fg_head;
	Boolean		pixel_good;	/* if the pixel entry is valid */
	Pixel		pixel;
};

struct fgrec {
	struct fgrec	*next;
	struct rgb	color;
	Boolean		pixel_good;	/* if the pixel entry is valid */
	Pixel		pixel;
#if GREY
	Boolean		palette_good;	/* if the palette entry is valid */
	Pixel		palette[16];	/* non-TrueColor only */
#endif
};

EXTERN	struct bgrec	*bg_head	INIT(NULL);	/* head of list */
EXTERN	struct bgrec	*bg_current	INIT(NULL);	/* current bg value */
EXTERN	struct fgrec	*fg_current;			/* current fg value */
EXTERN	struct fgrec	*fg_active	INIT(NULL);	/* where the GCs are */

/* List of allocated colors (to be deallocated upon document change) */
EXTERN	Pixel		*color_list;			/* list of colors */
EXTERN	unsigned int	color_list_len	INIT(0);	/* current len of list*/
EXTERN	unsigned int	color_list_max	INIT(0);	/* allocated size */

/* Whether the color situation has been warned about.  */
EXTERN	Boolean		color_warned	INIT(False);

/* Cursor color (for XRecolorCursor).  */
extern	XColor		cr_Color;

#endif /* COLOR */

extern	struct	mg_size_rec {
	int		w;
	int		h;
}
	mg_size[5];

EXTERN	int		debug		INIT(0);

#define	DBG_BITMAP	1
#define	DBG_DVI		2
#define	DBG_PK		4
#define	DBG_BATCH	8
#define	DBG_EVENT	16
#define	DBG_OPEN	32
#define	DBG_PS		64
#define	DBG_CLIENT	128
#define	DBG_ALL		(~DBG_BATCH)

EXTERN	int		offset_x, offset_y;
EXTERN	unsigned int	unshrunk_paper_w, unshrunk_paper_h;
EXTERN	unsigned int	unshrunk_page_w, unshrunk_page_h;

EXTERN	char		*dvi_name	INIT(NULL);	/* dvi file name */
EXTERN	FILE		*dvi_file;		/* user's file */
EXTERN	time_t		dvi_time;		/* last modification time */
EXTERN	ino_t		dvi_inode;		/* used for source specials */
EXTERN	unsigned char	*dvi_property;		/* for setting in window */
EXTERN	size_t		dvi_property_length;
#if TOOLKIT
EXTERN	Boolean		titles_are_stale INIT(True);
						/* replace icon/window titles */
#endif
EXTERN	_Xconst char	*prog;
EXTERN	int		bak_shrink;		/* last shrink factor != 1 */
EXTERN	Dimension	window_w, window_h;
EXTERN	XImage		*image;
EXTERN	int		backing_store;
EXTERN	int		home_x, home_y;

EXTERN	Display		*DISP;
EXTERN	Screen		*SCRN;
#if TOOLKIT
extern	XtActionsRec	Actions[];
extern	Cardinal	num_actions;
#endif
#if XAW
EXTERN	XtAccelerators	accels_cr, accels_cr_click;
#endif
#ifdef GREY
EXTERN	Visual		*our_visual;
EXTERN	unsigned int	our_depth;
EXTERN	Colormap	our_colormap;
#else
#define	our_depth	(unsigned int) DefaultDepthOfScreen(SCRN)
#define	our_visual	DefaultVisualOfScreen(SCRN)
#define	our_colormap	DefaultColormapOfScreen(SCRN)
#endif
EXTERN	GC		ruleGC;
EXTERN	GC		foreGC, highGC;
EXTERN	GC		foreGC2;
EXTERN	GC		copyGC;
EXTERN	Boolean		copy;

EXTERN	Cursor		redraw_cursor, ready_cursor, drag_cursor[3];

#if TOOLKIT
struct xdvi_action {
	struct xdvi_action *next;
	XtActionProc	proc;
	Cardinal	num_params;
	String		param;
};

struct wheel_acts {
	struct wheel_acts *next;
	Modifiers	mask;
	Modifiers	value;
	struct _LateBindings *late_bindings;
	unsigned int	button;
	struct xdvi_action *action;
};

EXTERN	struct wheel_acts	*wheel_actions;
#endif

#if MOTIF && BUTTONS
EXTERN	XtTranslations	wheel_trans_table	INIT(NULL);
#endif

#ifdef	GREY
EXTERN	Pixel		*pixeltbl;
EXTERN	Pixel		*pixeltbl_t;
#endif	/* GREY */

/*
 *	Flag values and masks for event_flags
 */

#define	EV_IDLE		(1<<0)	/* non-event */
#define	EV_CURSOR	(1<<1)	/* cursor needs to revert back to ready */
#define	EV_EXPOSE	(1<<2)	/* expose occurred somewhere */
#define	EV_MAG_MOVE	(1<<3)	/* magnifier moved */
#define	EV_MAG_GONE	(1<<4)	/* magnifier gone while being drawn */
#define	EV_ACK		(1<<5)	/* used internally */
#define	EV_SRC		(1<<6)	/* source special operation is pending */
#define	EV_NEWPAGE	(1<<7)	/* new page requested */
#define	EV_PS_TOGGLE	(1<<8)	/* PostScript toggled on or off */
#define	EV_NEWDOC	(1<<9)	/* new dvi file requested */
#define	EV_TERM		(1<<10)	/* quit */
#define	EV_MAXPLUS1	(1<<11)

#define	EV_GE_IDLE		(EV_MAXPLUS1 - EV_IDLE)
#define	EV_GT_IDLE		(EV_MAXPLUS1 - EV_CURSOR)
#define	EV_GE_CURSOR		(EV_MAXPLUS1 - EV_CURSOR)
#define	EV_GE_EXPOSE		(EV_MAXPLUS1 - EV_EXPOSE)
#define	EV_GE_MAG_MOVE		(EV_MAXPLUS1 - EV_MAG_MOVE)
#define	EV_GE_MAG_GONE		(EV_MAXPLUS1 - EV_MAG_GONE)
#define	EV_GE_ACK		(EV_MAXPLUS1 - EV_ACK)
#define	EV_GE_NEWPAGE		(EV_MAXPLUS1 - EV_NEWPAGE)
#define	EV_GE_PS_TOGGLE		(EV_MAXPLUS1 - EV_PS_TOGGLE)
#define	EV_GE_NEWDOC		(EV_MAXPLUS1 - EV_NEWDOC)
#define	EV_GE_TERM		(EV_MAXPLUS1 - EV_TERM)

#define	EV_NOWAIT		EV_GE_IDLE

EXTERN	unsigned int	ev_flags	INIT(EV_IDLE);
EXTERN	VOLATILE int	event_counter	INIT(0);
EXTERN	jmp_buf		canit_env;

struct	xchild {
	struct xchild	*next;		/* link to next in list */
	pid_t		pid;		/* pid of process, or 0 */
	Boolean		killable;	/* if can be killed with SIGKILL */
	void	(*proc) ARGS((int));	/* procedure to call */
};

struct	xio {
	struct xio	*next;		/* link to next in list */
	int		fd;		/* file descriptor */
	int		xio_events;	/* same as in struct pollfd (can't call
					   it events because poll.h on AIX
					   defines events to something else) */
#if HAVE_POLL
	struct pollfd	*pfd;
#endif
	void	(*read_proc) ARGS((void));	/* call to read */
	void	(*write_proc) ARGS((void));	/* call to write */
};

struct	xtimer {
	struct xtimer	*next;		/* link to next in chain */
	struct timeval	when;		/* when to call the routine */
	void	(*proc) ARGS((struct xtimer *));	/* procedure to call */
#if MOTIF_TIMERS
	XtTimerCallbackProc xt_proc;		/* additional data for Xm */
	XtPointer	closure;
#endif
};

#if MOTIF_TIMERS
# define TIMER_INIT(proc)	{NULL, {0, 0}, proc, NULL, NULL}
#else
# define TIMER_INIT(proc)	{NULL, {0, 0}, proc}
#endif

struct	WindowRec {
	Window		win;
	int		shrinkfactor;
	int		base_x, base_y;
	unsigned int	width, height;
	int	min_x, max_x, min_y, max_y;	/* for pending expose events */
};

extern	struct WindowRec mane, alt, currwin;
EXTERN	int		min_x, max_x, min_y, max_y;
EXTERN	Boolean		drawing_mag	INIT(False);

#define	shrink_factor	currwin.shrinkfactor

#if TOOLKIT
EXTERN	Widget		top_level	INIT(0);
EXTERN	Widget		vport_widget, draw_widget, clip_widget;
# if MOTIF
EXTERN	Widget		shrink_button[4];
EXTERN	Widget		x_bar, y_bar;	/* horizontal and vert. scroll bars */
# endif
# if BUTTONS
EXTERN	Widget		form_widget;
EXTERN	int		xtra_wid	INIT(0);
extern	_Xconst char	default_button_config[]; /* defined in events.c */
#  if XAW
EXTERN	Widget		panel_widget;
EXTERN	Cursor		panel_cursor	INIT(0);
#  endif
# endif
#else /* not TOOLKIT */
EXTERN	Window		top_level	INIT(0);

#define	BAR_WID		12	/* width of darkened area */
#define	BAR_THICK	15	/* gross amount removed */
#endif /* not TOOLKIT */

#if XAW
#define	WARN(t, s)	(void) warning_popup(s, "OK", NULL)
#define	WARN1(t, s, s1)	(void) warning_popup_long(s, "OK", NULL, s1)
#define	WARN2(t, s, s1, s2) (void) warning_popup_long(s, "OK", NULL, s1, s2)
#elif MOTIF
#define	WARN(t, s)	(void) warning_popup(s, t, NULL, NULL)
#define	WARN1(t, s, s1)	(void) warning_popup_long(s, t, NULL, NULL, s1)
#define	WARN2(t, s, s1, s2) (void) warning_popup_long(s, t, NULL, NULL, s1, s2)
#elif CC_K_AND_R
#define	WARN(t, s)	(void) fputs(s "\n", stderr)
#define	WARN1(t, s, s1)	(void) fprintf(stderr, s "\n", s1)
#else
#define	WARN(t, s)	(void) (fputs(s, stderr), putc('\n', stderr))
#define	WARN1(t, s, s1)	(void) (fprintf(stderr, s, s1), putc('\n', stderr))
#endif

/*
 * If a popup is popped up before the main window, then the main window is
 * likely to cover it.  So we have to postpone popping them up until after
 * realizing the main window.  It is not workable to pop them up immediately
 * and then raise them later, due to unpredictable window manager behavior.
 */

#if TOOLKIT
EXTERN	Boolean		postpone_popups		INIT(True);
EXTERN	size_t		n_init_popups		INIT(0);
EXTERN	Widget		*init_popups;
EXTERN	size_t		alloc_init_popups	INIT(0);
#endif

/*
 * Structure to use for status popups.
 */

#if TOOLKIT
struct status_popup {
	Widget	shell;
	Widget	label;
	int	expected_type;
	Boolean	popped;
	Boolean	spurious;
};
#endif

EXTERN	char	*ffline	INIT(NULL);	/* an array used by filefind to store */
					/* the file name being formed.  */
					/* It expands as needed. */
					/* Also used elsewhere.  */
EXTERN	size_t	ffline_len INIT(0);	/* current length of ffline[] */

/*
 *	Used by the geometry-scanning routines.
 *	It passes pointers to routines to be called at certain
 *	points in the dvi file, and other information.
 */

struct geom_info {
	void	(*geom_box)	ARGS((struct geom_info *,
				  long, long, long, long));
	void	(*geom_special)	ARGS((struct geom_info *, _Xconst char *));
	jmp_buf	done_env;
	void	*geom_data;
};

typedef	void	(*mouse_proc)	ARGS((XEvent *));
extern	void	null_mouse	ARGS((XEvent *));

EXTERN	mouse_proc	mouse_motion	INIT(null_mouse);
EXTERN	mouse_proc	mouse_release	INIT(null_mouse);

/* Used for source special lookup (forward search) and for window manager
   delete protocol (toolkit only).  */

#if XAW
EXTERN	Atom	atoms[5];
#elif MOTIF
EXTERN	Atom	atoms[4];
#else
EXTERN	Atom	atoms[3];
#endif

#define	ATOM_XDVI_WINDOWS	(atoms[0])
#define	ATOM_DVI_FILE		(atoms[1])
#define	ATOM_SRC_GOTO		(atoms[2])
#if TOOLKIT
#define	XA_WM_DELETE_WINDOW	(atoms[3])
#endif
#if XAW
#define	XA_WM_PROTOCOLS		(atoms[4])
#endif

#ifdef	SELFAUTO
EXTERN	_Xconst	char	*argv0;		/* argv[0] */
#endif

#if	PS

extern	struct psprocs	{
	void	(*toggle)	ARGS((void));
	void	(*destroy)	ARGS((void));
	void	(*interrupt)	ARGS((void));
	void	(*endpage)	ARGS((void));
	void	(*drawbegin)	ARGS((int, int, _Xconst char *));
	void	(*drawraw)	ARGS((_Xconst char *));
	void	(*drawfile)	ARGS((_Xconst char *, FILE *));
	void	(*drawend)	ARGS((_Xconst char *));
	void	(*beginheader)	ARGS((void));
	void	(*endheader)	ARGS((void));
	void	(*newdoc)	ARGS((void));
}	psp, no_ps_procs;

#endif	/* PS */

/********************************
 *	   Procedures		*
 *******************************/

_XFUNCPROTOBEGIN

extern	int	atopix ARGS((_Xconst char *, wide_bool));
#if TOOLKIT
extern	Bool	compile_action ARGS((_Xconst char *, struct xdvi_action **));
#endif
#if BUTTONS
extern	void	create_buttons ARGS((void));
#if XAW
extern	void	set_button_panel_height ARGS((XtArgVal));
#endif
#endif /* BUTTONS */
#if GREY
extern	void	init_plane_masks ARGS((void));
#endif
#if COLOR
extern	Pixel	alloc_color ARGS((_Xconst struct rgb *, Pixel));
extern	void	do_color_change ARGS((void));
#elif GREY
extern	void	init_pix ARGS((void));
#endif
extern	void	expose ARGS((struct WindowRec *, int, int,
		  unsigned int, unsigned int));
extern	void	home ARGS((wide_bool));
extern	void	reconfig ARGS((void));
#if TOOLKIT
extern	void	handle_resize ARGS((Widget, XtPointer, XEvent *, Boolean *));
extern	void	handle_expose ARGS((Widget, XtPointer, XEvent *, Boolean *));
extern	void	handle_property_change ARGS((Widget, XtPointer, XEvent *,
		  Boolean *));
#endif
#if XAW
extern	void	handle_messages ARGS((Widget, XtPointer, XEvent *, Boolean *));
#elif MOTIF
extern	void	handle_wm_delete ARGS((Widget, XtPointer, XtPointer));
#endif
extern	void	goto_page ARGS((int, home_proc));
#if MOTIF
extern	void	file_pulldown_callback ARGS((Widget, XtPointer, XtPointer));
extern	void	navigate_pulldown_callback ARGS((Widget, XtPointer, XtPointer));
extern	void	scale_pulldown_callback ARGS((Widget, XtPointer, XtPointer));
extern	void	set_shrink_factor ARGS((int));
extern	void	popdown_callback ARGS((Widget, XtPointer, XtPointer));
#endif
#if !TOOLKIT
extern	void	showmessage ARGS((_Xconst char *));
#endif
extern	void	set_chld ARGS((struct xchild *));
extern	void	clear_chld ARGS((struct xchild *));
extern	void	set_io ARGS((struct xio *));
extern	void	clear_io ARGS((struct xio *));
extern	void	set_timer ARGS((struct xtimer *, int));
extern	void	cancel_timer ARGS((struct xtimer *));
extern	unsigned int read_events ARGS((unsigned int));
extern	void	enable_intr ARGS((void));
extern	void	do_pages ARGS((void)) NORETURN;
#if XAW
extern	void	simple_popup ARGS((struct status_popup *, _Xconst char *,
		  XtCallbackProc));
extern	void	simple_popdown ARGS((struct status_popup *));
extern	void	do_popup ARGS((Widget));
extern	Widget	warning_popup ARGS((_Xconst char *, _Xconst char *,
		  XtCallbackProc));
extern	Widget	warning_popup_long VARGS((_Xconst char *, _Xconst char *,
		  XtCallbackProc, ...));
extern	void	Act_print ARGS((Widget, XEvent *, String *, Cardinal *));
extern	void	Act_open_dvi_file ARGS((Widget, XEvent *, String *,
		  Cardinal *));
#elif MOTIF
extern	void	simple_popup ARGS((struct status_popup *, _Xconst char *,
		  XtCallbackProc));
extern	void	simple_popdown ARGS((struct status_popup *));
extern	void	do_popup ARGS((Widget));
extern	Widget	warning_popup ARGS((_Xconst char *, int, _Xconst char *,
		  XtCallbackProc));
extern	Widget	warning_popup_long ARGS((_Xconst char *, int, _Xconst char *,
		  XtCallbackProc, ...));
extern	void	Act_print ARGS((Widget, XEvent *, String *, Cardinal *));
extern	void	Act_open_dvi_file ARGS((Widget, XEvent *, String *,
		  Cardinal *));
#endif
extern	void	reset_fonts ARGS((void));
#if COLOR
extern	void	reset_colors ARGS((void));
extern	void	full_reset_colors ARGS((void));
#endif
extern	void	realloc_font ARGS((struct font *, wide_ubyte));
extern	void	realloc_virtual_font ARGS((struct font *, wide_ubyte));
extern	Boolean	load_font ARGS((struct font *));
extern	struct font	*define_font ARGS((FILE *, wide_ubyte,
			struct font *, struct font **, unsigned int,
			struct tn **));
extern	void	init_page ARGS((void));
extern	Boolean	open_dvi_file ARGS((_Xconst char *));
extern	void	form_dvi_property ARGS((ino_t));
extern	void	init_dvi_file ARGS((void));
extern	void	set_dvi_property ARGS((void));
extern	Boolean	check_dvi_file ARGS((void));
extern	void	reload_dvi_file ARGS((void));
#ifndef	TEXXET
extern	long	set_char ARGS((wide_ubyte));
extern	long	load_n_set_char ARGS((wide_ubyte));
extern	long	set_vf_char ARGS((wide_ubyte));
#else
extern	void	set_char ARGS((wide_ubyte, wide_ubyte));
extern	void	load_n_set_char ARGS((wide_ubyte, wide_ubyte));
extern	void	set_vf_char ARGS((wide_ubyte, wide_ubyte));
#endif
extern	void	prescan ARGS((void));
extern	void	draw_page ARGS((void));
extern	void	source_reverse_search ARGS((int, int));
extern	void	source_special_show ARGS((wide_bool));
extern	void	source_forward_search ARGS((_Xconst char *));
#if	CFGFILE
extern	void	readconfig ARGS((void));
#endif
extern	void	init_font_open ARGS((void));
extern	FILE	*font_open ARGS((_Xconst char *, char **, double, int *, int,
			char **));
#if	PS
extern	void	ps_clear_cache ARGS((void));
extern	void	ps_destroy ARGS((void));
#endif
extern	void	init_prescan ARGS((void));
#if COLOR
extern	void	scan_color_eop ARGS((void));
extern	void	set_fg_color ARGS((_Xconst struct rgb *));
#endif
extern	void	applicationDoSpecial ARGS((char *));
extern	void	scan_special ARGS((char *));
extern	void	geom_do_special ARGS((struct geom_info *, char *, double));
extern	void	xdvi_exit ARGS((int)) NORETURN;
extern	void	oops VARGS((_Xconst char *, ...)) NORETURN;
#ifndef KPATHSEA
extern	void	*xmalloc ARGS((unsigned));
extern	void	*xrealloc ARGS((void *, unsigned));
extern	char	*xstrdup ARGS((_Xconst char *));
extern	char	*xmemdup ARGS((_Xconst char *, size_t));
#endif
#if TOOLKIT && !HAVE_STRERROR && !defined strerror
extern	char	*strerror ARGS((int));
#endif
extern	void	expandline ARGS((size_t));
extern	void	alloc_bitmap ARGS((struct bitmap *));
#ifndef KPATHSEA
extern	void	xputenv ARGS((_Xconst char *, _Xconst char *));
#endif
extern	int	memicmp ARGS((_Xconst char *, _Xconst char *, size_t));
extern	FILE	*xfopen ARGS((_Xconst char *, OPEN_MODE_ARGS));
#if XAW
extern	int	xopen ARGS((_Xconst char *, int));
#endif
extern	int	xpipe ARGS((int *));
extern	DIR	*xopendir ARGS((_Xconst char *));
extern	_Xconst	struct passwd *ff_getpw ARGS((_Xconst char **, _Xconst char *));
extern	unsigned long	num ARGS((FILE *, int));
extern	long	snum ARGS((FILE *, int));
extern	size_t	property_get_data ARGS((Window, Atom, unsigned char **,
		  int (*x_get_property) (Display *, Window, Atom, long,
		  long, Bool, Atom, Atom *, int *, unsigned long *,
		  unsigned long *, unsigned char **)));
#if PS
extern	int	xdvi_temp_fd ARGS((char **));
#endif
extern	void	prep_fd ARGS((int, wide_bool));
extern	void	read_PK_index ARGS((struct font *, wide_bool));
extern	void	read_GF_index ARGS((struct font *, wide_bool));
extern	void	read_VF_index ARGS((struct font *, wide_bool));

#if	PS
extern	void	ps_init_paths ARGS((void));
extern	void	drawbegin_none ARGS((int, int, _Xconst char *));
extern	void	draw_bbox ARGS((void));
extern	void	NullProc ARGS((void));
#ifdef	PS_DPS
extern	Boolean	initDPS ARGS((void));
#endif
#ifdef	PS_NEWS
extern	Boolean	initNeWS ARGS((void));
#endif
#ifdef	PS_GS
extern	Boolean	initGS ARGS((void));
extern	void	gs_resume_prescan ARGS((void));
#endif
#endif	/* PS */

_XFUNCPROTOEND

#define one(fp)		((unsigned char) getc(fp))
#define sone(fp)	((long) one(fp))
#define two(fp)		num (fp, 2)
#define stwo(fp)	snum(fp, 2)
#define four(fp)	num (fp, 4)
#define sfour(fp)	snum(fp, 4)

#endif	/* XDVI_H */