|
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 - 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); }