/*  SetColorTable - CLI invoked ColorTable fiddler.
    Copyright 1988 aklevin.  All rights reserved.

    Manx: cc +L, ln -lc32
*/

#include <intuition/intuitionbase.h>
#include <graphics/gfxbase.h>
#include <stdio.h>

#define INTUITION_REV	33
#define GRAPHICS_REV	33

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

/*  Error severity values:  */
#define EXIT_LOW	0
#define EXIT_MED	10
#define EXIT_HIGH	20


/*  L E A V E  - Prints the error message (if any),
                 closes any open libraries, and exits.
*/
void
leave(string, command_name, exit_val)
char *string, *command_name;
int exit_val;
{
	if (strlen(string)) fprintf(stderr, "%s: %s\n", command_name, string);
	if (GfxBase) CloseLibrary(GfxBase);
	if (IntuitionBase) CloseLibrary(IntuitionBase);
	exit(exit_val);
}	/* end leave() */


/*  U S A G E  - Gives the program parameter sumary.  */
void
usage(command_name, exit_val)
char *command_name;
int exit_val;
{
fprintf(stderr, "SetColorTable - Copyright 1988 aklevin.  All rights reserved.\n");
fprintf(stderr, "\nUsage:\n");
fprintf(stderr, "\n%s [-t \"Screen Title\"] Xrgb Xrgb Xrgb...\n", command_name);
fprintf(stderr, "    Displays the current ColorTable settings for the Workbench Screen,\n");
fprintf(stderr, "    (or the screen whose title is \"Screen Title\" if `-t' option is used)\n");
fprintf(stderr, "    then sets the ColorTable to the values given by Xrgb Xrgb Xrgb... .\n");
fprintf(stderr, "\n%s <colorfile [-t \"Screen Title\"]\n", command_name);
fprintf(stderr, "    As above, but RGB values are in file 'colorfile'.\n");
fprintf(stderr, "\n    Use \" >NIL:\" to prevent color values from being displayed.\n");
fprintf(stderr, "    Use \" >file\" to save color values for later restoration.\n");
fprintf(stderr, "    Any redirection ( <file  >file or >NIL:) MUST follow command name.\n");
fprintf(stderr, "\nX r g b <- Amount of Blue  in this color (0 to f).\n");
fprintf(stderr, "| | +----- Amount of Green in this color (0 to f).\n");
fprintf(stderr, "| +------- Amount of Red   in this color (0 to f).\n");
fprintf(stderr, "+--------- 0=Use value, 1=Skip value, 2=Skip this and all further values.\n\n");
leave("", "", exit_val);
}	/* end usage() */


/*  S E T   C O L O R   T A B L E  - Accepts RGB values from either stdin
                                     or the command line, and uses those
                                     values to alter the ColorTable for
                                     the named screen.
*/

/*  The largest ColorTable size.  */
#define TABLE_SIZE	32

main(argc, argv)
int argc;
char *argv[];
{

/*
  Variables you should know:
      from_cli- 0 if RGB values will come from stdin, 1 if from command line.
    max_colors- Maximum number of colors for this screen.
    num_colors- Counter for current number of colors.
         title- Screen Title.
*/
int argp=1, i, from_cli, max_colors=2, num_colors=0, scan_ok;
char title[81];
UWORD table[TABLE_SIZE], *tmp;
struct Screen *screen;
struct ViewPort *viewport=NULL;

/*  Set the default window title.  */
strcpy (title, "Workbench Screen");

/*  Argument parsing.  */
if (argc > 1) {
	/*  Give usage if first argument is a '?'.  */
	if (argv[argp][0] == '?') usage(argv[0], EXIT_LOW);
	if (argv[argp][0] == '-') {
		/*  Found an option.  Is it valid ('t' or 'T')?  */
		if (tolower(argv[argp][1]) == 't') {
			/*  Valid option, title is part of this argument.  */
			if (strlen(argv[argp]) > 2) strcpy(title, &argv[argp++][2]);
			else {
				/*  Valid option, title is next argument.  */
				if (argc > ++argp) strcpy(title, argv[argp++]);
				/*  No title given.  */
				else usage(argv[0], EXIT_MED);
			}  /* end else */
		}  /* end if (tolower */
		else usage(argv[0], EXIT_MED);  /*  Wasn't a valid option.  */
	}  /* end if (argv */
}  /* end if (argc */

/*  If there are still command line arguments
    to be parsed, then they must be RGB values.
*/
from_cli = (argp < argc) ? 1 : 0;

/*  Open intuition and graphics libraries.  */
IntuitionBase=(struct IntuitionBase *)
	OpenLibrary("intuition.library", INTUITION_REV);
if (IntuitionBase==NULL )
	leave("Couldn't open intuition.library.", argv[0], EXIT_HIGH);

GfxBase=(struct GfxBase *)
	OpenLibrary("graphics.library", GRAPHICS_REV);
if (GfxBase==NULL)
	leave("Couldn't open graphics.library.", argv[0], EXIT_HIGH);

/*  Find the screen with the desired title.  */
for (screen=IntuitionBase->FirstScreen; screen; screen=screen->NextScreen) 
	if (strcmp(screen->Title, title)==0) {
		viewport = &(screen->ViewPort);
		break;
	}

/*  Quit if the screen couldn't be found.  */
if (viewport==NULL) leave("Couldn't find that screen.", argv[0], EXIT_MED);

/*  Find out the maximum number of colors available.  Many thanks to
    Bryce Nesbitt and Eugene Mortimore for opening my eyes to this.  */
for (i=(int)screen->BitMap.Depth; i>1 ; i--) max_colors*=2;

/*  Print the current values, before they get changed.  */
for (i=0; i<max_colors; i++)
	printf("%04x%c", GetRGB4(viewport->ColorMap, i),
		((i<max_colors-1) ? ' ' : '\n'));

/*  Scanf the RGB values into the array 'table'.
    There are four conditions which break out of this loop:
    1) Current entry to be altered >= max_colors.
    2) EOF reached on stdin or illegal value entered.
    3) RGB values were being read from argv, and there are no more.
    4) RGB value >= 0x2000, meaning "no more entries should be altered".
*/
while ((num_colors < max_colors) && ( ! from_cli || (argp < argc))) {
	if (from_cli) scan_ok = sscanf(argv[argp++], "%04x", &tmp);
	else scan_ok = scanf("%04x", &tmp);
/*  If EOF was reached or input wasn't legal,
       don't alter this entry, or following ones.  */
	if (scan_ok == EOF || scan_ok == NULL) break;
/*  If first digit is >= 2, don't alter this entry, or following ones.  */
	if (tmp >= 0x2000) break;
/*  If first digit is >= 1, don't alter this entry.  */
	if (tmp >= 0x1000) tmp = GetRGB4(viewport->ColorMap, num_colors);
	table[num_colors++] = tmp;
}  /* end while */

/*  Alter the ColorTable.  */
LoadRGB4(viewport, &table[0], num_colors);

/*  All done.  */
leave("", "", EXIT_LOW);

}	/* end main() */

