/*
 * jvmain.c

 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 ??
 const declaration on number_VGA_cards did not work !!!!

 *
 *  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 */


/*
 * PD version of getopt(3).
 */

#include "egetopt.c"


extern	unsigned char cirrus, everex, paradise, tseng, trident;
extern	unsigned char t8900, ativga, aheada, aheadb;
extern	unsigned char oaktech, video7, chipstech, tseng4, genoa;
extern	unsigned char ncr, compaq, vesa;
extern	unsigned char vga512, vga1024;
extern	int maxx, maxy;

#define number_VGA_cards 16		/* the number of VGA cards supported */

/*		definations for reading keyboard */

#define arrow_left 0x4b
#define arrow_right 0x4d
#define arrow_up 0x48
#define arrow_down 0x50
#define page_up 0x49
#define page_down 0x51
#define escape 27
#define home 71
#define end 79


/*
 * 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;


struct mode {
	int x_size;
	int y_size;
	unsigned char mode_number;};

struct video_card {
	char name[15];
	struct mode vid_mode[5];
	} video_cards[number_VGA_cards] =			/* 16 was number_VGA_cards but compiler blew */
	{ {"ahead", {{320, 200, 0x13}, {640, 400, 0x60}, {640, 480, 0x61}, {800, 600, 0x62}, {0000, 000, 0x00}}},
	  {"ati", {{320, 200, 0x13}, {640, 400, 0x5c}, {640, 480, 0x5d}, {800, 600, 0x5e}, {1024, 768, 0x62}}},
	  {"chips & tech", {{320, 200, 0x13}, {640, 400, 0x78}, {640, 480, 0x79}, {800, 600, 0x7b}, {0, 0, 0x0}}},
	  {"everex", {{320, 200, 0x13}, {640, 400, 0x14}, {512, 480, 0x15}, {640, 480, 0x30}, {800, 600, 0x31}}},
	  {"oak-tek", {{320, 200, 0x13}, {640, 480, 0x53}, {800, 600, 0x54}, {0, 0, 0x0}, {0, 0, 0x0}}},
	  {"genoa", {{320, 200, 0x13}, {640, 400, 0x7e}, {640, 480, 0x5c}, {720, 512, 0x5d}, {800, 600, 0x5e}}},
	  {"NCR", {{320, 200, 0x13}, {640, 400, 0x5e}, {640, 480, 0x5f}, {800, 600, 0x5c}, {0, 0, 0x0}}},
	  {"paradise", {{320, 200, 0x13}, {640, 400, 0x5e}, {640, 480, 0x5f}, {0, 0, 0x0}, {0, 0, 0x0}}},
	  {"trident", {{320, 200, 0x13}, {640, 400, 0x5c}, {640, 480, 0x5d}, {800, 600, 0x5e}, {0, 0, 0x00}}},
	  {"trident 8900", {{320, 200, 0x13}, {640, 400, 0x5c}, {640, 480, 0x5d}, {800, 600, 0x5e}, {1024, 768, 0x62}}},
	  {"tseng", {{320, 200, 0x13}, {640, 350, 0x2d}, {640, 480, 0x2e}, {800, 600, 0x30}, {1024, 768, 0x38}}},
	  {"tseng 4000", {{320, 200, 0x13}, {640, 400, 0x2f}, {640, 480, 0x2e}, {800, 600, 0x30}, {1024, 768, 0x38}}},
	  {"video 7", {{320, 200, 0x13}, {640, 400, 0x66}, {640, 480, 0x67}, {800, 600, 0x69}, {1024, 768, 0x6a}}},
	  {"cirrus", {{320, 200, 0x13}, {640, 480, 0x2e}, {0, 0, 0x0}, {0, 0, 0x0}, {0, 0, 0x0}}},
	  {"compaq", {{320, 200, 0x13}, {640, 480, 0x2e}, {0, 0, 0x0}, {0, 0, 0x0}, {0, 0, 0x0}}},
	  {"vesa", {{320, 200, 0x13}, {640, 480, 0x00}, {0, 0, 0x0}, {0, 0, 0x0}, {0, 0, 0x0}}}
	};


#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 channel;
/*static cur_output_row;			/* current output row */
static big_sarray_ptr raw_pic_ptr;		/* pointer to virt. pic. for panning */


/* these are for the graphics interface */

	unsigned char palbuf[256][3];
	int svga;
	unsigned int color;
	int video_mode_used;		/* mode number index for card */
	int card_id;				/* card id # - put as enum */
	int forced_video;			/* forced video mode flag */
	int forced_mode;			/* forced mode # ie 1 to 255 */
	int enable_pan;			/* enough memory for panning && needed?? */
	int shrink;					/* 1 = normal, 2 = 1/2, 3 = 1/3 ... */

/*
 * 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] [-V #] [-M #] [-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\n");
  exit(EXIT_FAILURE);
}


LOCAL void
vid_usage (char * progname)
/* complain about bad video selection */
{
  fprintf(stderr, "usage: %s ", progname);
  fprintf(stderr, "video cards:\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\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 cards\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, "<+> zoom                  <-> shrink image\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;

	if (forced_mode == 0){
		for (i = 0; i < 5; i++)		/* set default to maximum resolution */
			if (video_cards[card_id].vid_mode[i].mode_number != 0)
				video_mode_used = i;

		for (i = 4; i >= 0; i--)
			if (video_cards[card_id].vid_mode[i].x_size >= cinfo->image_width
					&& video_cards[card_id].vid_mode[i].y_size >= cinfo->image_height
					&&	video_cards[card_id].vid_mode[i].x_size != 0)
				video_mode_used = i;
		}

/* now check if panning would be usefull - only iff card is detected and size know */

	if (video_cards[card_id].vid_mode[video_mode_used].y_size > cinfo->image_height
		 && video_cards[card_id].vid_mode[video_mode_used].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("size of image = %li, %li\n", cinfo->image_width, cinfo->image_height);
	printf("quantizing down to 256 colors\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;

	for (i=0; i < num_colors; i++)
		if (colormap != NULL && num_colors <= 256){
			if (cinfo->out_color_space == CS_RGB) {
			  /* Normal case: RGB color map */
			  palbuf[i][0] = (GETJSAMPLE(colormap[0][i]) >> 2);
			  palbuf[i][1] = (GETJSAMPLE(colormap[1][i]) >> 2);
			  palbuf[i][2] = (GETJSAMPLE(colormap[2][i]) >> 2);
			}
		}
		else printf("color map pointer = NULL or > 256 colors.\n");

	if (forced_mode == 0)
		svgamode(video_cards[card_id].vid_mode[video_mode_used].mode_number,
				video_cards[card_id].vid_mode[video_mode_used].x_size);
	else
		svgamode(forced_mode, 1024);		/* assume x_size */

	setmany(palbuf,0,256);
}


/*
 * 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 */
{
  /* This example shows how you might write full-color RGB data (3 components)
	* to an output file in which the data is stored 3 bytes per pixel.
	*/
register FILE * outfile = cinfo->output_file;
register JSAMPROW ptr0, output_row;
static  long col;
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 ------*/

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++){
		if (enable_pan) *output_row++ = GETJSAMPLE(*ptr0);
		if (gr_row < maxy && gr_col < maxx)
			if (row_cntr == 1 && col_cntr == 1)
				point(gr_col++, gr_row, GETJSAMPLE(*ptr0));
		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 */
		cmd;


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;
	cmd = getch();
	if (cmd == 0) cmd = getch();
	switch (cmd){
		case 45:			shrink++;	/* - key */
								if (shrink > 4) shrink = 4;	/* limit to 1/4 size */
								else redraw = 1;
								break;
		case 43:			shrink--;		/* + key */
								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 - 15 >= 0)
									y_delta = -15;
								else
									y_delta = -y_pos;		/* move all the way to top */
								break;
		case arrow_down:	if (y_pos + 15 + y_max <= y_size)
									y_delta = 15;
								else
									y_delta = y_max - (y_size - y_pos);
								break;
		case arrow_left:	if (x_pos - 15 >= 0)
									x_delta = -15;
								else
									x_delta = -x_pos;
								break;
		case arrow_right:	if (x_pos + 15 + x_max <= x_size)
									x_delta = 15;
								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 */
  /* Note: jselwxxx routine may make additional parameter changes,
	* such as forcing color quantization if it's a colormapped format.
	*/
/*  switch (requested_fmt) {
#ifdef GIF_SUPPORTED
  case FMT_GIF:
	 jselwgif(cinfo);
	 break;
#endif
#ifdef PPM_SUPPORTED
  case FMT_PPM:
	 jselwppm(cinfo);
	 break;
#endif
#ifdef RLE_SUPPORTED
  case FMT_RLE:
	 jselwrle(cinfo);
	 break;
#endif
  default:
	 ERREXIT(cinfo->emethods, "Unsupported output file format");
	 break;
  }*/
}




/*
 * 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 v_mod;

  /* 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;

	forced_video = forced_mode = 0;			/* flag for forced video mode */
	enable_pan = 1;	/* default to on */
	shrink = 1;			/* default to normal size */

  /* 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:PV:M:bgDm: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 'V':			/* force a video card and _assume_ card exists */
		if (optarg == NULL)
			usage(argv[0]);
		if (sscanf(optarg, "%d", &v_mod) < 1)
			vid_usage(argv[0]);
		if (v_mod > number_VGA_cards || v_mod < 1)		/* check valid card # */
			vid_usage(argv[0]);
		forced_video = 1;
		card_id = v_mod - 1;
		break;
	 case 'M':			/* for a video mode */
		if (optarg == NULL)
			usage(argv[0]);
		if (sscanf(optarg, "%d", &v_mod) < 1)
			vid_usage(argv[0]);
		if (v_mod > 255 || v_mod < 1)		/* check valid card # */
			usage(argv[0]);
		forced_mode = v_mod;
		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);
		}


  /* Set up to read a JFIF or baseline-JPEG file. */
  /* A smarter UI would inspect the first few bytes of the input file */
  /* to determine its type. */
#ifdef JFIF_SUPPORTED
  jselrjfif(&cinfo);
#else
  You shoulda defined JFIF_SUPPORTED.   /* deliberate syntax error */
#endif

/*
 * 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.
	*/


/* now check the video display */

	if (forced_video){
		forcevga(card_id+1);
		svga = 1;
		}
	else{
		svga=whichvga();

		if (aheada == 1 || aheadb == 1) card_id = 0;
		if (ativga == 1) card_id = 1;
		if (chipstech == 1) card_id = 2;
		if (everex == 1) card_id = 3;
		if (oaktech == 1) card_id = 4;
		if (genoa == 1) card_id = 5;
		if (ncr == 1) card_id = 6;
		if (paradise == 1) card_id = 7;
		if (trident == 1)
		if (t8900 == 1) card_id = 9;
			else card_id = 8;
		if (tseng == 1)
			if (tseng4 == 1) card_id = 11;
			else card_id = 10;
		if (video7 == 1) card_id = 12;
		if (cirrus == 1) card_id = 13;
		if (compaq == 1) card_id = 14;
		if (vesa == 1) card_id = 15;
	}



  /* 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.
	*/


  /* Here we go! */
  if (svga)
		jpeg_decompress(&cinfo);
  else
		printf("The video card is not a recognized 256 color card.\n");

  /* That's it, son.  Nothin' else to do, except close files. */
  /* Here we assume only the input file need be closed. */
  fclose(cinfo.input_file);

  txtmode();
	printf("video card: %s\n",video_cards[card_id].name);

  return 1;			/* indicate success */
}
