/*
 * jdmain.c  ver 1.0 May 11, 1992

 Panning, shrinking, video card, mode forcing, brightness works

 Improvements:
  - on panning check ahead to see if multiple keypress and if mult of one
	  type then do a multiple jump
  - do GIF decoding ??
  - write an interface using wildcard file selection to select files
  - allow video mode selection after load first of image?
  - get my name into this #@%% thing somewhere (email addr too)
  - limiting on pallet scaling to stop after one color rails?
  - beep upon completion of picture?

 still have to figure out Cirrus card
 can't force ahead b type
 what happens if you force a mode and don't know size??? default to 1024 - dangerous ??

 May 30, 1992
  - patch ATI driver (hardcoded a changable value that was changed)
  - fixed VESA modes
  - added ATI hi_color (32,768 color) mode as card #17 - actually sets ati_hi_color flag
  - note FORCED VIDEO MODE defaults to 1024 size (now removed) --- big mistake if its a lower resolution
  - ATI hi_color x size is patched to work with range checking and allow proper page selection
  - added Tseng 4000 ramdac hi-color modes
  - added multiple keypress detection to move multiple steps per draw
  - insert mode into the user list of modes sorts by y size (assume x also increases with x)
  - the user can fill the mode list with 10 of 320 * 200 if he wants - ie no checking
  - took out jquant1 in ?.h file since why bother using it?
  - fixed some erratic functioning in forcevga (doing something funny crossing segment boundary ??? - seems fixed

Problems
 - ATI hi_color fix doubles X size therefore paning selection is wrong!!! - check for other problems too
 - panning disabled for ATI hi_color
 - testing mode add card autodetect, user select and return 1 or 0
 - there must be 1 item in the user list of modes or else a up/down arrow will lock machine
	  - solve by only running program if there is a list and make detection a seperate program
 - file_mask has a 0x0a (LF) at the end of it which is needed for the fgets() - problem???
 - tried to add gif decompression but had problems between djmaster, cjmaster ie gif jpeg is write only - ah I don't know yet

To add
 - cut storage requirements in half for 256 color modes by packing bytes
 - ability to add custom modes (give mode #, resolution after selected card type
 - add ATI test for 1 meg??? or just let the user set and test modes ??
 - make video detection/testing a seperate program and save into a file
 - panning disabled for hi_color

 *
 *  first generation JPG viewer
 *
 * This file contains a trivial test user interface for the JPEG decompressor.
 * It should work on any system with Unix- or MS-DOS-style command lines.
 *
 * Two different command line styles are permitted, depending on the
 * compile-time switch TWO_FILE_COMMANDLINE:
 *	djpeg [options]  inputfile outputfile
 *	djpeg [options]  [inputfile]
 * In the second style, output is always to standard output, which you'd
 * normally redirect to a file or pipe to some other program.  Input is
 * either from a named file or from standard input (typically redirected).
 * The second style is convenient on Unix but is unhelpful on systems that
 * don't support pipes.  Also, you MUST use the first style if your system
 * doesn't do binary I/O to stdin/stdout.
 */

#include "jinclude.h"
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h>		/* to declare exit() */
#endif
#ifdef NEED_SIGNAL_CATCHER
#include <signal.h>		/* to declare signal() */
#endif


#ifdef DONT_USE_B_MODE		/* define mode parameters for fopen() */
#define READ_BINARY	"r"
#define WRITE_BINARY	"w"
#else
#define READ_BINARY	"rb"
#define WRITE_BINARY	"wb"
#endif

#ifndef EXIT_FAILURE		/* define exit() codes if not provided */
#define EXIT_FAILURE  1
#endif


#include "jversion.h"		/* for version message */
#include <conio.h>
#include "jvsetup.h"			/* setup things for all viewer files */


/*
 * PD version of getopt(3).
 */

#include "egetopt.c"


/*extern unsigned _stklen = 8192; was not a solution for erratic problems */


/*
 * This list defines the known output image formats
 * (not all of which need be supported by a given version).
 * You can change the default output format by defining DEFAULT_FMT;
 * indeed, you had better do so if you undefine PPM_SUPPORTED.
 */

typedef enum {
	FMT_GIF,		/* GIF format */
	FMT_PPM,		/* PPM/PGM (PBMPLUS formats) */
	FMT_RLE,		/* RLE format */
	FMT_TARGA,		/* Targa format */
	FMT_TIFF		/* TIFF format */
} IMAGE_FORMATS;



#ifndef DEFAULT_FMT		/* so can override from CFLAGS in Makefile */
#define DEFAULT_FMT	FMT_PPM
#endif


/* These static variables are needed by the error routines. */
/*static jmp_buf setjmp_buffer;	/* for return to caller */
static external_methods_ptr emethods; /* needed for access to message_parm */

/* buffer pointer for panning if needed/possible */

static big_sarray_ptr raw_pic_ptr;		/* pointer to virt. pic. for panning, 3 used for hi_color mode; 1 otherwise */


int get_key(void);


/*
 * Signal catcher to ensure that temporary files are removed before aborting.
 * NB: for Amiga Manx C this is actually a global routine named _abort();
 * see -Dsignal_catcher=_abort in CFLAGS.  Talk about bogus...
 */

#ifdef NEED_SIGNAL_CATCHER

GLOBAL void
signal_catcher (int signum)
{
  emethods->trace_level = 0;	/* turn off trace output */
  (*emethods->free_all) ();	/* clean up memory allocation & temp files */
  exit(EXIT_FAILURE);
}

#endif




LOCAL void
usage (char * progname)
/* complain about bad command line */
{
  fprintf(stderr, "usage: %s ", progname);
  fprintf(stderr, "[-P] [-S #] [-b] [-h] [-D] [-d] [-m mem]");
  fprintf(stderr, " inputfile\n");
  fprintf(stderr, " 1) Ahead           2) ATI VGA         3) Chips & Tech\n");
  fprintf(stderr, " 4) Everex          5) Oak Tech.       6) Genoa\n");
  fprintf(stderr, " 7) NCR             8) Paradise        9) Trident\n");
  fprintf(stderr, "10) Trident 8900   11) Tseng, Orchid, Genoa, Willow\n");
  fprintf(stderr, "12) Tseng 4000     13) Video 7        14) Cirrus\n");
  fprintf(stderr, "15) Compaq         16) Vesa           17) ATI - hi color\n");
  fprintf(stderr, "18) Tseng - hi color\n");
  exit(EXIT_FAILURE);
}



LOCAL void
help_usage ()
{
	fprintf(stderr, "-P   to disable panning (saves memory)\n");
/*	fprintf(stderr, "-M   to force the video mode requires the BIOS mode # in dec.\n");*/
/*	fprintf(stderr, "-V # force a certain video card\n");*/
	fprintf(stderr, "-b   use cross block smoothing\n");
	fprintf(stderr, "-g   use grayscale output\n");
	fprintf(stderr, "-D   supress dithering in quantization\n");
	fprintf(stderr, "-m # set maximum memory available\n");
	fprintf(stderr, "-d   enable debugging\n");
	fprintf(stderr, "-S # shrink image to 1/# size\n");
	fprintf(stderr, "Viewing funcions:\n");
	fprintf(stderr, "<Pg Up>  brighten         <Pg Dn>  darken\n");
	fprintf(stderr, "<up arrow>  scroll up     <dwn arrow>  scroll down\n");
	fprintf(stderr, "<up, down arrow> multiple hits will move pic. by larger amounts\n");
	fprintf(stderr, "<+> zoom                  <-> shrink image\n");
	fprintf(stderr, "ESC exit the program\n");
	exit(EXIT_FAILURE);
}


/* This routine is used for any and all trace, debug, or error printouts
 * from the JPEG code.  The parameter is a printf format string; up to 8
 * integer data values for the format string have been stored in the
 * message_parm[] field of the external_methods struct.
 */

METHODDEF void
trace_message (const char *msgtext)
{
  fprintf(stderr, msgtext,
	  emethods->message_parm[0], emethods->message_parm[1],
	  emethods->message_parm[2], emethods->message_parm[3],
	  emethods->message_parm[4], emethods->message_parm[5],
	  emethods->message_parm[6], emethods->message_parm[7]);
  fprintf(stderr, "\n");	/* there is no \n in the format string! */
}

/*
 * The error_exit() routine should not return to its caller.  The default
 * routine calls exit(), but here we assume that we want to return to
 * read_JPEG_data, which has set up a setjmp context for the purpose.
 * You should make sure that the free_all method is called, either within
 * error_exit or after the return to the outer-level routine.
 */

METHODDEF void
error_exit (const char *msgtext)
{
  txtmode();
  trace_message(msgtext);	/* report the error message */
  (*emethods->free_all) ();	/* clean up memory allocation & temp files */
/*	fclose(cinfo.input_file);*/
  exit(EXIT_FAILURE);
/*  longjmp(setjmp_buffer, 1);	/* return control to outer routine */
}



/*
 * To accept the image data from decompression, you must define four routines
 * output_init, put_color_map, put_pixel_rows, and output_term.
 *
 * You must understand the distinction between full color output mode
 * (N independent color components) and colormapped output mode (a single
 * output component representing an index into a color map).  You should use
 * colormapped mode to write to a colormapped display screen or output file.
 * Colormapped mode is also useful for reducing grayscale output to a small
 * number of gray levels: when using the 1-pass quantizer on grayscale data,
 * the colormap entries will be evenly spaced from 0 to MAX_JSAMPLE, so you
 * can regard the indexes are directly representing gray levels at reduced
 * precision.  In any other case, you should not depend on the colormap
 * entries having any particular order.
 * To get colormapped output, set cinfo->quantize_colors to TRUE and set
 * cinfo->desired_number_of_colors to the maximum number of entries in the
 * colormap.  This can be done either in your main routine or in
 * d_ui_method_selection.  For grayscale quantization, also set
 * cinfo->two_pass_quantize to FALSE to ensure the 1-pass quantizer is used
 * (presently this is the default, but it may not be so in the future).
 *
 * The output file writing modules (jwrppm.c, jwrgif.c, jwrtarga.c, etc) may be
 * useful examples of what these routines should actually do, although each of
 * them is encrusted with a lot of specialized code for its own file format.
 */


METHODDEF void
output_init (decompress_info_ptr cinfo)
/* This routine should do any setup required */
{
int i;
		/* find the right video mode */
		/* first if image is > all modes default to largest mode */
		for (i = 0; i < number_modes_in_list; i++)
			if (ok_mode[i].card_ID >= 0) video_mode_used = i;

		for (i = number_modes_in_list - 1; i >=0; i--)
		/* fudge the size calculation by 5 pixels for those pics that are slightly bigger than the mode */
			if (video_cards[ok_mode[i].card_ID].vid_mode[ok_mode[i].which_mode].x_size >= cinfo->image_width - 5
					&& video_cards[ok_mode[i].card_ID].vid_mode[ok_mode[i].which_mode].y_size >= cinfo->image_height - 5
					&&	ok_mode[i].card_ID >= 0)
				video_mode_used = i;

/* check if hi_color is chosen - if so do setup */
if (ok_mode[video_mode_used].card_ID > 16 ){
	enable_pan = 0;
	hi_color = 1;
	cinfo -> quantize_colors = FALSE;
	cinfo -> two_pass_quantize = FALSE;
	}

/* now check if panning would be usefull - only iff card is detected and size know */

	if (video_cards[ok_mode[video_mode_used].card_ID].vid_mode[ok_mode[video_mode_used].which_mode].y_size >= cinfo->image_height
		 && video_cards[ok_mode[video_mode_used].card_ID].vid_mode[ok_mode[video_mode_used].which_mode].x_size >= cinfo->image_width)
		 enable_pan = 0;

	if (enable_pan){
			raw_pic_ptr = (*cinfo->emethods->request_big_sarray)
				(cinfo->image_width, cinfo->image_height, 1L);
		printf("Panning enabled.\n");
		}
	else
		printf("Panning not enabled.\n");

	printf("size of image = %li, %li\n", cinfo->image_width, cinfo->image_height);


/* have user select the video mode from the list of working modes */


	if (hi_color == 0)
		printf("quantizing down to 256 colors\n");
	else
		printf("Hi_color mode being used\r\n");

  /* This routine can initialize for output based on the data passed in cinfo.
	* Useful fields include:
	*	image_width, image_height	Pretty obvious, I hope.
	*	data_precision			bits per pixel value; typically 8.
	*	out_color_space			output colorspace previously requested
	*	color_out_comps			number of color components in same
	*	final_out_comps			number of components actually output
	* final_out_comps is 1 if quantize_colors is true, else it is equal to
	* color_out_comps.
	*
	* If you have requested color quantization, the colormap is NOT yet set.
	* You may wish to defer output initialization until put_color_map is called.
	*/
}



/*
 * This routine is called if and only if you have set cinfo->quantize_colors
 * to TRUE.  It is given the selected colormap and can complete any required
 * initialization.  This call will occur after output_init and before any
 * calls to put_pixel_rows.  Note that the colormap pointer is also placed
 * in a cinfo field, whence it can be used by put_pixel_rows or output_term.
 * num_colors will be less than or equal to desired_number_of_colors.
 *
 * The colormap data is supplied as a 2-D array of JSAMPLEs, indexed as
 *		JSAMPLE colormap[component][indexvalue]
 * where component runs from 0 to cinfo->color_out_comps-1, and indexvalue
 * runs from 0 to num_colors-1.  Note that this is actually an array of
 * pointers to arrays rather than a true 2D array, since C does not support
 * variable-size multidimensional arrays.
 * JSAMPLE is typically typedef'd as "unsigned char".  If you want your code
 * to be as portable as the JPEG code proper, you should always access JSAMPLE
 * values with the GETJSAMPLE() macro, which will do the right thing if the
 * machine has only signed chars.
 */

METHODDEF void
put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
/* Write the color map */
{
int i;


forcevga(ok_mode[video_mode_used].card_ID);
svgamode(video_cards[ok_mode[video_mode_used].card_ID].vid_mode[ok_mode[video_mode_used].which_mode].mode_number,
			video_cards[ok_mode[video_mode_used].card_ID].vid_mode[ok_mode[video_mode_used].which_mode].x_size);

if (hi_color == 0)
	if (colormap != NULL && num_colors <= 256 && cinfo->out_color_space == CS_RGB){
/* Normal case: RGB color map */
		for (i=0; i < num_colors; i++){
			palbuf[i][0] = (GETJSAMPLE(colormap[0][i]) >> 2);
			palbuf[i][1] = (GETJSAMPLE(colormap[1][i]) >> 2);
			palbuf[i][2] = (GETJSAMPLE(colormap[2][i]) >> 2);
			}
		setmany(palbuf,0,256);
		}
	else printf("color map pointer = NULL or > 256 colors or color space != RGB.\n");
}


/*
 * This function is called repeatedly, with a few more rows of pixels supplied
 * on each call.  With the current JPEG code, some multiple of 8 rows will be
 * passed on each call except the last, but it is extremely bad form to depend
 * on this.  You CAN assume num_rows > 0.
 * The data is supplied in top-to-bottom row order (the standard order within
 * a JPEG file).  If you cannot readily use the data in that order, you'll
 * need an intermediate array to hold the image.  See jwrrle.c for an example
 * of outputting data in bottom-to-top order.
 *
 * The data is supplied as a 3-D array of JSAMPLEs, indexed as
 *		JSAMPLE pixel_data[component][row][column]
 * where component runs from 0 to cinfo->final_out_comps-1, row runs from 0 to
 * num_rows-1, and column runs from 0 to cinfo->image_width-1 (column 0 is
 * left edge of image).  Note that this is actually an array of pointers to
 * pointers to arrays rather than a true 3D array, since C does not support
 * variable-size multidimensional arrays.
 * JSAMPLE is typically typedef'd as "unsigned char".  If you want your code
 * to be as portable as the JPEG code proper, you should always access JSAMPLE
 * values with the GETJSAMPLE() macro, which will do the right thing if the
 * machine has only signed chars.
 *
 * If quantize_colors is true, then there is only one component, and its values
 * are indexes into the previously supplied colormap.  Otherwise the values
 * are actual data in your selected output colorspace.
 */


METHODDEF void
put_pixel_rows (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE pixel_data)
/* Write some rows of output data */
{
/*register FILE * outfile = cinfo->output_file;*/
register JSAMPROW ptr0, ptr1, ptr2, output_row;
static  long col;
static	int ati_color_low, ati_color_hi;					/* ati 15 bit color word for hi_color */
static  int row, gr_col;
static  unsigned int gr_row = 0;  /* warning 1 shot system here -----------*/
static  unsigned int read_row = 0;			/* more 1 shot */
static	int col_cntr=1, row_cntr=1;				/* warning more 1 shot variables */

/* note ------ row is not going from 0 to max because it goes in sections ------*/

if (hi_color){
	for (row = 0; row < num_rows; row++) {
		ptr0 = pixel_data[0][row];
		ptr1 = pixel_data[1][row];
		ptr2 = pixel_data[2][row];
		if (enable_pan){
			output_row = *((*cinfo->emethods->access_big_sarray)
				(raw_pic_ptr, read_row, TRUE));
			}
		for (gr_col = col = 0; col < cinfo->image_width; col++){
			ati_color_low = ((GETJSAMPLE(*ptr2) & 0x1f) + (GETJSAMPLE(*ptr1) << 5)) & 0xff;
			ati_color_hi = (((GETJSAMPLE(*ptr1) >> 3) & 0x03) + (GETJSAMPLE(*ptr0) << 2)) & 0x7f;
			if (enable_pan)
				*output_row++ = ati_color_low + (ati_color_hi << 8);

/* removed x range checking */
			if (gr_row < maxy)
				if (row_cntr == 1 && col_cntr == 1)
					if (tseng4){
						point_hi(gr_col++, gr_row, ati_color_low + (ati_color_hi << 8));
						}
					else{
						point(gr_col++, gr_row, ati_color_low);
						point(gr_col++, gr_row, ati_color_hi);
						}
			ptr0++;
			ptr1++;
			ptr2++;
			col_cntr = (col_cntr % shrink) + 1;
			}
		if (row_cntr == 1) gr_row++;
		row_cntr = (row_cntr % shrink) + 1;
		}
	}
else
	for (row = 0; row < num_rows; row++) {
		ptr0 = pixel_data[0][row];
		if (enable_pan) output_row = *((*cinfo->emethods->access_big_sarray)
								(raw_pic_ptr, read_row++, TRUE));
		for (gr_col = col = 0; col < cinfo->image_width; col++){
			ati_color_low = GETJSAMPLE(*ptr0);
			if (enable_pan) *output_row++ = ati_color_low;
			if (gr_row < maxy && gr_col < maxx)
				if (row_cntr == 1 && col_cntr == 1)
					point(gr_col++, gr_row, ati_color_low);
			ptr0++;
			col_cntr = (col_cntr % shrink) + 1;
			}
		if (row_cntr == 1) gr_row++;
		row_cntr = (row_cntr % shrink) + 1;
		}
}



METHODDEF void
output_term (decompress_info_ptr cinfo)
/* Finish up at the end of the output */
{
JSAMPROW output_row;		/* pseudo struct to hold 1 line for drawing */

static int
		exit,					/* exit flag ie on escape */
		x_pos, y_pos,		/*	current upper left x, y position */
		x_max, y_max,		/* maximum video x, y max (counting from 1 */
		x_size, y_size,	/* picture size */
		x, y,					/* drawing counters */
		old_color_scale,	/* old one to see if its changed */
		color_scale,		/* factor to scale pallete up or down */
		row, col,
		y_delta, x_delta,
		redraw,				/* cmd to force redraw */
		step,					/* step size (pixels) for pan - first used as a keypress counter*/
		cmd,
		cmd2;


static unsigned char	pallet[256][3];	/* duplicate pallete */

x_size = cinfo->image_width;
y_size = cinfo->image_height;
x_max = video_cards[card_id].vid_mode[video_mode_used].x_size;
y_max = video_cards[card_id].vid_mode[video_mode_used].y_size;
x_pos = y_pos = exit = color_scale = redraw = 0;

while(exit == 0){
	old_color_scale = color_scale;
	y_delta = x_delta = redraw = 0;
	step = 1;								/* assume 1 keypress only */
	cmd = get_key();
	while (kbhit()){
		cmd2 = get_key();						/* count the number of times a key is hit (for panning) */
		if (cmd2 == cmd) step++;
		if (cmd2 == escape){						/* if ESC then exit regardless */
			step = 1;
			cmd = escape;
			}
		}

	step *= 15;			/* step 15 pixels per keypress */
	switch (cmd){
		case minus:			shrink++;
								if (shrink > 4) shrink = 4;	/* limit to 1/4 size */
								else redraw = 1;
								break;
		case plus:			shrink--;
								if (shrink < 1) shrink = 1;	/* limit to 1:1 since can't zoom */
								else redraw = 1;
								break;
		case page_up:		color_scale += 2;			/* turn up intensity */
								break;
		case page_down:	color_scale--;				/* turn down intensity */
								break;
		case arrow_up:		if (y_pos - step >= 0)
									y_delta = -step;
								else
									y_delta = -y_pos;		/* move all the way to top */
								break;
		case arrow_down:	if (y_pos + step + y_max <= y_size)
									y_delta = step;
								else
									y_delta = y_max - (y_size - y_pos);
								break;
		case arrow_left:	if (x_pos - step >= 0)
									x_delta = -step;
								else
									x_delta = -x_pos;
								break;
		case arrow_right:	if (x_pos + step + x_max <= x_size)
									x_delta = step;
								else
									x_delta = x_max - (x_size - x_pos);
								break;
		case escape:		exit = 1;
								break;
/*		default:				exit = 1;*/
		}
	if (exit == 0){
		if (color_scale != old_color_scale){
/*			color_scale %= 200;	/* mod to 100 - ie it will wrap !! */
			if (color_scale > 100) color_scale = 100;
			if (color_scale < -40) color_scale = -40;
			for (x=0; x < 256; x++){
				pallet[x][0] = palbuf[x][0] * (1 + (float)color_scale / 40);
				pallet[x][1] = palbuf[x][1] * (1 + (float)color_scale / 40);
				pallet[x][2] =	palbuf[x][2] * (1 + (float)color_scale / 40);
				}
			setmany(pallet, 0, 256);
			}

		if (enable_pan && ( x_delta != 0 || y_delta != 0 || redraw)){
			x_pos += x_delta;
			y_pos += y_delta;
			if (shrink == 1){
				for (y=0; y < y_max; y++){
					output_row = *((*cinfo->emethods->access_big_sarray)
							(raw_pic_ptr, y+y_pos, FALSE));
					for (x = 0; x < x_size; x++)
						if (x > x_pos)
							point(x-x_pos, y, *output_row++);
						else
							*output_row++;
					}
				}
			else{		/* now do a shrunk picture */
				for (y=0; y < y_max; y++){
					row = y * shrink + y_pos;
					if (row < y_size){
						output_row = *((*cinfo->emethods->access_big_sarray)
								(raw_pic_ptr, row, FALSE));
						for (x = 0; x < x_size; x++){
							col = x * shrink + x_pos;
							if (x > x_pos && col < x_size)
								point(x-x_pos, y, *output_row++);
							else{
								*output_row++;
								if (x <= x_pos) point(x-x_pos, y, 0);		/* black ??  if shrouded */
								}
							*output_row++;		/* since its shrunk at least 1 times */
							if (shrink >= 3) *output_row++;
							if (shrink == 4) *output_row++;
							}
						}
					}
				}
			}
		}
  }
  /* This termination routine may not need to do anything. */
  /* Note that the JPEG code will only call it during successful exit; */
  /* if you want it called during error exit, you gotta do that yourself. */
}




/*
 * This routine gets control after the JPEG file header has been read;
 * at this point the image size and colorspace are known.
 * The routine must determine what output routines are to be used, and make
 * any decompression parameter changes that are desirable.  For example,
 * if it is found that the JPEG file is grayscale, you might want to do
 * things differently than if it is color.  You can also delay setting
 * quantize_colors and associated options until this point.
 *
 * j_d_defaults initializes out_color_space to CS_RGB.  If you want grayscale
 * output you should set out_color_space to CS_GRAYSCALE.  Note that you can
 * force grayscale output from a color JPEG file (though not vice versa).
 */

METHODDEF void
d_ui_method_selection (decompress_info_ptr cinfo)
{
  /* if grayscale input, force grayscale output; */
  /* else leave the output colorspace as set by main routine. */
  if (cinfo->jpeg_color_space == CS_GRAYSCALE)
	 cinfo->out_color_space = CS_GRAYSCALE;

  /* select output routines */
  cinfo->methods->output_init = output_init;
  cinfo->methods->put_color_map = put_color_map;
  cinfo->methods->put_pixel_rows = put_pixel_rows;
  cinfo->methods->output_term = output_term;

  /* select output file format */
  /* not need for showing pictures */
}




int get_key(void)
{
int cmd;
if ( (cmd = getch()) == 0) cmd = getch();
return cmd;
}




/*
 * The main program.
 */

GLOBAL int
main (int argc, char **argv)
{
	struct decompress_info_struct cinfo;
	struct decompress_methods_struct dc_methods;
	struct external_methods_struct e_methods;
	int c;
	int sel_card;			/* sort of general purpose int - used to load video mode list */
	char file_mask[20];	/* mask for file selection */
	FILE *config_file;
	int text_width,		/* text mode width - not used yet */
		text_mode,			/* text mode # - not used */
		sort_mode;			/* sort type for file names - not used yet */


  /* Initialize the system-dependent method pointers. */
  cinfo.methods = &dc_methods;
  cinfo.emethods = &e_methods;
  jselerror(&e_methods);	/* error/trace message routines */
  jselmemmgr(&e_methods);	/* memory allocation routines */
  dc_methods.d_ui_method_selection = d_ui_method_selection;

	enable_pan = 1;	/* default to on */
	shrink = 1;			/* default to normal size */
	hi_color = 0;		/* assume no hi_color */


	for (c = 0; c < number_modes_in_list; c++)
		ok_mode[c].card_ID = -1;						/* signal as unused to ensure undefined modes are not used */

  /* Now OK to enable signal catcher. */
#ifdef NEED_SIGNAL_CATCHER
  emethods = &e_methods;
  signal(SIGINT, signal_catcher);
#ifdef SIGTERM			/* not all systems have SIGTERM */
  signal(SIGTERM, signal_catcher);
#endif
#endif

  /* Set up default JPEG parameters. */
  j_d_defaults(&cinfo, TRUE);
/*  requested_fmt = DEFAULT_FMT;	/* set default output file format */

/* for viewer force quantization and 256 colors */
	cinfo.desired_number_of_colors = 256;
	cinfo.quantize_colors = TRUE;
	cinfo.two_pass_quantize = TRUE;

  /* Scan command line options, adjust parameters */

  while ((c = egetopt(argc, argv, "S:PbgDm:dh")) != EOF)
	 switch (c) {
	 case 'S':				/* allow a shrink to 1/# of the image */
		if (optarg == NULL){
			help_usage();
			usage(argv[0]);
			}
		if (sscanf(optarg, "%d", &shrink) < 1);
		else shrink = 2;
		if (shrink > 4 || shrink < 1){
			help_usage();
			usage(argv[0]);
			}
		break;
	 case 'P':			/* disable panning */
		enable_pan = 0;
		break;
	 case 'b':			/* Enable cross-block smoothing. */
		cinfo.do_block_smoothing = TRUE;
		break;
	 case 'g':			/* Force grayscale output. */
		cinfo.out_color_space = CS_GRAYSCALE;
		break;
	 case 'h':
		help_usage();
		break;
	 case 'D':			/* Suppress dithering in color quantization. */
		cinfo.use_dithering = FALSE;
		break;
	 case 'm':			/* Maximum memory in Kb (or Mb with 'm'). */
		{ long lval;
	char ch = 'x';

	if (optarg == NULL)
	  usage(argv[0]);
	if (sscanf(optarg, "%ld%c", &lval, &ch) < 1)
	  usage(argv[0]);
	if (ch == 'm' || ch == 'M')
	  lval *= 1000L;
	e_methods.max_memory_to_use = lval * 1000L;
		}
		break;
	 case 'd':			/* Debugging. */
		e_methods.trace_level++;
		break;
	 case '?':
	 default:
		usage(argv[0]);
		break;
	 }

  /* If -d appeared, print version identification */
  if (e_methods.trace_level > 0)
	 fprintf(stderr, "Erics DVPEG viewer, thanks to:\n");
	 fprintf(stderr, "Independent JPEG Group, version %s\n%s\n",
		 JVERSION, JCOPYRIGHT);

 /* Select the input and output files */
 /* not TWO_FILE_COMMANDLINE -- use Unix style */

  cinfo.input_file = stdin;	/* default input file */
  cinfo.output_file = stdout;	/* always the output file */

	if (optind != argc-1) {
		fprintf(stderr, "%s: need one input file\n", argv[0]);
		usage(argv[0]);
		}

	if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
		fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
		exit(EXIT_FAILURE);
		}

/*
  if ((c = getc(cinfo.input_file)) == EOF)
	 ERREXIT(cinfo.emethods, "Empty input file");

  switch (c) {
#ifdef GIF_SUPPORTED
  case 'G':
	 jselrgif(&cinfo);
	 break;
#endif
#ifdef PPM_SUPPORTED
  case 'P':
	 jselrppm(&cinfo);
	 break;
#endif
  default:			/* assume default is jpeg type picture */

#ifdef JFIF_SUPPORTED
  jselrjfif(&cinfo);
#else
  You shoulda defined JFIF_SUPPORTED.   /* deliberate syntax error */
#endif
/*	 break;
  }

if (ungetc(c, cinfo.input_file) == EOF)
	 ERREXIT(cinfo.emethods, "ungetc failed");
  */


/* does the dvpeg.cfg file exist? */
config_file = fopen("dvpeg.cfg", "rb");
if (config_file != NULL){						/* load the file mode descriptions */
	text_width = getw(config_file);
	text_mode = getw(config_file);
	sort_mode = getw(config_file);
	fgets(file_mask, 20, config_file);
	c = 0;
	while((sel_card = getw(config_file)) != -1){
		if (c >= number_modes_in_list){
			printf("Error in dvpeg.cfg file.  Please delete it and run vidseteup.\r\n");
			exit(-1);
			}
		ok_mode[c].card_ID = sel_card;
		ok_mode[c++].which_mode = getw(config_file);
		}
	fclose(config_file);
	}
else{					/* no? then autodetect */
	printf("The configuration file does not exist.\r\n");
	printf("Please run vidsetup.exe to select the video modes that you wish to use.\r\n");
	exit(-1);
	}


/*
 * OK, here is the main function that actually causes everything to happen.
 * We assume here that the JPEG filename is supplied by the caller of this
 * routine, and that all decompression parameters can be default values.
 * The routine returns 1 if successful, 0 if not.
 */

  cinfo.output_file = NULL;	/* if no actual output file involved */

  /* Here we supply our own error handler; compare to use of standard error
	* handler in the previous write_JPEG_file example.
	*/
  emethods = &e_methods;	/* save struct addr for possible access */
  e_methods.error_exit = error_exit; /* supply error-exit routine */
  e_methods.trace_message = trace_message; /* supply trace-message routine */


  /* If the decompressor requires full-image buffers (for two-pass color
	* quantization or a noninterleaved JPEG file), it will create temporary
	* files for anything that doesn't fit within the maximum-memory setting.
	* You can change the default maximum-memory setting by changing
	* e_methods.max_memory_to_use after jselmemmgr returns.
	* On some systems you may also need to set up a signal handler to
	* ensure that temporary files are deleted if the program is interrupted.
	* (This is most important if you are on MS-DOS and use the jmemdos.c
	* memory manager back end; it will try to grab extended memory for
	* temp files, and that space will NOT be freed automatically.)
	* See jcmain.c or jdmain.c for an example signal handler.
	*/



  /* At this point you can modify the default parameters set by j_d_defaults
	* as needed; for example, you can request color quantization or force
	* grayscale output.  See jdmain.c for examples of what you might change.
	*/


	jpeg_decompress(&cinfo);
	txtmode();

  /* Nothin' else to do, except close files. */
  /* Here we assume only the input file need be closed. */
  fclose(cinfo.input_file);

  return 1;			/* indicate success */
}
