|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: R T
Length: 77457 (0x12e91)
Types: TextFile
Names: »RasterEdit.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/RasterEdit.c«
/*
* $Source: /u1/Xr/src/Xrlib/Editor/RCS/RasterEdit.c,v $
* $Header: RasterEdit.c,v 1.1 86/12/17 09:03:45 swick Exp $
*/
#ifndef lint
static char *rcsid_RasterEdit_c = "$Header: RasterEdit.c,v 1.1 86/12/17 09:03:45 swick Exp $";
#endif lint
#include <Xr/xr-copyright.h>
/* $Header: RasterEdit.c,v 1.1 86/12/17 09:03:45 swick Exp $ */
/* Copyright 1986, Hewlett-Packard Company */
/* Copyright 1986, Massachussetts Institute of Technology */
static char rcsid[] = "$Header: RasterEdit.c,v 1.1 86/12/17 09:03:45 swick Exp $";
/*************************************<+>*************************************
*****************************************************************************
**
** File: RasterEdit.c
**
** Project: X-ray Toolbox
**
** Description:
** This file contains all of the source code (minus the
** field editor utility routines) for the raster edit
** field editor.
**
**
** ------------------------ MODIFICATION RECORD ------------------------
*
* $Log: RasterEdit.c,v $
* Revision 1.1 86/12/17 09:03:45 swick
* Initial revision
*
* Revision 6.1 86/11/13 12:57:58 12:57:58 fred ()
* Fixed scrollbar event bug
*
* Revision 6.0 86/11/10 15:34:15 15:34:15 fred ()
* QA #2 release
*
* Revision 5.2 86/11/07 14:21:41 14:21:41 fred ()
* Added new copyright message.
*
* Revision 5.1 86/11/04 08:57:37 08:57:37 fred ()
* Added continuous scrolling, and fixed a bug in MSG_SETSTATE.
*
* Revision 5.0 86/10/28 08:31:09 08:31:09 fred ()
* QA #1.1 release
*
* Revision 4.1 86/10/23 09:07:31 09:07:31 fred ()
* Removed unused variables.
*
* Revision 4.0 86/10/20 12:12:26 12:12:26 fred ()
* QA #1 release
*
* Revision 3.2 86/10/16 09:16:31 09:16:31 fred ()
* Performance enhanced: added use of register variables.
*
* Revision 3.1 86/10/09 07:46:52 07:46:52 fred ()
* Added default color check to create routine.
*
* Revision 3.0 86/10/02 16:00:12 16:00:12 fred ()
* Alpha release set to 3.0
*
* Revision 2.7 86/10/01 08:13:31 08:13:31 fred ()
* Fixed a bug where if only a single scrollbar was needed,
* it ended up getting displayed on top of the editing region,
* instead of next to it.
*
* Revision 2.6 86/09/22 12:37:35 12:37:35 fred ()
* Changed xrPixMap structure to xrPixmap, and
* added calls to XrEditorGroup().
*
* Revision 2.5 86/09/19 10:09:06 10:09:06 fred ()
* Fixed a bug where I was generating a fake "
* Select event instead of a SELECTUP event.
*
* Revision 2.4 86/09/19 07:11:24 07:11:24 fred ()
* Added a check for XrVISIBLE before doing any drawing.
*
* Revision 2.3 86/09/18 10:02:32 10:02:32 fred ()
* Fixed scrollbar processing, so that a fake select up event is
* pushed after the scrollbar processing, thus preventing _MsgEdit()
* from hanging, waiting for a non-existant select up event.
*
* Revision 2.2 86/09/18 07:40:57 07:40:57 fred ()
* Filled in procedure headers.
*
* Revision 2.1 86/09/17 08:16:24 08:16:24 fred ()
* Fixed a but in paintREdit(), where the input queue was only read
* when the cursor was within the editing region.
*
* Revision 2.0 86/09/16 08:08:18 08:08:18 fred ()
* Updated input processing routine to use new SELECT strategy.
*
* Revision 1.6 86/09/16 05:48:08 05:48:08 fred ()
* Modified to swallow a select up event.
*
* Revision 1.5 86/09/09 10:43:19 10:43:19 fred ()
* Added a line algorithm to the drawing routine, so
* that pixels are not skipped during drag operation.
*
* Revision 1.4 86/09/09 07:09:27 07:09:27 fred ()
* Added the view origin data to the event information returned
* when the view region is scrolled by the user.
*
* Revision 1.3 86/09/08 06:50:17 06:50:17 fred ()
* Broke up large functions into several smaller functions.
*
* Revision 1.2 86/09/05 15:05:31 15:05:31 fred ()
* Added handling of all message requests.
* This is the first complete version of this editor.
*
* Revision 1.1 86/09/03 13:57:33 13:57:33 fred ()
* Initial revision
*
*
*****************************************************************************
*************************************<+>*************************************/
#include <X/Xlib.h>
#include <Xr/defs.h>
#include <Xr/types.h>
#include <Xr/in_types.h>
#ifdef BSD
#include <sys/time.h>
#else
#include <time.h>
#endif
extern INT32 createREdit();
extern INT32 drawREdit();
extern INT32 processREdit();
extern INT32 reFreeMemory();
extern xrEditor * moveREdit();
extern xrEditor * resizeREdit();
extern xrEditor * positionREdit();
\f
/*************************************<->*************************************
*
* xrEditor *
* XrRasterEdit (rasterEdit, message, data)
*
* xrEditor * rasterEdit;
* INT32 message;
* INT8 * data;
*
* Description:
* -----------
* This is the entry point into the raster edit field editor.
* All requests (in the form of a message) are received here,
* and processed accordingly. Refer to the raster editor manual
* page for a complete description of the messages handled here,
* along with the meaning of the 'data' parameter.
*
*
* Inputs:
* ------
* rasterEdit = This is a pointer to the editor instance structure,
* returned when an instance was created.
*
* message = This is one of the raster editor messages.
*
* data = This parameter is message specific. Depending upon the
* 'message' parameter, this may contain a scalar value, or
* it may contain a pointer to a structure. The exact format
* of this parameter is discussed below, in the handling code
* for each message.
*
* Outputs:
* -------
* Upon successful completion of processing a message, the editor
* instance pointer will be returned. Other information may
* also be returned by means of the 'data' parameter; if this
* is the case, then it will be discussed in the handling code
* for each message.
*
* Upon failure, NULL will be returned, and xrErrno set.
*
* Procedures Called
* -----------------
* _MsgNew() [MsgCommon.c]
* _MsgFree() [MsgCommon.c]
* _MsgGetState() [MsgCommon.c]
* _MsgRedraw() [MsgCommon.c]
* _MsgEdit() [MsgCommon.c]
* XrScrollBar() [ScrollBar.c]
* sizeREdit()
* moveREdit()
* resizeREdit()
* positionREdit()
*
*************************************<->***********************************/
xrEditor *
XrRasterEdit (rasterEdit, message, data)
register xrEditor * rasterEdit;
INT32 message;
INT8 * data;
{
/* Determine the action being requested */
switch (message)
{
case MSG_NEW:
{
/*
* Create a new instance of the editor.
* The 'rasterEdit' parameter is unused.
* The 'data' parameter must point to an instance of
* the xrRasterEditInfo structure.
*/
return ((xrEditor *) _MsgNew (rasterEdit, data,
sizeof(xrRasterEditData),
createREdit, drawREdit,
reFreeMemory, XrRasterEdit,
NULL));
}
case MSG_FREE:
{
/*
* Destroy the specified editor instance.
* The 'rasterEdit' parameter must point to the editor
* instance structure associated with the instance to
* be freed. The 'data' parameter is unused.
*/
return ((xrEditor *) _MsgFree (rasterEdit, reFreeMemory));
}
case MSG_GETSTATE:
{
/*
* Return the state flags for an editor instance.
* The 'rasterEdit' parameter specifies the instance
* to be queried, while the 'data' parameter must point
* to an INT8 value, into which the state flags are returned.
*/
return ((xrEditor *) _MsgGetState (rasterEdit, data));
}
case MSG_SETSTATE:
{
/*
* Change the state flags for an editor instance.
* The 'rasterEdit' parameter specifies the instance to
* be modified. The 'data' parameter is interpreted as
* an INT8 value, containing the new state flags.
*/
register xrRasterEditData * reDataPtr;
register INT8 oldState;
register INT8 stateFlags = (INT8) data;
if (rasterEdit == NULL)
{
xrErrno = XrINVALIDID;
return ((xrEditor *)NULL);
}
oldState = rasterEdit->editorState;
rasterEdit->editorState = stateFlags;
/*
* Redraw the instance if either the XrVISIBLE flag has changed,
* or if the instance is visible and the XrSENSITIVE flag has
* changed.
*/
if (((oldState & XrVISIBLE) != (stateFlags & XrVISIBLE)) ||
((stateFlags & XrVISIBLE) &&
((oldState & XrSENSITIVE) != (stateFlags & XrSENSITIVE))))
{
if ((oldState & XrVISIBLE) != (stateFlags & XrVISIBLE))
drawREdit (rasterEdit, NULL);
/* Update the scrollbar states */
reDataPtr = (xrRasterEditData *) rasterEdit->editorData;
if (reDataPtr->vScrollbar)
XrScrollBar (reDataPtr->vScrollbar, MSG_SETSTATE, data);
if (reDataPtr->hScrollbar)
XrScrollBar (reDataPtr->hScrollbar, MSG_SETSTATE, data);
}
return (rasterEdit);
}
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 'rasterEdit'
* parameter is unused. The 'data' parameter must point to
* an instance of the 'xrRasterEditInfo' structure. The
* calculated rectangle is returned in the 'editorRect'
* field within this structure.
*/
xrRasterEditInfo * reInfoPtr;
reInfoPtr = (xrRasterEditInfo *)data;
if (reInfoPtr == NULL)
{
xrErrno = XrINVALIDPTR;
return ((xrEditor *)NULL);
}
else if (sizeREdit (reInfoPtr, &reInfoPtr->editorRect) == FALSE)
{
/* Size request failed; xrErrno set by sizeREdit */
return ((xrEditor *)NULL);
}
return ((xrEditor *) TRUE);
}
case MSG_REDRAW:
{
/*
* Redraw an instance of this editor.
* The 'rasterEdit' parameter specifies the instance to be
* redrawn. The 'data' parameter is interpreted as an INT32
* value, specifying the type of redraw to perform; this editor
* only supports the XrREDRAW_ALL option.
*/
register xrRasterEditData * reDataPtr;
if (_MsgRedraw (rasterEdit, data, drawREdit, NULL))
{
/* Redraw the scrollbars */
reDataPtr = (xrRasterEditData *) rasterEdit->editorData;
if (reDataPtr->vScrollbar)
XrScrollBar (reDataPtr->vScrollbar, MSG_REDRAW, XrREDRAW_ALL);
if (reDataPtr->hScrollbar)
XrScrollBar (reDataPtr->hScrollbar, MSG_REDRAW, XrREDRAW_ALL);
return (rasterEdit);
}
return ((xrEditor *) NULL);
}
case MSG_MOVE:
{
/*
* Reposition the origin of an instance's editorRect.
* The 'rasterEdit' parameter specifies the instance which is
* to be moved. The 'data' parameter must point to a POINT
* structure, specifying the new origin.
*/
return (moveREdit (rasterEdit, data));
}
case MSG_RESIZE:
{
/*
* Resize an existing raster editor instance.
* The 'rasterEdit' parameter specifies the instance which
* is to be resized. The 'data' parameter must point to an
* instance of the RECTANGLE structure, containing the new
* size and origin information.
*/
return (resizeREdit (rasterEdit, data));
}
case MSG_POSITION:
{
/*
* Change the portion of the raster image to be displayed
* within the view region.
* The 'rasterEdit' parameter specifies the instance which is
* to be modified. The 'data' parameter must point to an
* instance of the POINT structure, which contains the
* coordinates of the pixel which should be displayed in
* the upper left hand corner of the view region.
*/
return (positionREdit (rasterEdit, data));
}
case MSG_SETCOLOR:
{
/*
* Set a new pixel editing color.
* The 'rasterEdit' parameter indicates which instance
* is being referenced. The 'data' parameter is interpreted
* as a 32 bit integer value containing the new editing color.
*/
if (rasterEdit == NULL)
{
xrErrno = XrINVALIDID;
return ((xrEditor *) NULL);
}
((xrRasterEditData *)rasterEdit->editorData)->pixelColor =
(INT32) data;
return (rasterEdit);
}
case MSG_EDIT:
{
/*
* Process the incoming event, and generate a return event, to
* indicate to the application program how the editor instance
* was modified.
* The 'rasterEdit' parameter specifies the instance to which
* the event is to be applied. The 'data' parameter is assumed
* to point to an XEvent structure.
*/
return ((xrEditor *) _MsgEdit (rasterEdit, data,
processREdit, XrRASTEREDIT));
}
default:
/* All other commands are invalid */
xrErrno = XrINVALIDMSG;
return ((xrEditor *)NULL);
} /* end of switch */
} /* end of XrRasterEdit() */
\f
/*************************************<->*************************************
*
* reFreeMemory (reDataPtr)
*
* xrRasterEditData * reDataPtr;
*
* Description:
* -----------
* This routine will free up the scrollbars associated with a
* particular instance (if they are defined), and will also
* free up the pixel extraction instance used to extract the data
* from the raster image being edited. It is invoked either when
* a MSG_FREE is received, or when a MSG_NEW request fails at a point
* after createREdit() has been called.
*
*
* Inputs:
* ------
* reDataPtr = This is a pointer to an instance's internal 'data'
* structure. It contains the scrollbar instance pointers,
* along with the pixel extraction instance pointer.
*
* Outputs:
* -------
*
* Procedures Called
* -----------------
* XrScrollBar() [ScrollBar.c]
* _XrPixelExtract() [pixelExt.c]
*
*************************************<->***********************************/
static
INT32
reFreeMemory (reDataPtr)
register xrRasterEditData * reDataPtr;
{
/*
* If either a horizontal or vertical scrollbar was created,
* then instruct the scrollbar editor to destroy them.
*/
if (reDataPtr->vScrollbar)
XrScrollBar (reDataPtr->vScrollbar, MSG_FREE, NULL);
if (reDataPtr->hScrollbar)
XrScrollBar (reDataPtr->hScrollbar, MSG_FREE, NULL);
/* Release the pixel extraction resources */
_XrPixelExtract (reDataPtr->extractionData, MSG_FREE, NULL);
}
\f
/*************************************<->*************************************
*
* sizeREdit (reInfoPtr, rectPtr)
*
* xrRasterEditInfo * reInfoPtr;
* RECTANGLE * rectPtr;
*
* Description:
* -----------
* Given a raster image size, a view region size, and a pixel
* expansion factor, this routine will calculate the minimally
* sized 0-based rectangle needed to completely contain the
* described instance.
*
*
* Inputs:
* ------
* reInfoPtr = This must point to an instance of the xrRasterEditInfo
* structure, which defines a hypothetical raster edit
* instance.
*
* rectPtr = This must point to an instance of a RECTANGLE structure.
* The 0-based rectangle calculated by this procedure will
* be returned in that RECTANGLE structure.
*
* Outputs:
* -------
* Upon successful completion, a value of TRUE is returned, and the
* 0-based rectangle definition is returned in the structure
* pointed to by the 'rectPtr' parameter.
*
* Upon failure, FALSE is returned, an xrErrno is set.
*
* Procedures Called
* -----------------
* XrCopyRect() [calc.c]
*
*************************************<->***********************************/
static
sizeREdit (reInfoPtr, rectPtr)
register xrRasterEditInfo * reInfoPtr;
register RECTANGLE * rectPtr;
{
INT16 vHeight = reInfoPtr->viewRegion.height;
INT16 vWidth = reInfoPtr->viewRegion.width;
INT16 rHeight = reInfoPtr->rasterData.height;
INT16 rWidth = reInfoPtr->rasterData.width;
INT32 pixelSize = reInfoPtr->pixelSize;
/*
* Make sure the view region is at least 16 x 16, and
* also that the view region is NOT larger than the
* raster image.
*/
if ((vHeight < 16) || (vWidth < 16) ||
(vHeight > rHeight) || (vWidth > rWidth))
{
xrErrno = XrINVALIDPARM;
return (FALSE);
}
else if (pixelSize < 4)
{
xrErrno = XrPARMOUTOFRANGE;
return (FALSE);
}
/*
* The preliminary height of the editor rectangle is calculated
* using the following formula:
*
* ht = (viewRegion height * pixelSize) + (viewRegion height + 1)
* [ the second component takes the grid into account ]
*/
XrCopyRect (&xrZeroRect, rectPtr);
rectPtr->height = (vHeight * pixelSize) + (vHeight + 1);
/*
* The preliminary width of the editor rectangle is calculated
* using the following formula:
*
* width = (viewRegion width * pixelSize) + (viewRegion Width + 1)
* [ the second component take the grid into account ]
*/
rectPtr->width = (vWidth * pixelSize) + (vWidth + 1);
/*
* If the raster image width is larger than the view region width,
* then we need to take into account a horizontal scrollbar.
*/
if (rWidth > vWidth)
rectPtr->height += XrMIN_SCROLLBAR_HT + 2 + (pixelSize / 10);
/*
* If the raster image height is larger than the view region
* height, then we need to take into account a vertical scrollbar.
*/
if (rHeight > vHeight)
rectPtr->width += XrMIN_SCROLLBAR_WID + 2 + (pixelSize / 10);
return (TRUE);
}
\f
/*************************************<->*************************************
*
* createREdit (reDataPtr, reInfoPtr, message)
*
* xrRasterEditData * reDataPtr;
* xrRasterEditInfo * reInfoPtr;
* INT32 message;
*
* Description:
* -----------
* This routine takes a raster editor definition, contained in the
* structure pointed to by the 'reInfoPtr' parameter, and constructs
* all of the components necessary to create that instance. This
* includes filling in the structure pointed to by the 'reDataPtr'
* parameter, allocating a pixel extraction instance, and creating
* any needed scrollbars.
*
*
* Inputs:
* ------
* reDataPtr = This is a pointer to an instance of the xrRasterEditData
* structure, which will be filled in by this routine.
*
* reInfoPtr = This is a pointer to an instance of the xrRasterEditInfo
* structure, which must be completely filled out. The
* reDataPtr structure is filled out using information
* contained within this structure.
*
* message = This parameter is unused by this procedure.
*
* Outputs:
* -------
* Upon successful completion, a value of TRUE is returned, and the
* fields in the structure pointed to by the reDataPtr parameter
* will be filled.
*
* Upon failure, FALSE will be returned, and xrErrno set.
*
* Procedures Called
* -----------------
* XrCopyPt() [calc.c]
* _XrPixelExtract() [pixelExt.c]
* sizeREdit()
* createVScrollBar()
* createHScrollBar()
*
*************************************<->***********************************/
static
INT32
createREdit (reDataPtr, reInfoPtr, message)
register xrRasterEditData * reDataPtr;
register xrRasterEditInfo * reInfoPtr;
INT32 message;
{
INT32 depth;
RECTANGLE workRect;
/* Validate all parameters */
if (((depth = reInfoPtr->rasterData.depth) != XrBIT1) &&
(depth != XrBYTE1) && (depth != XrBYTE2) &&
(depth != XrBYTE3) && (depth != XrBYTE4))
{
xrErrno = XrINVALIDDEPTH;
return (FALSE);
}
else if (reInfoPtr->rasterData.raster == NULL)
{
xrErrno = XrINVALIDPTR;
return (FALSE);
}
/* Make sure a valid editor rectangle was specified */
if (sizeREdit (reInfoPtr, &workRect) == FALSE)
{
/* xrErrno is set by sizeREdit() */
return (FALSE);
}
else if ((reInfoPtr->editorRect.height < workRect.height) ||
(reInfoPtr->editorRect.width < workRect.width))
{
xrErrno = XrINVALIDRECT;
return (FALSE);
}
/* Initialize the pixel extraction routine */
if ((reDataPtr->extractionData = (xrPixelData *)
_XrPixelExtract (NULL, MSG_NEW, &reInfoPtr->rasterData)) == NULL)
{
/* xrErrno has already been set by _XrPixelExtract() */
return (FALSE);
}
/* Copy the rest of the information describing the instance */
reDataPtr->reFGColor = (reInfoPtr->editorFGColor == -1) ?
xrForegroundColor : reInfoPtr->editorFGColor;
reDataPtr->reBGColor = (reInfoPtr->editorBGColor == -1) ?
xrBackgroundColor : reInfoPtr->editorBGColor;
reDataPtr->pixelColor = reInfoPtr->pixelColor;
reDataPtr->pixelSize = reInfoPtr->pixelSize;
reDataPtr->vScrollbar = NULL;
reDataPtr->hScrollbar = NULL;
XrCopyPt (&xrZeroPt, &reDataPtr->viewOrigin);
_Xrmemcpy(&reDataPtr->viewRegion, &reInfoPtr->viewRegion, sizeof (SIZE));
_Xrmemcpy(&reDataPtr->rasterData, &reInfoPtr->rasterData, sizeof (xrPixmap));
/*
* Define the rectangle containing ONLY the editing region.
* It it tied to the upper left corner of the editor rectangle.
* width = Number of grid lines + (view width * pixelSize)
* height = Number of grid lines + (view height * pixelSize)
*/
reDataPtr->reRectangle.x = reInfoPtr->editorRect.x;
reDataPtr->reRectangle.y = reInfoPtr->editorRect.y;
reDataPtr->reRectangle.height = (reInfoPtr->viewRegion.height + 1) +
(reInfoPtr->viewRegion.height * reInfoPtr->pixelSize);
reDataPtr->reRectangle.width = (reInfoPtr->viewRegion.width + 1) +
(reInfoPtr->viewRegion.width * reInfoPtr->pixelSize);
/*
* If the height of the raster image is larger than the height
* of the view region, then create a vertical scrollbar. Tie its
* origin to the right edge of the editor rectangle.
*/
if (reInfoPtr->rasterData.height > reInfoPtr->viewRegion.height)
{
if (createVScrollBar (reInfoPtr, reDataPtr) == FALSE)
{
reFreeMemory (reDataPtr);
return (FALSE);
}
}
/*
* If the width of the raster image is larger than the width
* of the view region, then create a horizontal scrollbar. Tie
* its origin to the bottom of the editor rectangle.
*/
if (reInfoPtr->rasterData.width > reInfoPtr->viewRegion.width)
{
if (createHScrollBar (reInfoPtr, reDataPtr) == FALSE)
{
reFreeMemory (reDataPtr);
return (FALSE);
}
}
return (TRUE);
}
\f
/*************************************<->*************************************
*
* xrEditor *
* moveREdit (rasterEdit, ptPtr)
*
* xrEditor * rasterEdit;
* POINT * ptPtr;
*
* Description:
* -----------
* This routine will relocate all components of a raster editor
* instance. The new origin for the instance is specified in the
* POINT structure pointed to by the 'ptPtr' parameter. The
* components which must be moved are the editor rectangle, the
* editing region rectangle, and the scrollbars. If the instance
* is currently visible, then it will be redrawn at its new location
* after the move is complete.
*
*
* Inputs:
* ------
* rasterEdit = This is the instance pointer, and indicates which
* editor instance is to be moved.
*
* ptPtr = This is a pointer to a POINT structure, and contains the
* new editor rectangle origin.
*
* Outputs:
* -------
* Upon successful completion, the editor instance pointer is returned,
* and the editor instance is moved.
*
* Upon failure, NULL is returned, and xrErrno is set.
*
* Procedures Called
* -----------------
* XrCopyRect() [calc.c]
* XrOffsetRect() [calc.c]
* XrScrollBar() [ScrollBar.c]
* _XrMakeInvisible() [editorUtil.c]
* drawREdit()
*
*************************************<->***********************************/
static
xrEditor *
moveREdit (rasterEdit, ptPtr)
register xrEditor * rasterEdit;
POINT * ptPtr;
{
register xrRasterEditData * reDataPtr;
RECTANGLE workRect;
register INT16 xDelta;
register INT16 yDelta;
POINT sbOrigin;
if (rasterEdit == NULL)
{
xrErrno = XrINVALIDID;
return ((xrEditor *) NULL);
}
else if (ptPtr == NULL)
{
xrErrno = XrINVALIDPTR;
return ((xrEditor *) NULL);
}
/* Determine how much to relocate the instance by */
reDataPtr = (xrRasterEditData *) rasterEdit->editorData;
XrCopyRect (&rasterEdit->editorRect, &workRect);
xDelta = ptPtr->x - rasterEdit->editorRect.x;
yDelta = ptPtr->y - rasterEdit->editorRect.y;
/* Relocate each component of the raster editor instance */
XrOffsetRect (&rasterEdit->editorRect, xDelta, yDelta);
XrOffsetRect (&reDataPtr->reRectangle, xDelta, yDelta);
if (reDataPtr->vScrollbar)
{
if (rasterEdit->editorState & XrVISIBLE)
XrScrollBar (reDataPtr->vScrollbar, MSG_SETSTATE, 0);
sbOrigin.x = reDataPtr->vScrollbar->editorRect.x + xDelta;
sbOrigin.y = reDataPtr->vScrollbar->editorRect.y + yDelta;
XrScrollBar (reDataPtr->vScrollbar, MSG_MOVE, &sbOrigin);
}
if (reDataPtr->hScrollbar)
{
if (rasterEdit->editorState & XrVISIBLE)
XrScrollBar (reDataPtr->hScrollbar, MSG_SETSTATE, 0);
sbOrigin.x = reDataPtr->hScrollbar->editorRect.x + xDelta;
sbOrigin.y = reDataPtr->hScrollbar->editorRect.y + yDelta;
XrScrollBar (reDataPtr->hScrollbar, MSG_MOVE, &sbOrigin);
}
if (rasterEdit->editorState & XrVISIBLE)
{
/* Remove the instance from the window, if visible */
_XrMakeInvisible (rasterEdit->editorWindowId, &workRect, TRUE);
/* Redisplay the instance, if it was visible */
drawREdit (rasterEdit, NULL);
}
/* Force the editor group rectangle to be recalculated */
XrEditorGroup (NULL, MSG_ADJUSTGROUPRECT, rasterEdit);
return (rasterEdit);
}
\f
/*************************************<->*************************************
*
* xrEditor *
* resizeREdit (rasterEdit, rectPtr)
*
* xrEditor * rasterEdit;
* RECTANGLE * rectPtr;
*
* Description:
* -----------
* This routine will resize an existing raster edit instance. The
* application passes in a new editor rectangle definition, and the
* instance will be recalculated, such that it now fits within the
* new region; the same size restrictions which applied when the
* instance was created will apply. Resizing an instance involves
* moving the origin of the editor rectangle and the editing region
* rectangle; it also involves telling the scrollbar editor to
* move the scrollbar instances; they will continue to be tied to
* top right and bottom left corners of the editor rectangle.
*
*
* Inputs:
* ------
* rasterEdit = This is the instance pointer for the editor instance
* which is to be resized.
*
* rectPtr = This is a pointer to a RECTANGLE structure, containing
* the new size and location information for the instance.
*
* Outputs:
* -------
* Upon successful completion, the editor instance pointer will be
* returned, and the instance will have been resized, and
* redrawn (if it was visible).
*
* Upon failure, NULL is returned, and xrErrno is set.
*
* Procedures Called
* -----------------
* XrScrollBar() [ScrollBar.c]
* _XrMakeInvisible() [editorUtil.c]
* XrSetPt() [calc.c]
* drawREdit()
* sizeREdit()
*
*************************************<->***********************************/
static
xrEditor *
resizeREdit (rasterEdit, rectPtr)
register xrEditor * rasterEdit;
register RECTANGLE * rectPtr;
{
RECTANGLE tempRect;
xrRasterEditInfo reInfo;
POINT vSBOrigin;
POINT hSBOrigin;
register xrRasterEditData * reDataPtr;
/* Check for invalid parameters */
if (rasterEdit == NULL)
{
xrErrno = XrINVALIDID;
return ((xrEditor *) NULL);
}
else if (rectPtr == NULL)
{
xrErrno = XrINVALIDPTR;
return ((xrEditor *) NULL);
}
/* Set up a pseudo info structure to pass to sizeREdit() */
reDataPtr = (xrRasterEditData *) rasterEdit->editorData;
reInfo.pixelSize = reDataPtr->pixelSize;
reInfo.viewRegion.height = reDataPtr->viewRegion.height;
reInfo.viewRegion.width = reDataPtr->viewRegion.width;
reInfo.rasterData.height = reDataPtr->rasterData.height;
reInfo.rasterData.width = reDataPtr->rasterData.width;
/* Check for an invalid editor rectangle definition */
if (sizeREdit (&reInfo, &tempRect) == FALSE)
{
/* This better not ever fail here !! */
return ((xrEditor *) NULL);
}
else if ((rectPtr->height < tempRect.height) ||
(rectPtr->width < tempRect.width))
{
xrErrno = XrINVALIDRECT;
return ((xrEditor *) NULL);
}
/* Remove the old instance, if visible */
if (rasterEdit->editorState & XrVISIBLE)
{
XrScrollBar (reDataPtr->vScrollbar, MSG_SETSTATE,
rasterEdit->editorState & ~XrVISIBLE);
XrScrollBar (reDataPtr->hScrollbar, MSG_SETSTATE,
rasterEdit->editorState & ~XrVISIBLE);
_XrMakeInvisible (rasterEdit->editorWindowId,
&rasterEdit->editorRect, TRUE);
}
/* Move each component in the raster editor instance */
/* Move the editor rectangle */
rasterEdit->editorRect.x = rectPtr->x;
rasterEdit->editorRect.y = rectPtr->y;
rasterEdit->editorRect.height = rectPtr->height;
rasterEdit->editorRect.width = rectPtr->width;
/* Move the editing region rectangle */
reDataPtr->reRectangle.x = rectPtr->x;
reDataPtr->reRectangle.y = rectPtr->y;
/* Move the vertical scrollbar */
if (reDataPtr->vScrollbar)
{
XrSetPt (&vSBOrigin, (rectPtr->x + rectPtr->width - 1) -
reDataPtr->vScrollbar->editorRect.width,
rectPtr->y);
XrScrollBar (reDataPtr->vScrollbar, MSG_MOVE, &vSBOrigin);
}
/* Move the horizontal scrollbar */
if (reDataPtr->hScrollbar)
{
XrSetPt (&hSBOrigin, rectPtr->x,
(rectPtr->y + rectPtr->height - 1) -
reDataPtr->hScrollbar->editorRect.height);
XrScrollBar (reDataPtr->hScrollbar, MSG_MOVE, &hSBOrigin);
}
/* Redraw the instance, if visible */
if (rasterEdit->editorState & XrVISIBLE)
drawREdit (rasterEdit, NULL);
/* Force the editor group rectangle to be recalculated */
XrEditorGroup (NULL, MSG_ADJUSTGROUPRECT, rasterEdit);
return (rasterEdit);
}
\f
/*************************************<->*************************************
*
* xrEditor *
* positionREdit (rasterEdit, position)
*
* Description:
* -----------
* This routine allow a new view origin to be specified; the view
* origin is the coordinates of the pixel which is displayed in the
* upper left corner of the editing region. The value will be
* ignored if it meant that the visible portion of the raster image
* is smaller than the view region. After setting the new view
* origin, the instance will be redrawn, if it was visible.
*
*
* Inputs:
* ------
* rasterEdit = This points to the editor instance structure for the
* instance which is to be modified.
*
* position = This points to a POINT structure, which contains the
* new view origin point. This point will be displayed
* in the upper left square in the editing region.
*
* Outputs:
* -------
* Upon successful completion, the editor instance pointer is returned,
* the new view origin is set, and the instance is redraw, if it
* was visible.
*
* Upon failure, NULL is returned, and xrErrno is set.
*
* Procedures Called
* -----------------
* XrCopyPt() [calc.c]
* XrScrollBar() [calc.c]
* drawColorBoxes()
*
*************************************<->***********************************/
static
xrEditor *
positionREdit (rasterEdit, position)
xrEditor * rasterEdit;
register POINT * position;
{
register xrRasterEditData * reDataPtr;
if (rasterEdit == NULL)
{
xrErrno = XrINVALIDID;
return ((xrEditor *) NULL);
}
else if (position == NULL)
{
xrErrno = XrINVALIDPTR;
return ((xrEditor *) NULL);
}
/*
* Verify the location falls within the bounds of the raster image,
* and also still allows the complete view region to be filled.
*/
reDataPtr = (xrRasterEditData *) rasterEdit->editorData;
if ((position->x < 0) || (position->y < 0) ||
(position->x > (reDataPtr->rasterData.width -
reDataPtr->viewRegion.width) ||
(position->y > (reDataPtr->rasterData.height -
reDataPtr->viewRegion.height))))
{
xrErrno = XrINVALIDPARM;
return ((xrEditor *) NULL);
}
XrCopyPt (position, &reDataPtr->viewOrigin);
/* Reposition scrollbar, and redraw the instance */
if (reDataPtr->vScrollbar)
{
reDataPtr->vSBParameters.slidePosition = reDataPtr->viewOrigin.y;
XrScrollBar (reDataPtr->vScrollbar, MSG_SETPARAMETERS,
&reDataPtr->vSBParameters);
}
if (reDataPtr->hScrollbar)
{
reDataPtr->hSBParameters.slidePosition = reDataPtr->viewOrigin.x;
XrScrollBar (reDataPtr->hScrollbar, MSG_SETPARAMETERS,
&reDataPtr->hSBParameters);
}
if (rasterEdit->editorState & XrVISIBLE)
drawColorBoxes (rasterEdit, reDataPtr->viewOrigin.x,
reDataPtr->viewOrigin.y,
reDataPtr->viewOrigin.x + reDataPtr->viewRegion.width -1,
reDataPtr->viewOrigin.y + reDataPtr->viewRegion.height - 1);
return (rasterEdit);
}
\f
/*************************************<->*************************************
*
* createVScrollBar (reInfoPtr, reDataPtr)
*
* xrRasterEditInfo * reInfoPtr;
* xrRasterEditData * reDataPtr;
*
* Description:
* -----------
* This routine attempts to create a vertical scrollbar, whose height
* is equal to the height of the raster editing region. The scroll
* units are calculated with a min value of 0, and a max value equal
* the to raster image height - the view region height. The scrollbar
* is created invisible, so that the raster editor can draw it at the
* proper time. After the scrollbar is created, it is unattached from
* the window's editor list, so that XrInput() will not ever pass
* input events to it; only the raster editor should pass input events
* to it.
*
*
* Inputs:
* ------
* reInfoPtr = This is a pointer to the 'info' structure for the
* raster edit instance being created. It is used by
* this routine to calculate the size and scroll unit
* values for the scrollbar being created.
*
* reDataPtr = This is a pointer to the internal 'data' structure
* for the raster edit instance being created. Both
* the editor instance pointer for the new scrollbar
* and the scrollbar configuration values will be
* stored in this structure.
*
* Outputs:
* -------
* Upon successful completion, TRUE will be returned, and a vertical
* scrollbar will be created.
*
* Upon failure, FALSE will be returned, and xrErrno set.
*
* Procedures Called
* -----------------
* XrScrollBar() [ScrollBar.c]
* XrEditor() [editor.c]
*
*************************************<->***********************************/
static
INT32
createVScrollBar (reInfoPtr, reDataPtr)
register xrRasterEditInfo * reInfoPtr;
register xrRasterEditData * reDataPtr;
{
xrScrollBarInfo sbInfo;
register xrSBParameters * config;
/* Fill out the 'info' structure used to create the scrollbar */
sbInfo.editorWindowId = reInfoPtr->editorWindowId;
sbInfo.editorState = 0;
sbInfo.editorFGColor = reInfoPtr->editorFGColor;
sbInfo.editorBGColor = reInfoPtr->editorBGColor;
sbInfo.orientation = XrVERTICAL;
/* Fill the 'configuration' portion of the 'init' structure */
config = &sbInfo.configuration;
config->components = XrSCROLLARROWS | XrSLIDEBOX;
config->min = 0;
config->max = reInfoPtr->rasterData.height -
reInfoPtr->viewRegion.height;
config->slidePosition = 0;
config->slideSize = config->max / 10;
if (config->slideSize <= 0) config->slideSize = 1;
config->handler = NULL;
_Xrmemcpy (&reDataPtr->vSBParameters, config, sizeof (xrSBParameters));
/* Calculate the editor rectangle for this instance */
sbInfo.editorRect.width = XrMIN_SCROLLBAR_WID + 2 +
(reDataPtr->pixelSize / 10);
XrScrollBar (NULL, MSG_SIZE, &sbInfo);
sbInfo.editorRect.x = reInfoPtr->editorRect.x +
reInfoPtr->editorRect.width - 1 -
sbInfo.editorRect.width;
sbInfo.editorRect.y = reInfoPtr->editorRect.y;
sbInfo.editorRect.height = reDataPtr->reRectangle.height;
/* Create the editor instance */
if ((reDataPtr->vScrollbar = XrScrollBar (NULL, MSG_NEW, &sbInfo)) == NULL)
return (FALSE);
XrEditor (reInfoPtr->editorWindowId, MSG_REMOVE, reDataPtr->vScrollbar);
return (TRUE);
}
\f
/*************************************<->*************************************
*
* createHScrollBar (reInfoPtr, reDataPtr)
*
* xrRasterEditInfo * reInfoPtr;
* xrRasterEditData * reDataPtr;
*
* Description:
* -----------
* This routine attempts to create a horizontal scrollbar, whose width
* is equal to the width of the raster editing region. The scroll
* units are calculated with a min value of 0, and a max value equal
* the to raster image width - the view region width. The scrollbar
* is created invisible, so that the raster editor can draw it at the
* proper time. After the scrollbar is created, it is unattached from
* the window's editor list, so that XrInput() will not ever pass
* input events to it; only the raster editor should pass input events
* to it.
*
*
* Inputs:
* ------
* reInfoPtr = This is a pointer to the 'info' structure for the
* raster edit instance being created. It is used by
* this routine to calculate the size and scroll unit
* values for the scrollbar being created.
*
* reDataPtr = This is a pointer to the internal 'data' structure
* for the raster edit instance being created. Both
* the editor instance pointer for the new scrollbar
* and the scrollbar configuration values will be
* stored in this structure.
*
* Outputs:
* -------
* Upon successful completion, TRUE will be returned, and a horizontal
* scrollbar will be created.
*
* Upon failure, FALSE will be returned, and xrErrno set.
*
* Procedures Called
* -----------------
* XrScrollBar() [ScrollBar.c]
* XrEditor() [editor.c]
*
*************************************<->***********************************/
static
INT32
createHScrollBar (reInfoPtr, reDataPtr)
register xrRasterEditInfo * reInfoPtr;
register xrRasterEditData * reDataPtr;
{
xrScrollBarInfo sbInfo;
register xrSBParameters * config;
/* Fill out the 'info' structure used to create the scrollbar */
sbInfo.editorWindowId = reInfoPtr->editorWindowId;
sbInfo.editorState = 0;
sbInfo.editorFGColor = reInfoPtr->editorFGColor;
sbInfo.editorBGColor = reInfoPtr->editorBGColor;
sbInfo.orientation = XrHORIZONTAL;
/* Fill the 'configuration' portion of the 'init' structure */
config = &sbInfo.configuration;
config->components = XrSCROLLARROWS | XrSLIDEBOX;
config->min = 0;
config->max = reInfoPtr->rasterData.width -
reInfoPtr->viewRegion.width;
config->slidePosition = 0;
config->slideSize = config->max / 10;
if (config->slideSize <= 0) config->slideSize = 1;
config->handler = NULL;
_Xrmemcpy (&reDataPtr->hSBParameters, config, sizeof (xrSBParameters));
/* Calculate the editor rectangle for this instance */
sbInfo.editorRect.height = XrMIN_SCROLLBAR_HT + 2 +
(reDataPtr->pixelSize / 10);
XrScrollBar (NULL, MSG_SIZE, &sbInfo);
sbInfo.editorRect.x = reInfoPtr->editorRect.x;
sbInfo.editorRect.y = reInfoPtr->editorRect.y +
reInfoPtr->editorRect.height - 1 -
sbInfo.editorRect.height;
sbInfo.editorRect.width = reDataPtr->reRectangle.width;
/* Create the editor instance */
if ((reDataPtr->hScrollbar = XrScrollBar (NULL, MSG_NEW, &sbInfo)) == NULL)
return (FALSE);
XrEditor (reInfoPtr->editorWindowId, MSG_REMOVE, reDataPtr->hScrollbar);
return (TRUE);
}
\f
/*************************************<->*************************************
*
* drawREdit (rasterEdit, drawOption)
*
* Description:
* -----------
* This routine is responsible for drawing a raster editor instance,
* if it is visible, or for covering it with the window's background
* tile if it is not visible.
*
*
* Inputs:
* ------
* rasterEdit = This is a pointer to the editor instance structure,
* which contains all the data needed to draw the raster
* edit instance.
*
* drawOption = This parameter is unused.
*
* Outputs:
* -------
*
* Procedures Called
* -----------------
* _XrMakeInvisible() [editorUtil.c]
* XrScrollBar() [ScrollBar.c]
* drawGrid()
* drawColorBoxes()
*
*************************************<->***********************************/
static
INT32
drawREdit (rasterEdit, drawOption)
register xrEditor * rasterEdit;
INT32 drawOption;
{
register xrRasterEditData * reDataPtr;
Window windowId = rasterEdit->editorWindowId;
reDataPtr = (xrRasterEditData *) rasterEdit->editorData;
/*
* If the instance is not visible, then fill its area with the
* background tile for the window, thus making the instance invisible.
*/
if (!(rasterEdit->editorState & XrVISIBLE))
{
_XrMakeInvisible (windowId, &rasterEdit->editorRect, TRUE);
return;
}
/* Initialize the graphics context we will be needing */
_XrInitEditorGCs (reDataPtr->reFGColor, reDataPtr->reBGColor, -1);
/* Draw the editing region grid */
drawGrid (rasterEdit, reDataPtr);
/* Fill the editing rectangles */
drawColorBoxes (rasterEdit, reDataPtr->viewOrigin.x,
reDataPtr->viewOrigin.y,
reDataPtr->viewOrigin.x + reDataPtr->viewRegion.width - 1,
reDataPtr->viewOrigin.y + reDataPtr->viewRegion.height - 1);
/* Draw the scrollbars */
if (reDataPtr->vScrollbar)
XrScrollBar (reDataPtr->vScrollbar, MSG_SETSTATE,
XrSENSITIVE | XrVISIBLE);
if (reDataPtr->hScrollbar)
XrScrollBar (reDataPtr->hScrollbar, MSG_SETSTATE,
XrSENSITIVE | XrVISIBLE);
}
\f
/*************************************<->*************************************
*
* drawGrid (rasterEdit, reDataPtr)
*
* Description:
* -----------
* This routine will draw the editing region grid.
*
*
* Inputs:
* ------
* rasterEdit = This points to the editor instance structure. The
* window Id is extracted from it.
*
* reDataPtr = This is a pointer to the editor instance's internal
* 'data' structure. The editing region dimensions, and
* the pixel size values are obtained from it.
*
* Outputs:
* -------
*
* Procedures Called
* -----------------
* _XrLine() [rectUtil.c]
*
*************************************<->***********************************/
static
INT32
drawGrid (rasterEdit, reDataPtr)
register xrEditor * rasterEdit;
register xrRasterEditData * reDataPtr;
{
register INT32 x1, x2, y1, y2;
/* Draw the horizontal grid lines */
for (x1 = reDataPtr->reRectangle.x,
x2 = x1 + reDataPtr->reRectangle.width - 1,
y1 = reDataPtr->reRectangle.y;
y1 < reDataPtr->reRectangle.y + reDataPtr->reRectangle.height;
y1 += reDataPtr->pixelSize + 1)
{
_XrLine (rasterEdit->editorWindowId, xrEditorGC1, x1, y1, x2, y1);
}
/* Draw the vertical grid lines */
for (y1 = reDataPtr->reRectangle.y,
y2 = y1 + reDataPtr->reRectangle.height - 1,
x1 = reDataPtr->reRectangle.x;
x1 < reDataPtr->reRectangle.x + reDataPtr->reRectangle.width;
x1 += reDataPtr->pixelSize + 1)
{
_XrLine (rasterEdit->editorWindowId, xrEditorGC1, x1, y1, x1, y2);
}
}
\f
/*************************************<->*************************************
*
* drawColorBoxes (rasterEdit, xStart, yStart, xEnd, yEnd)
*
* xrEditor * rasterEdit;
* INT32 xStart, yStart;
* INT32 xEnd, yEnd;
*
* Description:
* -----------
* This routine updates a rectangular region of the the raster
* editing region. The four Start/End parameters specify the
* starting and ending row/columns which are to be updated.
* These values refer to a row and column within the raster image;
* not within the editing region. The colors are automatically
* mapped to their proper location within the editing region. It
* is up to the routine calling this to make sure that the region
* being drawn lies completely within the view region.
* If xStart = xEnd and yStart = yEnd, then only a single pixel is
* drawn.
*
*
* Inputs:
* ------
* rasterEdit = This points to the instance's editor structure.
*
* xStart, yStart = This specifies the starting column and row.
*
* xEnd, yEnd = This specifies the ending column and row.
*
* Outputs:
* -------
*
* Procedures Called
* -----------------
* XPixSet() [libX.a]
* XrSetPt() [calc.c]
* _XrPixelExtract() [pixelExt.c]
*
*************************************<->***********************************/
static
INT32
drawColorBoxes (rasterEdit, xStart, yStart, xEnd, yEnd)
xrEditor * rasterEdit;
INT32 xStart;
INT32 yStart;
INT32 xEnd;
INT32 yEnd;
{
Window windowId;
register xrRasterEditData * reDataPtr;
INT32 pixelSize;
POINT extractionLoc;
INT32 pixelValue;
register INT32 i, j;
register INT32 xOrigin;
register INT32 yOrigin;
register xrPixelData * instance;
/* Initialize variables */
windowId = rasterEdit->editorWindowId;
reDataPtr = (xrRasterEditData *) rasterEdit->editorData;
pixelSize = reDataPtr->pixelSize;
instance = reDataPtr->extractionData;
/* Redraw the request region, one row at a time */
yOrigin = reDataPtr->reRectangle.y + 1 +
((yStart - reDataPtr->viewOrigin.y) * (pixelSize + 1));
for (i = yStart; i <= yEnd; i++)
{
/* Set the pixel extraction location */
XrSetPt (&extractionLoc, xStart, i);
_XrPixelExtract (instance, MSG_LOCATION, &extractionLoc);
xOrigin = reDataPtr->reRectangle.x + 1 +
((xStart - reDataPtr->viewOrigin.x) * (pixelSize + 1));
/* Redraw one row */
for (j = xStart; j <= xEnd; j++)
{
_XrPixelExtract (instance, MSG_GETVALUE, &pixelValue);
XPixSet (windowId, xOrigin, yOrigin, pixelSize,
pixelSize, pixelValue);
xOrigin += pixelSize + 1;
}
yOrigin += pixelSize + 1;
}
}
\f
/*************************************<->*************************************
*
* scrollImage (windowId, reDataPtr, scrollDirection)
*
* Window windowId;
* xrRasterEditData * reDataPtr;
* INT32 scrollDirection;
*
* Description:
* -----------
* This routine will scroll the pixels within the editing region
* one pixel in any direction, as specified by the 'scrollDirection'
* parameter. Fast scrolling is accomplished by using the XMoveArea()
* library routine to move the area of the editing region which is
* not changing, except for its location, and then only redrawing the
* new row or column which just became visible; note: only the scrolling
* is done here; the redrawing of the new row/column is done elsewhere.
*
*
* Inputs:
* ------
* windowId = This is the window Id for the window in which the raster
* editor instance resides.
*
* reDataPtr = This points to the instance's internal 'data' structure.
*
* scrollDirection = The direction in which the editing region data is
* to be scrolled. It can be assigned any of the
* following values: XrSCROLL_UP, XrSCROLL_DOWN,
* XrSCROLL_LEFT or XrSCROLL_RIGHT.
*
* Outputs:
* -------
*
* Procedures Called
* -----------------
* XMoveArea() [libX.a]
*
*************************************<->***********************************/
static
INT32
scrollImage (windowId, reDataPtr, scrollDirection)
Window windowId;
register xrRasterEditData * reDataPtr;
INT32 scrollDirection;
{
INT32 srcX, srcY;
INT32 dstX, dstY;
INT32 height;
INT32 width;
INT32 pixelSize = reDataPtr->pixelSize;
/* Do a fast scroll, by moving an area of the window */
switch (scrollDirection)
{
case XrSCROLL_UP:
{
srcX = reDataPtr->reRectangle.x;
srcY = reDataPtr->reRectangle.y;
dstX = reDataPtr->reRectangle.x;
dstY = reDataPtr->reRectangle.y + pixelSize + 1;
height = (pixelSize + 1) * (reDataPtr->viewRegion.height - 1);
width = (pixelSize + 1) * reDataPtr->viewRegion.width;
break;
}
case XrSCROLL_DOWN:
{
srcX = reDataPtr->reRectangle.x;
srcY = reDataPtr->reRectangle.y + pixelSize + 1;
dstX = reDataPtr->reRectangle.x;
dstY = reDataPtr->reRectangle.y;
height = (pixelSize + 1) * (reDataPtr->viewRegion.height - 1);
width = (pixelSize + 1) * reDataPtr->viewRegion.width;
break;
}
case XrSCROLL_LEFT:
{
srcX = reDataPtr->reRectangle.x;
srcY = reDataPtr->reRectangle.y;
dstX = reDataPtr->reRectangle.x + pixelSize + 1;
dstY = reDataPtr->reRectangle.y;
height = (pixelSize + 1) * reDataPtr->viewRegion.height;
width = (pixelSize + 1) * (reDataPtr->viewRegion.width - 1);
break;
}
case XrSCROLL_RIGHT:
{
srcX = reDataPtr->reRectangle.x + pixelSize + 1;
srcY = reDataPtr->reRectangle.y;
dstX = reDataPtr->reRectangle.x;
dstY = reDataPtr->reRectangle.y;
height = (pixelSize + 1) * reDataPtr->viewRegion.height;
width = (pixelSize + 1) * (reDataPtr->viewRegion.width - 1);
break;
}
}
XMoveArea (windowId, srcX, srcY, dstX, dstY, width, height);
}
\f
/*************************************<->*************************************
*
* processREdit (rasterEdit, event, returnEvent)
*
* xrEditor * rasterEdit;
* XButtonEvent * event;
* xrEvent * returnEvent;
*
* Description:
* -----------
* This is the main event processing routine for the raster edit editor.
* It is invoked anytime an XrSELECT event occurs within a raster edit
* instance. It will determine which region of the raster editor the
* event occurred in (editing region, scrollbars or background), and
* will then call the appropriate handling routine.
*
*
* Inputs:
* ------
* rasterEdit = This points to the instance's editor structure.
*
* event = This is the X select event.
*
* returnEvent = This is a pointer to the xrEvent structure which will
* be returned to the application upon completion of our
* processing of the received X event.
*
* Outputs:
* -------
* The value1 field within the return event will be filled.
*
* Procedures Called
* -----------------
* XrPtInRect() [calc.c]
* XrSetPt() [calc.c]
* XrCopyRect() [calc.c]
* paintREdit()
* processVScrollbar()
* processHScrollbar()
*
*************************************<->***********************************/
static
INT32
processREdit (rasterEdit, event, returnEvent)
xrEditor * rasterEdit;
XButtonEvent * event;
xrEvent * returnEvent;
{
register xrRasterEditData * reDataPtr;
POINT spritePt;
RECTANGLE workRect;
/* Initialize variables */
reDataPtr = (xrRasterEditData *) rasterEdit->editorData;
XrSetPt (&spritePt, event->x, event->y);
/* Exclude the bottom and right grid lines */
XrCopyRect (&reDataPtr->reRectangle, &workRect);
workRect.height -= 1;
workRect.width -= 1;
/*
* Determine which component of the raster editor the
* select occurred in, and process it accordingly.
*/
if (XrPtInRect (&spritePt, &workRect))
{
paintREdit (rasterEdit, reDataPtr, &spritePt, &workRect);
returnEvent->value1 = XrSELECT;
}
else if ((reDataPtr->vScrollbar) &&
(XrPtInRect (&spritePt, &reDataPtr->vScrollbar->editorRect)))
{
processVScrollbar (rasterEdit, reDataPtr, event, returnEvent);
returnEvent->value1 = XrSCROLLBAR;
}
else if ((reDataPtr->hScrollbar) &&
(XrPtInRect (&spritePt, &reDataPtr->hScrollbar->editorRect)))
{
processHScrollbar (rasterEdit, reDataPtr, event, returnEvent);
returnEvent->value1 = XrSCROLLBAR;
}
else
/* Unimportant region */
returnEvent->value1 = NULL;
}
\f
/*************************************<->*************************************
*
* processVScrollbar (rasterEdit, reDataPtr, event, returnEvent)
*
* xrEditor * rasterEdit;
* xrRasterEditData * reDataPtr;
* XButtonEvent * event;
* xrEvent * returnEvent;
*
* Description:
* -----------
* This routine will process any select events which occur within the
* vertical scrollbar. This is done by passing the event to the
* scrollbar editor, then grabbing the event generated by the scrollbar
* editor. Using the scroll information within the event, it will either
* scroll the raster area 1 pixel up or down, or it will redraw the
* whole editing region if the user moved the slide box or selected
* a location within the slide region. Upon completion of the scroll
* operation, the new view region origin will be copied into the
* 'valuePt' field within the xrEvent structure pointed to by the
* 'returnEvent' parameter.
*
*
* Inputs:
* ------
* rasterEdit = This points to the instance's editor structure.
*
* reDataPtr = This points to the instance's internal 'data' structure.
*
* event = This points to the X select event.
*
* returnEvent = This points to the xrEvent structure which will be
* returned to the application upon completion of the
* scroll operation.
*
* Outputs:
* -------
* The 'valuePt' field within the structure pointed to by the
* 'returnEvent' parameter will be filled with the new view origin.
*
* Procedures Called
* -----------------
* XrScrollBar() [ScrollBar.c]
* XrInput() [input.c]
* XrCopyPt() [calc.c]
* scrollImage()
* drawColorBoxes()
*
*************************************<->***********************************/
static
INT32
processVScrollbar (rasterEdit, reDataPtr, event, returnEvent)
xrEditor * rasterEdit;
register xrRasterEditData * reDataPtr;
XButtonEvent * event;
xrEvent * returnEvent;
{
Window windowId = rasterEdit->editorWindowId;
xrEvent scrollEvent;
register POINT * viewOrigin = &reDataPtr->viewOrigin;
register SIZE * viewRegion = &reDataPtr->viewRegion;
xrEvent input;
struct timeval origTime;
struct timeval newTime;
INT16 firstPass;
xrWindowEvent windowEvent;
XButtonEvent selectUp;
/* Let the scrollbar editor handle the event */
XrScrollBar (reDataPtr->vScrollbar, MSG_EDIT, event);
/* Process the event generated by the scrollbar editor */
XrInput (NULL, MSG_NONBLKREAD, &scrollEvent);
XrInput (NULL, MSG_GETTIMEOUT, &origTime);
newTime.tv_sec = 0;
newTime.tv_usec = 500000;
firstPass = TRUE;
switch (scrollEvent.value1)
{
case XrSCROLL_UP:
{
/* Scroll the raster image down 1 pixel */
XrInput (NULL, MSG_SETTIMEOUT, &newTime);
while (1)
{
if (viewOrigin->y > 0)
{
viewOrigin->y -= 1;
reDataPtr->vSBParameters.slidePosition = viewOrigin->y;
XrScrollBar (reDataPtr->vScrollbar, MSG_SETPARAMETERS,
&reDataPtr->vSBParameters);
scrollImage (windowId, reDataPtr, XrSCROLL_UP);
drawColorBoxes (rasterEdit, viewOrigin->x, viewOrigin->y,
viewOrigin->x + viewRegion->width - 1,
viewOrigin->y);
}
if (XrInput (NULL, MSG_BLKREAD, &input) != FALSE)
{
XrInput (NULL, MSG_PUSHEVENT, &input);
break;
}
else if (firstPass)
{
newTime.tv_sec = 0;
newTime.tv_usec = 100000;
XrInput (NULL, MSG_SETTIMEOUT, &newTime);
firstPass = FALSE;
}
}
break;
}
case XrSCROLL_DOWN:
{
/* Scroll the raster image up 1 pixel */
XrInput (NULL, MSG_SETTIMEOUT, &newTime);
while (1)
{
if (viewOrigin->y <
(reDataPtr->rasterData.height - viewRegion->height))
{
viewOrigin->y += 1;
reDataPtr->vSBParameters.slidePosition = viewOrigin->y;
XrScrollBar (reDataPtr->vScrollbar, MSG_SETPARAMETERS,
&reDataPtr->vSBParameters);
scrollImage (windowId, reDataPtr, XrSCROLL_DOWN);
drawColorBoxes (rasterEdit, viewOrigin->x,
viewOrigin->y + viewRegion->height - 1,
viewOrigin->x + viewRegion->width - 1,
viewOrigin->y + viewRegion->height - 1);
}
if (XrInput (NULL, MSG_BLKREAD, &input) != FALSE)
{
XrInput (NULL, MSG_PUSHEVENT, &input);
break;
}
else if (firstPass)
{
newTime.tv_sec = 0;
newTime.tv_usec = 100000;
XrInput (NULL, MSG_SETTIMEOUT, &newTime);
firstPass = FALSE;
}
}
break;
}
case XrSCROLL_SLIDE:
{
/* Set the view origin to the selected position */
viewOrigin->y = scrollEvent.value2;
drawColorBoxes (rasterEdit, viewOrigin->x, viewOrigin->y,
viewOrigin->x + viewRegion->width -1,
viewOrigin->y + viewRegion->height - 1);
/* Push on a fake select up event */
XrGetWindowEvent (XrSELECTUP, &windowEvent);
selectUp.type = windowEvent.inputType;
selectUp.detail = windowEvent.inputCode;
XrInput (NULL, MSG_PUSHEVENT, &selectUp);
break;
}
case XrSCROLL_LESS:
case XrSCROLL_MORE:
{
/* Set the view origin to the selected position */
viewOrigin->y = scrollEvent.value3;
reDataPtr->vSBParameters.slidePosition = viewOrigin->y;
XrScrollBar (reDataPtr->vScrollbar, MSG_SETPARAMETERS,
&reDataPtr->vSBParameters);
drawColorBoxes (rasterEdit, viewOrigin->x, viewOrigin->y,
viewOrigin->x + viewRegion->width -1,
viewOrigin->y + viewRegion->height - 1);
/* Push on a fake select up event */
XrGetWindowEvent (XrSELECTUP, &windowEvent);
selectUp.type = windowEvent.inputType;
selectUp.detail = windowEvent.inputCode;
XrInput (NULL, MSG_PUSHEVENT, &selectUp);
break;
}
}
/* Set up the view origin return value */
XrCopyPt (viewOrigin, &returnEvent->valuePt);
XrInput (NULL, MSG_SETTIMEOUT, &origTime);
}
\f
/*************************************<->*************************************
*
* processHScrollbar (rasterEdit, reDataPtr, event, returnEvent)
*
* xrEditor * rasterEdit;
* xrRasterEditData * reDataPtr;
* XButtonEvent * event;
* xrEvent * returnEvent;
*
* Description:
* -----------
* This routine will process any select events which occur within the
* horizontal scrollbar. This is done by passing the event to the
* scrollbar editor, then grabbing the event generated by the scrollbar
* editor. Using the scroll information within the event, it will either
* scroll the raster area 1 pixel right or left, or it will redraw the
* whole editing region if the user moved the slide box or selected
* a location within the slide region. Upon completion of the scroll
* operation, the new view region origin will be copied into the
* 'valuePt' field within the xrEvent structure pointed to by the
* 'returnEvent' parameter.
*
*
* Inputs:
* ------
* rasterEdit = This points to the instance's editor structure.
*
* reDataPtr = This points to the instance's internal 'data' structure.
*
* event = This points to the X select event.
*
* returnEvent = This points to the xrEvent structure which will be
* returned to the application upon completion of the
* scroll operation.
*
* Outputs:
* -------
* The 'valuePt' field within the structure pointed to by the
* 'returnEvent' parameter will be filled with the new view origin.
*
* Procedures Called
* -----------------
* XrScrollBar() [ScrollBar.c]
* XrInput() [input.c]
* XrCopyPt() [calc.c]
* scrollImage()
* drawColorBoxes()
*
*************************************<->***********************************/
static
INT32
processHScrollbar (rasterEdit, reDataPtr, event, returnEvent)
xrEditor * rasterEdit;
register xrRasterEditData * reDataPtr;
XButtonEvent * event;
xrEvent * returnEvent;
{
Window windowId = rasterEdit->editorWindowId;
xrEvent scrollEvent;
register POINT * viewOrigin = &reDataPtr->viewOrigin;
register SIZE * viewRegion = &reDataPtr->viewRegion;
xrEvent input;
INT16 firstPass;
struct timeval origTime;
struct timeval newTime;
xrWindowEvent windowEvent;
XButtonEvent selectUp;
/* Let the scrollbar editor handle the event */
XrScrollBar (reDataPtr->hScrollbar, MSG_EDIT, event);
/* Process the event generated by the scrollbar editor */
XrInput (NULL, MSG_NONBLKREAD, &scrollEvent);
XrInput (NULL, MSG_GETTIMEOUT, &origTime);
newTime.tv_sec = 0;
newTime.tv_usec = 500000;
firstPass = TRUE;
switch (scrollEvent.value1)
{
case XrSCROLL_LEFT:
{
/* Scroll the raster image left 1 pixel */
XrInput (NULL, MSG_SETTIMEOUT, &newTime);
while (1)
{
if (viewOrigin->x > 0)
{
viewOrigin->x -= 1;
reDataPtr->hSBParameters.slidePosition = viewOrigin->x;
XrScrollBar (reDataPtr->hScrollbar, MSG_SETPARAMETERS,
&reDataPtr->hSBParameters);
scrollImage (windowId, reDataPtr, XrSCROLL_LEFT);
drawColorBoxes (rasterEdit, viewOrigin->x, viewOrigin->y,
viewOrigin->x,
viewOrigin->y + viewRegion->height - 1);
}
if (XrInput (NULL, MSG_BLKREAD, &input) != FALSE)
{
XrInput (NULL, MSG_PUSHEVENT, &input);
break;
}
else if (firstPass)
{
newTime.tv_sec = 0;
newTime.tv_usec = 100000;
XrInput (NULL, MSG_SETTIMEOUT, &newTime);
firstPass = FALSE;
}
}
break;
}
case XrSCROLL_RIGHT:
{
/* Scroll the raster image right 1 pixel */
XrInput (NULL, MSG_SETTIMEOUT, &newTime);
while (1)
{
if (viewOrigin->x <
(reDataPtr->rasterData.width - viewRegion->width))
{
viewOrigin->x += 1;
reDataPtr->hSBParameters.slidePosition = viewOrigin->x;
XrScrollBar (reDataPtr->hScrollbar, MSG_SETPARAMETERS,
&reDataPtr->hSBParameters);
scrollImage (windowId, reDataPtr, XrSCROLL_RIGHT);
drawColorBoxes (rasterEdit,viewOrigin->x+viewRegion->width - 1,
viewOrigin->y,
viewOrigin->x + viewRegion->width - 1,
viewOrigin->y + viewRegion->height - 1);
}
if (XrInput (NULL, MSG_BLKREAD, &input) != FALSE)
{
XrInput (NULL, MSG_PUSHEVENT, &input);
break;
}
else if (firstPass)
{
newTime.tv_sec = 0;
newTime.tv_usec = 100000;
XrInput (NULL, MSG_SETTIMEOUT, &newTime);
firstPass = FALSE;
}
}
break;
}
case XrSCROLL_SLIDE:
{
/* Set the view origin to the selected position */
viewOrigin->x = scrollEvent.value2;
drawColorBoxes (rasterEdit, viewOrigin->x, viewOrigin->y,
viewOrigin->x + viewRegion->width -1,
viewOrigin->y + viewRegion->height - 1);
/* Push on a fake select up event */
XrGetWindowEvent (XrSELECTUP, &windowEvent);
selectUp.type = windowEvent.inputType;
selectUp.detail = windowEvent.inputCode;
XrInput (NULL, MSG_PUSHEVENT, &selectUp);
break;
}
case XrSCROLL_LESS:
case XrSCROLL_MORE:
{
/* Set the view origin to the selected position */
viewOrigin->x = scrollEvent.value3;
reDataPtr->hSBParameters.slidePosition = viewOrigin->x;
XrScrollBar (reDataPtr->hScrollbar, MSG_SETPARAMETERS,
&reDataPtr->hSBParameters);
drawColorBoxes (rasterEdit, viewOrigin->x, viewOrigin->y,
viewOrigin->x + viewRegion->width -1,
viewOrigin->y + viewRegion->height - 1);
/* Push on a fake select up event */
XrGetWindowEvent (XrSELECTUP, &windowEvent);
selectUp.type = windowEvent.inputType;
selectUp.detail = windowEvent.inputCode;
XrInput (NULL, MSG_PUSHEVENT, &selectUp);
break;
}
}
/* Set up the view origin return value */
XrCopyPt (viewOrigin, &returnEvent->valuePt);
XrInput (NULL, MSG_SETTIMEOUT, &origTime);
}
\f
/*************************************<->*************************************
*
* paintREdit (rasterEdit, reDataPtr, spritePtr, editRect)
*
* xrEditor * rasterEdit;
* xrRasterEditData * reDataPtr;
* POINT * spritePtr;
* RECTANGLE * editRect;
*
* Description:
* -----------
* This routine processes all select events which occur within the
* editing region. When a select occurs in the editing region, this
* routine will continually poll the cursor position, and will change
* those pixels which lie in a line starting at the previous cursor
* position, and ending at the new cursor position. This is done
* because the cursor polling facilities are SLOW, and if we only
* changed the pixels at the cursor location, lots of gaps appear
* when the user moves the cursor quickly. When a select up, or any
* other X event is received, the painting operation will cease, and
* the event which caused us to terminate will be pushed back onto the
* front of the input queue; this is done so that the _MsgEdit() routine,
* which invoked our event processing routine, can strip the select up
* event, if it occurred.
*
* Inputs:
* ------
* rasterEdit = This points to the instance's editor structure.
*
* reDataPtr = This points to the instance's internal 'data' structure.
*
* spritePtr = This contains the initial cursor position at the time
* the select event occurred.
*
* editRect = This contains the rectangle describing the editing region.
*
* Outputs:
* -------
* The event which caused us to terminate is pushed onto the front of
* the application's input queue.
*
* Procedures Called
* -----------------
* XrPtInRect() [calc.c]
* XrCopyPt() [calc.c]
* XrEqualPt() [calc.c]
* XrSetPt() [calc.c]
* XrInput() [input.c]
* XQueryMouse() [libX.a]
* paintLine()
*
*************************************<->***********************************/
static
INT32
paintREdit (rasterEdit, reDataPtr, spritePtr, editRect)
xrEditor * rasterEdit;
xrRasterEditData * reDataPtr;
POINT * spritePtr;
register RECTANGLE * editRect;
{
register INT32 pixelSize;
register POINT * viewOrigin;
POINT pixelLoc;
POINT oldPixelLoc;
Window subw;
xrEvent tempEvent;
INT32 x,y;
Window windowId;
INT8 firstPass = TRUE;
windowId = rasterEdit->editorWindowId;
pixelSize = reDataPtr->pixelSize;
viewOrigin = &reDataPtr->viewOrigin;
/* Keep processing, until we receive another input event */
while (TRUE)
{
/* Ignore, if outside the editing region */
if (XrPtInRect (spritePtr, editRect))
{
pixelLoc.x = viewOrigin->x +
((spritePtr->x - editRect->x) / (pixelSize + 1));
pixelLoc.y = viewOrigin->y +
((spritePtr->y - editRect->y) / (pixelSize + 1));
if (firstPass)
XrCopyPt (&pixelLoc, &oldPixelLoc);
/* Redraw, only if in a new raster square */
if (!XrEqualPt (&pixelLoc, &oldPixelLoc) || firstPass)
{
paintLine (rasterEdit, reDataPtr, pixelLoc.x, pixelLoc.y,
oldPixelLoc.x, oldPixelLoc.y);
firstPass = FALSE;
}
XrCopyPt (&pixelLoc, &oldPixelLoc);
}
/* Stop, when an input event is received */
if (XrInput (NULL, MSG_NONBLKREAD, &tempEvent))
{
/*
* Push the event back on the input queue; this
* is done so that _MsgEdit(), which called us,
* properly exits and strips the select up event.
*/
XrInput (NULL, MSG_PUSHEVENT, &tempEvent);
return;
}
/* Continue polling for the cursor position */
XQueryMouse (windowId, &x, &y, &subw);
XrSetPt (spritePtr, x, y);
}
}
\f
/*************************************<->*************************************
*
* paintLine (rasterEdit, reDataPtr, x1, y1, x2, y2)
*
* xrEditor * rasterEdit;
* xrRsterEditData * reDataPtr;
* INT32 x1, y1;
* INT32 x2, y2;
*
* Description:
* -----------
* This routine will set to the current editing color, those pixels
* in the editing region which line along the line starting at point
* (x1, y1) and ending at point (x2, y2).
*
*
* Inputs:
* ------
* rasterEdit = This points to the instance's editor structure.
*
* reDataPtr = This points to the instance's internal 'data' structure.
*
* x1, y1 = This specifies the starting point of the line.
*
* x2, y2 = This specifies the ending point of the line.
*
* Outputs:
* -------
*
* Procedures Called
* -----------------
* XrSetPt() [calc.c]
* _XrPixelExtract() [pixelExt.c]
* drawColorBoxes()
*
*************************************<->***********************************/
static
INT32
paintLine (rasterEdit, reDataPtr, x1, y1, x2, y2)
xrEditor * rasterEdit;
register xrRasterEditData * reDataPtr;
register INT32 x1;
register INT32 y1;
register INT32 x2;
register INT32 y2;
{
register INT16 d;
register INT32 count;
POINT location;
INT16 xincr1, yincr1;
INT16 xincr2, yincr2;
INT16 a, b;
INT32 xPtCount;
INT32 yPtCount;
/* Draw the first point */
XrSetPt (&location, x1, y1);
_XrPixelExtract (reDataPtr->extractionData, MSG_LOCATION,
&location);
_XrPixelExtract (reDataPtr->extractionData, MSG_SETVALUE,
reDataPtr->pixelColor);
drawColorBoxes (rasterEdit, x1, y1, x1, y1);
/* Stop, if this is a single point line */
if (x1 == x2 && y1 == y2)
return;
/*
* Initialize the incrementing values used to generate
* the points within the segment
*/
xPtCount = abs(x2 - x1);
yPtCount = abs(y2 - y1);
if (x2 > x1)
{
if (y2 > y1)
xincr2 = yincr2 = 1;
else
{
xincr2 = 1;
yincr2 = -1;
}
}
else
{
if (y2 > y1)
{
xincr2 = -1;
yincr2 = 1;
}
else
xincr2 = yincr2 = -1;
}
if (xPtCount > yPtCount)
{
count = xPtCount;
xincr1 = xincr2;
yincr1 = 0;
b = yPtCount << 1;
a = (xPtCount << 1) - b;
d = b - xPtCount;
}
else
{
count = yPtCount;
xincr1 = 0;
yincr1 = yincr2;
b = xPtCount << 1;
a = (yPtCount << 1) - b;
d = b - yPtCount;
}
do
{
if (d > 0)
{
d -= a;
x1 += xincr2;
y1 += yincr2;
}
else
{
d += b;
x1 += xincr1;
y1 += yincr1;
}
/* Set the specified pixel, and draw it */
XrSetPt (&location, x1, y1);
_XrPixelExtract (reDataPtr->extractionData, MSG_LOCATION,
&location);
_XrPixelExtract (reDataPtr->extractionData, MSG_SETVALUE,
reDataPtr->pixelColor);
drawColorBoxes (rasterEdit, x1, y1, x1, y1);
}
while (--count);
}