/*
 This is bmv.h, part of the source code for

 BMV version 1.1  copyright by Jan Kybic, 19th January 1995
 
 Jan Kybic, Prosecka 681, Praha 9, Czech Republic, <kybic@earn.cvut.cz>

 BMV is a very simple viewer of images in the pbm(5)-raw format
     and front end for GhostScript		
     based on Svgalib library for Linux

 BMV is distributed under GNU GPL (General Public License),
   you can obtain a copy from many FTP sites if you are interested for details
*/

/* First we define the version string
   Please change it, if you modify the source */

#define VER "1.1"


/* Then we define the symbols you might want to change */

/* MAXIMBITS is esentially the maximum allowed reduction/compression ratio
   The size of the temporary buffers is proportional to it
   I do not think there is a point to increase it further
   STRMAXIMBITS is a MAXIMBITS enclosed in double quotes */

#define MAXIMBITS 9
#define STRMAXIMBITS "9"

/* DVGAMODE stands for default video mode. See <vga.h> */
#define DVGAMODE G640x480x16

/* if COLOUR is defined as nonzero colour support is enabled */
/* :-) but it is slower */

#define COLOUR 0

/* INIMAG is the initial magnification */
#define INIMAG  (-3)

/* PAPER<number> and INK<number> stands for paper and ink color respectively
   The <number> means number of bits per pixel. Currently paper is white and
   ink is dark blue, or black if we have just mono mode */

#define PAPERFOUR 15
#define INKFOUR 1
#define PAPEREIGHT 15
#define INKEIGHT 1
#define INKONE 0
#define PAPERONE 1

/* STEP, MAXSTEP, MINSTEP control the default, max and min values for a single
   step invoked by h,j,k,l keys. If you reduce or increase them from the
   viewer the value is multiplied or divided by two. Thus it works best if
   STEP,MAXSTEP,MINSTEP are powers of two */

#define STEP 256
#define MAXSTEP 1024
#define MINSTEP 32

/* GSRES is a default switch passed to GS to set resolution and GSRESLEN
   is the maximum length of this switch (also when entered from command line)
*/

#define GSRESLEN 10
#define GSRES "-r240x216"

/* GSNAME is a name to invoke GS, it should be absolute, but it can point to
   a script, provided it passes all the arguments to GS */

#ifndef GSNAME
#define GSNAME "/usr/bin/gs"
#endif

/* GSPAPER is passed to GS to set paper size. Do not set it to "" ! */

#define GSPAPER_PREFIX "-sPAPERSIZE="
#define GSPAPER "a4"

/* GSTIMEOUT is a time in seconds to wait for GhostScript. You should choose
   according to the speed of your machine and the complexity of your PS files.
*/

#define GSTIMEOUT (60)

/* INBUFSIZ is a buffer size for reading from GhostScript output pipe.
   Too small buffer slows the process down, too big wastes space. */

#define INBUFSIZ 4096

/* PBMFILEMIN is a minimum size for PBM files. If a file is shorter than this
   BMV does not bother to check if it really is a PBM file. */
#define PBMFILEMIN 1000

/* PIXTRESH is given in percents and it determines, how much of the pixel
   should be filled to be considered black. It aplies when scaling images
   down. Higher value results in lighter fonts and vice versa */

#define PIXTRESH 30


/* Now we include the header files we shall need */
#include <vga.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <fcntl.h>


/* And here come the external variable definitions */

/* vgaon=1 if we are in graphics mode; videomode is a number of this mode */
extern int vgaon,vidmode ;

/* file is a PBM file we are displaying, psfile is a PostScript file,
   gsin, gsout are descriptors for the pipes to send/get data to/from GS */
extern FILE *file ;
extern FILE *psfile ;

/* set buffer size */
#if BUFSIZ <= 16384
#define	BMV_BUFSIZ	16384
#endif

/* offset is a position in a PBM file where the actual graphics data begin */
extern long offset ;

/* screenw, screenh give dimensions of the screen in pixels and
   imagew, imageh give the dimensions of the image in pixels */

extern int screenw,screenh,imagew,imageh ;

/* pixthresh is given in percents */

extern int pixthresh ;

/* pXm magic number */

#define	PBMRAW_MAGIC	'4'
#define	PGMRAW_MAGIC	'5'
#define	PPMRAW_MAGIC	'6'

extern char image_magic ;

/* color components: number and maximum value */

extern int image_num_components, image_max_component ;

/* pixels in each image byte */

extern int image_pixels_per_byte;

/* number of components in a pixmap */

#define	NUM_PIX_COMPONENTS	3

/* when mag>0 resp. mag<0 it means enlarge resp. reduce image mag-times */

extern int mag ;

/* usedsc, psview, testpbm should have values 1 or 0
   They respectively mean that document conformes to DSC, that we are
   displaying PostScript (not PBM directly) and finaly testpbm=1
   when we just want to test if PBM is correct. If it is too short, we
   ask GS for some more data and do not exit with error */

extern int usedsc, psview, testpbm ;

/* pagedesc is a struct describing number of pages in a PS DSC conforming
   file (numpages) and the positions in file of the beginnings of code for
   each page. Page 'n' goes from pagepos[n-1] to pagepos[n]. If the PS
   file is not DSC, we pretend it has just one page */

typedef struct { int numpages ;
                 long *pagepos ; } pagedesc ;
extern pagedesc pages ;

/* gsres stores a string to be passed to GS to set resolution. Its initial
   value is GSRES and max length GSRESLEN */

extern const char *gsres ;
 
/* gsname is the full path to the ghostscript executable */

extern const char *gsname ;

/* gsincdir is the ghostscript -I font directory search option */

extern const char *gsincdir ;

/* gspaper is the ghostscript paper size */

extern const char *gspaper ;

/* gstimeout is the number of seconds we let ghostscript run */

extern int gstimeout ;

/* tempname is a name of a temporary PBM file, where we store the image */

extern char tempname[] ;

/* the pid_t type variables contain pids of the child processes,
   or -1 if the process is not running or 0 if I am that process.
   kbdpid process monitors the keyboard state and each time a key is pressed
   it notifies the parent to interrupt displaying.
   gspid runs GhostScript via exec.
   gswrite sends data to GS, while parent takes care about its output. */

extern pid_t kbdpid,gspid,gswrite ;

/* *buff are buffers used by showwindow */

extern unsigned char *outbuff,*readbuff,*inbuff ;
extern unsigned int *gray_inbuff, *pix_inbuff ;
extern unsigned char *filebuff ;

/* Keep track if we are leaving so we don't close things twice */

extern int leaving ;


/* And here we have global function prototypes */

/* printerr prints message on stdout, preceeds it by !BMV and adds newline */

extern void printerr(const char *e) ;

/* leave prints all the strings it is passed via printerr (the last argument
   should be NULL), makes his best to do the cleaning and makes exit(stat).
   It frees buffers, switches to text mode, removes temporary file, kills
   children and so on */

extern void leave(int stat,...) ;

/* display file displays a PBM file filename */
extern void displayfile(const char *filename) ;

/* bkgdisplayfile starts the keyboard monitoring process and calls displayfile
*/

extern void bkgdisplayfile(const char *filename) ;

/* opendisplay switches screen to graphics and sets all the globals */

extern void opendisplay(void) ;

/* closedisplay switches back to text mode */

extern void closedisplay(void) ;

/* openpbm opens PBM file, validates it and interprets the header */

extern void openpbm(const char *filename) ;

/* showwindow shows a portion of an open PBM file on the screen */

extern void showwindow(int mag,int windowx,int windowy) ;

/* openpsfile opens PS file and scans it for DSC comments */

extern void openpsfile(const char *filename) ;

extern void closepsfile(void) ;

/* displaypsfile does all the work with displaying PS file */

extern void displaypsfile(const char *filename) ;

/* makegsdisplay sends the source for page number num to GS and waits until
   it is finished */

extern void makegsdisplay(int num) ;


/* and some signal handlers - empty does nothing, sigint is called
   when child receives SIGINT */

extern void emptyhandler(int sig) ;
extern void siginthandler(int sig) ;

/* and finally some obvious macros */

#define min(a,b) ((a)<(b) ? a : b)
#define max(a,b) ((a)>(b) ? a : b)

#ifdef M_UNIX
#define	SIGREADY	SIGPOLL
#define	SIGDONE		SIGALRM
extern int mouse_pixel_x, mouse_pixel_y;
int vgasco_getchar(void);
extern void vgasco_printf(const char *format, ...);
#define	printf		vgasco_printf
#define puts(str)	vgasco_printf("%s\n",(str))
#else
#define	SIGREADY	SIGUSR1
#define	SIGDONE		SIGUSR2
#endif

/* ************** end of bmv.h ***************** */
