/* * Colour.c - a program for manipulating the colours of screens. * * Written because I like one set of colours in a CLI and another in * my terminal window, and can't always afford the memory for another * screen. Plus, I like a more direct way of changing colours than * twiddling a bunch of slider gadgets (although that way has its uses * too, so I include the capability). Lastly, Americans don't know * how to spell "colour" :-). * * Features include: * - save all colours from a given screen * - load a set of colours into a given screen * - set a particular colour register in a given screen * - adjust screen colours interactively (OPTIONAL) * * Copyright 1987, John Russell * * 5 Alderdice Place * St. John's, Newfoundland * Canada A1B 2P8 * (709) 726-7847 * * Freely redistributable. */ /* Manx users compile with "+l" just in case */ /* These includes might not be enough, I use precompiled includes. */ /* anything to do with screens & viewports may be required */ #include #include #include #include "ctype.h" #define LOAD 1 #define SAVE 2 #define SET 3 #define ADJUST 4 /* if "fancy" is defined, you have the option to adjust on-the-fly */ #define FANCY 1 /* debug = "puts" to enable tracing, leave blank to disable */ #define debug(x) struct IntuitionBase *IntuitionBase=NULL; struct GfxBase *GfxBase=NULL; char *usage = "\n\ Bad syntax.\n\n\ Usage 1: colour load [from] .\n\ Usage 2: colour save [to] .\n\ Usage 3: colour set index R G B.\n\ Usage 4: colour adjust .\n\n\ Note - Specify screen by first word of title (case doesn't matter).\n\ Note - Load file is searched for as \"file\" and \"s:file.col\".\n"; main(argc,argv) int argc; char *argv[]; { struct Screen *screen; /* which screen to consider */ struct ViewPort *vp; /* controlling viewport for screen */ FILE *fp; /* for loading & saving */ short good_args = 0; /* right # arguments for syntax? */ short mode = 0; /* what type of command is it? */ int r,g,b; int i,n,fname,depth; /* depth == number of colours in screen */ UWORD colour; /* I only remember these typedefs */ struct ColorMap *map; /* when reading includes :-) */ char name[80]; /* check for valid arguments and commands */ if (argc < 3) /* always need at least 3 */ { puts(usage); exit(0); } else if (!compare(argv[1],"load")) { debug("Asked to load a colour set."); mode = LOAD; if (argc == 4 || (!compare(argv[3],"from") && argc == 5)) good_args = 1; } else if (!compare(argv[1],"save")) { debug("Asked to save a colour set."); mode = SAVE; if (argc == 4 || (!compare(argv[3],"to") && argc == 5)) good_args = 1; } else if (!compare(argv[1],"set")) { debug("Asked to set a single colour."); mode = SET; if (argc == 7) good_args = 1; } #ifdef FANCY else if (!compare(argv[1],"adjust")) { debug("Asked to adjust screen colours."); mode = ADJUST; if (argc == 3) good_args = 1; } #endif fname = argc - 1; /* argv[fname] = file for load & save */ if (!good_args) { puts(usage); exit(0); } debug("Arguments are legal."); if (! (IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",33L))) { puts("Please use Kickstart/Workbench V1.2 for latest Intuition."); exit(0); } if (! (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",33L))) { puts("Please use Kickstart/Workbench V1.2 for latest Graphics."); exit(0); } screen = IntuitionBase->FirstScreen; /* the target screen is found when the first word of the title matches the 2nd argument specified, OR if the 2nd argument is -null, the first screen with NO title is matched (eg the DPaint screen) */ LockIBase(NULL); /* prevent window list from changing while in loop */ while (screen) /* do all screens */ { if (!compare(argv[2],screen->Title) || ((screen->Title == NULL) && (!compare(argv[2],"-null")))) { UnlockIBase(NULL); debug("Found the indicated screen."); vp = &screen->ViewPort; /* don't like 'em much myself */ map = vp->ColorMap; depth = 1 << screen->BitMap.Depth; /* no easier way? */ switch (mode) { case SET: i = atoi(argv[3]); /* colour index */ r = atoi(argv[4]); /* RGB values */ g = atoi(argv[5]); b = atoi(argv[6]); if (i < depth) { SetRGB4(vp,i,r,g,b); debug("Set single colour."); } else puts("Illegal colour index for this screen."); break; case LOAD: /* (LA Law is on in the background) */ /* search current directory and S: for file */ /* look for for file as "file" and "s:file.col" */ if (!(fp = fopen(argv[fname],"r"))) { /* Boy do I hate C string functions! */ strcpy(name,"s:"); strcat(name,argv[fname]); strcat(name,".col"); debug("Searching for file in S: directory."); fp = fopen(name,"r"); } if (!fp) { puts("Unable to open load file!"); goto QUIT; } debug("Opened file successfully."); /* This is an *ugly* loop condition! */ for (i=0; (i < depth) && (fscanf(fp,"%d %d %d\n",&r,&g,&b)==3); i++) { SetRGB4(vp,i,r,g,b); debug("Set a colour."); } fclose(fp); break; case SAVE: fp = fopen(argv[fname],"w"); if (!fp) { puts("Unable to open save file!"); goto QUIT; } for (i=0; i < depth; i++) { colour = GetRGB4(map,i); /* each colour component encoded by 4 bits */ r = (colour & 0xf00) >> 8; g = (colour & 0x0f0) >> 4; b = (colour & 0x00f); fprintf(fp,"%d %d %d\n",r,g,b); debug("Saved a colour."); } fclose(fp); break; #ifdef FANCY case ADJUST: ScreenToFront(screen); DoColorWindow(screen); /* I can't take credit for */ break; /* this section */ #endif default: debug("Illegal instruction mode."); break; } goto QUIT; /* only match 1 screen */ } screen = screen->NextScreen; } UnlockIBase(NULL); /* didn't find the screen at all */ debug("Didn't find indicated screen."); QUIT: CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); } /* case-insensitive string comparison, with \0 and space as end conditions */ compare(string1,string2) char *string1,*string2; { while ((*string1 != '\0') && (*string1 != ' ')) { if (toupper(*(string1++)) != toupper(*(string2++))) return(1); } return(0); /* return weird values like strcmp() */ }