home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-386-Vol-2of3.iso
/
b
/
bds-colr.zip
/
colormap.c
next >
Wrap
C/C++ Source or Header
|
1992-08-25
|
36KB
|
1,297 lines
/***
Colormap by Barry Solomon, Copyright 1991, 1992. Permission to copy and/or
distribute this program is hereby granted, given that recognition of my
contribution is noted.
This program displays the hardware colormap by creating a two-dimensional
grid either 16x16 or 4x4 (8 or 4 plane visuals respectivly) of little
filled rectangles of size cellwidth x cellheight. Each filled rectangle
will be filled with a unique color from the colortable.
Button Commands:
When the user depresses button 1 in a "colorcell", the color
that is displayed by that filled rectangle will be changed to cyan until
the button is released when the previous colormap will be re-installed.
The color cell id and the rgb value of that cell will be displayed.
Button1 - Highlight a colorcell
Button2 - Allocate an unallocated colorcell
Shift-Button2 - Allocate and set the color of an unallocated colorcell.
Button3 - Unallocate a colorcell previously allocated by us.
Key Commands:
'a' - cycle the colors in the installed colormap
'A' - run a single white color through the installed colormap
'd' - display the default colormap
'g' - Get all available colors and allocate
'l' - load a mixed color ramp and display
's' - show all allocated colormap entries
'S' - Unshow all allocated colormap entries
't' - toggle between a 4 and 8 bit visual and redisplay the colormap
'u' - Unget all colors that we have allocated
'q' - quit
Author Change Log
1.0 ????? 1990 Barry Initial implementation
2.0 Nov27 1990 Barry Use rectangles in leu of windows for color cells.
2.1 Dec18 1990 Barry Fix non-uninstall of mycolormap
2.2 Feb13 1991 Barry Add input arg to disable colormap swapping.
2.3 Apr19 1991 Barry Modify for true color devices
2.4 May03 1991 Barry Add in toggling for different visuals
2.5 Apr22 1992 Barry Add animation, MINCELL and lint this code.
2.6 Apr22 1992 Barry Add display of allocated colorcells
2.7 May11 1992 Barry Add allocation/deallocation of colorcells
2.8 Aug19 1992 Barry Fixed "show cells" if all cells allocated.
***/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <sys/timeb.h>
#include <stdio.h>
#define MINCELL 0 /* Lowest numbered cell to animate cmap */
#define MIN_COLOR_CELLS 15 /* Min number of colors needed to run */
#define CHAR 0
#define STRING 1
#define INTEGER 2
Display *display;
Visual *vis; /* Pointer to the current visual */
int dep; /* depth of the current visual */
GC gc, rgc; /* Graphics contexts */
Colormap dcm, *icm, *icm2; /* Default colormap and nstalled cmaps */
Colormap mycmap; /* Local colormap */
XColor colors[257]; /* Array for copying colors */
XColor LocColors[257];
Bool AllocatedCells[256];
Bool MyAllocedCells[256]; /* array of my color cells */
int dcms; /* default colormap size */
int numcells; /* Number of colors in current visual */
int cellwidth; /* Width of colorcell window */
int cellheight; /* Height of colorcell window */
int cols, rows; /* row and column loop indices */
Bool truecolor = False;
Window root, MainWin, pw, w;
int banner_height = 25; /* height of the clrmap id display */
int win_height, win_width;
int yoff, xoff; /* x & y offsets for colorcell placement */
char message[100];
int event_mask = 0;
/***************************************************** output_message */
output_message( Message, LineNumber)
/**
Display a message to the user in the banner area
**/
char *Message;
int LineNumber;
{
/*--------------------------------------------------------------------*/
XSetForeground(display, gc, 0);
if (LineNumber == 1)
XFillRectangle(display, MainWin, gc, 0, 0,
win_width, banner_height + 4);
else
XFillRectangle(display, MainWin, gc, 5, 12 * (LineNumber - 1) + 3,
win_width, 12);
XDrawImageString(display, MainWin, gc, 5, 12 * (LineNumber),
Message, strlen(Message));
XFlush(display);
}
/************************************************************ GetInput */
void GetInput( Buffer, InputType)
/**
Wait for the next KeyPress and defer all other events
and return keystring[0] in 'input'
**/
char *Buffer;
int InputType;
{
XEvent ev;
char string[20], *keystring;
KeySym key;
Bool done = False;
char lstring[133];
int lvalue = 0;
/*---------------------------------------------------------------------*/
strcpy(lstring, "");
while (!done) {
XMaskEvent(display, KeyPressMask, &ev);
XLookupString(&ev, string, 20, &key, NULL);
keystring = XKeysymToString(key);
switch (InputType) {
case CHAR:
if ((strlen(keystring) < 2) || (!strcmp(keystring, "Return"))) {
*Buffer = keystring[0];
done = True;
}
break;
case INTEGER:
if (!strcmp(keystring, "Return")) {
if (strcmp(lstring, ""))
*(int *) Buffer = lvalue;
done = True;
}
if (!strcmp(keystring, "BackSpace") && (strlen(lstring) > 0)) {
lstring[strlen(lstring) - 1] = '\0';
lvalue /= 10;
}
if ((keystring[0] >= '0') && (keystring[0] <= '9')) {
lvalue = 10 * lvalue + (keystring[0] - '0');
sprintf(lstring, "%d", lvalue);
}
break;
case STRING:
if (!strcmp(keystring, "Return")) {
strcpy(Buffer, lstring);
done = True;
}
if (!strcmp(keystring, "BackSpace") && (strlen(lstring) > 0)) {
lstring[strlen(lstring) - 1] = '\0';
}
if (!strcmp(keystring, "period")) {
sprintf(lstring, "%s.\0", lstring);
}
if (!strcmp(keystring, "slash")) {
sprintf(lstring, "%s/\0", lstring);
}
if (!strcmp(keystring, "numbersign")) {
sprintf(lstring, "%s#\0", lstring);
}
if (strlen(keystring) < 2) {
sprintf(lstring, "%s%s\0", lstring, keystring);
}
break;
} /* end switch(InputType) */
output_message( lstring, 2);
} /* end while(!done) */
}
/******************************************************* get_visual() */
Bool get_visual(depth)
/**
Get a visual of depth *depth if possible
**/
int *depth; /* The depth of the desired visual */
{
XVisualInfo *visualList;
long vmask = VisualNoMask;
XVisualInfo vinfo, *v; /* visual information */
int big_map = 0, istat;
Bool success = False;
/*--------------------------------------------------------------------*/
visualList = XGetVisualInfo( display, vmask, &vinfo, &istat);
switch (*depth) {
case 4:
for (v = visualList; v < visualList + istat; v++)
if ((v->depth == 4)&&(v->class == PseudoColor)) {
vinfo = *v;
success = True;
break;
}
break;
case 8:
for (v = visualList; v < visualList + istat; v++)
if ((v->depth == 8)&&(v->class == PseudoColor)) {
vinfo = *v;
success = True;
break;
}
break;
default:
for (v = visualList; v < visualList + istat; v++) {
if ((v->colormap_size>big_map)&&(v->class==PseudoColor)) {
big_map = v->colormap_size;
vinfo = *v;
success = True;
}
if (big_map >= 256) break;
}
}; /* end switch(depth) */
if (success) {
*depth = vinfo.depth;
vis = vinfo.visual;
numcells = vis->map_entries;
return(True);
}
else
return(False);
} /* end get_visual() */
/****************************************************** create_window */
Window create_window(parent, xpos, ypos, width, height)
/**
Create the main window
**/
Window parent;
int xpos, ypos;
int width, height;
{
Window NewWin;
int winfo_mask;
XSetWindowAttributes winfo;
XWMHints wmhints;
/*--------------------------------------------------------------------*/
winfo.background_pixmap = ParentRelative;
winfo.background_pixel = 0;
winfo.border_pixmap = CopyFromParent;
winfo.border_pixel = 0;
winfo.bit_gravity = NorthWestGravity;
winfo.win_gravity = NorthWestGravity;
winfo.backing_store = WhenMapped;
winfo.backing_planes = 0;
winfo.save_under = True;
winfo.event_mask = NoEventMask;
winfo.do_not_propagate_mask = NoEventMask;
winfo.override_redirect = False;
winfo.colormap = mycmap;
winfo_mask = CWEventMask |
CWBackingStore |
CWBorderPixel |
CWBackPixel |
CWColormap;
NewWin = XCreateWindow( display, parent, xpos, ypos, width, height, 0,
dep, CopyFromParent, vis, winfo_mask, &winfo);
XSelectInput( display, NewWin, event_mask);
/* Allow input
*/
wmhints.flags = InputHint;
wmhints.input = True;
XSetWMHints ( display, NewWin, &wmhints);
/* Set window banner title
*/
XStoreName( display, NewWin, "Colormap by Solotech v2.8");
/* Map the window to the display and flush the output queue
*/
XMapWindow( display, NewWin);
XFlush( display);
return(NewWin);
} /* end create_window() */
/****************************************************** toggle_visual */
toggle_visual()
{
int num;
int clrcells;
/*--------------------------------------------------------------------*/
dep = (dep == 4) ? 8 : 4;
if (!get_visual(&dep)) {
dep = (dep == 4) ? 8 : 4;
return;
}
clrcells = (dcms > vis->map_entries) ? vis->map_entries : dcms;
/*
* Re-Initialize my colormap
*/
XFreeColormap( display, mycmap);
mycmap = XCreateColormap( display, MainWin, vis, AllocAll);
icm = XListInstalledColormaps( display, root, &num);
/*
* Copy the colors from the installed colormap to mycmap
*/
XQueryColors( display, *icm, colors, clrcells);
XStoreColors( display, mycmap, colors, clrcells);
/*
* Recalculate the rows and columns for display
*/
numcells = (numcells > 256) ? 256 : numcells;
rows = (numcells > 254) ? 16 : 4;
cols = rows;
cellheight = (win_height) / rows;
cellwidth = (win_width ) / cols;
XDestroyWindow( display, MainWin);
MainWin = create_window( pw, 0, 0, win_width, win_height+banner_height);
XSync( display, 0);
} /* end toggle_visual() */
/**************************************************** display_default */
void display_default()
/**
Display the default colormap
If the user hits a "d" then display the default colormap
and wait for the user to generate one of the following:
to hit any key
to generate an exposure or configure event
to press a mouse button in the colormap window
**/
{
XEvent ev;
char string[20], *keystring;
KeySym key;
Bool Done = False;
/*--------------------------------------------------------------------*/
sprintf( message, "ColorMapId Id = %d (default)",dcm);
output_message( message, 1);
XInstallColormap( display, dcm);
/*
* Wait for a significant event before continuing and replace the event back
* on the queue to be processed by the main event loop
*/
while (!Done) {
XNextEvent( display, &ev);
switch (ev.type) {
case ConfigureNotify :
case ButtonPress :
case Expose :
XPutBackEvent( display, &ev);
Done = True;
break;
case KeyPress :
XLookupString( &ev, string, 20, &key, NULL);
keystring = XKeysymToString( key);
if ((keystring[0] != 'd') && (keystring[0] != 'D'))
XPutBackEvent( display, &ev);
Done = True;
break;
}
}
/* Reinstall mycmap and clear the message
*/
XInstallColormap( display, mycmap);
sprintf( message, "ColorMapId Id = %d", *icm);
output_message( message, 1);
} /* end display_default() */
/*************************************************** load_color_range */
load_color_range()
/**
**/
{
XEvent ev;
char string[20], *keystring;
KeySym key;
Colormap scratch_cmap;
int i;
Bool Done = False;
/*--------------------------------------------------------------------*/
/*
* Create a sratch colormap to load our color range
* so as to not mess up mycmap
*/
scratch_cmap = XCreateColormap( display, MainWin, vis, AllocAll);
/*
* Create/Load the mixed color map
*/
for (i=0; i<MINCELL; i++) {
LocColors[i].pixel = i;
LocColors[i].red = colors[i].red;
LocColors[i].green = colors[i].green;
LocColors[i].blue = colors[i].blue;
LocColors[i].flags = DoRed | DoGreen | DoBlue;
}
for (i=MINCELL; i< numcells; i++) {
LocColors[i].pixel = i;
LocColors[i].red = ((numcells-i) * 65535 ) / numcells;
LocColors[i].green = (( i) * 65535 ) / numcells;
LocColors[i].blue = ((numcells-i/2) * 65535 ) / numcells;
LocColors[i].flags = DoRed | DoGreen | DoBlue;
}
XStoreColors( display, scratch_cmap, LocColors, numcells);
XInstallColormap( display, scratch_cmap);
XFlush( display);
/*
* Wait for a significant event before continuing and replace the event back
* on the queue to be processed by the main event loop
*/
while (!Done) {
XNextEvent( display, &ev);
switch (ev.type) {
case ConfigureNotify :
case ButtonPress :
case Expose :
XPutBackEvent( display, &ev);
Done = True;
break;
case KeyPress :
XLookupString( &ev, string, 20, &key, NULL);
keystring = XKeysymToString( key);
if ((keystring[0] != 'l') && (keystring[0] != 'L'))
XPutBackEvent( display, &ev);
Done = True;
break;
}
}
/*
* We're done. Reinstall mycmap and trash the scratch amp
*/
XInstallColormap( display, mycmap);
XFreeColormap( display, scratch_cmap);
/*
* Reprint the colormap id display
*/
sprintf( message, "ColorMapId = %d", *icm);
output_message( message, 1);
} /* end load_color_range() */
/****************************************************** AnimateColormap */
AnimateColormap()
{
int i;
XColor SaveColor;
int Count, NumColors;
int Delay = 20;
struct timeb t1, t2;
/*---------------------------------------------------------------------*/
NumColors = numcells;
/*
* Get the colors that are in the colormap
*/
for (i = 0; i < 256; i++) {
LocColors[i].pixel = i;
LocColors[i].flags = DoRed | DoGreen | DoBlue;
}
XQueryColors(display, mycmap, LocColors, NumColors);
/*
* Cycle the colors NumCycles times
*/
for (Count = 0; Count < (NumColors - MINCELL); Count++) {
ftime(&t1);
SaveColor.pixel = LocColors[NumColors - 1].pixel;
SaveColor.red = LocColors[NumColors - 1].red;
SaveColor.green = LocColors[NumColors - 1].green;
SaveColor.blue = LocColors[NumColors - 1].blue;
for (i = NumColors - 1; i > MINCELL; i--) {
LocColors[i].red = LocColors[i - 1].red;
LocColors[i].green = LocColors[i - 1].green;
LocColors[i].blue = LocColors[i - 1].blue;
}
LocColors[i].pixel = SaveColor.pixel;
LocColors[i].red = SaveColor.red;
LocColors[i].green = SaveColor.green;
LocColors[i].blue = SaveColor.blue;
XStoreColors(display, mycmap, LocColors, NumColors);
XSync(display, 0);
ftime(&t2);
while ((t2.millitm - t1.millitm) < Delay)
ftime(&t2);
}
XStoreColors(display, mycmap, colors, NumColors);
XSync(display, 0);
}
/****************************************************** AnimateColormap */
TraverseColormap()
{
int i = 0;
XColor SaveColor;
int Count, NumColors, NumCycles;
int Delay;
struct timeb t1, t2;
/*---------------------------------------------------------------------*/
NumColors = numcells;
NumCycles = 1;
Delay = 50;
/*
* Get the colors that are in the colormap
*/
for (i = 0; i < 256; i++) {
LocColors[i].pixel = i;
LocColors[i].flags = DoRed | DoGreen | DoBlue;
}
XQueryColors(display, mycmap, LocColors, NumColors);
XSynchronize(display, 1);
/*
* Cycle the colors NumCycles times
*/
for (Count = 0; Count < NumCycles; Count++) {
for (i = MINCELL; i < NumColors; i++) {
ftime(&t1);
SaveColor.red = LocColors[i].red;
SaveColor.green = LocColors[i].green;
SaveColor.blue = LocColors[i].blue;
LocColors[i].red = 65535;
LocColors[i].green = 65535;
LocColors[i].blue = 65535;
XStoreColor(display, mycmap, &LocColors[i]);
XSync(display, 0);
LocColors[i].red = SaveColor.red;
LocColors[i].green = SaveColor.green;
LocColors[i].blue = SaveColor.blue;
XStoreColor(display, mycmap, &LocColors[i]);
XSync(display, 0);
ftime(&t2);
while ((t2.millitm - t1.millitm) < Delay)
ftime(&t2);
}
}
XSynchronize(display, 0);
XStoreColors(display, mycmap, colors, NumColors);
XSync(display, 0);
}
/*************************************************** UpdateCellDisplay */
void UpdateCellDisplay( CellId)
int CellId;
{
int xpos, ypos;
/*---------------------------------------------------------------------*/
/*
* Update CellId to reflect its current allocation
*/
xpos = ((CellId % cols) * cellwidth) + xoff;
ypos = ((CellId / cols) * cellheight) + yoff + banner_height;
/*
* Draw a filled rectangle with interior color_table_index = index
*/
XSetForeground(display, gc, CellId);
XFillRectangle(display, MainWin, gc, xpos, ypos, cellwidth, cellheight);
/*
* Draw a black border around the filled polygon
*/
XSetForeground(display, gc, 0);
XDrawRectangle(display, MainWin, gc, xpos, ypos, cellwidth, cellheight);
/*
* Add a diagonal slash if this color cell is Allocated
*/
if (AllocatedCells[CellId] == True)
XDrawLine(display, MainWin, rgc,
xpos, ypos, (xpos + cellwidth), (ypos + cellheight));
/*
* Add an extra diagonal slash if this color cell is Allocated by me
*/
if (MyAllocedCells[CellId] == True)
XDrawLine(display, MainWin, rgc,
xpos, (ypos + cellheight), (xpos + cellwidth), ypos);
}
/************************************************************* update */
update()
{
int xpos, ypos, index;
int cur_row, cur_col;
int num;
/*--------------------------------------------------------------------*/
/*
* Calculate an offset value so as to center the colortable grid in
* the window
*/
xoff = 0.45 * (win_width - (cols*cellwidth));
yoff = 0.70 * (win_height - (rows*cellheight));
/*
* Fill a rectagle for each color in the colormap
*/
for (cur_row=0; cur_row<rows; cur_row++) {
for (cur_col=0; cur_col<cols; cur_col++) {
index = (cur_row*cols)+cur_col;
if (index >= vis->map_entries) index = 0;
xpos = (cur_col*cellwidth) + xoff;
ypos = (cur_row*cellheight) + yoff + banner_height;
/*
* Draw a filled rectangle with interior color_table_index = index
*/
XSetForeground( display, gc, index);
XFillRectangle( display,MainWin,gc,xpos,ypos,cellwidth,cellheight);
/*
* Draw a black border around the filled polygon
*/
XSetForeground( display, gc, 0);
XDrawRectangle( display,MainWin,gc,xpos,ypos,cellwidth,cellheight);
/*
* Add a diagonal slash if this color cell is Allocated
*/
if (AllocatedCells[index] == True)
XDrawLine(display, MainWin, rgc,
xpos, ypos, (xpos + cellwidth), (ypos + cellheight));
/*
* Add an extra diagonal slash if this color cell is Allocated by me
*/
if (MyAllocedCells[index] == True)
XDrawLine(display, MainWin, rgc,
xpos, (ypos + cellheight), (xpos + cellwidth), ypos);
} /* end for cur_col */
} /* end for cur_row */
/*
* Query the current colormap id and display
*/
icm2 = XListInstalledColormaps( display, root, &num);
icm = (*icm2 != mycmap) ? icm2 : icm;
/*
* Display the colormap id to the user
*/
sprintf( message, "ColorMapId Id = %d", *icm);
output_message( message, 1);
XFlush( display);
} /* end update() */
/*************************************************** SetColorCellValue */
void SetColorCellValue( CellId)
{
char ColorName[1024];
XColor NewColor;
Status ColorParsed;
char Buffer[40];
/*---------------------------------------------------------------------*/
if (MyAllocedCells[CellId] == True) {
/*
* Get the name of a color
*/
output_message("Enter Color Name: ", 1);
GetInput(ColorName, STRING);
/*
* Restore the default color map message
*/
sprintf(message, "ColorMapId Id = %d", *icm);
output_message(message, 1);
/*
* Store the color into the default colormap and colors array
*/
if (ColorName[0] != NULL) {
ColorParsed = XParseColor(display, *icm,
ColorName, &colors[CellId]);
if (ColorParsed) {
XStoreColor(display, *icm, &colors[CellId]);
}
else {
XBell(display, 40);
sprintf(Buffer, "Invalid color spec: %s", ColorName);
output_message(Buffer, 2);
}
}
}
}
/************************************************* ShowAllocatedCells */
void ShowAllocatedCells()
/**
Display all the allocated color cells by putting a slash through them
**/
{
int i, xpos, ypos, index;
int cur_row, cur_col;
int NextNumColors, NumColors = 0, Pixels[256], Planes[16];
Status GotDemCells = False;
/*--------------------------------------------------------------------*/
/*
* Assume all cells are allocated
*/
for (i = 0; i < numcells; i++)
AllocatedCells[i] = True;
/*
* Attempt to allocated as many cells as possible
* when we allocate then Pixels containes those cells that are free
*/
NextNumColors = numcells;
while (!GotDemCells) {
NumColors = NextNumColors--;
GotDemCells = XAllocColorCells(display, *icm, False, Planes,
0, Pixels, NumColors);
if (GotDemCells)
XFreeColors(display, *icm, Pixels, NumColors, 0);
if (NextNumColors < 1) {
GotDemCells = True;
NumColors = 0;
}
}
/*
* For each cell in Pixels that we were able to allocate
* set its slot in AllocatedCells to False
*/
for (i = 0; i < NumColors; i++)
AllocatedCells[Pixels[i]] = False;
update();
} /* end ShowAllocatedCells() */
/************************************************** AllocateColorCell */
void AllocateColorCell( CellId, Allocate, SetColorValue)
int CellId;
Bool Allocate; /* True = allocate it, False = Unallocate it */
Bool SetColorValue;
{
int i, j, index;
int NextNumColors, NumColors = 0, Pixels[256], Planes[16];
Status GotDemCells = False;
Bool Allocated = False;
int Pixels2[256];
/*--------------------------------------------------------------------*/
if (Allocate == False) {
/*
* If the cell is allocated
* then free up the color cell
*/
if (MyAllocedCells[CellId] == True) {
XFreeColors(display, *icm, &CellId, 1, 0);
MyAllocedCells[CellId] = False;
AllocatedCells[CellId] = False;
}
}
else {
/*
* Attempt to allocated as many cells as possible
* when we allocate then Pixels containes those cells that are free
* search for CellId and free all other cells
*/
NextNumColors = numcells;
while (!GotDemCells) {
NumColors = NextNumColors--;
GotDemCells = XAllocColorCells(display, *icm, False, Planes,
0, Pixels, NumColors);
if (GotDemCells) {
for (i = 0, j = 0; i < NumColors; i++) {
if (Pixels[i] != CellId)
Pixels2[j++] = Pixels[i];
else {
MyAllocedCells[Pixels[i]] = True;
AllocatedCells[Pixels[i]] = True;
Allocated = True;
}
}
if (Allocated == True)
XFreeColors(display, *icm, Pixels2, NumColors - 1, 0);
else
XFreeColors(display, *icm, Pixels, NumColors, 0);
}
else
if (NextNumColors <= 0) {
output_message("All colorcells allocated", 2);
return;
}
}
}
if (Allocated && SetColorValue)
SetColorCellValue(CellId);
UpdateCellDisplay(CellId);
}
/******************************************************** GetAllCells */
GetAllCells()
{
int i, xpos, ypos, index;
int cur_row, cur_col;
int NextNumColors, NumColors = 0, Pixels[256], Planes[16];
Status GotDemCells = False;
/*--------------------------------------------------------------------*/
/*
* Attempt to allocated as many cells as possible
* when we allocate then Pixels containes those cells that are free
*/
NextNumColors = numcells;
while ((!GotDemCells) && NextNumColors) {
NumColors = NextNumColors--;
GotDemCells = XAllocColorCells(display, *icm, False, Planes,
0, Pixels, NumColors);
}
/*
* All cells are allocated
*/
for (i = 0; i < numcells; i++)
AllocatedCells[i] = True;
/*
* For each cell in Pixels that we were able to allocate
* set its slot in MyAllocedCells
*/
for (i = 0; i < NumColors; i++) {
MyAllocedCells[Pixels[i]] = True;
}
update();
}
/****************************************************** UngetAllCells */
void UngetAllCells()
/**
Loop through MyAllocedCells and unallocate any that we have gotten
**/
{
int i;
/*--------------------------------------------------------------------*/
for (i = 0; i < numcells; i++) {
if (MyAllocedCells[i] == True) {
MyAllocedCells[i] = False;
AllocatedCells[i] = False;
XFreeColors(display, *icm, &i, 1, 0);
UpdateCellDisplay(i);
}
}
XFlush(display);
}
/********************************************************* event_loop */
event_loop()
{
XEvent ev;
int num, i, j;
char string[20], *keystring;
KeySym key;
unsigned int clr_mask = DoRed | DoGreen | DoBlue;
Bool update_picture = True;
Bool done = False;
int bgcolor;
/*--------------------------------------------------------------------*/
while (!done) {
if (!XPending(display) && update_picture) {
update();
update_picture = False;
}
XNextEvent(display, &ev);
switch (ev.type) {
case ButtonPress:
/* Find the row and column indices of the mouse postion where
* the button was pressed */
i = -999;
j = -999;
if ((ev.xbutton.x - xoff) >= 0)
i = (ev.xbutton.x - xoff) / cellwidth;
if ((ev.xbutton.y - yoff - banner_height) >= 0)
j = (ev.xbutton.y - yoff - banner_height) / cellheight;
/* Calculate the colortable index */
if ((i < 0) || (i > cols - 1) || (j < 0) || (j > rows - 1))
bgcolor = 0;
else
bgcolor = (j * cols) + i;
switch (ev.xbutton.button) {
case 2:
AllocateColorCell(bgcolor, True,
(ev.xbutton.state & ShiftMask));
break;
case 3:
AllocateColorCell(bgcolor, False, False);
break;
default:
/* With a 4-bit visual there are 15 entries The last
* row/col needs to wrap around */
if (bgcolor > vis->map_entries - 1)
bgcolor = 0;
/* Store cyan in the colorcell of the mouse click */
XStoreNamedColor(display, mycmap, "cyan", bgcolor, clr_mask);
/* Output colormap id message */
sprintf(message, "Cell = %3d, RGB = %5.2f %5.2f %5.2f",
bgcolor,
colors[bgcolor].red / (float) 65535,
colors[bgcolor].green / (float) 65535,
colors[bgcolor].blue / (float) 65535);
output_message(message, 2);
break;
}
XFlush(display);
break;
case ButtonRelease:
/* Restore the color cells that have been modified. */
XStoreColors(display, mycmap, colors, numcells);
break;
case EnterNotify:
/* If we found the color then Inquire the currently loaded
* colormap copy its colors and load our colormap with them
* and store cyan into the colortable entry calculated above
* and load our colormap into the server */
icm2 = XListInstalledColormaps(display, root, &num);
if (*icm2 != mycmap) {
icm = icm2;
if (dcms < numcells) {
XQueryColors(display, *icm, colors, dcms);
XStoreColors(display, mycmap, colors, dcms);
}
else {
XQueryColors(display, *icm, colors, numcells);
XStoreColors(display, mycmap, colors, numcells);
}
XInstallColormap(display, mycmap);
XSetForeground(display, gc, 0);
XFillRectangle(display, MainWin, gc, 0, 0,
win_width, banner_height);
sprintf(message, "ColorMapId Id = %d", *icm);
output_message(message, 1);
}
break;
case LeaveNotify:
/* Uninstall my colormap and re-install the colormap that was
* installed previously XUninstallColormap( display, mycmap); */
XInstallColormap(display, *icm);
break;
case ColormapNotify:
icm2 = XListInstalledColormaps(display, root, &num);
if (*icm2 != mycmap) {
icm = icm2;
if (dcms < numcells)
XQueryColors(display, *icm, colors, dcms);
else
XQueryColors(display, *icm, colors, numcells);
}
XSetForeground(display, gc, 0);
XFillRectangle(display, MainWin, gc, 0, 0, win_width, banner_height);
sprintf(message, "ColorMapId Id = %d", *icm);
output_message(message, 1);
break;
case KeyPress:
XLookupString(&ev, string, 20, &key, NULL);
keystring = XKeysymToString(key);
if (strlen(keystring) < 2)
switch (keystring[0]) {
case 'a': /* Animate the colormap */
AnimateColormap();
break;
case 'A': /* Animate the colormap */
TraverseColormap();
break;
case 'd': /* Display the default colormap */
display_default();
break;
case 'l': /* Load a colorramp and display */
load_color_range();
break;
case 's': /* Show allocated colorcells */
ShowAllocatedCells();
break;
case 'S': /* UnShow allocated colorcells */
for (i = 0; i < numcells; i++)
if (MyAllocedCells[i] == False)
AllocatedCells[i] = False;
update();
break;
case 't': /* Toggle between different visuals */
toggle_visual();
break;
case 'u': /* Unallocate all the cells previously
* allocated */
UngetAllCells();
break;
case 'g': /* Get as many colorcells as possible */
GetAllCells();
break;
case 'q':
XInstallColormap(display, *icm);
done = True;
break;
} /* end switch(keystring[0]) */
break;
case Expose:
/* Set the update_picture flag so that when all the events
* have been processed we know that the picture needs to be
* updated with any changes */
XFillRectangle(display, MainWin, gc, 0, 0,
win_width, win_height + banner_height);
update_picture = True;
break;
case ConfigureNotify:
/* Store the new window width and height. Use the values to
* calculate a new colorcell width and height */
win_height = ev.xconfigure.height - banner_height;
win_width = ev.xconfigure.width;
cellheight = (win_height) / rows;
cellwidth = (win_width) / cols;
/* Need to figure out how to pass the resize down to the child
* windows */
if (ev.xconfigure.window == pw)
XResizeWindow(display, MainWin,
win_width, win_height + banner_height);
XSync(display, 0);
break;
default:
break;
} /* end switch() */
} /* end while(!done) */
}/* end event_loop() */
/*************************************************************** main */
main( argc, argv)
int argc;
char *argv[];
{
char cont;
int num;
int screen, index;
char Dashes[2];
/*--------------------------------------------------------------------*/
/*
* Initialize the connection to the XServer and get some default
* values for a start
*/
display = XOpenDisplay( NULL);
screen = XDefaultScreen( display);
dcm = DefaultColormap( display, screen);
vis = DefaultVisual( display, screen);
root = RootWindow( display, screen);
dcms = vis->map_entries;
truecolor = (vis->class == TrueColor) ? True : False;
dep = DefaultDepth( display, screen);
get_visual(&dep);
/*
* See if there are at least 16 colors to display. If there are less
* than 16, ask the user if s/he wants to continue anyway
*/
if (numcells < MIN_COLOR_CELLS ) {
printf("Your default visual is not set for color display\n");
printf("number of colorcells = %d\nContinue anyway?", numcells);
scanf("%c", &cont);
if (tolower(cont) != 'y') exit(0);
}
/*
* Currently, we are only dealing with either a 16 or 256 entry
* colortable, so rows and cols will be set to present a pretty
* colortable layout of 4x4 or 16x16
*/
numcells = (numcells > 256) ? 256 : numcells;
rows = (numcells > 254) ? 16 : 4;
cols = (numcells+rows-1)/rows;
/*
* Initialize the colors array's pixels value
* for use in the QueryColors call. The pixel field needs to be set
* to the colortable index of the color that we want information about
*/
for (index = 0; index < numcells; index++) {
colors[index].pixel = index;
MyAllocedCells[index] = False;
AllocatedCells[index] = False;
}
/*
* Initialize my colormap
*/
mycmap = XCreateColormap( display, root, vis, AllocAll);
icm = (Colormap *)XListInstalledColormaps( display, root, &num);
XQueryColors( display, *icm, colors, dcms);
XStoreColors( display, mycmap, colors, dcms);
/*
* Depending on the input arg, set the event mask
*/
if (argv[1] == NULL)
event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
| ButtonPressMask | ButtonReleaseMask
| EnterWindowMask | LeaveWindowMask;
else
event_mask = ExposureMask | StructureNotifyMask | KeyPressMask;
XSelectInput( display, root, ColormapChangeMask);
/*
* Create the main window
*/
xoff = 5;
yoff = 5;
if (rows == 4) {
cellwidth = 80;
cellheight = 40;
}
else {
cellwidth = 20;
cellheight = 10;
}
win_height = (rows * cellheight) + yoff;
win_width = (cols * cellwidth) + xoff;
pw = create_window( root, 0, -banner_height, win_width, win_height);
MainWin = create_window( pw, 0, 0, win_width, win_height);
/*
* Create a graphics context for the window and set the background color
*/
gc = XCreateGC( display, MainWin, 0, 0);
XSetBackground( display, gc, 1);
/*
* Create a graphics context for reverse video action
*/
rgc = XCreateGC( display, MainWin, 0, 0);
XSetForeground( display, rgc, BlackPixel(display, screen));
XSetBackground( display, rgc, WhitePixel(display, screen));
XSetFillStyle( display, rgc, FillOpaqueStippled);
Dashes[0] = 1;
Dashes[1] = 1;
XSetDashes( display, rgc, 0, Dashes, 2);
XSetLineAttributes( display, rgc, 1, LineDoubleDash, CapNotLast,
JoinMiter);
/*
* Start the event loop
*/
event_loop();
/*
* Close the connection to the display before quiting
*/
XCloseDisplay( display);
} /* main() */