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 / controller.c < prev    next >
C/C++ Source or Header  |  1991-08-28  |  20KB  |  728 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.  *        controller - control interface appearance and behaviour
  39.  *
  40.  *    DESCRIPTION
  41.  *        Controller provides a middle layer between the widgets
  42.  *        and the underlying data (resources.c) that is being managed.
  43.  *        Much of the work of this package is partitioned into other 
  44.  *        packages that deal with a specific portion of the interface - 
  45.  *        such as leaf.c, huebar.c - or a specific task - such as 
  46.  *        layout.c and message.c.
  47.  */
  48. #ifndef LINT
  49. static char *copy_notice = "Copyright 1991 Tektronix, Inc.";
  50. #ifdef RCS_ID
  51. static char *rcsid=  "$Header: controller.c,v 1.2 91/08/28 10:01:23 adamsc Exp $";
  52. #endif /* RCS_ID */
  53. #endif /* LINT */
  54.  
  55. /*
  56.  *      EXTERNAL INCLUDES
  57.  */
  58.  
  59. /*
  60.  *      INTERNAL INCLUDES
  61.  */
  62. #include "xtici.h"
  63. #include "CMSColor.h"
  64. #include <X11/Xatom.h>
  65. #include "patch.h"
  66.  
  67. #include "widgets/xticiSD.h"
  68. #include "widgets/ColorS.h"
  69. #include "widgets/Hvcleaf.h"
  70.  
  71. /*
  72.  *      EXTERNS
  73.  */
  74.  
  75. /*
  76.  *      GLOBALS
  77.  */
  78. #ifdef DEC
  79. #  define GLOBAL    global
  80. #else
  81. #  define GLOBAL
  82. #endif
  83.  
  84. GLOBAL int reqVisual;
  85.  
  86. /* special event processing mode */
  87. GLOBAL int grabState = GrabNone;
  88.  
  89. /* controls how the huebar is displayed */
  90. GLOBAL int huebarState = HuebarEmpty;
  91. /* and the leaf */
  92. GLOBAL int leafState = LeafEmpty;
  93.  
  94. /* ends of ranges, or color cells which could be displayed */
  95. GLOBAL Pixel clist[MaxList] = {0, 0};
  96. GLOBAL int currentPatch = 0;
  97.  
  98. /* cached local clipboard color */
  99. GLOBAL XcmsColor clipColor;
  100.  
  101. /* remembers if text widget is being programatically altered */
  102. GLOBAL int textProgramInput = 0;
  103.  
  104. /*
  105.  *      LOCAL DEFINES
  106.  */
  107. extern void ClearMapEdited();
  108. extern void NotifyTarget();
  109.  
  110. /*
  111.  *      LOCAL TYPEDEFS
  112.  */
  113.  
  114.  
  115. /*
  116.  *      LOCALS VARIABLES
  117.  */
  118. #ifdef DEBUG
  119. #  define STATIC
  120. #else
  121. #  define STATIC        static
  122. #endif
  123.  
  124. /*
  125.  * Variables allow the warnings about colors
  126.  * avoided after the first time.
  127.  */
  128. STATIC Boolean ifEditable = False;
  129. STATIC Boolean bwEditable = False;
  130.  
  131. STATIC char *overwriteCellHelp = "\
  132. This action imports the color value from the selected color cell.\n\
  133. The existing color in that cell has been edited.  If you continue this\n\
  134. action, those changes will be lost.  You may want to save the existing\n\
  135. color cell values to a file, then select Import Pixel again.";
  136.  
  137. /************************************************************************
  138.  *                                    *
  139.  *            PRIVATE ROUTINES                *
  140.  *                                    *
  141.  ************************************************************************/
  142.  
  143. /*
  144.  * Find the lowest InputOutput window enclosing the event.
  145.  * The window is sought in this order:
  146.  *  1) lowest window at x,y with CMS_Status property (if requested for export)
  147.  *  2) lowest window at x,y if no CMS_Status property exists for any enclosing
  148.  *     window.
  149.  *  3) a child of the root window.
  150.  *  4) the root window itself.
  151.  * Documentation use to say:
  152.  * "It is a piece of cake to go even further down the subwindow tree,
  153.  * but that is probably not the right thing to do."
  154.  * I am not sure why bobtl wrote that, so I am fixing a bug by looking
  155.  * down the entire subtree for the lowest window, or the lowest window
  156.  * with CMS_Status property set if the cmsflag is set during export operations.
  157.  * The x and y are the event coordinates in the returned window.
  158.  */
  159. STATIC void FindWindow(e, cmsflag, which, x, y)
  160. XButtonEvent *e;
  161. Bool cmsflag;        /* true if looking for window with CMS_Status property */
  162. Window *which;        /* return */
  163. int *x, *y;        /* return */
  164. {
  165.     Window root = DefaultRootWindow(dpy);
  166.     Window child = None;
  167.     Window cmswindow = None;
  168.     Window parent, target;
  169.     XWindowAttributes wa;
  170.  
  171.     STATIC Atom cmsatom;
  172.     Atom type = None;
  173.     int format;
  174.     unsigned long nitems, after;
  175.     unsigned char *data;
  176.  
  177.     if (!cmsatom)
  178.     cmsatom = XInternAtom(dpy, CMS_Status , False);
  179.  
  180.     /*
  181.      * Start at the top (root).  Locate the real (lowest) window the
  182.      * pointer was in based on the x,y.  If cmsflag is set, find the
  183.      * lowest window with CMS_Status property containing x,y.
  184.      *
  185.      * First start by translating to the root.
  186.      * Then progress down until no more children containing pointer.
  187.      * Do not traverse down any InputOnly windows since the window we return
  188.      * will be used in graphics calls.
  189.      */
  190.  
  191.     *x = e->x;
  192.     *y = e->y;
  193.     parent = e->window;
  194.     target = root;
  195.     do {
  196.     XTranslateCoordinates(dpy, parent, target, *x, *y, x, y, &child);
  197.     if(cmsflag){
  198.         /* check if this window has the magic CMS_Status property */
  199.         XGetWindowProperty(dpy, target, cmsatom, 0L, 0L, False,
  200.             AnyPropertyType, &type, &format, &nitems, &after, &data);
  201.         if (type != None)
  202.         cmswindow = target;
  203.     }
  204.     parent = target;
  205.     target = child;
  206.     if (child != None)
  207.         XGetWindowAttributes(dpy, child, &wa);
  208.  
  209.     } while (child != None && wa.class != InputOnly);
  210.  
  211.     if( !cmsflag || cmswindow == None)
  212.         *which = parent;    /* lowest window with x,y */
  213.     else
  214.         *which = cmswindow;    /* lowest window with x,y and CMS_Status prop */
  215. }
  216.  
  217. /*
  218.  * Return the pixel value at x,y in window w;
  219.  * Return -1 if the visual of the window is not PseudoColor.
  220.  * TODO: should allow editing of other color types
  221.  *
  222.  * The pixel value is found by extracting an image of size 1x1.
  223.  * This minimizes data transfer and also avoids problems when
  224.  * the window is partially off-screen.
  225.  */
  226. STATIC int GetCell(w, x, y, cell)
  227. Window w;
  228. int x, y;
  229. XcmsColor *cell;
  230. {
  231.     XWindowAttributes wa;
  232.     XImage *xi;
  233.     Pixel spot;
  234.  
  235.     XGetWindowAttributes(dpy, w, &wa);
  236.  
  237.     xi = XGetImage(dpy, w, x, y, 1, 1, AllPlanes, ZPixmap);
  238.     spot = XGetPixel(xi, 0, 0);
  239.     XDestroyImage(xi);
  240.  
  241.     cell->pixel = spot;
  242.     if (XcmsQueryColor(dpy, wa.colormap, cell, XcmsTekHVCFormat) 
  243.     == XcmsFailure) {
  244. #ifdef XDEBUG
  245.         fprintf(stderr, "Warning: XcmsQueryColor failed in GetCell\n");
  246. #endif
  247.     }
  248.  
  249.     return(spot);
  250. }
  251.  
  252. /*
  253.  * Handle an error by setting a semaphore.
  254.  */
  255. /* STATIC int HandleError(edpy, e)
  256.  * Display *edpy;
  257.  * XErrorEvent *e;
  258.  * {
  259.  *     xerror = e->error_code;
  260.  *     return(NULL);    /* return satisfies declared type for error handler */
  261. /* }
  262.  */
  263.  
  264. /************************************************************************
  265.  *                                    *
  266.  *            PUBLIC ROUTINES                    *
  267.  *                                    *
  268.  ************************************************************************/
  269.  
  270. /* ARGSUSED */
  271. void AllowFloat(w, gestureCode, call)
  272. Widget w;
  273. int gestureCode;
  274. TextCallbackStruct *call;
  275. {
  276.     int len, i;
  277.     char *ptr = NULL;
  278.  
  279.     if (call->reason != CR_MODIFYING_TEXT_VALUE)
  280.      return;
  281.  
  282.     /*
  283.      * This routine is called when any change is made to the text,
  284.      * even when that change is made by the program.  I don't care
  285.      * what changes the program is making, I just wan't to react to
  286.      * user input.
  287.      */
  288.     if (textProgramInput)
  289.     return;
  290.  
  291.     if (gesture == GestureNone)
  292.     BeginGesture(gestureCode);
  293.  
  294.     len = strlen(call->text);
  295.     ptr = call->text;
  296.  
  297.     if (len <= 0)
  298.     return;
  299.  
  300.     for (i = 0; i < len; i++, ptr++) {
  301.     if ( !isdigit(*ptr) && (*ptr != '.') ) 
  302.         call->doit = False;
  303.     }
  304. }
  305.  
  306. /* ARGSUSED */
  307. void AllowInt(w, gestureCode, call)
  308. Widget w;
  309. int gestureCode;
  310. TextCallbackStruct *call;
  311. {
  312.     int len, i;
  313.     char *ptr = NULL;
  314.  
  315.     if (call->reason != CR_MODIFYING_TEXT_VALUE)
  316.     return;
  317.  
  318.     /*
  319.      * This routine is called when any change is made to the text,
  320.      * even when that change is made by the program.  I don't care
  321.      * what changes the program is making, I just wan't to react to
  322.      * user input.
  323.      */
  324.     if (textProgramInput)
  325.     return;
  326.  
  327.     if (gesture == GestureNone)
  328.     BeginGesture(gestureCode);
  329.  
  330.     len = strlen(call->text);
  331.     ptr = call->text;
  332.  
  333.     if (len <= 0)
  334.     return;
  335.  
  336.     for (i = 0; i < len; i++, ptr++) {
  337.     if (!isdigit(*ptr)) 
  338.         call->doit = False;
  339.     }
  340. }
  341.  
  342. /* ARGSUSED */
  343. void ChangedIndex(w, which, call)
  344. Widget w;
  345. int which;
  346. ScaleCallbackStruct *call;
  347. {
  348.     switch (call->reason) {
  349.     case CR_DISARM:
  350.         EndIndex(which);
  351.         call->value = currentIndex;
  352.         return;
  353.     case CR_ARM:
  354.         BeginGesture(GestureMouse);
  355.         return;
  356.     case CR_SINGLE_SELECT:
  357.         BeginGesture(GestureNone);
  358.         break;
  359.     case CR_DRAG:
  360.     case CR_VALUE_CHANGED:
  361.         break;
  362.     }
  363.  
  364.     NewIndex ((int)call->value, which);
  365.     call->value = currentIndex;
  366. }
  367.  
  368. /*
  369.  * Application has grabbed the pointer; respond to mouse buttons.
  370.  * Return non-zero if this event is "used" by the grab.
  371.  * Any mouse button is used.
  372.  */
  373. int HandleGrab(e)
  374. XButtonEvent *e;    /* not necessarily a button event; check before using */
  375. {
  376.     int tmp;
  377.     Window target;
  378.     int x, y;
  379.     int newPixel;   /* Should be Pixel, but GetCell can return negative */
  380.     XcmsColor newCell;
  381.     Bool cmsflag = False;    /* False for imports, True for exports */
  382.     void NewCell();
  383.  
  384.     if ( (e->type != ButtonPress) && (e->type != ButtonRelease) )
  385.     return(0);
  386.  
  387.     if (grabState & GrabUp) {
  388.     if (e->type != ButtonPress)
  389.         return(1);
  390.     grabState |= GrabDown;
  391.     grabState &= ~GrabUp;
  392.     } else {    /* grabState is down */
  393.     if (e->type != ButtonRelease)
  394.         return(1);
  395.     /* based on grab state, process the pick */
  396.     if (grabState & GrabCell || grabState & GrabMap)
  397.         cmsflag = True;     /* Find export window with CMS_Status prop */
  398.     FindWindow(e, cmsflag, &target, &x, &y);
  399.     /* done with grab, release now,
  400.        following routines may require interaction */
  401.     tmp = grabState;
  402.     grabState = GrabNone;
  403.     XUngrabPointer(dpy, (Time)e->time);
  404.  
  405.     newCell.format = XcmsTekHVCFormat;
  406.     /*
  407.      * Grab a single color cell, importing its value from the window
  408.      * colormap, changing index and color to the new values.
  409.      */
  410.     if (tmp & GrabPixel) {
  411.         Pixel tmpPixel = currentIndex;
  412.         newPixel = GetCell(target, x, y, &newCell);
  413.         if (newPixel < 0)
  414.         return(1);
  415.         /*
  416.          * This undo is rather tricky because first we will need to 
  417.          * restore the changed values of the new cell, then restore
  418.          * the currently edited cell.
  419.          */
  420.         currentIndex = tmpPixel;
  421.         NewCell(&newCell, MenuWidget);
  422.     /*
  423.      * Grab the image of a window, complete with its supporting
  424.      * visual type and colormap.  Change complete colormap,
  425.      * along with the index.
  426.      */
  427.     } else {
  428.         /*
  429.          * The target returned by FindWindow may not be the main client
  430.          * window if the click is in the wm wrapper windows.
  431.          * Insure our target is the client.
  432.          * If Null is returned, then no window manager is running and we will
  433.          * go with the original target window (root or child of root).
  434.          *
  435.          * The above documentation is old.  Currently the above call
  436.          * to FindWindow() returns the lowest window with the
  437.          * CMS_Status property, or the lowest window if none has the
  438.          * CMS_Status property.  We ignore WM_State property.
  439.          * 
  440.          * Exporting a cell (GrabCell) or a map (GrabMap).
  441.          */
  442.         if (tmp & GrabCell) {
  443.         newPixel = currentIndex;
  444.         ClearIndexEdited(currentIndex);
  445.         } else {
  446.         newPixel = -1;
  447.         ClearMapEdited(mapSize);
  448.         }
  449.         NotifyTarget(target, e, newPixel);
  450.     }   
  451.     }    /* end else grab state is down */
  452.  
  453.     return(1);
  454. }
  455.  
  456. /*
  457.  *  Return true if the index should not be modified.
  458.  *  This involves checking if the index is Black/White Pixel
  459.  *  or one of the editor interface colors.
  460.  *  TODO: add help strings
  461.  */
  462. Boolean IndexProtected(pix)
  463. Pixel pix;
  464. {
  465.     if (!ifEditable && IsIfIndex(pix)) {
  466.     if (Warning("This color cell is used by the color editor", 
  467.             (char *)NULL) == MessageContinue) {
  468.         ifEditable = True;
  469.     } else {
  470.         return(True);
  471.     }
  472.     }
  473.     if (!bwEditable && IsBWIndex(pix)) {
  474.     if (Warning("This color cell is a default color (black or white)", 
  475.         (char *)NULL) == MessageContinue)
  476.         bwEditable = True;
  477.     else
  478.         return(True);
  479.     }
  480.     if (IsLeafIndex(pix)) {
  481.     if (Warning("This color cell is used to fill the leaf.\n\
  482. Fill will be removed to edit this cell.", (char *)NULL) == MessageContinue) {
  483.         NewLeafState(leafState & ~LeafFilled, NoWidget);
  484.     } else {
  485.         return(True);
  486.     }
  487.     } else if (IsHuebarIndex(pix)) {
  488.     if (Warning("This color cell is used to fill the Hue bar.\n\
  489. Hues will be removed to edit this cell.", (char *)NULL) == MessageContinue) {
  490.         NewHuebarState(HuebarEmpty, NoWidget);
  491.     } else {
  492.         return(True);
  493.     }
  494.     }
  495.  
  496.     return(False);
  497. }
  498.  
  499. /*
  500.  * Update all cached values to reflect a new color cell values.
  501.  * Then update all interface components.
  502.  */
  503. void NewCell(cell, from)
  504. XcmsColor *cell;
  505. int from;
  506. {
  507.     XcmsColor *hvc = cell;
  508.  
  509.     /* TODO: should also happen in local version */
  510.     /* allow user to back out of overwrite of an edited cell */
  511.     if (EditedIndex(cell->pixel) && Warning(
  512.         "Color value in cell will be lost", overwriteCellHelp))
  513.     return;
  514.  
  515.     NewIndex ((int)cell->pixel, from);
  516.     EditHvcCells(cell, 1, DECREASE_CHROMA, False);
  517.     NewColor(hvc, from, UnknownChange);
  518.  
  519.     /* cell may already have been marked; clear it */
  520.     ClearIndexEdited(cell->pixel);
  521.  
  522.     /* set checkpoint value */
  523.     CacheCell((int)cell->pixel);
  524. }
  525.  
  526. /*
  527.  * Replace all the cells in the passed range with the values in the
  528.  * passed map.
  529.  */
  530. void NewCellRange(oldmap, from, to)
  531. Colormap oldmap;
  532. Pixel from, to;
  533. {
  534.     int i;
  535.     XcmsColor color;
  536.  
  537.     for (i = from; i <= to; i++) {
  538.     if (!EditedIndex(i))
  539.         continue;
  540.     if (Warning("Current color values will be lost", overwriteCellHelp))
  541.         return;
  542.     }
  543.  
  544.     CopyColormap(oldmap, from, to, True);
  545.  
  546.     /* if the current cell is in the range, reset the interface */
  547.     if ( (currentIndex >= from) && (currentIndex <= to)) {
  548.     ConstrainColor(currentIndex);
  549.     bcopy((char *)¤tMap[currentIndex], (char *)&color, sizeof(XcmsColor));
  550.     NewColor(&color, NoWidget, UnknownChange);
  551.     }
  552.  
  553.     /* clear editing mark from all cells of range */
  554.     for (i = from; i <= to; i++)
  555.     ClearIndexEdited(i);
  556. }
  557.  
  558. /*
  559.  * Update the interface to reflect a new color.
  560.  * The color is always passed as an HVC specification.
  561.  */
  562. void NewColor(new, from, what)
  563. XcmsColor *new;
  564. int from;
  565. int what;
  566. {
  567.     /* Update the HVC interface */
  568.  
  569.     if ((what & HueChange) && 
  570.     (new->spec.TekHVC.H != currentHvc.spec.TekHVC.H)) {
  571.     currentHvc.spec.TekHVC.H = new->spec.TekHVC.H;
  572.     if (from != HuebarWidget)
  573.         UpdateHueWidget();
  574.     }
  575.  
  576.     /* only update the hue bar if we absolutely must */
  577.     if ( (currentHvc.spec.TekHVC.V != new->spec.TekHVC.V) || (currentHvc.spec.TekHVC.C != new->spec.TekHVC.C) ) {
  578.     Pixel dbase;
  579.     int   dlen;
  580.     currentHvc.spec.TekHVC.V = new->spec.TekHVC.V;
  581.     currentHvc.spec.TekHVC.C = new->spec.TekHVC.C;
  582.     if (huebarState == HuebarDynamic)
  583.         /* in this state, widget is ok; just set the colormap */
  584.        HuebarRangeUpdate (&dbase, &dlen);    
  585.     }
  586.  
  587.     /* this changes all three values at once, so do regardless of changes */
  588.     if (from != LeafWidget)
  589.     UpdateLeafWidget();
  590.  
  591.     /*
  592.      * Update the hvc coordinate widget if it is showing.
  593.      */
  594.     if (HvcShowing && (from != HvcWidget) )
  595.     UpdateShowWidget(HvcWidget);
  596.  
  597.     /* update other possible coordinate systems */
  598.     /* this involves server round trips, so do only at end of gesture */
  599.     if (gesture == GestureNone) {
  600.     if (RgbShowing && (from != RgbWidget) )
  601.         UpdateShowWidget(RgbWidget);
  602.     if (UvyShowing && (from != UvyWidget) )
  603.         UpdateShowWidget(UvyWidget);
  604.     }
  605.  
  606.     /* RGB and HVC coordinates are always showing, update them */
  607.     if (from != HvcWidget)
  608.     UpdateShowWidget(HvcWidget);
  609.     if ( (gesture == GestureNone) && (from != RgbWidget) )
  610.     UpdateShowWidget(RgbWidget);
  611. }
  612.  
  613. /*
  614.  * Store a new color (specified by HVC) in the colormap.
  615.  * Validate and constraint the color to be usable.
  616.  * Update the interface to reflect the new color.
  617.  */
  618. /* ARGSUSED */
  619. void NewHvc(new, from, what)
  620. XcmsColor *new;
  621. int from;
  622. int what;
  623. {
  624.     XcmsColor color;
  625.  
  626.     /* constrain values to be legal; chroma is clamped by library */
  627.     while (new->spec.TekHVC.H >= 360.0)
  628.     new->spec.TekHVC.H -= 360.0;
  629.     while (new->spec.TekHVC.H < 0.0)
  630.     new->spec.TekHVC.H += 360.0;
  631.     if (new->spec.TekHVC.V < 0.0)
  632.     new->spec.TekHVC.V = 0.0;
  633.     else if (new->spec.TekHVC.V > 100.0)
  634.     new->spec.TekHVC.V = 100.0;
  635.     if (new->spec.TekHVC.C < 0.0)
  636.     new->spec.TekHVC.C = 0.0;
  637.     /*
  638.      * Always constrain chroma to <= LeafMaxChroma so that it remains visible
  639.      * on the leaf widget.
  640.      */
  641.     else if (new->spec.TekHVC.C > LeafMaxChroma)
  642.     new->spec.TekHVC.C = LeafMaxChroma;
  643.  
  644.     color.format = XcmsTekHVCFormat;
  645.     color.pixel = new->pixel;
  646.     color.spec.TekHVC.H = new->spec.TekHVC.H;
  647.     color.spec.TekHVC.V = new->spec.TekHVC.V;
  648.     color.spec.TekHVC.C = new->spec.TekHVC.C;
  649.  
  650.     EditHvcCells(&color, 1, DECREASE_CHROMA, True);
  651.  
  652.     new->format = color.format;
  653.     new->pixel = color.pixel;
  654.     new->spec.TekHVC.H = color.spec.TekHVC.H;
  655.     new->spec.TekHVC.V = color.spec.TekHVC.V;
  656.     new->spec.TekHVC.C = color.spec.TekHVC.C;
  657.  
  658.     if ( (new->spec.TekHVC.H == currentHvc.spec.TekHVC.H) 
  659.         && (new->spec.TekHVC.V == currentHvc.spec.TekHVC.V) 
  660.         && (new->spec.TekHVC.C == currentHvc.spec.TekHVC.C) )
  661.     return;
  662.  
  663.     NewIndex ((int)new->pixel, NoWidget);
  664. }
  665.  
  666. /*
  667.  * Update the interface to correspond to a new index.
  668.  */
  669. void NewIndex (new, where)
  670. int new;
  671. int where;
  672. {
  673.     Arg arg;
  674.     XcmsColor color;
  675.  
  676.     if (!gesture && IndexProtected((Pixel)new)) {
  677.     return;
  678.     }
  679.  
  680.     currentIndex = (Pixel)new;
  681.     clist[currentPatch] = currentIndex;
  682.     currentHvc.pixel = currentIndex;
  683.  
  684.     /* 
  685.      * Update the all interface pieces that indicate index.
  686.      * Where may indicate that some pieces are already kosher.
  687.      */
  688.     if (where != ColormapWidget) {
  689.     /* UpdateMapWidget(); */
  690.     XtSetArg(arg, XtNvalue, new);
  691.     XtSetValues(colormap, &arg, 1);
  692.     } 
  693.  
  694.     /* always force the current patch to redraw */
  695.     UpdatePatchWidget(where);
  696.  
  697.     /* Assume that a change of index will mean a change of color; drive that */
  698.     ConstrainColor((Pixel)new);
  699.     bcopy((char *)¤tMap[new], (char *)&color, sizeof(XcmsColor));
  700.  
  701.     NewColor(&color, where, UnknownChange);
  702. }
  703.  
  704. /*
  705.  *  Update user interface components to reflect a new map size
  706.  */
  707. /* void NewSize(new)
  708.  * int new;
  709.  * {
  710.  *     Arg args[4];
  711.  *     int n = 0;
  712.  * 
  713.  *     mapSize = new;
  714.  *     XtSetArg(args[n], XtNmaximum, mapSize - 1);        n++;
  715.  *     XtSetArg(args[n], XtNlength, mapSize - 1);        n++;
  716.  *     /* shows 32 colors in the zoom bar */
  717. /*     XtSetArg(args[n], XtNzoom, new / 32);        n++;
  718.     /* 
  719.      * If currentIndex >= new, reset the value to avoid a toolkit warning.
  720.      * This is just temporary, the real value will be set later.
  721.      */
  722. /*     if (currentIndex >= new) {
  723.  *     XtSetArg(args[n], XtNvalue, mapSize - 1);    n++;
  724.  *     }
  725.  *     XtSetValues(colormap, args, n);
  726.  * }
  727.  */
  728.