|
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: ┃ S T ┃
Length: 73127 (0x11da7) Types: TextFile Names: »ScrollBar.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/ScrollBar.c«
/* * $Source: /u1/Xr/src/Xrlib/Editor/RCS/ScrollBar.c,v $ * $Header: ScrollBar.c,v 1.1 86/12/17 09:04:54 swick Exp $ */ #ifndef lint static char *rcsid_ScrollBar_c = "$Header: ScrollBar.c,v 1.1 86/12/17 09:04:54 swick Exp $"; #endif lint #include <Xr/xr-copyright.h> /* $Header: ScrollBar.c,v 1.1 86/12/17 09:04:54 swick Exp $ */ /* Copyright 1986, Hewlett-Packard Company */ /* Copyright 1986, Massachussetts Institute of Technology */ static char rcsid[] = "$Header: ScrollBar.c,v 1.1 86/12/17 09:04:54 swick Exp $"; /*************************************<+>************************************* ***************************************************************************** ** ** File: ScrollBar.c ** ** Project: X-ray Toolbox ** ** Description: ** Source code for the X-ray ScrollBar field editor. ** ** ** ------------------------ MODIFICATION RECORD ------------------------ * * $Log: ScrollBar.c,v $ * Revision 1.1 86/12/17 09:04:54 swick * Initial revision * * Revision 7.0 86/11/13 08:27:23 08:27:23 fred () * Final QA Release * * Revision 6.1 86/11/11 15:22:20 15:22:20 fred () * Fixed a NULL pointer bug in MSG_GETPARAMETERS. * * Revision 6.0 86/11/10 15:35:39 15:35:39 fred () * QA #2 release * * Revision 5.3 86/11/07 14:22:54 14:22:54 fred () * Added new copyright message. * * Revision 5.2 86/11/04 09:01:48 09:01:48 fred () * Fixed a bug dealing with the generation of a fake select up event. * The detail bits were being masked off. * * Revision 5.1 86/10/30 13:28:49 13:28:49 fred () * Added code to initialize the 'flags' field of the xr_PolyList structure. * * Revision 5.0 86/10/28 08:33:54 08:33:54 fred () * QA #1.1 release * * Revision 4.2 86/10/23 09:09:00 09:09:00 fred () * Removed unused variables. * * Revision 4.1 86/10/22 14:51:40 14:51:40 fred () * Filled in the procedure headers. * * Revision 4.0 86/10/20 12:13:30 12:13:30 fred () * QA #1 release * * Revision 3.5 86/10/20 11:10:11 11:10:11 fred () * Fixed an interactive slide bug, which occurred when the slide box * was the same size as the slide region. * * Revision 3.4 86/10/16 09:17:27 09:17:27 fred () * Performance enhanced: added use of register variables. * * Revision 3.3 86/10/13 13:46:53 13:46:53 fred () * Removed MSG_SLIDETOP message, because it could not work * 100% of the time, with the way scrollbars are implemented. * * Revision 3.2 86/10/13 10:06:37 10:06:37 fred () * Added use of the default tile, if needed. * * Revision 3.1 86/10/09 07:54:41 07:54:41 fred () * Added default color check to create routine. * * Revision 3.0 86/10/02 16:01:25 16:01:25 fred () * Alpha release set to 3.0 * * Revision 2.5 86/10/02 09:45:58 09:45:58 fred () * Added MSG_SLIDETOP. * * Revision 2.4 86/09/29 14:23:40 14:23:40 fred () * Fixed an 'off by 1' error in CalculateSlideBox(), where the * slide box was divided by 'unitWid' instead of (unitWid + 1). * Caused the slide box to be too large. * * Revision 2.3 86/09/24 11:15:30 11:15:30 fred () * No longer swallow select up events when one of the * scroll arrows are selected; this allows an application * to do continuous scrolling, if it wants. * * Revision 2.2 86/09/22 13:11:55 13:11:55 fred () * Added calls to XrEditorGroup(). * * Revision 2.1 86/09/19 07:12:37 07:12:37 fred () * Added a check for XrVISIBLE before doing any drawing. * * Revision 2.0 86/09/16 08:10:03 08:10:03 fred () * Updated all input processing routines to use new SELECT strategy. * * Revision 1.4 86/09/16 05:49:58 05:49:58 fred () * Modified to swallow a select up event. * * Revision 1.3 86/09/04 11:51:59 11:51:59 fred () * In invalidSBParameters(), the granularity value was being * checked, even though the interactive slide feature was disabled. * * Revision 1.2 86/09/04 09:45:38 09:45:38 fred () * In processScrollBar(), changed the size of the local variable * value1 from INT16 to INT8, to match the xrEvent structure. * * Revision 1.1 86/09/03 13:57:43 13:57:43 fred () * Initial revision * * ***************************************************************************** *************************************<+>*************************************/ #include <X/Xlib.h> #include <Xr/defs.h> #include <Xr/types.h> #include <Xr/in_types.h> extern INT32 drawScrollBar(); extern INT32 createScrollBar(); extern INT32 processScrollBar(); extern INT32 sbFreeMemory(); /* The default values for the scrollbar configuration parameters */ static xrSBParameters dft_configuration = { XrSCROLLARROWS | XrSLIDEBOX, 0, 100, 0, 10, NULL, 10 }; \f /*************************************<->************************************* * * xrEditor * * XrScrollBar (scrollBar, message, data) * * xrEditor * scrollBar; * INT32 message; * INT8 * data; * * Description: * ----------- * This is the main entry point and message handler for the scrollbar * field editor. It takes all message requests, and passes them onto * the appropriate handler; invalid messages will fail and return an * error. * * * Inputs: * ------ * scrollBar = 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] * _MsgRedraw() [MsgCommon.c] * _MsgEdit() [MsgCommon.c] * XrCopyRect() [calc.c] * XrOffsetRect() [calc.c] * _XrMakeInvisible() [editorUtil.c] * XrEditorGroup() [group.c] * sizeScrollBar() * drawScrollBar() * createScrollBar() * sbFreeMemory() * invalidSBParameters() * *************************************<->***********************************/ xrEditor * XrScrollBar (scrollBar, message, data) register xrEditor * scrollBar; INT32 message; INT8 * data; { /* Determine the action being requested */ switch (message) { case MSG_NEW: { /* * Create a new scrollbar instance. * The only parameter of interest is the 'data' parameter, * which is a pointer to a filled instance of the * xrScrollBarInfo structure. */ return ((xrEditor *) _MsgNew (scrollBar, data, sizeof(xrScrollBarData), createScrollBar, drawScrollBar, sbFreeMemory, XrScrollBar, NULL)); } case MSG_FREE: { /* * Destroy the specified scrollbar editor instance. * The 'scrollBar' parameter specifies the instance to * be destroyed; the 'data' parameter is unused. */ return ((xrEditor *) _MsgFree (scrollBar, sbFreeMemory)); } case MSG_GETSTATE: { /* * Return the settings of the state flags for the * specified scrollbar instance. The 'scrollBar' 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 (scrollBar, data)); } case MSG_SETSTATE: { /* * Change the state flag settings for the specified * instance. The 'scrollBar' parameter specifies the * instance to be modified, and the 'data' parameter is * interpreted as an INT8 value, containing the new state * flag settings. */ register INT8 oldState; register INT8 newState; if (scrollBar == NULL) { xrErrno = XrINVALIDID; return ((xrEditor *)NULL); } oldState = scrollBar->editorState; newState = (INT8) data; scrollBar->editorState = (INT8) data; /* Redraw the editor, using the new state */ if (((oldState & XrVISIBLE) != (newState & XrVISIBLE)) || ((newState & XrVISIBLE) && ((oldState & XrSENSITIVE) != (newState & XrSENSITIVE)))) { drawScrollBar (scrollBar, NULL); } return (scrollBar); } 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 'xrScrollBarInfo' structure; upon completion, * the 'editorRect' field of the 'info' structure will be * filled. */ xrScrollBarInfo *sbInfoPtr; sbInfoPtr = (xrScrollBarInfo *)data; if (sbInfoPtr == NULL) { xrErrno = XrINVALIDPTR; return ((xrEditor *)NULL); } else if (sizeScrollBar (sbInfoPtr, &sbInfoPtr->editorRect) == FALSE) { /* Size request failed; xrErrno set by sizeScrollBar() */ return ((xrEditor *)NULL); } return ((xrEditor *) TRUE); } case MSG_REDRAW: { /* * Redraw a scrollbar instance. * The 'scrollBar' parameter specifies the instance to redraw, * while the 'data' parameter is interpreted as an INT32 value, * specifying the type of redraw to perform. */ return ((xrEditor *) _MsgRedraw (scrollBar, data, drawScrollBar, NULL)); } case MSG_MOVE: { /* * Relocate a scrollbar instance to a new location. * The 'scrollBar' parameter specifies the instance to * be moved, while the 'data' parameter must point to a * POINT structure, containing the new editor rectangle * origin. */ POINT * ptPtr = (POINT *) data; register xrScrollBarData * sbDataPtr; RECTANGLE workRect; register INT16 xDelta; register INT16 yDelta; register INT32 i; if (scrollBar == NULL) { xrErrno = XrINVALIDID; return ((xrEditor *) NULL); } else if (data == NULL) { xrErrno = XrINVALIDPTR; return ((xrEditor *) NULL); } /* Determine how much to move each of the scrollbar components */ sbDataPtr = (xrScrollBarData *) scrollBar->editorData; XrCopyRect (&scrollBar->editorRect, &workRect); xDelta = ptPtr->x - scrollBar->editorRect.x; yDelta = ptPtr->y - scrollBar->editorRect.y; /* Move the origin of each of the scrollbar components */ XrOffsetRect (&scrollBar->editorRect, xDelta, yDelta); XrOffsetRect (&sbDataPtr->arrow1, xDelta, yDelta); XrOffsetRect (&sbDataPtr->arrow2, xDelta, yDelta); XrOffsetRect (&sbDataPtr->slideArea, xDelta, yDelta); XrOffsetRect (&sbDataPtr->slideBox, xDelta, yDelta); /* Translate the scroll arrow vector lists */ for (i = 0; i < 9; i++) { sbDataPtr->arrow1_vl[i].x += xDelta; sbDataPtr->arrow1_vl[i].y += yDelta; sbDataPtr->arrow2_vl[i].x += xDelta; sbDataPtr->arrow2_vl[i].y += yDelta; } if (scrollBar->editorState & XrVISIBLE) { /* Remove the instance from the window */ _XrMakeInvisible (scrollBar->editorWindowId, &workRect, TRUE); /* Redisplay the instance */ drawScrollBar (scrollBar, NULL); } /* Force the editor group rectangle to be recalculated */ XrEditorGroup (NULL, MSG_ADJUSTGROUPRECT, scrollBar); return (scrollBar); } case MSG_RESIZE: { /* * Resize an existing scrollbar instance. * The 'scrollBar' parameter indicates the instance to * be resized, while the 'data' parameter must point to a * RECTANGLE structure, containing the new editor rectangle * definition. */ register xrScrollBarData * sbDataPtr; xrScrollBarInfo sbInfo; RECTANGLE workRect; if (scrollBar == NULL) { xrErrno = XrINVALIDID; return ((xrEditor *) NULL); } else if (data == NULL) { xrErrno = XrINVALIDPTR; return ((xrEditor *) NULL); } /* Create a pseudo Info structure */ sbDataPtr = (xrScrollBarData *) scrollBar->editorData; XrCopyRect (&scrollBar->editorRect, &workRect); XrCopyRect ((RECTANGLE *) data, &sbInfo.editorRect); sbInfo.orientation = sbDataPtr->orientation; _Xrmemcpy (&(sbInfo.configuration), &(sbDataPtr->configuration), sizeof (xrSBParameters)); if (createScrollBar (sbDataPtr, &sbInfo, MSG_RESIZE) == FALSE) /* xrErrno is set by createScrollBar() */ return ((xrEditor *) NULL); /* Save the new rectangle definition */ XrCopyRect (&sbInfo.editorRect, &scrollBar->editorRect); if (scrollBar->editorState & XrVISIBLE) { /* Remove the instance from the window */ _XrMakeInvisible (scrollBar->editorWindowId, &workRect, TRUE); /* Redisplay the instance */ drawScrollBar (scrollBar, NULL); } /* Force the editor group rectangle to be recalculated */ XrEditorGroup (NULL, MSG_ADJUSTGROUPRECT, scrollBar); return (scrollBar); } case MSG_GETPARAMETERS: { /* * Return a copy of the current configuration parameters * associated with the specified scrollbar instance, * or the default setting, if the instance parameter is NULL. * The 'data' parameter must point to an instance of the * xrSBParameters structure, into which the configuration * data will be placed. */ xrScrollBarData * sbDataPtr; if (data == NULL) { xrErrno = XrINVALIDPTR; return ((xrEditor *) NULL); } if (scrollBar) { sbDataPtr = (xrScrollBarData *)scrollBar->editorData; _Xrmemcpy(data, &sbDataPtr->configuration, sizeof (xrSBParameters)); } else _Xrmemcpy(data, &dft_configuration, sizeof (xrSBParameters)); return (scrollBar); } case MSG_SETPARAMETERS: { /* * Save a copy of the new configuration parameters, and redraw * any affected regions of the scrollbar. The 'scrollBar' * parameter specifies the instance to be modified, while the * 'data' parameter must point to an instance of the xrSBParameters * structure, which must contain the new configuration values. */ xrSBParameters * sbParmPtr; xrScrollBarData * sbDataPtr; if (scrollBar == NULL) { xrErrno = XrINVALIDID; return ((xrEditor *) NULL); } else if (data == NULL) { xrErrno = XrINVALIDPTR; return ((xrEditor *) NULL); } /* Grab copies of the parameters we will be validating */ sbParmPtr = (xrSBParameters *) data; sbDataPtr = (xrScrollBarData *) scrollBar->editorData; if (invalidSBParameters (sbDataPtr, sbParmPtr)) /* xrErrno set by invalidSBParameters() */ return ((xrEditor *) NULL); /* Redraw only the affected components */ updateComponents (scrollBar, sbDataPtr); return (scrollBar); } 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 (scrollBar, data, processScrollBar, XrSCROLLBAR)); } default: /* All other commands are invalid */ xrErrno = XrINVALIDMSG; return ((xrEditor *)NULL); } /* end of switch */ } /* end of XrScrollBar() */ \f /*************************************<->************************************* * * INT32 * sbFreeMemory (sbDataPtr) * * xrScrollBarData * sbDataPtr; * * Description: * ----------- * This routine is called both when an existing instance is freed, * and when a MSG_NEW request fails after createScrollBar() has * been called. It will free up all resources which createScrollBar() * allocated for the instance. * * * Inputs: * ------ * sbDataPtr = Points to the instance's internal 'data' structure. * * Outputs: * ------- * * Procedures Called * ----------------- * XFreePixmap() [libX.a] * *************************************<->***********************************/ static INT32 sbFreeMemory (sbDataPtr) xrScrollBarData * sbDataPtr; { if (sbDataPtr->sbTileId != xrDefaultTile) XFreePixmap (sbDataPtr->sbTileId); } \f /*************************************<->************************************* * * INT32 * sizeScrollBar (sbInfoPtr, rectPtr) * * xrScrollBarInfo * sbInfoPtr; * RECTANGLE * rectPtr; * * Description: * ----------- * This routine will validate the needed parameters contained within * the 'info' structure pointed to by 'sbInfoPtr', and will then * calculate the size of the editor rectangle needed to contain the * described instance. * * * Inputs: * ------ * sbInfoPtr = Points to an instance of the 'xrScrollBarInfo' structure, * which describes the instance to be sized. * * rectPtr = Points to a RECTANGLE structure, into which the editor * rectangle definition will be placed. * * Outputs: * ------- * Upon successful completion, TRUE is returned, and the editor * rectangle is returned. * * Upon failure, FALSE is returned, and xrErrno is set. * * Procedures Called * ----------------- * *************************************<->***********************************/ static INT32 sizeScrollBar (sbInfoPtr, rectPtr) register xrScrollBarInfo * sbInfoPtr; register RECTANGLE * rectPtr; { register INT16 bar_wid, arrow_ht, slide_ht; INT16 slide_wid; switch (sbInfoPtr->orientation) { case XrHORIZONTAL: { /* Verify that a valid height was supplied */ if (rectPtr->height < XrMIN_SCROLLBAR_HT) { xrErrno = XrINVALIDPARM; return (FALSE); } /* Calculate the size of the components for the scrollbar */ bar_wid = rectPtr->height; break; } case XrVERTICAL: { /* Verify that a valid width was supplied */ if (rectPtr->width < XrMIN_SCROLLBAR_WID) { xrErrno = XrINVALIDPARM; return (FALSE); } /* Calculate the size of the components for the scrollbar */ bar_wid = rectPtr->width; break; } default: { /* Invalid scrollbar orientation value specified */ xrErrno = XrINVALIDOPTION; return (FALSE); } } arrow_ht = bar_wid + 1; slide_wid = bar_wid - 4; slide_ht = slide_wid; /* Fill in the coordinates for the editor rectangle */ rectPtr->x = 0; rectPtr->y = 0; if (sbInfoPtr->orientation == XrHORIZONTAL) { rectPtr->width = arrow_ht + 1 + slide_ht + 1 + arrow_ht; rectPtr->height = bar_wid; } else { rectPtr->width = bar_wid; rectPtr->height = arrow_ht + 1 + slide_ht + 1 + arrow_ht; } return (TRUE); } \f /*************************************<->************************************* * * INT32 * createScrollBar (sbDataPtr, sbInfoPtr, message) * * xrScrollBarData * sbDataPtr; * xrScrollBarInfo * sbInfoPtr; * INT32 message; * * Description: * ----------- * if (message == MSG_NEW) * This routine is responsible for creating a new scrollbar instance. * The description of the new instance is contained within the structure * pointed to by the 'sbInfoPtr' parameter. Besides allocating the * resources needed for the new instance, this procedure will also fill * in the structure pointed to by the 'sbDataPtr' parameter with the * state information for the new instance. * * if (message == MSG_RESIZE) * This routine will take the information contained within the * 'sbInfoPtr' structure, and will recalculate the location of each * component within an existing scrollbar instance, to match the new * data. This will do no resource allocation. * * * Inputs: * ------ * sbDataPtr = Points to the 'data' structure for the instance being * created or resized. * * sbInfoPtr = 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 'sbDataPtr' * structure is filled out. * * Upon failure, FALSE is returned, and xrErrno is set. * * Procedures Called * ----------------- * XrCopyRect() [calc.c] * XrResource() [resource.c] * XMakePixmap() [libX.a] * CalculateSlideBox() * MakeHorzArrows() * MkaeVertArrows() * sizeScrollBar() * invalidSBParameters() * *************************************<->***********************************/ static INT32 createScrollBar (sbDataPtr, sbInfoPtr, message) register xrScrollBarData * sbDataPtr; register xrScrollBarInfo * sbInfoPtr; INT32 message; { INT8 orientation = sbInfoPtr->orientation; RECTANGLE tempRect; RECTANGLE workRect; RECTANGLE * rectPtr; register INT16 bar_ht; INT16 bar_wid; xrResourceInfo bitmapInfo; /* * Validate the percent and orientation values. */ if (invalidSBParameters (sbDataPtr, &sbInfoPtr->configuration)) { /* xrErrno is set by invalidSBParameters() */ return (FALSE); } else if (orientation != XrHORIZONTAL && orientation != XrVERTICAL) { xrErrno = XrINVALIDOPTION; return (FALSE); } /* * Make sure the editorRect is large enough to hold the instance. */ XrCopyRect (&(sbInfoPtr->editorRect), &workRect); if (sizeScrollBar (sbInfoPtr, &workRect) == FALSE) { /* xrErrno is set by sizeScrollBar() */ return (FALSE); } XrCopyRect (&(sbInfoPtr->editorRect), &tempRect); if (orientation == XrHORIZONTAL) { if ((tempRect.height < XrMIN_SCROLLBAR_HT) || (tempRect.width < workRect.width)) { xrErrno = XrINVALIDRECT; return (FALSE); } } else { if ((tempRect.width < XrMIN_SCROLLBAR_WID) || (tempRect.height < workRect.height)) { xrErrno = XrINVALIDRECT; return (FALSE); } } if (message == MSG_NEW) { /* * Now that we know all of the parameters are valid, we can start * filling in the structure pointed to by 'sbDataPtr'. For starters, * we will copy out the data from the 'sbInfoPtr' structure which we * need. */ sbDataPtr->orientation = orientation; sbDataPtr->sbFGColor = (sbInfoPtr->editorFGColor == -1) ? xrForegroundColor : sbInfoPtr->editorFGColor; sbDataPtr->sbBGColor = (sbInfoPtr->editorBGColor == -1) ? xrBackgroundColor : sbInfoPtr->editorBGColor; /* * Create the 50% tile we will need when drawing the background * for the scrollbar. */ if ((sbInfoPtr->editorFGColor == -1) && (sbInfoPtr->editorBGColor == -1)) { /* Use the default 50% tile */ sbDataPtr->sbTileId = xrDefaultTile; } else { bitmapInfo.resourceType = XrTYPE_BITMAPID; bitmapInfo.resourceId = XrPERCENT50; if ((XrResource (MSG_FIND, &bitmapInfo) == FALSE) || ((sbDataPtr->sbTileId = XMakePixmap (((xrBitmapId *)bitmapInfo.resourceObject)->bitmapId, sbDataPtr->sbFGColor, sbDataPtr->sbBGColor)) == 0)) { xrErrno = XrXCALLFAILED; return (FALSE); } } } /* * Generate the rectangles which enclose each of the scrollbar * components. The formulae used will depend upon the orientation * of the scrollbar. */ XrCopyRect (&(sbInfoPtr->editorRect), &workRect); XrCopyRect (&workRect, &(sbDataPtr->arrow1)); XrCopyRect (&workRect, &(sbDataPtr->arrow2)); rectPtr = &sbDataPtr->slideArea; XrCopyRect (&workRect, rectPtr); switch (orientation) { case XrHORIZONTAL: { bar_ht = workRect.height; /* Scroll arrow1 */ sbDataPtr->arrow1.width = bar_ht + 1; /* Scroll arrow2 */ sbDataPtr->arrow2.x = (workRect.x + workRect.width - 1) - bar_ht; sbDataPtr->arrow2.width = bar_ht + 1; /* Slide area */ rectPtr->x = (sbDataPtr->arrow1.x + sbDataPtr->arrow1.width - 1) + 2; rectPtr->width = (sbDataPtr->arrow2.x - rectPtr->x - 1); /* Slide box */ CalculateSlideBox (sbDataPtr); /* Lastly, generate the vector lists for the scroll arrows */ MakeHorzArrows (sbDataPtr, workRect.height%2); break; } case XrVERTICAL: { bar_wid = workRect.width; /* Scroll arrow1 */ sbDataPtr->arrow1.height = bar_wid + 1; /* Scroll arrow2 */ sbDataPtr->arrow2.y = (workRect.y + workRect.height - 1) - bar_wid; sbDataPtr->arrow2.height = bar_wid + 1; /* Slide area */ rectPtr->y = (sbDataPtr->arrow1.y + sbDataPtr->arrow1.height - 1) +2; rectPtr->height = (sbDataPtr->arrow2.y - rectPtr->y - 1); /* Slide box */ CalculateSlideBox (sbDataPtr); /* Lastly, generate the vector lists for the scroll arrows */ MakeVertArrows (sbDataPtr, workRect.width%2); break; } } return (TRUE); } \f /*************************************<->************************************* * * INT32 * MakeHorzArrows (sbDataPtr, oddFlag) * * xrScrollBarData * sbDataPtr; * INT32 oddFlag; * * Description: * ----------- * This routine generates the endpoints which describe the two * horizontal scrollbar arrows; the endpoints describe a polygon. * The 'oddFlag' parameter signals whether the scrollbar height * is an odd or even number of pixels. The polygon endpoints are * stored within the 'sbDataPtr' structure. * * * Inputs: * ------ * sbDataPtr = Points to the instance's internal 'data' structure. * * oddFlag = TRUE if the scrollbar height is an odd number of pixels. * * Outputs: * ------- * * Procedures Called * ----------------- * *************************************<->***********************************/ static INT32 MakeHorzArrows (sbDataPtr, oddFlag) register xrScrollBarData * sbDataPtr; INT32 oddFlag; { register POINT * arrow1 = sbDataPtr->arrow1_vl; register POINT * arrow2 = sbDataPtr->arrow2_vl; register INT16 left, top, right, bottom; /* Initialize the point count for each scroll arrow */ sbDataPtr->pointCount = 8; /* * Get the info describing the rectangle into which scroll * arrow 1 must fit. */ left = sbDataPtr->arrow1.x + 2; top = sbDataPtr->arrow1.y + 2; right = (sbDataPtr->arrow1.x + sbDataPtr->arrow1.width - 1) - 2; bottom = (sbDataPtr->arrow1.y + sbDataPtr->arrow1.height - 1) - 2; /* Start generating the vector lists */ if (oddFlag) { /* Generate the endpoints for scroll arrow 1 */ (arrow1 + 0)->x = left; (arrow1 + 0)->y = bottom - (bottom - top)/2; (arrow1 + 1)->x = left + (right - left)/2; (arrow1 + 1)->y = bottom; (arrow1 + 2)->x = left + (right - left)/2; (arrow1 + 2)->y = bottom - (bottom - top)/3; (arrow1 + 3)->x = right; (arrow1 + 3)->y = bottom - (bottom - top)/3; (arrow1 + 4)->x = right; (arrow1 + 4)->y = top + (bottom - top)/3; (arrow1 + 5)->x = left + (right - left)/2; (arrow1 + 5)->y = top + (bottom - top)/3; (arrow1 + 6)->x = left + (right - left)/2; (arrow1 + 6)->y = top; (arrow1 + 7)->x = left; (arrow1 + 7)->y = bottom - (bottom - top)/2; /* * Get the info describing the rectangle into which scroll * arrow 2 must fit. */ left = sbDataPtr->arrow2.x + 2; top = sbDataPtr->arrow2.y + 2; right = (sbDataPtr->arrow2.x + sbDataPtr->arrow2.width - 1) - 2; bottom = (sbDataPtr->arrow2.y + sbDataPtr->arrow2.height - 1) - 2; /* Generate the endpoints for scroll arrow 2 */ (arrow2 + 0)->x = right; (arrow2 + 0)->y = bottom - (bottom - top)/2; (arrow2 + 1)->x = right - (right - left)/2; (arrow2 + 1)->y = bottom; (arrow2 + 2)->x = right - (right - left)/2; (arrow2 + 2)->y = bottom - (bottom - top)/3; (arrow2 + 3)->x = left; (arrow2 + 3)->y = bottom - (bottom - top)/3; (arrow2 + 4)->x = left; (arrow2 + 4)->y = top + (bottom - top)/3; (arrow2 + 5)->x = right - (right - left)/2; (arrow2 + 5)->y = top + (bottom - top)/3; (arrow2 + 6)->x = right - (right - left)/2; (arrow2 + 6)->y = top; (arrow2 + 7)->x = right; (arrow2 + 7)->y = bottom - (bottom - top)/2; } else { /* Initialize the point count for each scroll arrow */ sbDataPtr->pointCount++; /* Generate the endpoints for scroll arrow 1 */ (arrow1 + 0)->x = left; (arrow1 + 0)->y = bottom - (bottom - top)/2; (arrow1 + 1)->x = left - 1 + (right - left)/2; (arrow1 + 1)->y = bottom; (arrow1 + 2)->x = left - 1 + (right - left)/2; (arrow1 + 2)->y = bottom - (bottom - top + 2)/3; (arrow1 + 3)->x = right; (arrow1 + 3)->y = bottom - (bottom - top + 2)/3; (arrow1 + 4)->x = right; (arrow1 + 4)->y = top + (bottom - top + 2)/3; (arrow1 + 5)->x = left - 1 + (right - left)/2; (arrow1 + 5)->y = top + (bottom - top + 2)/3; (arrow1 + 6)->x = left - 1 + (right - left)/2; (arrow1 + 6)->y = top; (arrow1 + 7)->x = left; (arrow1 + 7)->y = top + (bottom - top)/2; (arrow1 + 8)->x = left; (arrow1 + 8)->y = bottom - (bottom - top)/2; /* * Get the info describing the rectangle into which scroll * arrow 2 must fit. */ left = sbDataPtr->arrow2.x + 2; top = sbDataPtr->arrow2.y + 2; right = (sbDataPtr->arrow2.x + sbDataPtr->arrow2.width - 1) - 2; bottom = (sbDataPtr->arrow2.y + sbDataPtr->arrow2.height - 1) - 2; (arrow2 + 0)->x = right; (arrow2 + 0)->y = bottom - (bottom - top)/2; (arrow2 + 1)->x = right + 1 - (right - left)/2; (arrow2 + 1)->y = bottom; (arrow2 + 2)->x = right + 1 - (right - left)/2; (arrow2 + 2)->y = bottom - (bottom - top + 2)/3; (arrow2 + 3)->x = left; (arrow2 + 3)->y = bottom - (bottom - top + 2)/3; (arrow2 + 4)->x = left; (arrow2 + 4)->y = top + (bottom - top + 2)/3; (arrow2 + 5)->x = right + 1 - (right - left)/2; (arrow2 + 5)->y = top + (bottom - top + 2)/3; (arrow2 + 6)->x = right + 1 - (right - left)/2; (arrow2 + 6)->y = top; (arrow2 + 7)->x = right; (arrow2 + 7)->y = top + (bottom - top)/2; (arrow2 + 8)->x = right; (arrow2 + 8)->y = bottom - (bottom - top)/2; } } \f /*************************************<->************************************* * * INT32 * MakeVertArrows (sbDataPtr, oddFlag) * * xrScrollBarData * sbDataPtr; * INT32 oddFlag; * * Description: * ----------- * This routine generates the endpoints which describe the two * vertical scrollbar arrows; the endpoints describe a polygon. * The 'oddFlag' parameter signals whether the scrollbar width * is an odd or even number of pixels. The polygon endpoints are * stored within the 'sbDataPtr' structure. * * * Inputs: * ------ * sbDataPtr = Points to the instance's internal 'data' structure. * * oddFlag = TRUE if the scrollbar width is an odd number of pixels. * * Outputs: * ------- * * Procedures Called * ----------------- * *************************************<->***********************************/ static INT32 MakeVertArrows (sbDataPtr, oddFlag) register xrScrollBarData * sbDataPtr; INT32 oddFlag; { register POINT * arrow1 = sbDataPtr->arrow1_vl; register POINT * arrow2 = sbDataPtr->arrow2_vl; register INT16 left, top, right, bottom; INT32 i; /* Initialize the point count for each scroll arrow */ sbDataPtr->pointCount = 8; /* * Get the info describing the rectangle into which scroll * arrow 1 must fit. */ left = sbDataPtr->arrow1.x + 2; top = sbDataPtr->arrow1.y + 2; right = (sbDataPtr->arrow1.x + sbDataPtr->arrow1.width - 1) - 2; bottom = (sbDataPtr->arrow1.y + sbDataPtr->arrow1.height - 1) - 2; /* Start generating the vector lists */ if (oddFlag) { /* Generate the endpoints for scroll arrow 1 */ (arrow1 + 0)->x = left + (right - left)/2; (arrow1 + 0)->y = top; (arrow1 + 1)->x = left; (arrow1 + 1)->y = top + (bottom - top)/2; (arrow1 + 2)->x = left + (right - left)/3; (arrow1 + 2)->y = top + (bottom - top)/2; (arrow1 + 3)->x = left + (right - left)/3; (arrow1 + 3)->y = bottom; (arrow1 + 4)->x = right - (right - left)/3; (arrow1 + 4)->y = bottom; (arrow1 + 5)->x = right - (right - left)/3; (arrow1 + 5)->y = top + (bottom - top)/2; (arrow1 + 6)->x = right; (arrow1 + 6)->y = top + (bottom - top)/2; (arrow1 + 7)->x = left + (right - left)/2; (arrow1 + 7)->y = top; /* * Get the info describing the rectangle into which scroll * arrow 2 must fit. */ left = sbDataPtr->arrow2.x + 2; top = sbDataPtr->arrow2.y + 2; right = (sbDataPtr->arrow2.x + sbDataPtr->arrow2.width - 1) - 2; bottom = (sbDataPtr->arrow2.y + sbDataPtr->arrow2.height - 1) - 2; /* Generate the endpoints for scroll arrow 2 */ (arrow2 + 0)->x = left + (right - left)/2; (arrow2 + 0)->y = bottom; (arrow2 + 1)->x = left; (arrow2 + 1)->y = bottom - (bottom - top)/2; (arrow2 + 2)->x = left + (right - left)/3; (arrow2 + 2)->y = bottom - (bottom - top)/2; (arrow2 + 3)->x = left + (right - left)/3; (arrow2 + 3)->y = top; (arrow2 + 4)->x = right - (right - left)/3; (arrow2 + 4)->y = top; (arrow2 + 5)->x = right - (right - left)/3; (arrow2 + 5)->y = bottom - (bottom - top)/2; (arrow2 + 6)->x = right; (arrow2 + 6)->y = bottom - (bottom - top)/2; (arrow2 + 7)->x = left + (right - left)/2; (arrow2 + 7)->y = bottom; } else { /* Initialize the point count for each scroll arrow */ sbDataPtr->pointCount++; /* Generate the endpoints for scroll arrow 1 */ (arrow1 + 0)->x = left + (right - left)/2; (arrow1 + 0)->y = top; (arrow1 + 1)->x = left; (arrow1 + 1)->y = top - 1 + (bottom - top)/2; (arrow1 + 2)->x = left + (right - left + 2)/3; (arrow1 + 2)->y = top - 1 + (bottom - top)/2; (arrow1 + 3)->x = left + (right - left + 2)/3; (arrow1 + 3)->y = bottom; (arrow1 + 4)->x = right - (right - left + 2)/3; (arrow1 + 4)->y = bottom; (arrow1 + 5)->x = right - (right - left + 2)/3; (arrow1 + 5)->y = top - 1 + (bottom - top)/2; (arrow1 + 6)->x = right; (arrow1 + 6)->y = top - 1 + (bottom - top)/2; (arrow1 + 7)->x = right - (right - left)/2; (arrow1 + 7)->y = top; (arrow1 + 8)->x = left + (right - left)/2; (arrow1 + 8)->y = top; /* * Get the info describing the rectangle into which scroll * arrow 2 must fit. */ left = sbDataPtr->arrow2.x + 2; top = sbDataPtr->arrow2.y + 2; right = (sbDataPtr->arrow2.x + sbDataPtr->arrow2.width - 1) - 2; bottom = (sbDataPtr->arrow2.y + sbDataPtr->arrow2.height - 1) - 2; /* Generate the endpoints for scroll arrow 2 */ (arrow2 + 0)->x = left + (right - left)/2; (arrow2 + 0)->y = bottom; (arrow2 + 1)->x = left; (arrow2 + 1)->y = bottom + 1 - (bottom - top)/2; (arrow2 + 2)->x = left + (right - left + 2)/3; (arrow2 + 2)->y = bottom + 1 - (bottom - top)/2; (arrow2 + 3)->x = left + (right - left + 2)/3; (arrow2 + 3)->y = top; (arrow2 + 4)->x = right - (right - left + 2)/3; (arrow2 + 4)->y = top; (arrow2 + 5)->x = right - (right - left + 2)/3; (arrow2 + 5)->y = bottom + 1 - (bottom - top)/2; (arrow2 + 6)->x = right; (arrow2 + 6)->y = bottom + 1 - (bottom - top)/2; (arrow2 + 7)->x = right - (right - left)/2; (arrow2 + 7)->y = bottom; (arrow2 + 8)->x = left + (right - left)/2; (arrow2 + 8)->y = bottom; } } \f /*************************************<->************************************* * * INT32 * drawScrollBar (scrollBar, drawOption) * * xrEditor * scrollBar; * INT32 drawOption; * * Description: * ----------- * This routine will display a complete scrollbar instance. * * * Inputs: * ------ * scrollBar = Points to the instance pointer for the scrollbar * being drawn. * * drawOption = Not used; this parameter is present only so that * this routine may be called by _MsgNew(). * * Outputs: * ------- * * Procedures Called * ----------------- * _XrMakeInvisible() [editorUtil.c] * _XrBorderFillRectangle() [rectUtil.c] * setMyGCs() * drawArrowBoxes() * drawScrollArrows() * drawSlideBox() * *************************************<->***********************************/ static INT32 drawScrollBar (scrollBar, drawOption) register xrEditor * scrollBar; INT32 drawOption; { register xrScrollBarData * sbDataPtr; register INT8 sensitive; register Window windowId = scrollBar->editorWindowId; RECTANGLE workRect; sbDataPtr =(xrScrollBarData *)scrollBar->editorData; XrCopyRect (&scrollBar->editorRect, &workRect); /* * If the instance is not visible, then fill its area with the * background tile for the port, thus making the instance invisible. */ if (!(scrollBar->editorState & XrVISIBLE)) { _XrMakeInvisible (windowId, &workRect, TRUE); return; } /* Initialize the graphic contexts we will be using */ setMyGCs (sbDataPtr); sensitive = (scrollBar->editorState & XrSENSITIVE) ? TRUE : FALSE; /* Draw and fill the rectangle defining the scrollbar */ if (sensitive) { /* Draw a bordered rectangle with a 50% tile fill */ _XrBorderFillRectangle (windowId, xrEditorGC1, xrEditorGC3, &workRect); } else { /* Draw a bordered rectangle, filled with the background color */ _XrBorderFillRectangle (windowId, xrEditorGC1, xrEditorGC2, &workRect); } /* Draw the bordered and filled boxes for the scroll arrows */ drawArrowBoxes (windowId, sbDataPtr); /* Draw the scroll arrows */ if (sbDataPtr->configuration.components & XrSCROLLARROWS) drawScrollArrows (windowId, sbDataPtr, sensitive); /* Draw the slide box, if defined */ if (sbDataPtr->configuration.components & XrSLIDEBOX) drawSlideBox (windowId, sbDataPtr, sensitive); } \f /*************************************<->************************************* * * INT32 * CalculateSlidebox (sbDataPtr) * * xrScrollBarData * sbDataPtr; * * Description: * ----------- * This routine takes the slide box position, expressed in units * which are in the range of the max and min values for the instance, * and calculates the (x, y, height and width) for the rectangle which * describes the slide box. This information is stored in the * 'sbDataPtr' structure. * * * Inputs: * ------ * sbDataPtr = Points to the instance's internal data structure. * * Outputs: * ------- * * Procedures Called * ----------------- * *************************************<->***********************************/ static INT32 CalculateSlideBox (sbDataPtr) register xrScrollBarData * sbDataPtr; { register RECTANGLE * scrollRegion; register INT16 slide_wid; INT16 slide_ht; INT16 max, min; INT16 position; INT16 slideSize; INT16 unitWid; /* Set up local variables needed for our calculations */ scrollRegion = &sbDataPtr->slideArea; max = sbDataPtr->configuration.max; min = sbDataPtr->configuration.min; unitWid = max - min; position = sbDataPtr->configuration.slidePosition - min; slideSize = sbDataPtr->configuration.slideSize; if (sbDataPtr->orientation == XrHORIZONTAL) { slide_wid = (slideSize * scrollRegion->width) / (unitWid + 1); sbDataPtr->slideBox.x = scrollRegion->x + ((scrollRegion->width - slide_wid) * position)/unitWid; sbDataPtr->slideBox.y = scrollRegion->y + 2; sbDataPtr->slideBox.width = (slide_wid == 0 ? 1 : slide_wid); sbDataPtr->slideBox.height = scrollRegion->height - 4; } else { slide_ht = (slideSize * scrollRegion->height) / (unitWid + 1); sbDataPtr->slideBox.x = scrollRegion->x + 2; sbDataPtr->slideBox.y = scrollRegion->y + ((scrollRegion->height - slide_ht) * position)/unitWid; sbDataPtr->slideBox.width = scrollRegion->width - 4; sbDataPtr->slideBox.height = (slide_ht == 0 ? 1 : slide_ht); } } \f /*************************************<->************************************* * * INT32 * invalidSBParameters (sbDataPtr, sbParmPtr) * * xrScrollBarData * sbDataPtr; * xrSBParameters * sbParmPtr; * * Description: * ----------- * This routine is called anytime the scrollbar configuration * parameters are being changed. It will validate all of the * new settings, and will fail if an invalid setting is found. * If the settings are valid, then they will be saved in the * instance's internal 'data' structure. * * * Inputs: * ------ * sbDataPtr = Points to the internal 'data' structure associated * with the instance which is having its configuration * parameters modified. * * sbParmPtr = Points to the structure containing the new configuration * parameters. * * Outputs: * ------- * Upon successful completion, TRUE is returned, and the new * configuration parameter will be saved. * * Upon failure, FALSE is returned, and xrErrno is set. * * Procedures Called * ----------------- * *************************************<->***********************************/ static INT32 invalidSBParameters (sbDataPtr, sbParmPtr) register xrScrollBarData * sbDataPtr; register xrSBParameters * sbParmPtr; { register INT16 min; register INT16 max; min = sbParmPtr->min; max = sbParmPtr->max; /* Validate the new configuration parameters */ if (min >= max) { xrErrno = XrINVALIDPARM; return (TRUE); } if (sbParmPtr->components & XrSLIDEBOX) { if ((sbParmPtr->slidePosition < min) || (sbParmPtr->slidePosition > max) || (sbParmPtr->slideSize > (max - min + 1)) || (sbParmPtr->slideSize <= 0) || ((sbParmPtr->handler) && ((sbParmPtr->granularity <= 0) || (sbParmPtr->granularity > (max - min + 1))))) { xrErrno = XrPARMOUTOFRANGE; return (TRUE); } _Xrmemcpy (&sbDataPtr->configuration, sbParmPtr, sizeof (xrSBParameters)); } else { _Xrmemcpy (&sbDataPtr->configuration, sbParmPtr, sizeof (xrSBParameters)); sbDataPtr->configuration.slidePosition = min; sbDataPtr->configuration.slideSize = 1; sbDataPtr->configuration.granularity = 1; sbDataPtr->configuration.handler = NULL; } return (FALSE); } \f /*************************************<->************************************* * * INT32 * setMyGCs (sbDataPtr) * * xrScrollBarData * sbDataPtr; * * Description: * ----------- * This routine initializes the 3 graphic context structures which * are needed each time a scrollbar instance is displayed. * * * Inputs: * ------ * sbDataPtr = This points to the instance's internal 'data' * structure. The foreground and background colors * are contained here. * * Outputs: * ------- * * Procedures Called * ----------------- * _XrInitEditorGCs() [gcUtil.c] * _XrCopyGC() [gcUtil.c] * _XrChangeGC() [gcUtil.c] * *************************************<->***********************************/ static INT32 setMyGCs (sbDataPtr) xrScrollBarData * sbDataPtr; { INT32 changeList[21]; INT32 changeMask; /* Initialize the graphic contexts we will use during drawing */ _XrInitEditorGCs (sbDataPtr->sbFGColor, sbDataPtr->sbBGColor, xrBaseFontInfo->id); /* * Create another graphics context, which we will use whenever * we need to tile fill the background of a sensitive scrollbar. */ changeList[XrFILLSTYLEVAL] = Tiled; changeList[XrTILEVAL] = sbDataPtr->sbTileId; changeMask = (XrFILLSTYLE | XrTILE); _XrCopyGC (xrDefaultGC, xrEditorGC3); _XrChangeGC (xrEditorGC3, changeMask, changeList); } \f /*************************************<->************************************* * * INT32 * updateComponents (scrollBar, sbDataPtr) * * xrEditor * scrollBar; * xrScrollBarData * sbDataPtr; * * Description: * ----------- * This routine looks at the new configuration parameters for the * specified scrollbar instance, and calculates the new slide box * location. In addition, it redraws the instance to match, assuming * the instance is visible * * * Inputs: * ------ * scrollBar = Points to the instance structure associated with the * scrollbar being worked on. This contains the window * Id for the window to which the instance is attached. * * sbDataPtr = Points to the instance's internal 'data' structure. * * Outputs: * ------- * * Procedures Called * ----------------- * XrCopyRect() [calc.c] * XrEqualRect() [calc.c] * removeSlideBox() * drawSlideBox() * CalculateSlideBox() * drawScrollArrows() * drawArrowBoxes() * setMyGCs() * *************************************<->***********************************/ static INT32 updateComponents (scrollBar, sbDataPtr) register xrEditor * scrollBar; register xrScrollBarData * sbDataPtr; { INT8 sensitive = scrollBar->editorState & XrSENSITIVE; RECTANGLE slideBox; /* Initialize the graphic contexts we will use during drawing */ setMyGCs (sbDataPtr); /* Calculate the new slide position */ XrCopyRect (&sbDataPtr->slideBox, &slideBox); CalculateSlideBox (sbDataPtr); /* Update the visual instance only if it is visible */ if (scrollBar->editorState & XrVISIBLE) { /* See if the state of the scroll arrows has changed */ if (sbDataPtr->configuration.components & XrSCROLLARROWS) drawScrollArrows (scrollBar->editorWindowId, sbDataPtr, sensitive); else drawArrowBoxes (scrollBar->editorWindowId, sbDataPtr); /* See if the state of the slide box has changed */ if (! (sbDataPtr->configuration.components & XrSLIDEBOX) || (! XrEqualRect (&slideBox, &sbDataPtr->slideBox))) { removeSlideBox (scrollBar->editorWindowId, &slideBox, sbDataPtr, sensitive, FALSE); } if (sbDataPtr->configuration.components & XrSLIDEBOX) drawSlideBox (scrollBar->editorWindowId, sbDataPtr, sensitive); } } \f /*************************************<->************************************* * * INT32 * removeSlideBox (windowId, rectPtr, sbDataPtr, sensitive, xparentMode) * * Description: * ----------- * This routine is used both during interactive slide operations, and * any other time the slide box needs to be removed. The manner in * which the removal is performed depends upon the 'xparentMode' * parameter. If 'xparentMode' is set to FALSE, then the slide box * is removed by overwriting it with the background tile (if the * instance is sensitive) or the background color (if the instance is * not sensitive). However, if 'xparentMode' is set to TRUE, then * we know that an interactive slide is going on, so we only want to * 'remove' that portion of the transparent slide box which does not * intersect with the real slide box. * * * Inputs: * ------ * windowId = Id of window to which the scrollbar is attached. * * rectPtr = Current slide box (normal or transparent) location. * * sbDataPtr = Points to instance's internal 'data' structure. * * sensitive = TRUE if instance is sensitive; FALSE otherwise. * * xparentMode = TRUE if transparent mode interactive slide operation * is currently taking place. * * Outputs: * ------- * * Procedures Called * ----------------- * XrCopyRect() [calc.c] * _XrFillRectangle() [rectUtil.c] * *************************************<->***********************************/ static INT32 removeSlideBox (windowId, rectPtr, sbDataPtr, sensitive, xparentMode) Window windowId; register RECTANGLE * rectPtr; INT8 sensitive; xrScrollBarData * sbDataPtr; INT8 xparentMode; { /* Check for a transparent mode slide operation in progress */ if (xparentMode) { RECTANGLE workRect; register RECTANGLE * sbPtr = &sbDataPtr->slideBox; XrCopyRect (rectPtr, &workRect); /* * Determine the portion of the slide outline which does * not intersect with the real slide box. This is the * part which must be removed. */ if (sbPtr->x > rectPtr->x) workRect.width = sbPtr->x - rectPtr->x; else if (sbPtr->x < rectPtr->x) { workRect.x = sbPtr->x + sbPtr->width; workRect.width = rectPtr->width - (workRect.x - rectPtr->x); } if (sbPtr->y > rectPtr->y) workRect.height = sbPtr->y - rectPtr->y; else if (sbPtr->y < rectPtr->y) { workRect.y = sbPtr->y + sbPtr->height; workRect.height = rectPtr->height - (workRect.y - rectPtr->y); } _XrFillRectangle (windowId, xrEditorGC3, &workRect); } else { /* Cover the slide box, using the 50% background tile */ if (sensitive) _XrFillRectangle (windowId, xrEditorGC3, rectPtr); else _XrFillRectangle (windowId, xrEditorGC2, rectPtr); } } \f /*************************************<->************************************* * * INT32 * drawSlidebox (windowId, sbDataPtr, sensitive) * * Window windowId; * xrScrollBarData * sbDataPtr; * INT8 sensitive; * * Description: * ----------- * This routine draws the slide box at its current location, as * specified in the instance's internal 'data' structure. * * * Inputs: * ------ * windowId = Id of window to which the instance is attached. * * sbDataPtr = Points to the instance's internal 'data' structure. * * sensitive = TRUE if the instance is currently sensitive; FALSE * otherwise. * * Outputs: * ------- * * Procedures Called * ----------------- * XrBorderFillRectangle() [rectUtil.c] * *************************************<->***********************************/ static INT32 drawSlideBox (windowId, sbDataPtr, sensitive) Window windowId; xrScrollBarData * sbDataPtr; INT8 sensitive; { INT32 fillGC; if (sensitive) fillGC = xrEditorGC1; else fillGC = xrEditorGC2; _XrBorderFillRectangle (windowId, xrEditorGC1, fillGC, &sbDataPtr->slideBox); } \f /*************************************<->************************************* * * INT32 * drawArrowBoxes (windowId, sbDataPtr) * * Window windowId; * xrScrollBarData * sbDataPtr; * * Description: * ----------- * This routine will draw the two scroll arrow boxes (not the scroll * arrows themselves) at either end of the scrollbar. * * * Inputs: * ------ * windowId = Id of window to which the instance is attached. * * sbDataPtr = Points to the instance's internal 'data' structure. * * Outputs: * ------- * * Procedures Called * ----------------- * _XrBorderFillRectangle() [rectUtil.c] * *************************************<->***********************************/ static INT32 drawArrowBoxes (windowId, sbDataPtr) Window windowId; xrScrollBarData * sbDataPtr; { _XrBorderFillRectangle (windowId, xrEditorGC1, xrEditorGC2, &sbDataPtr->arrow1); _XrBorderFillRectangle (windowId, xrEditorGC1, xrEditorGC2, &sbDataPtr->arrow2); } \f /*************************************<->************************************* * * INT32 * drawScrollArrows (windowId, sbDataPtr, sensitive) * * Window windowId; * xrScrollBarData * sbDataPtr; * INT8 sensitive; * * Description: * ----------- * This routine will draw the two scroll arrows located at either * end of a scrollbar. They will be drawn as filled arrows if the * instance is sensitive; otherwise, only their outline will be * drawn. The definitions for the polygons describing the arrow * are contained in the instance's internal 'data' structure. * * * Inputs: * ------ * windowId = Id of the window to which the instance is attached. * * sbDataPtr = Points to the instance's internal 'data' structure. * * sensitive = TRUE if the instance is sensitive; FALSE otherwise. * * Outputs: * ------- * * Procedures Called * ----------------- * _XrFillPoly() [polyUtil.c] * _XrPoly() [polyUtil.c] * *************************************<->***********************************/ static INT32 drawScrollArrows (windowId, sbDataPtr, sensitive) register Window windowId; register xrScrollBarData * sbDataPtr; INT8 sensitive; { register INT32 i; register INT16 pointCount; /* Draw scroll arrow 1 */ pointCount = sbDataPtr->pointCount; for (i = 0; i < pointCount; i++) { xr_PolyList[i].x = sbDataPtr->arrow1_vl[i].x; xr_PolyList[i].y = sbDataPtr->arrow1_vl[i].y; xr_PolyList[i].flags = 0; } if (sensitive) _XrFillPoly (windowId, xrEditorGC1, pointCount, xr_PolyList); else _XrPoly (windowId, xrEditorGC1, pointCount, xr_PolyList); /* Draw scroll arrow 2 */ for (i = 0; i < pointCount; i++) { xr_PolyList[i].x = sbDataPtr->arrow2_vl[i].x; xr_PolyList[i].y = sbDataPtr->arrow2_vl[i].y; xr_PolyList[i].flags = 0; } if (sensitive) _XrFillPoly (windowId, xrEditorGC1, pointCount, xr_PolyList); else _XrPoly (windowId, xrEditorGC1, pointCount, xr_PolyList); } \f /*************************************<->************************************* * * INT32 * processScrollBar (scrollBar, input, returnEvent) * * xrEditor * scrollBar; * XButtonEvent * input; * xrEvent * returnEvent; * * Description: * ----------- * This is the event processing routine for the scrollbar editor. * It takes an event and determines which component of the scrollbar * the select occurred in. The possible choices are one of the * scroll arrows, the slide region or the slide box. * * * Inputs: * ------ * scrollBar = Instance pointer for the scrollbar being selected. * * input = Points to the event to be processed. * * returnEvent = Points to a partially filled out X-ray event * structure. It can be used by this routine when * it needs to generate a return event for the * application. Every field is already filled, except * for the 'value' fields. * * Outputs: * ------- * * Procedures Called * ----------------- * XrSetPt() [calc.c] * XrPtInRect() [calc.c] * XrGetWindowEvent() [utilities.c] * XrInput() [input.c] * XrCopyRect() [calc.c] * interactiveSlide() * *************************************<->***********************************/ static INT32 processScrollBar (scrollBar, input, returnEvent) xrEditor * scrollBar; XButtonEvent * input; xrEvent * returnEvent; { register xrScrollBarData * sbDataPtr; register INT8 orientation; POINT spritePt; register RECTANGLE * saPtr; /* Ptr to slide area rectangle */ RECTANGLE slideBox; INT8 arrowsShowing; INT8 slideBoxShowing; INT16 min; INT16 max; XButtonEvent selectUp; xrWindowEvent windowEvent; sbDataPtr = (xrScrollBarData *) scrollBar->editorData; min = sbDataPtr->configuration.min; max = sbDataPtr->configuration.max; orientation = sbDataPtr->orientation; arrowsShowing = sbDataPtr->configuration.components & XrSCROLLARROWS; slideBoxShowing = sbDataPtr->configuration.components & XrSLIDEBOX; XrSetPt (&spritePt, input->x, input->y); returnEvent->value2 = sbDataPtr->configuration.slidePosition; /* * Determine which region was selected */ /* Check for a select in scroll arrow 1 region */ if (XrPtInRect (&spritePt, &sbDataPtr->arrow1)) { /* Do nothing but set up the return event */ if (! arrowsShowing) returnEvent->value1 = NULL; else { if (orientation == XrHORIZONTAL) returnEvent->value1 = XrSCROLL_LEFT; else returnEvent->value1 = XrSCROLL_UP; } /* * Push a fake select up event, so that the real * select up event won't be swallowed by _MsgEdit(), * and will instead pass through to the application. */ XrGetWindowEvent (XrSELECTUP, &windowEvent); selectUp.type = windowEvent.inputType; selectUp.detail = windowEvent.inputCode; XrInput (NULL, MSG_PUSHEVENT, &selectUp); return; } /* Check for a select in scroll arrow 2 region */ if (XrPtInRect (&spritePt, &sbDataPtr->arrow2)) { /* Do nothing but set up the return event */ if (! arrowsShowing) returnEvent->value1 = NULL; else { if (orientation == XrHORIZONTAL) returnEvent->value1 = XrSCROLL_RIGHT; else returnEvent->value1 = XrSCROLL_DOWN; } /* * Push a fake select up event, so that the real * select up event won't be swallowed by _MsgEdit(), * and will instead pass through to the application. */ XrGetWindowEvent (XrSELECTUP, &windowEvent); selectUp.type = windowEvent.inputType; selectUp.detail = windowEvent.inputCode; XrInput (NULL, MSG_PUSHEVENT, &selectUp); return; } /* Check for a select in the scroll area; excluding the slide box */ saPtr = &sbDataPtr->slideArea; XrCopyRect (&sbDataPtr->slideBox, &slideBox); /* * Increase the size of the slide box, to include the one * pixel of space above and below it (for a horizontal scrollbar) * or the one pixel of space to the right and left of it (for * a vertical scrollbar). */ if (sbDataPtr->orientation == XrHORIZONTAL) { slideBox.y -= 2; slideBox.height += 4; } else { slideBox.x -= 2; slideBox.width += 4; } if ( (!slideBoxShowing) || !(XrPtInRect (&spritePt, &slideBox)) ) { /* Calculate the sprite position within the scroll area */ if (orientation == XrHORIZONTAL) { if (spritePt.x < saPtr->x) spritePt.x = saPtr->x; else if (spritePt.x > (saPtr->x + saPtr->width - 1)) spritePt.x = (saPtr->x + saPtr->width - 1); returnEvent->value3 = min + (((max - min + 1)*(spritePt.x - saPtr->x))/saPtr->width); if ( (slideBoxShowing) && (spritePt.x < slideBox.x) ) returnEvent->value1 = XrSCROLL_LESS; else returnEvent->value1 = XrSCROLL_MORE; } else { if (spritePt.y < saPtr->y) spritePt.y = saPtr->y; else if (spritePt.y > (saPtr->y + saPtr->height - 1)) spritePt.y = (saPtr->y + saPtr->height - 1); returnEvent->value3 = min + (((max - min + 1)*(spritePt.y - saPtr->y))/saPtr->height); if ( (slideBoxShowing) && (spritePt.y < slideBox.y) ) returnEvent->value1 = XrSCROLL_LESS; else returnEvent->value1 = XrSCROLL_MORE; } return; } /* * By default, the slide box must have been selected * Keep processing, until the Select button is released */ interactiveSlide (scrollBar, sbDataPtr, &spritePt, returnEvent); } \f /*************************************<->************************************* * * INT32 * interactiveSlide (scrollBar, sbDataPtr, spritePtr, returnEvent) * * xrEditor * scrollBar; * xrScrollBarData * sbDataPtr; * POINT * spritePtr; * xrEvent * returnEvent; * * Description: * ----------- * This routine is invoked anytime a select event occurs within the * slide box. When this happens, this routine will continue to move * the slide box, until either the user releases the select button, * or any other X event is received; under either of these conditions, * the interactive slide operation will terminate, and a return event * will be generated. * * * Inputs: * ------ * scrollBar = Points to the instance structure. * * sbDataPtr = Points to the instance's internal 'data' structure. * * spritePtr = Points to the initial mouse position at the time the * select event occurred. * * returnEvent = Points to a partially filled out X-ray event structure. * It can be used by this routine when it needs to * generate its return event. Every field is already * filled, except for the 'value' fields. * * Outputs: * ------- * * Procedures Called * ----------------- * XrCopyPt() [calc.c] * XrSetPt() [calc.c] * XrCopyRect() [calc.c] * XrOffsetRect() [calc.c] * _XrRectangle() [rectUtil.c] * XrInput() [input.c] * XFlush() [libX.a] * XQueryMouse() [libX.a] * removeSlideBox() * drawSlideBox() * setMyGCs() * *************************************<->***********************************/ static INT32 interactiveSlide (scrollBar, sbDataPtr, spritePtr, returnEvent) xrEditor * scrollBar; register xrScrollBarData * sbDataPtr; POINT * spritePtr; xrEvent * returnEvent; { register INT8 orientation; register INT8 transparentMode; register RECTANGLE * saPtr; /* Ptr to slide area rectangle */ register RECTANGLE * sbPtr; /* Ptr to slide box rectangle */ RECTANGLE workRect; RECTANGLE xparentBox; xrEvent key; INT16 xOffset, yOffset; POINT oldCursor; INT32 cursorX, cursorY; Window subw; Window windowId; INT16 location; INT16 min; INT16 max; register INT16 slidePosition; register INT16 granularity; INT8 handlerFlag; /* Initialize local variables */ min = sbDataPtr->configuration.min; max = sbDataPtr->configuration.max; orientation = sbDataPtr->orientation; XrCopyPt (spritePtr, &oldCursor); setMyGCs (sbDataPtr); saPtr = &sbDataPtr->slideArea; windowId = scrollBar->editorWindowId; transparentMode = scrollBar->editorState & XrTRANSPARENT; handlerFlag = (sbDataPtr->configuration.handler ? TRUE : FALSE); slidePosition = sbDataPtr->configuration.slidePosition; granularity = sbDataPtr->configuration.granularity; /* Set up the slide box pointer */ if (transparentMode) { sbPtr = &xparentBox; XrCopyRect (&sbDataPtr->slideBox, sbPtr); /* Display the slidebox outline */ _XrRectangle (windowId, xrEditorGC1, sbPtr); } else sbPtr = &sbDataPtr->slideBox; /* Determine where, within the slide box, the cursor is */ xOffset = spritePtr->x - sbPtr->x + 1; yOffset = spritePtr->y - sbPtr->y + 1; while (1) { /* Stop as soon as any X event is received */ if (XrInput (NULL, MSG_NONBLKREAD, &key)) { /* Finish up the slide operation */ if (orientation == XrHORIZONTAL) { if (saPtr->width == sbPtr->width) location = min; else location = (((sbPtr->x - saPtr->x) * (max - min)) / (saPtr->width - sbPtr->width)) + min; } else { if (saPtr->height == sbPtr->height) location = min; else location = (((sbPtr->y - saPtr->y) * (max - min)) / (saPtr->height - sbPtr->height)) + min; } /* * Regardless of what this event is, push it back onto * the input queue, so that _MsgEdit() will properly * strip the select up event. */ XrInput (NULL, MSG_PUSHEVENT, &key); /* Generate our return event */ if (transparentMode) { /* Remove the slide box outline */ removeSlideBox (windowId, sbPtr, sbDataPtr, XrSENSITIVE, TRUE); drawSlideBox (windowId, sbDataPtr, XrSENSITIVE); XFlush(); returnEvent->value3 = location; returnEvent->value1 = XrTSCROLL_SLIDE; return; } else { returnEvent->value2 = location; sbDataPtr->configuration.slidePosition = location; returnEvent->value1 = XrSCROLL_SLIDE; return; } } /* Get cursor position, and process it */ XQueryMouse (scrollBar->editorWindowId, &cursorX, &cursorY, &subw); /* Update only if the cursor location has changed */ if (cursorX != oldCursor.x || cursorY != oldCursor.y) { if (orientation == XrHORIZONTAL) { /* * Check for the slide box already being located at one * end of the slide region, or for the cursor being outside * the slide region. */ if (cursorX < saPtr->x + xOffset - 1) { if (sbPtr->x > saPtr->x) cursorX= saPtr->x + xOffset - 1; else continue; } else if (cursorX > ((saPtr->x + saPtr->width - 1) - sbPtr->width + xOffset)) { if (sbPtr->x + sbPtr->width - 1 < saPtr->x + saPtr->width - 1) cursorX = (saPtr->x + saPtr->width - 1) + xOffset - sbPtr->width; else continue; } XrCopyRect (sbPtr, &workRect); XrOffsetRect (&workRect, (cursorX - xOffset + 1) - sbPtr->x, 0); } else { /* * Check for the slide box already being located at one * end of the slide region, or for the cursor being outside * the slide region. */ if (cursorY < saPtr->y + yOffset - 1) { if (sbPtr->y > saPtr->y) cursorY= saPtr->y + yOffset - 1; else continue; } else if (cursorY > ((saPtr->y + saPtr->height - 1) - sbPtr->height + yOffset)) { if (sbPtr->y + sbPtr->height - 1 < saPtr->y + saPtr->height - 1) cursorY = (saPtr->y + saPtr->height - 1) + yOffset - sbPtr->height; else continue; } XrCopyRect (sbPtr, &workRect); XrOffsetRect (&workRect, 0, (cursorY - yOffset + 1) - sbPtr->y); } /* Draw the scrollbox at its new position */ if (transparentMode) { /* Remove the old slide box outline */ removeSlideBox (windowId, sbPtr, sbDataPtr, XrSENSITIVE, TRUE); drawSlideBox (windowId, sbDataPtr, XrSENSITIVE); /* Draw the slide box outline at the new position */ _XrRectangle (windowId, xrEditorGC1, &workRect); XrCopyRect (&workRect, sbPtr); } else { removeSlideBox (windowId, sbPtr, sbDataPtr, XrSENSITIVE, FALSE); XrCopyRect (&workRect, sbPtr); drawSlideBox (windowId, sbDataPtr, XrSENSITIVE); } XrSetPt (&oldCursor, cursorX, cursorY); /* * Call the application's handler, if the granularity * delta was surpassed, and a handler is specified. */ if (handlerFlag) { if (orientation == XrHORIZONTAL) { location = (((sbPtr->x - saPtr->x) * (max - min)) / (saPtr->width - sbPtr->width)) + min; } else { location = (((sbPtr->y - saPtr->y) * (max - min)) / (saPtr->height - sbPtr->height)) + min; } if ((location <= slidePosition - granularity) || (location >= slidePosition + granularity) || (location == max && slidePosition != max) || (location == min && slidePosition != min)) { (*sbDataPtr->configuration.handler) (windowId, scrollBar, location); slidePosition = location; } } } } }