/*  CONDITIONAL COMPILATION FLAGS  */
#define BRUCE   1
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#include "jinclude.h"
#include "hicolor.h"
#include "viewer.h"
#include "dither.h"
#include "pc.h"
#include "dir.h"
#include "gppconio.h"
#ifdef OLD_DRIVERS
#include "graphics.h"
#else
#include "grx.h"
#include "grdriver.h"
#endif

/*
 * Include file for declaring JPEG data structures.
 * This file also includes some system headers like <stdio.h>;
 * if you prefer, you can include "jconfig.h" and "jpegdata.h" instead.
 */


void targa_input_init (compress_info_ptr cinfo);

/*  GLOBALS  */
ulong *Buffer0, *Buffer1, *Buffer2;	/* buffer to hold one row of pixels */
BYTE ColorLUT[257];
BYTE ColorLUT256[257];
WORD *DispBuf;
char *DispBuf256;
int NewTotal;			/* */
int XOffset, YOffset;
int filerow, endrow, scrrow;
int BytesPerPixel;
long bytesPerRow;
ulong lOffset;
ulong Ytotal;
ulong Yratio, Xratio, InvYratio, InvXratio;
int width;			/* number of pixels to display in a row */
int height;

int sameaspectF;
int scaleF, interpF, isbottomupF, ditherF, GinterpF, hicolorF, nohicolor, twopassF,
 blocksmoothF, pixelsmoothF, debugF;
int F1024, F800, F640, hi800F, hi640F;

IMAGE_FORMATS FormatFlag = FMT_JFIF;	/* image file format */
double Gamma;			/* exponent for contrast stretch */
DCtrlType DitherCtrl;
char PB[512];
Files moh_files[MAXFILES];
int totalfiles = 0;
#ifdef OLD_DRIVERS
#else
GR_DRIVER_MODE_ENTRY far *ttab, *gtab;
#endif
extern JSAMPARRAY gifcolormap;
/*
 * <setjmp.h> is used for the optional error recovery mechanism shown in
 * the second part of the example.
 */

#include <setjmp.h>
/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/

/* This half of the example shows how to read data from the JPEG decompressor.
 * It's a little more refined than the above in that we show how to do your
 * own error recovery.  If you don't care about that, you don't need these
 * next two routines.
 */


/*
 * These routines replace the default trace/error routines included with the
 * JPEG code.  The example trace_message routine shown here is actually the
 * same as the standard one, but you could modify it if you don't want messages
 * sent to stderr.  The example error_exit routine is set up to return
 * control to read_JPEG_file() rather than calling exit().  You can use the
 * same routines for both compression and decompression error recovery.
 */

/* 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 */


/* 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)
{
  trace_message (msgtext);	/* report the error message */
  (*emethods->free_all) ();	/* clean up memory allocation & temp files */
  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.
 */
void
MakeColorLUT (
	       BYTE * pLut,	/* array to hold LUT */
	       BYTE minIn,	/* minimum input intensity */
	       BYTE maxIn,	/* maximum input intensity */
	       BYTE minOut,	/* minimum output intensity */
	       BYTE maxOut,	/* maximum output intensity */
	       double gamma	/* exponent of stretch */
)
{
  int index;			/* LUT index */
  double scale;			/* scale factor (K) */
  double lutVal;		/* LUT value */

  scale = (maxOut - minOut) / pow (maxIn - minIn, gamma);
  for (index = minIn; index <= maxIn; index++)
    {
      lutVal = minOut + scale * pow (index - minIn, gamma);
      *pLut++ = (BYTE) (lutVal + 0.5);
    }
}


METHODDEF void
output_init (decompress_info_ptr cinfo)
/* This routine should do any setup required */
{
  /* 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. */

  int mode = 0x30;
  int w, h;
  ulong *b0, *b1, *b2;
  int i, j, k;
  int numcolors, scrwidth, scrheight;



  if (hicolorF)
    {
      numcolors = 32768;
      BytesPerPixel = 2;
      scrwidth = 640;
      scrheight = 480;
      if ((cinfo->image_width > 640 || cinfo->image_height > 480) && hi800F)
	{
	  scrwidth = 800;
	  scrheight = 600;
	}
    }
  else
    {
      numcolors = 256;
      BytesPerPixel = 1;
      scrwidth = 640;
      scrheight = 480;
      if ((cinfo->image_width > 640 || cinfo->image_height > 480) && F800)
	{
	  scrwidth = 800;
	  scrheight = 600;
	}
      if ((cinfo->image_width > 800 || cinfo->image_height > 600) && F1024)
	{
	  scrwidth = 1024;
	  scrheight = 768;
	}
    }
  bytesPerRow = scrwidth * BytesPerPixel;
  interpF = GinterpF;
  NewTotal = 0;
  Ytotal = 0;
  XOffset = YOffset = 0;
  scrrow = 0;
  filerow = 0;
  Xratio = Yratio = (1L << InflateBase);
  InvXratio = InvYratio = (1L << InflateBase);
  w = cinfo->image_width;
  h = cinfo->image_height;
  if (w > scrwidth)
    {
      Xratio = (w << InflateBase) / (scrwidth);
      InvXratio = (scrwidth << InflateBase) / w;
    }

  if (h > scrheight)
    {
      Yratio = (h << InflateBase) / (scrheight);
      InvYratio = (scrheight << InflateBase) / h;
    }
  if (sameaspectF)
    {
      if (Yratio > Xratio)
	{
	  Xratio = Yratio;
	  InvXratio = InvYratio;
	}
      else
	{
	  Yratio = Xratio;
	  InvYratio = InvXratio;
	}
    }
  if (!scaleF)
    {
      Xratio = Yratio = (1L << InflateBase);
      InvXratio = InvYratio = (1L << InflateBase);
    }

  w = cinfo->image_width * InvXratio;
  h = cinfo->image_height * InvYratio;
  if (w % (1L << InflateBase))
    {
      w = w >> InflateBase;
      w++;
    }
  else
    w = w >> InflateBase;
  if (h % (1L << InflateBase))
    {
      h = h >> InflateBase;
      h++;
    }
  else
    h = h >> InflateBase;

  width = (cinfo->image_width * InvXratio) >> InflateBase;
  height = (cinfo->image_width * InvYratio) >> InflateBase;

  if (w <= scrwidth)
    XOffset = (scrwidth - w) / 2;
  if (h <= scrheight)
    YOffset = (scrheight - h) / 2;

  lOffset = 0xd0200000 + (ulong) YOffset *bytesPerRow + XOffset * BytesPerPixel;


  endrow = Yratio >> InflateBase;

  if (Xratio == (1L << InflateBase) && Yratio == (1L << InflateBase))
    interpF = 0;

  if (cinfo->total_passes == IS_BOTTOM_UP)
    {				/* ### kludge for bottom up
                                     targa files */
      lOffset += h * bytesPerRow;
      bytesPerRow = -bytesPerRow;
    }

  b0 = Buffer0 = (ulong *) jget_small (sizeof (ulong) * cinfo->image_width);
  b1 = Buffer1 = (ulong *) jget_small (sizeof (ulong) * cinfo->image_width);
  b2 = Buffer2 = (ulong *) jget_small (sizeof (ulong) * cinfo->image_width);
  for (i = 0; i < cinfo->image_width; i++)
    *b0++ = *b1++ = *b2++ = 0;

  DispBuf = (WORD *) jget_small (sizeof (WORD) * cinfo->image_width);
  DispBuf256 = (char *) jget_small (sizeof (char) * cinfo->image_width);

  if (ditherF)
    if (interpF)
      DitherInit (0, 255, 0, 31, width, &DitherCtrl);
    else
      DitherInit (0, 255, 0, 31, cinfo->image_width, &DitherCtrl);

  if (debugF)
    {
      printf ("image : %ld x %ld \n", cinfo->image_width, cinfo->image_height);
      printf ("screen %dx%d\n", scrwidth, scrheight);
      printf ("Xratio: %ld  Yratio: %ld\n", Xratio, Yratio);
      printf ("InvXratio: %ld  InvYratio: %ld\n", InvXratio, InvYratio);
      printf ("screen width %d\n", width);
      if (interpF)
	printf ("interpolating output\n");
      else
	printf ("Not interpolating output\n");
      if (ditherF)
	printf ("dithering output\n");
      else
	printf ("Not dithering output\n");
      printf ("out color space: %d\n", (int) cinfo->out_color_space);

      if (getch () == 'q')
	exit (0);
      printf ("ok.\n");
    }
#ifdef OLD_DRIVERS
  GrSetMode (GR_width_height_graphics,
         scrwidth, scrheight);
#else
  GrSetMode (GR_width_height_color_graphics,
	     scrwidth, scrheight, numcolors);
#endif
/*
  SetVideoMode(mode);
*/
  /* my Tseng manual says we should be in 256 */
/*
  SetHicolorMode(mode);
*/
  /* color mode before switching to hicolor */

}


/*
 * 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;
  JSAMPROW ptr0, ptr1, ptr2;
  /* You need not provide this routine if you always set
	 cinfo->quantize_colors FALSE; but a safer practice is to provide it and
     have it just print an error message, like this: */
/*
  fprintf(stderr, "put_color_map called: there's a bug here somewhere!\n");
*/
  ptr0 = colormap[0];
  if (cinfo->out_color_space == CS_RGB)
    {
      ptr1 = colormap[1];
      ptr2 = colormap[2];
    }
  else
    ptr1 = ptr2 = ptr0;

  for (i = 0; i < num_colors; i++)
    GrSetColor (i, ColorLUT256[*(ptr0++)],
		ColorLUT256[*(ptr1++)], ColorLUT256[*(ptr2++)]);
}


/*
 * 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.
 */

#define SRED     GETJSAMPLE(*ptr0)
#define SGREEN   GETJSAMPLE(*ptr1)
#define SBLUE    GETJSAMPLE(*ptr2)



METHODDEF void
put_pixel_rows256 (decompress_info_ptr cinfo, int num_rows,
		   JSAMPIMAGE pixel_data)
{
  int col, row;
  JSAMPROW ptr0;




  for (row = 0; row < num_rows; row++)
    {
      if (Ytotal <= (NewTotal + (1L << InflateBase)))
	{

	  ptr0 = pixel_data[0][row];
	  if (Xratio != (1L << InflateBase))
	    {
	      for (col = 0; col < cinfo->image_width; col++)
		{
		  DispBuf256[(col * InvXratio + (1L << (InflateBase - 1))) >> InflateBase] =
		    *ptr0;
		  ptr0++;
		}
	      memcpy ((char *) lOffset, DispBuf256, BytesPerPixel * width);
	    }			/* for col */
	  else
	    memcpy ((char *) lOffset, ptr0, BytesPerPixel * width);


	  lOffset += (long) bytesPerRow;


/*

      PutVideoRow30H(NewTotal + YOffset, XOffset, width, DispBuf);
*/
	  NewTotal += (1L << InflateBase);
	  Ytotal += Yratio;
	}
      else
	Ytotal -= (1L << InflateBase);

    }				/* for row */
}



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. */
  JSAMPROW ptr0, ptr1, ptr2;
  ulong *b0, *b1, *b2;
  int col;
  int row;
  int newrow, mycol;
  ulong temp0, temp1, temp2;
  int endcol, scrcol;
  char r, g, b;
  register
  WORD *pBuf;			/* pointer to video row buffer */
  WORD w0, w1, w2;
  ulong rowfrac, colfrac;

/*
printf("got into put_pixel_rows\n");
*/

  for (row = 0; row < num_rows; row++)
    {
      if (interpF)
	{
	  ptr0 = pixel_data[0][row];
	  if (cinfo->out_color_space == CS_RGB)
	    {
	      ptr1 = pixel_data[1][row];
	      ptr2 = pixel_data[2][row];
	    }
	  else
	    ptr1 = ptr2 = ptr0;
	  b0 = Buffer0;
	  b1 = Buffer1;
	  b2 = Buffer2;
/*
printf("filrow: %d endrow: %d\n",filerow,endrow);
*/
/*
printf("starting as: %d\n",*ptr0);
*/
	  if (filerow == endrow)
	    {
	      endrow = ((scrrow + 2) * Yratio) >> InflateBase;
	      rowfrac = ((scrrow + 1) << InflateBase) - filerow * InvYratio;
	      for (col = 0; col < cinfo->image_width; col++)
		{
		  *b0 += rowfrac * SRED;
		  *b1 += rowfrac * SGREEN;
		  *b2 += rowfrac * SBLUE;
		  b0++;
		  b1++;
		  b2++;
		  ptr0++;
		  ptr1++;
		  ptr2++;
		}
/*
printf("after row interp: %u\n",*Buffer0);
*/
	      ptr0 = pixel_data[0][row];
	      if (cinfo->out_color_space == CS_RGB)
		{
		  ptr1 = pixel_data[1][row];
		  ptr2 = pixel_data[2][row];
		}
	      else
		ptr1 = ptr2 = ptr0;
	      b0 = Buffer0;
	      b1 = Buffer1;
	      b2 = Buffer2;
	      rowfrac = InvYratio - rowfrac;
	      endcol = Xratio >> InflateBase;
	      scrcol = 0;
	      temp0 = temp1 = temp2 = 0;
	      for (col = 0; col < cinfo->image_width; col++)
		{
		  if (col == endcol)
		    {
		      endcol = ((scrcol + 2) * Xratio) >> InflateBase;
		      colfrac = ((ulong) (scrcol + 1) << InflateBase) - (col * InvXratio);
		      temp0 += colfrac * ((*b0 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
		      temp1 += colfrac * ((*b1 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
		      temp2 += colfrac * ((*b2 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
/*
if (col==1) printf("after col frac: %u wih colfrac %u\n",temp0,colfrac);
*/


		      if (!ditherF)
			DispBuf[scrcol] =
			  (((WORD) (ColorLUT[(temp0 + (1L << (ColorBase - 1))) >> ColorBase])) << 10 |
			   ((WORD) (ColorLUT[(temp1 + (1L << (ColorBase - 1))) >> ColorBase])) << 5 |
			   (WORD) (ColorLUT[(temp2 + (1L << (ColorBase - 1))) >> ColorBase]));
		      else
			{
			  Buffer0[scrcol] = ColorLUT256[(temp0 + (1L << (ColorBase - 1))) >> ColorBase];
			  Buffer1[scrcol] = ColorLUT256[(temp1 + (1L << (ColorBase - 1))) >> ColorBase];
			  Buffer2[scrcol] = ColorLUT256[(temp2 + (1L << (ColorBase - 1))) >> ColorBase];
			}

		      colfrac = InvXratio - colfrac;
		      temp0 = colfrac * ((*b0 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
		      temp1 = colfrac * ((*b1 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
		      temp2 = colfrac * ((*b2 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
		      scrcol++;
		    }
		  else
		    {
		      temp0 += InvXratio * ((*b0 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
		      temp1 += InvXratio * ((*b1 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
		      temp2 += InvXratio * ((*b2 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
/*
if (!col) printf("after col add: %u\n",temp0);
*/
		    }

		  *b0++;
		  *b1++;
		  *b2++;
		  ptr0++;
		  ptr1++;
		  ptr2++;
		}
/*
printf("after col interp: %u\n",*Buffer0);

*/

	      if (ditherF)
		{
		  Dither (&DitherCtrl, Buffer0, Buffer0, scrrow % 2);
		  Dither (&DitherCtrl, Buffer1, Buffer1, scrrow % 2);
		  Dither (&DitherCtrl, Buffer2, Buffer2, scrrow % 2);
		  for (col = 0; col < width; col++)
		    DispBuf[col] = ((WORD) Buffer0[col] << 10) |
		      ((WORD) Buffer1[col] << 5) |
		      ((WORD) Buffer2[col]);
		}


	      memcpy ((char *) lOffset, DispBuf, BytesPerPixel * width);
	      lOffset += (long) bytesPerRow;
	      scrrow++;

	      b0 = Buffer0;
	      b1 = Buffer1;
	      b2 = Buffer2;
	      ptr0 = pixel_data[0][row];
	      if (cinfo->out_color_space == CS_RGB)
		{
		  ptr1 = pixel_data[1][row];
		  ptr2 = pixel_data[2][row];
		}
	      else
		ptr1 = ptr2 = ptr0;
	      for (col = 0; col < cinfo->image_width; col++)
		{
		  *b0++ = rowfrac * SRED;
		  *b1++ = rowfrac * SGREEN;
		  *b2++ = rowfrac * SBLUE;
		  ptr0++;
		  ptr1++;
		  ptr2++;
		}

	    }
	  else
	    {
	      for (col = 0; col < cinfo->image_width; col++)
		{
		  *b0 += InvYratio * SRED;
		  *b1 += InvYratio * SGREEN;
		  *b2 += InvYratio * SBLUE;
		  b0++;
		  b1++;
		  b2++;
		  ptr0++;
		  ptr1++;
		  ptr2++;
		}
/*
printf("after row add: %u\n",*Buffer0);
*/
	    }
	  filerow++;


	}
      else if (Ytotal <= (NewTotal + (1L << InflateBase)))
	{


	  ptr0 = pixel_data[0][row];
	  if (cinfo->out_color_space == CS_RGB)
	    {
	      ptr1 = pixel_data[1][row];
	      ptr2 = pixel_data[2][row];
	    }
	  else
	    ptr1 = ptr2 = ptr0;
	  if (ditherF)
	    {
	      DitherChar (&DitherCtrl, ptr0, ptr0, (NewTotal >> InflateBase) % 2);
	      DitherChar (&DitherCtrl, ptr1, ptr1, (NewTotal >> InflateBase) % 2);
	      DitherChar (&DitherCtrl, ptr2, ptr2, (NewTotal >> InflateBase) % 2);
	      for (col = 0; col < cinfo->image_width; col++)
		DispBuf[(col * InvXratio + (1L << (InflateBase - 1))) >> InflateBase] =
		  ((WORD) ptr0[col] << 10) |
		  ((WORD) ptr1[col] << 5) |
		  ((WORD) ptr2[col]);
	    }
	  else
	    for (col = 0; col < cinfo->image_width; col++)
	      {
		DispBuf[(col * InvXratio + (1L << (InflateBase - 1))) >> InflateBase] =
		  (((WORD) (ColorLUT[SRED])) << 10 |
		   ((WORD) (ColorLUT[SGREEN])) << 5 |
		   (WORD) (ColorLUT[SBLUE]));
		ptr0++;
		ptr1++;
		ptr2++;

	      }			/* for */


	  /* calculate video page and offset */


	  memcpy ((char *) lOffset, DispBuf, BytesPerPixel * width);
	  lOffset += (long) bytesPerRow;


/*

      PutVideoRow30H(NewTotal + YOffset, XOffset, width, DispBuf);
*/
	  NewTotal += (1L << InflateBase);
	  Ytotal += Yratio;
	}
      else
	Ytotal -= (1L << InflateBase);
    }
}



METHODDEF void
output_term (decompress_info_ptr cinfo)
/* Finish up at the end of the output */
{
  /* 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. */
  DitherTerm (&DitherCtrl);
  (*cinfo->emethods->free_all) ();

}


/*
 * That's it for the routines that deal with writing the output image.
 * Now we have overall control and parameter selection routines.
 */


/*
 * 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;
  if (hicolorF)
    cinfo->methods->put_pixel_rows = put_pixel_rows;
  else
    cinfo->methods->put_pixel_rows = put_pixel_rows256;
  cinfo->methods->output_term = output_term;
}


/*
 * 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.
 */

GLOBAL int
read_JPEG_file (char *filename)
{
  /* These three structs contain JPEG parameters and working data. They must
	 survive for the duration of parameter setup and one call to
	 jpeg_decompress; typically, making them local data in the calling
	 routine is the best strategy. */
  struct decompress_info_struct cinfo;
  struct decompress_methods_struct dc_methods;
  struct external_methods_struct e_methods;
  /* Select the input and output files. In this example we want to open the
	 input file before doing anything else, so that the setjmp() error
	 recovery below can assume the file is open. Note that cinfo.output_file
	 is only used if your output handling routines use it; otherwise, you can
	 just make it NULL. VERY IMPORTANT: use "b" option to fopen() if you are
	 on a machine that requires it in order to read binary files. */

  if ((cinfo.input_file = fopen (filename, "rb")) == NULL)
    {
      fprintf (stderr, "can't open %s\n", filename);
      return 0;
    }
  cinfo.output_file = NULL;	/* if no actual output file involved */

  /* Initialize the system-dependent method pointers. */
  cinfo.methods = &dc_methods;	/* links to method structs */
  cinfo.emethods = &e_methods;
  /* 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.trace_level = 0;
  e_methods.error_exit = error_exit;	/* supply error-exit routine */
  e_methods.trace_message = trace_message;	/* supply trace-message
						   routine */

  /* prepare setjmp context for possible exit from error_exit */
  if (setjmp (setjmp_buffer))
    {
      /* If we get here, the JPEG code has signaled an error. Memory allocation
         has already been cleaned up (see free_all call in error_exit), but we
         need to close the input file before returning. You might also need to
         close an output file, etc. */
      fclose (cinfo.input_file);
      return 0;
    }
  /* Here we use the standard memory manager provided with the JPEG code. In
	 some cases you might want to replace the memory manager, or at least the
	 system-dependent part of it, with your own code. */
  jselmemmgr (&e_methods);	/* select std memory allocation routines */
  /* 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. */

  /* Here, set up the pointer to your own routine for post-header-reading
	 parameter selection.  You could also initialize the pointers to the
	 output data handling routines here, if they are not dependent on the
	 image type. */
  dc_methods.d_ui_method_selection = d_ui_method_selection;

  /* Set up default decompression parameters. */
  j_d_defaults (&cinfo, TRUE);
  /* TRUE indicates that an input buffer should be allocated. In unusual
	 cases you may want to allocate the input buffer yourself; see jddeflts.c
	 for commentary. */

  /* 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. */

  if (!hicolorF)
    {
      cinfo.quantize_colors = TRUE;
      if (twopassF)
	cinfo.two_pass_quantize = TRUE;
      else
	cinfo.two_pass_quantize = FALSE;
    }
  if (blocksmoothF)
    cinfo.do_block_smoothing = TRUE;
  if (pixelsmoothF)
    cinfo.do_pixel_smoothing = TRUE;


  /* Set up to read a JFIF or baseline-JPEG file. */
  /* This is the only JPEG file format currently supported. */
  jselrjfif (&cinfo);

  /* Here we go! */
  jpeg_decompress (&cinfo);

  /* 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);

  return 1;			/* indicate success */

  /* Note: if you want to decompress more than one image, we recommend you
	 repeat this whole routine.  You MUST repeat the j_d_defaults()/alter
	 parameters/jpeg_decompress() sequence, as some data structures allocated
	 in j_d_defaults are freed upon exit from jpeg_decompress. */
}

void
read_TARGA_file (char *name)
{
  struct compress_info_struct moh_cinfo;
  struct decompress_info_struct moh_dcinfo;
  struct compress_methods_struct moh_c_methods;
  struct external_methods_struct moh_e_methods;

  JSAMPARRAY pixel_row;
  int i, j, k;
  JSAMPIMAGE pixel_rows;

/* note the similarities here and read_JPEG_file */
/* ## clearly needs modularization */


  moh_cinfo.methods = &moh_c_methods;
  moh_cinfo.emethods = &moh_e_methods;
  jselerror (&moh_e_methods);	/* error/trace message routines */
  jselmemmgr (&moh_e_methods);	/* memory allocation routines */

  if ((moh_cinfo.input_file = fopen (name, "rb")) == NULL)
    {
      fprintf (stderr, "Can't open %s\n", name);
      exit (EXIT_FAILURE);
    }

  jselrtarga (&moh_cinfo);

  moh_cinfo.total_passes = 0;
  (*moh_cinfo.methods->input_init) (&moh_cinfo);

  /* now to copy the info into a *de*compress info struct, */
  /* as put_pixel_rows & output_init require that */
  /* ## I dislike this hack */

  moh_dcinfo.image_width = moh_cinfo.image_width;
  moh_dcinfo.image_height = moh_cinfo.image_height;
  moh_dcinfo.methods = moh_cinfo.methods;
  moh_dcinfo.emethods = moh_cinfo.emethods;

  moh_dcinfo.total_passes = moh_cinfo.total_passes;
  moh_dcinfo.out_color_space = CS_RGB;

  /* allolcate space for one row of data */
  pixel_rows = (JSAMPIMAGE) (*moh_cinfo.emethods->alloc_small)
    (3 * SIZEOF (JSAMPARRAY));
  pixel_rows[0] = (JSAMPARRAY) (*moh_cinfo.emethods->alloc_small)
    (MAXROWREAD * SIZEOF (JSAMPROW));
  pixel_rows[1] = (JSAMPARRAY) (*moh_cinfo.emethods->alloc_small)
    (MAXROWREAD * SIZEOF (JSAMPROW));
  pixel_rows[2] = (JSAMPARRAY) (*moh_cinfo.emethods->alloc_small)
    (MAXROWREAD * SIZEOF (JSAMPROW));
  for (i = 0; i < 3; i++)
    {
      for (j = 0; j < MAXROWREAD; j++)
	pixel_rows[i][j] = (JSAMPROW)
	  (*moh_cinfo.emethods->alloc_small) (moh_cinfo.image_width * sizeof (JSAMPLE));
    }
  pixel_row = (JSAMPARRAY) (*moh_cinfo.emethods->alloc_small)
    (3 /* moh_cinfo.num_components */ * SIZEOF (JSAMPROW));
  for (i = 0; i < 3 /* moh_cinfo.num_components */ ; i++)
    pixel_row[i] = (JSAMPROW) (*moh_cinfo.emethods->alloc_small)
      (moh_cinfo.image_width * sizeof (JSAMPLE));
/*

	pixel_row=(JSAMPIMAGE) malloc(3 *sizeof(JSAMPARRAY));
	for(i=0;i<3;i++)
		pixel_row[i]=(JSAMPROW) malloc(sizeof(JSAMPLE)*moh_cinfo.image_width);
*/

  output_init (&moh_dcinfo);
  for (i = moh_cinfo.image_height; i;)
    {
      k = MIN (i, MAXROWREAD);
      i -= k;
      for (j = 0; j < k; j++)
	{
	  pixel_row[0] = pixel_rows[0][j];
	  pixel_row[1] = pixel_rows[1][j];
	  pixel_row[2] = pixel_rows[2][j];
	  (*moh_cinfo.methods->get_input_row) (&moh_cinfo, pixel_row);
	}
      put_pixel_rows (&moh_dcinfo, k, pixel_rows);
    }
  /*now to free things */
  (*moh_cinfo.emethods->free_all) ();

  fclose (moh_cinfo.input_file);
}

void
read_GIF_file (char *name)
{
  struct compress_info_struct moh_cinfo;
  struct decompress_info_struct moh_dcinfo;
  struct compress_methods_struct moh_c_methods;
  struct external_methods_struct moh_e_methods;

  JSAMPIMAGE pixel_row;
  JSAMPIMAGE pixel_rows;
  int i, j, k;
  int temphicolor, tempdither;

  temphicolor = hicolorF;
  tempdither = ditherF;

  hicolorF = 0;
  ditherF = 0;

/* note the similarities here and read_JPEG_file */
/* ## clearly needs modularization */


  moh_cinfo.methods = &moh_c_methods;
  moh_cinfo.emethods = &moh_e_methods;
  jselerror (&moh_e_methods);	/* error/trace message routines */
  jselmemmgr (&moh_e_methods);	/* memory allocation routines */

  if ((moh_cinfo.input_file = fopen (name, "rb")) == NULL)
    {
      fprintf (stderr, "Can't open %s\n", name);
      exit (EXIT_FAILURE);
    }

  jselrgif (&moh_cinfo);

  moh_cinfo.total_passes = 0;
  (*moh_cinfo.methods->input_init) (&moh_cinfo);

  /* now to copy the info into a *de*compress info struct, */
  /* as put_pixel_rows & output_init require that */
  /* ## I dislike this hack */

  moh_dcinfo.image_width = moh_cinfo.image_width;
  moh_dcinfo.image_height = moh_cinfo.image_height;
  moh_dcinfo.methods = moh_cinfo.methods;
  moh_dcinfo.emethods = moh_cinfo.emethods;

  moh_dcinfo.total_passes = moh_cinfo.total_passes;
  moh_dcinfo.out_color_space = CS_RGB;

  /* allolcate space for one row of data */
  pixel_row = (JSAMPIMAGE) (*moh_cinfo.emethods->alloc_small)
    (1 * SIZEOF (JSAMPARRAY));
  pixel_row[0] = (JSAMPARRAY) (*moh_cinfo.emethods->alloc_small)
    (MAXROWREAD * SIZEOF (JSAMPROW));
  pixel_row[0][0] = (JSAMPROW)
    (*moh_cinfo.emethods->alloc_small) (moh_cinfo.image_width * sizeof (JSAMPLE));

  output_init (&moh_dcinfo);
  put_color_map (&moh_dcinfo, 256, gifcolormap);
  for (i = moh_cinfo.image_height; i; i--)
    {
      (*moh_cinfo.methods->get_input_row) (&moh_cinfo, (JSAMPARRAY) pixel_row);
      put_pixel_rows256 (&moh_dcinfo, 1, pixel_row);

    }

  /*now to free things */
  (*moh_cinfo.emethods->free_all) ();

  fclose (moh_cinfo.input_file);
  hicolorF = temphicolor;
  ditherF = tempdither;

}



void
Usage ()
{
  fprintf (stderr, "Usage: hiview [options] file ...\n");
  fprintf (stderr, "   where the options are:\n");
  fprintf (stderr, "     -d   toggle Floyd-Steinberg dithering, default is off\n");
  fprintf (stderr, "     -i   toggle smooth interpolation when resizing image, default is on\n");
  fprintf (stderr, "     -g   GIF format file\n");
  fprintf (stderr, "     -t   TARGA format file\n");
  fprintf (stderr, "     -s gamma	contrast stretch using exponent gamma\n");
  fprintf (stderr, "          gamma is a positive double precision number\n");
  fprintf (stderr, "          values are typically in the range 0.5 .. 1.0\n");
  fprintf (stderr, "     -q toggle one/two pass quantization, default is one\n");
  fprintf (stderr, "     -? this message\n");
  fprintf (stderr, "     -D   Debug mode\n");
  fprintf (stderr, "   Filenames may contain wildcards\n");
  fprintf (stderr, "\n");
}


IMAGE_FORMATS
getformat (char *name)
{
  char drive[MAXDRIVE];
  char dir[MAXDIR];
  char file[MAXFILE];
  char ext[MAXEXT];
  IMAGE_FORMATS type;

  fnsplit (name, drive, dir, file, ext);
  if (!strcmp (ext, ".JPG"))
    type = FMT_JFIF;
  else if (!strcmp (ext, ".GIF"))
    type = FMT_GIF;
  else if (!strcmp (ext, ".TGA"))
    type = FMT_TARGA;
  else
    type = FMT_UNKNOWN;
  return (type);
}
void
getfiles (char *path, IMAGE_FORMATS ex_type, int level)
{
  struct ffblk tempfile;
  int result;
  char drive[MAXDRIVE];
  char dir[MAXDIR];
  char file[MAXFILE];
  char ext[MAXEXT];
  char newpath[500];
  IMAGE_FORMATS type;

  result = findfirst (path, &tempfile, 0 | FA_RDONLY | FA_DIREC);
  type = ex_type;
  while (result >= 0)
    {
      if (!(tempfile.ff_attrib & FA_DIREC))
	{
	  fnsplit (path, drive, dir, file, ext);
	  strcpy (moh_files[totalfiles].name, drive);
	  strcat (moh_files[totalfiles].name, dir);
	  strcat (moh_files[totalfiles].name, tempfile.ff_name);
	  if (ex_type == FMT_UNKNOWN)
	    type = getformat (moh_files[totalfiles].name);
	  moh_files[totalfiles].type = type;
	  moh_files[totalfiles].selected = 0;
	  totalfiles++;
	  result = findnext (&tempfile);
	}
      else
	{			/* find all *.jpg, gif, tga in directory */
	  fnsplit (path, drive, dir, file, ext);
	  strcpy (newpath, drive);
	  strcat (newpath, dir);
	  strcat (newpath, tempfile.ff_name);
	  result = findnext (&tempfile);
	}
    }
}

void
parse_command (int argc, char **argv)
{
  struct ffblk tempfile;
  int result, i, filespec;
  IMAGE_FORMATS type;
  char flag;

  filespec = 0;
  type = FMT_UNKNOWN;
  for (i = 1; i < argc; i++)
    {
      if (*argv[i] == '-')
	{
	  flag = *(argv[i] + 1);
	  switch (flag)
	    {
	    case 't':
	      type = FMT_TARGA;
	      break;
	    case 'g':
	      type = FMT_GIF;
	      break;
	    case 'j':
	      type = FMT_JFIF;
	      break;
	    case 'd':
	      ditherF = !ditherF;
	      break;
	    case 'i':
	      GinterpF = !GinterpF;
	      break;
	    case 's':
	      Gamma = atof (argv[++i]);
	      break;
	    case 'h':
	      hicolorF = !hicolorF;
	      break;
	    case 'b':
	      blocksmoothF = !blocksmoothF;
	      break;
	    case 'p':
	      pixelsmoothF = !pixelsmoothF;
	      break;
	    case 'q':
	      twopassF = !twopassF;
	      break;
	    case 'D':
	      debugF = 1;
	      break;
	    case '?':
	      Usage ();
	      exit (0);
	      break;

	    }
	}
      else
	{
	  filespec = 1;
	  getfiles (argv[i], type, 0);
	}
    }

  if (!filespec)
    {
      getfiles ("*.jpg", FMT_JFIF, 1);
      getfiles ("*.tga", FMT_TARGA, 1);
      getfiles ("*.gif", FMT_GIF, 1);
    }
}

void
draw_border ()
{
  int i;

  gotoxy (1, 1);

  textbackground (BORDER_BCOLOR);
  textcolor (BORDER_FCOLOR);
  for (i = 1; i < SC_WIDTH - 1; i++)
    cprintf (" ");
  gotoxy (34, 1);
  cprintf ("%s v.%s", PROGNAME,VERSION);
  gotoxy (1, SC_HEIGHT);
  for (i = 1; i < SC_WIDTH - 1; i++)
    cprintf (" ");
  gotoxy (1, SC_HEIGHT - 1);
  textbackground (MESSAGE_BCOLOR);
  textcolor (MESSAGE_FCOLOR);
  cprintf ("%d Files.", totalfiles);
  gotoxy (40, SC_HEIGHT - 1);
  textcolor (MESSAGE_HIGHLIGHT);
  cprintf ("O");
  textcolor (MESSAGE_FCOLOR);
  cprintf ("ptions");


}

void
highlight (int fileoffset, int currentpos, int on)
{
  int x, y, i, j;
  int colheight;
  char drive[MAXDRIVE];
  char dir[MAXDIR];
  char file[MAXFILE];
  char ext[MAXEXT];

  colheight = SC_HEIGHT - SC_HEADER - SC_FOOTER;
  x = (SC_WIDTH - SC_COLS * SC_COL_WIDTH) / 2;
  y = SC_HEADER + 1;
  i = currentpos - fileoffset;
  while (i >= colheight)
    {
      i -= colheight;
      x += SC_COL_WIDTH;
    }
  y += i;
  x -= 1;

  gotoxy (x, y);
  if (on)
    {
      textcolor (FILE_BCOLOR);
      textbackground (FILE_FCOLOR);
    }
  else
    {
      textbackground (FILE_BCOLOR);
      textcolor (FILE_FCOLOR);
    }
  for (i = 0; i < SC_COL_WIDTH; i++)
    cprintf (" ");
  gotoxy (x, y);
  fnsplit (moh_files[currentpos].name, drive, dir, file, ext);

  cprintf (" %s", file);
  gotoxy (x + 10, y);
  cprintf ("%s ", ext);
  textbackground (FILE_BCOLOR);
  textcolor (FILE_FCOLOR);



}



void
print_files (int fileoffset, int currentpos)
{
  int i, j, k;
  int x, y, lastfile;
  int onscreen;
  char drive[MAXDRIVE];
  char dir[MAXDIR];
  char myfilename[50];
  char ext[MAXEXT];

  onscreen = (SC_HEIGHT - SC_HEADER - SC_FOOTER) * SC_COLS;

  textbackground (FILE_BCOLOR);
  textcolor (FILE_FCOLOR);

  for (i = SC_HEADER + 1; i <= SC_HEIGHT - SC_FOOTER; i++)
    {
      gotoxy (1, i);
      clreol ();
    }
  x = (SC_WIDTH - SC_COLS * SC_COL_WIDTH) / 2;
  y = SC_HEADER + 1;
  lastfile = MIN (totalfiles, onscreen + fileoffset);
  for (i = fileoffset; i < lastfile; i++)
    {
      gotoxy (x, y);
      fnsplit (moh_files[i].name, drive, dir, myfilename, ext);
      cprintf ("%s", myfilename);

      gotoxy (x + 9, y);

      cprintf ("%s", ext);
      y++;
      if (y > SC_HEIGHT - SC_FOOTER)
	{
	  x += SC_COL_WIDTH;
	  y = SC_HEADER + 1;
	}
    }
  highlight (fileoffset, currentpos, 1);
}

double
getdouble ()
{
  double gamma;

  scanf ("%lf", &gamma);
  if (gamma<0) gamma=1;
  return (gamma);
}

void
optionsmenu ()
{
  int quitF = 0;
  int c;

  clrscr ();
  gotoxy (1, SC_HEADER + 1);
  textbackground (MESSAGE_BCOLOR);
  textcolor (MESSAGE_HEADER);
  cprintf ("Global Options: ");
  gotoxy (1, SC_HEADER + 2);
  textcolor (MESSAGE_HIGHLIGHT);
  cprintf ("H");
  textcolor (MESSAGE_FCOLOR);
  cprintf ("icolor: ");
  if (nohicolor)
    cprintf ("Not available.");
  else if (hicolorF)
    cprintf ("Used.");
  else
    cprintf ("Not used.");
  gotoxy (1, SC_HEADER + 3);
  textcolor (MESSAGE_HIGHLIGHT);
  cprintf ("B");
  textcolor (MESSAGE_FCOLOR);
  cprintf ("lock smoothing: ");
  if (blocksmoothF)
    cprintf ("Yes.");
  else
    cprintf ("No.");

  gotoxy (1, SC_HEADER + 4);
  textcolor (MESSAGE_HIGHLIGHT);
  cprintf ("P");
  textcolor (MESSAGE_FCOLOR);
  cprintf ("ixel smoothing: ");
  if (pixelsmoothF)
    cprintf ("Yes.");
  else
    cprintf ("No");
  gotoxy (1, SC_HEADER + 5);
  textcolor (MESSAGE_HIGHLIGHT);
  cprintf ("G");
  textcolor (MESSAGE_FCOLOR);
  cprintf ("amma: %0.2lf\n", Gamma);

  gotoxy (1, SC_HEADER + 7);
  textcolor (MESSAGE_HEADER);
  cprintf ("24->15 bit Options: ");
  gotoxy (1, SC_HEADER + 8);
  textcolor (MESSAGE_HIGHLIGHT);
  cprintf ("I");
  textcolor (MESSAGE_FCOLOR);
  cprintf ("nterpolation: ");
  if (GinterpF)
    cprintf ("Linear Averaging.\n");
  else
    cprintf ("None.\n");
  gotoxy (1, SC_HEADER + 9);
  textcolor (MESSAGE_HIGHLIGHT);
  cprintf ("D");
  textcolor (MESSAGE_FCOLOR);
  cprintf ("ithering: ");
  if (ditherF)
    cprintf ("Floyd-Steinberg.\n");
  else
    cprintf ("None.\n");
  gotoxy (1, SC_HEADER + 11);
  textcolor (MESSAGE_HEADER);
  cprintf ("24->8 bit Options: ");
  gotoxy (1, SC_HEADER + 12);
  textcolor (MESSAGE_HIGHLIGHT);
  cprintf ("Q");
  textcolor (MESSAGE_FCOLOR);
  cprintf ("uantization: ");
  if (twopassF)
    cprintf ("Two pass.");
  else
    cprintf ("One Pass.");
  while (!quitF)
    {
      gotoxy (1, SC_HEIGHT - SC_FOOTER - 1);
      clreol ();
      cprintf ("Please enter your choice: ");
      c = getxkey ();
      switch (c)
	{
	case 'i':
	case 'I':
	  GinterpF = !GinterpF;
	  gotoxy (1, SC_HEADER + 8);
	  clreol ();
	  textcolor (MESSAGE_HIGHLIGHT);
	  cprintf ("I");
	  textcolor (MESSAGE_FCOLOR);
	  cprintf ("nterpolation: ");
	  if (GinterpF)
	    cprintf ("Linear Averaging.\n");
	  else
	    cprintf ("None.\n");
	  clreol ();
	  break;
	case 'd':
	case 'D':
	  ditherF = !ditherF;
	  gotoxy (1, SC_HEADER + 9);
	  clreol ();
	  textcolor (MESSAGE_HIGHLIGHT);
	  cprintf ("D");
	  textcolor (MESSAGE_FCOLOR);
	  cprintf ("ithering: ");
	  if (ditherF)
	    cprintf ("Floyd-Steinberg.\n");
	  else
	    cprintf ("None.\n");
	  clreol ();
	  break;
	case 'g':
	case 'G':
	  gotoxy (1, SC_HEIGHT - SC_FOOTER - 1);
	  clreol ();
	  cprintf ("Please enter gamma: ");
	  Gamma = getdouble ();
      MakeColorLUT (ColorLUT, 0, 255, 0, 31, Gamma);
      ColorLUT[256] = ColorLUT[255];/* to take care of rounding errors */
      MakeColorLUT (ColorLUT256, 0, 255, 0, 255, Gamma);
      ColorLUT256[256] = ColorLUT256[255];
      
	  gotoxy (1, SC_HEADER + 5);
	  clreol ();
	  textcolor (MESSAGE_HIGHLIGHT);
	  cprintf ("G");
	  textcolor (MESSAGE_FCOLOR);
	  cprintf ("amma: %0.2lf\n", Gamma);
	  break;
	case 'b':
	case 'B':
	  blocksmoothF = !blocksmoothF;
	  gotoxy (1, SC_HEADER + 3);
	  clreol ();
	  textcolor (MESSAGE_HIGHLIGHT);
	  cprintf ("B");
	  textcolor (MESSAGE_FCOLOR);
	  cprintf ("lock smoothing: ");
	  if (blocksmoothF)
	    cprintf ("Yes.");
	  else
	    cprintf ("No.");
	  break;
	case 'p':
	case 'P':
	  pixelsmoothF = !pixelsmoothF;
	  gotoxy (1, SC_HEADER + 4);
	  clreol ();
	  textcolor (MESSAGE_HIGHLIGHT);
	  cprintf ("P");
	  textcolor (MESSAGE_FCOLOR);
	  cprintf ("ixel smoothing: ");
	  if (pixelsmoothF)
	    cprintf ("Yes.");
	  else
	    cprintf ("No");
	  break;
	case 'q':
	case 'Q':
	  twopassF = !twopassF;
	  gotoxy (1, SC_HEADER + 12);
	  clreol ();
	  textcolor (MESSAGE_HIGHLIGHT);
	  cprintf ("Q");
	  textcolor (MESSAGE_FCOLOR);
	  cprintf ("uantization: ");
	  if (twopassF)
	    cprintf ("Two pass.");
	  else
	    cprintf ("One Pass.");
	  break;
	case 'h':
	case 'H':
	  if (!nohicolor)
	    {
	      hicolorF = !hicolorF;
	      gotoxy (1, SC_HEADER + 2);
	      clreol ();
	      textcolor (MESSAGE_HIGHLIGHT);
	      cprintf ("H");
	      textcolor (MESSAGE_FCOLOR);
	      cprintf ("icolor: ");
	      if (hicolorF)
		cprintf ("Used.");
	      else
		cprintf ("Not used.");
	    }
	  break;
	case ESC:
	  quitF = 1;
	  break;
	}
    }				/* while */


}

void
userint ()
{
  int quitF = 0;
  int fileoffset = 0;
  int currentpos = 0;
  int onscreen;
  int specialF;
  int c;
  int colheight;


  colheight = SC_HEIGHT - SC_HEADER - SC_FOOTER;
  onscreen = colheight * SC_COLS;

  clrscr ();
  draw_border ();
  print_files (fileoffset, currentpos);
  while (!quitF)
    {
      c = getxkey ();
      switch (c)
	{
	case UP:
	  currentpos--;
	  if (currentpos < 0)
	    currentpos = 0;
	  else if (currentpos < fileoffset)
	    {
	      fileoffset--;
	      print_files (fileoffset, currentpos);
	    }
	  else
	    {
	      highlight (fileoffset, currentpos + 1, 0);
	      highlight (fileoffset, currentpos, 1);
	    }
	  break;
	case DOWN:
	  currentpos++;
	  if (currentpos >= totalfiles)
	    currentpos = totalfiles - 1;
	  else if (currentpos > fileoffset + onscreen - 1)
	    {
	      fileoffset++;
	      print_files (fileoffset, currentpos);
	    }
	  else
	    {
	      highlight (fileoffset, currentpos - 1, 0);
	      highlight (fileoffset, currentpos, 1);
	    }
	  break;
	case RIGHT:
	  highlight (fileoffset, currentpos, 0);
	  currentpos += colheight;
	  if (currentpos >= totalfiles)
	    currentpos = totalfiles - 1;

	  if (currentpos > fileoffset + onscreen - 1)
	    {
	      fileoffset += colheight;
	      print_files (fileoffset, currentpos);
	    }
	  else
	    {
	      highlight (fileoffset, currentpos, 1);
	    }
	  break;
	case LEFT:
	  highlight (fileoffset, currentpos, 0);
	  currentpos -= colheight;
	  if (currentpos < 0)
	    currentpos = 0;
	  if (currentpos < fileoffset)
	    {
	      fileoffset -= colheight;
	      if (fileoffset < 0)
		fileoffset = 0;
	      print_files (fileoffset, currentpos);
	    }
	  else
	    {
	      highlight (fileoffset, currentpos, 1);
	    }
	  break;
	case 'o':
	case 'O':
	  optionsmenu ();
	  clrscr ();
	  draw_border ();
	  print_files (fileoffset, currentpos);
	  break;
	case ESC:
	  return;
	  break;
	case RETURN:
	  switch (moh_files[currentpos].type)
	    {
	    case FMT_JFIF:
	      read_JPEG_file (moh_files[currentpos].name);
	      break;
	    case FMT_TARGA:
	      read_TARGA_file (moh_files[currentpos].name);
	      break;
	    case FMT_GIF:
	      read_GIF_file (moh_files[currentpos].name);
	      break;
	    }
	  getch ();
	  GrSetMode (GR_80_25_text);
	  draw_border ();
	  print_files (fileoffset, currentpos);

	  break;
	case 'q':
	  quitF = 1;
	  break;
	}
    }				/* while */
}


main (int argc, char **argv)
{
  char *fname;
  IMAGE_FORMATS filetype;
  int i, j, a;


  debugF = 0;
  scaleF = 1;
  sameaspectF = 1;
  GinterpF = 1;
  interpF = 1;
  Gamma = 1.0;
  blocksmoothF = 0;
  pixelsmoothF = 0;
  twopassF = 0;
  filetype = FMT_JFIF;
  ditherF = 0;
  if (debugF)
    for (i = 0; i < argc; i++)
      printf ("%s\n", argv[i]);
  nohicolor = 1;

  parse_command (argc, argv);
  if (debugF)
    {
      printf ("parsed %d files\n", totalfiles);
      for (i = 0; i < totalfiles; i++)
        printf ("%s\n", moh_files[i].name);
      getch ();
    }
  gppconio_init ();
  if (totalfiles)
    {
        MakeColorLUT (ColorLUT, 0, 255, 0, 31, Gamma);
        ColorLUT[256] = ColorLUT[255];/* to take care of rounding errors */
        MakeColorLUT (ColorLUT256, 0, 255, 0, 255, Gamma);
        ColorLUT256[256] = ColorLUT256[255];
#ifdef OLD_DRIVERS 
        F1024 = F800 = F640 =0;
        GrSetMode(GR_width_height_graphics,640,480);
        if (GrSizeX()==640 && GrSizeY()==480) F640=1;
        if (GrSizeX()==800 && GrSizeY()==600) F800=1;
        if (GrSizeX()==1024 && GrSizeY()==768) F1024=1;
        GrSetMode (GR_80_25_text);
        if (F640==F1024==F800==0)
        {
            printf("Sorry, Video card not supported.\n");
            exit(1);
        }
#else
        GrGetDriverModes (&ttab, &gtab);
        F1024 = F800 = F640 = hi800F = hi640F = 0;
        for (i = 0; gtab[i].width != 0; i++)
        {
            if (gtab[i].number_of_colors == 32768)
            nohicolor = 0;
            if (gtab[i].width == 1024 && gtab[i].height == 768 &&
            gtab[i].number_of_colors == 256)
            F1024 = 1;
            if (gtab[i].width == 800 && gtab[i].height == 600 &&
            gtab[i].number_of_colors == 256)
            F800 = 1;
            if (gtab[i].width == 640 && gtab[i].height == 480 &&
            gtab[i].number_of_colors == 256)
            F640 = 1;
            if (gtab[i].width == 800 && gtab[i].height == 600 &&
            gtab[i].number_of_colors == 32768)
            hi800F = 1;
            if (gtab[i].width == 640 && gtab[i].height == 480 &&
            gtab[i].number_of_colors == 32768)
            hi640F = 1;
        }
        if (F640==F1024==F800==hi800F==hi640F==0)
        {
            printf("Sorry, Video card not supported.\n");
            exit(1);
        }
#endif
      if (nohicolor)
          hicolorF = 0;
      else
          hicolorF = 1;
      userint ();
      GrSetMode (GR_80_25_text);
    }
  else printf("No files found");
  return 0;
}

void
mr_prints (int x, int y, int attr, char *str)
{
  while (*str)
    {
      if (*str == '\t')
	x = (x / 8) * 8 + 8;
      else if (*str == '\n')
	y++;
      else
	ScreenPutChar (*(str++), attr, x++, y);
      if (x >= 80)
	{
	  y++;
	  x = 0;
	}
    }
}
