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 / widgets / ColorS.c < prev    next >
C/C++ Source or Header  |  1991-08-28  |  29KB  |  966 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.  *        ColorS.c -- Routines for ColorScaleWidget
  39.  *
  40.  *    DESCRIPTION
  41.  *        This widget implements the Colormap Scale and Huebar
  42.  *
  43.  *    HISTORY
  44.  *
  45.  *    HISTORY END
  46.  *
  47.  */
  48.  
  49. #ifndef LINT
  50. static char *copy_notice = "Copyright 1991 Tektronix, Inc.";
  51. #ifdef RCS_ID
  52. static char *rcsid=  "$Header: ColorS.c,v 1.2 91/08/22 11:36:06 adamsc Exp $";
  53. #endif /* RCS_ID */
  54. #endif /* LINT */
  55.  
  56. #include <stdio.h>
  57. #include <math.h>
  58. #include <X11/IntrinsicP.h>
  59. #include <X11/StringDefs.h>
  60. #include <X11/Xaw/FormP.h>
  61. #include <X11/Xaw/LabelP.h>
  62. #include <X11/Xaw/ScrollbarP.h>
  63. #include <X11/Xaw/Text.h>
  64. #include "ColorSP.h"
  65. #include "ColorbarP.h"
  66. #include "RepeatBP.h"
  67. #include "ZoomP.h"
  68.  
  69. /****************************************************************
  70.  *
  71.  * Color Scale Resources
  72.  *
  73.  ****************************************************************/
  74.  
  75. static XtResource resources[] = {
  76. #define offset(field) XtOffset(ColorScaleWidget, colorScale.field)
  77.     /* {name, class, type, size, offset, default_type, default_addr}, */
  78.     { XtNbase, XtCBase, XtRPixel, sizeof(Pixel),
  79.       offset(base), XtRImmediate, (XtPointer)(-1) },
  80.     { XtNlength, XtCLength, XtRInt, sizeof(int),
  81.       offset(length), XtRImmediate, (XtPointer)(-1) },
  82.     { XtNpixelInc, XtCPixelInc, XtRPixel, sizeof(Pixel),
  83.     offset(pixelInc), XtRImmediate, (XtPointer)1 },
  84.     { XtNlabel, XtCLabel, XtRString, sizeof(String),
  85.     offset(label), XtRImmediate, (XtPointer)NULL },
  86.     { XtNincrement, XtCIncrement, XtRInt, sizeof(int),
  87.     offset(inc), XtRImmediate, (XtPointer)1 },
  88.     { XtNminimum, XtCMinimum, XtRInt, sizeof(int),
  89.       offset(min), XtRImmediate, (XtPointer)0 },
  90.     { XtNmaximum, XtCMaximum, XtRInt, sizeof(int),
  91.       offset(max), XtRImmediate, (XtPointer)100 },
  92.     { XtNvalue, XtCValue, XtRInt, sizeof(int),
  93.       offset(value), XtRImmediate, (XtPointer)0 },
  94.     { XtNvalueChangedCallback, XtCCallback, XtRCallback, 
  95.     sizeof(XtCallbackList), offset(changed), XtRCallback, NULL },
  96.     { XtNzoom, XtCZoom, XtRInt, sizeof(int),
  97.       offset(zoom), XtRImmediate, (XtPointer)0 },
  98.     { XtNwrap, XtCBoolean, XtRBoolean, sizeof(Boolean),
  99.       offset(wrap), XtRImmediate, (XtPointer)False },
  100. #undef offset
  101. };
  102.  
  103. /* 
  104.  *  SliderFractionBase is the numerator for some percent calculations
  105.  */
  106. #define SliderFractionBase    1000
  107.  
  108. /*
  109.  * ColorScale actions are identical to those of Form.
  110.  * If I understand this correctly, I can set the action table to NULL,
  111.  * all superclass tables will be searched for an action.
  112.  * I can also just inherit actions themselves
  113.  */
  114.  
  115. /* forward declarations for the class struct */
  116. static void Initialize();
  117. #ifdef LATER
  118. static void Resize();
  119. #endif
  120. static Boolean SetValues();
  121.  
  122. ColorScaleClassRec colorScaleClassRec = {
  123.   { /* core_class fields */
  124.     /* superclass        */    (WidgetClass) &formClassRec,
  125.     /* class_name        */    "ColorScale",
  126.     /* widget_size        */    sizeof(ColorScaleRec),
  127.     /* class_initialize        */    NULL,
  128.     /* class_part_initialize    */    NULL,
  129.     /* class_inited        */    FALSE,
  130.     /* initialize        */    Initialize,
  131.     /* initialize_hook        */    NULL,
  132.     /* realize            */    XtInheritRealize,
  133.     /* actions            */    NULL,
  134.     /* num_actions        */    0,
  135.     /* resources        */    resources,
  136.     /* num_resources        */    XtNumber(resources),
  137.     /* xrm_class        */    NULLQUARK,
  138.     /* compress_motion        */    TRUE,
  139.     /* compress_exposure    */    TRUE,
  140.     /* compress_enterleave    */    TRUE,
  141.     /* visible_interest        */    FALSE,
  142.     /* destroy            */    NULL,
  143.     /* resize            */    XtInheritResize, /* Resize */
  144.     /* expose            */    XtInheritExpose,
  145.     /* set_values        */    SetValues,
  146.     /* set_values_hook        */    NULL,
  147.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  148.     /* get_values_hook        */    NULL,
  149.     /* accept_focus        */    NULL,
  150.     /* version            */    XtVersion,
  151.     /* callback_private        */    NULL,
  152.     /* tm_table            */    XtInheritTranslations,
  153.     /* query_geometry        */    XtInheritQueryGeometry,
  154.     /* display_accelerator    */    NULL,
  155.     /* extension        */    NULL
  156.   },
  157.   { /* composite fields */
  158.     /* geometry manager        */    XtInheritGeometryManager,
  159.     /* change managed        */    XtInheritChangeManaged,
  160.     /* insert child        */    XtInheritInsertChild,
  161.     /* delete child        */    XtInheritDeleteChild,
  162.     /* extension        */    NULL
  163.   },
  164.   { /* constraint fields */
  165.     /* constraint resources    */    NULL,
  166.     /* number of resources    */    0,
  167.     /* size of record        */    sizeof(FormConstraintsRec),
  168.     /* constraint initialization*/    NULL,
  169.     /* constraint destroy    */    NULL,
  170.     /* set values        */    NULL,
  171.     /* extension        */    NULL
  172.   },
  173.   { /* form fields */
  174.     /* layout                   */    XtInheritLayout,
  175.   },
  176.   { /* color scale fields */
  177.     /* extension        */    NULL
  178.   },
  179. };
  180.  
  181. WidgetClass colorScaleWidgetClass = (WidgetClass)&colorScaleClassRec;
  182.  
  183. /* forward declarations of utility functions */
  184. static void AttachChildren();
  185. static void AttachLabel();
  186. static void AttachUpArrow();
  187. static void AttachDownArrow();
  188. static void AttachBar();
  189. static void AttachScrollbar();
  190. static void AttachExpand();
  191. static void AttachZoom();
  192. static void CreateChildren();
  193. static void Incr();
  194. static void Jump();
  195. static void NewVal();
  196. static void ResetZoom();
  197. static void Scroll();
  198. static void SetZoom();
  199. static void Single();
  200.  
  201. static char *warning1 = "increment must be non-negative";
  202. static char *warning2 = "maximum must be greater than or equal to minimum";
  203. static char *warning3 = "value must be within range of minimum to maximum";
  204.  
  205. /* Up and Down mean positive and negative, not the direction of the arrow */
  206. #define Label        0
  207. #define UpArrow        1
  208. #define DownArrow   2
  209. #define Scrollbar   3
  210. #define Bar        4
  211. #define Zoom        5
  212. #define Expand        6
  213.  
  214. static void Warning (widget, message)
  215. Widget widget;
  216. char *message;
  217. {
  218.     /*  R4 says use XtAppWarningMsg but no information on how to set
  219.      *  the parameters.
  220.      */
  221.     if (!widget)
  222.     XtWarning(message);
  223.     else
  224.     XtAppWarning(XtWidgetToApplicationContext(widget), message);
  225. }
  226.  
  227. static void Initialize(req, new)
  228. ColorScaleWidget req, new;
  229. {
  230.     LabelWidget lbl;
  231.  
  232.     /*    Validate input resources */
  233.     if (new->colorScale.inc < 0) {  /* 0 is valid, means no buttons */
  234.     Warning(new, warning1);
  235.     new->colorScale.inc = 1;
  236.     }
  237.     /* negative base and length mean use min / max instead */
  238.     if (new->colorScale.min > new->colorScale.max) {
  239.     Warning(new, warning2);
  240.     new->colorScale.max = new->colorScale.min + 100;
  241.     }
  242.     if ( (new->colorScale.value < new->colorScale.min)
  243.         || (new->colorScale.value > new->colorScale.max) ) {
  244.     Warning(new, warning3);        
  245.     new->colorScale.value = new->colorScale.min;
  246.     }
  247.  
  248.     /* create all of the widgets */
  249.     CreateChildren(new);
  250.  
  251.     lbl = (LabelWidget)new->colorScale.wlist[Label];
  252.     if (req->core.width == 0)
  253.     new->core.width = lbl->core.width * 3;
  254.     if (req->core.height == 0)
  255.     new->core.height = lbl->core.width * 3;
  256.  
  257.     if (new->colorScale.zoom > 1)
  258.     ResetZoom(new);
  259. }
  260.  
  261. /* Most values are passed on to one child or another */
  262. /*ARGSUSED*/
  263. static Boolean SetValues(cur, req, new)
  264. ColorScaleWidget cur, req, new;
  265. {
  266.     Arg arg;
  267.     Arg bargs[2], sargs[4];
  268.     int bct = 0, sct = 0;
  269.     int rezoom = 0;
  270.     int reattach = 0;
  271.  
  272.     if (new->colorScale.inc < 0) {
  273.     Warning(new, warning1);
  274.     new->colorScale.inc = cur->colorScale.inc;
  275.     } else if ( (new->colorScale.inc == 0) && (cur->colorScale.inc != 0) ) {
  276.     reattach = 1;
  277.     } else if ( (new->colorScale.inc != 0) && (cur->colorScale.inc == 0) ) {
  278.     reattach = 1;
  279.     }
  280.  
  281.     /* max and min may be used as defaults later, so insure they are right */
  282.     if (new->colorScale.min > new->colorScale.max) {
  283.     Warning(new, warning2);
  284.     new->colorScale.max = cur->colorScale.max;
  285.     new->colorScale.min = cur->colorScale.min;
  286.     }
  287.     if ( (new->colorScale.value < new->colorScale.min)
  288.         || (new->colorScale.value > new->colorScale.max) ) {
  289.     Warning(new, warning3);        
  290.     new->colorScale.value = new->colorScale.min;
  291.     }
  292.  
  293.     if (new->colorScale.min != cur->colorScale.min ||
  294.     new->colorScale.max != cur->colorScale.max) {
  295.     XtSetArg(sargs[sct], XtNlength, 
  296.          new->colorScale.max - new->colorScale.min + 1);    sct++;
  297.     rezoom = 1;
  298.     }
  299.  
  300.     if (new->colorScale.base != cur->colorScale.base) {
  301.     if ((int)new->colorScale.base >=0)
  302.         XtSetArg(bargs[bct], XtNbase, new->colorScale.base);
  303.     else
  304.         XtSetArg(bargs[bct], XtNbase, new->colorScale.min);
  305.     bct++;
  306.     rezoom = 1;
  307.     }
  308.     if (new->colorScale.length != cur->colorScale.length) {
  309.     if (new->colorScale.length >=0)
  310.         XtSetArg(bargs[bct], XtNlength, new->colorScale.length);
  311.     else
  312.         XtSetArg(bargs[bct], XtNlength, 
  313.             new->colorScale.max - new->colorScale.min + 1);
  314.     bct++;
  315.     rezoom = 1;
  316.     }
  317.  
  318.     if (new->colorScale.label != cur->colorScale.label) {
  319.     XtSetArg(arg, XtNlabel, new->colorScale.label);
  320.     XtSetValues(new->colorScale.wlist[Label], &arg, 1);
  321.     }
  322.  
  323.     if (new->colorScale.value != cur->colorScale.value) {
  324.         if (new->colorScale.value < new->colorScale.max - 8) {
  325.         float top;
  326.  
  327.         top = (float)(new->colorScale.max - (new->colorScale.value + 8)) / 
  328.               (float)(new->colorScale.max - new->colorScale.min + 1);
  329.         XawScrollbarSetThumb(new->colorScale.wlist[Scrollbar], top, -1.0);
  330.     } else {
  331.         XawScrollbarSetThumb(new->colorScale.wlist[Scrollbar], 1.0, -1.0);
  332.     }
  333.     /* avoid doing a reset for just a value change */
  334.     if (new->colorScale.zoom > 1 && !rezoom)
  335.         SetZoom(new);
  336.     }
  337.  
  338.     if (new->colorScale.zoom != cur->colorScale.zoom) {
  339.     if ( (new->colorScale.zoom > 1) && (cur->colorScale.zoom <= 1) ) {
  340.         reattach = 1;
  341.     } else if ((new->colorScale.zoom <= 1) && (cur->colorScale.zoom > 1)) {
  342.         reattach = 1;
  343.     }
  344.     /* if (new->colorScale.zoom > 1) {
  345.      *     XtSetArg(sargs[sct], XtNsliderExtent, 
  346.      *         SliderFractionBase / new->colorScale.zoom); sct++;
  347.      * }
  348.      */
  349.     rezoom = 1;
  350.     }
  351.  
  352.     if (bct > 0)
  353.     XtSetValues(new->colorScale.wlist[Bar], bargs, bct);
  354.     if (sct > 0)
  355.     XtSetValues(new->colorScale.wlist[Scrollbar], sargs, sct);
  356.  
  357.     if (reattach)
  358.     AttachChildren(new);
  359.     if (new->colorScale.zoom > 1 && rezoom)
  360.     ResetZoom(new);
  361.  
  362.     return(False);    /* there is nothing for this widget to redraw */
  363. }
  364.  
  365.  
  366. /*****************************************************************************
  367.  *
  368.  * Resize
  369.  *
  370.  ***************************************************************************/
  371. #ifdef LATER
  372. static void Resize(cs)
  373. ColorScaleWidget cs;
  374. {
  375.     WidgetList           wlist;
  376.     RepeaterButtonWidget upArw;
  377.     RepeaterButtonWidget dwArw;
  378.     LabelWidget          lbl;
  379.     ScrollbarWidget      sld;
  380.     ColorbarWidget       cbar;
  381.     ColorbarWidget       expnd;
  382.     ZoomWidget           zm;
  383.     Dimension            width, wr, hr;
  384.     Arg args[2];
  385.     String *pString;
  386.     XtGeometryResult result;
  387.     int lblwidth;
  388.     int cnt;
  389.  
  390.     wlist = (WidgetList) cs->colorScale.wlist;
  391.     upArw = (RepeaterButtonWidget) wlist[UpArrow];
  392.     dwArw = (RepeaterButtonWidget) wlist[DownArrow];
  393.     lbl = (LabelWidget) wlist[Label];
  394.     sld = (ScrollbarWidget) wlist[Scrollbar];
  395.     cbar = (ColorbarWidget) wlist[Bar];
  396.     expnd = (ColorbarWidget) wlist[Expand];
  397.     zm = (ZoomWidget) wlist[Zoom];
  398.  
  399.     /* Get the width of the string in the label */
  400.     lblwidth = lbl->core.width;
  401.     if (cs->colorScale.zoom > 1) {
  402.     if (lblwidth > 180) {
  403.         width = lblwidth;
  404.     } else {
  405.         width = 170;
  406.     }
  407.     } else {
  408.     if (lblwidth > 100) {
  409.         width = lblwidth;
  410.     } else {
  411.         width = 90;
  412.     }
  413.     }
  414.  
  415.     if (upArw->core.width != 25 || upArw->core.height != 25)
  416.     XtResizeWidget(upArw, 25, 25, 0);
  417.     if (dwArw->core.width != 25 || dwArw->core.height != 25)
  418.     XtResizeWidget(dwArw, 25, 25, 0);
  419.     if (sld->core.width != 25)
  420.     XtResizeWidget(sld, 25, sld->core.height, 0);
  421.     if (cbar->core.width != 40)
  422.     XtResizeWidget(cbar, 40, cbar->core.height, 0);
  423.     if (cs->colorScale.zoom > 1) {
  424.     if (zm->core.width != 40)
  425.         XtResizeWidget(zm, 40, zm->core.height, 0);
  426.     if (expnd->core.width != 40)
  427.         XtResizeWidget(expnd, 40, expnd->core.height, 0);
  428.     }
  429.     if (width != cs->core.width) {
  430.     result = XtMakeResizeRequest (cs, width, cs->core.height, &wr, &hr);
  431.  
  432.     if (result == XtGeometryAlmost) {
  433.         result = XtMakeResizeRequest (cs, wr, hr, NULL, NULL);
  434.         cs->core.width = wr;
  435.     } else {
  436.         cs->core.width = width;
  437.     }
  438.     }
  439.     return;
  440. }
  441. #endif /* LATER */
  442.  
  443. static void AttachChildren(cs)
  444. ColorScaleWidget cs;
  445. {
  446.     Widget *wlist = cs->colorScale.wlist;
  447.     Arg args[8];
  448.     int n = 0;
  449.  
  450.     /* could only change some constraints on orientation or facing change */
  451.  
  452.     AttachLabel(args, &n);
  453.     XtSetValues(wlist[Label], args, n);
  454.  
  455.     if (cs->colorScale.inc > 0) {
  456.     n = 0;
  457.     AttachUpArrow(cs,args, &n);
  458.     XtSetValues(wlist[UpArrow], args, n);
  459.  
  460.     n = 0;
  461.     AttachDownArrow(cs,args, &n);
  462.     XtSetValues(wlist[DownArrow], args, n);
  463.  
  464.     XtManageChild(wlist[UpArrow]);
  465.     XtManageChild(wlist[DownArrow]);
  466.     } else {
  467.     XtUnmanageChild(wlist[UpArrow]);
  468.     XtUnmanageChild(wlist[DownArrow]);
  469.     }
  470.  
  471.     n = 0;
  472.     AttachScrollbar(cs, args, &n);
  473.     XtSetValues(wlist[Scrollbar], args, n);
  474.  
  475.     n = 0;
  476.     AttachExpand(cs, args, &n);
  477.     XtSetValues(wlist[Expand], args, n);
  478.  
  479.     if (cs->colorScale.zoom > 1) {
  480.     n = 0;
  481.     AttachZoom(cs, args, &n);
  482.     XtSetValues(wlist[Zoom], args, n);
  483.  
  484.     n = 0;
  485.     AttachBar(cs, args, &n);
  486.     XtSetValues(wlist[Bar], args, n);
  487.  
  488.     XtManageChild(wlist[Bar]);
  489.     XtManageChild(wlist[Zoom]);
  490.     } else {
  491.     XtUnmanageChild(wlist[Bar]);
  492.     XtUnmanageChild(wlist[Zoom]);
  493.     }
  494. }
  495.  
  496. static void AttachLabel(argList, ct)
  497. Arg *argList;
  498. int *ct;
  499. {
  500.     Arg *args = argList + *ct;
  501.     int n = *ct;
  502.  
  503.     XtSetArg(args[n], XtNjustify, XtJustifyCenter);    n++;
  504.  
  505.     *ct += n;
  506. }
  507.  
  508. static void AttachUpArrow(cs, argList, ct)
  509. ColorScaleWidget cs;
  510. Arg *argList;
  511. int *ct;
  512. {
  513.     Widget lbl = cs->colorScale.wlist[Label];
  514.     Arg *args = argList + *ct;
  515.     int n = *ct;
  516.  
  517.     XtSetArg(args[n], XtNfromVert, lbl);            n++;
  518.     XtSetArg(args[n], XtNvertDistance, 85);            n++;
  519.     XtSetArg(args[n], XtNarrowDirection, XtorientationUp);    n++;
  520. /*    XtSetArg(args[n], XmNhighlightThickness, 2);    n++; */
  521. /*    XtSetArg(args[n], XmNtraversalOn, True);        n++; */
  522.  
  523.     *ct += n;
  524. }
  525.  
  526. static void AttachDownArrow(cs, argList, ct)
  527. ColorScaleWidget cs;
  528. Arg *argList;
  529. int *ct;
  530. {
  531.     Widget wid = cs->colorScale.wlist[UpArrow];
  532.     Arg *args = argList + *ct;
  533.     int n = *ct;
  534.  
  535.     XtSetArg(args[n], XtNfromVert, wid);            n++;
  536.     XtSetArg(args[n], XtNvertDistance, 10);            n++;
  537.     XtSetArg(args[n], XtNarrowDirection, XtorientationDown);    n++;
  538. /*    XtSetArg(args[n], XmNhighlightThickness, 2);    n++; */
  539. /*    XtSetArg(args[n], XmNtraversalOn, True);        n++; */
  540.  
  541.     *ct += n;
  542. }
  543.  
  544. static void AttachScrollbar(cs, argList, ct)
  545. ColorScaleWidget cs;
  546. Arg *argList;
  547. int *ct;
  548. {
  549.     Widget arw, lbl;
  550.     Arg *args = argList + *ct;
  551.     int n = *ct;
  552.  
  553.     if (cs->colorScale.inc > 0)
  554.     arw = cs->colorScale.wlist[UpArrow];
  555.     else
  556.     arw = NULL;
  557.     lbl = cs->colorScale.wlist[Label];
  558.  
  559.     XtSetArg(args[n], XtNfromHoriz, arw);            n++;
  560.     XtSetArg(args[n], XtNfromVert, lbl);            n++;
  561.  
  562.     *ct += n;
  563. }
  564.  
  565. /*
  566.  * BUG: Cannot get the form widget to properly constrain children when
  567.  * I set those constraints after creation time.  This forces this rather
  568.  * arcane way of determining constraints.
  569.  */
  570.  
  571. static void AttachBar(cs, argList, ct)
  572. ColorScaleWidget cs;
  573. Arg *argList;
  574. int *ct;
  575. {
  576.     Widget sb = cs->colorScale.wlist[Scrollbar];
  577.     Widget lbl = cs->colorScale.wlist[Label];
  578.     Arg *args = argList + *ct;
  579.     int n = *ct;
  580.  
  581.     XtSetArg(args[n], XtNfromHoriz, sb);            n++;
  582.     XtSetArg(args[n], XtNfromVert, lbl);            n++;
  583.  
  584.     *ct += n;
  585. }
  586.  
  587. static void AttachZoom(cs, argList, ct)
  588. ColorScaleWidget cs;
  589. Arg *argList;
  590. int *ct;
  591. {
  592.     Widget lbl = cs->colorScale.wlist[Label];
  593.     Widget bar = cs->colorScale.wlist[Bar];
  594.     Arg *args = argList + *ct;
  595.     int n = *ct;
  596.  
  597.     XtSetArg(args[n], XtNfromHoriz, bar);            n++;
  598.     XtSetArg(args[n], XtNfromVert, lbl);            n++;
  599.  
  600.     *ct += n;
  601. }
  602.  
  603. static void AttachExpand(cs, argList, ct)
  604. ColorScaleWidget cs;
  605. Arg *argList;
  606. int *ct;
  607. {
  608.     Widget lbl = cs->colorScale.wlist[Label];
  609.     Widget zm = cs->colorScale.wlist[Zoom];
  610.     Arg *args = argList + *ct;
  611.     int n = *ct;
  612.  
  613.     XtSetArg(args[n], XtNfromHoriz, zm);            n++;
  614.     XtSetArg(args[n], XtNfromVert, lbl);            n++;
  615.  
  616.     *ct += n;
  617. }
  618.  
  619. static void CreateChildren(cs)
  620. ColorScaleWidget cs;
  621. {
  622.     int manage = MaxColorScaleChildCt;
  623.     int extent;
  624.     int n = 0;
  625.     float top, shown;
  626.     Arg args[20];
  627.     WidgetList wlist = (WidgetList)cs->colorScale.wlist;
  628.  
  629.     AttachLabel(args, &n);
  630.     XtSetArg(args[n], XtNlabel, cs->colorScale.label);    n++;
  631.     wlist[Label] = XtCreateWidget ("label", labelWidgetClass, (Widget)cs,
  632.                    args, n);
  633.  
  634.     n = 0;
  635.     AttachUpArrow(cs,args, &n);
  636.     XtSetArg(args[n], XtNwidth, 18);                    n++;
  637.     XtSetArg(args[n], XtNheight, 18);                   n++;
  638.     wlist[UpArrow] = XtCreateWidget ("up", repeaterButtonClass, (Widget)cs,
  639.                      args, n);
  640.  
  641.     n = 0;
  642.     AttachDownArrow(cs, args, &n);
  643.     XtSetArg(args[n], XtNwidth, 18);                    n++;
  644.     XtSetArg(args[n], XtNheight, 18);                   n++;
  645.     wlist[DownArrow] = XtCreateWidget("down", repeaterButtonClass, (Widget)cs,
  646.                       args,n);
  647.  
  648.     if (cs->colorScale.zoom <= 1) {
  649.     extent = 100;
  650.     manage -= 2;
  651.     } else{
  652.     extent = SliderFractionBase / cs->colorScale.zoom;
  653.     if (extent < 30)
  654.         extent = 30;
  655.     }
  656.     n = 0;
  657.     AttachScrollbar(cs, args, &n);
  658.     XtSetArg(args[n], XtNwidth, 17);                     n++;
  659.     XtSetArg(args[n], XtNheight, 253);                   n++;
  660.     XtSetArg(args[n], XtNlength, cs->colorScale.max - cs->colorScale.min + 1);
  661.     top = 1.0;
  662.     shown = 32 / (cs->colorScale.max - cs->colorScale.min + 1);
  663.     if (sizeof(float) > sizeof(XtArgVal)) {
  664.     XtSetArg(args[n], XtNtopOfThumb, &top);             n++;
  665.     XtSetArg(args[n], XtNshown, &shown);                n++;
  666.     } else {
  667.     XtArgVal *l_top = (XtArgVal *)⊤
  668.     XtArgVal *l_shown = (XtArgVal *)&shown;
  669.     XtSetArg(args[n], XtNtopOfThumb, *l_top);           n++;
  670.     XtSetArg(args[n], XtNshown, *l_shown);              n++;
  671.     }
  672.     /* XtSetArg(args[n], XtNsliderExtent, extent);            n++; */
  673.     wlist[Scrollbar] = XtCreateWidget ("scrollbar", scrollbarWidgetClass,
  674.                        (Widget)cs, args, n);
  675.  
  676.     n = 0;
  677.     AttachBar(cs, args, &n);
  678.     XtSetArg(args[n], XtNwidth, 17);                    n++;
  679.     XtSetArg(args[n], XtNheight, 253);                    n++;
  680.     if ((int)cs->colorScale.base < 0) {
  681.     XtSetArg(args[n], XtNbase, cs->colorScale.min);            n++;
  682.     } else {
  683.     XtSetArg(args[n], XtNbase, cs->colorScale.base);        n++;
  684.     }
  685.     if (cs->colorScale.length < 0) {
  686.     XtSetArg(args[n], XtNlength, 
  687.             (cs->colorScale.max - cs->colorScale.min + 1));    n++;
  688.     } else {
  689.     XtSetArg(args[n], XtNlength, cs->colorScale.length);        n++;
  690.     }
  691.     if (cs->colorScale.pixelInc > 1) {
  692.     XtSetArg(args[n], XtNpixelInc, cs->colorScale.pixelInc);    n++;
  693.     }
  694.     wlist[Bar] = XtCreateWidget ("bar", colorbarWidgetClass, (Widget)cs,
  695.                  args, n);
  696.  
  697.     /* always create zoom, even if not initially managed */
  698.     n = 0;
  699.     AttachZoom(cs, args, &n);
  700.     XtSetArg(args[n], XtNwidth, 18);                     n++;
  701.     XtSetArg(args[n], XtNheight, 253);                   n++;
  702.     wlist[Zoom] = XtCreateWidget ("zoom", zoomWidgetClass, (Widget)cs,
  703.                   args, n);
  704.  
  705.     n = 0;
  706.     AttachExpand(cs, args, &n);
  707.     XtSetArg(args[n], XtNwidth, 18);                     n++;
  708.     XtSetArg(args[n], XtNheight, 253);                   n++;
  709.     if (cs->colorScale.pixelInc > 1) {
  710.     XtSetArg(args[n], XtNpixelInc, cs->colorScale.pixelInc);    n++;
  711.     }
  712.     wlist[Expand] = XtCreateWidget ("expand", colorbarWidgetClass, (Widget)cs,
  713.                        args, n);
  714.  
  715.     /* add callbacks */
  716.     XtAddCallback(wlist[DownArrow], XtNarmCallback, Incr, (XtPointer)DownArrow);
  717.     XtAddCallback(wlist[DownArrow], XtNactivateCallback, Incr, (XtPointer)DownArrow);
  718.     XtAddCallback(wlist[DownArrow], XtNdisarmCallback, Incr, (XtPointer)DownArrow);
  719.     XtAddCallback(wlist[UpArrow], XtNarmCallback, Incr, (XtPointer)UpArrow);
  720.     XtAddCallback(wlist[UpArrow], XtNactivateCallback, Incr, (XtPointer)UpArrow);
  721.     XtAddCallback(wlist[UpArrow], XtNdisarmCallback, Incr, (XtPointer)UpArrow);
  722.     XtAddCallback(wlist[Scrollbar], XtNjumpProc, Jump, (XtPointer)Scrollbar);
  723.     XtAddCallback(wlist[Scrollbar], XtNscrollProc, Scroll, (XtPointer)Scrollbar);
  724.     XtAddCallback(wlist[Bar], XtNsingleSelectionCallback, Single, (XtPointer)Bar);
  725.     XtAddCallback(wlist[Expand], XtNsingleSelectionCallback, Single, (XtPointer)Expand);
  726.  
  727.     /* manage children; avoid mapping unneeded children */
  728.     if (cs->colorScale.inc > 0)
  729.     XtManageChildren(wlist, manage);
  730.     else
  731.     XtManageChildren(wlist + Label, manage - Label);
  732. }
  733.  
  734. /*
  735.  * Callback for arrow button action
  736.  */
  737. static void Incr(w, which, call)
  738. Widget w;
  739. int which;
  740. ScaleCallbackStruct *call;
  741. {
  742.     ColorScaleWidget cs = (ColorScaleWidget)XtParent(w);
  743.     int val;
  744.     ScaleCallbackStruct tmp;
  745.  
  746.     tmp.reason = call->reason;
  747.  
  748.     /* if reason is not activate, just pass through without value changes */
  749.     if (call->reason == CR_ACTIVATE) {
  750.     if (which == UpArrow) {
  751.         val = cs->colorScale.value + cs->colorScale.inc;
  752.         tmp.reason = CR_INCREMENT;
  753.     } else {
  754.         val = cs->colorScale.value - cs->colorScale.inc;
  755.         tmp.reason = CR_DECREMENT;
  756.     }
  757.     /* If wrapping, move one beyond limit */
  758.     if (val < cs->colorScale.min) {
  759.         if (cs->colorScale.wrap)
  760.         val += cs->colorScale.max - cs->colorScale.min + 1;
  761.         else
  762.         val = cs->colorScale.min;
  763.     } else if (val > cs->colorScale.max) {
  764.         if (cs->colorScale.wrap)
  765.         val -= cs->colorScale.max - cs->colorScale.min + 1;
  766.         else
  767.         val = cs->colorScale.max;
  768.     }
  769.     if (val == cs->colorScale.value)
  770.         return;
  771.     tmp.value = val;
  772.     } else
  773.     tmp.value = cs->colorScale.value;
  774.  
  775.     tmp.event = call->event;
  776.     XtCallCallbacks((Widget)cs, XtNvalueChangedCallback, &tmp);
  777.     /* Check if application trashed the value */
  778.     if ((tmp.value < cs->colorScale.min) || (tmp.value > cs->colorScale.max)) {
  779.     Warning(cs, warning3);        
  780.     return;
  781.     }
  782.     if (tmp.value != cs->colorScale.value)
  783.     NewVal(cs, tmp.value);
  784. }
  785.  
  786. /*
  787.  * Callback for scroll action
  788.  */
  789. /*ARGSUSED*/
  790. static void Scroll(w, which, position)
  791. Widget w;
  792. int which;
  793. int position;
  794. {
  795.     ScrollbarWidget sbw = (ScrollbarWidget)w;
  796.     ColorScaleWidget cs = (ColorScaleWidget)XtParent(w);
  797.     ScaleCallbackStruct call;
  798.     float tmp;
  799.  
  800.     if (position > 0)
  801.         tmp = (float)cs->colorScale.value +
  802.                 ((1.0 - ((float)position / (float)sbw->scrollbar.length)) *
  803.         ((float)cs->colorScale.max - (float)cs->colorScale.min));
  804.     else
  805.         tmp = (float)cs->colorScale.value +
  806.           (((float)position / (float)sbw->scrollbar.length) *
  807.                ((float)cs->colorScale.max - (float)cs->colorScale.min));
  808.  
  809.     if (tmp > cs->colorScale.max)
  810.         tmp = cs->colorScale.max;
  811.     else if (tmp < cs->colorScale.min)
  812.         tmp = cs->colorScale.min;
  813.     call.reason = CR_VALUE_CHANGED;
  814.     call.event = NULL;
  815.     call.value = (int)tmp;
  816.     XtCallCallbacks((Widget)cs, XtNvalueChangedCallback, &call);
  817.  
  818.     /* Check if application trashed the value */
  819.     if ( (call.value < cs->colorScale.min)
  820.         || (call.value > cs->colorScale.max) ) {
  821.     Warning(cs, warning3);        
  822.     return;
  823.     }
  824.     if (call.value != cs->colorScale.value)
  825.     NewVal(cs, call.value);    
  826. }
  827. /*
  828.  * Callback for scale action
  829.  */
  830. /*ARGSUSED*/
  831. static void Jump(w, which, percent_ptr)
  832. Widget w;
  833. int which;
  834. float *percent_ptr;
  835. {
  836.     ColorScaleWidget cs = (ColorScaleWidget)XtParent(w);
  837.     ScaleCallbackStruct call;
  838.     float tmp = (float)cs->colorScale.min + 
  839.         ((float)(1.0 - *percent_ptr) * 
  840.          (float)(cs->colorScale.max - cs->colorScale.min) + 
  841.          (float)(0.5));
  842.  
  843.     call.reason = CR_VALUE_CHANGED;
  844.     call.event = NULL;
  845.     call.value = (int)tmp;
  846.     XtCallCallbacks((Widget)cs, XtNvalueChangedCallback, &call);
  847.  
  848.     /* Check if application trashed the value */
  849.     if ( (call.value < cs->colorScale.min)
  850.         || (call.value > cs->colorScale.max) ) {
  851.     Warning(cs, warning3);        
  852.     return;
  853.     }
  854.     if (call.value != cs->colorScale.value)
  855.     NewVal(cs, call.value);
  856. }
  857.  
  858. static void NewVal(cs, new)
  859. ColorScaleWidget cs;
  860. int new;
  861. {
  862.     float top;
  863.  
  864.     /* TODO: set this directly, avoiding SetValues */
  865.     cs->colorScale.value = new;
  866.     if (new < cs->colorScale.max - 7) {
  867.         top = (float)(cs->colorScale.max - (new + 8)) / 
  868.           (float)(cs->colorScale.max - cs->colorScale.min + 1);
  869.     XawScrollbarSetThumb(cs->colorScale.wlist[Scrollbar], top, -1.0);
  870.     } else {
  871.         XawScrollbarSetThumb(cs->colorScale.wlist[Scrollbar], 1.0, -1.0);
  872.     }
  873.     if (cs->colorScale.zoom > 1)
  874.     SetZoom(cs);
  875. }
  876.  
  877. /*
  878.  * ResetZoom is called when a basic change has occurred in the basic
  879.  * widget attributes like max or min.  This does not happen very often.
  880.  * SetZoom is called in response to a current value change.
  881.  * ResetZoom performs a superset of SetZoom actions by calling it.
  882.  */
  883. static void ResetZoom(cs)
  884. ColorScaleWidget cs;
  885. {
  886.     Arg args[3];
  887.  
  888.     XtSetArg(args[0], XtNleftMin, cs->colorScale.min);
  889.     XtSetArg(args[1], XtNleftMax, cs->colorScale.max);
  890.     /* rightMin defaults to zero, rightMax changes with zoomLen */
  891.     /* all left values change with current value */
  892.     /* rightLow and rightMax default to Min and Max */
  893.     /* rightValue changes with ZoomLen */
  894.     XtSetValues(cs->colorScale.wlist[Zoom], args, 2);
  895.  
  896.     SetZoom(cs);
  897. }
  898.  
  899. static void SetZoom(cs)
  900. ColorScaleWidget cs;
  901. {
  902.     int len, zoomlen;
  903.     int start;
  904.     Arg args[8];
  905.     int n = 0;
  906.  
  907.     len = cs->colorScale.max - cs->colorScale.min + 1;
  908.  
  909.     zoomlen = len / cs->colorScale.zoom;
  910.  
  911.     start = cs->colorScale.value - zoomlen / 2;
  912.     if (start < cs->colorScale.min) {
  913.     zoomlen += start - cs->colorScale.min;
  914.     start = cs->colorScale.min;
  915.     } else if (start + zoomlen > cs->colorScale.min + len) {
  916.     zoomlen = cs->colorScale.min + len - start;
  917.     }
  918.  
  919.     cs->colorScale.zoomBase = start;
  920.     cs->colorScale.zoomLen = zoomlen;
  921.  
  922.     XtSetArg(args[n], XtNbase, start);                    n++;
  923.     XtSetArg(args[n], XtNlength, zoomlen);                n++;
  924.     XtSetValues(cs->colorScale.wlist[Expand], args, n);
  925.  
  926.     n = 0;
  927.     XtSetArg(args[n], XtNleftLow, start);                n++;
  928.     XtSetArg(args[n], XtNleftValue, cs->colorScale.value);        n++;
  929.     XtSetArg(args[n], XtNleftHigh, start+zoomlen-1);            n++;
  930.     XtSetArg(args[n], XtNrightMax, zoomlen-1);                n++;
  931.     XtSetArg(args[n], XtNrightValue, cs->colorScale.value - start);    n++;
  932.     XtSetValues(cs->colorScale.wlist[Zoom], args, n);
  933. }
  934.  
  935. /*
  936.  * Callback for color scale action from Colorbar.
  937.  * Use of ScaleCallbackStruct is required and handled by Colorbar.
  938.  */
  939. static void Single(w, which, call)
  940. Widget w;
  941. int which;
  942. ScaleCallbackStruct *call;
  943. {
  944.     ColorScaleWidget cs = (ColorScaleWidget)XtParent(w);
  945.     double spot = (float)call->value / (CbarFractionBase + 1);
  946.     int len, bs;
  947.  
  948.     if (which == Bar) {
  949.     len = cs->colorScale.max - cs->colorScale.min + 1;
  950.     bs = cs->colorScale.min;
  951.     } else {
  952.     len = cs->colorScale.zoomLen;
  953.     bs = cs->colorScale.zoomBase;
  954.     }
  955.     call->value = (int)floor((double)bs + (spot * (double)len));
  956.     XtCallCallbacks((Widget)cs, XtNvalueChangedCallback, call);
  957.     /* Check if application trashed the value */
  958.     if ( (call->value < cs->colorScale.min)
  959.         || (call->value > cs->colorScale.max) ) {
  960.     Warning(cs, warning3);        
  961.     return;
  962.     }
  963.     if (call->value != cs->colorScale.value)
  964.     NewVal(cs, call->value);
  965. }
  966.