/***************************************************************************
 *
 * showcolor.c
 *
 */

#pragma extend

/*
 * The standard iC include files are first
 */
#include <math.h>
#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;

usage( void )
{
  fprintf(stderr,
     "usage: showcolor -c cgi_dev -x x_size -y y_size -n num_color\n");
  fprintf(stderr,
     "   if -c is not specified then :VDI: is assumed.\n");
  fprintf(stderr,
     "   if -x is not specified then 320 is used.\n");
  fprintf(stderr,
     "   if -y is not specified then 240 is used.\n");
  fprintf(stderr,
     "   if -n is not specified then 16 is used.\n");
  exit(1);
}

void far showcolor_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,j,k;
  int XR,YR,N,rx,ry,bits;

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

  /* initializations for command line options */
  cginame = defcginame;
  XR = 320;
  YR = 240;
  N = 16;  /* should be a power of two... */

  while ((argc > 1) && (argv[1][0] == '-')) {
    switch (argv[1][1]) {
    case 'c':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
        cginame = argv[1];
      else usage();
      break;
    case 'x':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
        XR = atoi((const char *)&argv[1][0]);
      else usage();
      if ((XR > 640) || (XR < 0)) {
        fprintf(stderr,"X-size must be positive and cannot exceed 640.\n");
        exit(1);
      }
      break;
    case 'y':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
        YR = atoi((const char *)&argv[1][0]);
      else usage();
      if ((YR > 480) || (YR < 0)) {
        fprintf(stderr,"Y-size must be positive and cannot exceed 480.\n");
        exit(1);
      }
      break;
    case 'n':
      argv++; argc--;
      if ((argc > 1) && (argv[1][0] != '-')) 
        N = atoi((const char *)&argv[1][0]);
      else usage();
      if ((N != 2) && (N != 4) && (N != 16) && (N != 256)) {
        fprintf(stderr,"Number of Colors must be 2, 4, 16, or 256.\n");
        exit(1);
      }
      break;
    default: 
      fprintf(stderr,"Unrecognized Control: %s\n",argv[1]);
      usage();
      break;
    }
    argv++; argc--;
  }
  if ((argc > 1) && (argv[1][0] != '-')) usage();

  /* 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);
  }

  /* subdivide a rectangle R into N equal sized subrectangles r each
   * having the same ratio of X and Y dimension as R itself (preserving
   * aspect ratio), and filling R completely.
   *
   *  X(r) = X(R)/SQR(N)
   *  Y(r) = Y(R)/SQR(N)
   */
  if (N != 2) {
    rx = (int)((double)XR/sqrt((double)N));
    ry = (int)((double)YR/sqrt((double)N));
    bits = (int)(log((double)N)/log((double)2.0));
  } else {
    rx = XR/2;
    ry = YR;
    bits = 1;
  }
  gqdeleteallbitmaps    (cgidev);
  gqdeleteallwindows    (cgidev);
  gqcreatebitmap        (cgidev, (BitmapId)0, (DC)XR, (DC)YR, (RGI_Index)bits);
  gqselectdrawingbitmap (cgidev, (BitmapId)0);
  gqsetvdcextent        (cgidev, (VDC)0, (VDC)0, (VDC)XR, (VDC)YR);
  gqsetinteriorstyle    (cgidev, (RGI_Index)SOLID_INTERIOR,
                                 (RGI_Index)PERIMETER_OFF);

  for (k = 0, i = 0; ((i < XR) && (k < N)); i+=rx) {
    for (j = 0; ((j < YR) && (k < N)); j+=ry) {
      gqsetfillcolor(cgidev, (ColorIndex)k++);
      gqrectangle(cgidev, (VDC)i, (VDC)j, (VDC)(i+rx), (VDC)(j+ry));
    }
  }
  gqcreatewindow(cgidev, (WindowId)0, (BitmapId)0, (RGI_Index)255, 
                         (RGI_Index)VISIBLE, (DC)0, (DC)0, (DC)(640-XR), 
                         (DC)0, (DC)XR, (DC)YR);

  /* 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);

  dqexit((WORD)0);
}
