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 >
Wrap
C/C++ Source or Header
|
1991-08-28
|
31KB
|
926 lines
/***********************************************************
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
/*
* (c) Copyright 1990 1991 Tektronix, Inc.
* Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
* All Rights Reserved
*
* This file is a component of an X Window System client which uses the Xcms
* Color Management System. TekColor is a trademark of Tektronix, Inc. The
* TekColor Editor is the subject of U.S. and foreign patents pending. The
* term "TekHVC" designates a particular color space that is the subject of
* U.S. Patent No. 4,985,853 (equivalent foreign patents pending).
* Permission is hereby granted to use, copy, modify, sell, and otherwise
* distribute this software and its documentation for the X Window System
* environment, for any purpose and without fee, provided that:
*
* 1. The code and documentation are only used to implement a
* TekColor Editor in an X Window System environment; and
* 2. This copyright and permission notice is reproduced in all copies
* of the code and in supporting documentation.
*
* Permission is granted to modify this code as required to allow it to
* be compiled on any host computer, provided that the functionality of
* the TekColor Editor is not modified in any way. A description of any
* modifications must be sent to Tektronix, Inc. Contact
* Tektronix Inc., P.O. Box 1000, Mail Station 60-850,
* Network Displays Division Engineering, Wilsonville, OR 97070.
*
* Tektronix makes no representation about the suitability of this software
* for any purpose. It is provided "as is" and with all faults.
*
* TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
* INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef LINT
#ifdef RCS_ID
static char *rcsid = "$Header: TekBox.c,v 1.2 91/08/22 11:37:06 adamsc Exp $";
#endif /* RCS_ID */
#endif /* LINT */
#ifndef lint
static char Xrcsid[] = "$XConsortium: TekBox.c,v 1.44 90/03/23 18:13:58 converse Exp $";
#endif /* lint */
/*
* TekBox.c - TekBox composite widget
*
*/
#include <stdio.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xmu/Misc.h>
#include <X11/Xaw/SmeP.h>
#include <X11/Xaw/SimpleMenP.h>
#include "TekBoxP.h"
#include <X11/Xaw/XawInit.h>
#define MIN_WIDTH 140
#define MIN_HEIGHT 85
/****************************************************************
*
* TekBox Resources
*
****************************************************************/
static XtResource resources[] = {
{ XtNhSpace, XtCHSpace, XtRDimension, sizeof(Dimension),
XtOffsetOf(TekBoxRec, box.h_space),
XtRImmediate, (XtPointer)4 },
{ XtNvSpace, XtCVSpace, XtRDimension, sizeof(Dimension),
XtOffsetOf(TekBoxRec, box.v_space),
XtRImmediate, (XtPointer)4 },
};
/****************************************************************
*
* Full class record constant
*
****************************************************************/
static void ClassInitialize();
static void Initialize();
static void Realize();
static void Resize();
static Boolean SetValues();
static XtGeometryResult GeometryManager();
static void ChangeManaged();
static XtGeometryResult QueryGeometry();
TekBoxClassRec tekBoxClassRec = {
{
/* core_class fields */
/* superclass */ (WidgetClass) &compositeClassRec,
/* class_name */ "TekBox",
/* widget_size */ sizeof(TekBoxRec),
/* class_initialize */ ClassInitialize,
/* class_part_init */ NULL,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ Realize,
/* actions */ NULL,
/* num_actions */ 0,
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ TRUE,
/* compress_enterleave*/ TRUE,
/* visible_interest */ FALSE,
/* destroy */ NULL,
/* resize */ Resize,
/* expose */ NULL,
/* set_values */ SetValues,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* accept_focus */ NULL,
/* version */ XtVersion,
/* callback_private */ NULL,
/* tm_table */ NULL,
/* query_geometry */ QueryGeometry,
/* display_accelerator*/ XtInheritDisplayAccelerator,
/* extension */ NULL
},{
/* composite_class fields */
/* geometry_manager */ GeometryManager,
/* change_managed */ ChangeManaged,
/* insert_child */ XtInheritInsertChild,
/* delete_child */ XtInheritDeleteChild,
/* extension */ NULL
},{
/* TekBox class fields */
/* empty */ 0,
}
};
WidgetClass tekBoxWidgetClass = (WidgetClass)&tekBoxClassRec;
/****************************************************************
*
* Private Routines
*
****************************************************************/
/*
*
* Do a layout by just calculating size needed.
* Returns minimum width and height that will preserve the same layout.
*
*/
static void DoLayout(tbw, width, height, reply_width, reply_height)
TekBoxWidget tbw;
Dimension width, height;
Dimension *reply_width, *reply_height; /* bounding box */
{
Cardinal i;
/* Position x, y; /* X and Y position */
int tw, th; /* Width and height needed for box */
int bw, bh; /* Width and height needed for current widget */
int menuh; /* Height of menubar */
int colorw; /* Width and height of colormap */
int patchh; /* Width and height of patch */
int coorw, coorh; /* Width and height of coordinates */
int hbarw; /* Width and height of huebar */
int leafw, leafh; /* Width and height of hueleaf */
Position h_space; /* Local copy of tbw->box.h_space */
Position v_space; /* Local copy of tbw->box.v_space */
XtWidgetGeometry request, prefer;
register Widget widget; /* Current widget */
/* TekBox width and height */
h_space = tbw->box.h_space;
v_space = tbw->box.v_space;
/* tw = width; > MIN_WIDTH ? width : MIN_WIDTH; /* assume minimum size */
/* th = height; /* > MIN_HEIGHT ? height : MIN_HEIGHT; */
if ((int)width > 4 * h_space)
tw = width;
else
tw = 5 * h_space;
if ((int)height > 4 * v_space)
th = height;
else
th = 5 * v_space;
tw -= (2 * h_space); /* box width for menu bar */
th -= (3 * v_space); /* box height for menu bar and colormap */
bw = tw - (2 * h_space); /* box width for all other widgets */
bh = th - v_space; /* box height for all other widgets */
/* special checks to make sure I am laying out the correct widgets */
if (tbw->composite.num_children != 6) {
fprintf(stderr, "Number of children should be 6; was %d\n",
tbw->composite.num_children);
*reply_width = width;
*reply_height = height;
return;
}
for (i = 0; i < tbw->composite.num_children; i++) {
widget = tbw->composite.children[i];
if (!widget->core.managed) {
fprintf(stderr,
"All widgets should be managed; widget %d unmanaged\n", i);
}
}
/***********************************************************************
* Get the menubar width and height.
***********************************************************************/
widget = tbw->composite.children[MENUBAR];
request.request_mode = CWWidth | CWHeight;
request.width = (Dimension) tw;
request.height = th / 16;
switch(XtQueryGeometry (widget, &request, &prefer)) {
case XtGeometryYes:
menuh = (int)request.height;
break;
case XtGeometryNo:
case XtGeometryAlmost:
if ((prefer.request_mode & CWWidth) &&
prefer.width > request.width) {
tw = (int)prefer.width;
bw = tw - (2 * h_space);
}
if ((prefer.request_mode & CWHeight) &&
prefer.height > request.height) {
th += (int)(prefer.height - request.height);
bh = th - v_space;
menuh = (int)prefer.height;
} else {
menuh = th / 16;
}
break;
}
/***********************************************************************
* Get the colormap width and height.
***********************************************************************/
widget = tbw->composite.children[COLORMAP];
request.request_mode = CWWidth | CWHeight;
request.width = (Dimension)((bw * 2) / 9);
request.height = (Dimension)(th - menuh);
switch(XtQueryGeometry (widget, &request, &prefer)) {
case XtGeometryYes:
colorw = (int)request.width;
break;
case XtGeometryNo:
case XtGeometryAlmost:
if ((prefer.request_mode & CWWidth) &&
prefer.width > request.width) {
tw += (int)(prefer.width - request.width);
bw = tw - (2 * h_space);
colorw = (int)prefer.width;
} else {
colorw = (int)request.width;
}
if ((prefer.request_mode & CWHeight) &&
prefer.height > request.height) {
th += (int)(prefer.height - request.height);
bh = th - v_space;
}
break;
}
/* if (colorw > 150)
* colorw = 150;
*/
/***********************************************************************
* Get the coordinates width and height.
***********************************************************************/
widget = tbw->composite.children[COORDINATES];
request.request_mode = CWWidth | CWHeight;
request.width = (Dimension)((bw - colorw) / 2);
request.height = (Dimension)(bh / 6);
switch(XtQueryGeometry (widget, &request, &prefer)) {
case XtGeometryYes:
coorw = (int)request.width;
coorh = (int)request.height;
break;
case XtGeometryNo:
case XtGeometryAlmost:
if ((prefer.request_mode & CWWidth) &&
prefer.width > request.width) {
tw += (int)(prefer.width - request.width);
bw = tw - (2 * h_space);
coorw = (int)prefer.width;
} else {
coorw = (int)request.width;
}
if ((prefer.request_mode & CWHeight) &&
prefer.height > request.height) {
th += (int)(prefer.height - request.height);
bh = th - v_space;
coorh = (int)prefer.height;
} else {
coorh = (int)request.height;
}
break;
}
/***********************************************************************
* Get the patch width and height.
***********************************************************************/
widget = tbw->composite.children[PATCH];
request.request_mode = CWWidth | CWHeight;
request.width = (Dimension)(bw - colorw - coorw);
request.height = (Dimension)coorh;
switch(XtQueryGeometry (widget, &request, &prefer)) {
case XtGeometryYes:
patchh = (int)request.height;
break;
case XtGeometryNo:
case XtGeometryAlmost:
if ((prefer.request_mode & CWWidth) &&
prefer.width > request.width) {
tw += (int)(prefer.width - request.width);
bw = tw - (2 * h_space);
}
if ((prefer.request_mode & CWHeight) &&
prefer.height > request.height) {
th += (int)(prefer.height - request.height);
bh = th - v_space;
patchh = (int)prefer.height;
} else {
patchh = (int)request.height;
}
break;
}
if (patchh > coorh) {
coorh = patchh;
} else
patchh = coorh;
/***********************************************************************
* Get the hue bar width and height.
***********************************************************************/
widget = tbw->composite.children[HUEBAR];
request.request_mode = CWWidth | CWHeight;
request.width = (Dimension)(bw / 9);
request.height = (Dimension)(bh - menuh - coorh);
switch(XtQueryGeometry (widget, &request, &prefer)) {
case XtGeometryYes:
hbarw = (int)request.width;
break;
case XtGeometryNo:
case XtGeometryAlmost:
if ((prefer.request_mode & CWWidth) &&
prefer.width > request.width) {
tw += (int)(prefer.width - request.width);
bw = tw - (2 * h_space);
hbarw = (int)prefer.width;
} else {
hbarw = (int)request.width;
}
if ((prefer.request_mode & CWHeight) &&
prefer.height > request.height) {
th += (int)(prefer.height - request.height);
bh = th - v_space;
}
break;
}
/* if (hbarw > 90)
* hbarw = 90;
*/
/***********************************************************************
* Get the hue leaf width and height.
***********************************************************************/
widget = tbw->composite.children[HUELEAF];
request.request_mode = CWWidth | CWHeight;
request.width = (Dimension)(bw - colorw - hbarw);
request.height = (Dimension)(bh - menuh - coorh);
switch(XtQueryGeometry (widget, &request, &prefer)) {
case XtGeometryYes:
leafw = (int)request.width;
leafh = (int)request.height;
break;
case XtGeometryNo:
case XtGeometryAlmost:
if ((prefer.request_mode & CWWidth) &&
prefer.width > request.width) {
tw += (int)(prefer.width - request.width);
bw = tw - (2 * h_space);
leafw = (int)prefer.width;
} else {
leafw = (int)request.width;
}
if ((prefer.request_mode & CWHeight) &&
prefer.height > request.height) {
th += (int)(prefer.height - request.height);
bh = th - v_space;
leafh = (int)prefer.height;
} else {
leafh = (int)request.height;
}
if (leafw > (leafh * (int)prefer.width) / (int)prefer.height) {
leafw = (leafh * (int)prefer.width) / (int)prefer.height;
} else if (leafw < (leafh * (int)prefer.width) / (int)prefer.height) {
leafh = (leafw * (int)prefer.height) / (int)prefer.width;
}
break;
}
tw += (2 * h_space);
th += (3 * v_space);
*reply_width = Max(tw, 1);
*reply_height = Max(th, 1);
}
/*
* Actually use the size requested. Override any of the children's sizes
* as needed.
*/
static void Layout(tbw, width, height)
TekBoxWidget tbw;
int width, height;
{
int i;
Position x, y; /* X and Y position */
int tw, th; /* Width and height needed for box */
int bw, bh; /* Width and height needed for current widget */
int menuw, menuh; /* Width and height of menubar */
int colorw, colorh; /* Width and height of colormap */
int patchw, patchh; /* Width and height of patch */
int coorw, coorh; /* Width and height of coordinates */
int hbarw, hbarh; /* Width and height of huebar */
int leafw, leafh; /* Width and height of hueleaf */
Position h_space; /* Local copy of tbw->box.v_space */
Position v_space; /* Local copy of tbw->box.v_space */
int num_mapped_children = 0;
register Widget widget; /* Current widget */
/* TekBox width and height */
h_space = tbw->box.h_space;
v_space = tbw->box.v_space;
if (width > 4 * h_space)
tw = width;
else
tw = 5 * h_space;
if (height > 4 * v_space)
th = height;
else
th = 5 * v_space;
tw -= (2 * h_space); /* box width for menu bar */
th -= (3 * v_space); /* box height for menu bar and colormap */
bw = tw - (2 * h_space); /* box width for all other widgets */
bh = th - v_space; /* box height for all other widgets */
if (tbw->composite.num_children != 6) {
fprintf(stderr, "Number of children should be 6; was %d\n",
tbw->composite.num_children);
}
for (i = 0; i < tbw->composite.num_children; i++) {
widget = tbw->composite.children[i];
if (!widget->core.managed) {
fprintf(stderr,
"All widgets should be managed; widget %d unmanaged\n", i);
} else {
num_mapped_children++;
}
}
/* Determine menubar width and height */
menuw = tw;
menuh = bh / 16;
widget = tbw->composite.children[MENUBAR];
if (widget->core.width != (Dimension)menuw ||
widget->core.height != (Dimension)menuh ||
h_space != widget->core.x || v_space != widget->core.y)
XtConfigureWidget (widget, h_space, v_space,
(Dimension)menuw, (Dimension)menuh,
widget->core.border_width);
/* Determine colormap scale width and height */
colorh = th - menuh;
colorw = (bw * 2) / 9;
if (colorw > 150)
colorw = 150;
widget = tbw->composite.children[COLORMAP];
y = menuh + (2 * v_space);
if (widget->core.width != (Dimension)colorw ||
widget->core.height != (Dimension)colorh ||
h_space != widget->core.x || y != widget->core.y)
XtConfigureWidget (widget, h_space, y,
(Dimension)colorw, (Dimension)colorh,
widget->core.border_width);
/* Determine the coordinates width and height */
coorw = (bw - colorw) / 2;
coorh = (bh - menuh) / 6;
widget = tbw->composite.children[COORDINATES];
if (coorh < (int)widget->core.height)
coorh = widget->core.height;
x = width - coorw - h_space;
/* y = menuh + (2 * v_space); */
if (widget->core.width != (Dimension)coorw ||
widget->core.height != (Dimension)coorh ||
x != widget->core.x || y != widget->core.y)
XtConfigureWidget (widget, x, y,
(Dimension)coorw, (Dimension)coorh,
widget->core.border_width);
/* Determine the patch width and height */
patchw = (bw - colorw - coorw);
patchh = coorh;
widget = tbw->composite.children[PATCH];
x = colorw + (2 * h_space);
/* y = menuh + (2 * v_space); */
if (widget->core.width != (Dimension)patchw ||
widget->core.height != (Dimension)patchh ||
x != widget->core.x || y != widget->core.y)
XtConfigureWidget (widget, x, y,
(Dimension)patchw, (Dimension)patchh,
widget->core.border_width);
/* Determine the huebar width and height */
hbarw = bw / 9;
if (hbarw > 100)
hbarw = 100;
hbarh = bh - menuh - coorh;
widget = tbw->composite.children[HUEBAR];
y = menuh + coorh + (3 * v_space);
x = colorw + (2 * h_space);
if (widget->core.width != (Dimension)hbarw ||
widget->core.height != (Dimension)hbarh ||
x != widget->core.x || y != widget->core.y)
XtConfigureWidget (widget, x, y,
(Dimension)hbarw, (Dimension)hbarh,
widget->core.border_width);
/* Determine the hue leaf width and height */
leafw = bw - colorw - hbarw;
leafh = bh - menuh - coorh;
widget = tbw->composite.children[HUELEAF];
/* y = menuh + coorh + (3 * v_space); */
x = colorw + hbarw + (3 * h_space);
if (widget->core.width != (Dimension)leafw ||
widget->core.height != (Dimension)leafh ||
x != widget->core.x || y != widget->core.y)
XtConfigureWidget (widget, x, y,
(Dimension)leafw, (Dimension)leafh,
widget->core.border_width);
if (XtIsRealized((Widget)tbw)) {
if (tbw->composite.num_children == num_mapped_children) {
XMapSubwindows( XtDisplay((Widget)tbw), XtWindow((Widget)tbw) );
} else {
register Widget *childP = tbw->composite.children;
for (i = 0; i > 0; childP++, i--)
if (XtIsRealized(*childP) && XtIsManaged(*childP) &&
(*childP)->core.mapped_when_managed)
XtMapWidget(*childP);
}
}
}
/*
*
* Calculate preferred size, given constraining box, caching it in the widget.
*
*/
static XtGeometryResult QueryGeometry(widget, propose, prefer)
Widget widget;
XtWidgetGeometry *propose, *prefer;
{
TekBoxWidget tmpW = (TekBoxWidget)widget;
Dimension width, height;
Dimension preferred_width = tmpW->box.preferred_width;
Dimension preferred_height = tmpW->box.preferred_height;
propose->request_mode &= CWWidth | CWHeight;
if (propose->request_mode == 0)
/* parent isn't going to change w or h, so nothing to re-compute */
return XtGeometryYes;
if (propose->request_mode == tmpW->box.last_query_mode &&
(!(propose->request_mode & CWWidth) ||
propose->width == tmpW->box.last_query_width) &&
(!(propose->request_mode & CWHeight) ||
propose->height == tmpW->box.last_query_height)) {
/* same query; current preferences are still valid */
prefer->request_mode = CWWidth | CWHeight;
prefer->width = preferred_width;
prefer->height = preferred_height;
if (propose->request_mode == (CWWidth | CWHeight) &&
propose->width == preferred_width &&
propose->height == preferred_height)
return XtGeometryYes;
else
return XtGeometryAlmost;
}
/* else gotta do it the long way...
* I have a preference for tall and narrow, so if my width is
* constrained, I'll accept it; otherwise, I'll compute the minimum
* width that will fit me within the height proposed.
*/
tmpW->box.last_query_mode = propose->request_mode;
tmpW->box.last_query_width = propose->width;
tmpW->box.last_query_height= propose->height;
if (propose->request_mode & (CWWidth | CWHeight)) {
if (propose->request_mode & CWWidth) {
width = propose->width;
} else {
/* if only looking at height see if we can get smallest */
/* width for height given */
width = 0;
propose->width = 65535;
}
if (propose->request_mode & CWHeight) {
height = propose->height;
} else {
/* if only looking at width see if we can get smallest height */
/* for given width */
height = 0;
propose->height = 65535;
}
} else {
return XtGeometryYes;
}
DoLayout(tmpW, width, height, &preferred_width, &preferred_height);
if (propose->request_mode & CWHeight &&
preferred_height > propose->height) {
/* find minimum width for this height */
if (preferred_width > propose->width) {
/* punt; over-constrained */
} else {
width = preferred_width;
do { /* find some width big enough to stay within this height */
width *= 2;
if (width > propose->width)
width = propose->width;
DoLayout(tmpW, width, propose->height,
&preferred_width, &preferred_height);
} while (preferred_height > propose->height &&
width < propose->width);
if (width != propose->width) {
do { /* find minimum width */
width = preferred_width;
height = propose->height;
DoLayout(tmpW, preferred_width-1, height,
&preferred_width, &preferred_height);
} while (preferred_height < propose->height);
/* one last time */
DoLayout(tmpW, width, height,
&preferred_width, &preferred_height);
}
}
}
prefer->request_mode = CWWidth | CWHeight;
prefer->width = tmpW->box.preferred_width = preferred_width;
prefer->height = tmpW->box.preferred_height = preferred_height;
if (propose->width == preferred_width &&
propose->height == preferred_height)
return XtGeometryYes;
else
return XtGeometryAlmost;
}
/*
*
* Actually layout the box
*
*/
static void Resize(widget)
Widget widget;
{
Layout((TekBoxWidget)widget, (int)widget->core.width,
(int)widget->core.height);
} /* Resize */
/*
*
* Try to do a new layout within the current width and height;
* if that fails try to resize and do it within the box returned
* by QueryGeometry.
*
* TryNewLayout just says if it's possible, and doesn't actually move the kids
*/
static Boolean TryNewLayout(tbw)
TekBoxWidget tbw;
{
Dimension preferred_width, preferred_height;
Dimension proposed_width, proposed_height;
int iterations;
DoLayout(tbw, tbw->core.width,
tbw->core.height,
&preferred_width, &preferred_height);
/* at this point, preferred_width is guaranteed to not be greater
than tbw->core.width unless some child is larger, so there's no
point in re-computing another layout */
if ((tbw->core.width == (int)preferred_width) &&
(tbw->core.height == (int)preferred_height)) {
/* Same size */
return (TRUE);
}
/* let's see if our parent will go for a new size. */
iterations = 0;
proposed_width = preferred_width;
proposed_height = preferred_height;
do {
switch (XtMakeResizeRequest((Widget)tbw,(Dimension)proposed_width,(Dimension)proposed_height,
(Dimension *)&proposed_width, (Dimension *)&proposed_height))
{
case XtGeometryYes:
return (TRUE);
case XtGeometryNo:
if (iterations > 0)
/* protect from malicious parents who change their minds */
DoLayout(tbw, tbw->core.width,
tbw->core.height,
&preferred_width, &preferred_height);
if ((preferred_width <= tbw->core.width) &&
(preferred_height <= tbw->core.height))
return (TRUE);
else
return (FALSE);
case XtGeometryAlmost:
if (proposed_height >= preferred_height &&
proposed_width >= preferred_width) {
/*
* Take it, and assume the parent knows what it is doing.
*
* The parent must accept this since it was returned in
* almost.
*
*/
(void) XtMakeResizeRequest( (Widget)tbw,
proposed_width, proposed_height,
&proposed_width, &proposed_height);
return(TRUE);
}
else if (proposed_width != preferred_width) {
/* recalc bounding box; height might change */
DoLayout(tbw, proposed_width, 0,
&preferred_width, &preferred_height);
proposed_height = preferred_height;
} else { /* proposed_height != preferred_height */
XtWidgetGeometry constraints, reply;
constraints.request_mode = CWHeight;
constraints.height = (Dimension)proposed_height;
(void)QueryGeometry((Widget)tbw, &constraints, &reply);
proposed_width = preferred_width;
}
}
iterations++;
} while (iterations < 10);
return (FALSE);
}
/*
*
* Geometry Manager
*
* 'reply' is unused; we say only yeay or nay, never almost.
*
*/
/*ARGSUSED*/
static XtGeometryResult GeometryManager(w, request, reply)
Widget w;
XtWidgetGeometry *request;
XtWidgetGeometry *reply; /* RETURN */
{
int width, height, borderWidth;
TekBoxWidget tbw;
/* Position request always denied */
if ((request->request_mode & CWX && request->x != w->core.x) ||
(request->request_mode & CWY && request->y != w->core.y))
return (XtGeometryNo);
/* Size changes must see if the new size can be accomodated */
if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth)) {
/* Make all three fields in the request valid */
if ((request->request_mode & CWWidth) == 0)
request->width = w->core.width;
if ((request->request_mode & CWHeight) == 0)
request->height = w->core.height;
if ((request->request_mode & CWBorderWidth) == 0)
request->border_width = w->core.border_width;
/* Save current size and set to new size */
width = (int)w->core.width;
height = (int)w->core.height;
borderWidth = (int)w->core.border_width;
w->core.width = request->width;
w->core.height = request->height;
w->core.border_width = request->border_width;
/* Decide if new layout works: (1) new widget is smaller,
(2) new widget fits in existing TekBox, (3) TekBox can be
expanded to allow new widget to fit */
tbw = (TekBoxWidget) w->core.parent;
if (TryNewLayout(tbw)) {
/* Fits in existing or new space, relayout */
(*XtClass((Widget)tbw)->core_class.resize)((Widget)tbw);
return (XtGeometryYes);
} else {
/* Cannot satisfy request, change back to original geometry */
w->core.width = (Dimension)width;
w->core.height = (Dimension)height;
w->core.border_width = (Dimension)borderWidth;
return (XtGeometryNo);
}
}; /* if any size changes requested */
/* Any stacking changes don't make a difference, so allow if that's all */
return (XtGeometryYes);
}
static void ChangeManaged(widget)
Widget widget;
{
/* Reconfigure the box */
(void) TryNewLayout((TekBoxWidget)widget);
Resize(widget);
}
static void ClassInitialize()
{
(void) XawInitializeWidgetSet();
XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
NULL, (Cardinal)0 );
}
/* ARGSUSED */
static void Initialize(request, new)
Widget request, new;
{
TekBoxWidget newtbw = (TekBoxWidget)new;
newtbw->box.last_query_mode = CWWidth | CWHeight;
newtbw->box.last_query_width = newtbw->box.last_query_height = 0;
newtbw->box.preferred_width = Max(newtbw->box.h_space, 1);
newtbw->box.preferred_height = Max(newtbw->box.v_space, 1);
if (newtbw->core.width == 0)
newtbw->core.width = newtbw->box.preferred_width;
if (newtbw->core.height == 0)
newtbw->core.height = newtbw->box.preferred_height;
} /* Initialize */
static void Realize(widget, valueMask, attributes)
register Widget widget;
Mask *valueMask;
XSetWindowAttributes *attributes;
{
attributes->bit_gravity = NorthWestGravity;
*valueMask |= CWBitGravity;
XtCreateWindow(widget, (unsigned)InputOutput, (Visual *)CopyFromParent,
*valueMask, attributes);
} /* Realize */
/* ARGSUSED */
static Boolean SetValues(current, request, new)
Widget current, request, new;
{
/* need to relayout if h_space or v_space change */
return False;
}