home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xtici.zip / xtici / resources.c < prev    next >
C/C++ Source or Header  |  1991-08-28  |  38KB  |  1,346 lines

  1. /*
  2.  * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
  3.  *     All Rights Reserved
  4.  * 
  5.  * This file is a component of an X Window System client which uses the Xcms 
  6.  * Color Management System.  TekColor is a trademark of Tektronix, Inc.  The
  7.  * TekColor Editor is the subject of U.S. and foreign patents pending.  The
  8.  * term "TekHVC" designates a particular color space that is the subject of
  9.  * U.S. Patent No. 4,985,853 (equivalent foreign patents pending).
  10.  * Permission is hereby granted to use, copy, modify, sell, and otherwise
  11.  * distribute this software and its documentation for the X Window System
  12.  * environment, for any purpose and without fee, provided that:
  13.  * 
  14.  * 1.    The code and documentation are only used to implement a 
  15.  *      TekColor Editor in an X Window System environment; and
  16.  * 2.    This copyright and permission notice is reproduced in all copies
  17.  *     of the code and in supporting documentation.
  18.  * 
  19.  * Permission is granted to modify this code as required to allow it to
  20.  * be compiled on any host computer, provided that the functionality of
  21.  * the TekColor Editor is not modified in any way.  A description of any 
  22.  * modifications must be sent to Tektronix, Inc.  Contact 
  23.  * Tektronix Inc., P.O. Box 1000, Mail Station 60-850, 
  24.  * Network Displays Division Engineering, Wilsonville, OR 97070.
  25.  *
  26.  * Tektronix makes no representation about the suitability of this software
  27.  * for any purpose.  It is provided "as is" and with all faults.
  28.  * 
  29.  * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
  30.  * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  31.  * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
  32.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  33.  * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
  34.  * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  35.  * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
  36.  * 
  37.  *    NAME
  38.  *        resources - manage objects manipulated by the interface
  39.  *
  40.  *    DESCRIPTION
  41.  *        This is the lowest level of the interface, actually modifying
  42.  *        objects.  Some of these objects are located on the server,
  43.  *        some located in this file.
  44.  *        In addition, some X objects used by the interface are 
  45.  *        created here, even though they are not strictly manipulated 
  46.  *        by the interface. Some objects and the routines to control 
  47.  *        them have been partitioned into other files because of this 
  48.  *        file size - for example, selection.c and package.c
  49.  */
  50. #ifndef LINT
  51. static char *copy_notice = "Copyright 1991 Tektronix, Inc.";
  52. #ifdef RCS_ID
  53. static char *rcsid=  "$Header: resources.c,v 1.3 91/08/28 10:03:20 adamsc Exp $";
  54. #endif /* RCS_ID */
  55. #endif /* LINT */
  56.  
  57. /*
  58.  *      EXTERNAL INCLUDES
  59.  */
  60.  
  61.  
  62. /*
  63.  *      INTERNAL INCLUDES
  64.  */
  65. #include <stdio.h>
  66. #include "xtici.h"
  67. #include <X11/cursorfont.h>
  68. #include <X11/StringDefs.h>
  69. #include <X11/Intrinsic.h>
  70. #include "cursors.h"
  71. #include "icon.h"
  72.  
  73. /*
  74.  *      EXTERNS
  75.  */
  76. extern Bool restoreFill;
  77. extern Status XcmsTekHVCClipC();
  78. extern Status XcmsTekHVCClipV();
  79. extern Status XcmsTekHVCClipVC();
  80.  
  81. /*
  82.  *      GLOBALS
  83.  */
  84. #ifdef DEC
  85. #  define GLOBAL    global
  86. #else
  87. #  define GLOBAL
  88. #endif
  89.  
  90. GLOBAL Display        *dpy;
  91. GLOBAL XcmsCCC        pDefaultCCC;
  92. GLOBAL XVisualInfo  visInfo;
  93. GLOBAL Colormap    cmap;
  94.  
  95. /*
  96.  * This is the value of the current color;
  97.  * Could be a pointer into the currentMap.
  98.  */
  99. GLOBAL XcmsColor currentHvc;
  100. /*
  101.  * This is the value of the current color in RGB,
  102.  * however, it is only updated when needed - not always current.
  103.  */
  104. GLOBAL XColor currentRgb = {0, 0, 0, 0, DoRed | DoGreen | DoBlue};
  105. /*
  106.  * This is the value of the current color in u'v'Y,
  107.  * however, it is only updated when needed - not always current.
  108.  */
  109. GLOBAL XcmsCIEuvY currentUvy = {0.0, 0.0, 0.0};
  110.  
  111. /*
  112.  * This structure mimics the colormap stored in the server.
  113.  * We need this because some colors are not reachable by the server,
  114.  * so they cannot be stored there.
  115.  * This could be an array of hvc's, but using XcmsColors allows changes
  116.  * to be made more quickly.  The drawback is the increased size, of course.
  117.  */
  118. GLOBAL XcmsColor *currentMap = (XcmsColor *)NULL;
  119.  
  120. /*
  121.  * This is used to cache checkpointed values.
  122.  */
  123. GLOBAL XcmsColor *cpmap = (XcmsColor *)NULL;
  124.  
  125. GLOBAL Cursor normalCursor, hvcCursor, waitCursor, grabCursor;
  126.  
  127. GLOBAL int *edited = NULL;
  128.  
  129. GLOBAL int GamutComp = GamutCompChroma;
  130.  
  131. /*
  132.  * This variable is used to control which interface fill options are available.
  133.  * It is first set by the available size of the colormap; filling is not
  134.  * allowed if it uses more than 2/3 of the map.
  135.  * It is further restricted if any interface color falls in the block
  136.  * of cells reserved for filling the object.
  137.  */
  138. GLOBAL int allowFill = FillAny;
  139.  
  140. /*
  141.  *      LOCAL DEFINES
  142.  */
  143. #define MaxIfColors 12
  144.  
  145. /*
  146.  * Steal the top part of the colormap for the huebar.
  147.  */
  148. #define HuebarColors    72
  149.  
  150. /*
  151.  * Steal the next part of the map to fill the leaf.
  152.  */
  153. #define LeafColors    56
  154.  
  155. /*
  156.  *      LOCAL TYPEDEFS
  157.  */
  158.  
  159. /*
  160.  *      LOCALS VARIABLES
  161.  */
  162. #ifdef DEBUG
  163. #  define STATIC
  164. #else
  165. #  define STATIC        static
  166. #endif /* DEBUG */
  167.  
  168. /*
  169.  * This array is used to check if XcmsStoreColors clamped a chroma.
  170.  * The number of colors stored at one time depends on colormap size,
  171.  * so it must be dynamically allocated.
  172.  */
  173. STATIC unsigned char *clampCheck;
  174.  
  175. /*
  176.  * This could be dynamically sized, but it isn't worth it.
  177.  * If the interface needs more than this many colors,
  178.  * we are probably in trouble anyway.
  179.  */
  180. STATIC Pixel ifColors[MaxIfColors];
  181. STATIC int ifColorCt = 0;
  182.  
  183. /* TODO: Does the local client need this ??? */
  184. STATIC Colormap tmpMap;
  185.  
  186. STATIC Pixel huebarBase = 0;
  187. /*
  188.  * Use HVC because that is the natural computational system
  189.  * Cache precomputed MaxChromaValues for the constant hues.
  190.  * Compute this on the fly for the local client
  191.  */
  192. STATIC XcmsColor constantHuebar[HuebarColors];
  193. /* This is the base to use when empty - it is the widget background */
  194. STATIC Pixel huebarBackground = ~(Pixel)0;
  195.  
  196. /* Values are always computed in the leaf widget. */
  197. STATIC Pixel leafBase = 0;
  198.  
  199. /*
  200.  *      LOCAL FUNCTION DECLARATIONS
  201.  */
  202. STATIC int IfColorChanged();
  203.  
  204. #ifdef XDEBUG
  205. STATIC char *routine_name;
  206. STATIC char *CONSTRAIN_COLOR = "ConstrainColor";
  207. STATIC char *COPY_ARRAY = "CopyArray";
  208. STATIC char *COPY_COLORMAP = "CopyColormap";
  209. STATIC char *EDIT_UVY_CELLS = "EditUvyCells";
  210. STATIC char *GET_COLORS = "GetColors";
  211. STATIC char *UNCACHE_CELL = "UncacheCell";
  212. #endif
  213.  
  214.  
  215. /*
  216.  * Store the given cell in the backup map.  If the index is -1,
  217.  * store the entire map.
  218.  */
  219. void CacheCell(index)
  220. int index;
  221. {
  222.     if (index < 0)
  223.     bcopy(currentMap, cpmap, mapSize * sizeof(XcmsColor));
  224.     else
  225.     bcopy(¤tMap[index], &cpmap[index], sizeof(XcmsColor));
  226. }
  227.  
  228. /*
  229.  *  Force a change in the colormap.
  230.  *  Apply constraints as proper.
  231.  */
  232. /* ARGSUSED */
  233. void ChangeHvcCells(hvcs, len, method)
  234. XcmsColor *hvcs;
  235. int len;
  236. unsigned char method;
  237. {
  238.     int i;
  239.  
  240.     for (i = 0; i < len; i++) {
  241.     bcopy((char *)&hvcs[i],(char *)¤tMap[hvcs[i].pixel],sizeof(XcmsColor));
  242.         ConstrainColor(hvcs[i].pixel);
  243.     bcopy((char *)¤tMap[hvcs[i].pixel], (char *)&hvcs[i], sizeof(XcmsColor));
  244.     }
  245. }
  246.  
  247. /*
  248.  * Clear all of the edited index marks
  249.  */
  250. void ClearMapEdited(limit)
  251. int limit;
  252. {
  253.     int i;
  254.     int easy = limit / 32;
  255.     int rest = limit % 32;
  256.     int mask;
  257.  
  258.     for (i = 0; i < easy; i++)
  259.     edited[i] = 0;
  260.  
  261.     if (rest) {
  262.     mask = (1 << (rest+1)) - 1;
  263.     edited[easy] &= ~mask;
  264.     }
  265. }
  266.  
  267. /*****************************************************************************
  268.  *
  269.  * This gets the default CCC of the display.
  270.  * This checks for a PseudoColor visual for that display.
  271.  *
  272.  * If all this is ok then pick the largest colormap possible.
  273.  * Set up resources based on visuals and the map size of visual in use.
  274.  *
  275.  *****************************************************************************/
  276. void ValidateDisplay()
  277. {
  278.     long mask;
  279.     XVisualInfo *list, *visList;
  280.     XVisualInfo template;
  281.     int i, ct;
  282.     int visCt;
  283.     int maxMapSize = 0;
  284.     extern void ClearMapEdited();
  285.  
  286.     /* determine if the display supports the extension */
  287.     if ((pDefaultCCC = XcmsDefaultCCC(dpy, DefaultScreen(dpy))) == NULL) {
  288.     Error("Failed to find the Default XcmsCCC.\n\
  289. Check to make sure the extension property is loaded on the root window.");
  290.     } 
  291.     switch(GamutComp) {
  292.     case GamutCompValue:
  293.         XcmsSetCompressionProc(pDefaultCCC, XcmsTekHVCClipV, NULL);
  294.         break;
  295.     case GamutCompClosest:
  296.         XcmsSetCompressionProc(pDefaultCCC, XcmsTekHVCClipVC, NULL);
  297.         break;
  298.     case GamutCompChroma:
  299.     default:
  300.         XcmsSetCompressionProc(pDefaultCCC, XcmsTekHVCClipC, NULL);
  301.         break;
  302.     }
  303.  
  304.     /* find the interesting visuals */
  305.     /* only use PseudoColor visuals */
  306.     template.class = reqVisual;
  307.     mask = VisualClassMask;
  308.     list = XGetVisualInfo(dpy, mask, &template, &ct);
  309.  
  310.     visList = (XVisualInfo *)XtCalloc(ct, sizeof(XVisualInfo));
  311.     visCt = 0;
  312.  
  313.     for (i = 0; i < ct; i++) {
  314.     /* just in case */
  315.     if (list[i].class != reqVisual)
  316.         continue;
  317.     /* use the largest possible visual */
  318.     if (1 << list[i].depth > maxMapSize) {
  319.         maxMapSize = 1 << list[i].depth;
  320.         visInfo = list[i];
  321.     }
  322.     visList[visCt++] = list[i];
  323.     }
  324.  
  325.     /* Error will exit, so don't bother to free list */
  326.     if (visCt == 0) {
  327.     Error("No PseudoColor visual on this screen");
  328.     }
  329.     mapSize = maxMapSize;
  330.  
  331.     edited = (int *)XtCalloc((maxMapSize + 31)/32, sizeof(int));
  332.     clampCheck = (unsigned char *)XtCalloc(maxMapSize, sizeof(unsigned char));
  333.  
  334.     ClearMapEdited(maxMapSize);
  335.     huebarBase = maxMapSize - HuebarColors;
  336.     leafBase = huebarBase - LeafColors;
  337.     /* don't allow this option if filling leaves less than 1/3 of map */
  338.     if (leafBase < maxMapSize / 3)
  339.     allowFill = FillHuebar;
  340.     if (huebarBase < maxMapSize / 3)
  341.     allowFill = FillNone;
  342.  
  343.     XFree((char *)list);
  344. }
  345.  
  346. /*
  347.  * Apply the current clamping constraint(s) to the passed cells
  348.  * in the cached colormap (currentMap).  The backup map is not modified.
  349.  * If the backup (cpmap) is restored, constraints are applied at that time.
  350.  */
  351. void ConstrainColor(index)
  352. Pixel index;
  353. {
  354.     XcmsColor tmp;
  355.  
  356.     bcopy((char *)¤tMap[index], (char *)&tmp, sizeof(XcmsColor));
  357. #ifdef XDEBUG
  358.     routine_name = CONSTRAIN_COLOR;
  359. #endif
  360.     StoreAllocColors(dpy, cmap, &tmp, 1, XcmsTekHVCFormat);
  361.  
  362.     if (clampState & ClampMonitor) {
  363.     /* which should be applied only if clamping to monitor */
  364.     switch (GamutComp) {
  365.         case GamutCompValue:
  366.         currentMap[index].spec.TekHVC.V = tmp.spec.TekHVC.V;
  367.         break;
  368.         case GamutCompClosest:
  369.         currentMap[index].spec.TekHVC.V = tmp.spec.TekHVC.V;
  370.         case GamutCompChroma:
  371.         default:
  372.         currentMap[index].spec.TekHVC.C = tmp.spec.TekHVC.C;
  373.     }
  374.     }
  375. }
  376.  
  377. /*
  378.  * Adjust the passed value to fall in the legal range determined by
  379.  * the current colormap size.
  380.  */
  381. Pixel ConstrainIndex(index)
  382. Pixel index;
  383. {
  384.     /* Pixel is unsigned, so index cannot be negative */
  385.     if (index >= mapSize)
  386.     return((Pixel)(mapSize - 1));
  387.     else
  388.     return(index);
  389. }
  390.  
  391. /*
  392.  * Copy the target XcmsColor array into our editable map.
  393.  * If protect is set, allow user to restore interface colors.
  394.  */
  395. STATIC char *protectIfHelp = "\
  396. The new colormap has different values in at least one cell that the editor\n\
  397. is using.  If you continue, any image will be displayed correctly, but the\n\
  398. editor may not be usable.  If you cancel, editor interface colors will remain\n\
  399. unchanged, but the image may not be displayed correctly.\n\
  400. \n\
  401. In either case, colors not used by the interface will be changed to reflect\n\
  402. the colors in the new colormap.";
  403.  
  404. /* for now, is not used by the local client; used to load a colormap */
  405. /* void CopyArray(old, size, protect)
  406.  * XcmsColor *old;
  407.  * int size;
  408.  * Boolean protect;
  409.  * {
  410.  *     int i;
  411.  *     int limit;
  412.  *     Boolean restore = False;
  413.  *     XcmsColor ifCols[MaxIfColors];
  414.  *     int ifColsCt = ifColorCt;
  415.  * 
  416.  *     /* if we need to protect interface colors, cache them first */
  417. /*     if (protect) {
  418.  *     for (i = 0; i < ifColsCt; i++)
  419.  *         bcopy((char *)¤tMap[ifColors[i]], (char *)&ifCols[i], sizeof(XcmsColor));
  420.  *     }
  421.  * 
  422.  *     /* often we are copying from existing arrays; avoid that */
  423. /*     if (old != cpmap)
  424.  *     bcopy(old, cpmap, size * sizeof(XcmsColor));
  425.  *     /* set properly to do stores; reset later to avoid adjustments */
  426. /*     if (old != currentMap)
  427.  *     bcopy(old, currentMap, size * sizeof(XcmsColor));
  428.  * 
  429.  *     /* if huebar is filled, don't modify those cells */
  430. /*     if ( (leafState & LeafFilled) && (size >= leafBase) )
  431.  *     limit = leafBase;
  432.  *     else if ( (huebarState != HuebarEmpty) && (size >= huebarBase) )
  433.  *     limit = huebarBase;
  434.  *     else
  435.  *     limit = size;
  436.  * #ifdef XDEBUG
  437.  *     routine_name = COPY_ARRAY;
  438.  * #endif
  439.  *     StoreAllocColors(dpy, cmap, currentMap, limit, XcmsTekHVCFormat);
  440.  * 
  441.  *     if ( (leafState & LeafFilled) && (huebarState == HuebarEmpty)
  442.  *         && (size >= huebarBase) ) {
  443.  * #ifdef XDEBUG
  444.  *     routine_name = COPY_ARRAY;
  445.  * #endif
  446.  *     (void) StoreAllocColors(dpy, cmap, currentMap+huebarBase, size - huebarBase, XcmsTekHVCFormat);
  447.  *     }
  448.  * 
  449.  *     /* If needed, restore the interface colors */
  450. /*     if (protect) {
  451.  *     if (IfColorChanged(cpmap, ifCols, ifColsCt))
  452.  *         restore = (Warning("Modify interface color cell?", protectIfHelp)
  453.  *                 != MessageContinue);
  454.  *     }
  455.  *     if (restore) {
  456.  *     for (i = 0; i < ifColsCt; i++)
  457.  *         cpmap[ifCols[i].pixel] = ifCols[i];
  458.  * #ifdef XDEBUG
  459.  *     routine_name = COPY_ARRAY;
  460.  * #endif
  461.  *     (void) StoreAllocColors(dpy, cmap, ifCols, ifColsCt, XcmsTekHVCFormat);
  462.  *     }
  463.  * 
  464.  *     bcopy(cpmap, currentMap, size * sizeof(XcmsColor));
  465.  * }
  466.  */
  467. /*
  468.  * Copy the target map into our editable map.
  469.  * If protect is set, allow user to restore interface colors.
  470.  */
  471. void CopyColormap(old, from, to, protect)
  472. Colormap old;
  473. Pixel from, to;
  474. Boolean protect;
  475. {
  476.     int i;
  477.     Pixel limit, size = to - from + 1;
  478.     Boolean restore = False;
  479.     XcmsColor ifCols[MaxIfColors];
  480.     /* ifColorCt may change, so save value that matches remembered array */
  481.     int ifColsCt = ifColorCt;
  482.  
  483.     /* if we need to protect interface colors, cache them first */
  484.     if (protect) {
  485.     for (i = 0; i < ifColsCt; i++)
  486.         bcopy((char *)¤tMap[ifColors[i]], (char *)&ifCols[i], sizeof(XcmsColor));
  487.     }
  488.  
  489.     if (XcmsQueryColors(dpy, old, cpmap+from, size, XcmsTekHVCFormat)
  490.     == XcmsFailure) {
  491. #ifdef XDEBUG
  492.         fprintf (stderr, "Warning: XcmsQueryColors failed in CopyColormap\n");
  493. #endif
  494.     }
  495.     /* set the current map properly to store colors; */
  496.     /* reset later to avoid unwanted coordinate adjustments */
  497.     bcopy(cpmap+from, currentMap+from, size * sizeof(XcmsColor));
  498.  
  499.     /* if huebar filled, don't modify those cells */
  500.     if ( (leafState & LeafFilled) && (size >= leafBase) )
  501.     limit = leafBase - from;
  502.     else if ( (huebarState != HuebarEmpty) && (size >= huebarBase) )
  503.     limit = huebarBase - from;
  504.     else
  505.     limit = size;
  506. #ifdef XDEBUG
  507.     routine_name = COPY_COLORMAP;
  508. #endif
  509.     (void) StoreAllocColors(dpy, cmap, currentMap+from, (int)limit, 
  510.                 XcmsTekHVCFormat);
  511.  
  512.     /* if necessary, do piece beyond leaf hues */
  513.     if ( (leafState & LeafFilled) && (huebarState == HuebarEmpty)
  514.         && (to >= huebarBase) ) {
  515. #ifdef XDEBUG
  516.     routine_name = COPY_COLORMAP;
  517. #endif
  518.     StoreAllocColors(dpy, cmap, currentMap+huebarBase, 
  519.              (int)(to - huebarBase + 1), XcmsTekHVCFormat);
  520.  
  521.     }
  522.  
  523.     /* If needed, restore the interface colors */
  524.     if (protect) {
  525.     if (IfColorChanged(cpmap, ifCols, ifColsCt))
  526.         restore = (Warning("Modify interface color cell?", protectIfHelp)
  527.                 != MessageContinue);
  528.     }
  529.     if (restore) {
  530.     for (i = 0; i < ifColsCt; i++)
  531.         cpmap[ifCols[i].pixel] = ifCols[i];
  532. #ifdef XDEBUG
  533.     routine_name =    COPY_COLORMAP;
  534. #endif
  535.     StoreAllocColors(dpy, cmap, ifCols, ifColsCt, XcmsTekHVCFormat);
  536.     }
  537.  
  538.     bcopy(cpmap, currentMap, size * sizeof(XcmsColor));
  539. }
  540.  
  541. /*
  542.  * Create a colormap to use for editing from the interface visual.
  543.  * Allocate all colors in the map.  Copy the colors of the default
  544.  * colormap into it for starters.
  545.  */
  546. void CreateColormap()
  547. {
  548.     Pixel i, cmap_size;
  549.     XcmsColor tmpColor;
  550.  
  551.     /* The window identifies the screen, not visual or depth */
  552.     cmap = XCreateColormap(dpy, RootWindow(dpy, visInfo.screen), 
  553.                    visInfo.visual, AllocAll);
  554.     XcmsSetCompressionProc(XcmsCCCOfColormap(dpy, cmap),
  555.                  pDefaultCCC->gamutCompProc, NULL);
  556.     tmpMap = XCreateColormap(dpy, RootWindow(dpy, visInfo.screen), 
  557.                  visInfo.visual, AllocAll);
  558.     XcmsSetCompressionProc(XcmsCCCOfColormap(dpy, tmpMap),
  559.                  pDefaultCCC->gamutCompProc, NULL);
  560.  
  561.     cmap_size = 1 << visInfo.depth;
  562.     currentMap = (XcmsColor *)XtCalloc(cmap_size, sizeof(XcmsColor));
  563.     cpmap = (XcmsColor *)XtCalloc(cmap_size, sizeof(XcmsColor));
  564.     tmpColor.format = XcmsTekHVCFormat;
  565.     tmpColor.spec.TekHVC.H=tmpColor.spec.TekHVC.V=tmpColor.spec.TekHVC.C=0.0;
  566.  
  567.     for (i = 0; i < cmap_size; i++) {
  568.     tmpColor.pixel = i;
  569.     bcopy((char *)&tmpColor, (char *)&cpmap[i], sizeof(XcmsColor));
  570.     bcopy((char *)&tmpColor, (char *)¤tMap[i], sizeof(XcmsColor));
  571.     }
  572.  
  573.     /* copy colormap entries */
  574.     CopyColormap(DefaultColormap(dpy, visInfo.screen), (Pixel)0, 
  575.                  (Pixel)(cmap_size - 1), (Boolean) False);
  576.  
  577.     /* Get the current HVC value for the first time */
  578.     /* arbitrarily use the WhitePixel to start */
  579.     currentHvc.format = XcmsTekHVCFormat;
  580.     currentHvc.pixel = WhitePixel(dpy, visInfo.screen);
  581.     if (XcmsQueryColor(dpy, DefaultColormap(dpy, visInfo.screen), ¤tHvc, 
  582.                XcmsTekHVCFormat) == XcmsFailure) {
  583. #ifdef XDEBUG
  584.     fprintf (stderr, "Warning: XcmsQueryColor failed in CreateColormap\n");
  585. #endif
  586.     }
  587. }
  588.  
  589. /*
  590.  *  Force a change in the colormap, with all of its side effects.
  591.  *  Side effects include marking the cell as edited,
  592.  *  and trying to assume selection ownership (if not already owned).
  593.  *  Apply constraints as proper.
  594.  *
  595.  *  Return NO_ADJUST iff the entire range was ok.
  596.  */
  597. void EditHvcCells(pHVCs, len, method, mark)
  598. XcmsColor *pHVCs;
  599. int len;
  600. unsigned char method;
  601. Boolean mark;
  602. {
  603.     int i;
  604.  
  605.     for (i = 0; i < len; i++) {
  606.     if (mark)
  607.         MarkIndexEdited(pHVCs[i].pixel);
  608.  
  609.     ChangeHvcCells(pHVCs+i, 1, method);
  610.     }
  611.  
  612. /*
  613.  *    It takes 2-3 times as long to modify the map one cell at a time,
  614.  *    but StoreColors has a bug in that it does not modify the passed value.
  615.  *    In addition, the update can take a long time, particularly on the
  616.  *    20 and 30 servers.  Even though it takes a while, at least the user
  617.  *    can see something happening.
  618.  *
  619.  *    Definitely want to consider changing calling sequences to
  620.  *    improve performance.
  621.  *
  622.  *   if (!selectionMine)
  623.  *    TakeSelection();
  624.  */
  625.     for (i = 0; i < len; i++) {
  626.     if (clampCheck[i] != NO_ADJUST)
  627.         return;
  628.     }
  629. }
  630.  
  631. /*
  632.  *  This routine combines EditHvcCells and ChangeHvcCells for a change
  633.  *  in RGB.  This is because we never want to change a RGB color except
  634.  *  when editing.  If this ever changes, extract it.
  635.  *
  636.  *  May want to modify this algorithm to be more efficient.
  637.  */
  638. void EditRgbCells(rgbs, len)
  639. XColor *rgbs;
  640. int len;
  641. {
  642.     int i;
  643.     Pixel start = mapSize, stop = 0;
  644.  
  645.     XStoreColors(dpy, cmap, rgbs, len);
  646.  
  647.     for (i = 0; i < len; i++) {
  648.     MarkIndexEdited(rgbs[i].pixel);
  649.     if (rgbs[i].pixel < start)
  650.         start = rgbs[i].pixel;
  651.     if (rgbs[i].pixel > stop)
  652.         stop = rgbs[i].pixel;
  653.     }
  654.  
  655.     
  656.     /* update the internal copy */
  657.     /* but only need to if XStoreColors was used */
  658.     /* could query the entire map, but I think this is more efficient */
  659.     if (XcmsQueryColors(dpy, cmap, currentMap+start, stop - start + 1,
  660.             XcmsTekHVCFormat) == XcmsFailure) {
  661. #ifdef XDEBUG
  662.     fprintf (stderr, "Warning: XcmsQueryColors failed in EditRGB Cells\n");
  663. #endif
  664.     }
  665.     for (i = 0; i < len; i++)
  666.     ConstrainColor(rgbs[i].pixel);
  667.  
  668. /*    if (!selectionMine)
  669.  *    TakeSelection();
  670.  */
  671. }
  672.  
  673. /*
  674.  * This routine is identical to EditRgbCells, except it deals with
  675.  * coordinates specified in u'v'Y space.
  676.  * Since the local client does not support this space,
  677.  * only defined for the host based client.
  678.  */
  679. void EditUvyCells(uvys, len)
  680. XcmsColor *uvys;
  681. int len;
  682. {
  683.     int i;
  684.     Pixel start = mapSize, stop = 0;
  685.  
  686. #ifdef XDEBUG
  687.     routine_name = EDIT_UVY_CELLS;
  688. #endif
  689.     StoreAllocColors(dpy, cmap, uvys, len, XcmsCIEuvYFormat);
  690.  
  691.     for (i = 0; i < len; i++) {
  692.     MarkIndexEdited(uvys[i].pixel);
  693.     if (uvys[i].pixel < start)
  694.         start = uvys[i].pixel;
  695.     if (uvys[i].pixel > stop)
  696.         stop = uvys[i].pixel;
  697.     }
  698.  
  699.     /* update the internal copy */
  700.     /* could query the entire map, but I think this is more efficient */
  701.     if (XcmsQueryColors(dpy, cmap, currentMap+start, stop - start + 1,
  702.             XcmsTekHVCFormat) == XcmsFailure) {
  703. #ifdef XDEBUG
  704.     fprintf (stderr, "Warning: XcmsQueryColors failed in EdituvYCells\n");
  705. #endif
  706.     }
  707.     for (i = 0; i < len; i++)
  708.     ConstrainColor(uvys[i].pixel);
  709.  
  710. /*    if (!selectionMine)
  711.  *    TakeSelection();
  712.  */
  713. }
  714.  
  715. STATIC Cursor MakeCursor();
  716. void CreateCursors()
  717. {
  718.     unsigned int bestWidth, bestHeight;
  719.  
  720.     /* normal cursor is always boring upper left arrow */
  721.     normalCursor = XCreateFontCursor(dpy, XC_left_ptr);
  722.  
  723.     XQueryBestSize(dpy, CursorShape, RootWindow(dpy, visInfo.screen), 
  724.         (unsigned int)hvc_cursor_width, (unsigned int)hvc_cursor_height,
  725.         &bestWidth, &bestHeight);
  726.     /* If best size is less than what we asked for, use font cursors */
  727.     if ( (bestWidth < hvc_cursor_width) || (bestHeight < hvc_cursor_height) ) {
  728.     hvcCursor = normalCursor;
  729.     waitCursor = XCreateFontCursor(dpy, XC_watch);
  730.     grabCursor = XCreateFontCursor(dpy, XC_crosshair);
  731.     /* otherwise use our larger cursors */
  732.     } else {
  733.     hvcCursor = MakeCursor(hvc_cursor_bits, hvc_mask_cursor_bits,
  734.                 hvc_mask_cursor_width, hvc_mask_cursor_height,
  735.                 hvc_cursor_x_hot, hvc_cursor_y_hot);
  736.     waitCursor = MakeCursor(wait_cursor_bits, wait_mask_cursor_bits,
  737.                 wait_mask_cursor_width, wait_mask_cursor_height,
  738.                 wait_cursor_x_hot, wait_cursor_y_hot);
  739.     grabCursor = MakeCursor(pick_cursor_bits, pick_mask_cursor_bits,
  740.                 pick_mask_cursor_width, pick_mask_cursor_height,
  741.                 pick_cursor_x_hot, pick_cursor_y_hot);
  742.     }
  743. }
  744.  
  745. /*
  746.  * Return non-zero if any cell in the map has been edited
  747.  */
  748. int EditedMap(limit)
  749. int limit;
  750. {
  751.     int i;
  752.     int easy = limit / 32;
  753.     int rest = limit % 32;
  754.     int mask;
  755.  
  756.     for (i = 0; i < easy; i++) {
  757.     if (edited[i])
  758.         return(1);
  759.     }
  760.  
  761.     if (rest) {
  762.     mask = (1 << (rest+1)) - 1;
  763.     return(mask & edited[easy]);
  764.     } else
  765.     return(0);
  766. }
  767.  
  768. /*
  769.  * Return up to size colors from the current map, beginning at start.
  770.  * Return the colors in the format requested HVC.
  771.  * The effective top limit is mapSize.
  772.  */
  773. /* int GetColors(colors, start, size)
  774.  * XtPointer *colors;
  775.  * int start, size;
  776.  * {
  777.  *     XcmsColor *pHVCs = (XcmsColor *)colors;
  778.  *     int chunk;
  779.  * 
  780.  *     /* only copy to the limit of current mapSize */
  781. /*     if (start >= mapSize)
  782.  *     return(0);
  783.  * 
  784.  *     chunk = mapSize - start;
  785.  *     if (chunk > size)
  786.  *     chunk = size;
  787.  * 
  788.  *     /* if (format == FileHVC) */
  789. /*     bcopy(currentMap, pHVCs, chunk * sizeof(XcmsColor));
  790.  * 
  791.  *     return(chunk);
  792.  * }
  793.  */
  794. /*
  795.  * If any of the displayed pixel values are stolen by the hue bar,
  796.  * tell the user to back off of a cell available for editing.
  797.  * TODO: either prevent this from happening, or provide a way to continue.
  798.  */
  799. /* TODO: this is lousy help; how do you free?  what is the high end? */
  800. STATIC char *huebarCellInUse = "\
  801. This option `steals' a number of color cells from the top end of the colormap.\n\
  802. At least one of these cells has already been chosen to be edited.  Since \n\
  803. the cell cannot be used for both purposes, the option cannot be implemented.\n\
  804. \n\
  805. To enable the option, free the cells in the high end of the colormap from\n\
  806. editing.";
  807. int HuebarRangeBusy()
  808. {
  809.     Pixel *colors;
  810.     int ct;
  811.     int i;
  812.  
  813.     colors = EditingIndexes(&ct);
  814.  
  815.     for (i = 0; i < ct; i++) {
  816.     if (colors[i] >= huebarBase) {
  817.         InformMsg("Color cell in use.  Change cell to enable option.",
  818.             huebarCellInUse);
  819.         return(1);
  820.     }
  821.     }
  822.     return(0);
  823. }
  824.  
  825. /*
  826.  * Load a pre-computed range of max ValueChromas for different hues
  827.  * into the back end of the colormap.  Then tell the huebar widget to use
  828.  * them.
  829.  */
  830. void HuebarRangeLoad(base, len)
  831. Pixel *base;
  832. int *len;
  833. {
  834.     int i;
  835.     XcmsFloat HRL_step;
  836.     XcmsFloat HRL_hue;
  837.  
  838.     /* set up the range the first time we are called and cache it */
  839.     if (constantHuebar[1].pixel != huebarBase + 1) {
  840.     HRL_step = 360.0 / (XcmsFloat)HuebarColors;
  841.     HRL_hue = HRL_step / 2.0;
  842.  
  843.     for (i = 0; i < HuebarColors; i++, HRL_hue += HRL_step) {
  844.         constantHuebar[i].pixel = huebarBase + i;
  845.         constantHuebar[i].format = XcmsTekHVCFormat;
  846.         constantHuebar[i].spec.TekHVC.H = HRL_hue;
  847.         if (!XcmsTekHVCQueryMaxVC(pDefaultCCC, HRL_hue, &constantHuebar[i])) {
  848.         return;
  849.         }
  850.         constantHuebar[i].pixel = huebarBase + i;
  851.         if (constantHuebar[i].format != XcmsTekHVCFormat) {
  852.         if ((XcmsConvertColors (pDefaultCCC, &constantHuebar[i], 1,
  853.                     XcmsTekHVCFormat, NULL) == XcmsFailure)&&
  854.             constantHuebar[i].format != XcmsTekHVCFormat) {
  855. #ifdef XDEBUG
  856.              fprintf (stderr, "Warning: XcmsConvertColors failed in HuebarRangeLoad\n"); 
  857. #endif
  858.         }
  859.         constantHuebar[i].pixel = huebarBase + i;
  860.         }
  861.      }
  862.     }
  863.  
  864.     if (XcmsStoreColors(dpy, cmap, constantHuebar, 
  865.             HuebarColors, NULL) == XcmsFailure) {
  866. #ifdef XDEBUG
  867.      fprintf (stderr, "Warning: XcmsStoreColors failed HuebarRangeLoad \n"); 
  868. #endif
  869.     }
  870.     if (XcmsQueryColors(dpy, cmap, constantHuebar, HuebarColors,
  871.             XcmsTekHVCFormat) == XcmsFailure) {
  872. #ifdef XDEBUG
  873.      fprintf (stderr, "Warning: XcmsQueryColors failed HuebarRangeLoad\n"); 
  874. #endif    
  875.     }
  876.  
  877.     *base = huebarBase;
  878.     *len = HuebarColors;
  879. }
  880.  
  881. /*
  882.  * Restore real colormap values, previously saved with HuebarRangeSave.
  883.  * Set the huebar widget to use only the single background color.
  884.  */
  885. void HuebarRangeRestore(base, len)
  886. Pixel *base;
  887. int *len;
  888. {
  889.     if (XcmsStoreColors(dpy, cmap, currentMap+huebarBase,
  890.             HuebarColors, NULL) == XcmsFailure) {
  891. #ifdef XDEBUG
  892.      fprintf (stderr, "Warning: XcmsStoreColors failed HuebarRangeRestore\n"); 
  893. #endif
  894.     }
  895.     if (XcmsQueryColors(dpy, cmap, currentMap+huebarBase, 
  896.             HuebarColors, XcmsTekHVCFormat) == XcmsFailure) {
  897. #ifdef XDEBUG
  898.      fprintf (stderr, "Warning: XcmsQueryColors failed HuebarRangeRestore\n"); 
  899. #endif    
  900.     }
  901.  
  902.     *base = huebarBackground;
  903.     *len = 1;
  904. }
  905.  
  906. /*
  907.  * Save the real colormap values of those cells stolen for the hue bar 
  908.  * This routine is no longer needs to save cells since they are in the
  909.  * currentColormap, but it does set huebarBackground.
  910.  */
  911. void HuebarRangeSave()
  912. {
  913.     Arg arg;
  914.  
  915.     /* This needs only to be set once, since background doesn't change */
  916.     if ((int)huebarBackground >= 0)
  917.     return;
  918.     XtSetArg(arg, XtNbackground, &huebarBackground);
  919.     /*
  920.      * this routine can be called by routine creating hue,
  921.      * so use interface parent widget instead.
  922.      */
  923.     XtGetValues(primary, &arg, 1);
  924. }
  925.  
  926. /*
  927.  * Load a range of colors at different hues with current value and chroma
  928.  * into the back end of the colormap.
  929.  */
  930. void HuebarRangeUpdate(base, len)
  931. Pixel *base;
  932. int *len;
  933. {
  934.     int i;
  935.     XcmsFloat HRU_step = 360.0 / (XcmsFloat)HuebarColors;
  936.     XcmsColor range[HuebarColors];
  937.     XcmsColor target;
  938.  
  939.     /* set up the range */
  940.     target.spec.TekHVC.H = HRU_step / 2.0;
  941.     target.spec.TekHVC.V = currentHvc.spec.TekHVC.V;
  942.     target.spec.TekHVC.C = currentHvc.spec.TekHVC.C;
  943.     for (i = 0; i < HuebarColors; i++) {
  944.     range[i].pixel = huebarBase + i;
  945.     range[i].format = XcmsTekHVCFormat;
  946.     range[i].spec.TekHVC.H = target.spec.TekHVC.H;
  947.     range[i].spec.TekHVC.V = target.spec.TekHVC.V;
  948.     range[i].spec.TekHVC.C = target.spec.TekHVC.C;
  949.     target.spec.TekHVC.H += HRU_step;
  950.     }
  951.     if (XcmsStoreColors(dpy, cmap, range, 
  952.             HuebarColors, NULL) == XcmsFailure) {
  953. #ifdef XDEBUG
  954.      fprintf (stderr, "Warning: XcmsStoreColors failed HuebarRangeUpdate\n"); 
  955. #endif
  956.     }
  957.     if (XcmsQueryColors(dpy, cmap, range, HuebarColors, 
  958.             XcmsTekHVCFormat) == XcmsFailure) {
  959. #ifdef XDEBUG
  960.      fprintf (stderr, "Warning: XcmsQueryColor failed HuebarRangeUpdate\n"); 
  961. #endif    
  962.     }
  963.  
  964.     *base = huebarBase;
  965.     *len = HuebarColors;
  966. }
  967.  
  968. /*
  969.  * Return non-zero iff the pixel of the passed color struct is in use in the
  970.  * interface and its color differs from the current colors.
  971.  * This routine assumes that the array of current colors contains a color
  972.  * structure for each pixel in the ifColors array.
  973.  */
  974. STATIC int IfColorChanged(col, ifCols, ifColsCt)
  975. XcmsColor *col, *ifCols;
  976. int ifColsCt;
  977. {
  978.     int i;
  979.     Pixel index;
  980.  
  981.     for (i = 0; i < ifColsCt; i++) {
  982.     index = ifCols[i].pixel;
  983.     /* TODO: need epsilon check instead of strict equality ?? */
  984.     if (col[index].spec.TekHVC.H != ifCols[i].spec.TekHVC.H)
  985.         return(1);
  986.     if (col[index].spec.TekHVC.V != ifCols[i].spec.TekHVC.V)
  987.         return(1);
  988.     if (col[index].spec.TekHVC.C != ifCols[i].spec.TekHVC.C)
  989.         return(1);
  990.     }
  991.  
  992.     return(0);
  993. }
  994.  
  995. /* a convenience macro used by Is*Range functions */
  996. #define PixInRange(p,l,h) (( (p) >= (l) ) && ( (p) <= (h) ))
  997.  
  998. /*
  999.  * Return true if black or white pixel are in the passed range
  1000.  */
  1001. /* Boolean IsBWRange(lo, hi)
  1002.  * Pixel lo, hi;
  1003.  * {
  1004.  *     return (PixInRange(WhitePixel(dpy,visInfo.screen), lo, hi) 
  1005.  *         || PixInRange(BlackPixel(dpy,visInfo.screen), lo, hi) );
  1006.  * }
  1007.  */
  1008. /*
  1009.  * Return true if the passed pixel is used in the hue bar.
  1010.  */
  1011. Boolean IsHuebarIndex(pix)
  1012. Pixel pix;
  1013. {
  1014.     return(huebarState != HuebarEmpty && pix >= huebarBase);
  1015. }
  1016.  
  1017. /*
  1018.  * Return true if the passed pixel is used in the interface
  1019.  */
  1020. Boolean IsIfIndex(pix)
  1021. Pixel pix;
  1022. {
  1023.     int i;
  1024.     for (i = 0; i < ifColorCt; i++) {
  1025.     if (ifColors[i] == pix)
  1026.         return(True);
  1027.     }
  1028.  
  1029.     return(False);
  1030. }
  1031.  
  1032. /*
  1033.  * Return true if the an interface pixel is in the passed range
  1034.  */
  1035. /* Boolean IsIfRange(lo, hi)
  1036.  * Pixel lo, hi;
  1037.  * {
  1038.  *     int i;
  1039.  *     for (i = 0; i < ifColorCt; i++) {
  1040.  *     if (PixInRange(ifColors[i], lo, hi))
  1041.  *         return(True);
  1042.  *     }
  1043.  * 
  1044.  *     return(False);
  1045.  * }
  1046.  */
  1047. /*
  1048.  * Return true if the passed pixel is used to fill the leaf.
  1049.  */
  1050. Boolean IsLeafIndex(pix)
  1051. Pixel pix;
  1052. {
  1053.     return((leafState & LeafFilled) && (pix >= leafBase) && (pix < huebarBase));
  1054. }
  1055.  
  1056. /*
  1057.  * If any of the displayed pixel values are stolen by the leaf,
  1058.  * tell the user to back off of a cell available for editing.
  1059.  * TODO: either prevent this from happening, or provide a way to continue.
  1060.  */
  1061. /* TODO: this is lousy help; how do you free?  what is the high end? */
  1062. STATIC char *leafCellInUse = "\
  1063. This option `steals' a number of color cells from the colormap.\n\
  1064. At least one of these cells has already been chosen to be edited.  Since \n\
  1065. the cell cannot be used for both purposes, the option cannot be implemented.\n\
  1066. \n\
  1067. To enable the option, free the cells in the middle of the colormap from\n\
  1068. editing.";
  1069. int LeafRangeBusy()
  1070. {
  1071.     Pixel *colors;
  1072.     int ct;
  1073.     int i;
  1074.  
  1075.     colors = EditingIndexes(&ct);
  1076.  
  1077.     for (i = 0; i < ct; i++) {
  1078.     if ( (colors[i] >= leafBase) && (colors[i] - leafBase < LeafColors) ) {
  1079.         InformMsg("Color cell in use.  Change cell to enable option.",
  1080.             leafCellInUse);
  1081.         return(1);
  1082.     }
  1083.     }
  1084.     return(0);
  1085. }
  1086.  
  1087. /*
  1088.  * Restore real colormap values, previously saved with LeafRangeSave.
  1089.  * Set the leaf widget to not fill (-1)
  1090.  */
  1091. void LeafRangeRestore(base)
  1092. Pixel *base;
  1093. {
  1094.     if (XcmsStoreColors(dpy, cmap, currentMap+leafBase, 
  1095.             LeafColors, NULL) == XcmsFailure) {
  1096. #ifdef XDEBUG
  1097.      fprintf (stderr, "Warning: XcmsStoreColors failed LeafRangeRestore\n"); 
  1098. #endif
  1099.     }
  1100.     if (XcmsQueryColors(dpy, cmap, currentMap+leafBase, LeafColors, 
  1101.             XcmsTekHVCFormat) == XcmsFailure) {
  1102. #ifdef XDEBUG
  1103.      fprintf (stderr, "Warning: XcmsQueryColors failed LeafRangeRestore\n"); 
  1104. #endif    
  1105.     }
  1106.  
  1107.     *base = (Pixel)-1;
  1108. }
  1109.  
  1110. /*
  1111.  * Save the real colormap values of those cells stolen for leaf.
  1112.  * Return the base of the colors saved (widget can then use those colors).
  1113.  * This routine is no longer needed since cells are already stored
  1114.  * in currentColormap.
  1115.  */
  1116. void LeafRangeSave(base)
  1117. Pixel *base;
  1118. {
  1119.     *base = leafBase;
  1120. }
  1121.  
  1122. STATIC Cursor MakeCursor(image, mask, wt, ht, x, y)
  1123.     unsigned char *image, *mask;
  1124.     unsigned int wt, ht;
  1125.     int x, y;
  1126. {
  1127.     Cursor crsr;
  1128.     Pixmap img, msk;
  1129.     XColor  white, black;
  1130.  
  1131.     /* set the colors */
  1132.     white.flags = black.flags = DoRed | DoGreen | DoBlue;
  1133.     white.pixel = WhitePixel(dpy, visInfo.screen);
  1134.     black.pixel = BlackPixel(dpy, visInfo.screen);
  1135.     XQueryColor(dpy, DefaultColormap(dpy, visInfo.screen), &white);
  1136.     XQueryColor(dpy, DefaultColormap(dpy, visInfo.screen), &black);
  1137.  
  1138.     /* build images from data */
  1139.     img = XCreateBitmapFromData(dpy, RootWindow(dpy, visInfo.screen),
  1140.                 (char *)image, wt, ht);
  1141.     msk = XCreateBitmapFromData(dpy, RootWindow(dpy, visInfo.screen),
  1142.                 (char *)mask, wt, ht);
  1143.  
  1144.     /* make cursor from images */
  1145.     crsr = XCreatePixmapCursor(dpy, img, msk, &white, &black, x, y);
  1146.  
  1147.     /* free the images */
  1148.     XFreePixmap(dpy, img);
  1149.     XFreePixmap(dpy, msk);
  1150.  
  1151.     return(crsr);
  1152. }
  1153.  
  1154. /* 
  1155.  * If the passed shell widget does not have an icon bitmap set,
  1156.  * create one and set it.
  1157.  */
  1158. Pixmap MakeIcon()
  1159. {
  1160.     /*
  1161.      * Could get icon sizes, build a pixmap and render into it.
  1162.      * However, 32x32 seems to be a likely candidate (if the wm
  1163.      * supports this at all).  And this is easier.
  1164.      */
  1165.     return(XCreateBitmapFromData(dpy, RootWindow(dpy, visInfo.screen), 
  1166.             (char *)icon_bits, icon_width, icon_height));
  1167. }
  1168.  
  1169. /*
  1170.  * Place the given colors into an array of XcmsColors.  
  1171.  * Exactly which array is not specified -
  1172.  * but we use cpmap.
  1173.  * Return the colormap the colors are going into.
  1174.  *
  1175.  * The idea is that after this map is completely loaded,
  1176.  * it will copied into the primary editing map.
  1177.  */
  1178. /* XcmsColor *PutHvcColors(colors, size)
  1179.  * XcmsColor *colors;
  1180.  * int size;
  1181.  * {
  1182.  *     bcopy(colors, cpmap+colors->pixel, size * sizeof(XcmsColor));
  1183.  * 
  1184.  *     return(cpmap);
  1185.  * }
  1186.  */
  1187. /*
  1188.  * Place the given colors into a colormap.  Exactly which colormap
  1189.  * is not specified, but we put it into a temporary.
  1190.  * Return the colormap the colors are going into.
  1191.  *
  1192.  * The idea is that after this map is completely loaded,
  1193.  * it will copied into the primary editing map.
  1194.  */
  1195. /* Colormap PutRgbColors(colors, size)
  1196.  * XColor *colors;
  1197.  * int size;
  1198.  * {
  1199.  *     XStoreColors(dpy, tmpMap, colors, size);
  1200.  * 
  1201.  *     return(tmpMap);
  1202.  * }
  1203.  */
  1204. /*
  1205.  * Remember pixels allocated by widgets to avoid later conflicts
  1206.  */
  1207. void RegisterIfPixel(pix)
  1208. Pixel pix;
  1209. {
  1210.     int i;
  1211.  
  1212.     /* allow only unique entries */
  1213.     for (i = 0; i < ifColorCt; i++) {
  1214.     if (ifColors[i] == pix)
  1215.         return;
  1216.     }
  1217.  
  1218.     /* disable filling mode if pixel is in "stolen" range */
  1219.     if ( (pix >= huebarBase) && (allowFill <= FillHuebar) ) {
  1220.     allowFill = FillHuebar + 1;
  1221.     huebarState = HuebarEmpty;
  1222.     }
  1223.     if ( (pix >= leafBase) && (allowFill <= FillLeaf) ) {
  1224.     allowFill = FillLeaf + 1;
  1225.     leafState &= ~LeafFilled;
  1226.     }
  1227.  
  1228.     ifColors[ifColorCt++] = pix;
  1229.     if (ifColorCt >= MaxIfColors)
  1230.     Error("Too many colors allocated for the interface");
  1231. }
  1232.  
  1233. /* 
  1234.  * If the passed shell widget does not have an icon bitmap set,
  1235.  * create one and set it.
  1236.  */
  1237. /* void SetIcon(w)
  1238.  * Widget w;
  1239.  * {
  1240.  * #if defined(HOST_BASED) || defined(MIT)
  1241.  *     Arg arg;
  1242.  *     Pixmap existing;
  1243.  *     STATIC Pixmap icon = NULL;
  1244.  * 
  1245.  *     XtSetArg(arg, XtNiconPixmap, &existing);
  1246.  *     XtGetValues(w, &arg, 1);
  1247.  * 
  1248.  *     if (existing != NULL)
  1249.  *     return;
  1250.  * 
  1251.  *     /*
  1252.  *      * Could get icon sizes, build a pixmap and render into it.
  1253.  *      * However, 32x32 seems to be a likely candidate (if the wm
  1254.  *      * supports this at all).  And this is easier.
  1255.  *      *//*
  1256.  *     if (!icon)
  1257.  *     icon = XCreateBitmapFromData(dpy, RootWindow(dpy, visInfo.screen), 
  1258.  *             icon_bits, icon_width, icon_height);
  1259.  *     arg.value = (XtArgVal)icon;
  1260.  *     XtSetValues(w, &arg, 1);
  1261.  * }
  1262.  */
  1263. void SetCursor(crsr)
  1264. Cursor crsr;
  1265. {
  1266.     /* TODO: need to know how to get windows to update */
  1267.     XDefineCursor(dpy, XtWindow(primary), crsr);
  1268.     /* use XSync instead ?? */
  1269.     XFlush(dpy);
  1270. }
  1271.  
  1272. /*
  1273.  * Load the given cell from the backup map into the visible map.  
  1274.  * If the index is -1, load the entire map.
  1275.  */
  1276. /* void UncacheCell(index)
  1277.  * int index;
  1278.  * {
  1279.  *     if (index < 0) {
  1280.  *     bcopy(cpmap, currentMap, mapSize * sizeof(XcmsColor));
  1281.  * #ifdef XDEBUG
  1282.  *     routine_name = UNCACHE_CELL;
  1283.  * #endif
  1284.  *     StoreAllocColors(dpy, cmap, cpmap, mapSize, XcmsTekHVCFormat);
  1285.  *     } else {
  1286.  *     bcopy((char *)&cpmap[index], (char *)¤tMap[index], sizeof(XcmsColor));
  1287.  * #ifdef XDEBUG
  1288.  *     routine_name = UNCACHE_CELL;
  1289.  * #endif
  1290.  *     StoreAllocColors(dpy, cmap, cpmap+index, 1, XcmsTekHVCFormat);
  1291.  *     }
  1292.  * }
  1293.  */
  1294.  
  1295. /****************************************************************************
  1296.  *
  1297.  *    NAME
  1298.  *        StoreAllocColors - Either Store or Allocate Colors
  1299.  *
  1300.  *    DESCRIPTION
  1301.  *        Do XcmsStoreColors/XcmsQueryColors if the visual is dynamic.
  1302.  *        Do XcmsAllocColor if visual is static.
  1303.  *
  1304.  *        Returns
  1305.  *            0 = Failure
  1306.  *            1 = Success
  1307.  *
  1308.  *****************************************************************************/
  1309. void StoreAllocColors (dsply, colormap, color, count, f1)
  1310. Display *dsply;
  1311. Colormap colormap;
  1312. XcmsColor *color;
  1313. int count;
  1314. XcmsColorFormat f1;
  1315. {
  1316.     if (XcmsStoreColors(dsply, colormap, color, count, NULL) == XcmsFailure) {
  1317. #ifdef XDEBUG
  1318.     fprintf (stderr, "Warning: XcmsStoreColors failed in %s\n", routine_name);
  1319. #endif
  1320.     }
  1321.     if (XcmsQueryColors(dsply, colormap, color, count, f1)==XcmsFailure) {
  1322. #ifdef XDEBUG
  1323.     fprintf (stderr, "Warning: XcmsQueryColors failed in %s\n", routine_name); 
  1324. #endif
  1325.     }
  1326. }
  1327.  
  1328. /*
  1329.  * Set the value of the current index.
  1330.  * Must be called after all widgets are created to avoid conflicts.
  1331.  */
  1332. void SetFirstIndex()
  1333. {
  1334.     Pixel i;
  1335.     int new = -1;
  1336.  
  1337.     for (i = 0; new < 0; i++) {
  1338.     if (IsIfIndex(i))
  1339.         continue;
  1340.     if (IsBWIndex(i))
  1341.         continue;
  1342.     new = (int)i;
  1343.     }
  1344.     NewIndex(new, NoWidget);
  1345. }
  1346.