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 >
C/C++ Source or Header  |  1992-08-25  |  36KB  |  1,297 lines

  1. /***
  2.    Colormap by Barry Solomon, Copyright 1991, 1992.  Permission to copy and/or
  3.    distribute this program is hereby granted, given that recognition of my
  4.    contribution is noted.
  5.  
  6.    This program displays the hardware colormap by creating a two-dimensional
  7.    grid either 16x16 or 4x4 (8 or 4 plane visuals respectivly) of little
  8.    filled rectangles of size cellwidth x cellheight.  Each filled rectangle
  9.    will be filled with a unique color from the colortable.
  10.  
  11.    Button Commands:
  12.     When the user depresses button 1 in a "colorcell", the color
  13.     that is displayed by that filled rectangle will be changed to cyan until
  14.     the button is released when the previous colormap will be re-installed. 
  15.     The color cell id and the rgb value of that cell will be displayed.
  16.       Button1       - Highlight a colorcell
  17.       Button2       - Allocate an unallocated colorcell
  18.       Shift-Button2 - Allocate and set the color of an unallocated colorcell.
  19.       Button3       - Unallocate a colorcell previously allocated by us.
  20.  
  21.    Key Commands:
  22.     'a' - cycle the colors in the installed colormap
  23.     'A' - run a single white color through the installed colormap
  24.     'd' - display the default colormap
  25.     'g' - Get all available colors and allocate
  26.     'l' - load a mixed color ramp and display
  27.     's' - show all allocated colormap entries
  28.     'S' - Unshow all allocated colormap entries
  29.     't' - toggle between a 4 and 8 bit visual and redisplay the colormap
  30.     'u' - Unget all colors that we have allocated
  31.     'q' - quit
  32.  
  33.    Author Change Log
  34.     1.0  ????? 1990   Barry   Initial implementation
  35.     2.0  Nov27 1990   Barry   Use rectangles in leu of windows for color cells.
  36.     2.1  Dec18 1990   Barry   Fix non-uninstall of mycolormap
  37.     2.2  Feb13 1991   Barry   Add input arg to disable colormap swapping.
  38.     2.3  Apr19 1991   Barry   Modify for true color devices
  39.     2.4  May03 1991   Barry   Add in toggling for different visuals
  40.     2.5  Apr22 1992   Barry   Add animation, MINCELL and lint this code.
  41.     2.6  Apr22 1992   Barry   Add display of allocated colorcells
  42.     2.7  May11 1992   Barry   Add allocation/deallocation of colorcells
  43.     2.8  Aug19 1992   Barry   Fixed "show cells" if all cells allocated.
  44. ***/
  45.  
  46. #include <X11/Xlib.h>
  47. #include <X11/Xutil.h>
  48. #include <X11/cursorfont.h>
  49. #include <sys/timeb.h>
  50. #include <stdio.h>
  51.  
  52. #define     MINCELL 0         /* Lowest numbered cell to animate cmap */
  53. #define     MIN_COLOR_CELLS 15   /* Min number of colors needed to run */
  54.  
  55. #define     CHAR    0
  56. #define     STRING  1
  57. #define     INTEGER 2
  58.  
  59. Display     *display;
  60. Visual      *vis;                /* Pointer to the current visual */
  61. int         dep;                 /* depth of the current visual */
  62. GC          gc, rgc;             /* Graphics contexts */
  63.  
  64. Colormap    dcm, *icm, *icm2;    /* Default colormap and nstalled cmaps */
  65. Colormap    mycmap;              /* Local colormap */
  66. XColor      colors[257];         /* Array for copying colors */
  67. XColor      LocColors[257];
  68. Bool        AllocatedCells[256];
  69. Bool        MyAllocedCells[256]; /* array of my color cells */
  70. int         dcms;                /* default colormap size */
  71. int         numcells;            /* Number of colors in current visual */
  72. int         cellwidth;           /* Width of colorcell window */
  73. int         cellheight;          /* Height of colorcell window */
  74. int         cols, rows;          /* row and column loop indices */
  75. Bool        truecolor = False;
  76.  
  77. Window      root, MainWin, pw, w;
  78. int         banner_height = 25;  /* height of the clrmap id display */
  79. int         win_height, win_width;
  80. int         yoff, xoff;          /* x & y offsets for colorcell placement */
  81.  
  82. char        message[100];
  83.  
  84. int         event_mask = 0;
  85.  
  86.  
  87. /***************************************************** output_message */
  88. output_message( Message, LineNumber)
  89. /**
  90.     Display a message to the user in the banner area
  91. **/
  92.     char    *Message;
  93.     int        LineNumber;
  94. {
  95. /*--------------------------------------------------------------------*/
  96.     XSetForeground(display, gc, 0);
  97.  
  98.     if (LineNumber == 1)
  99.     XFillRectangle(display, MainWin, gc, 0, 0,
  100.                win_width, banner_height + 4);
  101.     else
  102.     XFillRectangle(display, MainWin, gc, 5, 12 * (LineNumber - 1) + 3,
  103.                win_width, 12);
  104.  
  105.     XDrawImageString(display, MainWin, gc, 5, 12 * (LineNumber),
  106.              Message, strlen(Message));
  107.  
  108.     XFlush(display);
  109.  
  110. }
  111.  
  112. /************************************************************ GetInput */
  113. void GetInput( Buffer, InputType)
  114. /**
  115.     Wait for the next KeyPress and defer all other events
  116.     and return keystring[0] in 'input'
  117. **/
  118.     char *Buffer;
  119.     int  InputType;
  120. {
  121.     XEvent          ev;
  122.     char            string[20], *keystring;
  123.     KeySym          key;
  124.     Bool            done = False;
  125.     char            lstring[133];
  126.     int             lvalue = 0;
  127. /*---------------------------------------------------------------------*/
  128.     strcpy(lstring, "");
  129.  
  130.     while (!done) {
  131.  
  132.     XMaskEvent(display, KeyPressMask, &ev);
  133.  
  134.     XLookupString(&ev, string, 20, &key, NULL);
  135.     keystring = XKeysymToString(key);
  136.  
  137.     switch (InputType) {
  138.  
  139.     case CHAR:
  140.         if ((strlen(keystring) < 2) || (!strcmp(keystring, "Return"))) {
  141.         *Buffer = keystring[0];
  142.         done = True;
  143.         }
  144.         break;
  145.  
  146.     case INTEGER:
  147.  
  148.         if (!strcmp(keystring, "Return")) {
  149.         if (strcmp(lstring, ""))
  150.             *(int *) Buffer = lvalue;
  151.         done = True;
  152.         }
  153.  
  154.         if (!strcmp(keystring, "BackSpace") && (strlen(lstring) > 0)) {
  155.         lstring[strlen(lstring) - 1] = '\0';
  156.         lvalue /= 10;
  157.         }
  158.  
  159.         if ((keystring[0] >= '0') && (keystring[0] <= '9')) {
  160.         lvalue = 10 * lvalue + (keystring[0] - '0');
  161.         sprintf(lstring, "%d", lvalue);
  162.         }
  163.         break;
  164.  
  165.     case STRING:
  166.  
  167.         if (!strcmp(keystring, "Return")) {
  168.         strcpy(Buffer, lstring);
  169.         done = True;
  170.         }
  171.  
  172.         if (!strcmp(keystring, "BackSpace") && (strlen(lstring) > 0)) {
  173.         lstring[strlen(lstring) - 1] = '\0';
  174.         }
  175.         if (!strcmp(keystring, "period")) {
  176.         sprintf(lstring, "%s.\0", lstring);
  177.         }
  178.         if (!strcmp(keystring, "slash")) {
  179.         sprintf(lstring, "%s/\0", lstring);
  180.         }
  181.         if (!strcmp(keystring, "numbersign")) {
  182.         sprintf(lstring, "%s#\0", lstring);
  183.         }
  184.         if (strlen(keystring) < 2) {
  185.         sprintf(lstring, "%s%s\0", lstring, keystring);
  186.         }
  187.  
  188.         break;
  189.  
  190.     }    /* end switch(InputType) */
  191.  
  192.     output_message( lstring, 2);
  193.  
  194.     }    /* end while(!done) */
  195.  
  196. }
  197.  
  198. /******************************************************* get_visual() */
  199. Bool get_visual(depth)
  200. /**
  201.     Get a visual of depth *depth if possible
  202. **/
  203.     int    *depth;  /* The depth of the desired visual */
  204. {
  205.     XVisualInfo *visualList;
  206.     long        vmask = VisualNoMask;
  207.     XVisualInfo vinfo, *v;           /* visual information */
  208.     int         big_map = 0, istat;
  209.     Bool        success = False;
  210. /*--------------------------------------------------------------------*/
  211.     visualList = XGetVisualInfo( display, vmask, &vinfo, &istat);
  212.  
  213.     switch (*depth) {
  214.  
  215.         case 4:
  216.             for (v = visualList; v < visualList + istat; v++)
  217.                 if ((v->depth == 4)&&(v->class == PseudoColor)) {
  218.                     vinfo = *v;
  219.                     success = True;
  220.                     break;
  221.                 }
  222.             break;
  223.  
  224.         case 8:
  225.             for (v = visualList; v < visualList + istat; v++)
  226.                 if ((v->depth == 8)&&(v->class == PseudoColor)) {
  227.                     vinfo = *v;
  228.                     success = True;
  229.                     break;
  230.                 }
  231.             break;
  232.  
  233.         default:
  234.             for (v = visualList; v < visualList + istat; v++) {
  235.                 if ((v->colormap_size>big_map)&&(v->class==PseudoColor)) {
  236.                     big_map = v->colormap_size;
  237.                     vinfo   = *v;
  238.                     success = True;
  239.                 }
  240.                 if (big_map >= 256) break;
  241.             }
  242.         
  243.     }; /* end switch(depth) */
  244.  
  245.     if (success) {
  246.         *depth   = vinfo.depth;
  247.         vis      = vinfo.visual;
  248.         numcells = vis->map_entries;
  249.         return(True);
  250.     }
  251.     else
  252.         return(False);
  253.  
  254. } /* end get_visual() */
  255.  
  256. /****************************************************** create_window */
  257. Window create_window(parent, xpos, ypos, width, height)
  258. /**
  259.     Create the main window
  260. **/
  261.     Window   parent;
  262.     int      xpos, ypos;
  263.     int      width, height;
  264. {
  265.     Window   NewWin;
  266.     int      winfo_mask;
  267.     XSetWindowAttributes winfo;
  268.     XWMHints wmhints;
  269. /*--------------------------------------------------------------------*/
  270.     winfo.background_pixmap     = ParentRelative;
  271.     winfo.background_pixel      = 0;
  272.     winfo.border_pixmap         = CopyFromParent;
  273.     winfo.border_pixel          = 0;
  274.     winfo.bit_gravity           = NorthWestGravity;
  275.     winfo.win_gravity           = NorthWestGravity;
  276.     winfo.backing_store         = WhenMapped;
  277.     winfo.backing_planes        = 0;
  278.     winfo.save_under            = True;
  279.     winfo.event_mask            = NoEventMask;
  280.     winfo.do_not_propagate_mask = NoEventMask;
  281.     winfo.override_redirect     = False;
  282.     winfo.colormap              = mycmap;
  283.     winfo_mask                  = CWEventMask |
  284.                                   CWBackingStore |
  285.                                   CWBorderPixel |
  286.                                   CWBackPixel |
  287.                                   CWColormap;
  288.  
  289.     NewWin = XCreateWindow( display, parent, xpos, ypos, width, height, 0,
  290.                             dep, CopyFromParent, vis, winfo_mask, &winfo);
  291.  
  292.     XSelectInput( display, NewWin, event_mask);
  293.  
  294.     /* Allow input
  295.     */
  296.     wmhints.flags = InputHint;
  297.     wmhints.input = True;
  298.     XSetWMHints ( display, NewWin, &wmhints);
  299.  
  300.     /* Set window banner title
  301.     */
  302.     XStoreName( display, NewWin, "Colormap by Solotech v2.8");
  303.  
  304.     /* Map the window to the display and flush the output queue
  305.     */
  306.     XMapWindow( display, NewWin);
  307.     XFlush( display);
  308.  
  309.     return(NewWin);
  310.  
  311. } /* end create_window() */
  312.  
  313. /****************************************************** toggle_visual */
  314. toggle_visual()
  315. {
  316.     int num;
  317.     int clrcells;
  318. /*--------------------------------------------------------------------*/
  319.     dep = (dep == 4) ? 8 : 4;
  320.  
  321.     if (!get_visual(&dep)) {
  322.         dep = (dep == 4) ? 8 : 4;
  323.         return;
  324.     }
  325.  
  326.     clrcells = (dcms > vis->map_entries) ? vis->map_entries : dcms;
  327.  
  328. /*
  329.  *  Re-Initialize my colormap
  330.  */
  331.     XFreeColormap( display, mycmap);
  332.     mycmap = XCreateColormap( display, MainWin, vis, AllocAll);
  333.     icm    = XListInstalledColormaps( display, root, &num);
  334.  
  335. /*
  336.  *  Copy the colors from the installed colormap to mycmap
  337.  */
  338.     XQueryColors( display, *icm,   colors, clrcells);
  339.     XStoreColors( display, mycmap, colors, clrcells);
  340.  
  341. /* 
  342.  *  Recalculate the rows and columns for display
  343.  */
  344.     numcells   = (numcells > 256) ? 256 : numcells;
  345.     rows       = (numcells > 254) ? 16 : 4;
  346.     cols       = rows;
  347.     cellheight = (win_height) / rows;
  348.     cellwidth  = (win_width ) / cols;
  349.  
  350.     XDestroyWindow( display, MainWin);
  351.     MainWin = create_window( pw, 0, 0, win_width, win_height+banner_height);
  352.     
  353.     XSync( display, 0);
  354.  
  355. } /* end toggle_visual() */
  356.  
  357. /**************************************************** display_default */
  358. void display_default()
  359. /**
  360.     Display the default colormap
  361.  
  362.     If the user hits a "d" then display the default colormap
  363.     and wait for the user to generate one of the following:
  364.         to hit any key
  365.         to generate an exposure or configure event
  366.         to press a mouse button in the colormap window
  367. **/
  368. {
  369.     XEvent  ev;
  370.     char    string[20], *keystring;
  371.     KeySym  key;
  372.     Bool    Done = False;
  373. /*--------------------------------------------------------------------*/
  374.     sprintf( message, "ColorMapId Id = %d (default)",dcm);
  375.     output_message( message, 1);
  376.  
  377.     XInstallColormap( display, dcm);
  378.  
  379. /*
  380.  *  Wait for a significant event before continuing and replace the event back
  381.  *  on the queue to be processed by the main event loop
  382.  */
  383.     while (!Done) {
  384.  
  385.         XNextEvent( display, &ev);
  386.         switch (ev.type) {
  387.             case ConfigureNotify :
  388.             case ButtonPress :
  389.             case Expose :
  390.             XPutBackEvent( display, &ev);
  391.             Done = True;
  392.                 break;
  393.             case KeyPress :
  394.             XLookupString( &ev, string, 20, &key, NULL);
  395.             keystring = XKeysymToString( key);
  396.             if ((keystring[0] != 'd') && (keystring[0] != 'D')) 
  397.             XPutBackEvent( display, &ev);
  398.             Done = True;
  399.                 break;
  400.         }
  401.     }
  402.  
  403.     /* Reinstall mycmap and clear the message
  404.     */
  405.     XInstallColormap( display, mycmap);
  406.  
  407.     sprintf( message, "ColorMapId Id = %d", *icm);
  408.     output_message( message, 1);
  409.  
  410. } /* end display_default() */
  411.  
  412. /*************************************************** load_color_range */
  413. load_color_range()
  414. /**
  415. **/
  416. {
  417.     XEvent    ev;
  418.     char      string[20], *keystring;
  419.     KeySym    key;
  420.     Colormap  scratch_cmap;
  421.     int       i;
  422.     Bool      Done = False;
  423. /*--------------------------------------------------------------------*/
  424. /*
  425.  *  Create a sratch colormap to load our color range
  426.  *  so as to not mess up mycmap
  427.  */
  428.     scratch_cmap = XCreateColormap( display, MainWin, vis, AllocAll);
  429.  
  430. /*
  431.  *  Create/Load the mixed color map
  432.  */
  433.     for (i=0; i<MINCELL; i++) {
  434.         LocColors[i].pixel = i;
  435.         LocColors[i].red   = colors[i].red;
  436.         LocColors[i].green = colors[i].green;
  437.         LocColors[i].blue  = colors[i].blue;
  438.         LocColors[i].flags = DoRed | DoGreen | DoBlue;    
  439.     }
  440.     for (i=MINCELL; i< numcells; i++) {
  441.         LocColors[i].pixel = i;
  442.         LocColors[i].red   = ((numcells-i) * 65535 ) / numcells;
  443.         LocColors[i].green = ((         i) * 65535 ) / numcells;
  444.         LocColors[i].blue  = ((numcells-i/2) * 65535 ) / numcells;
  445.         LocColors[i].flags = DoRed | DoGreen | DoBlue;
  446.     }
  447.     XStoreColors( display, scratch_cmap, LocColors, numcells);
  448.     XInstallColormap( display, scratch_cmap);
  449.     XFlush( display);
  450.  
  451. /*
  452.  *  Wait for a significant event before continuing and replace the event back
  453.  *  on the queue to be processed by the main event loop
  454.  */
  455.     while (!Done) {
  456.  
  457.         XNextEvent( display, &ev);
  458.         switch (ev.type) {
  459.             case ConfigureNotify :
  460.             case ButtonPress :
  461.             case Expose :
  462.             XPutBackEvent( display, &ev);
  463.             Done = True;
  464.                 break;
  465.             case KeyPress :
  466.             XLookupString( &ev, string, 20, &key, NULL);
  467.             keystring = XKeysymToString( key);
  468.             if ((keystring[0] != 'l') && (keystring[0] != 'L')) 
  469.             XPutBackEvent( display, &ev);
  470.             Done = True;
  471.                 break;
  472.         }
  473.     }
  474.  
  475. /*
  476.  *  We're done.  Reinstall mycmap and trash the scratch amp
  477.  */
  478.     XInstallColormap( display, mycmap);
  479.     XFreeColormap( display, scratch_cmap);
  480.  
  481. /*
  482.  *  Reprint the colormap id display
  483.  */
  484.     sprintf( message, "ColorMapId = %d", *icm);
  485.     output_message( message, 1);
  486.  
  487. } /* end load_color_range() */
  488.  
  489. /****************************************************** AnimateColormap */
  490. AnimateColormap()
  491. {
  492.     int             i;
  493.     XColor          SaveColor;
  494.     int             Count, NumColors;
  495.     int             Delay = 20;
  496.     struct timeb    t1, t2;
  497. /*---------------------------------------------------------------------*/
  498.     NumColors = numcells;
  499.  
  500. /*
  501.  *  Get the colors that are in the colormap
  502.  */
  503.     for (i = 0; i < 256; i++) {
  504.     LocColors[i].pixel = i;
  505.     LocColors[i].flags = DoRed | DoGreen | DoBlue;
  506.     }
  507.     XQueryColors(display, mycmap, LocColors, NumColors);
  508.  
  509. /*
  510.  *  Cycle the colors NumCycles times
  511.  */
  512.     for (Count = 0; Count < (NumColors - MINCELL); Count++) {
  513.  
  514.     ftime(&t1);
  515.  
  516.     SaveColor.pixel = LocColors[NumColors - 1].pixel;
  517.     SaveColor.red = LocColors[NumColors - 1].red;
  518.     SaveColor.green = LocColors[NumColors - 1].green;
  519.     SaveColor.blue = LocColors[NumColors - 1].blue;
  520.  
  521.     for (i = NumColors - 1; i > MINCELL; i--) {
  522.         LocColors[i].red = LocColors[i - 1].red;
  523.         LocColors[i].green = LocColors[i - 1].green;
  524.         LocColors[i].blue = LocColors[i - 1].blue;
  525.     }
  526.  
  527.     LocColors[i].pixel = SaveColor.pixel;
  528.     LocColors[i].red = SaveColor.red;
  529.     LocColors[i].green = SaveColor.green;
  530.     LocColors[i].blue = SaveColor.blue;
  531.  
  532.     XStoreColors(display, mycmap, LocColors, NumColors);
  533.     XSync(display, 0);
  534.  
  535.     ftime(&t2);
  536.     while ((t2.millitm - t1.millitm) < Delay)
  537.         ftime(&t2);
  538.  
  539.     }
  540.  
  541.     XStoreColors(display, mycmap, colors, NumColors);
  542.     XSync(display, 0);
  543.  
  544. }
  545.  
  546. /****************************************************** AnimateColormap */
  547. TraverseColormap()
  548. {
  549.     int             i = 0;
  550.     XColor          SaveColor;
  551.     int             Count, NumColors, NumCycles;
  552.     int             Delay;
  553.     struct timeb    t1, t2;
  554. /*---------------------------------------------------------------------*/
  555.     NumColors = numcells;
  556.     NumCycles = 1;
  557.     Delay = 50;
  558.  
  559. /*
  560.  *  Get the colors that are in the colormap
  561.  */
  562.     for (i = 0; i < 256; i++) {
  563.     LocColors[i].pixel = i;
  564.     LocColors[i].flags = DoRed | DoGreen | DoBlue;
  565.     }
  566.     XQueryColors(display, mycmap, LocColors, NumColors);
  567.  
  568.     XSynchronize(display, 1);
  569. /*
  570.  *  Cycle the colors NumCycles times
  571.  */
  572.     for (Count = 0; Count < NumCycles; Count++) {
  573.  
  574.     for (i = MINCELL; i < NumColors; i++) {
  575.  
  576.         ftime(&t1);
  577.  
  578.         SaveColor.red = LocColors[i].red;
  579.         SaveColor.green = LocColors[i].green;
  580.         SaveColor.blue = LocColors[i].blue;
  581.  
  582.         LocColors[i].red = 65535;
  583.         LocColors[i].green = 65535;
  584.         LocColors[i].blue = 65535;
  585.  
  586.         XStoreColor(display, mycmap, &LocColors[i]);
  587.         XSync(display, 0);
  588.  
  589.         LocColors[i].red = SaveColor.red;
  590.         LocColors[i].green = SaveColor.green;
  591.         LocColors[i].blue = SaveColor.blue;
  592.  
  593.         XStoreColor(display, mycmap, &LocColors[i]);
  594.         XSync(display, 0);
  595.  
  596.         ftime(&t2);
  597.         while ((t2.millitm - t1.millitm) < Delay)
  598.         ftime(&t2);
  599.     }
  600.  
  601.     }
  602.  
  603.     XSynchronize(display, 0);
  604.     XStoreColors(display, mycmap, colors, NumColors);
  605.     XSync(display, 0);
  606.  
  607. }
  608.  
  609. /*************************************************** UpdateCellDisplay */
  610. void UpdateCellDisplay( CellId)
  611.     int CellId;
  612. {
  613.     int xpos, ypos;
  614. /*---------------------------------------------------------------------*/
  615. /*
  616.  *  Update CellId to reflect its current allocation
  617.  */
  618.     xpos = ((CellId % cols) * cellwidth) + xoff;
  619.     ypos = ((CellId / cols) * cellheight) + yoff + banner_height;
  620. /*
  621.  *  Draw a filled rectangle with interior color_table_index = index
  622.  */
  623.     XSetForeground(display, gc, CellId);
  624.     XFillRectangle(display, MainWin, gc, xpos, ypos, cellwidth, cellheight);
  625. /*
  626.  *  Draw a black border around the filled polygon
  627.  */
  628.     XSetForeground(display, gc, 0);
  629.     XDrawRectangle(display, MainWin, gc, xpos, ypos, cellwidth, cellheight);
  630. /*
  631.  *  Add a diagonal slash if this color cell is Allocated
  632.  */
  633.     if (AllocatedCells[CellId] == True)
  634.     XDrawLine(display, MainWin, rgc,
  635.           xpos, ypos, (xpos + cellwidth), (ypos + cellheight));
  636. /*
  637.  *  Add an extra diagonal slash if this color cell is Allocated by me
  638.  */
  639.     if (MyAllocedCells[CellId] == True)
  640.     XDrawLine(display, MainWin, rgc,
  641.           xpos, (ypos + cellheight), (xpos + cellwidth), ypos);
  642.     
  643. }
  644.  
  645. /************************************************************* update */
  646. update()
  647. {
  648.     int   xpos, ypos, index;
  649.     int   cur_row, cur_col;
  650.     int   num;
  651. /*--------------------------------------------------------------------*/
  652. /* 
  653.  *  Calculate an offset value so as to center the colortable grid in
  654.  *  the window
  655.  */
  656.     xoff = 0.45 * (win_width  - (cols*cellwidth));
  657.     yoff = 0.70 * (win_height - (rows*cellheight));
  658.  
  659. /*
  660.  *  Fill a rectagle for each color in the colormap
  661.  */
  662.     for (cur_row=0; cur_row<rows; cur_row++) {
  663.         for (cur_col=0; cur_col<cols; cur_col++) {
  664.  
  665.             index = (cur_row*cols)+cur_col;
  666.             if (index >= vis->map_entries) index = 0;
  667.  
  668.             xpos  = (cur_col*cellwidth)  + xoff;
  669.             ypos  = (cur_row*cellheight) + yoff + banner_height;
  670. /*
  671.  *          Draw a filled rectangle with interior color_table_index = index
  672.  */
  673.             XSetForeground( display, gc, index);
  674.             XFillRectangle( display,MainWin,gc,xpos,ypos,cellwidth,cellheight);
  675. /*
  676.  *          Draw a black border around the filled polygon
  677.  */
  678.             XSetForeground( display, gc, 0);
  679.             XDrawRectangle( display,MainWin,gc,xpos,ypos,cellwidth,cellheight);
  680. /*
  681.  *          Add a diagonal slash if this color cell is Allocated
  682.  */
  683.         if (AllocatedCells[index] == True)
  684.         XDrawLine(display, MainWin, rgc,
  685.             xpos, ypos, (xpos + cellwidth), (ypos + cellheight));
  686. /*
  687.  *          Add an extra diagonal slash if this color cell is Allocated by me
  688.  */
  689.         if (MyAllocedCells[index] == True)
  690.         XDrawLine(display, MainWin, rgc,
  691.             xpos, (ypos + cellheight), (xpos + cellwidth), ypos);
  692.  
  693.         } /* end for cur_col */
  694.     } /* end for cur_row */
  695.  
  696. /*
  697.  *  Query the current colormap id and display
  698.  */
  699.     icm2 = XListInstalledColormaps( display, root, &num);
  700.     icm = (*icm2 != mycmap) ? icm2 : icm;
  701.  
  702. /*
  703.  *  Display the colormap id to the user
  704.  */
  705.     sprintf( message, "ColorMapId Id = %d", *icm);
  706.     output_message( message, 1);
  707.  
  708.     XFlush( display);
  709.  
  710. } /* end update() */
  711.  
  712. /*************************************************** SetColorCellValue */
  713. void SetColorCellValue( CellId)
  714. {
  715.     char            ColorName[1024];
  716.     XColor          NewColor;
  717.     Status          ColorParsed;
  718.     char            Buffer[40];
  719. /*---------------------------------------------------------------------*/
  720.  
  721.     if (MyAllocedCells[CellId] == True) {
  722. /*
  723.  *      Get the name of a color
  724.  */
  725.     output_message("Enter Color Name: ", 1);
  726.     GetInput(ColorName, STRING);
  727. /*
  728.  *      Restore the default color map message
  729.  */
  730.     sprintf(message, "ColorMapId Id = %d", *icm);
  731.     output_message(message, 1);
  732. /*
  733.  *      Store the color into the default colormap and colors array
  734.  */
  735.     if (ColorName[0] != NULL) {
  736.         ColorParsed = XParseColor(display, *icm,
  737.                       ColorName, &colors[CellId]);
  738.         if (ColorParsed) {
  739.         XStoreColor(display, *icm, &colors[CellId]);
  740.         }
  741.         else {
  742.         XBell(display, 40);
  743.         sprintf(Buffer, "Invalid color spec: %s", ColorName);
  744.         output_message(Buffer, 2);
  745.         }
  746.     }
  747.  
  748.     }
  749. }
  750.  
  751. /************************************************* ShowAllocatedCells */
  752. void ShowAllocatedCells()
  753. /**
  754.     Display all the allocated color cells by putting a slash through them
  755. **/
  756. {
  757.     int             i, xpos, ypos, index;
  758.     int             cur_row, cur_col;
  759.     int             NextNumColors, NumColors = 0, Pixels[256], Planes[16];
  760.     Status          GotDemCells = False;
  761. /*--------------------------------------------------------------------*/
  762. /*
  763.  *  Assume all cells are allocated
  764.  */
  765.     for (i = 0; i < numcells; i++)
  766.     AllocatedCells[i] = True;
  767. /*
  768.  *  Attempt to allocated as many cells as possible
  769.  *  when we allocate then Pixels containes those cells that are free
  770.  */
  771.     NextNumColors = numcells;
  772.     while (!GotDemCells) {
  773.  
  774.     NumColors = NextNumColors--;
  775.  
  776.     GotDemCells = XAllocColorCells(display, *icm, False, Planes,
  777.                        0, Pixels, NumColors);
  778.     if (GotDemCells)
  779.         XFreeColors(display, *icm, Pixels, NumColors, 0);
  780.  
  781.     if (NextNumColors < 1) {
  782.         GotDemCells = True;
  783.         NumColors = 0;        
  784.     }
  785.  
  786.     }
  787. /*
  788.  *  For each cell in Pixels that we were able to allocate
  789.  *  set its slot in AllocatedCells to False
  790.  */
  791.     for (i = 0; i < NumColors; i++)
  792.     AllocatedCells[Pixels[i]] = False;
  793.  
  794.     update();
  795.  
  796. } /* end ShowAllocatedCells() */
  797.  
  798. /************************************************** AllocateColorCell */
  799. void AllocateColorCell( CellId, Allocate, SetColorValue)
  800.     int    CellId;
  801.     Bool Allocate; /* True = allocate it, False = Unallocate it */
  802.     Bool SetColorValue;
  803. {
  804.     int             i, j, index;
  805.     int             NextNumColors, NumColors = 0, Pixels[256], Planes[16];
  806.     Status          GotDemCells = False;
  807.     Bool            Allocated = False;
  808.     int             Pixels2[256];
  809. /*--------------------------------------------------------------------*/
  810.     if (Allocate == False) {
  811. /*
  812.  *      If the cell is allocated
  813.  *      then free up the color cell
  814.  */
  815.     if (MyAllocedCells[CellId] == True) {
  816.         XFreeColors(display, *icm, &CellId, 1, 0);
  817.         MyAllocedCells[CellId] = False;
  818.         AllocatedCells[CellId] = False;
  819.     }
  820.     }
  821.     else {
  822. /*
  823.  *    Attempt to allocated as many cells as possible
  824.  *    when we allocate then Pixels containes those cells that are free
  825.  *    search for CellId and free all other cells
  826.  */
  827.     NextNumColors = numcells;
  828.     while (!GotDemCells) {
  829.  
  830.         NumColors = NextNumColors--;
  831.  
  832.         GotDemCells = XAllocColorCells(display, *icm, False, Planes,
  833.                        0, Pixels, NumColors);
  834.         if (GotDemCells) {
  835.  
  836.         for (i = 0, j = 0; i < NumColors; i++) {
  837.             if (Pixels[i] != CellId)
  838.             Pixels2[j++] = Pixels[i];
  839.             else {
  840.             MyAllocedCells[Pixels[i]] = True;
  841.             AllocatedCells[Pixels[i]] = True;
  842.             Allocated = True;
  843.             }
  844.         }
  845.  
  846.         if (Allocated == True)
  847.             XFreeColors(display, *icm, Pixels2, NumColors - 1, 0);
  848.         else
  849.             XFreeColors(display, *icm, Pixels, NumColors, 0);
  850.  
  851.         }
  852.             else
  853.                 if (NextNumColors <= 0) {
  854.                     output_message("All colorcells allocated", 2);
  855.                     return;
  856.                 }
  857.     }
  858.     }
  859.  
  860.     if (Allocated && SetColorValue)
  861.     SetColorCellValue(CellId);
  862.  
  863.     UpdateCellDisplay(CellId);
  864.  
  865. }
  866.  
  867. /******************************************************** GetAllCells */
  868. GetAllCells()
  869. {
  870.     int             i, xpos, ypos, index;
  871.     int             cur_row, cur_col;
  872.     int             NextNumColors, NumColors = 0, Pixels[256], Planes[16];
  873.     Status          GotDemCells = False;
  874. /*--------------------------------------------------------------------*/
  875. /*
  876.  *  Attempt to allocated as many cells as possible
  877.  *  when we allocate then Pixels containes those cells that are free
  878.  */
  879.     NextNumColors = numcells;
  880.     while ((!GotDemCells) && NextNumColors) {
  881.  
  882.     NumColors = NextNumColors--;
  883.  
  884.     GotDemCells = XAllocColorCells(display, *icm, False, Planes,
  885.                        0, Pixels, NumColors);
  886.  
  887.     }
  888. /*
  889.  *  All cells are allocated
  890.  */
  891.     for (i = 0; i < numcells; i++)
  892.     AllocatedCells[i] = True;
  893. /*
  894.  *  For each cell in Pixels that we were able to allocate
  895.  *  set its slot in MyAllocedCells
  896.  */
  897.     for (i = 0; i < NumColors; i++) {
  898.     MyAllocedCells[Pixels[i]] = True;    
  899.     }
  900.  
  901.     update();
  902.  
  903. }
  904.  
  905. /****************************************************** UngetAllCells */
  906. void UngetAllCells()
  907. /**
  908.     Loop through MyAllocedCells and unallocate any that we have gotten
  909. **/
  910. {
  911.     int             i;
  912. /*--------------------------------------------------------------------*/
  913.     for (i = 0; i < numcells; i++) {
  914.  
  915.     if (MyAllocedCells[i] == True) {
  916.  
  917.         MyAllocedCells[i] = False;
  918.         AllocatedCells[i] = False;
  919.  
  920.         XFreeColors(display, *icm, &i, 1, 0);
  921.  
  922.         UpdateCellDisplay(i);
  923.  
  924.     }
  925.  
  926.     }
  927.     XFlush(display);
  928.  
  929. }
  930.  
  931. /********************************************************* event_loop */
  932. event_loop()
  933. {
  934.     XEvent          ev;
  935.     int             num, i, j;
  936.     char            string[20], *keystring;
  937.     KeySym          key;
  938.     unsigned int    clr_mask = DoRed | DoGreen | DoBlue;
  939.     Bool            update_picture = True;
  940.     Bool            done = False;
  941.     int             bgcolor;
  942. /*--------------------------------------------------------------------*/
  943.     while (!done) {
  944.  
  945.     if (!XPending(display) && update_picture) {
  946.         update();
  947.         update_picture = False;
  948.     }
  949.  
  950.     XNextEvent(display, &ev);
  951.  
  952.     switch (ev.type) {
  953.  
  954.     case ButtonPress:
  955.  
  956.         /* Find the row and column indices of the mouse postion where
  957.          * the button was pressed */
  958.         i = -999;
  959.         j = -999;
  960.         if ((ev.xbutton.x - xoff) >= 0)
  961.         i = (ev.xbutton.x - xoff) / cellwidth;
  962.         if ((ev.xbutton.y - yoff - banner_height) >= 0)
  963.         j = (ev.xbutton.y - yoff - banner_height) / cellheight;
  964.  
  965.         /* Calculate the colortable index */
  966.         if ((i < 0) || (i > cols - 1) || (j < 0) || (j > rows - 1))
  967.         bgcolor = 0;
  968.         else
  969.         bgcolor = (j * cols) + i;
  970.  
  971.         switch (ev.xbutton.button) {
  972.  
  973.         case 2:
  974.         AllocateColorCell(bgcolor, True,
  975.                   (ev.xbutton.state & ShiftMask));
  976.         break;
  977.  
  978.         case 3:
  979.         AllocateColorCell(bgcolor, False, False);
  980.         break;
  981.  
  982.         default:
  983.  
  984.         /* With a 4-bit visual there are 15 entries The last
  985.          * row/col needs to wrap around */
  986.         if (bgcolor > vis->map_entries - 1)
  987.             bgcolor = 0;
  988.  
  989.         /* Store cyan in the colorcell of the mouse click */
  990.         XStoreNamedColor(display, mycmap, "cyan", bgcolor, clr_mask);
  991.  
  992.         /* Output colormap id message */
  993.         sprintf(message, "Cell = %3d, RGB = %5.2f %5.2f %5.2f",
  994.             bgcolor,
  995.             colors[bgcolor].red / (float) 65535,
  996.             colors[bgcolor].green / (float) 65535,
  997.             colors[bgcolor].blue / (float) 65535);
  998.         output_message(message, 2);
  999.         break;
  1000.         }
  1001.  
  1002.         XFlush(display);
  1003.  
  1004.         break;
  1005.  
  1006.     case ButtonRelease:
  1007.  
  1008.         /* Restore the color cells that have been modified. */
  1009.         XStoreColors(display, mycmap, colors, numcells);
  1010.  
  1011.         break;
  1012.  
  1013.     case EnterNotify:
  1014.  
  1015.         /* If we found the color then Inquire the currently loaded
  1016.          * colormap copy its colors and load our colormap with them
  1017.          * and store cyan into the colortable entry calculated above
  1018.          * and load our colormap into the server */
  1019.  
  1020.         icm2 = XListInstalledColormaps(display, root, &num);
  1021.         if (*icm2 != mycmap) {
  1022.  
  1023.         icm = icm2;
  1024.  
  1025.         if (dcms < numcells) {
  1026.             XQueryColors(display, *icm, colors, dcms);
  1027.             XStoreColors(display, mycmap, colors, dcms);
  1028.         }
  1029.         else {
  1030.             XQueryColors(display, *icm, colors, numcells);
  1031.             XStoreColors(display, mycmap, colors, numcells);
  1032.         }
  1033.  
  1034.         XInstallColormap(display, mycmap);
  1035.  
  1036.         XSetForeground(display, gc, 0);
  1037.         XFillRectangle(display, MainWin, gc, 0, 0,
  1038.                    win_width, banner_height);
  1039.  
  1040.         sprintf(message, "ColorMapId Id = %d", *icm);
  1041.         output_message(message, 1);
  1042.  
  1043.         }
  1044.  
  1045.         break;
  1046.  
  1047.     case LeaveNotify:
  1048.  
  1049.         /* Uninstall my colormap and re-install the colormap that was
  1050.          * installed previously XUninstallColormap( display, mycmap); */
  1051.         XInstallColormap(display, *icm);
  1052.  
  1053.         break;
  1054.  
  1055.     case ColormapNotify:
  1056.  
  1057.         icm2 = XListInstalledColormaps(display, root, &num);
  1058.         if (*icm2 != mycmap) {
  1059.         icm = icm2;
  1060.         if (dcms < numcells)
  1061.             XQueryColors(display, *icm, colors, dcms);
  1062.         else
  1063.             XQueryColors(display, *icm, colors, numcells);
  1064.         }
  1065.  
  1066.         XSetForeground(display, gc, 0);
  1067.         XFillRectangle(display, MainWin, gc, 0, 0, win_width, banner_height);
  1068.  
  1069.         sprintf(message, "ColorMapId Id = %d", *icm);
  1070.         output_message(message, 1);
  1071.  
  1072.         break;
  1073.  
  1074.     case KeyPress:
  1075.  
  1076.         XLookupString(&ev, string, 20, &key, NULL);
  1077.         keystring = XKeysymToString(key);
  1078.  
  1079.         if (strlen(keystring) < 2)
  1080.         switch (keystring[0]) {
  1081.  
  1082.         case 'a':    /* Animate the colormap */
  1083.             AnimateColormap();
  1084.             break;
  1085.  
  1086.         case 'A':    /* Animate the colormap */
  1087.             TraverseColormap();
  1088.             break;
  1089.  
  1090.         case 'd':    /* Display the default colormap */
  1091.             display_default();
  1092.             break;
  1093.  
  1094.         case 'l':    /* Load a colorramp and display */
  1095.             load_color_range();
  1096.             break;
  1097.  
  1098.         case 's':    /* Show allocated colorcells */
  1099.             ShowAllocatedCells();
  1100.             break;
  1101.  
  1102.         case 'S':    /* UnShow allocated colorcells */
  1103.             for (i = 0; i < numcells; i++)
  1104.             if (MyAllocedCells[i] == False)
  1105.                 AllocatedCells[i] = False;
  1106.             update();
  1107.             break;
  1108.  
  1109.         case 't':    /* Toggle between different visuals */
  1110.             toggle_visual();
  1111.             break;
  1112.  
  1113.         case 'u':    /* Unallocate all the cells previously
  1114.                  * allocated */
  1115.             UngetAllCells();
  1116.             break;
  1117.  
  1118.         case 'g':    /* Get as many colorcells as possible */
  1119.             GetAllCells();
  1120.             break;
  1121.  
  1122.         case 'q':
  1123.             XInstallColormap(display, *icm);
  1124.             done = True;
  1125.             break;
  1126.  
  1127.         }    /* end switch(keystring[0]) */
  1128.  
  1129.         break;
  1130.  
  1131.     case Expose:
  1132.  
  1133.         /* Set the update_picture flag so that when all the events
  1134.          * have been processed we know that the picture needs to be
  1135.          * updated with any changes */
  1136.         XFillRectangle(display, MainWin, gc, 0, 0,
  1137.                win_width, win_height + banner_height);
  1138.         update_picture = True;
  1139.         break;
  1140.  
  1141.     case ConfigureNotify:
  1142.  
  1143.         /* Store the new window width and height.  Use the values to
  1144.          * calculate a new colorcell width and height */
  1145.         win_height = ev.xconfigure.height - banner_height;
  1146.         win_width = ev.xconfigure.width;
  1147.         cellheight = (win_height) / rows;
  1148.         cellwidth = (win_width) / cols;
  1149.  
  1150.         /* Need to figure out how to pass the resize down to the child
  1151.          * windows */
  1152.         if (ev.xconfigure.window == pw)
  1153.         XResizeWindow(display, MainWin,
  1154.                   win_width, win_height + banner_height);
  1155.  
  1156.         XSync(display, 0);
  1157.  
  1158.         break;
  1159.  
  1160.     default:
  1161.         break;
  1162.  
  1163.     }    /* end switch() */
  1164.  
  1165.     }    /* end while(!done) */
  1166.  
  1167. }/* end event_loop() */
  1168.  
  1169. /*************************************************************** main */
  1170. main( argc, argv)
  1171.     int  argc;
  1172.     char *argv[];
  1173. {
  1174.     char        cont;
  1175.     int         num;
  1176.     int         screen, index;
  1177.     char        Dashes[2];
  1178. /*--------------------------------------------------------------------*/
  1179. /*
  1180.  *  Initialize the connection to the XServer and get some default
  1181.  *  values for a start
  1182.  */
  1183.     display   = XOpenDisplay( NULL);
  1184.     screen    = XDefaultScreen( display);
  1185.     dcm       = DefaultColormap( display, screen);
  1186.     vis       = DefaultVisual( display, screen);
  1187.     root      = RootWindow( display, screen);
  1188.     dcms      = vis->map_entries;
  1189.     truecolor = (vis->class == TrueColor) ? True : False;
  1190.     dep       = DefaultDepth( display, screen);
  1191.  
  1192.     get_visual(&dep);
  1193.  
  1194. /*
  1195.  *  See if there are at least 16 colors to display.  If there are less
  1196.  *  than 16, ask the user if s/he wants to continue anyway
  1197.  */
  1198.     if (numcells < MIN_COLOR_CELLS ) {
  1199.     printf("Your default visual is not set for color display\n");
  1200.         printf("number of colorcells = %d\nContinue anyway?", numcells);
  1201.         scanf("%c", &cont);
  1202.         if (tolower(cont) != 'y') exit(0);
  1203.     }
  1204.  
  1205. /*
  1206.  *  Currently, we are only dealing with either a 16 or 256 entry
  1207.  *  colortable, so rows and cols will be set to present a pretty 
  1208.  *  colortable layout of 4x4 or 16x16
  1209.  */
  1210.     numcells = (numcells > 256) ? 256 : numcells;
  1211.     rows     = (numcells > 254) ? 16 : 4;
  1212.     cols     = (numcells+rows-1)/rows;
  1213.  
  1214. /*
  1215.  *  Initialize the colors array's pixels value
  1216.  *  for use in the QueryColors call.  The pixel field needs to be set
  1217.  *  to the colortable index of the color that we want information about
  1218.  */
  1219.     for (index = 0; index < numcells; index++) {
  1220.         colors[index].pixel = index;
  1221.         MyAllocedCells[index] = False;
  1222.     AllocatedCells[index] = False;
  1223.     }
  1224.  
  1225. /*
  1226.  *  Initialize my colormap
  1227.  */
  1228.     mycmap = XCreateColormap( display, root, vis, AllocAll);
  1229.     icm    = (Colormap *)XListInstalledColormaps( display, root, &num);
  1230.     XQueryColors( display, *icm,   colors, dcms);
  1231.     XStoreColors( display, mycmap, colors, dcms);
  1232.  
  1233. /*
  1234.  *  Depending on the input arg, set the event mask
  1235.  */
  1236.     if (argv[1] == NULL) 
  1237.         event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
  1238.                           | ButtonPressMask | ButtonReleaseMask
  1239.                           | EnterWindowMask | LeaveWindowMask;
  1240.     else
  1241.         event_mask = ExposureMask | StructureNotifyMask | KeyPressMask;
  1242.  
  1243.     XSelectInput( display, root, ColormapChangeMask);
  1244.  
  1245. /*
  1246.  *  Create the main window
  1247.  */
  1248.  
  1249.     xoff = 5;
  1250.     yoff = 5;
  1251.  
  1252.     if (rows == 4) {
  1253.         cellwidth  = 80;
  1254.         cellheight = 40;
  1255.     }
  1256.     else {
  1257.         cellwidth  = 20;
  1258.         cellheight = 10;
  1259.     }
  1260.  
  1261.     win_height = (rows * cellheight) + yoff;
  1262.     win_width  = (cols * cellwidth)  + xoff;
  1263.  
  1264.     pw = create_window( root, 0, -banner_height, win_width, win_height);
  1265.     MainWin  = create_window( pw, 0, 0, win_width, win_height);
  1266.  
  1267. /*
  1268.  *  Create a graphics context for the window and set the background color
  1269.  */
  1270.     gc = XCreateGC( display, MainWin, 0, 0);
  1271.     XSetBackground( display, gc, 1);
  1272.  
  1273. /*
  1274.  *  Create a graphics context for reverse video action
  1275.  */
  1276.     rgc = XCreateGC( display, MainWin, 0, 0);
  1277.     XSetForeground( display, rgc, BlackPixel(display, screen));
  1278.     XSetBackground( display, rgc, WhitePixel(display, screen));
  1279.     XSetFillStyle( display, rgc, FillOpaqueStippled);
  1280.     Dashes[0] = 1;
  1281.     Dashes[1] = 1;
  1282.     XSetDashes( display, rgc, 0, Dashes, 2);    
  1283.     XSetLineAttributes( display, rgc, 1, LineDoubleDash, CapNotLast,
  1284.             JoinMiter);
  1285.  
  1286. /*
  1287.  *  Start the event loop
  1288.  */
  1289.     event_loop();
  1290.  
  1291. /*
  1292.  *  Close the connection to the display before quiting
  1293.  */
  1294.     XCloseDisplay( display);
  1295.  
  1296. } /* main() */
  1297.