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 / TekBox.c < prev    next >
C/C++ Source or Header  |  1991-08-28  |  31KB  |  926 lines

  1. /***********************************************************
  2. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /*
  26.  * (c) Copyright 1990 1991 Tektronix, Inc.
  27.  * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
  28.  *     All Rights Reserved
  29.  * 
  30.  * This file is a component of an X Window System client which uses the Xcms 
  31.  * Color Management System.  TekColor is a trademark of Tektronix, Inc.  The
  32.  * TekColor Editor is the subject of U.S. and foreign patents pending.  The
  33.  * term "TekHVC" designates a particular color space that is the subject of
  34.  * U.S. Patent No. 4,985,853 (equivalent foreign patents pending).
  35.  * Permission is hereby granted to use, copy, modify, sell, and otherwise
  36.  * distribute this software and its documentation for the X Window System
  37.  * environment, for any purpose and without fee, provided that:
  38.  * 
  39.  * 1.    The code and documentation are only used to implement a 
  40.  *      TekColor Editor in an X Window System environment; and
  41.  * 2.    This copyright and permission notice is reproduced in all copies
  42.  *     of the code and in supporting documentation.
  43.  * 
  44.  * Permission is granted to modify this code as required to allow it to
  45.  * be compiled on any host computer, provided that the functionality of
  46.  * the TekColor Editor is not modified in any way.  A description of any 
  47.  * modifications must be sent to Tektronix, Inc.  Contact 
  48.  * Tektronix Inc., P.O. Box 1000, Mail Station 60-850, 
  49.  * Network Displays Division Engineering, Wilsonville, OR 97070.
  50.  *
  51.  * Tektronix makes no representation about the suitability of this software
  52.  * for any purpose.  It is provided "as is" and with all faults.
  53.  * 
  54.  * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
  55.  * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  56.  * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
  57.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  58.  * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
  59.  * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  60.  * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
  61.  * 
  62.  */
  63.  
  64. #ifndef LINT
  65. #ifdef RCS_ID
  66. static char *rcsid = "$Header: TekBox.c,v 1.2 91/08/22 11:37:06 adamsc Exp $";
  67. #endif /* RCS_ID */
  68. #endif /* LINT */
  69. #ifndef lint
  70. static char Xrcsid[] = "$XConsortium: TekBox.c,v 1.44 90/03/23 18:13:58 converse Exp $";
  71. #endif /* lint */
  72.  
  73. /* 
  74.  * TekBox.c - TekBox composite widget
  75.  * 
  76.  */
  77.  
  78. #include    <stdio.h>
  79. #include    <X11/IntrinsicP.h>
  80. #include    <X11/StringDefs.h>
  81. #include    <X11/Xmu/Misc.h>
  82. #include    <X11/Xaw/SmeP.h>
  83. #include    <X11/Xaw/SimpleMenP.h>
  84. #include    "TekBoxP.h"
  85. #include    <X11/Xaw/XawInit.h>
  86.  
  87. #define MIN_WIDTH   140
  88. #define MIN_HEIGHT  85
  89.  
  90. /****************************************************************
  91.  *
  92.  * TekBox Resources
  93.  *
  94.  ****************************************************************/
  95.  
  96. static XtResource resources[] = {
  97.     { XtNhSpace, XtCHSpace, XtRDimension, sizeof(Dimension),
  98.         XtOffsetOf(TekBoxRec, box.h_space),
  99.         XtRImmediate, (XtPointer)4 },
  100.     { XtNvSpace, XtCVSpace, XtRDimension, sizeof(Dimension),
  101.         XtOffsetOf(TekBoxRec, box.v_space),
  102.         XtRImmediate, (XtPointer)4 },
  103. };
  104.  
  105. /****************************************************************
  106.  *
  107.  * Full class record constant
  108.  *
  109.  ****************************************************************/
  110.  
  111. static void ClassInitialize();
  112. static void Initialize();
  113. static void Realize();
  114. static void Resize();
  115. static Boolean SetValues();
  116. static XtGeometryResult GeometryManager();
  117. static void ChangeManaged();
  118. static XtGeometryResult QueryGeometry();
  119.  
  120. TekBoxClassRec tekBoxClassRec = {
  121.   {
  122. /* core_class fields      */
  123.     /* superclass         */    (WidgetClass) &compositeClassRec,
  124.     /* class_name         */    "TekBox",
  125.     /* widget_size        */    sizeof(TekBoxRec),
  126.     /* class_initialize   */    ClassInitialize,
  127.     /* class_part_init    */    NULL,
  128.     /* class_inited       */    FALSE,
  129.     /* initialize         */    Initialize,
  130.     /* initialize_hook    */    NULL,
  131.     /* realize            */    Realize,
  132.     /* actions            */    NULL,
  133.     /* num_actions      */    0,
  134.     /* resources          */    resources,
  135.     /* num_resources      */    XtNumber(resources),
  136.     /* xrm_class          */    NULLQUARK,
  137.     /* compress_motion      */    TRUE,
  138.     /* compress_exposure  */    TRUE,
  139.     /* compress_enterleave*/    TRUE,
  140.     /* visible_interest   */    FALSE,
  141.     /* destroy            */    NULL,
  142.     /* resize             */    Resize,
  143.     /* expose             */    NULL,
  144.     /* set_values         */    SetValues,
  145.     /* set_values_hook    */    NULL,
  146.     /* set_values_almost  */    XtInheritSetValuesAlmost,
  147.     /* get_values_hook    */    NULL,
  148.     /* accept_focus       */    NULL,
  149.     /* version            */    XtVersion,
  150.     /* callback_private   */    NULL,
  151.     /* tm_table           */    NULL,
  152.     /* query_geometry     */    QueryGeometry,
  153.     /* display_accelerator*/    XtInheritDisplayAccelerator,
  154.     /* extension          */    NULL
  155.   },{
  156. /* composite_class fields */
  157.     /* geometry_manager   */    GeometryManager,
  158.     /* change_managed     */    ChangeManaged,
  159.     /* insert_child      */    XtInheritInsertChild,
  160.     /* delete_child      */    XtInheritDeleteChild,
  161.     /* extension          */    NULL
  162.   },{
  163. /* TekBox class fields */
  164.     /* empty          */    0,
  165.   }
  166. };
  167.  
  168. WidgetClass tekBoxWidgetClass = (WidgetClass)&tekBoxClassRec;
  169.  
  170.  
  171. /****************************************************************
  172.  *
  173.  * Private Routines
  174.  *
  175.  ****************************************************************/
  176.  
  177. /*
  178.  *
  179.  * Do a layout by just calculating size needed.
  180.  * Returns minimum width and height that will preserve the same layout.
  181.  *
  182.  */
  183. static void DoLayout(tbw, width, height, reply_width, reply_height)
  184.     TekBoxWidget    tbw;
  185.     Dimension    width, height;
  186.     Dimension    *reply_width, *reply_height; /* bounding box */
  187. {
  188.     Cardinal  i;
  189.     /* Position  x, y;        /* X and Y position */
  190.     int tw, th;    /* Width and height needed for box         */
  191.     int bw, bh;    /* Width and height needed for current widget */
  192.     int menuh;        /* Height of menubar        */
  193.     int colorw;        /* Width and height of colormap    */
  194.     int patchh;        /* Width and height of patch    */
  195.     int coorw, coorh;    /* Width and height of coordinates    */
  196.     int hbarw;        /* Width and height of huebar        */
  197.     int leafw, leafh;    /* Width and height of hueleaf        */
  198.     Position h_space;        /* Local copy of tbw->box.h_space    */
  199.     Position v_space;        /* Local copy of tbw->box.v_space    */
  200.     XtWidgetGeometry request, prefer;
  201.     register Widget widget;    /* Current widget */
  202.  
  203.     /* TekBox width and height */
  204.     h_space = tbw->box.h_space;
  205.     v_space = tbw->box.v_space;
  206.     /* tw = width; > MIN_WIDTH ? width : MIN_WIDTH;  /* assume minimum size */
  207.     /* th = height; /* > MIN_HEIGHT ? height : MIN_HEIGHT; */
  208.     if ((int)width > 4 * h_space)
  209.     tw = width;
  210.     else
  211.     tw = 5 * h_space;
  212.     if ((int)height > 4 * v_space)
  213.     th = height;
  214.     else
  215.     th = 5 * v_space;
  216.     tw -= (2 * h_space);        /* box width for menu bar */
  217.     th -= (3 * v_space);        /* box height for menu bar and colormap */
  218.     bw = tw - (2 * h_space);        /* box width for all other widgets */
  219.     bh = th - v_space;            /* box height for all other widgets */
  220.  
  221.     /* special checks to make sure I am laying out the correct widgets */
  222.     if (tbw->composite.num_children != 6) {
  223.     fprintf(stderr, "Number of children should be 6; was %d\n", 
  224.         tbw->composite.num_children);
  225.     *reply_width = width;
  226.     *reply_height = height;
  227.     return;
  228.     }
  229.     for (i = 0; i < tbw->composite.num_children; i++) {
  230.     widget = tbw->composite.children[i];
  231.     if (!widget->core.managed) {
  232.         fprintf(stderr, 
  233.             "All widgets should be managed; widget %d unmanaged\n", i);
  234.     }
  235.     }
  236.  
  237.     /***********************************************************************
  238.      * Get the menubar width and height.
  239.      ***********************************************************************/
  240.     widget = tbw->composite.children[MENUBAR];
  241.     request.request_mode = CWWidth | CWHeight;
  242.     request.width = (Dimension) tw;
  243.     request.height = th / 16;
  244.  
  245.     switch(XtQueryGeometry (widget, &request, &prefer)) {
  246.     case XtGeometryYes:
  247.         menuh = (int)request.height;
  248.         break;
  249.     case XtGeometryNo:
  250.     case XtGeometryAlmost:
  251.         if ((prefer.request_mode & CWWidth) &&
  252.         prefer.width > request.width) {
  253.         tw = (int)prefer.width;
  254.         bw = tw - (2 * h_space);
  255.         } 
  256.         if ((prefer.request_mode & CWHeight) &&
  257.         prefer.height > request.height) {
  258.         th += (int)(prefer.height - request.height);
  259.         bh = th - v_space;
  260.         menuh = (int)prefer.height;
  261.         } else {
  262.         menuh = th / 16;
  263.         }
  264.         break;
  265.     }
  266.  
  267.     /***********************************************************************
  268.      * Get the colormap width and height.  
  269.      ***********************************************************************/
  270.     widget = tbw->composite.children[COLORMAP];
  271.     request.request_mode = CWWidth | CWHeight;
  272.     request.width = (Dimension)((bw * 2) / 9);
  273.     request.height = (Dimension)(th - menuh);
  274.  
  275.     switch(XtQueryGeometry (widget, &request, &prefer)) {
  276.     case XtGeometryYes:
  277.         colorw = (int)request.width;
  278.         break;
  279.     case XtGeometryNo:
  280.     case XtGeometryAlmost:
  281.         if ((prefer.request_mode & CWWidth) &&
  282.         prefer.width > request.width) {
  283.         tw += (int)(prefer.width - request.width);
  284.         bw = tw - (2 * h_space);
  285.         colorw = (int)prefer.width;
  286.         } else {
  287.         colorw = (int)request.width;
  288.         }
  289.         if ((prefer.request_mode & CWHeight) &&
  290.             prefer.height > request.height) {
  291.         th += (int)(prefer.height - request.height);
  292.         bh = th - v_space;
  293.         
  294.         } 
  295.         break;
  296.     }
  297.     /* if (colorw > 150)
  298.      *    colorw = 150;
  299.      */
  300.     /***********************************************************************
  301.      * Get the coordinates width and height.  
  302.      ***********************************************************************/
  303.     widget = tbw->composite.children[COORDINATES];
  304.     request.request_mode = CWWidth | CWHeight;
  305.     request.width = (Dimension)((bw - colorw) / 2);
  306.     request.height = (Dimension)(bh / 6);
  307.  
  308.     switch(XtQueryGeometry (widget, &request, &prefer)) {
  309.     case XtGeometryYes:
  310.         coorw = (int)request.width;
  311.         coorh = (int)request.height;
  312.         break;
  313.     case XtGeometryNo:
  314.     case XtGeometryAlmost:
  315.         if ((prefer.request_mode & CWWidth) &&
  316.         prefer.width > request.width) {
  317.         tw += (int)(prefer.width - request.width);
  318.         bw = tw - (2 * h_space);
  319.         coorw = (int)prefer.width;
  320.         } else {
  321.         coorw = (int)request.width;
  322.         }
  323.         if ((prefer.request_mode & CWHeight) &&
  324.         prefer.height > request.height) {
  325.         th += (int)(prefer.height - request.height);
  326.         bh = th - v_space;
  327.         coorh = (int)prefer.height;
  328.         } else {
  329.         coorh = (int)request.height;
  330.         }
  331.         break;
  332.     }
  333.  
  334.     /***********************************************************************
  335.      * Get the patch width and height.  
  336.      ***********************************************************************/
  337.     widget = tbw->composite.children[PATCH];
  338.     request.request_mode = CWWidth | CWHeight;
  339.     request.width = (Dimension)(bw - colorw - coorw);
  340.     request.height = (Dimension)coorh;
  341.  
  342.     switch(XtQueryGeometry (widget, &request, &prefer)) {
  343.     case XtGeometryYes:
  344.         patchh = (int)request.height;
  345.         break;
  346.     case XtGeometryNo:
  347.     case XtGeometryAlmost:
  348.         if ((prefer.request_mode & CWWidth) &&
  349.         prefer.width > request.width) {
  350.         tw += (int)(prefer.width - request.width);
  351.         bw = tw - (2 * h_space);
  352.         }
  353.         if ((prefer.request_mode & CWHeight) &&
  354.         prefer.height > request.height) {
  355.         th += (int)(prefer.height - request.height);
  356.         bh = th - v_space;
  357.         patchh = (int)prefer.height;
  358.         } else {
  359.         patchh = (int)request.height;
  360.         }
  361.         break;
  362.     }
  363.     if (patchh > coorh) {
  364.     coorh = patchh;
  365.     } else
  366.     patchh = coorh;
  367.  
  368.     /***********************************************************************
  369.      * Get the hue bar width and height.  
  370.      ***********************************************************************/
  371.     widget = tbw->composite.children[HUEBAR];
  372.     request.request_mode = CWWidth | CWHeight;
  373.     request.width = (Dimension)(bw / 9);
  374.     request.height = (Dimension)(bh - menuh - coorh);
  375.  
  376.     switch(XtQueryGeometry (widget, &request, &prefer)) {
  377.     case XtGeometryYes:
  378.         hbarw = (int)request.width;
  379.         break;
  380.     case XtGeometryNo:
  381.     case XtGeometryAlmost:
  382.         if ((prefer.request_mode & CWWidth) &&
  383.         prefer.width > request.width) {
  384.         tw += (int)(prefer.width - request.width);
  385.         bw = tw - (2 * h_space);
  386.         hbarw = (int)prefer.width;
  387.         } else {
  388.         hbarw = (int)request.width;
  389.         }
  390.         if ((prefer.request_mode & CWHeight) &&
  391.         prefer.height > request.height) {
  392.         th += (int)(prefer.height - request.height);
  393.         bh = th - v_space;
  394.         }
  395.         break;
  396.     }
  397.     /* if (hbarw > 90)
  398.      *    hbarw = 90;
  399.      */
  400.     /***********************************************************************
  401.      * Get the hue leaf width and height.
  402.      ***********************************************************************/
  403.     widget = tbw->composite.children[HUELEAF];
  404.     request.request_mode = CWWidth | CWHeight;
  405.     request.width = (Dimension)(bw - colorw - hbarw);
  406.     request.height = (Dimension)(bh - menuh - coorh);
  407.  
  408.     switch(XtQueryGeometry (widget, &request, &prefer)) {
  409.     case XtGeometryYes:
  410.         leafw = (int)request.width;
  411.         leafh = (int)request.height;
  412.         break;
  413.     case XtGeometryNo:
  414.     case XtGeometryAlmost:
  415.         if ((prefer.request_mode & CWWidth) &&
  416.         prefer.width > request.width) {
  417.         tw += (int)(prefer.width - request.width);
  418.         bw = tw - (2 * h_space);
  419.         leafw = (int)prefer.width;
  420.         } else {
  421.         leafw = (int)request.width;
  422.         }
  423.         if ((prefer.request_mode & CWHeight) &&
  424.         prefer.height > request.height) {
  425.         th += (int)(prefer.height - request.height);
  426.         bh = th - v_space;
  427.         leafh = (int)prefer.height;
  428.         } else {
  429.         leafh = (int)request.height;
  430.         }
  431.         if (leafw > (leafh * (int)prefer.width) / (int)prefer.height) {
  432.         leafw = (leafh * (int)prefer.width) / (int)prefer.height;
  433.         } else if (leafw < (leafh * (int)prefer.width) / (int)prefer.height) {
  434.         leafh = (leafw * (int)prefer.height) / (int)prefer.width;
  435.         }
  436.         break;
  437.     }
  438.  
  439.     tw += (2 * h_space);
  440.     th += (3 * v_space);
  441.  
  442.     *reply_width = Max(tw, 1);
  443.     *reply_height = Max(th, 1);
  444. }
  445.  
  446. /*
  447.  * Actually use the size requested.  Override any of the children's sizes
  448.  * as needed.
  449.  */
  450. static void Layout(tbw, width, height)
  451.     TekBoxWidget tbw;
  452.     int width, height;
  453. {
  454.     int i;
  455.     Position x, y;             /* X and Y position */
  456.     int tw, th;                /* Width and height needed for box */
  457.     int bw, bh;                /* Width and height needed for current widget */
  458.     int menuw, menuh;          /* Width and height of menubar */
  459.     int colorw, colorh;        /* Width and height of colormap */
  460.     int patchw, patchh;        /* Width and height of patch */
  461.     int coorw, coorh;          /* Width and height of coordinates */
  462.     int hbarw, hbarh;          /* Width and height of huebar */
  463.     int leafw, leafh;          /* Width and height of hueleaf */
  464.     Position h_space;          /* Local copy of tbw->box.v_space */
  465.     Position v_space;          /* Local copy of tbw->box.v_space */
  466.     int num_mapped_children = 0;
  467.     register Widget widget;    /* Current widget */
  468.  
  469.     /* TekBox width and height */
  470.     h_space = tbw->box.h_space;
  471.     v_space = tbw->box.v_space;
  472.     if (width > 4 * h_space)
  473.         tw = width;
  474.     else
  475.         tw = 5 * h_space;
  476.     if (height > 4 * v_space)
  477.         th = height;
  478.     else
  479.         th = 5 * v_space;
  480.     tw -= (2 * h_space);            /* box width for menu bar */
  481.     th -= (3 * v_space);            /* box height for menu bar and colormap */
  482.     bw = tw - (2 * h_space);        /* box width for all other widgets */
  483.     bh = th - v_space;              /* box height for all other widgets */
  484.  
  485.     if (tbw->composite.num_children != 6) {
  486.         fprintf(stderr, "Number of children should be 6; was %d\n",
  487.         tbw->composite.num_children);
  488.     }
  489.     for (i = 0; i < tbw->composite.num_children; i++) {
  490.         widget = tbw->composite.children[i];
  491.     if (!widget->core.managed) {
  492.         fprintf(stderr,
  493.             "All widgets should be managed; widget %d unmanaged\n", i);
  494.     } else {
  495.         num_mapped_children++;
  496.     }
  497.     }
  498.     /* Determine menubar width and height */
  499.     menuw = tw;
  500.     menuh = bh / 16;
  501.     widget = tbw->composite.children[MENUBAR];
  502.     if (widget->core.width != (Dimension)menuw || 
  503.     widget->core.height != (Dimension)menuh ||
  504.     h_space  != widget->core.x || v_space  != widget->core.y)
  505.     XtConfigureWidget (widget, h_space, v_space, 
  506.                 (Dimension)menuw, (Dimension)menuh, 
  507.                  widget->core.border_width);
  508.  
  509.     /* Determine colormap scale width and height */
  510.     colorh = th - menuh;
  511.     colorw = (bw * 2) / 9;
  512.     if (colorw > 150)
  513.         colorw = 150;
  514.     widget = tbw->composite.children[COLORMAP];
  515.     y = menuh + (2 * v_space);
  516.     if (widget->core.width != (Dimension)colorw || 
  517.     widget->core.height != (Dimension)colorh ||
  518.     h_space  != widget->core.x || y != widget->core.y)
  519.     XtConfigureWidget (widget, h_space, y, 
  520.                 (Dimension)colorw, (Dimension)colorh, 
  521.                 widget->core.border_width);
  522.  
  523.     /* Determine the coordinates width and height */
  524.     coorw = (bw - colorw) / 2;
  525.     coorh = (bh - menuh) / 6;
  526.     widget = tbw->composite.children[COORDINATES];
  527.     if (coorh < (int)widget->core.height) 
  528.         coorh = widget->core.height;
  529.     x = width - coorw - h_space;
  530.     /* y = menuh + (2 * v_space); */
  531.     if (widget->core.width != (Dimension)coorw || 
  532.     widget->core.height != (Dimension)coorh ||
  533.     x != widget->core.x || y != widget->core.y)
  534.     XtConfigureWidget (widget, x, y, 
  535.                 (Dimension)coorw, (Dimension)coorh, 
  536.                 widget->core.border_width);
  537.  
  538.     /* Determine the patch width and height */
  539.     patchw = (bw - colorw - coorw);
  540.     patchh = coorh;
  541.     widget = tbw->composite.children[PATCH];
  542.     x = colorw + (2 * h_space);
  543.     /* y = menuh + (2 * v_space); */
  544.     if (widget->core.width != (Dimension)patchw || 
  545.     widget->core.height != (Dimension)patchh ||
  546.     x != widget->core.x || y != widget->core.y)
  547.     XtConfigureWidget (widget, x, y, 
  548.                 (Dimension)patchw, (Dimension)patchh, 
  549.                 widget->core.border_width);
  550.  
  551.     /* Determine the huebar width and height */
  552.     hbarw = bw / 9;
  553.     if (hbarw > 100)
  554.         hbarw = 100;
  555.     hbarh = bh - menuh - coorh;
  556.     widget = tbw->composite.children[HUEBAR];
  557.     y = menuh + coorh + (3 * v_space);
  558.     x = colorw + (2 * h_space);
  559.     if (widget->core.width != (Dimension)hbarw || 
  560.     widget->core.height != (Dimension)hbarh ||
  561.     x != widget->core.x || y != widget->core.y)
  562.     XtConfigureWidget (widget, x, y, 
  563.                 (Dimension)hbarw, (Dimension)hbarh, 
  564.                 widget->core.border_width);
  565.  
  566.     /* Determine the hue leaf width and height */
  567.     leafw = bw - colorw - hbarw;
  568.     leafh = bh - menuh - coorh;
  569.     widget = tbw->composite.children[HUELEAF];
  570.     /* y = menuh + coorh + (3 * v_space); */
  571.     x = colorw + hbarw + (3 * h_space);
  572.     if (widget->core.width != (Dimension)leafw || 
  573.     widget->core.height != (Dimension)leafh ||
  574.     x != widget->core.x || y != widget->core.y)
  575.     XtConfigureWidget (widget, x, y, 
  576.                 (Dimension)leafw, (Dimension)leafh, 
  577.                 widget->core.border_width);
  578.  
  579.     if (XtIsRealized((Widget)tbw)) {
  580.         if (tbw->composite.num_children == num_mapped_children) {
  581.         XMapSubwindows( XtDisplay((Widget)tbw), XtWindow((Widget)tbw) );
  582.     } else {
  583.         register Widget *childP = tbw->composite.children;
  584.  
  585.         for (i = 0; i > 0; childP++, i--)
  586.         if (XtIsRealized(*childP) && XtIsManaged(*childP) &&
  587.             (*childP)->core.mapped_when_managed)
  588.             XtMapWidget(*childP);
  589.     }
  590.     }
  591. }
  592.  
  593. /*
  594.  *
  595.  * Calculate preferred size, given constraining box, caching it in the widget.
  596.  *
  597.  */
  598.  
  599. static XtGeometryResult QueryGeometry(widget, propose, prefer)
  600.     Widget widget;
  601.     XtWidgetGeometry *propose, *prefer;
  602. {
  603.     TekBoxWidget tmpW = (TekBoxWidget)widget;
  604.     Dimension width, height;
  605.     Dimension preferred_width = tmpW->box.preferred_width;
  606.     Dimension preferred_height = tmpW->box.preferred_height;
  607.  
  608.     propose->request_mode &= CWWidth | CWHeight;
  609.  
  610.     if (propose->request_mode == 0)
  611.     /* parent isn't going to change w or h, so nothing to re-compute */
  612.     return XtGeometryYes;
  613.  
  614.     if (propose->request_mode == tmpW->box.last_query_mode &&
  615.     (!(propose->request_mode & CWWidth) ||
  616.      propose->width == tmpW->box.last_query_width) &&
  617.     (!(propose->request_mode & CWHeight) ||
  618.      propose->height == tmpW->box.last_query_height)) {
  619.     /* same query; current preferences are still valid */
  620.     prefer->request_mode = CWWidth | CWHeight;
  621.     prefer->width = preferred_width;
  622.     prefer->height = preferred_height;
  623.     if (propose->request_mode == (CWWidth | CWHeight) &&
  624.         propose->width == preferred_width &&
  625.         propose->height == preferred_height)
  626.         return XtGeometryYes;
  627.     else
  628.         return XtGeometryAlmost;
  629.     }
  630.     
  631.     /* else gotta do it the long way...
  632.      * I have a preference for tall and narrow, so if my width is
  633.      * constrained, I'll accept it; otherwise, I'll compute the minimum
  634.      * width that will fit me within the height proposed.
  635.      */
  636.  
  637.     tmpW->box.last_query_mode = propose->request_mode;
  638.     tmpW->box.last_query_width = propose->width;
  639.     tmpW->box.last_query_height= propose->height;
  640.  
  641.     if (propose->request_mode & (CWWidth | CWHeight)) {
  642.     if (propose->request_mode & CWWidth) {
  643.         width = propose->width;
  644.     } else {
  645.         /* if only looking at height see if we can get smallest */
  646.         /* width for height given */
  647.         width = 0;
  648.         propose->width = 65535;        
  649.     }
  650.     if (propose->request_mode & CWHeight) {
  651.         height = propose->height;
  652.     } else {
  653.         /* if only looking at width see if we can get smallest height */
  654.         /* for given width */
  655.         height = 0;
  656.         propose->height = 65535;
  657.     }
  658.     } else {
  659.     return XtGeometryYes;
  660.     }
  661.  
  662.     DoLayout(tmpW, width, height, &preferred_width, &preferred_height);
  663.  
  664.     if (propose->request_mode & CWHeight &&
  665.     preferred_height > propose->height) {
  666.     /* find minimum width for this height */
  667.     if (preferred_width > propose->width) {
  668.         /* punt; over-constrained */
  669.     } else {
  670.         width = preferred_width;
  671.         do { /* find some width big enough to stay within this height */
  672.         width *= 2;
  673.         if (width > propose->width) 
  674.             width = propose->width;
  675.         DoLayout(tmpW, width, propose->height, 
  676.              &preferred_width, &preferred_height);
  677.         } while (preferred_height > propose->height &&
  678.              width < propose->width);
  679.         if (width != propose->width) {
  680.         do { /* find minimum width */
  681.             width = preferred_width;
  682.             height = propose->height;
  683.             DoLayout(tmpW, preferred_width-1, height,
  684.                  &preferred_width, &preferred_height);
  685.         } while (preferred_height < propose->height);
  686.         /* one last time */
  687.         DoLayout(tmpW, width, height, 
  688.              &preferred_width, &preferred_height);
  689.         }
  690.     }
  691.     }
  692.  
  693.     prefer->request_mode = CWWidth | CWHeight;
  694.     prefer->width = tmpW->box.preferred_width = preferred_width;
  695.     prefer->height = tmpW->box.preferred_height = preferred_height;
  696.  
  697.     if (propose->width == preferred_width &&
  698.     propose->height == preferred_height)
  699.     return XtGeometryYes;
  700.     else
  701.     return XtGeometryAlmost;
  702.  
  703. }
  704.  
  705. /*
  706.  *
  707.  * Actually layout the box
  708.  *
  709.  */
  710.  
  711. static void Resize(widget)
  712.     Widget    widget;
  713. {
  714.  
  715.     Layout((TekBoxWidget)widget, (int)widget->core.width, 
  716.                    (int)widget->core.height);
  717.  
  718. } /* Resize */
  719.  
  720. /*
  721.  *
  722.  * Try to do a new layout within the current width and height;
  723.  * if that fails try to resize and do it within the box returned
  724.  * by QueryGeometry.
  725.  *
  726.  * TryNewLayout just says if it's possible, and doesn't actually move the kids
  727.  */
  728.  
  729. static Boolean TryNewLayout(tbw)
  730.     TekBoxWidget    tbw;
  731. {
  732.     Dimension preferred_width, preferred_height;
  733.     Dimension proposed_width, proposed_height;
  734.     int iterations;
  735.  
  736.     DoLayout(tbw, tbw->core.width, 
  737.           tbw->core.height,
  738.               &preferred_width, &preferred_height);
  739.  
  740.     /* at this point, preferred_width is guaranteed to not be greater
  741.        than tbw->core.width unless some child is larger, so there's no
  742.        point in re-computing another layout */
  743.  
  744.     if ((tbw->core.width == (int)preferred_width) &&
  745.     (tbw->core.height == (int)preferred_height)) {
  746.         /* Same size */
  747.     return (TRUE);
  748.     }
  749.  
  750.     /* let's see if our parent will go for a new size. */
  751.     iterations = 0;
  752.     proposed_width = preferred_width;
  753.     proposed_height = preferred_height;
  754.     do {
  755.     switch (XtMakeResizeRequest((Widget)tbw,(Dimension)proposed_width,(Dimension)proposed_height,
  756.                      (Dimension *)&proposed_width, (Dimension *)&proposed_height))
  757.     {
  758.         case XtGeometryYes:
  759.         return (TRUE);
  760.         case XtGeometryNo:
  761.         if (iterations > 0)
  762.             /* protect from malicious parents who change their minds */
  763.             DoLayout(tbw, tbw->core.width, 
  764.                   tbw->core.height,
  765.                   &preferred_width, &preferred_height);
  766.         if ((preferred_width <= tbw->core.width) &&
  767.             (preferred_height <= tbw->core.height))
  768.             return (TRUE);
  769.         else
  770.             return (FALSE);
  771.  
  772.         case XtGeometryAlmost:
  773.         if (proposed_height >= preferred_height &&
  774.             proposed_width >= preferred_width) {
  775.  
  776.             /*
  777.              * Take it, and assume the parent knows what it is doing.
  778.              *
  779.              * The parent must accept this since it was returned in
  780.              * almost.
  781.              *
  782.              */
  783.             (void) XtMakeResizeRequest( (Widget)tbw,
  784.                        proposed_width, proposed_height,
  785.                        &proposed_width, &proposed_height);
  786.             return(TRUE);
  787.         }
  788.         else if (proposed_width != preferred_width) {
  789.             /* recalc bounding box; height might change */
  790.             DoLayout(tbw, proposed_width, 0,
  791.                  &preferred_width, &preferred_height);
  792.             proposed_height = preferred_height;
  793.         } else { /* proposed_height != preferred_height */
  794.             XtWidgetGeometry constraints, reply;
  795.  
  796.             constraints.request_mode = CWHeight;
  797.             constraints.height = (Dimension)proposed_height;
  798.             (void)QueryGeometry((Widget)tbw, &constraints, &reply);
  799.             proposed_width = preferred_width;
  800.         }
  801.     }
  802.     iterations++;
  803.     } while (iterations < 10);
  804.     return (FALSE);
  805. }
  806.  
  807. /*
  808.  *
  809.  * Geometry Manager
  810.  *
  811.  * 'reply' is unused; we say only yeay or nay, never almost.
  812.  *
  813.  */
  814.  
  815. /*ARGSUSED*/
  816. static XtGeometryResult GeometryManager(w, request, reply)
  817.     Widget        w;
  818.     XtWidgetGeometry    *request;
  819.     XtWidgetGeometry    *reply;    /* RETURN */
  820.  
  821. {
  822.     int width, height, borderWidth;
  823.     TekBoxWidget tbw;
  824.  
  825.     /* Position request always denied */
  826.     if ((request->request_mode & CWX && request->x != w->core.x) ||
  827.     (request->request_mode & CWY && request->y != w->core.y))
  828.         return (XtGeometryNo);
  829.  
  830.     /* Size changes must see if the new size can be accomodated */
  831.     if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth)) {
  832.  
  833.     /* Make all three fields in the request valid */
  834.     if ((request->request_mode & CWWidth) == 0)
  835.         request->width = w->core.width;
  836.     if ((request->request_mode & CWHeight) == 0)
  837.         request->height = w->core.height;
  838.         if ((request->request_mode & CWBorderWidth) == 0)
  839.         request->border_width = w->core.border_width;
  840.  
  841.     /* Save current size and set to new size */
  842.     width = (int)w->core.width;
  843.     height = (int)w->core.height;
  844.     borderWidth = (int)w->core.border_width;
  845.     w->core.width = request->width;
  846.     w->core.height = request->height;
  847.     w->core.border_width = request->border_width;
  848.  
  849.     /* Decide if new layout works: (1) new widget is smaller,
  850.        (2) new widget fits in existing TekBox, (3) TekBox can be
  851.        expanded to allow new widget to fit */
  852.  
  853.     tbw = (TekBoxWidget) w->core.parent;
  854.  
  855.     if (TryNewLayout(tbw)) {
  856.         /* Fits in existing or new space, relayout */
  857.         (*XtClass((Widget)tbw)->core_class.resize)((Widget)tbw);
  858.         return (XtGeometryYes);
  859.     } else {
  860.         /* Cannot satisfy request, change back to original geometry */
  861.         w->core.width = (Dimension)width;
  862.         w->core.height = (Dimension)height;
  863.         w->core.border_width = (Dimension)borderWidth;
  864.         return (XtGeometryNo);
  865.     }
  866.     }; /* if any size changes requested */
  867.  
  868.     /* Any stacking changes don't make a difference, so allow if that's all */
  869.     return (XtGeometryYes);
  870. }
  871.  
  872. static void ChangeManaged(widget)
  873.     Widget widget;
  874. {
  875.     /* Reconfigure the box */
  876.     (void) TryNewLayout((TekBoxWidget)widget);
  877.     Resize(widget);
  878. }
  879.  
  880. static void ClassInitialize()
  881. {
  882.     (void) XawInitializeWidgetSet();
  883.     XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
  884.             NULL, (Cardinal)0 );
  885. }
  886.  
  887. /* ARGSUSED */
  888. static void Initialize(request, new)
  889.     Widget request, new;
  890. {
  891.     TekBoxWidget newtbw = (TekBoxWidget)new;
  892.  
  893.     newtbw->box.last_query_mode = CWWidth | CWHeight;
  894.     newtbw->box.last_query_width = newtbw->box.last_query_height = 0;
  895.     newtbw->box.preferred_width = Max(newtbw->box.h_space, 1);
  896.     newtbw->box.preferred_height = Max(newtbw->box.v_space, 1);
  897.  
  898.     if (newtbw->core.width == 0)
  899.         newtbw->core.width = newtbw->box.preferred_width;
  900.  
  901.     if (newtbw->core.height == 0)
  902.     newtbw->core.height = newtbw->box.preferred_height;
  903.  
  904. } /* Initialize */
  905.  
  906. static void Realize(widget, valueMask, attributes)
  907.     register Widget widget;
  908.     Mask *valueMask;
  909.     XSetWindowAttributes *attributes;
  910. {
  911.     attributes->bit_gravity = NorthWestGravity;
  912.     *valueMask |= CWBitGravity;
  913.  
  914.     XtCreateWindow(widget, (unsigned)InputOutput, (Visual *)CopyFromParent,
  915.             *valueMask, attributes);
  916. } /* Realize */
  917.  
  918. /* ARGSUSED */
  919. static Boolean SetValues(current, request, new)
  920.     Widget current, request, new;
  921. {
  922.    /* need to relayout if h_space or v_space change */
  923.  
  924.     return False;
  925. }
  926.