|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: 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;
}
}
}
}
}