/***************************************************************************
 *
 * loadcolor.c
 *
 */

#pragma extend

/*
 * The standard iC include files are first
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <udi.h>


#include <rmxc.h>
#include <rmxerr.h>

#include <rgi.h>

static char ucginame[256];
static TOKEN cgiconn;
static char cgibuff[1024];

static EXCEPTIONSTRUCT noexcept = {0,0,0};

static CGIDevice cgidev;
static char defcginame[] = ":VDI:";
static char *cginame = defcginame;
static int cgiopen = 0;
static int opdone = 0;

static char defclrtable[768] = {
#include <deftab.h>
};

usage( void )
{
  fprintf(stderr,
     "usage: loadcolor -c dev -i in_file -s seed -r rv -g gv -b bv -h\n");
  fprintf(stderr,
     "                 -o out_file\n\n");
  fprintf(stderr,
     "   if -c is specified then dev is used as the graphics pathname.\n");
  fprintf(stderr,
     "      :VDI: is used for dev if -c is not specified.\n");
  fprintf(stderr,
     "   if -i is specified then in_file is read to obtain the table.\n");
  fprintf(stderr,
     "      if in_file is not specified then stdin is read.\n");
  fprintf(stderr,
 "   if -o is specified then the current color table is printed on out_file.\n");
  fprintf(stderr,
     "      if out_file is not specified then stdout is assumed.\n");
  fprintf(stderr,
     "   if -s is specified then seed is used to generate a random table.\n");
  fprintf(stderr,
     "      if seed is not specified, then 0 is used.\n");
  fprintf(stderr,
     "   if -r is specified then the red table is loaded with rv\n");
  fprintf(stderr,
     "      if rv is not specified, then 0-255 is used.\n");
  fprintf(stderr,
     "   if -g is specified then the green table is loaded with gv\n");
  fprintf(stderr,
     "      if gv is not specified, then 0-255 is used.\n");
  fprintf(stderr,
     "   if -b is specified then the blue table is loaded with bv\n");
  fprintf(stderr,
     "      if bv is not specified, then 0-255 is used.\n");
  fprintf(stderr,
     "   if -h is specified, this help message is printed on stderr.\n");
  fprintf(stderr,
     "   With no arguments, a compiled-in color table is loaded to :RGI:.\n");
  fprintf(stderr,
     "   All args are positional (including -o), so '-i -o' and '-o -i'\n");
  fprintf(stderr,
     "   may produce differing results depending upon the input file.\n");
  fprintf(stderr,
     "   The depth of the current bitmap on the output device determines\n");
  fprintf(stderr,
     "   how many entries are actually modified - :RGI: should be 8 BPP.\n");

  exit(1);
}

getdev( void )
{
  WORD except = 0; 
  Word rgi_except;

  if (cgiopen == 0) 
  {
    /* get the cgi device connection */  
    cgiconn = rqsattachfile((STRING *)udistr(ucginame, (const char *)cginame),
                            &except);
    if (except != EOK) 
    {

      fprintf(stderr, "Error %d Attaching Output File: %s\n",except,cginame);
      dqexit((WORD)1);
    }
    rqsopen(cgiconn,  (BYTE)3, (BYTE)0, &except);
    if (except != EOK) 
    {
      fprintf(stderr, "Error %d Opening Output File: %s\n",except,cginame);
      dqexit((WORD)1);
    }

    cgidev = cgi_initialize(cgiconn, cgibuff, sizeof cgibuff, &rgi_except);
    if (rgi_except != EOK) 
    {
      fprintf(stderr, "Error %d Initializing CGI library: %s\n", rgi_except,
                      cginame);
      dqexit((WORD)1);
    }
    cgiopen = 1;
    gqdeleteallbitmaps    (cgidev);
    gqcreatebitmap(cgidev, (BitmapId)0, (DC)10, (DC)10, (RGI_Index)8);
    /* Select the bitmap for drawing to allow access to the entire color table */
    gqselectdrawingbitmap(cgidev, (BitmapId)0);
    cgi_flush(cgidev, &rgi_except);
  }
}  

void far loadcolor_error ()
{
  WORD except;
  Word rgi_except;

  /* Clean up any bitmaps/windows */
  gqdeleteallbitmaps    (cgidev);
  cgi_terminate (cgidev, &rgi_except);
  if (rgi_except != EOK) dqexit((WORD)1);
  dqclose(cgiconn,&except);
  if (except != EOK) dqexit((WORD)1);
  dqdetach(cgiconn,&except);
  if (except != EOK) dqexit((WORD)1);
  dqexit((WORD)1);
}

main(
int   argc,
char *argv[])
{
  WORD except = 0; 
  Word rgi_except;
  int i,rseed;
  FILE *fopen(), *fp, *pp;
  char cm;

  rqsetexceptionhandler(&noexcept,&except);
  dqtrapcc( (HANDLERPTRSTRUCT *) &loadcolor_error, &except);
  if (except != EOK) exit(1);


  while ((argc > 1) && (argv[1][0] == '-')) 
  {
    if (cgiopen == 1) 
    {
      /* get rid of the cgi connection */  
      cgi_terminate(cgidev, &rgi_except);
      if (rgi_except != EOK) dqexit((WORD)1);
      rqsclose(cgiconn,&except);
      if (except != EOK) dqexit((WORD)1);
      rqsdeleteconnection(cgiconn,&except);
      if (except != EOK) dqexit((WORD)1);
      cgiopen = 0;
    }

    switch (argv[1][1]) 
    {
    case 'c':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
        cginame = argv[1];
      else usage();
      getdev();
      break;
    case 'i':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
      {
        if ((fp = fopen(argv[1],"r")) == NULL) 
        {
          fprintf(stderr,"Cannot Access File %s\n",argv[1]);
          exit(1);
        }
      }
      else fp = stdin;
      for (i=0;i<sizeof(defclrtable);i+=3) 
      {
        if (fscanf(fp," %x, %x, %x",&defclrtable[i],
                                    &defclrtable[i+1],
                                    &defclrtable[i+2]) == EOF) 
         {
          fprintf(stderr,"Premature EOF on File %s\n",argv[1]);
          exit(1);
         }
      while ((cm = getc(fp)) != '\n') ;
      }
      getdev();
      gqsetcolortable(cgidev, (ColorIndex)0, (RGI_Index)  1, (void *)&defclrtable[0]);
      gqsetcolortable(cgidev, (ColorIndex)1, (RGI_Index)255, (void *)&defclrtable[3]);
      opdone = 1;
      break;
    case 'o':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
      {
        if ((pp = fopen(argv[1],"w")) == NULL) 
        {
          fprintf(stderr,"Cannot Access File %s\n",argv[1]);
          exit(1);
        }
      }
      else pp = stdout;
      for (i=0;i<sizeof(defclrtable);i+=3) 
      {
        fprintf(pp," 0x0%02.02x, 0x0%02.02x, 0x0%02.02x",
                                 defclrtable[i] & 0x0ff,
                                 defclrtable[i+1] & 0x0ff,
                                 defclrtable[i+2] & 0x0ff);
        switch (i/3) 
        {
        case 0:
           fprintf(pp,", /* Entry 0 - Start of 8BPP Color Map */\n");
          break;
        case 231:
           fprintf(pp,", /* Entry 231 - Default FIELD Color */\n");
          break;
        case 232:
           fprintf(pp,", /* Entry 232 - Default BORDER Color */\n");
          break;
        case 233:
           fprintf(pp,", /* Entry 233 - Default CURSOR Color */\n");
          break;
        case 234:
           fprintf(pp,", /* Entry 234 - Default 1BPP Color Map */\n");
          break;
        case 236:
           fprintf(pp,", /* Entry 236 - Default 2BPP Color Map */\n");
          break;
        case 240:
           fprintf(pp,", /* Entry 240 - Default 4BPP Color Map */\n");
          break;
        case 255:
           fprintf(pp,"  /* Entry 255 - End of 8BPP Color Map */\n");
          break;
        default:
           fprintf(pp,", /* Entry %d */\n",i/3);
          break;
        }
      }
      break;
    case 's':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
      {
        rseed = atoi((const char *)&argv[1][0]);
      }
      else 
      {
        rseed = 0;
        argc++; argv--;
      }
      srand((unsigned int)rseed);
      for (i=0; i<sizeof(defclrtable); i++) 
      {
        defclrtable[i] = (char) (((rand() & 0x07f80) >> 7) & 0x0ff);
      }
      getdev();
      gqsetcolortable(cgidev, (ColorIndex)0, (RGI_Index)  1, (void *)&defclrtable[0]);
      gqsetcolortable(cgidev, (ColorIndex)1, (RGI_Index)255, (void *)&defclrtable[3]);
      opdone = 1;
      break;
    case 'r':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
      {
        rseed = atoi((const char *)&argv[1][0]);
      }
      else 
      {
        rseed = -1;
        argc++;argv--;
      }
      for (i=0;i<sizeof(defclrtable);i+=3) 
      {
        defclrtable[i] = (rseed==-1?(i/3):rseed);
      }
      getdev();
      gqsetcolortable(cgidev, (ColorIndex)0, (RGI_Index)  1, (void *)&defclrtable[0]);
      gqsetcolortable(cgidev, (ColorIndex)1, (RGI_Index)255, (void *)&defclrtable[3]);
      opdone = 1;
      break;
    case 'g':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
      {
        rseed = atoi((const char *)&argv[1][0]);
      }
      else 
      {
        rseed = -1;
        argc++;argv--;
      }
      for (i=0;i<sizeof(defclrtable);i+=3) 
      {
        defclrtable[i+1] = (rseed==-1?(i/3):rseed);
      }
      getdev();
      gqsetcolortable(cgidev, (ColorIndex)0, (RGI_Index)  1, (void *)&defclrtable[0]);
      gqsetcolortable(cgidev, (ColorIndex)1, (RGI_Index)255, (void *)&defclrtable[3]);
      opdone = 1;
      break;
    case 'b':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
      {
        rseed = atoi((const char *)&argv[1][0]);
      }
      else 
      {
        rseed = -1;
        argc++;argv--;
      }
      for (i=0;i<sizeof(defclrtable);i+=3) 
      {
        defclrtable[i+2] = (rseed==-1?(i/3):rseed);
      }
      getdev();
      gqsetcolortable(cgidev, (ColorIndex)0, (RGI_Index)  1, (void *)&defclrtable[0]);
      gqsetcolortable(cgidev, (ColorIndex)1, (RGI_Index)255, (void *)&defclrtable[3]);
      opdone = 1;
      break;
    case 'h':
      usage();
      break;
    default: 
      fprintf(stderr,"Unrecognized Control: %s\n",argv[1]);
      usage();
      break;
    }
    argv++; argc--;
  }
  if ((argc > 1) && (argv[1][0] != '-')) usage();

  /* did we do anything? */
  /* note that -o will still cause a load, since we are not doing an
     an inquiry (which is probably the right thing to do, or we can hang
     if the wrong device is used)
   */
  if (opdone == 0) 
  {
      getdev();
      gqsetcolortable(cgidev, (ColorIndex)0, (RGI_Index)  1, (void *)&defclrtable[0]);
      gqsetcolortable(cgidev, (ColorIndex)1, (RGI_Index)255, (void *)&defclrtable[3]);
      cgi_flush(cgidev, &rgi_except);
  }
  /* basically we are all done - flush buffers and leave */
  if (cgiopen == 1) 
  {
    /* get rid of the cgi connection */  
    cgi_terminate(cgidev, &rgi_except);
    if (rgi_except != EOK) dqexit((WORD)1);
    rqsclose(cgiconn, &except);
    if (except != EOK) dqexit((WORD)1);
    rqsdeleteconnection(cgiconn, &except);
    if (except != EOK) dqexit((WORD)1);
    cgiopen = 0;

    dqexit((WORD)0);
  }
}
