hoenig@informatik.uni-kl.de (Helmut Hoenig) (03/23/90)
Submitted-by: Helmut Hoenig <hoenig@informatik.uni-kl.de> Posting-number: Volume 6, Issue 47 Archive-name: xcol/part01 XCol is a program to edit occurrences of color-names in text-files (i.e. the '.twmrc'-file). It shows the available colors and you can change the textfile by selecting new colors with the mouse. Even without editing a textfile, it gives you a good impression of the available colors (the colors defined in the 'rgb.txt'-file of the server). The program runs on X11R4. It should run on X11R3 too, but I already had some small problems with the created colormap. A manual page is included. by Helmut Hoenig hoenig@informatik.uni-kl.de ------------------------------------------------------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: xcol.txt makefile Imakefile patchlevel.h xcol.part1 # Wrapped by hoenig@popper on Wed Mar 21 16:47:26 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f xcol.txt -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"xcol.txt\" else echo shar: Extracting \"xcol.txt\" \(3824 characters\) sed "s/^X//" >xcol.txt <<'END_OF_xcol.txt' XNAME X xcol - change color-entries in textfiles X XSYNOPSIS X xcol [-options ...] [filename] X XDESCRIPTION X XCol displays the colors defined in the rgb.txt-file of the X XServer. The colors are sorted by their names and their X RGB-values and shown in a cube in the ColorView-Window (The X positions represent the RGB-values). Since there usually X are more colors defined in the file than cells in the color- X map, entries with the same name but different RGB-values for X different intensities, are grouped together. X X If a filename is given as a parameter, all occurrences of X color-names in that file are shown in an additional X TextView-Window. To change the colors, a text-line has to be X made active. Afterwards a new color can be selected in the X ColorView-Window. To get a better impression of the color, a X help-color (background) can be selected for each text-line. X If 2 lines define a foreground and a background color, an X association can be made and the colors of both lines can be X selected together. X XBUTTONS X in ColorView-Window X X left: select color for the active line. X middle: select help-color for the active line. X right: warp pointer to color of active line. X X in TextView-Window X X left: select line as active line. X middle: toggle reverse-mode or X connect/disconnect 2 lines. X right: show line in the textfile. X XOPTIONS X -rv Color-positions are reversed in the cube. Some new X colors can become visible in the area of the very X bright colors. X X -b<n> The size of color blocks is set to the constant <n>. X By default, it depends on the size of the X ColorView-Window. X X -gran<n> X The maximum number of associated colors is set to X <n>. By default, this value is 11. (You can see the X effect when reaching the grey-field, where 101 X associated entries are possibly available.) X X -dark<n> X The percentage of the intensity of other colors can X be set (default: 50). It is easier to select a X color, if the screen is darkened a little bit. X X +<char_list> X add characters to list of 'space'-chars. The color- X string in the textfile has to occur between 2 X 'space'-chars to be recognized. By default, these X letters are ' ', '\t', '\n', ':', '"'. X X -strings X Names of colors in the file are only recognized when X used in a string (useful for C-Sources). This means X that the list of 'space'-chars is set to '"' only. X X -case All occurrences of color-names in wrong case are X replaced by the color-name of the 'rgb.txt'-file. X X -help print some instructions (usage of buttons). X X -file <name> X name of a different 'rgb.txt'-file. X XFILES X /usr/lib/X11/rgb.txt X XSEE ALSO X X(1) X XBUGS X Actually I wanted the program to work with the selection X mechanism used in xterm (when no textfile is given), but it X seems to be too complicated to use it here. So, the current X version always stores the string of the color in X CUT_BUFFER0. If anyone has an easy way to use the correct X selection mechanism, please inform me. X XCOPYRIGHT X Copyright 1990, University of Kaiserslautern. X X Author: Helmut Hoenig (hoenig@informatik.uni-kl.de) X X Permission to use, copy, modify, and distribute this X software for any purpose and without fee is hereby granted, X provided that the above copyright notice appear in all X copies. END_OF_xcol.txt if test 3824 -ne `wc -c <xcol.txt`; then echo shar: \"xcol.txt\" unpacked with wrong size! fi # end of overwriting check fi if test -f makefile -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"makefile\" else echo shar: Extracting \"makefile\" \(99 characters\) sed "s/^X//" >makefile <<'END_OF_makefile' XCFLAGS = XLIBS = -lX11 XG_OBJ = xcol.o X Xxcol: $(G_OBJ) X $(CC) $(CFLAGS) $(G_OBJ) $(LIBS) -o xcol END_OF_makefile if test 99 -ne `wc -c <makefile`; then echo shar: \"makefile\" unpacked with wrong size! fi # end of overwriting check fi if test -f Imakefile -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Imakefile\" else echo shar: Extracting \"Imakefile\" \(78 characters\) sed "s/^X//" >Imakefile <<'END_OF_Imakefile' X SRCS = xcol.c X OBJS = xcol.o X XComplexProgramTarget(xcol) END_OF_Imakefile if test 78 -ne `wc -c <Imakefile`; then echo shar: \"Imakefile\" unpacked with wrong size! fi # end of overwriting check fi if test -f patchlevel.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"patchlevel.h\" else echo shar: Extracting \"patchlevel.h\" \(53 characters\) sed "s/^X//" >patchlevel.h <<'END_OF_patchlevel.h' X#define PATCHLEVEL 0 X#define PATCHDATE "Mar-21-1990" END_OF_patchlevel.h if test 53 -ne `wc -c <patchlevel.h`; then echo shar: \"patchlevel.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f xcol.part1 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"xcol.part1\" else echo shar: Extracting \"xcol.part1\" \(24317 characters\) sed "s/^X//" >xcol.part1 <<'END_OF_xcol.part1' X/**************************************************************** X * * X * xcol - program to edit color-name-occurrences in textfiles * X * * X * Written by Helmut Hoenig, Feb. 1990. * X * University of Kaiserslautern, Germany * X * * X * email: hoenig@informatik.uni-kl.de * X * * X ****************************************************************/ X X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include <X11/cursorfont.h> X X#include <sys/param.h> X#include <stdio.h> X#include <strings.h> X#include <ctype.h> X X#include "patchlevel.h" X X/*----------------------------------------------------------------------------*/ X X#define COLOR_FONT "-adobe-times-bold-r-normal--17-120-100-100-p-88-iso8859-1" X#define TEXT_FONT "-adobe-times-bold-r-normal--12-120-75-75-p-67-iso8859-1" X X#define RGB_FILE "/usr/lib/X11/rgb.txt" X X/* MAX_??? - definitions are used in the definition of some local arrays, X where I didn't want to make complicated memory allocation. */ X X#define MAX_CELLS 256 /* number of cells, used by the programm*/ X X#define MAX_COLS 1000 /* colors in rgb.txt-file */ X#define MAX_COLOR_LINES 400 /* color occurrences in a textfile */ X#define MAX_LINE_LENGTH 1000 /* linelength of textfile */ X X/*----------------------------------------------------------------------------*/ X X/* switch on/off some bugs ?? */ X#define CHG_TEXT_WINDOW_COLORMAP X#define _RECOLOR_CURSOR X X/* variables for parameters (default is set) */ Xint reverse = 0; Xint BO_def = 0; Xint darkness=50; Xint gran =11; Xint original= 0; X X/* X-Data */ XDisplay *display; XScreen *screen; XXFontStruct *finfo; XGC gc; Xint cells; X X/* the grey-pixmap is used to get an impression of mixing the foreground X * and background color of a color-line. X */ X#define grey_width 16 X#define grey_height 16 Xstatic char grey_bits[] = { X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa}; XPixmap grey_pixmap; X XCursor mw_cursor; /* Cursor in main-window */ XCursor tw_cursor; /* Cursor in text-window */ XCursor subsel_cursor; /* Cursor during selection of associated colors */ XCursor text_cursor; /* Cursor while looking in the source-file */ XCursor quest_cursor; /* Cursor while asking for write-confirmation */ XCursor updown_cursor; /* Cursor while making association */ X X/* Mainwindow-Data */ XWindow mw; /* Window-Id */ Xint dx, dy; /* current size of the window */ Xint BO=14; /* current size of the color-boxes in the window */ X X/* Textwindow-Data */ XWindow tw = NULL; XXFontStruct *tinfo; /* Structure of the textfont */ Xint char_width, char_height;/* char-size depending on the font */ Xchar *tw_message[2]; /* messages in header and footer-line */ Xint twidth; /* width in pixel */ Xint tw_lines; /* height in lines (header&footer not included) */ Xint act_line=0; /* active-line */ Xint act_offset=0; /* first color-line (when not all lines fit in the window) */ X X/* Subwindow-Data (little window for selected color) */ XWindow subw; /* Window-Id */ Xint sdx, sdy; /* current size of subwindow */ Xint subcols; /* number of associated colors in the subwindow */ X X/* Color-Management */ XColormap my_map=NULL; Xint my_pixel[MAX_CELLS]; /* flag: 0 = pixel not used in my program */ Xint only_mine; /* flag: 1 = allocations only in own map */ X X#define NotAllocated (-1L) X#define Undefined (-2L) X Xtypedef struct _color_def { X int r, g, b; /* rgb-value from the 'rbg.txt'-file */ X char *name; /* name from the 'rgb.txt'-file */ X int x, y; /* position in main window */ X unsigned long pixel; /* allocated pixel for the color */ X struct _color_def *associated; /* colors with different intensity (e.g. 'blue' -> 'blue4' ... ) */ X struct _color_def *brother; /* colors with different name (e.g. 'OldLace' -> 'old lace') */ X} ColorDef; X Xtypedef struct _color_strings { X char *name; X int length; X ColorDef *def; X} ColorString; X XColorDef *color[MAX_COLS]; /* field with the definitions of the colors */ XColorString cname[MAX_COLS]; /* sorted field with the names of all colors */ XColorString *first[256]; /* 'Hash-Table', points to the first name X that starts with the given letter. */ X Xint color_names; /* number of color-names X = entries in the 'rgb.txt'-file */ Xint color_number; /* number of 'different' colors X = number of colors shown in the cube */ X X#define BLACK_STRING "black" X#define WHITE_STRING "white" X#define GREY_STRING "gray" X XColorDef std_black = { 0, 0, 0, BLACK_STRING }; XColorDef std_white = { 255, 255, 255, WHITE_STRING }; XColorDef std_grey = { 192, 192, 192, GREY_STRING }; X Xunsigned long white, black, grey; /* pixel-values (in my_map !!) */ XColorDef *back_def; /* default background in textwindow */ X X/*----------------------------------------------------------------------------*/ X Xtypedef struct _text_line { /* structure to store the text-file */ X char *contents; X struct _text_line *next; X struct _text_line *previous; X} TextLine; X Xtypedef struct _color_line { /* structure for a line with color-entry */ X TextLine *line; /* pointer to the textline */ X ColorDef *color; /* the color defined in the line */ X ColorDef *help; /* a help-color for the background */ X int reverse; /* flag to display line in reverse */ X int pos_in_line; /* position of the color-name in the line */ X int assoc; /* corresponding color-line, when a X 'foreground-background'-association X was found (or entered) */ X} ColorLine; X Xchar *file_name; /* name of the text-file */ XTextLine *loaded_text; /* Pointer to the first line */ XColorLine line[MAX_COLOR_LINES]; /* array of the color-lines */ Xint color_lines; /* number of the color-lines */ Xint longest_colored; /* length of the longest color-line */ X Xchar space_char[256]; /* flag, which chars should be recognized X as spaces */ X X X/******************************************************************************** X * parsing the text-file (not very efficient, but who cares) * X ********************************************************************************/ X X Xvoid set_default_spaces() X{ X memset( space_char, 0, (int)sizeof(space_char) ); X space_char[ ' ' ] = space_char[ '\t' ] = space_char[ '\n' ] = X space_char[ ':' ] = space_char[ '"' ] = 1; X} X Xint strncase_equal( s1, s2, n ) X register char *s1; X register char *s2; X register int n; X/* the function is NOT correct, since just proves, if strings are equal X when the 5th bit of their characters is ignored. X */ X{ X while(n--) X { if ( ((*s1++)^(*s2++))&((unsigned char)~32) ) return(1); X } X return(0); X} X Xint strcase_equal( s1, s2 ) X char *s1,*s2; X{ Xint n1,n2; X X n1 = strlen(s1); X n2 = strlen(s2); X if (n1!=n2) return(-1); X else return(strncase_equal( s1, s2, n1 )); X} X Xstring_exchange( cline, new_color ) X ColorLine *cline; X ColorDef *new_color; X/* replaces the color-string in a color-line */ X{ Xchar new_line[MAX_LINE_LENGTH]; Xint pos; X X pos = cline->pos_in_line; X strncpy( &new_line[0], cline->line->contents, pos ); X strcpy( &new_line[pos], new_color->name ); X strcat( new_line, &cline->line->contents[pos+strlen(cline->color->name)] ); X free( cline->line->contents ); X cline->line->contents = (char *)malloc((unsigned) strlen( new_line )+1 ); X strcpy( cline->line->contents, new_line ); X} X Xvoid check_colors( in_line ) X TextLine *in_line; X/* checks, if a color exists in the given line and possibly adds X * the line to the list of color-lines. X */ X{ Xint i, c; Xchar lett; Xchar check; XColorString *col; Xchar *act_line = in_line->contents; X X c=strlen(act_line); X while(c>0) X { do X { c--; X if (space_char[act_line[c-1]]) break; X } X while(c>1); X X lett = act_line[c]; X if (isalpha(lett)) X { X if (isupper(lett)) lett = tolower( lett ); X /* compares both cases */ X for (i=0;i<2;i++) X { for (col=first[lett];col<first[lett+1];col++) X { X check = act_line[c+col->length]; X if (space_char[check]) X { if ((strncase_equal( &act_line[c], col->name, col->length )==0 )) X { line[color_lines].line = in_line; X line[color_lines].color= col->def; X line[color_lines].help = back_def; X line[color_lines].pos_in_line = c; X line[color_lines].reverse = 0; X line[color_lines].assoc = -1; X X if (original) X { string_exchange( &line[color_lines], col->def ); X } X if (XTextWidth( tinfo, act_line, strlen(act_line) )>longest_colored) X longest_colored = XTextWidth( tinfo, act_line, strlen(act_line) ); X color_lines++; X return; X } X } X } X lett = toupper( lett ); X } X } X } X} X Xint spc_line( search_string, line, name, length ) X char *search_string; X TextLine *line; X char *name; X int *length; X/* searches for the search-string in the given line. If it exists, the name X * in front of the search-string is copied to name and its length is returned. X */ X{ Xint c, sl, cs; X X c = strlen( line->contents ); X sl = strlen(search_string); X while( c>0 ) X { if (strncase_equal( search_string, &line->contents[c], sl )==0) X { cs=c; X do X { cs--; X if (isspace(line->contents[cs])) break; X } X while(cs>0); X *length = c-cs; X if (cs) X { (*length)--; cs++; X } X X strncpy( name, &line->contents[cs], *length ); X name[*length]='\0'; X return(1); X } X c--; X } X return(0); X} X Xvoid find_assocs() X/* tries to find 'Foreground-Background'-Associations in the Color-Lines */ X{ Xint i, j; Xchar name1[100], name2[100]; Xint length1, length2; X X for (i=0;i<color_lines;i++) X { if (spc_line("foreground", line[i].line, name1, &length1)) X { for (j=i+1;j>=i-1;j-=2) X { if ((j>=0)&&(j<color_lines)) X { if (spc_line("background", line[j].line, name2, &length2)) X { X if (strcmp(name1, name2)==0) X { line[i].reverse=0; X line[i].help = line[j].color; X line[i].assoc= j; X X line[j].reverse=1; X line[j].help = line[i].color; X line[j].assoc= i; X } X } X } X } X } X else if ((spc_line("background", line[i].line, name1, &length1))&&(line[i].assoc<0)) X { for (j=i+1;j>=i-1;j-=2) X { if ((j>=0)&&(j<color_lines)) X { if (spc_line("border", line[j].line, name2, &length2)) X { X if (strcmp(name1, name2)==0) X { line[i].reverse=1; X line[i].help = line[j].color; X line[i].assoc= j; X X line[j].reverse=0; X line[j].help = line[i].color; X line[j].assoc= i; X } X } X } X } X } X } X} X Xint load_file( fname ) X char *fname; X/* loads the text-file and tries to find color-entries in each line */ X{ XFILE *fp; XTextLine *act, *next; Xchar linebuffer[MAX_LINE_LENGTH]; X X/* load the file with colors */ X longest_colored = 0; X color_lines = 0; X X fp = fopen( fname, "r" ); X if (fp==NULL) X { fprintf( stderr, "can't load file '%s'.\n", fname ); X return(0); X } X X loaded_text = act = NULL; X while (fgets( linebuffer, sizeof linebuffer, fp )!=NULL) X { next = (TextLine *)malloc((unsigned)sizeof(TextLine)); X next->contents = (char *)malloc((unsigned)strlen(linebuffer)+1); X strcpy( next->contents, linebuffer ); X X check_colors( next ); X if (act==NULL) X { loaded_text=act = next; X next->previous = NULL; X } X else X { act->next = next; X next->previous = act; X act = next; X } X } X fclose( fp ); X act->next=NULL; X return(1); X} X Xint write_file( fname ) X char *fname; X{ XFILE *fp; XTextLine *act; X X fp = fopen( fname, "w" ); X if (fp==NULL) return(-1); X act = loaded_text; X while( act ) X { if (fputs( act->contents, fp )==EOF) X { fprintf(stderr, "write error on file '%s'\n", fname); X fclose(fp); X return(-2); X } X act = act->next; X } X fclose( fp ); X return(0); X} X X X/******************************************************************************** X * allocating, freeing, sorting, searching COLORS. * X ********************************************************************************/ X X XColorDef *find_color( name ) X char *name; X/* searches in the tree of colordefinitions for the named color */ X{ XColorDef *erg, *assoc; Xint i; X X for (i=0;i<color_number;i++) X { erg = color[i]; X do X { X if (strcase_equal(erg->name, name)==0) return( erg ); X assoc = erg->associated; X while( assoc ) X { if (strcase_equal(assoc->name, name)==0) return( assoc ); X assoc = assoc->associated; X } X erg = erg->brother; X } X while (erg); X } X return(NULL); X} X Xvoid load_color( act ) X ColorDef *act; X/* allocates a pixel for the color, if it is not already allocated. When it's X * still possible to allocate pixels in the DefaultColormap, this is done and X * the same color is stored in both maps. If no more cells are available in X * the DefaultColormap, the program continues working only in its own map. X */ X{ XXColor scr; Xlong pixel; X X if (act->pixel==NotAllocated) X { if (!only_mine) X { if ( (!XAllocColorCells( display, DefaultColormapOfScreen(screen), True, X NULL, 0, (unsigned long*)&pixel, 1 )) || (pixel>=cells) ) X { X for (pixel=0;pixel<cells;pixel++) X { X if (my_pixel[pixel]) X { XFreeColors( display, DefaultColormapOfScreen(screen), X (unsigned long*)&pixel, 1, 0 ); X } X } X X only_mine=1; X#ifdef CHG_TEXT_WINDOW_COLORMAP X/* when switched on, all windows (not only the textwindow), are displayed X * in my Colormap, when the DefaultColormap hasn't got any more cells available. X * Try the option -gran100 and search for the 'gray'-color in the main-window X * to reach the extremes of the program. X */ X if (tw) X { XSetWindowColormap( display, tw, my_map ); X } X#endif X } X } X if (only_mine) X { for (pixel=cells-1;pixel>=0;pixel--) X { if (my_pixel[pixel]==0) break; X } X /* the reaction to an overflow in the color-map is hard, but X * I can't think of an easy solution for that problem. X */ if (pixel<0) X { fprintf( stderr, "You did it. The Colormap if full.\n"); X if (CellsOfScreen(screen)>MAX_CELLS) X { fprintf( stderr, "Compile the program again with the\n"); X fprintf( stderr, "MAX_CELLS-macro set to an higher value.\n"); X } X exit(0); X } X } X act -> pixel = pixel; X scr.pixel = pixel; X scr.flags = DoRed | DoGreen | DoBlue; X scr.red = act->r << 8; X scr.green = act->g << 8; X scr.blue = act->b << 8; X XStoreColor( display, my_map, &scr ); X if (!only_mine) X XStoreColor( display, DefaultColormapOfScreen(screen), &scr ); X } X my_pixel[act->pixel]++; X} X Xvoid unload_color( act ) X ColorDef *act; X/* The color is not used anymore. It is possible that the color was loaded X * more than once and therefor, the cell can't be freed. X */ X{ X if (act->pixel==NotAllocated) return; X X if ((--my_pixel[act->pixel])==0) X { if (!only_mine) X { XFreeColors( display, DefaultColormapOfScreen(screen), X &act->pixel, 1, 0 ); X } X act->pixel=NotAllocated; X } X} X Xvoid load_text_colors() X/* to load all colors used in the color-lines of the text-file */ X{ Xint i; X X for (i=0;i<color_lines;i++) X { load_color( line[i].color ); X load_color( line[i].help ); X } X} X Xvoid exchange( old, new ) X ColorDef **old; X ColorDef *new; X/* correct exchanging of a loaded color */ X{ X if (*old) X { unload_color( *old ); X } X load_color( new ); X *old = new; X} X X/*----------------------------------------------------------------------------*/ X X/* X * functions to sort the colors X */ X Xint color_name_sort( p1, p2 ) X ColorString *p1, *p2; X{ X return(strcmp(p1->name, p2->name)); X} X Xint color_sort( p1, p2 ) X ColorDef **p1, **p2; X{ Xchar *s1, *s2; X X if ((*p1)->b!=(*p2)->b) return(((*p1)->b>(*p2)->b)?1:-1); X if ((*p1)->g!=(*p2)->g) return(((*p1)->g>(*p2)->g)?1:-1); X if ((*p1)->r!=(*p2)->r) return(((*p1)->r>(*p2)->r)?1:-1); X s1 = index((*p1)->name, ' '); X s2 = index((*p2)->name, ' '); X s1 = s2 = NULL; X X if (s1) X { if (s2) return(strcmp((*p1)->name, (*p2)->name)); X else return(1); X } X else X { if (s2) return(-1); X else return(strcmp((*p1)->name, (*p2)->name)); X } X} X Xint color_sort_r( p1, p2 ) X ColorDef **p1, **p2; X{ X if ((*p1)->b!=(*p2)->b) return(((*p1)->b>(*p2)->b)?-1:1); X if ((*p1)->g!=(*p2)->g) return(((*p1)->g>(*p2)->g)?-1:1); X if ((*p1)->r!=(*p2)->r) return(((*p1)->r>(*p2)->r)?-1:1); X return(0); X} X Xvoid brother_sort( first ) X ColorDef **first; X{ XColorDef *list[1000]; Xint length; X X length = 0; X X list[length] = *first; X while(list[length]->brother) X { list[length+1] = list[length]->brother; X length++; X } X X qsort( (char *)list, length+1, sizeof(ColorDef *), color_sort ); X X list[length]->brother = NULL; X X while(length>0) X { list[length-1]->brother = list[length]; X length--; X } X *first = list[0]; X} X Xvoid associated_sort( first ) X ColorDef *first; X{ XColorDef *list[1000]; Xint length; X X length = 0; X X list[length] = first; X while(list[length]->associated) X { list[length+1] = list[length]->associated; X length++; X } X X qsort( (char *)&list[1], length, sizeof(ColorDef *), color_sort ); X X list[length]->associated = NULL; X X while(length>0) X { list[length-1]->associated = list[length]; X length--; X } X} X X/*----------------------------------------------------------------------------*/ X X/* X * functions to load the color-file and build the tree with colordefinitions X */ X Xchar *cut_digits( name ) X char *name; X/* cuts digits from a color-string. returns a pointer to a static string X * which of course must not be freed. if there where no digits, the original X * pointer is returned. X */ X{ Xstatic char short_name[40]; Xint i; X X i = strlen(name); X if ((i>39)||(!isdigit(name[i-1]))) return(name); X X strcpy( short_name, name ); X i--; X while ((i>0)&&(isdigit(short_name[i]))) X { short_name[i] = '\0'; X i--; X } X return(short_name); X} X Xvoid next_name( act ) X ColorDef *act; X/* collects color-names for the hash-table */ X{ X if (act->pixel==Undefined) X { fprintf(stderr, "%s not defined.\n", act->name); X return; X } X cname[color_names].name = act->name; X cname[color_names].length = strlen(act->name); X cname[color_names].def = act; X color_names++; X} X XColorDef *make_entry( new ) X ColorDef *new; X/* allocates space for the data of a new color */ X{ XColorDef *erg; X X erg = (ColorDef *)malloc((unsigned) sizeof(ColorDef) ); X memcpy( (char *)erg, (char *)new, sizeof(ColorDef) ); X erg -> associated = NULL; X erg -> brother = NULL; X erg -> pixel = NotAllocated; X X return( erg ); X} X Xvoid new_color( new ) X ColorDef *new; X/* searches for overlaps in the color-field and stores the new color */ X{ Xchar *search_name; XColorDef *act; XColorDef *help; Xint i; Xint subname = 0; X X search_name = cut_digits( new->name ); X subname = (search_name!=new->name); X X act = find_color( search_name ); X X if (act) X { if (subname) /* found and associated entry */ X { help = act->associated; X act->associated = make_entry( new ); X act->associated->associated = help; X } X else /* strange: color declared twice ? */ X { if (act->pixel==Undefined) X { memcpy( (char *)act, (char *)new, sizeof(ColorDef)-2*sizeof(ColorDef *) ); X act->pixel = NotAllocated; X } X else X { X help = act->brother; X act->brother = make_entry( new ); X act->brother->brother = help; X } X } X } X else X { for (i=0;i<color_number;i++) X { if ( (new->r==color[i]->r) && (new->g==color[i]->g) && (new->b==color[i]->b) ) break; X } X if (i<color_number) X { help = color[i]->brother; X color[i]->brother = make_entry( new ); X color[i]->brother->brother = help; X } X else X { if (subname) /* indexed name found before original */ X { act = (ColorDef *)malloc((unsigned) sizeof(ColorDef) ); X memset( (char *)act, (char)-1, sizeof(ColorDef) ); X act->pixel = Undefined; X act->name = (char *)malloc((unsigned) strlen(search_name)+1 ); X strcpy( act->name, search_name ); X act->associated = make_entry( new ); X act->brother = NULL; X color[color_number++] = act; X } X else /* found new color */ X { color[color_number++] = make_entry( new ); X } X } X } X} X Xload_standard( act ) X ColorDef *act; X{ XXColor exact_def,screen_def; X X if (XLookupColor( display, DefaultColormapOfScreen(screen), act->name, X &exact_def, &screen_def )) X { act->r = exact_def.red >> 8; X act->g = exact_def.green >> 8; X act->b = exact_def.blue >> 8; X } X new_color( act ); X} X X/*----------------------------------------------------------------------------*/ X Xupdate_map() X/* sets unused pixels in my_map to the colors (with different intensity) X * of the DefaultColormap. X */ X{ XXColor qcols[MAX_CELLS]; Xint i, j; X X j=0; X for (i=0;i<cells;i++) X { if (my_pixel[i]==0) qcols[j++].pixel=i; X } X XQueryColors( display, DefaultColormapOfScreen(screen), qcols, j ); X for (i=0;i<j;i++) X { qcols[i].red = ((long)qcols[i].red *darkness)/100; X qcols[i].green = ((long)qcols[i].green*darkness)/100; X qcols[i].blue = ((long)qcols[i].blue *darkness)/100; X qcols[i].flags = DoRed | DoGreen | DoBlue; X } X XStoreColors( display, my_map, qcols, j ); X} X Xcreate_new_map() X/* get an own colormap */ X{ Xint i; XXColor qcols[MAX_CELLS]; Xunsigned long pixel[MAX_CELLS]; X X/* allocate new colormap and copy the darkened colors of the default-map */ X my_map = XCreateColormap( display, mw, X XDefaultVisualOfScreen(screen), AllocAll); X if (my_map==(Colormap)0) X { fprintf(stderr, "can't create colormap.\n" ); X exit(0); X } X memset( (char *)my_pixel, (char)0, sizeof(my_pixel) ); X X/* copy the default-map */ X for (i=0;i<cells;i++) qcols[i].pixel = i; X XQueryColors( display, DefaultColormapOfScreen(screen), qcols, cells ); X for (i=0;i<cells;i++) X { qcols[i].red = ((long)qcols[i].red *darkness)/100; X qcols[i].green = ((long)qcols[i].green*darkness)/100; X qcols[i].blue = ((long)qcols[i].blue *darkness)/100; X qcols[i].flags = DoRed | DoGreen | DoBlue; X } X XStoreColors( display, my_map, qcols, cells ); X X/* try to allocate the color_cells in the default-map */ X if (XAllocColorCells( display, DefaultColormapOfScreen(screen), True, X NULL, 0, pixel, color_number )) X { int high_value=0; X X /* store the colors into my map and into and into the default-colormap X * as there are enough cells for both. X */ X for (i=0;i<color_number;i++) X { qcols[i].pixel = pixel[i]; X qcols[i].flags = DoRed | DoGreen | DoBlue; X qcols[i].red = color[i]->r << 8; X qcols[i].green = color[i]->g << 8; X qcols[i].blue = color[i]->b << 8; X color[i]->pixel = pixel[i]; X if (pixel[i]>=cells) X { high_value=1; X break; X } X my_pixel[pixel[i]]=1; X } X X if (high_value) X { XFreeColors( display, DefaultColormapOfScreen(screen), X pixel, color_number, 0 ); X only_mine = 1; X } X else X { X XStoreColors( display, DefaultColormapOfScreen(screen), qcols, color_number ); X XStoreColors( display, my_map, qcols, color_number ); X only_mine = 0; X } X } X else only_mine = 1; X X if (only_mine) X { X /* pixels are just used from high to low numbers */ X for (i=0;i<color_number;i++) X { X qcols[i].pixel = cells-i-1; X qcols[i].flags = DoRed | DoGreen | DoBlue; X qcols[i].red = color[i]->r << 8; X qcols[i].green = color[i]->g << 8; X qcols[i].blue = color[i]->b << 8; X color[i]->pixel = cells-i-1; X my_pixel[cells-i-1]=1; X } X XStoreColors( display, my_map, qcols, color_number ); X X /* afterwards, all free pixels of the default-map are allocated X * and set to the values of the new colormap. X */ X i=0; X while( XAllocColorCells( display, DefaultColormapOfScreen(screen), True, X NULL, 0, &pixel[i], 1 ) ) X { qcols[i].pixel = pixel[i]; X i++; X } X XQueryColors( display, my_map, qcols, i ); X XStoreColors( display, DefaultColormapOfScreen(screen), qcols, i ); X XFreeColors( display, DefaultColormapOfScreen(screen), pixel, i, 0 ); X only_mine = 1; X } X X/* the pixels for black, white have to be used from my_map, since X * the entries of the DefaultColormap are possibly darkened. X */ X black = find_color( BLACK_STRING )->pixel; X my_pixel[black]++; X white = find_color( WHITE_STRING )->pixel; X my_pixel[white]++; X grey = find_color( GREY_STRING )->pixel; X my_pixel[grey]++; X} X Xdestroy_colormap() X/* not used */ X{ Xunsigned long pixel[MAX_CELLS]; Xint i, j; XColorDef *assoc, *erg; X X XFreeColormap( display, my_map ); X j=0; X if (!only_mine) X { for (i=0;i<cells;i++) X { if (my_pixel[i]) pixel[j++] = i; X } X XFreeColors( display, DefaultColormapOfScreen(screen), pixel, j, 0 ); X } X my_map = NULL; X memset( (char *)my_pixel, (char)0, sizeof(my_pixel) ); X X for (i=0;i<color_number;i++) X { erg = color[i]; X do X { erg->pixel = NotAllocated; X assoc = erg->associated; X while( assoc ) X { assoc->pixel = NotAllocated; X assoc = assoc->associated; X } X erg = erg->brother; X } X while (erg); X } X} X X END_OF_xcol.part1 if test 24317 -ne `wc -c <xcol.part1`; then echo shar: \"xcol.part1\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. # additional concatenation of splitted file if test -f xcol.part2 ; then echo ' concatenation of "xcol.part1" and "xcol.part2" to "xcol.c".' cat xcol.part1 xcol.part2 > xcol.c echo ' removing "xcol.part1" and "xcol.part2".' rm xcol.part1 xcol.part2 else echo ' unpack the second part now.' fi exit 0 dan ----------------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com 632 Petaluma Ave, Sebastopol, CA 95472 800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104 Opinions expressed reflect those of the author only.