|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: R T
Length: 41965 (0xa3ed)
Types: TextFile
Names: »RButton.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z«
└─⟦2109abc41⟧
└─⟦this⟧ »./X.V10R4/Toolkit/Xr/src/Xrlib/Editor/RButton.c«
/*
* $Source: /u1/Xr/src/Xrlib/Editor/RCS/RButton.c,v $
* $Header: RButton.c,v 1.1 86/12/17 09:02:37 swick Exp $
*/
#ifndef lint
static char *rcsid_RButton_c = "$Header: RButton.c,v 1.1 86/12/17 09:02:37 swick Exp $";
#endif lint
#include <Xr/xr-copyright.h>
/* $Header: RButton.c,v 1.1 86/12/17 09:02:37 swick Exp $ */
/* Copyright 1986, Hewlett-Packard Company */
/* Copyright 1986, Massachussetts Institute of Technology */
static char rcsid[] = "$Header: RButton.c,v 1.1 86/12/17 09:02:37 swick Exp $";
/*************************************<+>*************************************
*****************************************************************************
**
** File: RButton.c
**
** Project: X-ray Toolbox
**
** Description:
** This file contains the source code for the X-ray radio
** button field editor.
**
**
** ------------------------ MODIFICATION RECORD ------------------------
*
* $Log: RButton.c,v $
* Revision 1.1 86/12/17 09:02:37 swick
* Initial revision
*
* Revision 7.0 86/11/13 08:24:18 08:24:18 fred ()
* Final QA Release
*
* Revision 6.1 86/11/10 16:12:17 16:12:17 fred ()
* Revised circle drawing algorithm.
*
* Revision 6.0 86/11/10 15:29:57 15:29:57 fred ()
* QA #2 release
*
* Revision 5.2 86/11/07 14:20:50 14:20:50 fred ()
* Added new copyright message.
*
* Revision 5.1 86/10/30 13:28:06 13:28:06 fred ()
* Added check for numCols <= 0, and changed the button
* drawing algorithm.
*
* Revision 5.0 86/10/28 08:29:24 08:29:24 fred ()
* QA #1.1 release
*
* Revision 4.0 86/10/20 12:11:06 12:11:06 fred ()
* QA #1 release
*
* Revision 3.5 86/10/16 10:04:35 10:04:35 fred ()
* Filled in the procedure headers.
*
* Revision 3.4 86/10/16 09:15:42 09:15:42 fred ()
* Performance enhanced: added use of register variables.
*
* Revision 3.3 86/10/13 10:06:03 10:06:03 fred ()
* Added use of the default tile, if needed.
*
* Revision 3.2 86/10/09 07:45:30 07:45:30 fred ()
* Added default color check to create routine.
*
* Revision 3.1 86/10/07 16:04:54 16:04:54 fred ()
* Added check for invalid rectangle size.
*
* Revision 3.0 86/10/02 15:59:26 15:59:26 fred ()
* Alpha release set to 3.0
*
* Revision 2.5 86/10/01 06:54:05 06:54:05 fred ()
* Changed default label padding from font's maxWidth to avgWidth.
*
* Revision 2.4 86/09/30 08:34:23 08:34:23 fred ()
* Modified the return event so that value3 contains the index
* of the previously active radio button.
*
* Revision 2.3 86/09/25 13:25:29 13:25:29 fred ()
* Added the compile ifdef MVAX, for drawing real circles.
*
* Revision 2.2 86/09/22 13:11:00 13:11:00 fred ()
* Added calls to XrEditorGroup().
*
* Revision 2.1 86/09/19 07:10:26 07:10:26 fred ()
* Added a check for XrVISIBLE before doing any drawing.
*
* Revision 2.0 86/09/16 08:06:54 08:06:54 fred ()
* Updated input processing routine to use new SELECT strategy.
*
* Revision 1.4 86/09/16 05:47:14 05:47:14 fred ()
* Modified to swallow a select up event.
*
* Revision 1.3 86/09/10 07:26:23 07:26:23 fred ()
* Changed numRows to numCols in all data structures.
*
* Revision 1.2 86/09/09 13:08:09 13:08:09 fred ()
* changed some variables from INT32 to INT16
*
* Revision 1.1 86/09/04 06:43:06 06:43:06 fred ()
* Initial revision
*
*
*
*****************************************************************************
*************************************<+>*************************************/
#include <X/Xlib.h>
#include <Xr/defs.h>
#include <Xr/types.h>
#include <Xr/in_types.h>
extern INT32 createRButtons();
extern INT32 drawRButtons();
extern INT32 processRButtons();
extern INT32 rbFreeMemory();
extern INT32 calcRBComponents();
\f
/*************************************<->*************************************
*
* xrEditor *
* XrRadioButton (radioButton, message, data)
*
* xrEditor * radioButton;
* INT32 message;
* INT8 * data;
*
* Description:
* -----------
* This is the main entry point and message handler for the radio
* button field editor. It takes all message requests, and passes
* them onto the appropriate handler; invalid messages will fail
* and return an error.
*
*
* Inputs:
* ------
* radioButton = For all messages but MSG_NEW and MSG_SIZE, this
* contains the instance pointer.
*
* message = This indicates which action the editor should perform.
*
* data = This is the message specific data. It's usage depends upon
* the 'message' parameter, and may be a scalar or a pointer.
*
* Outputs:
* -------
* Upon successful completion of a command, the instance pointer
* is returned; additional information may be returned by means
* of the 'data' parameter.
*
* Upon failure, NULL is returned, and xrErrno is set.
*
* Procedures Called
* -----------------
* _MsgNew() [MsgCommon.c]
* _MsgFree() [MsgCommon.c]
* _MsgGetState() [MsgCommon.c]
* _MsgSetState() [MsgCommon.c]
* _MsgEdit() [MsgCommon.c]
* _MsgGetItemStates() [MsgItem.c]
* _MsgSetItemStates() [MsgItem.c]
* _MsgGetItemCount() [MsgItem.c]
* _MsgGetItemRects() [MsgItem.c]
* _MsgSize() [MsgItem.c]
* _MsgMove() [MsgItem.c]
* _XrMakeInvisible() [editorUtil.c]
* XrCopyRect() [calc.c]
* processRButtons()
* calcRBComponents()
* createRButtons()
* drawRButtons()
* rbFreeMemory()
*
*************************************<->***********************************/
xrEditor *
XrRadioButton (radioButton, message, data)
register xrEditor * radioButton;
INT32 message;
INT8 * data;
{
/* Determine the action being requested */
switch (message)
{
case MSG_NEW:
{
/*
* Create a new radio button instance.
* The only parameter of interest is the 'data'
* parameter, which is a pointer to a filled
* instance of the xrRadioButtonInfo structure.
*/
return ((xrEditor *)_MsgNew (radioButton, data,
sizeof(xrRadioButtonData),
createRButtons, drawRButtons,
rbFreeMemory, XrRadioButton,
XrALLBUTTONS));
}
case MSG_FREE:
{
/*
* Destroy the specified radio button editor instance.
* The 'radioButton' parameter specifies the instance to
* be destroyed; the 'data' parameter is unused.
*/
return ((xrEditor *) _MsgFree (radioButton, rbFreeMemory));
}
case MSG_GETSTATE:
{
/*
* Return the settings of the state flags for the
* specified radio button instance. The 'radioButton'
* parameter specifies the instance to be queried, while
* the 'data' parameter must point to an INT8 value, into
* which the state flags will be placed.
*/
return ((xrEditor *) _MsgGetState (radioButton, data));
}
case MSG_SETSTATE:
{
/*
* Change the state flag settings for the specified
* instance. The 'radioButton' parameter specifies the
* instance to be modified, and the 'data' parameter is
* interpreted as an INT8 value, containing the new state
* flag settings.
*/
return ((xrEditor *) _MsgSetState (radioButton, data,
drawRButtons, XrALLBUTTONS));
}
case MSG_GETITEMSTATES:
{
/*
* Return the state flags for the individual radio buttons.
* The 'radioButton' parameter specifies the instance to be
* queried, while the 'data' parameter must point to an array
* of INT8 values, into which the state flags will be returned.
*/
return ((xrEditor *)_MsgGetItemStates(radioButton, data));
}
case MSG_SETITEMSTATES:
{
/*
* Set the individual radio button states; redraw only those
* whose state has then changed. The 'radioButton' parameter
* specifies the instance to be modified, while the 'data'
* parameter points to an array of INT8 values, containing
* the new state flags.
*/
return ((xrEditor *) _MsgSetItemStates (radioButton, data,
drawRButtons));
}
case MSG_GETITEMCOUNT:
{
/*
* Return the number of radio buttons in the specified instance.
* The 'radioButton' parameter specifies the instance to be
* queried, while the 'data' parameter must point to an INT32
* value, into which the item count will be placed.
*/
return ((xrEditor *) _MsgGetItemCount (radioButton, data));
}
case MSG_GETITEMRECTS:
{
/*
* Fill the array passed in by the application, with the
* rectangle information describing each radio button in
* the specified instance. The 'radioButton' parameter
* indicates the instance to be queried, while the 'data'
* parameter must point to an array of RECTANGLE structures,
* into which the individual button rectangles will be placed.
*/
return ((xrEditor *) _MsgGetItemRects (radioButton, data));
}
case MSG_SIZE:
{
/*
* Return the size of the rectangle needed to enclose
* an instance of this editor, using the specifications
* passed in by the application program. The 'data'
* parameter must point to a partially filled out instance
* of the 'xrRadioButtonInfo' structure; upon completion,
* the 'editorRect' field of the 'info' structure will
* be filled.
*/
return ((xrEditor *) _MsgSize (data, calcRBComponents));
}
case MSG_MOVE:
{
/*
* Relocate an instance of radio buttons to a new location.
* The 'radioButton' parameter specifies the instance to be
* moved, while the 'data' parameter must point to a POINT
* structure, containing the new editor rectangle origin.
*/
return ((xrEditor *) _MsgMove (radioButton, data, drawRButtons));
}
case MSG_RESIZE:
{
/*
* Resize an existing instance of radio buttons.
* The 'radioButton' parameter indicates the instance
* to be resized, while the 'data' parameter must point
* to a RECTANGLE structure, containing the new editor
* rectangle definition.
*/
RECTANGLE workRect;
xrRadioButtonInfo rbInfo;
register xrRadioButtonData * rbDataPtr;
register xrRadioButtonInfo * rbInfoPtr;
if (radioButton == NULL)
{
xrErrno = XrINVALIDID;
return ((xrEditor *) NULL);
}
else if (data == NULL)
{
xrErrno = XrINVALIDPTR;
return ((xrEditor *) NULL);
}
/* Create a pseudo Info structure */
rbDataPtr = (xrRadioButtonData *) radioButton->editorData;
XrCopyRect (&radioButton->editorRect, &workRect);
rbInfoPtr = &rbInfo;
XrCopyRect ((RECTANGLE *) data, &rbInfoPtr->editorRect);
rbInfoPtr->editorFont = rbDataPtr->rbFont.fontInfo;
rbInfoPtr->numFields = rbDataPtr->rbNumFields;
rbInfoPtr->numCols = rbDataPtr->rbNumCols;
rbInfoPtr->labels = rbDataPtr->rbLabels;
/* Calculate the component positions */
if (createRButtons (rbDataPtr, rbInfoPtr, MSG_RESIZE) == FALSE)
return ((xrEditor *) NULL);
XrCopyRect (&rbInfoPtr->editorRect, &radioButton->editorRect);
if (radioButton->editorState & XrVISIBLE)
{
/* Remove the instance from the window */
_XrMakeInvisible (radioButton->editorWindowId, &workRect, TRUE);
/* Redisplay the instance */
drawRButtons (radioButton, XrALLBUTTONS);
}
/* Force the editor group rectangle to be recalculated */
XrEditorGroup (NULL, MSG_ADJUSTGROUPRECT, radioButton);
return (radioButton);
}
case MSG_REDRAW:
{
/*
* Redraw a radio button instance.
* The 'radioButton' parameter specifies the instance to redraw,
* while the 'data' parameter is interpreted as an INT32 value,
* specifying the type of redraw to perform.
*/
INT32 redrawMode = (INT32) data;
register xrRadioButtonData * rbDataPtr;
/* Validate the instance pointer and the redraw mode */
if (radioButton == NULL)
{
xrErrno = XrINVALIDID;
return ((xrEditor *) NULL);
}
else if (redrawMode == XrREDRAW_ALL)
{
rbDataPtr = (xrRadioButtonData *) radioButton->editorData;
/* Check for an invalid active button index */
if ((*rbDataPtr->rbActive < 0) ||
(*rbDataPtr->rbActive >= rbDataPtr->rbNumFields))
{
*rbDataPtr->rbActive = rbDataPtr->rblastActive;
xrErrno = XrPARMOUTOFRANGE;
return ((xrEditor *) NULL);
}
if (radioButton->editorState & XrVISIBLE)
drawRButtons (radioButton, XrALLBUTTONS);
rbDataPtr->rblastActive = *rbDataPtr->rbActive;
return (radioButton);
}
else if (redrawMode == XrREDRAW_ACTIVE)
{
rbDataPtr = (xrRadioButtonData *) radioButton->editorData;
/* Check for an invalid active button index */
if ((*rbDataPtr->rbActive < 0) ||
(*rbDataPtr->rbActive >= rbDataPtr->rbNumFields))
{
*rbDataPtr->rbActive = rbDataPtr->rblastActive;
xrErrno = XrPARMOUTOFRANGE;
return ((xrEditor *) NULL);
}
if (radioButton->editorState & XrVISIBLE)
{
if (rbDataPtr->rblastActive != *rbDataPtr->rbActive)
drawRButtons (radioButton, rbDataPtr->rblastActive);
drawRButtons (radioButton, *rbDataPtr->rbActive);
}
rbDataPtr->rblastActive = *rbDataPtr->rbActive;
return (radioButton);
}
else
{
xrErrno = XrINVALIDOPTION;
return ((xrEditor *) NULL);
}
}
case MSG_EDIT:
{
/*
* Process the incoming keystroke, and generate a return
* keystroke, to indicate to the application program
* how the editor instance was modified. The 'data'
* parameter must point to the event to be processed.
*/
return ((xrEditor *) _MsgEdit (radioButton, data,
processRButtons, XrRADIOBUTTON));
}
default:
/* All other commands are invalid */
xrErrno = XrINVALIDMSG;
return ((xrEditor *)NULL);
} /* end of switch */
} /* end of XrRadioButton() */
\f
/*************************************<->*************************************
*
* INT32
* rbFreeMemory (rbDataPtr)
*
* xrRadioButtonData * rbDataPtr;
*
* Description:
* -----------
* This routine is called both when an existing instance is freed,
* and when a MSG_NEW request fails after createRButtons() has
* been called. It will free up all resources which createRButtons()
* allocated for the instance.
*
*
* Inputs:
* ------
* rbDataPtr = This is a pointer to the instance's internal 'data'
* structure.
*
* Outputs:
* -------
*
* Procedures Called
* -----------------
* XFreePixmap() [libX.a]
*
*************************************<->***********************************/
static
INT32
rbFreeMemory (rbDataPtr)
xrRadioButtonData * rbDataPtr;
{
/*
* Free up the background tile, and the array holding the
* individual radio button information.
*/
if (rbDataPtr->rbTileId != xrDefaultTile)
XFreePixmap (rbDataPtr->rbTileId);
(*xrFree) (rbDataPtr->rbFields);
}
\f
/*************************************<->*************************************
*
* INT32
* calcRBComponents (rbInfoPtr, fields, cmd)
*
* xrRadioButtonInfo * rbInfoPtr;
* xrItemData * fields;
* INT32 cmd;
*
* Description:
* -----------
* If the 'cmd' parameter is set to MSG_SIZE, then this routine will
* calculate the size of the editor rectangle needed to contain the
* instance described by the structure pointed to by 'rbInfoPtr; the
* editor rectangle information is returned in the 'editorRect' field
* within the structure pointed to by the 'rbInfoPtr' parameter.
* If the 'cmd' parameter is set to any other value, then this
* routine will calculate the location and size of each radio button
* rectangle and corresponding button label; this information is then
* stored in the structure pointed to by the 'fields' parameter.
*
*
* Inputs:
* ------
* rbInfoPtr = This points to an instance of the radio button 'info'
* structure, which describes the instance being sized
* or created.
*
* fields = This must point to an array of structures, which will be
* used to store temporary information, if 'cmd' is set to
* MSG_SIZE, or will be used to store the component information,
* if 'cmd' is set to MSG_NEW.
*
* cmd = This indicates whether just the size of the editor rectangle
* needs to be calculated (MSG_SIZE), or whether the size and
* location of each component must be calculated (MSG_NEW).
*
* Outputs:
* -------
* Upon successful completion, TRUE is returned, along with some
* additional information in either the 'rbInfoPtr' structure,
* or the 'fields' structure.
*
* Upon failure, FALSE is returned, and xrErrno is set.
*
* Procedures Called
* -----------------
* _XrTextInfo() [textUtil.c]
* XrStringWidth() [utilities.c]
* XrCopyRect() [calc.c]
* XrSetRect() [calc.c]
* XrSetPt() [calc.c]
*
*************************************<->***********************************/
static
INT32
calcRBComponents (rbInfoPtr, fields, cmd)
register xrRadioButtonInfo * rbInfoPtr;
register xrItemData * fields;
INT32 cmd;
{
INT16 numFields = rbInfoPtr->numFields;
INT16 numCols = rbInfoPtr->numCols;
INT16 numRows;
RECTANGLE * rectPtr = &(rbInfoPtr->editorRect);
FontInfo * fontPtr;
xrTextInfo fontData;
register INT16 i, col;
INT16 hPadding, vPadding;
INT16 xPos, yPos;
INT16 itemWidth, maxItemWidth;
INT16 heightMin, widthMin;
INT16 lineHt;
/* Check for invalid dimensions */
if ((numFields < numCols) || (numFields <= 0) || (numCols <= 0))
{
xrErrno = XrINVALIDPARM;
return (FALSE);
}
/* Initialize variables we'll need for our calculations */
numRows = (numFields + numCols - 1) / numCols;
fontPtr = rbInfoPtr->editorFont ? rbInfoPtr->editorFont : xrBaseFontInfo;
_XrTextInfo (fontPtr, &fontData);
lineHt = fontData.ascent + fontData.descent;
rectPtr = &(rbInfoPtr->editorRect);
/*
* Determine the preliminary size of the instance. This is done by
* using the following formulae:
*
* height = number of Rows * height of a line
* width = Sum of longest item in each column
*
* An item in a column is composed of a radio button, some padding,
* and an optional label.
*/
heightMin = numRows * lineHt;
for (widthMin = 0, col = 0; col < numCols; col++)
{
/* Keep track of longest item in each column */
maxItemWidth = 0;
/* Calculate the width of each item in the column */
for (i = col; i < numFields; i += numCols)
{
/* Take into account the size of the radio button */
itemWidth = lineHt;
/* Include the label and padding, if a label is defined */
if ((rbInfoPtr->labels) && (rbInfoPtr->labels[i]))
itemWidth += fontData.avgWidth + XrStringWidth (fontData.fontInfo,
rbInfoPtr->labels[i], XrNULLTERMINATED, 0, 0);
/* See if this is the longest item encountered in the column */
if (itemWidth > maxItemWidth)
maxItemWidth = itemWidth;
}
/* Keep a running total of all the column width */
widthMin += maxItemWidth;
}
/*
* If this is being done in response to a MSG_SIZE request, then
* take the height and width values calculated above, and add some
* default padding values between each row and column; then return
* the rectangle definition. The following padding values are used:
*
* hPadding = 2 * font leading vPadding = font leading
*/
if (cmd == MSG_SIZE)
{
/* Add the default padding */
XrCopyRect (&xrZeroRect, rectPtr);
rectPtr->height = heightMin + (numRows - 1) * fontData.leading;
rectPtr->width = widthMin + (numCols - 1) * (fontData.leading << 1);
return (TRUE);
}
/* If the rectangle passed in by the application is larger than the
* preliminary rectangle calculated above, then use this extra space
* as padding between the row and column items.
*/
hPadding = (rectPtr->width - widthMin)/((numCols == 1) ? 1 : (numCols - 1));
vPadding = (rectPtr->height - heightMin)/((numRows == 1) ? 1:(numRows - 1));
/* Now, we can calculate the rectangle definition for each radio button */
for (xPos = rectPtr->x, col = 0; col < numCols; col++)
{
maxItemWidth = 0;
yPos = rectPtr->y;
for (i = col; i < numFields; i += numCols)
{
/* Keep track of the longest item in a column */
itemWidth = lineHt;
if ((rbInfoPtr->labels) && (rbInfoPtr->labels[i]))
itemWidth += fontData.avgWidth + XrStringWidth (fontData.fontInfo,
rbInfoPtr->labels[i], XrNULLTERMINATED, 0, 0);
if (itemWidth > maxItemWidth)
maxItemWidth = itemWidth;
/* Set the rectangle describing the complete radio button */
XrSetRect (&((fields+i)->subRectangle), xPos, yPos, itemWidth, lineHt);
/* Set the rectangle describing just the radio button; no label */
XrSetRect (&((fields+i)->rectangle), xPos, yPos, lineHt, lineHt);
/* Set the point describing where the label is displayed */
XrSetPt (&((fields+i)->labelPt), xPos + lineHt + fontData.avgWidth,
yPos);
/* Increment for the next radio button in the column */
yPos += lineHt + vPadding;
}
/* Increment for the start of the next column */
xPos += maxItemWidth + hPadding;
}
return (TRUE);
}
\f
/*************************************<->*************************************
*
* static
* INT32
* createRButtons (rbDataPtr, rbInfoPtr, message)
*
* xrRadioButtonData * rbDataPtr;
* xrRadioButtonInfo * rbInfoPtr;
* INT32 message;
*
* Description:
* -----------
* if (message == MSG_NEW):
* This routine is responsible for creating a new radio button instance.
* The description of the new instance is contained within the structure
* pointed to by the 'rbInfoPtr' parameter. Besides allocating the
* resources needed for the new instance, this procedure will also fill
* in the structure pointed to by the 'rbDataPtr' parameter with the
* state information for the new instance.
*
* if (message == MSG_RESIZE)
* This routine will take the information contained within the 'rbInfoPtr'
* structure, and will recalculate the location of each component within
* an existing instance of radio buttons, to match the new data. This
* will do no resource allocation.
*
*
* Inputs:
* ------
* rbDataPtr = Points to the 'data' structure for the instance being
* created or resized.
*
* rbInfoPtr = Points to the 'info' structure, which describes how the
* instance is to be laid out.
*
* message = This can be set to MSG_NEW or MSG_RESIZE.
*
* Outputs:
* -------
* Upon successful completion, TRUE is returned, and the 'rbDataPtr'
* structure is filled out.
*
* Upon failure, FALSE is returned, and xrErrno is set.
*
* Procedures Called
* -----------------
* XrResource() [resource.c]
* XrCopyRect() [calc.c]
* _XrTextInfo() [textUtil.c]
* XMakePixmap() [libX.a]
* XFreePixmap() [libX.a]
* calcRBComponents()
*
*************************************<->***********************************/
static
INT32
createRButtons (rbDataPtr, rbInfoPtr, message)
register xrRadioButtonData * rbDataPtr;
register xrRadioButtonInfo * rbInfoPtr;
int message;
{
FontInfo * fontPtr;
register xrItemData * aButton;
register INT16 i;
xrResourceInfo bitmapInfo;
RECTANGLE minRect;
RECTANGLE editorRect;
xrItemData * tempItems;
/* Allocate space to hold our rectangle size calculations */
if ((tempItems = (xrItemData *) (*xrMalloc)
(sizeof (xrItemData) * rbInfoPtr->numFields)) == NULL)
{
/* Unable to allocate the memory we need */
xrErrno = XrOUTOFMEM;
return (FALSE);
}
if (message == MSG_NEW)
{
/* Validate incoming parameters */
if (rbInfoPtr->value == NULL)
{
(*xrFree)(tempItems);
xrErrno = XrINVALIDPTR;
return (FALSE);
}
else if ((*rbInfoPtr->value < 0) ||
(*rbInfoPtr->value >= rbInfoPtr->numFields))
{
(*xrFree)(tempItems);
xrErrno = XrPARMOUTOFRANGE;
return (FALSE);
}
/* Allocate space to hold the individual radio button information */
if ((rbDataPtr->rbFields = (xrItemData *) (*xrMalloc)
(sizeof (xrItemData) * rbInfoPtr->numFields)) == NULL)
{
/* Unable to allocate the memory we need */
(*xrFree)(tempItems);
xrErrno = XrOUTOFMEM;
return (FALSE);
}
rbDataPtr->rbFGColor = (rbInfoPtr->editorFGColor == -1) ?
xrForegroundColor : rbInfoPtr->editorFGColor;
rbDataPtr->rbBGColor = (rbInfoPtr->editorBGColor == -1) ?
xrBackgroundColor : rbInfoPtr->editorBGColor;
/* Create the 50% tile we will need when drawing insensitive box */
if ((rbInfoPtr->editorFGColor == -1) &&
(rbInfoPtr->editorBGColor == -1))
{
/* Use the default 50% tile */
rbDataPtr->rbTileId = xrDefaultTile;
}
else
{
bitmapInfo.resourceType = XrTYPE_BITMAPID;
bitmapInfo.resourceId = XrPERCENT50;
if ((XrResource (MSG_FIND, &bitmapInfo) == FALSE) ||
((rbDataPtr->rbTileId =
XMakePixmap (((xrBitmapId *)bitmapInfo.resourceObject)->bitmapId,
rbDataPtr->rbFGColor, rbDataPtr->rbBGColor)) == 0))
{
/* Unable to create the tile */
(*xrFree)(tempItems);
(*xrFree) (rbDataPtr->rbFields);
xrErrno = XrXCALLFAILED;
return (FALSE);
}
}
}
/* Check the rectangle definition */
XrCopyRect (&rbInfoPtr->editorRect, &editorRect);
if (calcRBComponents (rbInfoPtr, tempItems, MSG_SIZE) == FALSE)
{
/* The application supplied invalid information */
/* xrErrno is set by calcRBComponents */
XrCopyRect (&editorRect, &rbInfoPtr->editorRect);
(*xrFree) (tempItems);
if (message == MSG_NEW)
{
if (rbDataPtr->rbTileId != xrDefaultTile)
XFreePixmap (rbDataPtr->rbTileId);
(*xrFree) (rbDataPtr->rbFields);
}
return (FALSE);
}
(*xrFree)(tempItems);
XrCopyRect (&rbInfoPtr->editorRect, &minRect);
XrCopyRect (&editorRect, &rbInfoPtr->editorRect);
if ((editorRect.height < minRect.height) ||
(editorRect.width < minRect.width))
{
/* The application supplied an invalid rectangle */
xrErrno = XrINVALIDRECT;
if (message == MSG_NEW)
{
if (rbDataPtr->rbTileId != xrDefaultTile)
XFreePixmap (rbDataPtr->rbTileId);
(*xrFree) (rbDataPtr->rbFields);
}
return (FALSE);
}
/* Generate the location and size information associated with each button */
calcRBComponents (rbInfoPtr, rbDataPtr->rbFields, MSG_NEW);
if (message == MSG_NEW)
{
/* Fill in the rest of the fields in the radio button structures */
rbDataPtr->rbNumFields = rbInfoPtr->numFields;
rbDataPtr->rbNumCols = rbInfoPtr->numCols;
fontPtr = rbInfoPtr->editorFont ? rbInfoPtr->editorFont : xrBaseFontInfo;
_XrTextInfo (fontPtr, &rbDataPtr->rbFont);
rbDataPtr->rbLabels = rbInfoPtr->labels;
rbDataPtr->rbActive = rbInfoPtr->value;
rbDataPtr->rblastActive = *(rbInfoPtr->value);
rbDataPtr->rbStates = rbInfoPtr->stateFlags;
aButton = rbDataPtr->rbFields;
for (i = 0; i < rbDataPtr->rbNumFields; i++, aButton++)
{
/* Copy over each radio button label */
if (rbInfoPtr->labels)
aButton->label = rbInfoPtr->labels[i];
else
aButton->label = NULL;
/* Copy the state flags */
if (rbInfoPtr->stateFlags)
aButton->state = rbInfoPtr->stateFlags[i];
else
aButton->state = (XrVISIBLE | XrSENSITIVE);
}
}
return (TRUE);
}
\f
/*************************************<->*************************************
*
* static
* INT32
* drawRButtons (radioButton, buttonNum)
*
* xrEditor * radioButton;
* INT32 buttonNum;
*
* Description:
* -----------
* This routine will display either a single radio button, or else
* all of the radio buttons, depending upon the value specified in
* the 'buttonNum' parameter.
*
*
* Inputs:
* ------
* radioButton = Points to the editor instance structure.
*
* buttonNum = This can be set to the index of the button to be drawn,
* or to the define XrALLBUTTONS, if all the buttons should
* be redrawn.
*
* Outputs:
* -------
*
* Procedures Called
* -----------------
* _XrMakeInvisible() [editorUtil.c]
* _XrInitEditorGCs() [gcUtil.c]
* _XrCopyGC() [gcUtil.c]
* _XrChangeGC() [gcUtil.c]
* XrCopyRect() [calc.c]
* _XrFillEllipse() [ellipUtil.c]
* _XrEllipse() [ellipUtil.c]
* _XrImageText8() [textUtil.c]
*
*************************************<->***********************************/
static
INT32
drawRButtons (radioButton, buttonNum)
xrEditor * radioButton;
INT32 buttonNum;
{
register xrRadioButtonData * rbDataPtr;
Window windowId;
INT32 sensitive;
register INT16 firstButton, lastButton;
register xrItemData * aButton;
RECTANGLE workRect;
register RECTANGLE * workRectPtr;
INT32 changeList[21];
INT8 makeGCFlag;
/* Initialize variables */
rbDataPtr = (xrRadioButtonData *) radioButton->editorData;
windowId = radioButton->editorWindowId;
workRectPtr = &workRect;
makeGCFlag = TRUE;
/* Check for an invalid active button index */
if ((*rbDataPtr->rbActive < 0) ||
(*rbDataPtr->rbActive >= rbDataPtr->rbNumFields))
{
*rbDataPtr->rbActive = rbDataPtr->rblastActive;
}
else
rbDataPtr->rblastActive = *rbDataPtr->rbActive;
/*
* If the instance is not visible, then fill its area with the
* background tile for the window, thus making the instance invisible.
*/
if (!(radioButton->editorState & XrVISIBLE))
{
_XrMakeInvisible (windowId, &radioButton->editorRect, TRUE);
return;
}
/* Initialize the standard graphic contexts we will be using */
_XrInitEditorGCs (rbDataPtr->rbFGColor, rbDataPtr->rbBGColor,
rbDataPtr->rbFont.fontInfo->id);
/* Initialize the graphics context used to draw insensitive radio buttons */
_XrCopyGC (xrDefaultGC, xrEditorGC3);
changeList[XrTILEVAL] = rbDataPtr->rbTileId;
changeList[XrFILLSTYLEVAL] = Tiled;
_XrChangeGC (xrEditorGC3, (XrTILE | XrFILLSTYLE), changeList);
sensitive = (radioButton->editorState & XrSENSITIVE) ? TRUE : FALSE;
/* Determine the range of radio buttons to be drawn */
if (buttonNum == XrALLBUTTONS)
{
firstButton = 0;
lastButton = rbDataPtr->rbNumFields - 1;
}
else
firstButton = lastButton = buttonNum;
while (firstButton <= lastButton)
{
aButton = (rbDataPtr->rbFields) + firstButton;
XrCopyRect (&(aButton->rectangle), workRectPtr);
/* Determine how to draw the button, depending upon it's state */
if (aButton->state & XrVISIBLE)
{
if (sensitive && (aButton->state & XrSENSITIVE))
{
/* Determine if the button is active or inactive */
if (firstButton == *(rbDataPtr->rbActive))
{
/*
* The state of the radio button is 'ACTIVE', so draw
* it as a filled circle, using the foreground color.
*/
draw1Button (windowId, xrEditorGC1, xrEditorGC1, workRectPtr);
}
else
{
/*
* The state of the radio button is 'INACTIVE', so draw
* draw the circle with the border in the foreground
* color, and the interior in the background color.
*/
draw1Button (windowId, xrEditorGC2, xrEditorGC1, workRectPtr);
}
}
else
{
/*
* The radio button is insensitive, so we will draw it as a
* filled circle, using the 50% tile.
*/
draw1Button (windowId, xrEditorGC3, xrEditorGC1, workRectPtr);
}
/* If the radio button has a label, then we will draw that now. */
if ((aButton->label) && (strlen(aButton->label) > 0))
_XrImageText8 (windowId, xrEditorGC1, strlen(aButton->label),
aButton->labelPt.x, aButton->labelPt.y,
aButton->label);
}
else
{
/*
* The radio button is not visible, so fill the area it would occupy
* with the window's background color.
*/
_XrMakeInvisible (windowId, &(aButton->subRectangle), makeGCFlag);
makeGCFlag = FALSE;
}
/* Go on and process the next radio button */
firstButton++;
}
}
\f
/*************************************<->*************************************
*
* static
* INT32
* processRButtons (radioButton, input, returnEvent)
*
* xrEditor * radioButton;
* XButtonEvent * input;
* xrEvent * returnEvent;
*
* Description:
* -----------
* This is the event processing routine for the radio button editor.
* It takes an event, and determines which, if any, of the radio
* buttons the event occurred within. If a radio button was selected,
* then it will be redrawn as active, and its index will be returned
* to the application.
*
*
* Inputs:
* ------
* radioButton = This is the instance pointer for the instance in which
* the event occurred.
*
* input = This points to the event to be processed.
*
* returnEvent = This points to a partially filled out X-ray event
* structure. It can be used by this routine when it
* needs to push a return event on the input queue.
* Every field is already filled, except for the 'value'
* fields.
*
* Outputs:
* -------
* Although a value is not directly returned, an input event will be
* pushed onto the input queue, telling the application which
* part of the instance was selected.
*
* Procedures Called
* -----------------
* XrSetPt() [calc.c]
* XrPtInRect() [calc.c]
* drawRButtons()
*
*************************************<->***********************************/
static
INT32
processRButtons (radioButton, input, returnEvent)
xrEditor * radioButton;
XButtonEvent * input;
xrEvent * returnEvent;
{
register xrRadioButtonData * rbDataPtr;
POINT spritePt;
register INT16 i;
register xrItemData * aButton;
rbDataPtr = (xrRadioButtonData *) radioButton->editorData;
XrSetPt (&spritePt, input->x, input->y);
returnEvent->value1 = NULL;
/* Check each radio button to see if one was selected */
for (i = 0; i < rbDataPtr->rbNumFields; i++)
{
aButton = (rbDataPtr->rbFields) + i;
if (XrPtInRect (&spritePt, &(aButton->rectangle)) &&
((aButton->state & (XrVISIBLE | XrSENSITIVE)) ==
(XrVISIBLE | XrSENSITIVE)))
{
/* A radio button was selected; modify its value and redraw it */
*rbDataPtr->rbActive = i;
returnEvent->value3 = rbDataPtr->rblastActive;
if (i != rbDataPtr->rblastActive)
drawRButtons (radioButton, rbDataPtr->rblastActive);
drawRButtons (radioButton, i);
/* Save the index of the radio button which changed, and return */
returnEvent->value2 = i;
returnEvent->value1 = XrSELECT;
}
}
}
\f
/*************************************<->*************************************
*
* draw1Button (windowId, fillGC, borderGC, rectPtr)
*
* Window windowId;
* INT32 fillGC;
* INT32 borderGC;
* RECTANGLE * rectPtr;
*
* Description:
* -----------
* This routines draws and fills a single radio button. The button
* is drawn as a 12 sided polygon.
*
*
* Inputs:
* ------
* windowId = Id of window in which button is to be drawn.
*
* fillGC = Graphic context to use to fill the interior of the button.
*
* borderGC = Graphic context to use to draw the button border.
*
* rectPtr = Describes the square in which the button will be drawn.
*
* Outputs:
* -------
*
* Procedures Called
* -----------------
* _XrPoly() [polyUtil.c]
* _XrFillPoly() [polyUtil.c]
*
*************************************<->***********************************/
static
INT32
draw1Button (windowId, fillGC, borderGC, rect)
Window windowId;
INT32 fillGC;
INT32 borderGC;
RECTANGLE * rect;
{
INT16 rightEdge, bottom;
INT16 oneEighthH, threeEighthsH;
INT16 oneEighthW, threeEighthsW;
INT16 halfHeight, halfWidth;
INT32 i;
RECTANGLE workRect;
/*
* Calculate our working values.
* Force the rectangle to an odd height and width.
*/
XrCopyRect (rect, &workRect);
if ((workRect.height & 0x01) == 0)
workRect.height --;
if ((workRect.width & 0x01) == 0)
workRect.width --;
rightEdge = workRect.x + workRect.width - 1;
bottom = workRect.y + workRect.height - 1;
oneEighthH = workRect.height >> 3;
oneEighthW = workRect.width >> 3;
threeEighthsH = (workRect.height * 3) >> 3;
threeEighthsW = (workRect.width * 3) >> 3;
halfWidth = workRect.x + (workRect.width >> 1);
halfHeight = workRect.y + (workRect.height >> 1);
/* Fill in the 'flags' field of the polygon structure */
for (i = 0; i < 13; i++)
xr_PolyList[i].flags = 0;
/* Calculate the polygon endpoints */
xr_PolyList[0].x = halfWidth - oneEighthW;
xr_PolyList[0].y = workRect.y;
xr_PolyList[1].x = halfWidth + oneEighthW;
xr_PolyList[1].y = workRect.y;
xr_PolyList[2].x = halfWidth + threeEighthsW;
xr_PolyList[2].y = halfHeight - threeEighthsH;
xr_PolyList[3].x = rightEdge;
xr_PolyList[3].y = halfHeight - oneEighthH;
xr_PolyList[4].x = rightEdge;
xr_PolyList[4].y = halfHeight + oneEighthH;
xr_PolyList[5].x = halfWidth + threeEighthsW;
xr_PolyList[5].y = halfHeight + threeEighthsH;
xr_PolyList[6].x = halfWidth + oneEighthW;
xr_PolyList[6].y = bottom;
xr_PolyList[7].x = halfWidth - oneEighthW;
xr_PolyList[7].y = bottom;
xr_PolyList[8].x = halfWidth - threeEighthsW;
xr_PolyList[8].y = halfHeight + threeEighthsH;
xr_PolyList[9].x = workRect.x;
xr_PolyList[9].y = halfHeight + oneEighthH;
xr_PolyList[10].x = workRect.x;
xr_PolyList[10].y = halfHeight - oneEighthH;
xr_PolyList[11].x = halfWidth - threeEighthsW;
xr_PolyList[11].y = halfHeight - threeEighthsH;
xr_PolyList[12].x = halfWidth - oneEighthW;
xr_PolyList[12].y = workRect.y;
/* Draw the button */
_XrFillPoly (windowId, fillGC, 13, xr_PolyList);
_XrPoly (windowId, borderGC, 13, xr_PolyList);
}