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