/* Library for writing 256-color ZSoft PCX files
   Written by Akos Domotor
   Copyright WFSH and Sapikli TM. */

#include <stdio.h>

static char VERSION_STRING[]="PCX256 v1.0.4  27/10/1998";

static char aktchar=0;
static char count=0;
static FILE *pcxfile;

#ifndef __MSDOS__
static void putw(unsigned int w, FILE *f1)
{
  putc(w&0xFF,f1);
  putc(w>>8,f1);
}
#endif

void PCXheader(FILE *pcx, int x, int y)
{
  int f;

  if (pcx==NULL) return;
  pcxfile=pcx;
  putw(0x050A,pcxfile);       /* 10 = ZSoft PCX, 5 = version */
  putw(0x0801,pcxfile);       /* 1 = encode, 8 = bits per pixel */
  putw(0x0000,pcxfile);       /* xmin */
  putw(0x0000,pcxfile);       /* ymin */
  putw(x-1,pcxfile);          /* xmax */
  putw(y-1,pcxfile);          /* ymax */
  putw(60,pcxfile);           /* hDPI */
  putw(60,pcxfile);           /* vDPI */
  for (f=0; f<48; f++) putc(f/3,pcxfile);  /* colormap */ /* not used */
  putw(0x0100,pcxfile);       /* 0 = reserved, 1 = number of planes */
  putw(x,pcxfile);            /* bytes per line */
  putw(0x0001,pcxfile);       /* paletteinfo color */
  putw(x,pcxfile);            /* hscreensize */
  putw(y,pcxfile);            /* vscreensize */
  for (f=0; f<54; f++) putc(0,pcxfile);
  count=0;
}


void endPCXline(void)
{
  if (count>0 && pcxfile!=NULL) {
    if (count>1 || aktchar>=0xc0) putc(0xc0|count,pcxfile);
    putc(aktchar,pcxfile);
    count=0;
  }
}

void putPCXdata(char c)
{
  if (pcxfile==NULL) return;
  if (aktchar==c) {
    count++;
    if (count>63) {
      count=1;
      putc(0xc0|63,pcxfile);
      putc(c,pcxfile);
    }
  }
  else {
    endPCXline();
    count=1;
  }
  aktchar=c;
}

void PCXpalette(int mode)
{
  int f;
  char rgb[3];

  if (pcxfile==NULL) return;
  putc(0x0c,pcxfile);          /* reserved */
  rgb[0]=0;
  rgb[1]=0;
  rgb[2]=0;
  switch (mode) {
    case 1: { /* Here comes "jet" palette, in blocks [0-63],[64-127],[128-191],[192-255] */
      for (f=0; f<64; f++,rgb[2]+=4) fwrite(&rgb,3,1,pcxfile);
      rgb[2]=255;
      for (f=0; f<64; f++,rgb[1]+=4) fwrite(&rgb,3,1,pcxfile);
      rgb[1]=255;
      for (f=0,rgb[2]=252; f<64; f++,rgb[0]+=4,rgb[2]-=4) fwrite(&rgb,3,1,pcxfile);
      rgb[0]=255;
      rgb[2]=0;
      for (f=0,rgb[1]=252; f<63; f++,rgb[1]-=4) fwrite(&rgb,3,1,pcxfile);
    } break;
    case 2: { /* Here comes "hsv" palette, in blocks [0-7],[8-15],... */
      for (f=0; f<32; f++,rgb[0]+=8) fwrite(&rgb,3,1,pcxfile);
      rgb[0]=255;
      for (f=0; f<32; f++,rgb[1]+=8) fwrite(&rgb,3,1,pcxfile);
      rgb[1]=255;
      for (f=0,rgb[0]=252; f<32; f++,rgb[0]-=8) fwrite(&rgb,3,1,pcxfile);
      rgb[0]=0;
      for (f=0; f<32; f++,rgb[2]+=8) fwrite(&rgb,3,1,pcxfile);
      rgb[2]=255;
      for (f=0,rgb[1]=252; f<32; f++,rgb[1]-=8) fwrite(&rgb,3,1,pcxfile);
      rgb[1]=0;
      for (f=0; f<32; f++,rgb[0]+=8) fwrite(&rgb,3,1,pcxfile);
      rgb[0]=255;
      for (f=0,rgb[2]=252; f<32; f++,rgb[2]-=8) fwrite(&rgb,3,1,pcxfile);
      rgb[2]=0;
      for (f=0; f<31; f++,rgb[1]+=8, rgb[2]+=8) fwrite(&rgb,3,1,pcxfile);
    } break;
    default: { /* Gray palette */
      for (f=0; f<255; f++) {
        putc(f,pcxfile);
        putc(f,pcxfile);
        putc(f,pcxfile);
      }
    }
  }
  putc(255,pcxfile);
  putc(255,pcxfile);
  putc(255,pcxfile);
  pcxfile=NULL;
}
