/* PCX2PBM v0.0 - Copyright (c) 1996 by Dave Humphrey - aj589@freenet.carleton.ca
 * Converts PCX to Planer bitmaps and vice-versa
 */


//Some conversion routines I got from a BMP conversion source code
#define HexToLong(Start) (unsigned long)(*(Start) & 0xff) + \
			 (unsigned long)((*(Start + 1) << 8) & 0xffff) + \
			 (unsigned long)(((unsigned long)*(Start+3) << 24) & 0xffffffffl) + \
			 (unsigned long)(((unsigned long)*(Start+2) << 16) & 0xffffffl)

#define HexToInt(Start) (unsigned int)(*(Start) & 0xff) + \
			(unsigned int)((*(Start + 1) << 8) & 0xffff)

//General include files
#include <sys\stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <alloc.h>
#include <ctype.h>

//Include files for the graphics routines, can remove if your using/creating
//your own
#include "c:\tc\xlib612\include\xlib.h"
#include "c:\tc\xlib612\include\xpal.h"
#include "c:\tc\xlib612\include\xpoint.h"
#include "c:\tc\xlib612\include\xrect.h"
#include "c:\tc\xlib612\include\xtext.h"
#include "c:\tc\xlib612\include\xbmtools.h"
#include "c:\tc\xlib612\include\xpbitmap.h"

#define VERSION 0.10
#define CR 0x0A

//Standard boolean type
typedef enum {TRUE = 1, FALSE = 0} boolean;

//STRUCTURES
typedef struct RBG_color_typ {
       unsigned char red, green, blue;
     } RGB_color, *RGB_color_ptr;


typedef struct pcx_header_typ {
        char manufacturer;
        char version;
        char encoding;
        char bits_per_pixel;
        int x,y;
        int width,height;
        int horz_res;
        int vert_res;
        char ega_palette[48];
        char reserved;
        char num_color_planes;
        int bytes_per_line;
        int palette_type;
        char padding[58];
  } pcx_header, *pcx_header_ptr;


typedef struct pcx_picture_typ {
	pcx_header header;
	RGB_color palette[256];
	char far *buffer;
  } pcx_picture, *pcx_picture_ptr;


typedef struct pbm_picture_typ {
	unsigned int width, height;
	unsigned int image_size;
	char far *data;
  } pbm_picture, *pbm_picture_ptr;


//Procedure/function prototypes
    void bug           (char *string, char *filename);
    void chrcat        (char *buf, const char ch);
    void display_help  (void);
unsigned get_filesize  (const char *filename);
     int find_color    (char *pal);
 boolean if_exist      (const char *filename);
    void int_to_hex    (unsigned int i, char *buf);
 boolean load_config   (char *filename);
 boolean load_pcx      (char *filename, pcx_picture_ptr image, char *pal);
 boolean load_pal      (char *pal, char *file);
 boolean load_pbm      (pbm_picture_ptr picture_ptr, char *file_ptr);
 boolean load_font     (char *userfont);
    void long_to_hex   (unsigned long i, char *buf);
    void put_pcx       (int x, int y, unsigned int width, unsigned int height, char far *pic);
 boolean save_pal      (char *pal, const char *filename);
 boolean save_pbm      (char *filename, pbm_picture_ptr pic);
 boolean save_pcx      (pcx_picture_ptr pic, char *pal, char *filename);

char pal_path[80] = ".\\";
char pbm_path[80] = ".\\";
char pcx_path[80] = ".\\";
char bak_path[80] = ".\\";
int c;


//========= Notifies User of a bug/error ====================================
void bug(char *string, char *filename) {
  /* General error message routine notifying user of an error */

  x_text_mode(); //Switch to text mode

  clrscr();
  printf ("DAGPIC.C v%3.2f, 27 November 1996, Dave Humphrey\n", VERSION);
  printf ("BUG: %s\n", string);
  if (filename != NULL) printf ("Filename = %s\n", filename);
  printf ("\n\n");
  _exit(1); //Exit program
 }
//========= End of procedure bug() ==========================================


//========= Appends a character to end of string ============================
void chrcat(char *buf, const char ch) {
  int i = strlen(buf);

  *(buf + i + 1) = '\0';
  *(buf + i) = ch; }
//========= End of procedure chrcat() =======================================


//========= Displays a simple help screen ===================================
void display_help(void) {
  printf ("\n");
  printf ("PCX2PBM v%3.2f  Copyright (c) 1996 - Dave Humphrey\n", VERSION);
  printf ("Converts PCX to PBM and vice-versa.\n\n");

  printf ("  PCX2PBM filename [options]\n\n");

  printf ("  Options...\n");
  printf ("         filename - The PBM file you wish to convert\n");
  printf ("      /B:PCX file - The PCX file you wish to convert\n");
  printf ("     /2[pcx, pbm] - Convert PBM-PCX or PCX-PBM\n");
  printf ("     [/P:palette] - Saves the palette from PCX's\n");
  printf ("             [/D] - Display image, otherwise no output to screen\n");

  printf ("Bugs/comments etc... can be E-Mailed to: aj589@freenet.carleton.ca\n\n");
 }
//========= End of procedure display_help() =================================


//========= Finds the 'whitest' in palette Color for Box+Text ===============
int find_color(char *pal) {
  /* Looks for the color with the highest average in the current palette.
   * This color is returned and used for printing text etc...*/

  int y, r, b, g, avg;
  int best_c = 255, max_avg = 0;

  for (y = 0; y < 255; y++) {  //Look through all colours in paleete
	//Read the 3 color values, red, green, and blue
    r = (int) *pal;
    pal++;
    g = (int) *pal;
    pal++;
    b = (int) *pal;
    pal++;

    avg = (r + g + b) / 3; //Compute the average

    if (avg > max_avg) { //Compare with maximum average
      max_avg = avg;
      best_c = y;
     }
   }

  return(best_c); }
//========= End of function find_color() ====================================


//========= Returns the size of the file ====================================
unsigned int get_filesize(const char *filename) {
  FILE *f;
  struct stat file_stat;

  if (!if_exist(filename)) return(0);
  f = fopen(filename, "r");
  fstat(fileno(f), &file_stat);
  fclose(f);
  return((unsigned int)file_stat.st_size); }
//========= End of function get_filesize() ==================================


//========= Returns TRUE if file exists =====================================
boolean if_exist(const char *filename) {
  FILE *f;
		       //Attempt to open file
  if ((f = fopen(filename, "r")) == NULL) return(FALSE);
  fclose(f);	   //File was opened and therefore exists, close it
  return(TRUE); }
//========= End of function if_exist() ======================================


//========== Converts a Int to Hexadecimal String ===========================
void int_to_hex (unsigned int i, char *buf) {
  unsigned int rem, div;

  rem = i/256;
  div = i - rem * 256;
  *(buf + 1) = (unsigned char) rem;
  *(buf) = (unsigned char) div;
  *(buf + 2) = '\0';
 }
//========== End of procedure int_to_hex() ==================================


//========== Attempts to Load and Parse a Config file =======================
boolean load_config(char *filename) {
  FILE *f;
  char ch, buffer[101], *temp_ptr, buffer1[101], *temp_ptr1;
  char command[21], arg[81];
  boolean done = FALSE;

  if ((f = fopen(filename, "rt")) == NULL) return(FALSE);

  do {
    buffer[0] = '\0';

    do {
     ch = fgetc(f);
     chrcat(&buffer[0], ch);
    } while (ch != CR && strlen(buffer) < 100 && ch != EOF);

    if (ch == EOF) {
      done = TRUE;
      buffer[strlen(buffer) - 1] = CR;
     }
    else if (ch == CR)
      buffer[strlen(buffer) - 1] = 0;

    temp_ptr = &buffer[0];

    if (*temp_ptr != '#') {
      while (*temp_ptr == 32 && *temp_ptr != CR)  //Remove leading spaces
	temp_ptr++;

      if (*temp_ptr != CR) {
	strcpy(buffer1, temp_ptr);
	temp_ptr1 = &buffer[0];

	while (*temp_ptr1 != 32 && *temp_ptr1 != CR)
	  temp_ptr1++;

	if (*temp_ptr1 != CR) {
	  *temp_ptr1 = 0;
	  strcpy(command, buffer);
	  temp_ptr1++;

	  while (*temp_ptr1 == 32 && *temp_ptr1 != CR)  //Remove mid spaces
	    temp_ptr1++;

	  if (*temp_ptr1 != CR) {
	    strcpy(buffer, temp_ptr1);

	    while (*temp_ptr1 != 32 && *temp_ptr1 != CR)
	      temp_ptr1++;

	     *temp_ptr1 = 0;
	     strcpy(arg, buffer);

	     if (strcmp(arg, ".") == 0) arg[0] = 0;

	     if (strcmpi(command, "pal") == 0)
	       strcpy(pal_path, arg);
	     else if (strcmpi(command, "pbm") == 0)
	       strcpy(pbm_path, arg);
	     else if (strcmpi(command, "pcx") == 0)
	       strcpy(pcx_path, arg);
	     else if (strcmpi(command, "bak") == 0)
	       strcpy(bak_path, arg);
	     else if (strcmpi(command, "end") == 0)
	       done = TRUE;
	   }
	 }
       }
     } //End of if != '#'
  } while (!done);

  fclose(f);
  return(TRUE); }
//========== End of function load_config ====================================


//========= Loads the game pallette into memory =============================
boolean load_pal (char *pal, char *file) {
  int count;
  FILE *f;

  if ((f = fopen (file, "rb")) == NULL) bug("Could not open palette file!", file);

  for (count = 1; count < 256*3; count++) {
    *pal = fgetc(f);
     pal = pal + 1; }

  fclose(f);
  return (TRUE); }
//========= End of procedure load_pal() =====================================


//========= Loads a picture named *file_ptr into picture_ptr ================
boolean load_pbm(pbm_picture_ptr picture_ptr, char *file_ptr) {
  int count;
  unsigned image_size;
  char *data_ptr;
  FILE *f;

  if ((f = fopen (file_ptr, "rb")) == NULL) return (FALSE);

  picture_ptr->width = 4*fgetc(f);
  picture_ptr->height = fgetc(f);
  image_size = picture_ptr->height*picture_ptr->width;
  if ((picture_ptr->data = (char *) farmalloc(image_size + 3)) == NULL) return (FALSE);
  data_ptr = picture_ptr->data;

  *data_ptr = picture_ptr->width/4;
  data_ptr++;
  *data_ptr = picture_ptr->height;
  data_ptr++;


  for (count = 1; count <= image_size; count++) {
    *data_ptr = fgetc(f);
    data_ptr++; }

  fclose(f);
  return (TRUE); }
//========== End of load_pbm() ==============================================


//========== Loads a user defined font into memory ==========================
boolean load_font (char *userfont) {
  FILE *f;
  char font_file[16] = "smalthin.fnt", ch;

  if ((f = fopen (font_file, "rb")) == NULL) return (FALSE);

  do {
    ch = fgetc (f);
    *userfont = ch;
    userfont++;
  } while (ch != EOF);

  fclose (f);
  return (TRUE); }
//========== End of procedure load_font() ===================================


//========= Loads a PCX into memory and converts it to IMG structure ========
boolean load_pcx(char *filename, pcx_picture_ptr image, char *pal) {
// this function loads a pcx file into a picture structure, the actual image
// data for the pcx file is decompressed and expanded into a secondary buffer
// within the picture structure, the separate images can be grabbed from this
// buffer later.  also the header and palette are loaded

  FILE *fp;
  int num_bytes, i, row_diff, row, bytes;
  unsigned int count, image_size;
  unsigned char data;
  char far *temp_buffer;

	//open the file
  if ((fp = fopen(filename, "rb")) == NULL)
    bug("Could not open PCX file!", filename);

	//load the header
  temp_buffer = (char far *)image;

  for (i = 0; i < 128; i++) {
    temp_buffer[i] = (char)getc(fp);
   } // end for index

  image->header.width++;
  image->header.height++;

	// load the data and decompress into buffer
  count = 0;
  i = 0;

  if ((image->buffer = (char far *) farmalloc(image->header.width * image->header.height + 3)) == NULL)
    bug("Could not allocate PCX buffer!", NULL);

  image->buffer[0] = (unsigned char) image->header.width;
  image->buffer[1] = (unsigned char) image->header.height;
  row_diff = image->header.bytes_per_line - image->header.width;
  image_size = image->header.width * image->header.height;
  row = 0;
  bytes = 0;

  while(count <= image_size) {

	// is this a rle?
    if (row_diff > 0 && i >= image->header.width) {  //Remove row padding
      if (i == image->header.bytes_per_line) {
	i = 0;
	row++;
	count--;
       }
      else if (i >= image->header.width) {
	i = 0;
	row++;

	while (i != row_diff) {
	  data = (unsigned char) getc(fp);
	  bytes++;

	  if (data >= 192) {
	    data = (unsigned char)getc(fp);
	    bytes++;
	   }

	  i++; }

	i = 0;
       }

     }
    else {
	// get the first piece of data
      data = (unsigned char) getc(fp);
      bytes++;

      if (data >= 192) {

		// how many bytes in run?
	num_bytes = data - 192;

		// get the actual data for the run
	data  = (unsigned char)getc(fp);
	bytes++;

	// replicate data in buffer num_bytes times
	while(num_bytes-- > 0) {
	  *(image->buffer + count + 2) = data;
	  count++;
	  i++;
	 } // end while

       } // end if rle
      else { // actual data, just copy it into buffer at next location
	*(image->buffer + count + 2) = data;
	count++;
	i++;
       } // end else not rle
     }//End of else not row padding
   } // end while

  fseek(fp,-768L,SEEK_END);

		//load the pallete into the palette
  for (i = 0; i < 256; i++)    {
	//get the red component
    image->palette[i].red   = (unsigned char)(getc(fp) >> 2);
    *pal = image->palette[i].red;
    pal++;

	//get the green component
    image->palette[i].green = (unsigned char)(getc(fp) >> 2);
    *pal = image->palette[i].green;
    pal++;

	//get the blue component
    image->palette[i].blue  = (unsigned char)(getc(fp) >> 2);
    *pal = image->palette[i].blue;
    pal++;
  } //end for i

  return(TRUE); }
//========== End of function load_pcx() =====================================



//========== Converts a Long Int to Hexadecimal String ======================
void long_to_hex (unsigned long i, char *buf) {
  unsigned long rem, div;

  rem = i/256/256/256;
  div = i - rem * 256 * 256 * 256;
  *(buf + 3) = (unsigned char) rem;

  rem = div/256/256;
  div = div - rem * 256 * 256;
  *(buf + 2) = (unsigned char) rem;

  rem = div/256;
  div = div - rem * 256;
  *(buf + 1) = (unsigned char) rem;
  *(buf) = (unsigned char) div;
  *(buf + 4) = '\0';
 }
//========== End of procedure long_to_hex() =================================


//========== Puts a PCX Image onto the Screen ===============================
void put_pcx (int x, int y, unsigned int width, unsigned int height, char far *pic) {
  int x1, y1, i = 0;
  pic += 2; //Skip height+width info...

			//Print out the image
  for (y1 = y; y1 < y + height; y1++)
    for (x1 = x; x1 < x + width; x1++, i++, pic++)
      x_put_pix(x1, y1, VisiblePageOffs, *pic);
  //Replace with put_pixel routine if not using XLIB library
 }
//========== End of procedure put_pcx() =====================================


//========= Saves the game pallette to disk =================================
boolean save_pal (char *pal, const char *filename) {
  int count;
  char ch;
  FILE *f;

  if (if_exist(filename)) {
    printf ("\nFile %s already exists. Overwrite? [y/n]?", filename);

    do {
       ch = toupper(getch());
    } while (ch != 'Y' && ch != 'N' && ch != 27);

    printf("\n");
    if (ch != 'Y') return(FALSE);
   } //End of if file exists

  if ((f = fopen (filename, "wb")) == NULL) return(FALSE);

  for (count = 0; count < 256*3; count++) {
    fputc(*pal, f);
    pal = pal + 1; }

  fclose(f);
  return (TRUE); }
//========= End of procedure load_pal() =====================================


//========== Saves a PBM - planer bitmap ====================================
boolean save_pbm(char *filename, pbm_picture_ptr pic) {
  FILE *f;
  unsigned int i;
  char *data_ptr, ch;

  if (if_exist(filename)) { //Does file already exist?
    printf ("\nFile %s already exists. Overwrite [y/n]?", filename);

    do {
      ch = toupper(getch());
    } while (ch != 'Y' && ch != 'N' && ch != 27);

    printf("\n");
    if (ch != 'Y') return(FALSE);
   }
			       //Overwrite file for writing new data
  if ((f = fopen(filename, "wb")) == NULL) return(FALSE);
  data_ptr = pic->data;

  for (i = 0; i < pic->image_size + 2; i++) {
    fputc(*data_ptr, f);
    data_ptr++; }

  fclose(f);
  return(TRUE); }
//========== End of function save_pbm() =====================================


//========== Saves pcx to disk ==============================================
boolean save_pcx (pcx_picture_ptr pic, char *pal, char *filename) {
  /* I got some of this from some pcx source code file but alot from
   * actually looking at a pcx file.  There are a few numbers near the
   * beginning which I don't know what they are, and a few other things
   * which I don't understand, but for the most part it works...
   */
  int x, y = 1, num;
  unsigned int image_size;
  char buffer[80], pre, *temp_ptr, ch;
  FILE *f;

		//Attempt to open file for writing to
  if (if_exist(filename)) {
    printf ("\nFile %s already exists. Overwrite? [y/n]?", filename);

    do {
       ch = toupper(getch());
    } while (ch != 'Y' && ch != 'N' && ch != 27);

    printf("\n");
    if (ch != 'Y') return(FALSE);
   } //End of if file exists

  if ((f = fopen(filename, "wb")) == NULL) return(FALSE);
  fputc(10, f);
  fputc(5, f);
  fputc(1, f);  //Encoding?
  fputc(8, f);

  fputc(0, f);
  fputc(0, f);
  fputc(0, f);
  fputc(0, f);


  int_to_hex(pic->header.width - 1, &buffer[0]);   //Write Width, height
  int_to_hex(pic->header.height - 1, &buffer[2]);
  fwrite(buffer, sizeof(char), 4, f);

  int_to_hex(360, &buffer[0]);
  fwrite(buffer, sizeof(char), 2, f);
  fwrite(buffer, sizeof(char), 2, f);

  for (x = 0; x < 48; x++)
    fputc (0, f); //EGA Palette

  fputc(0, f);
  fputc(1, f); //Color planes?

  int_to_hex(pic->header.width, &buffer[0]); //Write Width - Bytes/line
  fwrite(buffer, sizeof(char), 2, f);

  fputc (1, f);  //256 color
  fputc (0, f);
  fputc (0, f);

  fputc(4, f);
  fputc(0, f);
  fputc(3, f);

  for (x = 0; x < 54; x++)
    fputc(0, f);  //Padding

  temp_ptr = (pic->buffer + 2);
  image_size = pic->header.width * pic->header.height;
  pre = *temp_ptr;
  temp_ptr++;

  for (x = 0; x < image_size - 1; x++) {
    num = 1;

    while (*temp_ptr == pre && num < 63 && y != pic->header.width) {
      temp_ptr++;
      num++;
      x++;
      y++;
     }

    if ((unsigned char)pre < 192 && num == 1)
      fputc(pre, f);
    else if (num == 1) {
      fputc(193, f);
      fputc(pre, f);
     }
    else { //RLE...
      fputc((char)(192+num), f);
      fputc(pre, f);
     }

    if (y == pic->header.width) y = 0;
    pre = *temp_ptr;
    temp_ptr++;
    y++;
 }

  fputc(0x0C, f);  //?

    //Write palette data
  for (x = 0; x < 256*3; x++) {
    fputc((*pal)*4, f);
    pal++;  }

  fclose(f);
  return(TRUE); }
//========== End of procedure save_pcx() ====================================


//========== Begin main program =============================================
int main (int argv, char *argc[]) {
  pbm_picture picture;	//Pointer to hold picture data
  pcx_picture pcx_pic;
  char *temp_ptr;   //Temp variables
  char *pal, pal_filename[80];  //Palette pointer and filename
  char *smalthin; 	   //Hold font data
  char filename[80], pcx_filename[80];  //pcx filename and file to load
  char bak_filename[80];	  //Temp string, backup filename
  int i;	          //Loop counters
  boolean pcx_file = FALSE, pbm_file = FALSE, display = FALSE;  //Toggles
  boolean convert_to_pcx = FALSE, pal_file = FALSE;

  load_config("pcx2pbm.cfg");
  strcpy(pal_filename, pal_path);
  strcat(pal_filename, "default.pal");
  strcpy(filename, "NULL");
  strcpy(pcx_filename, "NULL");

  if (argv > 1) { //Make sure there are arguments
			      //Check ARGs for commands
    for (i = 1; i < argv;i ++) {
				       //Palette
      if ((temp_ptr = strstr(strupr(argc[i]), "/P:")) != NULL) {
	if (strlen(argc[i]) > 3) {
	  strcpy(pal_filename, pal_path);
	  strcat(pal_filename, temp_ptr + 3);  //Move to start of palette filename
	  pal_file = TRUE;
	 }
       }
					//Don't display image
      else if ((temp_ptr = strstr(strupr(argc[i]), "/D")) != NULL && !display) {
	display = TRUE;
       }
					//Convert to PBM/PCX?
      else if ((temp_ptr = strstr(strupr(argc[i]), "/2")) != NULL && !convert_to_pcx) {
	if (strlen(temp_ptr) > 2) { //Make sure we have a proper string...
	  temp_ptr += 2;

	  if (stricmp(temp_ptr, "pcx") == 0)
	    convert_to_pcx = TRUE;
	  else if (stricmp(temp_ptr, "pbm") == 0)
	    convert_to_pcx = FALSE;
	 }
       } //End of convert pcx
					//Specify PCX name
      else if ((temp_ptr = strstr(strupr(argc[i]), "/B:")) != NULL && !pcx_file) {

	if (strlen(argc[i]) > 3) {
	  strcpy(pcx_filename, pcx_path);
	  strcat(pcx_filename, temp_ptr + 3);
	  pcx_file = TRUE;
	 }
       } //end of if /B:
				//Help screen
      else if (strchr(argc[i], '?') != NULL) {
	display_help();
	exit(0);
       }
      else if (!pbm_file) { //Must be image filename
	strcpy(bak_filename, bak_path);
	strcat(bak_filename, argc[i]);
	strcpy(filename, pbm_path);
	strcat(filename, argc[i]);
	pbm_file = TRUE;
       }
     } //End of for arg loop

    if (display && pbm_file && !pcx_file) convert_to_pcx = TRUE;

    if ((pal = (char *) malloc (800)) == NULL) bug("Could not allocate 800 Bytes!", NULL);

    if (!convert_to_pcx) { //Convert from PCX to PBM...

      if (pcx_file) { //Load PCX
	if (!load_pcx(pcx_filename, &pcx_pic, pal)) bug("Failed to read PCX file!", pcx_filename);

	if (display) {
	  if ((smalthin = (char *) malloc(800)) == NULL) bug("Could not allocate 800 Bytes!", NULL);
	  if (!load_font(smalthin)) bug("Could not load font file!", NULL);
	  c = find_color(pal);
	  if (x_set_mode (8, 360) == -1) bug("Error: Could not initialize graphics mode!", NULL);
	  x_text_init();      //Setup the text functions
	  x_register_userfont(smalthin);
	  x_set_font(2);
	  x_put_pal_raw ((unsigned char *) pal, 256, 0);
	  temp_ptr = &pcx_pic.buffer[0];
	  x_rect_fill(0, 0, pcx_pic.header.width + 2, pcx_pic.header.height + 2, VisiblePageOffs, c);   //Display image bounding box
	  put_pcx (1, 1, pcx_pic.header.width, pcx_pic.header.height, temp_ptr);

	  x_printf(1, 180, VisiblePageOffs, c, "%s - %d x %d", pcx_filename,
		   pcx_pic.header.width, pcx_pic.header.height);

	  x_printf (1, 190, VisiblePageOffs, c, "Press any key to Continue....");

	  getch();
	  x_text_mode();
	  free (smalthin);
	 }
		       //Make sure we have a filename to convert to
	if (!pbm_file) bug("Must specify PBM file to save PCX as!", NULL);
			//Allocate memory for PBM
	if ((picture.data = (char far *) farmalloc(pcx_pic.header.width * pcx_pic.header.height + 3)) == NULL) bug("Could not allocate PBM picture!", NULL);
	picture.image_size = pcx_pic.header.width * pcx_pic.header.height;
	picture.width = pcx_pic.header.width;
	picture.height = pcx_pic.header.height;
	if (x_bm_to_pbm(&pcx_pic.buffer[0], picture.data) != 0) bug("Failed to convert PCX to PBM!", pcx_filename);

	if (save_pbm(filename, &picture))
	  printf("\n%s successfully converted to %s.\n", pcx_filename, filename);
	else
	  printf("\n%s WAS NOT successfully converted to %s!\n", pcx_filename, filename);

	if (pal_file) {
	  if (save_pal(pal, pal_filename))
	    printf("\n%s's palette successfully converted to %s.\n", pcx_filename, pal_filename);
	  else
	    printf("\n%s's palette WAS NOT successfully converted to %s!\n", pcx_filename, pal_filename);
	 }

	printf("\n");
       }
      else
	bug("Must specify PCX file to convert!", NULL);

     } //End of if (convert_pcx)
    else { //Convert from PBM to PCX
      if (pbm_file) { //Load PBM and Pal
	if (!load_pbm(&picture, filename)) bug("Could not load image!", filename);
	if (!load_pal(pal, pal_filename)) bug("Could not load palette!", pal_filename);   //Load the palette

	if (display) {
	  if ((smalthin = (char *) malloc(800)) == NULL) bug("Could not allocate 800 Bytes!", NULL);
	  if (!load_font(smalthin)) bug("Could not load font file!", NULL);
	  c = find_color(pal);
	  if (x_set_mode (8, 360) == -1) bug("Error: Could not initialize graphics mode!", NULL);
	  x_text_init();      //Setup the text functions
	  x_register_userfont(smalthin);
	  x_set_font(2);
	  x_put_pal_raw ((unsigned char *) pal, 256, 0);
	  x_rect_fill(0, 0, picture.width + 2, picture.height + 2, VisiblePageOffs, c);   //Display image bounding box
	  x_put_pbm(1, 1, VisiblePageOffs, (unsigned char *) picture.data);

	  x_printf(1, 180, VisiblePageOffs, c, "%s - %d x %d", filename,
		   picture.width, picture.height);

	  x_printf (1, 190, VisiblePageOffs, c, "Press any key to Continue....");

	  getch();
	  x_text_mode();
	  free (smalthin);
	 }

	if (!pcx_file) bug("Must specify PCX file to save as!", NULL);

	if ((pcx_pic.buffer = (char far *) farmalloc(picture.width * picture.height + 3)) == NULL) bug("Could not allocate PCX buffer!", NULL);
	pcx_pic.header.width = picture.width;
	pcx_pic.header.height = picture.height;
	if (x_pbm_to_bm(picture.data, pcx_pic.buffer) != 0) bug("Failed to convert PBM to PCX!", pcx_filename);

	if (save_pcx(&pcx_pic, pal, pcx_filename))
	  printf("\n%s successfully converted to %s.\n\n", filename, pcx_filename);
	else
	  printf("\n%s WAS NOT successfully converted to %s!\n\n", filename, pcx_filename);
       }
      else
	bug("Must specify PBM file to convert!", NULL);
     } //End of else (!convert_pcx)

    farfree (picture.data);
    farfree (pcx_pic.buffer);
    free (pal);  }
  else { //No arguments
    display_help();
   }

  printf ("Farheapcheck() = %d\n\n", farheapcheck());
  return (TRUE); }
//========== End of program =================================================