|
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: P T
Length: 116103 (0x1c587) Types: TextFile Names: »PageEdit.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/PageEdit.c«
/* * $Source: /u1/Xr/src/Xrlib/Editor/RCS/PageEdit.c,v $ * $Header: PageEdit.c,v 1.1 86/12/17 09:00:34 swick Exp $ */ #ifndef lint static char *rcsid_PageEdit_c = "$Header: PageEdit.c,v 1.1 86/12/17 09:00:34 swick Exp $"; #endif lint #include <Xr/xr-copyright.h> /* $Header: PageEdit.c,v 1.1 86/12/17 09:00:34 swick Exp $ */ /* Copyright 1986, Hewlett-Packard Company */ /* Copyright 1986, Massachussetts Institute of Technology */ static char rcsid[] = "$Header: PageEdit.c,v 1.1 86/12/17 09:00:34 swick Exp $"; /*************************************<+>************************************* ***************************************************************************** ** ** File: PageEdit.c ** ** Project: X-ray Toolbox ** ** Description: ** Source code for the X-ray multi-line text edit field editor. ** ** ** ------------------------ MODIFICATION RECORD ------------------------ * * $Log: PageEdit.c,v $ * Revision 1.1 86/12/17 09:00:34 swick * Initial revision * * Revision 7.0 86/11/13 08:22:17 08:22:17 fred () * Final QA Release * * Revision 6.0 86/11/10 15:27:37 15:27:37 fred () * QA #2 release * * Revision 5.4 86/11/07 14:19:18 14:19:18 fred () * Added new copyright message. * * Revision 5.3 86/11/05 08:46:03 08:46:03 fred () * Now only handles input events if they occurred in the window in which * the editor instance was created. * * Revision 5.2 86/11/03 11:47:34 11:47:34 fred () * Added fix to treat DEL the same as BACKSPACE. * * Revision 5.1 86/10/30 13:24:21 13:24:21 fred () * Fixed cursor movement bug (using mouse), and also fixed the * handling of the RETURN key. * * Revision 5.0 86/10/28 08:27:29 08:27:29 fred () * QA #1.1 release * * Revision 4.4 86/10/27 16:51:36 16:51:36 fred () * Fixed but in NEXT PAGE code. * * Revision 4.3 86/10/27 15:48:55 15:48:55 fred () * Fixed bug introduced by previous update. * * Revision 4.2 86/10/27 13:48:24 13:48:24 fred () * Updated to match new XrInputMap() syntax. * * Revision 4.1 86/10/23 09:05:05 09:05:05 fred () * Removed unused variables. * * Revision 4.0 86/10/20 12:08:48 12:08:48 fred () * QA #1 release * * Revision 1.9 86/10/20 09:11:34 09:11:34 fred () * Fixed character insertion mode bug. * * Revision 1.8 86/10/17 15:26:26 15:26:26 fred () * Enhanced redraw during character insertion, and scrolling. * * Revision 1.7 86/10/17 12:12:20 12:12:20 fred () * Enhanced the redraw algorithm used during placement of ascii * characters which do not wrap. * * Revision 1.6 86/10/17 08:46:41 08:46:41 fred () * Tab expansion and control characters now completely in. Control * character in last column still not handled correctly; Ok for now. * (version received from Phil). * * Revision 1.3 86/10/10 13:14:13 13:14:13 fred () * Filled procedure headers and fixed several small bugs. * * Revision 1.2 86/10/10 08:42:32 08:42:32 fred () * First real working version. Includes all editing features but * the scroll keys, paging, and control character input. * * Revision 1.1 86/10/10 07:33:36 07:33:36 fred () * Initial revision * * ***************************************************************************** *************************************<+>*************************************/ #include <X/Xlib.h> #include <Xr/defs.h> #include <Xr/types.h> #include <Xr/in_types.h> #include <ctype.h> #include <Xr/keycode.h> extern INT32 createPageEdit(); extern INT32 drawPageEdit(); extern INT32 peFreeMemory(); extern INT8 * getStartOfPreviousLine(); extern xrEditor * processPageEdit(); extern xrEditor * peMOVE_handler(); extern xrEditor * peRESIZE_handler(); extern xrEditor * peREDRAW_handler(); extern xrEditor * peINSERTMODE_handler(); extern xrEditor * peActivate(); #define XrFRAME_ONLY 0x01 #define XrALLCOMPONENTS 0x02 #define SCREEN 0x01 #define BUFFER 0x02 #define BORDER 3 #define PADDING 2 #define UP 0 #define DOWN 1 \f /*************************************<->************************************* * * XrPageEdit (pageEdit, message, data) * * xrEditor * pageEdit; * INT32 message; * INT8 * data; * * Description: * ----------- * This is the main handler routine for the multi-line text edit field * editor. It takes each action request issued by an application, * verifies that the editor can handle it, and then calls the * appropriate handling routine. * * * Inputs: * ------ * pageEdit = For all messages by MSG_NEW and MSG_SIZE, this must * contain the editor instance pointer for the instance * which is to be operated upon. * * message = This specifies the action to be taken by the editor. * * data = This is the message specific data. It may be a scalar, * a pointer, or not used, depending upon the action requested. * * Outputs: * ------- * Upon successful completion, all messages will return a non-NULL * value (normally the instance pointer). Additional data may * be returned by certain messages. * * Upon failure, NULL will be returned, and xrErrno set. * * Procedures Called * ----------------- * _MsgNew() [MsgCommon.c] * _MsgFree() [MsgCommon.c] * _MsgGetState() [MsgCommon.c] * _MsgSetState() [MsgCommon.c] * XrCopyRect() [calc.c] * sizePageEdit() * createPageEdit() * drawPageEdit() * drawTextRegion() * displayBuffer() * drawCursor() * processPageEdit() * peInitGCs() * peActivate() * peMOVE_handler() * peREDRAW_handler() * *************************************<->***********************************/ xrEditor * XrPageEdit (pageEdit, message, data) register xrEditor * pageEdit; INT32 message; INT8 * data; { /* Determine the action being requested */ switch (message) { case MSG_NEW: { /* * Create a new instance of this editor. * The 'pageEdit' parameter is unused, but the 'data' * parameter must point to a filled out instance of * the 'xrPageEditInfo' structure, which describes the * instance which is to be created. */ return ((xrEditor *)_MsgNew (pageEdit, data, sizeof(xrPageEditData), createPageEdit, drawPageEdit, peFreeMemory, XrPageEdit, NULL)); } case MSG_FREE: { /* * Destroy the specified editor instance. * The only parameter of instance is 'pageEdit', which * contains the editor instance pointer for the instance * which is to be destroyed. */ return ((xrEditor *) _MsgFree (pageEdit, peFreeMemory)); } case MSG_GETSTATE: { /* * Return the current state flags associated with the * specified page edit instance. The 'pageEdit' parameter * contains the editor instance pointer, and the 'data' * parameter points to an INT8 value, into which the * state flag values will be placed. */ return ((xrEditor *) _MsgGetState (pageEdit, data)); } case MSG_SETSTATE: { /* * Change the state flags associated with a particular page * edit instance. The 'pageEdit' parameter contains the * editor instance pointer for the instance to be modified, * while the 'data' parameter is interpreted as an INT8 * value, containing the new state flag values. */ return ((xrEditor *) _MsgSetState (pageEdit, data, drawPageEdit, NULL)); } 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 'pageEdit' * parameter is unused, while the 'data' parameter must * point to a partially filled out instance of the * 'xrPageEditInfo' structure. */ xrPageEditInfo * peInfoPtr = (xrPageEditInfo *) data; if (peInfoPtr == NULL) { xrErrno = XrINVALIDPTR; return ((xrEditor *) NULL); } return((xrEditor *) sizePageEdit (peInfoPtr, &peInfoPtr->editorRect)); } case MSG_REDRAW: { /* * Redraw the editor, to match new value. * The 'pageEdit' parameter must contain the editor instance * pointer, while the 'data' parameter will be interpreted * as an INT32 value, specifying the type of redraw to perform. */ return ((xrEditor *) peREDRAW_handler (pageEdit, (INT32) data)); } case MSG_DEACTIVATE: { /* * Force the page edit field inactive. * The 'pageEdit' parameter must contain the editor instance * pointer; the 'data' parameter is unused. */ xrPageEditData * peDataPtr; if (pageEdit == NULL) { xrErrno = XrINVALIDID; return ((xrEditor *) NULL); } peDataPtr = (xrPageEditData *) pageEdit->editorData; if (peDataPtr->peCursorOn) { peDataPtr->peCursorOn = FALSE; peInitGCs (peDataPtr); drawTextRegion (pageEdit, XrFRAME_ONLY); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); } return (pageEdit); } case MSG_ACTIVATE: { /* * Activate the instance, and start waiting for an * input event to be received. The 'pageEdit' parameter * must contain the editor instance pointer, while the * 'data' parameter is unused. */ return (peActivate (pageEdit)); } case MSG_GETBUFINFO: { /* * Return a block of information describing the contents * and limits associated with the editing buffer. The * 'pageEdit' parameter specifies the instance to be * queried, while the 'data' parameter must point to an * instance of the 'xrPageEditBufInfo' structure, into * which the buffer information will be placed. */ xrPageEditBufInfo * bufInfo = (xrPageEditBufInfo *) data; xrPageEditData * peDataPtr; if (pageEdit == NULL) { xrErrno = XrINVALIDID; return ((xrEditor *) NULL); } else if (bufInfo == NULL) { xrErrno = XrINVALIDPTR; return ((xrEditor *) NULL); } peDataPtr = (xrPageEditData *) pageEdit->editorData; bufInfo->buffer = peDataPtr->peBuffer; bufInfo->bufferCount = peDataPtr->peBufferCount; bufInfo->bufferSize = peDataPtr->peBufferSize; bufInfo->maxCharCount = peDataPtr->peMaxSize; return (pageEdit); } case MSG_SETBUFINFO: { /* * Take the modified buffer information, contained in the * structure pointed to by the 'data' parameter, and attempt * to determine where the top of frame, the cursor pointer, * and the cursor row/col should be located. */ xrPageEditBufInfo * bufInfo = (xrPageEditBufInfo *) data; xrPageEditData * peDataPtr; /* Validate all of the parameter values */ if (pageEdit == NULL) { xrErrno = XrINVALIDID; return ((xrEditor *) NULL); } else if (bufInfo == NULL) { xrErrno = XrINVALIDPTR; return ((xrEditor *) NULL); } else if (bufInfo->buffer == NULL) { xrErrno = XrINVALIDPTR; return (FALSE); } else if ((bufInfo->maxCharCount == 0) || (bufInfo->bufferSize <= 0)) { xrErrno = XrINVALIDPARM; return (FALSE); } else if (((bufInfo->maxCharCount > 0) && (bufInfo->bufferCount > bufInfo->maxCharCount)) || (bufInfo->bufferCount > bufInfo->bufferSize)) { xrErrno = XrPARMOUTOFRANGE; return (FALSE); } else if (bufInfo->bufferCount < 0) { xrErrno = XrINVALIDPARM; return (FALSE); } /***********************************/ /* Determine the top of frame, the */ /* cursor ptr, and the cursor row */ /* height here. */ /***********************************/ /* * For first pass, whenever the application changes the * buffer contents, we will force the top of frame back * to the start of the buffer, and the cursor to (0,0). * This could be enhanced at a later time, with a much * more complicated algorithm. */ peDataPtr = (xrPageEditData *) pageEdit->editorData; peDataPtr->peBuffer = bufInfo->buffer; peDataPtr->peBufferCount = bufInfo->bufferCount; peDataPtr->peBufferSize = bufInfo->bufferSize; peDataPtr->peMaxSize = bufInfo->maxCharCount; peDataPtr->peTopOfFrame = peDataPtr->peBuffer; peDataPtr->peCursorPtr = peDataPtr->peBuffer; peDataPtr->peCursorRow = 0; peDataPtr->peCursorCol = 0; peDataPtr->peVCursorCol = 0; /* Redraw, if the instance is visible */ if (pageEdit->editorState & XrVISIBLE) { peInitGCs (peDataPtr); displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); if (peDataPtr->peCursorOn) drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } return (pageEdit); } case MSG_MOVE: { /* * Relocate an instance of the page editor to a new location. * The 'pageEdit' parameter must contain the editor instance * pointer, while the 'data' parameter must point to an * instance of the 'POINT' structure, which contains the new * editor rectangle origin. */ return ((xrEditor *) peMOVE_handler (pageEdit, data)); } case MSG_EDIT: { /* * Process the incoming keystroke, and generate a return * keystroke, to indicate to the application program how the * editor instance was modified. The 'pageEdit' parameter * must contain the editor instance pointer; the 'data' parameter * must point to an XEvent structure, containing some X event. */ if ((pageEdit == NULL) || (data == NULL) || ((pageEdit->editorState & (XrSENSITIVE | XrVISIBLE)) != (XrSENSITIVE | XrVISIBLE))) return ((xrEditor *) NULL); return (processPageEdit (pageEdit, data)); } default: /* All other commands are invalid */ xrErrno = XrINVALIDMSG; return ((xrEditor *)NULL); } /* end of switch */ } /* end of XrPageEdit() */ \f /*************************************<->************************************* * * INT32 * peFreeMemory (peDataPtr) * * xrPageEditData * peDataPtr * * Description: * ----------- * This routine is invoked whenever an instance is destroyed [MSG_FREE], * or anytime a MSG_NEW fails after createPageEdit() has been called. * It will delete the 'peBlanks' buffer space, along with freeing * up the pixmap which was created for displaying an insensitive * instance. * * * Inputs: * ------ * peDataPtr = This points to the internal 'data' structure associated * with the instance being destroyed. * * Outputs: * ------- * * Procedures Called * ----------------- * XFreePixmap() [libX.a] * (*xrFree)() * *************************************<->***********************************/ static INT32 peFreeMemory (peDataPtr) xrPageEditData * peDataPtr; { (*xrFree) (peDataPtr->peBlanks); if (peDataPtr->peTileId != xrDefaultTile) XFreePixmap (peDataPtr->peTileId); } \f /*************************************<->************************************* * * INT32 * sizePageEdit (peInfoPtr, rectPtr) * * xrPageEditInfo * peInfoPtr; * RECTANGLE * rectPtr; * * Description: * ----------- * This routine takes the page edit specifications, contained in the * 'info' structure pointed to by the 'peInfoPtr' parameter, and * calculates the size of the rectangle needed to contain the instance. * * * Inputs: * ------ * peInfoPtr = This points to an 'info' structure, containing the * specifics describing the hypothetical instance. Only * the 'editorFont', 'colCount' and 'rowCount' * fields need to be initialized. * * rectPtr = The minimally sized 0-based rectangle needed to contain * the instance will be returned in the structure pointed to * by this parameter. * * Outputs: * ------- * Upon successful completion, TRUE is returned, along with the * rectangle definition. * * Upon failure, FALSE is returned, and xrErrno is set. * * Procedures Called * ----------------- * _XrTextInfo() [textUtil.c] * XrSetRect() [calc.c] * *************************************<->***********************************/ static INT32 sizePageEdit (peInfoPtr, rectPtr) xrPageEditInfo * peInfoPtr; RECTANGLE * rectPtr; { INT16 height; INT16 width; INT16 lineWidth; INT16 lineHeight; FontInfo * fontPtr; xrTextInfo fontData; /* Check the row and column specifications */ if ((peInfoPtr->rowCount <= 0) || (peInfoPtr->colCount <= 0)) { xrErrno = XrPARMOUTOFRANGE; return (FALSE); } /* Request extra information for the font we will be using. */ fontPtr = (peInfoPtr->editorFont) ? peInfoPtr->editorFont : xrBaseFontInfo; _XrTextInfo (fontPtr, &fontData); /* Make sure the font is fixed width */ if (fontPtr->fixedwidth == 0) { xrErrno = XrINVALIDPARM; return (FALSE); } /* Calculate the width of the text region */ lineWidth = (peInfoPtr->colCount * fontData.maxWidth); lineHeight = (fontData.ascent + fontData.descent + fontData.leading); /* * We now have enough information to calculate the editor rectangle. * * width = border width + padding + line width + padding + * border width. * [ For the width, padding = 2 pixels ] * * height = border height + padding + (font height * line count) + * padding + border height. * [ For the height, padding = 2 pixels ] */ width = BORDER + PADDING + lineWidth + PADDING + BORDER; height = BORDER + PADDING + (lineHeight * peInfoPtr->rowCount) + PADDING + BORDER; XrSetRect (rectPtr, 0, 0, width, height); return (TRUE); } \f /*************************************<->************************************* * * createPageEdit (peDataPtr, peInfoPtr, message) * * xrPageEditData * peDataPtr; * xrPageEditInfo * peInfoPtr; * INT32 message; * * Description: * ----------- * This routine is used during the creation of a new page edit instance. * It expects the 'peInfoPtr' parameter to point to a filled out * instance of the the 'info' structure. Using this information, it * will calculate the size and location of each component of the * instance being created; all of this information will be stored in * the 'data' structure pointed to by the 'peDataPtr' parameter. * * * Inputs: * ------ * peDataPtr = This points to the 'data' structure, into which the * component information is to be saved. * * peInfoPtr = This must point to an instance of the 'info' structure. * It must be completely filled out. * * message = This parameter is unused for this editor. * * Outputs: * ------- * Upon successful completion, TRUE is returned, and the 'data' * structure is filled out. * * Upon failure, FALSE is returned, and xrErrno is set. * * Procedures Called * ----------------- * _XrTextInfo() [textUtil.c] * XrResource() [resource.c] * XMakePixmap() [libX.a] * XFreePixmap() [libX.a] * sizePageEdit() * *************************************<->***********************************/ static INT32 createPageEdit (peDataPtr, peInfoPtr, message) register xrPageEditData * peDataPtr; register xrPageEditInfo * peInfoPtr; INT32 message; { register INT32 i; register RECTANGLE * editorRect; FontInfo * fontPtr; xrResourceInfo bitmapInfo; RECTANGLE workRect; /* Validate incoming parameters */ if (peInfoPtr->buffer == NULL) { xrErrno = XrINVALIDPTR; return (FALSE); } else if ((peInfoPtr->maxCharCount == 0) || (peInfoPtr->bufferSize <= 0)) { xrErrno = XrINVALIDPARM; return (FALSE); } else if (((peInfoPtr->maxCharCount > 0) && (peInfoPtr->bufferCount > peInfoPtr->maxCharCount)) || (peInfoPtr->bufferCount > peInfoPtr->bufferSize)) { xrErrno = XrPARMOUTOFRANGE; return (FALSE); } else if (peInfoPtr->bufferCount < 0) { xrErrno = XrINVALIDPARM; return (FALSE); } else { /* Parameters are valid, so save them */ peDataPtr->peBuffer = peInfoPtr->buffer; peDataPtr->peBufferCount = peInfoPtr->bufferCount; peDataPtr->peBufferSize = peInfoPtr->bufferSize; peDataPtr->peMaxSize = peInfoPtr->maxCharCount; } /* Make sure the specified rectangle is not too small */ if (sizePageEdit (peInfoPtr, &workRect) == FALSE) return (FALSE); editorRect = &peInfoPtr->editorRect; if ((editorRect->width != workRect.width) || (editorRect->height != workRect.height)) { xrErrno = XrINVALIDRECT; return (FALSE); } /* Get the font description */ fontPtr = (peInfoPtr->editorFont) ? peInfoPtr->editorFont : xrBaseFontInfo; _XrTextInfo (fontPtr, &peDataPtr->peFont); /* Create the 50% tile used when drawing insensitive page editor */ peDataPtr->peFGColor = (peInfoPtr->editorFGColor == -1) ? xrForegroundColor : peInfoPtr->editorFGColor; peDataPtr->peBGColor = (peInfoPtr->editorBGColor == -1) ? xrBackgroundColor : peInfoPtr->editorBGColor; bitmapInfo.resourceType = XrTYPE_BITMAPID; bitmapInfo.resourceId = XrPERCENT50; if ((peInfoPtr->editorFGColor == -1) && (peInfoPtr->editorBGColor == -1)) { peDataPtr->peTileId = xrDefaultTile; } else { if ((XrResource (MSG_FIND, &bitmapInfo) == FALSE) || ((peDataPtr->peTileId = XMakePixmap (((xrBitmapId *)bitmapInfo.resourceObject)->bitmapId, peDataPtr->peFGColor, peDataPtr->peBGColor)) == 0)) { /* Unable to create the tile */ xrErrno = XrXCALLFAILED; return (FALSE); } } /* Create an array to use when blanking out a line */ if ((peDataPtr->peBlanks = (*xrMalloc)(peInfoPtr->colCount)) == NULL) { if (peDataPtr->peTileId != xrDefaultTile) XFreePixmap (peDataPtr->peTileId); xrErrno = XrOUTOFMEM; return (FALSE); } for (i = 0; i < peInfoPtr->colCount; i++) peDataPtr->peBlanks[i] = ' '; /* Fill in the rest of the fields in the text edit structures */ peDataPtr->peCursorOn = FALSE; peDataPtr->peRowNum = peInfoPtr->rowCount; peDataPtr->peColNum = peInfoPtr->colCount; peDataPtr->peTopOfFrame = peDataPtr->peBuffer; peDataPtr->peCursorPtr = peDataPtr->peBuffer; peDataPtr->peCursorRow = 0; peDataPtr->peCursorCol = 0; peDataPtr->peVCursorCol = 0; if (peInfoPtr->tabWidth <= 0) peDataPtr->peTabWidth = 1; else peDataPtr->peTabWidth = peInfoPtr->tabWidth; return (TRUE); } \f /*************************************<->************************************* * * INT32 * drawPageEdit (pageEdit, components) * * xrEditor * pageEdit; * INT32 components; * * Description: * ----------- * This routine will draw all of an existing text edit instance. * This includes the border, interior, text, and cursor (if on). * * * Inputs: * ------ * pageEdit = This is the instance pointer for the instance which * is to be drawn. * * components = This parameter is not used by this module. It needs * to be present so that this routine may be invoked * by _MsgNew(). * * Outputs: * ------- * * Procedures Called * ----------------- * _XrMakeInvisible() [editorUtil.c] * drawTextRegion() * displayBuffer() * drawCursor() * peInitGCs() * *************************************<->***********************************/ static INT32 drawPageEdit (pageEdit, components) xrEditor * pageEdit; INT32 components; { register xrPageEditData * peDataPtr; /* Initialize variables */ peDataPtr = (xrPageEditData *) pageEdit->editorData; /* * If the instance is not visible, then fill its area with the * background tile for the window, thus making the instance invisible. */ if (!(pageEdit->editorState & XrVISIBLE)) { _XrMakeInvisible (pageEdit->editorWindowId, &pageEdit->editorRect, TRUE); return; } /* Initialize the graphic contexts */ peInitGCs (peDataPtr); /* Draw the instance */ drawTextRegion (pageEdit, XrALLCOMPONENTS); displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); if (peDataPtr->peCursorOn) drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } \f /*************************************<->************************************* * * xrEditor * * processPageEdit (pageEdit, eventPtr) * * xrEditor * pageEdit; * XEvent * eventPtr; * * Description: * ----------- * This is the main event processing routine the the page editor. * When it first receives an event, it will call the various * sub-event handlers (ascii, editing and button) * and will give them the opportunity to handle the event. If the * event is handled, then it will read the input queue, and wait * for the next event. This continues until either a permanent * exit condition occurs (a SELECT outside the instance) * or a temporary break condition occurs (buffer expansion occurred * or failed, or an unknown event is received). * When the sub-event handler is called, it is passed some information * describing the new event, along with a pointer to a partially filled * out X-ray event structure; if the sub-event handler plans to exit, * it fills out the rest of the X-ray event, pushes it onto the * input queue, sets 'exitFlag' to TRUE, and returns a value of TRUE. * * * Inputs: * ------ * pageEdit = This is the instance pointer for the instance to which * the input event is to be applied. * * eventPtr = This is a pointer to an XEvent structure, containing the * event to be processed. * * Outputs: * ------- * Upon exiting, if any events were handled, then TRUE is returned, * along with anywhere from 0 to 2 events pushed onto the front * of the input queue. * * If the initial event received (pointed to by 'eventPtr') is not * handled, then NULL is returned. * * Procedures Called * ----------------- * XrInput() [input.c] * peInitGCs() * peButtonEvent() * peAsciiEvent() * peEditEvent() * *************************************<->***********************************/ static xrEditor * processPageEdit (pageEdit, eventPtr) xrEditor * pageEdit; XEvent * eventPtr; { register xrPageEditData * peDataPtr; xrEvent peEvent; INT8 exitFlag; UINT16 code; INT8 * string; INT32 byteCount; peDataPtr = (xrPageEditData *) pageEdit->editorData; /* Initialize the return event structure */ peEvent.type = XrXRAY; peEvent.source = eventPtr->window; peEvent.inputType = XrEDITOR; peEvent.inputCode = XrPAGEEDIT; peEvent.valuePtr = (INT32) pageEdit; peInitGCs (peDataPtr); /* Keep processing until a terminating event occurs */ while (1) { exitFlag = FALSE; if ((eventPtr->type == ButtonPressed) || (eventPtr->type == ButtonReleased)) { peButtonEvent (pageEdit, peDataPtr, eventPtr, &peEvent, &exitFlag); if (exitFlag) return (pageEdit); } else if (eventPtr->type == KeyPressed) { string = XrInputMap (eventPtr, &byteCount); if (byteCount == 1) code = *string; else if (byteCount == 2) code = (*string << 8) + *(string + 1); if (byteCount == 1 || byteCount == 2) { if (peAsciiEvent (pageEdit, peDataPtr, code, &peEvent, &exitFlag)) { if (exitFlag) return (pageEdit); } else if (peEditEvent (pageEdit,peDataPtr,code,&peEvent,&exitFlag)) { if (exitFlag) return (pageEdit); } } } else if (eventPtr->type == KeyReleased) { /* Swallow all of these events */ } else { if (peDataPtr->peCursorOn) { /* * Unknown Event: * Push the unknown event onto the input queue, along with * a page edit event, and return to the application. */ XrInput (NULL, MSG_PUSHEVENT, eventPtr); peEvent.value1 = XrUNKNOWN_EVENT; XrInput (NULL, MSG_PUSHEVENT, &peEvent); return (pageEdit); } else return ((xrEditor *) NULL); } /* Grab the next input event */ while (1) { if ((XrInput (NULL, MSG_BLKREAD, eventPtr) != FALSE) && (eventPtr->window == pageEdit->editorWindowId)) break; } } /* End of while loop */ } \f /*************************************<->************************************* * * INT32 * teButtonEvent (pageEdit, peDataPtr, event, returnEvent, exitFlag) * * xrEditor * pageEdit; * xrPageEditData * peDataPtr; * XButonEvent * event; * xrEvent * returnEvent; * INT8 exitFlag; * * Description: * ----------- * This routine takes the 'event', and first determines if it is a * button event; if not, it returns and does nothing. If it is, then * it checks to see if it is a SELECT or SELECTUP event; if not, then * it is treated as an unknown event, and both the event and an * X-ray 'unknown' event will be pushed onto the input queue, and the * application will be given the change to handle it. The SELECTUP * will be swallowed. If this is a SELECT event, then a check will be * made to see if it occurred within the instance. If it did, then the * cursor will be moved to the character cell nearest to where the * select occurred. If the select is outside the instance, then the * select event will be pushed back onto the input queue, along with * another event indicating that the instance is going inactive, and * the instance will then be drawn as inactive; the application is * then given the opportunity to handle the select event. * * * Inputs: * ------ * pageEdit = This is the instance pointer for the page edit instance * to which the event is to be applied. * * peDataPtr = This is a pointer to the 'data' structure associated * with the instance. * * event = This is a pointer to the X event to be processed. * * returnEvent = This is a pointer to a partially filled out X-ray * event structure. If we need to push an X-ray event * onto the front of the input queue, we simply fill * out any additional fields necessary, and then use * this. * * exitFlag = This allows us to signal to the main event handler that * the event just handled is causing us to exit and return * to the application; this is set when either an unknown * event is received, or a select outside the instance * occurs. * * Outputs: * ------- * Upon completion, 'exitFlag' will be set as described above, and * it is possible that 1 or more events have been pushed onto * the front of the input queue. * * Procedures Called * ----------------- * XrMapButton() [utilities.c] * XrSetPt() [calc.c] * XrPtInRect() [calc.c] * XrInput() [input.c] * XFlush() [libX.a] * drawCursor() * drawTextRegion() * getScreenCol() * getBufCol() * *************************************<->***********************************/ static INT32 peButtonEvent (pageEdit, peDataPtr, event, returnEvent, exitFlag) xrEditor * pageEdit; xrPageEditData * peDataPtr; XButtonEvent * event; xrEvent * returnEvent; INT8 * exitFlag; { POINT cursorPos; INT32 selectRow, selectCol; INT32 rowCount, lineLen; INT32 newLineFound; register INT8 * startOfLine; register INT8 * ptr; if (XrMapButton (XrSELECT, event)) { /* If the select is outside the editor's rectangle, then break */ XrSetPt (&cursorPos, event->x, event->y); if (!XrPtInRect (&cursorPos, &pageEdit->editorRect)) { /* * Return two events: the select which is causing us to * exit, followed by the break notification. */ XrInput (NULL, MSG_PUSHEVENT, event); returnEvent->value1 = XrPEDIT_BREAK; returnEvent->value2 = XrSELECT; XrInput (NULL, MSG_PUSHEVENT, returnEvent); /* Redraw the field as inactive */ peDataPtr->peCursorOn = FALSE; drawTextRegion (pageEdit, XrFRAME_ONLY); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); XFlush(); *exitFlag = TRUE; return; } else if (peDataPtr->peCursorOn) { /* * Place the cursor as close as possible to the location * where the select occurred. */ /* Convert the point to a row and column */ selectRow = ((event->y - pageEdit->editorRect.y-BORDER-PADDING) / (peDataPtr->peFont.ascent + peDataPtr->peFont.descent + peDataPtr->peFont.leading)); selectCol = ((event->x - pageEdit->editorRect.x-BORDER-PADDING) / peDataPtr->peFont.maxWidth); /* Check an edge condition */ if (selectRow >= peDataPtr->peRowNum) selectRow = peDataPtr->peRowNum - 1; if (selectCol >= peDataPtr->peColNum) selectCol = peDataPtr->peColNum - 1; /* Turn off the cursor */ if (peDataPtr->peCursorOn) drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr,FALSE); /* Get a pointer to the start of that line */ startOfLine = ptr = peDataPtr->peTopOfFrame; rowCount = 0; lineLen = 0; newLineFound = FALSE; while (selectRow + 1 != rowCount) { /* Check for the end of the buffer */ if (ptr >= peDataPtr->peBuffer + peDataPtr->peBufferCount) break; lineLen = readALine (peDataPtr, ptr, &newLineFound); startOfLine = ptr; ptr += lineLen; rowCount++; } /* Check where the select occurred */ if (peDataPtr->peBufferCount == 0) { peDataPtr->peCursorPtr = peDataPtr->peBuffer; selectRow = 0; selectCol = 0; } else if (rowCount != selectRow + 1) { /* * The select occurred outside the range of the buffer, * so place the cursor at the end of the line. */ peDataPtr->peCursorPtr = peDataPtr->peBuffer + peDataPtr->peBufferCount; if (newLineFound) { /* * The last character in the buffer is a newline, * so place cursor at start of next line. */ selectCol = 0; selectRow = rowCount; } else { /* * The last character in the buffer is not a newline, * so place cursor at the end of this line. */ selectCol = lineLen; selectRow = rowCount - 1; } } else { /* The line exists */ if (lineLen <= selectCol) { /* * The line exists, but it is too short. Therefore, * if the last character in the line is a newline, * then place the cursor on top of the newline; else * place the cursor after the last character. */ if (newLineFound) selectCol = lineLen - 1; else selectCol = lineLen; } peDataPtr->peCursorPtr = startOfLine + getBufCol(peDataPtr, startOfLine, selectCol); } peDataPtr->peCursorRow = selectRow; peDataPtr->peCursorCol = selectCol; peDataPtr->peVCursorCol = getScreenCol (peDataPtr, startOfLine, (INT32)(peDataPtr->peCursorPtr - startOfLine)); /* Turn the cursor back on */ if (peDataPtr->peCursorOn) drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr,TRUE); } /* * Force the field active, and redraw the instance. */ if (!peDataPtr->peCursorOn) { peDataPtr->peCursorOn = TRUE; drawTextRegion (pageEdit, XrFRAME_ONLY); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } return; } else if (XrMapButton (XrSELECTUP, event)) { /* Swallow a selectup event */ return; } else { /* * Treat all other events as unknown events. * Push it back on the input queue, and add * a page edit break event afterwards. */ XrInput (NULL, MSG_PUSHEVENT, event); returnEvent->value1 = XrUNKNOWN_EVENT; XrInput (NULL, MSG_PUSHEVENT, returnEvent); *exitFlag = TRUE; return; } } \f /*************************************<->************************************* * * INT32 * peAsciiEvent (pageEdit, peDataPtr, keyCode, returnEvent, exitFlag) * * xrEditor * pageEdit; * xrPageEditData * peDataPtr; * UINT16 keyCode; * xrEvent * returnEvent; * INT8 exitFlag; * * Description: * ----------- * If the buffer is not already full, then this routine takes the * keycode and adds it to the buffer at the current cursor position. * Afterwards, the cursor position is updated, and a check is made * to see if the buffer is full. If the buffer is full, than an * attempt will be made to expand the buffer, if this feature is * enabled. If the buffer is full, or gets expanded, or the * expansion fails, then a status event will be pushed onto the * input queue, and control will return to the application. * * * Inputs: * ------ * pageEdit = This is the instance pointer for the page edit instance * to which the event is to be applied. * * peDataPtr = This is a pointer to the 'data' structure associated * with the instance. * * keyCode = This contains the keyCode into which the event mapped. * * returnEvent = This is a pointer to a partially filled out X-ray * event structure. If we need to push an X-ray event * onto the front of the input queue, we simply fill * out any additional fields necessary, and then use * this. * * exitFlag = This allows us to signal to the main event handler that * the event just handled is causing us to exit and return * to the application; this is set only if the buffer becomes * full, is expanded, or the expansion fails. * * Outputs: * ------- * If the keyCode is handled by this routine, then TRUE will be returned, * and 'exitFlag' will be set as described above. In addition, a * single status event may be pushed onto the input queue. * * If the keyCode is not handled here, then FALSE is returned. * * Procedures Called * ----------------- * XLookupMapping() [libX.a] * XrInput() [input.c] * displayBuffer() * drawCursor() * getCharWidth() * expandBuffer() * *************************************<->***********************************/ static INT32 peAsciiEvent (pageEdit, peDataPtr, keyCode, returnEvent, exitFlag) xrEditor * pageEdit; register xrPageEditData * peDataPtr; UINT16 keyCode; xrEvent * returnEvent; INT8 * exitFlag; { INT8 key; INT32 junk; INT32 newLineFound; INT32 redrawLine; INT32 lineHeight; INT32 oldLineCount, newLineCount; INT8 * endOfBuffer; register INT8 * bufr; if ((keyCode == (RETURN_KEY | K_s)) || (keyCode == '\r')) keyCode = '\n'; else if ((keyCode == (TAB_KEY | K_s)) || (keyCode == (BACKTAB_KEY | K_s)) || (keyCode == '\011')) keyCode = '\t'; else if (((keyCode & 0xFF00) == K_s) || (keyCode == '\010') || (keyCode == '\177')) return (FALSE); /* Check for an already full buffer */ if (expandBuffer (peDataPtr, exitFlag, returnEvent)) return (TRUE); key = keyCode & 0xFF; lineHeight = peDataPtr->peFont.ascent + peDataPtr->peFont.descent + peDataPtr->peFont.leading; endOfBuffer = peDataPtr->peBuffer + peDataPtr->peBufferCount; drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); /* Shift all character down in the buffer, and add the new character */ oldLineCount = getLineCount (peDataPtr, getStartOfPreviousLine ( peDataPtr, peDataPtr->peCursorPtr, &junk, SCREEN)); for (bufr = endOfBuffer; bufr > peDataPtr->peCursorPtr; bufr--) *bufr = *(bufr - 1); *(peDataPtr->peCursorPtr) = key; peDataPtr->peBufferCount++; /* Update the cursor position */ redrawLine = peDataPtr->peCursorRow; peDataPtr->peCursorCol += getCharWidth (peDataPtr, peDataPtr->peCursorPtr, peDataPtr->peCursorCol); peDataPtr->peVCursorCol = peDataPtr->peCursorCol; peDataPtr->peCursorPtr++; newLineCount = getLineCount (peDataPtr, getStartOfPreviousLine ( peDataPtr, peDataPtr->peCursorPtr, &junk, SCREEN)); /* Check for line wrap, or a newline character */ if ((peDataPtr->peCursorCol >= peDataPtr->peColNum) || (key == '\012')) { /* Move to the start of the next line */ peDataPtr->peCursorCol = 0; peDataPtr->peVCursorCol = 0; /* See if we need to scroll */ if (peDataPtr->peCursorRow + 1 == peDataPtr->peRowNum) { peDataPtr->peTopOfFrame += readALine (peDataPtr, peDataPtr->peTopOfFrame, &newLineFound); blockCopy (pageEdit, peDataPtr, UP, 1); displayBuffer (pageEdit, peDataPtr, peDataPtr->peRowNum - 2, peDataPtr->peRowNum); } else { blockCopy (pageEdit, peDataPtr, DOWN, peDataPtr->peCursorRow + oldLineCount); displayBuffer (pageEdit, peDataPtr, peDataPtr->peCursorRow, peDataPtr->peCursorRow + newLineCount + 1); peDataPtr->peCursorRow++; } } else { if (newLineCount == oldLineCount) { displayBuffer (pageEdit, peDataPtr, redrawLine, redrawLine + newLineCount); } else { blockCopy (pageEdit, peDataPtr, DOWN, peDataPtr->peCursorRow + oldLineCount); displayBuffer (pageEdit, peDataPtr, peDataPtr->peCursorRow, peDataPtr->peCursorRow + newLineCount); } } /* Redraw the affected area */ drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); /* Check to see if the buffer is full, or needs to be expanded */ expandBuffer (peDataPtr, exitFlag, returnEvent); return (TRUE); } \f /*************************************<->************************************* * * INT32 * peEditEvent (pageEdit, peDataPtr, keyCode, returnEvent, exitFlag) * * xrEditor * pageEdit; * xrPageEditData * peDataPtr; * UINT16 keyCode; * xrEvent * returnEvent; * INT8 exitFlag; * * Description: * ----------- * This routine is responsible for handling all of the editing keys. * * * Inputs: * ------ * pageEdit = This is the instance pointer for the page edit instance * to which the event is to be applied. * * peDataPtr = This is a pointer to the 'data' structure associated * with the instance. * * keyCode = This is the keycode into which the event mapped. * * returnEvent = This is a pointer to a partially filled out X-ray * event structure. If we need to push an X-ray event * onto the front of the input queue, we simply fill * out any additional fields necessary, and then use * this. * * exitFlag = This allows us to signal to the main event handler that * the event just handled is causing us to exit and return * to the application; this normally only occurs if the * buffer is full, is expanded, or the expansion fails. * * Outputs: * ------- * If the event is handled, then TRUE is returned, else FALSE. * * Procedures Called * ----------------- * XrInput() [input.c] * readALine() * getStartOfPreviousLine() * getLineCount() * displayBuffer() * drawCursor() * expandBuffer() * getScreenCol() * getBufCol() * *************************************<->***********************************/ static INT32 peEditEvent (pageEdit, peDataPtr, keyCode, returnEvent, exitFlag) xrEditor * pageEdit; register xrPageEditData * peDataPtr; UINT16 keyCode; xrEvent * returnEvent; INT8 * exitFlag; { register INT32 i; INT32 lineDelta; INT32 count; INT32 count2; INT32 newLineFound; INT8 * endOfBuffer; register INT8 * bufr; INT8 * previousLinePtr; INT8 * nextLinePtr; register INT8 * ptr; if ((keyCode == (BS_KEY | K_s)) || (keyCode == '\010') || (keyCode == '\177')) { /* Make sure we're not already at the start of the buffer */ if (peDataPtr->peCursorPtr == peDataPtr->peBuffer) return (TRUE); /* See if we need to scroll or wrap */ if (peDataPtr->peCursorCol != 0) { /* Move the cursor */ peDataPtr->peCursorPtr--; previousLinePtr = getStartOfPreviousLine (peDataPtr, peDataPtr->peCursorPtr, &count, SCREEN); peDataPtr->peCursorCol = getScreenCol (peDataPtr, previousLinePtr, (INT32)(peDataPtr->peCursorPtr - previousLinePtr)); peDataPtr->peVCursorCol = peDataPtr->peCursorCol; drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } else if (peDataPtr->peCursorRow == 0) { /* Scroll 1 line */ peDataPtr->peTopOfFrame = getStartOfPreviousLine (peDataPtr, peDataPtr->peTopOfFrame - 1, &count, SCREEN); peDataPtr->peCursorPtr--; peDataPtr->peCursorCol = getScreenCol (peDataPtr, peDataPtr->peTopOfFrame, (INT32)(peDataPtr->peCursorPtr - peDataPtr->peTopOfFrame)); peDataPtr->peVCursorCol = peDataPtr->peCursorCol; } else { /* Just wrap 1 line */ peDataPtr->peCursorRow--; peDataPtr->peCursorPtr--; previousLinePtr = getStartOfPreviousLine (peDataPtr, peDataPtr->peCursorPtr, &count, SCREEN); peDataPtr->peCursorCol = getScreenCol (peDataPtr, previousLinePtr, (INT32)(peDataPtr->peCursorPtr - previousLinePtr)); peDataPtr->peVCursorCol = peDataPtr->peCursorCol; } /* Delete the character under the cursor */ ptr = peDataPtr->peCursorPtr; while (ptr < (peDataPtr->peBuffer + peDataPtr->peBufferCount)) { *ptr = *(ptr+1); ptr++; } *ptr = '\0'; peDataPtr->peBufferCount --; /* Redraw */ displayBuffer (pageEdit, peDataPtr, peDataPtr->peCursorRow, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); return (TRUE); } else if (keyCode == (DEL_CHAR_KEY | K_s)) { /* Ignore, if at end of the buffer */ if (peDataPtr->peCursorPtr != (peDataPtr->peBuffer + peDataPtr->peBufferCount)) { /* Delete the character under the cursor */ ptr = peDataPtr->peCursorPtr; while (ptr < (peDataPtr->peBuffer + peDataPtr->peBufferCount)) { *ptr = *(ptr+1); ptr++; } *ptr = '\0'; peDataPtr->peBufferCount --; /* Redisplay */ displayBuffer (pageEdit, peDataPtr, peDataPtr->peCursorRow, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } return (TRUE); } else if (keyCode == (CURS_RT_KEY | K_s)) { /* Make sure we're not already at the end of the buffer */ if (peDataPtr->peCursorPtr >= (peDataPtr->peBuffer + peDataPtr->peBufferCount)) return(TRUE); /* See if we need to wrap */ count = getCharWidth (peDataPtr, peDataPtr->peCursorPtr, peDataPtr->peCursorCol); if ((*peDataPtr->peCursorPtr == '\n') || (peDataPtr->peCursorCol + count >= peDataPtr->peColNum)) { /* See if we need to scroll */ if (peDataPtr->peCursorRow + 1 == peDataPtr->peRowNum) { /* Scroll 1 line */ peDataPtr->peCursorCol = 0; peDataPtr->peVCursorCol = 0; peDataPtr->peCursorPtr ++; peDataPtr->peTopOfFrame += readALine (peDataPtr, peDataPtr->peTopOfFrame, &newLineFound); displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } else { /* No scroll; just move to next line */ drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peCursorRow++; peDataPtr->peCursorCol = 0; peDataPtr->peVCursorCol = 0; peDataPtr->peCursorPtr++; drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } } else { /* Move the cursor */ drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peCursorCol += count; peDataPtr->peVCursorCol = peDataPtr->peCursorCol; peDataPtr->peCursorPtr++; drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } return (TRUE); } else if (keyCode == (CURS_LF_KEY | K_s)) { /* Make sure we're not already at the start of the buffer */ if (peDataPtr->peCursorPtr == peDataPtr->peBuffer) return(TRUE); /* See if we need to scroll or wrap */ if (peDataPtr->peCursorCol != 0) { /* Move the cursor */ drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peCursorPtr--; previousLinePtr = getStartOfPreviousLine (peDataPtr, peDataPtr->peCursorPtr, &count, SCREEN); peDataPtr->peCursorCol = getScreenCol (peDataPtr, previousLinePtr, (INT32)(peDataPtr->peCursorPtr - previousLinePtr)); peDataPtr->peVCursorCol = peDataPtr->peCursorCol; drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } else if (peDataPtr->peCursorRow == 0) { /* Scroll 1 line */ peDataPtr->peTopOfFrame = getStartOfPreviousLine (peDataPtr, peDataPtr->peTopOfFrame - 1, &count, SCREEN); peDataPtr->peCursorPtr--; peDataPtr->peCursorCol = getScreenCol (peDataPtr, peDataPtr->peTopOfFrame, (INT32)(peDataPtr->peCursorPtr - peDataPtr->peTopOfFrame)); peDataPtr->peVCursorCol = peDataPtr->peCursorCol; displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } else { /* Just wrap 1 line */ drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peCursorRow--; peDataPtr->peCursorPtr--; previousLinePtr = getStartOfPreviousLine (peDataPtr, peDataPtr->peCursorPtr, &count, SCREEN); peDataPtr->peCursorCol = getScreenCol (peDataPtr, previousLinePtr, (INT32)(peDataPtr->peCursorPtr - previousLinePtr)); peDataPtr->peVCursorCol = peDataPtr->peCursorCol; drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } return (TRUE); } else if (keyCode == (CURS_UP_KEY | K_s)) { /* Determine if we can just move the cursor, or if we must scroll */ if (peDataPtr->peCursorRow != 0) { /* Just move the cursor */ previousLinePtr = getStartOfPreviousLine (peDataPtr, peDataPtr->peCursorPtr, &count, SCREEN); if (previousLinePtr != peDataPtr->peBuffer) { drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peCursorRow--; /* Find position of end of new line */ previousLinePtr = getStartOfPreviousLine (peDataPtr, previousLinePtr - 1, &count, SCREEN); peDataPtr->peCursorCol = getScreenCol (peDataPtr, previousLinePtr, count - 1); /* Position at shorter of line end or traveling column */ if (peDataPtr->peCursorCol > peDataPtr->peVCursorCol) peDataPtr->peCursorCol = peDataPtr->peVCursorCol; /* Compute position of character in buffer */ peDataPtr->peCursorPtr = previousLinePtr + getBufCol (peDataPtr, previousLinePtr, peDataPtr->peCursorCol); /* Adjust cursor to beginning position of character on screen */ peDataPtr->peCursorCol = getScreenCol(peDataPtr, previousLinePtr, (INT32)(peDataPtr->peCursorPtr - previousLinePtr)); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } } else { /* Need to scroll */ if (peDataPtr->peTopOfFrame != peDataPtr->peBuffer) { drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peTopOfFrame = getStartOfPreviousLine (peDataPtr, peDataPtr->peTopOfFrame - 1, &count, SCREEN); /* Find position of end of new line */ peDataPtr->peCursorCol = getScreenCol (peDataPtr, peDataPtr->peTopOfFrame, count - 1); /* Position at shorter of line end or traveling column */ if (peDataPtr->peCursorCol > peDataPtr->peVCursorCol) peDataPtr->peCursorCol = peDataPtr->peVCursorCol; /* Compute position of character in buffer */ peDataPtr->peCursorPtr = peDataPtr->peTopOfFrame + getBufCol (peDataPtr, peDataPtr->peTopOfFrame, peDataPtr->peCursorCol); /* Adjust cursor to beginning position of character on screen */ peDataPtr->peCursorCol = getScreenCol(peDataPtr, peDataPtr->peTopOfFrame, (INT32)(peDataPtr->peCursorPtr - peDataPtr->peTopOfFrame)); blockCopy (pageEdit, peDataPtr, DOWN, 0); displayBuffer (pageEdit, peDataPtr, 0, 1); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } } return (TRUE); } else if (keyCode == (CURS_DN_KEY | K_s)) { if (peDataPtr->peBufferCount == 0) return (TRUE); /* Get to beginning of previous line */ previousLinePtr = getStartOfPreviousLine (peDataPtr, peDataPtr->peCursorPtr, &count, SCREEN); /* Find beginning of next line */ nextLinePtr = previousLinePtr + readALine (peDataPtr, previousLinePtr, &newLineFound); /* Can't move if buffer end is on same screen line as cursor */ if (getStartOfPreviousLine (peDataPtr, nextLinePtr, &count, SCREEN) == previousLinePtr) return (TRUE); /* Determine if we need to scroll, or can just move the cursor */ if (peDataPtr->peCursorRow + 1 == peDataPtr->peRowNum) { /* Scroll up 1 line */ drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peTopOfFrame += readALine (peDataPtr, peDataPtr->peTopOfFrame, &newLineFound); /* Find position of the end of new line */ count = readALine (peDataPtr, nextLinePtr, &newLineFound); peDataPtr->peCursorCol = getScreenCol(peDataPtr, nextLinePtr, count); /* Position at shorter of line end or traveling column */ if (peDataPtr->peCursorCol <= peDataPtr->peVCursorCol) { /* Try to position cursor on the newline character */ if (*(nextLinePtr + count - 1) == '\n') peDataPtr->peCursorCol--; } else peDataPtr->peCursorCol = peDataPtr->peVCursorCol; /* Compute position of character in buffer */ peDataPtr->peCursorPtr = nextLinePtr + getBufCol (peDataPtr, nextLinePtr, peDataPtr->peCursorCol); /* Adjust cursor to beginning position of character on screen */ peDataPtr->peCursorCol = getScreenCol(peDataPtr, nextLinePtr, (INT32)(peDataPtr->peCursorPtr - nextLinePtr)); blockCopy (pageEdit, peDataPtr, UP, 1); displayBuffer (pageEdit, peDataPtr, peDataPtr->peRowNum - 1, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } else { /* Just move the cursor down */ drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peCursorRow++; /* Find position of end of new line */ count = readALine (peDataPtr, nextLinePtr, &newLineFound); peDataPtr->peCursorCol = getScreenCol (peDataPtr, nextLinePtr, count); /* Position at shorter of line end or traveling column */ if (peDataPtr->peCursorCol <= peDataPtr->peVCursorCol) { /* Position at shorter of line end or traveling column */ if (*(nextLinePtr + count - 1) == '\n') peDataPtr->peCursorCol--; } else peDataPtr->peCursorCol = peDataPtr->peVCursorCol; /* Compute position of character in buffer */ peDataPtr->peCursorPtr = nextLinePtr + getBufCol (peDataPtr, nextLinePtr, peDataPtr->peCursorCol); /* Adjust cursor to beginning position of character on screen */ peDataPtr->peCursorCol = getScreenCol(peDataPtr, nextLinePtr, (INT32)(peDataPtr->peCursorPtr - nextLinePtr)); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } return (TRUE); } else if (keyCode == (ROLL_DN_KEY | K_s)) { /* Determine if we can scroll down */ if (peDataPtr->peTopOfFrame == peDataPtr->peBuffer) return (TRUE); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peTopOfFrame = getStartOfPreviousLine (peDataPtr, peDataPtr->peTopOfFrame - 1, &count, SCREEN); /* Get info for the line the cursor was on */ previousLinePtr = getStartOfPreviousLine (peDataPtr, peDataPtr->peCursorPtr, &count, SCREEN); /* Find position of end of new line */ previousLinePtr = getStartOfPreviousLine (peDataPtr, previousLinePtr - 1, &count, SCREEN); peDataPtr->peCursorCol = getScreenCol (peDataPtr, previousLinePtr, count - 1); /* position at shorter of line end or traveling column */ if (peDataPtr->peCursorCol > peDataPtr->peVCursorCol) peDataPtr->peCursorCol = peDataPtr->peVCursorCol; /* Compute position of character in buffer */ peDataPtr->peCursorPtr = previousLinePtr + getBufCol (peDataPtr, previousLinePtr, peDataPtr->peCursorCol); /* Adjust cursor to beginning position of character on screen */ peDataPtr->peCursorCol = getScreenCol(peDataPtr, previousLinePtr, (INT32)(peDataPtr->peCursorPtr - previousLinePtr)); blockCopy (pageEdit, peDataPtr, DOWN, 0); displayBuffer (pageEdit, peDataPtr, 0, 1); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); return (TRUE); } else if (keyCode == (ROLL_UP_KEY | K_s)) { if (peDataPtr->peBufferCount == 0) return (TRUE); /* get to the beginning of current line */ previousLinePtr = getStartOfPreviousLine (peDataPtr, peDataPtr->peCursorPtr, &count, SCREEN); /* Find beginning of next line */ nextLinePtr = previousLinePtr + readALine (peDataPtr, previousLinePtr, &newLineFound); /* Can't move if buffer end is on same screen line as cursor */ if (getStartOfPreviousLine (peDataPtr, nextLinePtr, &count, SCREEN) == previousLinePtr) return (TRUE); /* Scroll up 1 line */ drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peTopOfFrame += readALine (peDataPtr, peDataPtr->peTopOfFrame, &newLineFound); /* Find position of end of new line */ count = readALine (peDataPtr, nextLinePtr, &newLineFound); peDataPtr->peCursorCol = getScreenCol (peDataPtr, nextLinePtr, count); /* Position at shorter of line end or traveling column */ if (peDataPtr->peCursorCol <= peDataPtr->peVCursorCol) { /* Try to position cursor on the newline character */ if (*(nextLinePtr + count - 1) == '\n') peDataPtr->peCursorCol--; } else peDataPtr->peCursorCol = peDataPtr->peVCursorCol; /* Compute position of character in buffer */ peDataPtr->peCursorPtr = nextLinePtr + getBufCol (peDataPtr, nextLinePtr, peDataPtr->peCursorCol); /* Adjust cursor to beginning position of character on screen */ peDataPtr->peCursorCol = getScreenCol(peDataPtr, nextLinePtr, (INT32)(peDataPtr->peCursorPtr - nextLinePtr)); blockCopy (pageEdit, peDataPtr, UP, 1); displayBuffer (pageEdit, peDataPtr, peDataPtr->peRowNum - 1, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); return (TRUE); } else if (keyCode == (PREV_KEY | K_s)) { /* count back rows to start of previous frame or start of buffer */ for (i=1; (i < peDataPtr->peRowNum) && (peDataPtr->peTopOfFrame != peDataPtr->peBuffer); i++) peDataPtr->peTopOfFrame = getStartOfPreviousLine (peDataPtr, peDataPtr->peTopOfFrame - 1, &count, SCREEN); peDataPtr->peVCursorCol = peDataPtr->peCursorCol = 0; peDataPtr->peCursorRow = 0; peDataPtr->peCursorPtr = peDataPtr->peTopOfFrame; displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); return (TRUE); } else if (keyCode == (NEXT_KEY | K_s)) { if (peDataPtr->peBufferCount == 0) return (TRUE); for (i=1; i < peDataPtr->peRowNum; i++) { /* Find beginning of next line */ nextLinePtr = peDataPtr->peTopOfFrame + readALine (peDataPtr, peDataPtr->peTopOfFrame, &newLineFound); /* Can't move further if buffer end is on same screen line * as top of frame */ if (getStartOfPreviousLine (peDataPtr, nextLinePtr, &count, SCREEN) == peDataPtr->peTopOfFrame) break; peDataPtr->peTopOfFrame = nextLinePtr; } peDataPtr->peVCursorCol = peDataPtr->peCursorCol = 0; peDataPtr->peCursorRow = 0; peDataPtr->peCursorPtr = peDataPtr->peTopOfFrame; displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); return (TRUE); } else if (keyCode == (HOME_UP_KEY | K_s)) { drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); peDataPtr->peVCursorCol = peDataPtr->peCursorCol = 0; peDataPtr->peCursorRow = 0; peDataPtr->peCursorPtr = peDataPtr->peBuffer; if (peDataPtr->peTopOfFrame != peDataPtr->peBuffer) { peDataPtr->peTopOfFrame = peDataPtr->peBuffer; displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); } drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); return (TRUE); } else if (keyCode == (HOME_DN_KEY | K_s)) { if (peDataPtr->peBufferCount == 0) return(TRUE); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, FALSE); previousLinePtr = getStartOfPreviousLine (peDataPtr, peDataPtr->peBuffer + peDataPtr->peBufferCount, &count, SCREEN); peDataPtr->peCursorCol = getScreenCol (peDataPtr, previousLinePtr, count); peDataPtr->peCursorPtr = previousLinePtr + count; peDataPtr->peVCursorCol = peDataPtr->peCursorCol; /* count back rows to top of frame */ for (i = 1; (i < peDataPtr->peRowNum) && (previousLinePtr != peDataPtr->peTopOfFrame); i++) previousLinePtr = getStartOfPreviousLine (peDataPtr, previousLinePtr - 1, &count, SCREEN); peDataPtr->peCursorRow = i - 1; peDataPtr->peTopOfFrame = previousLinePtr; displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); return (TRUE); } else if (keyCode == (CLR_LINE_KEY | K_s)) { /* Clear from the cursor to the next Newline character */ /* Ignore, if at end of the buffer */ if (peDataPtr->peCursorPtr >= peDataPtr->peBuffer + peDataPtr->peBufferCount) return (TRUE); /* Determine how many characters to delete */ count = 0; newLineFound = FALSE; while (!newLineFound) { count += readALine (peDataPtr, peDataPtr->peCursorPtr + count, &newLineFound); if (peDataPtr->peCursorPtr + count >= peDataPtr->peBuffer + peDataPtr->peBufferCount) break; } /* Don't delete the newline at end of line, if present */ if (*(peDataPtr->peCursorPtr + count - 1) == '\n') count--; if (count == 0) return (TRUE); /* Delete the characters */ for (ptr = peDataPtr->peCursorPtr + count; ptr < peDataPtr->peBuffer + peDataPtr->peBufferCount; ptr++) *(ptr - count) = *(ptr); peDataPtr->peBufferCount -= count; displayBuffer (pageEdit, peDataPtr, peDataPtr->peCursorRow, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); return (TRUE); } else if (keyCode == (DEL_LINE_KEY | K_s)) { /* Clear from previous Newline to the next Newline character */ /* Ignore if buffer is empty */ if (peDataPtr->peBufferCount == 0) return (TRUE); /* Determine how many characters to delete */ previousLinePtr = getStartOfPreviousLine (peDataPtr, peDataPtr->peCursorPtr, &count, SCREEN); count = 0; newLineFound = FALSE; /* Find the end of the line */ while (!newLineFound) { count += readALine (peDataPtr, previousLinePtr + count, &newLineFound); if (previousLinePtr + count >= peDataPtr->peBuffer + peDataPtr->peBufferCount) break; } /* Find the start of the line */ ptr = getStartOfPreviousLine (peDataPtr, previousLinePtr, &count2, BUFFER); count += count2 - 1; lineDelta = getLineCount (peDataPtr, ptr) - getLineCount (peDataPtr, previousLinePtr); if (count == 0) return (TRUE); /* Delete the characters */ peDataPtr->peCursorPtr = ptr; for (; ptr < peDataPtr->peBuffer + peDataPtr->peBufferCount; ptr++) *ptr = *(ptr + count); peDataPtr->peBufferCount -= count; /* Update the cursor position */ peDataPtr->peCursorCol = 0; peDataPtr->peVCursorCol = 0; if (peDataPtr->peCursorPtr < peDataPtr->peTopOfFrame) { peDataPtr->peTopOfFrame = peDataPtr->peCursorPtr; peDataPtr->peCursorRow = 0; } else peDataPtr->peCursorRow -= lineDelta; displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); return (TRUE); } else if (keyCode == (INSERT_LINE_KEY | K_s)) { /* * Insert a new line before the line at which the cursor is * currently positioned. */ /* See if the buffer is full */ if (expandBuffer (peDataPtr, exitFlag, returnEvent)) return (TRUE); /* Find the start of the line */ ptr = getStartOfPreviousLine (peDataPtr, peDataPtr->peCursorPtr, &count, BUFFER); /* Determine how many lines the cursor position will change by */ lineDelta = getLineCount (peDataPtr, ptr) - getLineCount (peDataPtr, peDataPtr->peCursorPtr - peDataPtr->peCursorCol); /* Shift buffer, and insert the newline character */ endOfBuffer = peDataPtr->peBuffer + peDataPtr->peBufferCount; for (bufr = endOfBuffer; bufr > ptr; bufr--) *bufr = *(bufr - 1); *ptr = '\n'; peDataPtr->peBufferCount++; /* * If the newline was inserted above the current top of frame, * then we need to update the top of frame, in addition to the * cursor position. */ if (ptr < peDataPtr->peTopOfFrame) { peDataPtr->peTopOfFrame = ptr; peDataPtr->peCursorRow = 0; } else peDataPtr->peCursorRow -= lineDelta; peDataPtr->peCursorPtr = ptr; peDataPtr->peCursorCol = 0; peDataPtr->peVCursorCol = 0; /* Redraw the screen */ displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); /* * Check to see if the buffer is now full, or needs to * be expanded. */ expandBuffer (peDataPtr, exitFlag, returnEvent); } else return (FALSE); } \f /*************************************<->************************************* * * xrEditor * * peActivate (pageEdit) * * xrEditor * pageEdit; * * Description: * ----------- * This is the handler for the MSG_ACTIVATE message. It will allow * an existing page edit field to be activated, only if the instance * is both visible and sensitive. After verify the parameters and * the instance's state, the instance will be redrawn as active, and * then this routine will wait for an input event to be received. * When an event is received, the main event handler will be called, * and passed the event; it will then maintain control until an * exit condition occurs. * * * Inputs: * ------ * pageEdit = This is the instance pointer for the page edit instance * which is to be activated. * * Outputs: * ------- * If the field is successfully activated, then the instance pointer * will be returned; otherwise, NULL will be returned. * * Procedures Called * ----------------- * XrInput() [input.c] * drawTextRegion() * drawCursor() * processPageEdit() * *************************************<->***********************************/ static xrEditor * peActivate (pageEdit) xrEditor * pageEdit; { xrPageEditData * peDataPtr; XEvent event; /* Validate the instance pointer */ if (pageEdit == NULL) { xrErrno = XrINVALIDID; return ((xrEditor *) NULL); } /* Fail, if the instance is not visible and sensitive */ if ((pageEdit->editorState & (XrVISIBLE | XrSENSITIVE)) != (XrVISIBLE | XrSENSITIVE)) { xrErrno = XrINVALIDPARM; return ((xrEditor *) NULL); } peDataPtr = (xrPageEditData *) pageEdit->editorData; /* Activate the field, if not already */ if (! (peDataPtr->peCursorOn)) { peDataPtr->peCursorOn = TRUE; drawTextRegion (pageEdit, XrFRAME_ONLY); drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } /* Wait for the initial input event */ while (1) { if ((XrInput (NULL, MSG_BLKREAD, &event) != FALSE) && (event.window == pageEdit->editorWindowId)) break; } /* Let the processing routine take it from here */ return (processPageEdit (pageEdit, &event)); } \f /*************************************<->************************************* * * xrEditor * * peMOVE_handler (pageEdit, ptPtr) * * xrEditor * pageEdit; * POINT * ptPtr; * * Description: * ----------- * This routine will relocate an existing page edit instance, such * that the origin of the editor rectangle is at the point indicated * by the 'ptPtr' parameter. * * * Inputs: * ------ * pageEdit = Editor instance pointer, for the instance to be moved. * * ptPtr = Pointer to a 'POINT' structure, containing new origin. * * Outputs: * ------- * Upon successful completion, the instance pointer is returned. * * Upon failure, NULL is returned, and xrErrno is set. * * Procedures Called * ----------------- * XrCopyRect() [calc.c] * _XrMakeInvisible() [editorUtil.c] * XrEditorGroup() [group.c] * drawPageEdit() * *************************************<->***********************************/ static xrEditor * peMOVE_handler (pageEdit, ptPtr) xrEditor * pageEdit; POINT * ptPtr; { RECTANGLE workRect; /* Check for invalid parameters */ if (pageEdit == NULL) { xrErrno = XrINVALIDID; return ((xrEditor *) NULL); } else if (ptPtr == NULL) { xrErrno = XrINVALIDPTR; return ((xrEditor *) NULL); } /* Save a copy of the old editor rectangle */ XrCopyRect (&pageEdit->editorRect, &workRect); /* Set the new editor rectangle origin */ pageEdit->editorRect.x = ptPtr->x; pageEdit->editorRect.y = ptPtr->y; /* Redraw the instance, if visible */ if (pageEdit->editorState & XrVISIBLE) { /* Remove the instance from the window */ _XrMakeInvisible (pageEdit->editorWindowId, &workRect, TRUE); /* Redisplay the instance at its new location */ drawPageEdit (pageEdit, NULL); } /* Force an editor group rectangle resize */ XrEditorGroup (NULL, MSG_ADJUSTGROUPRECT, pageEdit); return (pageEdit); } \f /*************************************<->************************************* * * xrEditor * * teREDRAW_handler (pageEdit, redrawMode) * * xrEditor * pageEdit; * INT32 redrawMode; * * Description: * ----------- * This is the handler routine for the MSG_REDRAW message; it is * capable of handling either an XrREDRAW_ALL or XrREDRAW_TEXT * request. These redraw the entire field, or just the editing * text. It will assume that the user has not modified the * buffer contents at all!! * * * Inputs: * ------ * pageEdit = This is the instance pointer for the instance to be * redrawn. * * redrawMode = This specifies the type of redraw to perform. This * must be set to either of the values mentioned in the * description above. * * Outputs: * ------- * Upon successful completion, the instance pointer is returned, and * the instance is redrawn (if it was visible). * * Upon failure, NULL is returned, and xrErrno is set. * * Procedures Called * ----------------- * drawPageEdit() * displayBuffer() * drawCursor() * peInitGCs() * *************************************<->***********************************/ static xrEditor * peREDRAW_handler (pageEdit, redrawMode) xrEditor * pageEdit; INT32 redrawMode; { xrPageEditData * peDataPtr; /* Validate the instance pointer and the redraw mode */ if (pageEdit == NULL) { xrErrno = XrINVALIDID; return ((xrEditor *) NULL); } else if (redrawMode == XrREDRAW_ALL) { if (pageEdit->editorState & XrVISIBLE) drawPageEdit (pageEdit, NULL); return (pageEdit); } else if (redrawMode == XrREDRAW_TEXT) { if (pageEdit->editorState & XrVISIBLE) { peDataPtr = (xrPageEditData *) pageEdit->editorData; peInitGCs (peDataPtr); displayBuffer (pageEdit, peDataPtr, 0, peDataPtr->peRowNum); if (peDataPtr->peCursorOn) drawCursor (pageEdit, pageEdit->editorWindowId, peDataPtr, TRUE); } return (pageEdit); } else { xrErrno = XrINVALIDOPTION; return ((xrEditor *) NULL); } } \f /*************************************<->************************************* * * peInitGCs (peDataPtr) * * xrPageEditData * peDataPtr; * * Description: * ----------- * This routine initializes 6 graphics context structures. * These include ones used for drawing the wide border, ones used * for drawing a sensitive instance, and also ones used for drawing * the hashed text string displayed in an insensitive page edit instance. * * * Inputs: * ------ * peDataPtr = This points to the internal 'data' structure associated * with instance for which these graphic contexts are being * initialized; this structure contains the font and color * information. * * Outputs: * ------- * The graphic contexts references by the defines xrEditorGC1, * xrEditorGC2, xrEditorGC3, xrEditorGC4, xrEditorGC5 and xrEditorGC6 * will be set. * * Procedures Called * ----------------- * _XrCopyGC() [gcUtil.c] * _XrChangeGC() [gcUtil.c] * *************************************<->***********************************/ static peInitGCs (peDataPtr) xrPageEditData * peDataPtr; { INT32 changeList[21]; INT32 changeMask; /* Initialize the standard graphic contexts we will be using */ _XrInitEditorGCs (peDataPtr->peFGColor, peDataPtr->peBGColor, peDataPtr->peFont.fontInfo->id); /* * Initialize the graphics context used to draw * the background for an insensitive page edit instance, * and the wide border. */ _XrCopyGC (xrDefaultGC, xrEditorGC3); changeList[XrFOREGROUNDVAL] = peDataPtr->peFGColor; changeList[XrBACKGROUNDVAL] = peDataPtr->peBGColor; changeList[XrLINEWIDTHVAL] = BORDER; changeList[XrTILEVAL] = peDataPtr->peTileId; changeList[XrFILLSTYLEVAL] = Tiled; changeMask = (XrTILE | XrFILLSTYLE | XrFOREGROUND | XrBACKGROUND | XrLINEWIDTH); _XrChangeGC (xrEditorGC3, changeMask, changeList); /* * Initialize the two graphics contexts used to draw an insensitive * editing string. */ _XrCopyGC (xrDefaultGC, xrEditorGC4); changeList[XrFOREGROUNDVAL] = 0; changeList[XrBACKGROUNDVAL] = AllPlanes; changeList[XrFONTVAL] = peDataPtr->peFont.fontInfo->id; changeList[XrALUVAL] = GXand; changeMask = (XrFOREGROUND | XrBACKGROUND | XrFONT | XrALU); _XrChangeGC (xrEditorGC4, changeMask, changeList); _XrCopyGC (xrDefaultGC, xrEditorGC5); changeList[XrFOREGROUNDVAL] = peDataPtr->peFGColor; changeList[XrBACKGROUNDVAL] = 0; changeList[XrFONTVAL] = peDataPtr->peFont.fontInfo->id; changeList[XrALUVAL] = GXor; changeMask = (XrFOREGROUND | XrBACKGROUND | XrFONT | XrALU); _XrChangeGC (xrEditorGC5, changeMask, changeList); /* GC used for drawing over the wide border */ _XrCopyGC (xrDefaultGC, xrEditorGC6); changeList[XrFOREGROUNDVAL] = peDataPtr->peBGColor; changeList[XrBACKGROUNDVAL] = peDataPtr->peFGColor; changeList[XrLINEWIDTHVAL] = BORDER - 1; changeMask = (XrFOREGROUND | XrBACKGROUND | XrLINEWIDTH); _XrChangeGC (xrEditorGC6, changeMask, changeList); } \f /*************************************<->************************************* * * INT32 * drawTextRegion (pageEdit, components) * * xrEditor * pageEdit; * INT32 components; * * Description: * ----------- * This routine draws only the editing region (the border and the * interior of the instance); the actual text data is not displayed * here. If the 'components' parameter is set to XrALLCOMPONENTS, * then both the frame and the interior of the instance will be * drawn. If the 'components' parameter is set to XrFRAME_ONLY, * then only the frame is drawn. XrALLCOMPONENTS is normally used * only when the complete instance needs to be redrawn. XrFRAME_ONLY * is used when the field is to be activated and deactivated, and * we only want the frame redrawn. * * * Inputs: * ------ * pageEdit = The instance pointer for the instance to be drawn. * * components = The portion of the instance to be redrawn, as explained * above. * * Outputs: * ------- * * Procedures Called * ----------------- * XrCopyRect() [calc.c] * _XrRectangle() [rectUtil.c] * _XrBorderFillRectangle() [rectUtil.c] * *************************************<->***********************************/ static INT32 drawTextRegion (pageEdit, components) xrEditor * pageEdit; INT32 components; { RECTANGLE frameRect; xrPageEditData * peDataPtr = (xrPageEditData *) pageEdit->editorData; /* * If the field is active, then draw a wide border, else * draw a narrow border. The frame definition will need * to be adjusted to take into account the wide border, * because X does wierd things with wide line drawing. */ XrCopyRect (&pageEdit->editorRect, &frameRect); if (peDataPtr->peCursorOn) { /* Draw the field as active */ frameRect.width -= BORDER - 1; frameRect.height -= BORDER - 1; /* Draw a wide border, and fill, if requested */ if (components == XrFRAME_ONLY) _XrRectangle (pageEdit->editorWindowId, xrEditorGC3, &frameRect); else if (pageEdit->editorState & XrSENSITIVE) _XrBorderFillRectangle (pageEdit->editorWindowId, xrEditorGC3, xrEditorGC2, &frameRect); else _XrBorderFillRectangle (pageEdit->editorWindowId, xrEditorGC3, xrEditorGC3, &frameRect); } else { /* Draw the field as inactive */ if (components == XrFRAME_ONLY) { /* Draw the narrow border */ _XrRectangle (pageEdit->editorWindowId, xrEditorGC1, &frameRect); frameRect.x += 1; frameRect.y += 1; frameRect.width -= BORDER; frameRect.height -= BORDER; _XrRectangle (pageEdit->editorWindowId, xrEditorGC6, &frameRect); return; } /* Draw a narrow border, and fill the interior */ if (pageEdit->editorState & XrSENSITIVE) _XrBorderFillRectangle (pageEdit->editorWindowId, xrEditorGC1, xrEditorGC2, &frameRect); else _XrBorderFillRectangle (pageEdit->editorWindowId, xrEditorGC1, xrEditorGC3, &frameRect); } } \f /*************************************<->************************************* * * INT32 * drawCursor (pageEdit, windowId, peDataPtr, showing) * * xrEditor * pageEdit; * Window windowId; * xrPageEditData * peDataPtr; * INT32 showing; * * Description: * ----------- * This routine will draw the cursor at the current cursor position, * if 'showing' is set to TRUE, or it will remove the cursor, if * 'showing' is set to FALSE. When drawing the cursor, if either * no character is defined at the cursor position, or a newline is * at the cursor position, then the SPACE character will be used; if * a printable character is at the cursor position, then it will be * redrawn, to look as if a block cursor were on top of it. * * * Inputs: * ------ * pageEdit = This is the instance pointer for the instance which is * to have its cursor modified. * * windowId = The window Id for the window to which the instance is * attached. * * peDataPtr = Pointer to the instance's internal 'data' structure. * * showing = 'TRUE' if cursor should be drawn as visible, else FALSE. * * Outputs: * ------- * * Procedures Called * ----------------- * _XrImageText8() [textUtil.c] * *************************************<->***********************************/ static INT32 drawCursor (pageEdit, windowId, peDataPtr, showing) xrEditor * pageEdit; Window windowId; register xrPageEditData * peDataPtr; INT32 showing; { register INT8 * cursorLoc; INT8 cursorChar; register INT32 penX, penY; register xrTextInfo * fontPtr; cursorLoc = peDataPtr->peCursorPtr; /* Determine what character the cursor will sit on top of */ if ((*cursorLoc == '\n') || (*cursorLoc == '\t') || (cursorLoc == peDataPtr->peBuffer + peDataPtr->peBufferCount)) { cursorChar = ' '; } else if ((*cursorLoc & '\340') == 0) /* control char */ cursorChar = '^'; else cursorChar = *cursorLoc; fontPtr = &peDataPtr->peFont; penX = pageEdit->editorRect.x + PADDING + BORDER + (fontPtr->maxWidth * peDataPtr->peCursorCol), penY = pageEdit->editorRect.y + PADDING + BORDER + (peDataPtr->peCursorRow * (fontPtr->ascent + fontPtr->descent + fontPtr->leading)); if (showing) _XrImageText8 (windowId, xrEditorGC2, 1, penX, penY, &cursorChar); else _XrImageText8 (windowId, xrEditorGC1, 1, penX, penY, &cursorChar); } \f /*************************************<->************************************* * * INT32 * readALine (peDataPtr, start, newLineFound) * * xrPageEditData * peDataPtr; * INT8 * start; * INT32 newLineFound; * * Description: * ----------- * Starting at the specified position within the editing buffer, * this routine will extract a single screen line of data, and * return the number of bytes in the line. When extracting a line, * it will continue until either the end of the buffer is encountered, * a newline is encountered, or 1 full screen line is obtained. * In addition, upon return, the 'newLineFound' parameter will specify * if it was a newline character which caused the scan to stop. * The starting point must be at the beginning of a screen line, or * else this routine will not work correctly. * * * Inputs: * ------ * peDataPtr = This is a pointer to the internal data structure * associated with the instance being manipulated. * * start = This is the point at which the scan will start. IT MUST * POINT AT THE BEGINNING OF A LINE, OR THIS ROUTINE WILL * NOT WORK!! * * newLineFound = If the scan stops because a newline character is * encountered, then this will be set to TRUE; for * any other stopping reason, this will be set to * FALSE. * * Outputs: * ------- * Upon completion, the value pointed to by 'newLineFound' will be * set as described above; also, the number of bytes in the * line will be returned. * * Procedures Called * ----------------- * getCharWidth() * *************************************<->***********************************/ static INT32 readALine (peDataPtr, start, newLineFound) register xrPageEditData * peDataPtr; register INT8 * start; INT32 * newLineFound; { register INT8 * end = start; register INT32 cursorCol = 0; register INT8 * EOF = peDataPtr->peBuffer + peDataPtr->peBufferCount; *newLineFound = FALSE; /* Extract upto a single display line */ while ((end < EOF) && (cursorCol < peDataPtr->peColNum) && (*newLineFound == FALSE)) { if (*end == '\n') *newLineFound = TRUE; cursorCol += getCharWidth (peDataPtr, end, cursorCol); end++; } return (end - start); } \f /*************************************<->************************************* * * INT32 * printALine (pageEdit, peDataPtr, start, count, line) * * xrEditor * pageEdit; * xrPageEditData * peDataPtr; * INT8 * start; * INT32 count; * INT32 line; * * Description: * ----------- * This routine will print a single screen line starting at the * screen line specified by the 'line' parameter; It does not * print lines starting at any point other than the left margin. * If a line has a newline character at the end, 'count' should * not include this; this routine does not know how to handle a * newline character. A routine calling this can use the 'line' * parameter to get the effect of a newline. * * If the instance is sensitive, then the text is displayed using * the foreground color. If the instance is insensitive, then the * text is displayed in a hashed form. * * * Inputs: * ------ * pageEdit = This is the editor instance pointer. * * peDataPtr = This points to the instance's internal data. * * start = This points to the start of the line, within the buffer. * * count = This specifies the number of characters in the line. * * line = This specifies the screen line at which the text is to appear. * * Outputs: * ------- * * Procedures Called * ----------------- * _XrImageText8() [textUtil.c] * XrStringWidth() [utilities.c] * *************************************<->***********************************/ static INT32 printALine (pageEdit, peDataPtr, start, count, line) xrEditor * pageEdit; xrPageEditData * peDataPtr; INT8 * start; INT32 count; INT32 line; { INT16 penX, penY, lineHeight; INT8 * EOF = start+count; INT8 * end; INT8 * printBufPtr; INT8 printBuf[2]; INT32 printCount; INT32 printCol; /* Calculate the pen position */ lineHeight = peDataPtr->peFont.ascent + peDataPtr->peFont.descent + peDataPtr->peFont.leading; penX = pageEdit->editorRect.x + BORDER + PADDING; penY = pageEdit->editorRect.y + BORDER + PADDING + (line * lineHeight); printCol = 0; for (end = start; end != EOF; start = end) { if (*start == '\t') /* tab */ { printBufPtr = peDataPtr->peBlanks; printCount = getCharWidth (peDataPtr, start, printCol); if ((printCol + printCount) > peDataPtr->peColNum) printCount = peDataPtr->peColNum - printCol; printCol += printCount; end = start + 1; } else if ((*start & '\340') == 0) /* control char */ { printBufPtr = printBuf; printBuf[0] = '^'; printBuf[1] = *start | '\100'; printCount = 2; if ((printCol + printCount) > peDataPtr->peColNum) printCount = peDataPtr->peColNum - printCol; printCol += printCount; end = start + 1; } else /* normal char */ { printBufPtr = start; printCount = 0; while ((end != EOF) && (*end != '\t') && ((*end & '\340') != 0)) { printCount++; printCol++; end++; } } if (pageEdit->editorState & XrSENSITIVE) _XrImageText8 (pageEdit->editorWindowId, xrEditorGC1, printCount, penX, penY, printBufPtr); else { /* Draw the text as insensitive */ _XrImageText8 (pageEdit->editorWindowId, xrEditorGC4, printCount, penX, penY, printBufPtr); _XrImageText8 (pageEdit->editorWindowId, xrEditorGC5, printCount, penX, penY, printBufPtr); } penX = penX + XrStringWidth (peDataPtr->peFont.fontInfo, printBufPtr, printCount, 0, 0); } /* pad out the rest of the line */ if (pageEdit->editorState & XrSENSITIVE) _XrImageText8 (pageEdit->editorWindowId, xrEditorGC1, peDataPtr->peColNum - printCol, penX, penY, peDataPtr->peBlanks); else { _XrImageText8 (pageEdit->editorWindowId, xrEditorGC4, peDataPtr->peColNum - printCol, penX, penY, peDataPtr->peBlanks); _XrImageText8 (pageEdit->editorWindowId, xrEditorGC5, peDataPtr->peColNum - count, penX, penY, peDataPtr->peBlanks); } } \f /*************************************<->************************************* * * INT32 * displayBuffer (pageEdit, peDataPtr, firstLine) * * xrEditor * pageEdit; * xrPageEditData * peDataPtr; * INT32 firstLine; * * Description: * ----------- * This routine displays the contents of the editing buffer, starting * at the screen line specified by 'firstLine', and ending at the end * of the editing region. It is used to repaint the screen, after * most editing functions. * * * Inputs: * ------ * pageEdit = This is the instance pointer. * * peDataPtr = This points to the instance's internal data. * * firstLine = This specifies where, in screen lines, the redisplay * is to start. * * Outputs: * ------- * * Procedures Called * ----------------- * readALine() * printALine() * *************************************<->***********************************/ static INT32 displayBuffer (pageEdit, peDataPtr, firstLine, stopAtLine) register xrEditor * pageEdit; register xrPageEditData * peDataPtr; register INT32 firstLine; register INT32 stopAtLine; { register INT8 * start = peDataPtr->peTopOfFrame; register INT8 * EOB; register INT32 currentLine = 0; INT32 count; INT32 newLineFound; INT32 lineHt; RECTANGLE drawRect; EOB = peDataPtr->peBuffer + peDataPtr->peBufferCount; if (stopAtLine > peDataPtr->peRowNum) stopAtLine = peDataPtr->peRowNum; if (firstLine < 0) firstLine = 0; /* Skip to the request line */ while (currentLine < firstLine) { count = readALine (peDataPtr, start, &newLineFound); currentLine++; start += count; } /* Display the request lines */ while (firstLine < stopAtLine) { /* Check for end of buffer */ if (start >= EOB) { /* Fill the remainder of the window */ lineHt = peDataPtr->peFont.ascent + peDataPtr->peFont.descent + peDataPtr->peFont.leading; drawRect.x = pageEdit->editorRect.x + BORDER + PADDING; drawRect.y = pageEdit->editorRect.y + BORDER + PADDING + (firstLine * lineHt); drawRect.height = (peDataPtr->peRowNum - firstLine) * lineHt; drawRect.width = pageEdit->editorRect.width - (BORDER << 1) - (PADDING << 1); _XrFillRectangle (pageEdit->editorWindowId, xrEditorGC2, &drawRect); break; } count = readALine (peDataPtr, start, &newLineFound); printALine (pageEdit, peDataPtr, start, (newLineFound ? count - 1 : count), firstLine); firstLine ++; start += count; } } \f /*************************************<->************************************* * * INT8 * * getStartOfPreviousLine (peDataPtr, bufPtr, count, mode) * * xrPageEditData * peDataPtr; * INT8 * bufPtr; * INT32 * count; * INT32 mode; * * Description: * ----------- * Given a pointer to the end of a screen line, this routine will * return a pointer to the start of that line. If mode is set to * "SCREEN", then it will be the start of that screen line (not * including any wrapping to a previous screen line). If mode is * set to "BUFFER", then it will be the start of complete line. * In addition, it also returns the number of characters in the * line, including the NEWLINE character if ther is one. * * * Inputs: * ------ * peDataPtr = This points to the instance's internal data. * * bufPtr = This is the pointer to the end of a screen line. * * count = This points to an INT32 value, into which the number * of bytes in the line minus 1 is placed. * * mode = SCREEN or BUFFER, as described above. * * Outputs: * ------- * Returns a pointer to the start of the line, along with the * number of bytes (as described above). * * Procedures Called * ----------------- * readALine() * getScreenCol() * *************************************<->***********************************/ INT8 * getStartOfPreviousLine (peDataPtr, bufPtr, count, mode) register xrPageEditData * peDataPtr; register INT8 * bufPtr; register INT32 * count; INT32 mode; { register INT8 * nextLinePtr; register INT8 * currentLinePtr = bufPtr; INT32 newLineFound; register INT8 * EOF = peDataPtr->peBuffer + peDataPtr->peBufferCount; *count = 1; /* Look for the start of the previous line */ while((currentLinePtr != peDataPtr->peBuffer) && (*(currentLinePtr - 1) != '\n')) { (*count)++; currentLinePtr--; } /* Determine how much of the line fits */ if (mode == SCREEN) { /* Scan forward for screen line that contains bufPtr */ nextLinePtr = currentLinePtr; while ((nextLinePtr <= bufPtr) && (nextLinePtr != EOF)) { currentLinePtr = nextLinePtr; nextLinePtr += readALine (peDataPtr, currentLinePtr, &newLineFound); } /* wrap if bufPtr is at end of last line that is full */ if ((bufPtr == EOF) && (getScreenCol(peDataPtr, currentLinePtr, (INT32)(nextLinePtr - currentLinePtr)) >= peDataPtr->peColNum)) currentLinePtr = nextLinePtr; *count = nextLinePtr - currentLinePtr; } return (currentLinePtr); } \f /*************************************<->************************************* * * INT32 * getLineCount (peDataPtr, bufPtr) * * xrPageEditData * peDataPtr; * INT8 * bufPtr; * * Description: * ----------- * Starting at the beginning of a screen line, as specified by the * 'bufPtr' parameter, this routine will determine how many screen * lines are occupied by that line. The scan continues until either * the end of the buffer is encountered, or a newline is found. * * * Inputs: * ------ * peDataPtr = This points to the instance's internal data. * * bufPtr = This points to the start of the screen line. * * Outputs: * ------- * The number of screen lines is returned. * * Procedures Called * ----------------- * readALine() * getScreenCol() * *************************************<->***********************************/ static INT32 getLineCount (peDataPtr, bufPtr) register xrPageEditData * peDataPtr; register INT8 * bufPtr; { register INT32 lineCount = 0; register INT32 count; register INT8 * EOF = peDataPtr->peBuffer + peDataPtr->peBufferCount; INT32 newLineFound = FALSE; while (!newLineFound) { count = readALine (peDataPtr, bufPtr, &newLineFound); lineCount++; if (bufPtr + count == EOF) { /* Count extra line when full last line wraps */ if (getScreenCol(peDataPtr, bufPtr, count) >= peDataPtr->peColNum) lineCount++; break; } bufPtr += count; } return (lineCount); } \f /*************************************<->************************************* * * INT32 * getCharWidth (peDataPtr, chrPtr, chrCol) * * xrPageEditData * peDataPtr; * INT8 * chrPtr; * INT32 * chrCol; * * Description: * ----------- * Determines the display width of the character pointed to by * 'chrPtr', which is to be displayed starting in column 'chrCol' * in the display. * * * Inputs: * ------ * peDataPtr = This points to the instance's internal data. * * chrPtr = This points to the character whose display width is required * * chrCol = This is the column in which the character is displayed * * Outputs: * ------- * The display width of the character * * Procedures Called * ----------------- * *************************************<->***********************************/ static INT32 getCharWidth (peDataPtr, chrPtr, chrCol) xrPageEditData * peDataPtr; INT8 * chrPtr; INT32 chrCol; { register INT32 chrWidth; if (*chrPtr == '\t') /* tab character */ chrWidth = peDataPtr->peTabWidth - (chrCol % peDataPtr->peTabWidth); else if (*chrPtr == '\n') /* newline character */ chrWidth = 1; else if ((*chrPtr == '\010') || (*chrPtr == '\177')) /* backspace */ chrWidth = -1; else if ((*chrPtr & '\340') == 0) /* control character */ chrWidth = 2; else /* normal character */ chrWidth = 1; return (chrWidth); } \f /*************************************<->************************************* * * INT32 * getScreenCol (peDataPtr, bufStartPtr, bufCol) * * xrPageEditData * peDataPtr; * INT8 * bufStartPtr * INT32 bufCol * * Description: * ----------- * Determines the screen column of a character given the buffer column * and a pointer to beginning of the line * * * Inputs: * ------ * peDataPtr = This is a pointer to the internal data structure * associated with the instance being manipulated. * * bufStartPtr = This is a pointer to the character position in the buffer * POINT AT THE BEGINNING OF A LINE, OR THIS ROUTINE WILL * NOT WORK!! * * bufCol = This is the byte offset in the buffer from the start of line * * Outputs: * ------- * Returns the screen column corresponding to the given buffer column * * Procedures Called * ----------------- * getCharWidth() * *************************************<->***********************************/ static INT32 getScreenCol (peDataPtr, bufStartPtr, bufCol) xrPageEditData * peDataPtr; INT8 * bufStartPtr; INT32 bufCol; { INT32 screenCol = 0; register INT32 i; for (i=0; i < bufCol; i++) { screenCol += getCharWidth (peDataPtr, bufStartPtr, screenCol); bufStartPtr++; } return (screenCol); } \f /*************************************<->************************************* * * INT32 * getBufCol (peDataPtr, bufStartPtr, screenCol) * * xrPageEditData * peDataPtr; * INT8 * bufStartPtr * INT32 screenCol * * Description: * ----------- * Determines the buffer column of a character given the screen column * and a pointer to beginning of the line * * * Inputs: * ------ * peDataPtr = This is a pointer to the internal data structure * associated with the instance being manipulated. * * bufStartPtr = This is a pointer to the character position in the buffer * POINT AT THE BEGINNING OF A LINE, OR THIS ROUTINE WILL * NOT WORK!! * * screenCol = This is the screen position of the character in the line * * Outputs: * ------- * Returns the buffer column corresponding to the given screen column * * Procedures Called * ----------------- * getCharWidth() * *************************************<->***********************************/ static INT32 getBufCol (peDataPtr, bufStartPtr, screenCol) xrPageEditData * peDataPtr; INT8 * bufStartPtr; INT32 screenCol; { INT8 * bufPtr = bufStartPtr; register INT32 i = 0; while ((i += getCharWidth (peDataPtr, bufPtr, i)) <= screenCol) bufPtr++; return (bufPtr - bufStartPtr); } \f /*************************************<->************************************* * * INT32 * expandBuffer (peDataPtr, exitFlag, returnEvent) * * xrPageEditData * peDataPtr; * INT8 * exitFlag; * xrEvent * returnEvent; * * Description: * ----------- * This routine checks to see if the buffer has reached its end. * If so, one of several things will happen. If the buffer is as * large as the application will allow it, then a "BUFFER FULL" * event will be pushed onto the front of the input queue, and * control will return to the application. Otherwise, an attempt * will be made to expand the buffer. If this succeeds, then a * "BUFFER EXPANDED" event will be pushed onto the front of the * input queue, and control will return to the application. If * the buffer expansion fails, then a "BUFFER EXPAND FAILED" event * will be pushed onto the front of the input queue, and control * will return to the application. * * * Inputs: * ------ * peDataPtr = Pointer to the instance's internal data. * * exitFlag = Set to TRUE if control must be returned to the * application, because an event was pushed. * * returnEvent = Pointer to a partially filled out X-ray event. * This will be used to push any return events. * * Outputs: * ------- * If the buffer cannot be expanded, for one reason or another, then * a value of TRUE is returned; otherwise, FALSE is returned. A * TRUE value tells the routine which called us that it is NOT * safe to add anymore characters. * * Procedures Called * ----------------- * XrInput() [input.c] * *************************************<->***********************************/ static INT32 expandBuffer (peDataPtr, exitFlag, returnEvent) xrPageEditData * peDataPtr; INT8 * exitFlag; xrEvent * returnEvent; { register INT8 * bufr; INT32 delta; INT32 cursorOffset; INT32 frameOffset; if (peDataPtr->peBufferCount == peDataPtr->peMaxSize) { /* The buffer has reached the application imposed limit */ returnEvent->value1 = XrBUFFER_FULL; *exitFlag = TRUE; XrInput (NULL, MSG_PUSHEVENT, returnEvent); return (TRUE); } else if (peDataPtr->peBufferCount == peDataPtr->peBufferSize) { /* Determine how much to expand the buffer by */ delta = ((peDataPtr->peMaxSize == -1) || (peDataPtr->peMaxSize - peDataPtr->peBufferSize > 5120)) ? 5120 : (peDataPtr->peMaxSize - peDataPtr->peBufferSize); cursorOffset = peDataPtr->peCursorPtr - peDataPtr->peBuffer; frameOffset = peDataPtr->peTopOfFrame - peDataPtr->peBuffer; /* Attempt to expand the buffer */ if ((bufr = (char *) (*xrRealloc)(peDataPtr->peBuffer, delta)) == NULL) { /* Buffer expansion failed */ returnEvent->value1 = XrBUFEXPANDFAILED; *exitFlag = TRUE; XrInput (NULL, MSG_PUSHEVENT, returnEvent); return (TRUE); } else { /* * Tell the application the buffer has expanded, and potentially * moved. */ returnEvent->value1 = XrBUFEXPANDED; *exitFlag = TRUE; XrInput (NULL, MSG_PUSHEVENT, returnEvent); peDataPtr->peBuffer = bufr; peDataPtr->peBufferSize += delta; peDataPtr->peCursorPtr = peDataPtr->peBuffer + cursorOffset; peDataPtr->peTopOfFrame = peDataPtr->peBuffer + frameOffset; return (FALSE); } } return (FALSE); } \f /*************************************<->************************************* * * ProcedureName (parameters) * * Description: * ----------- * xxxxxxxxxxxxxxxxxxxxxxx * * * Inputs: * ------ * xxxxxxxxxxxx = xxxxxxxxxxxxx * * Outputs: * ------- * xxxxxxxxxxxx = xxxxxxxxxxxxx * * Procedures Called * ----------------- * *************************************<->***********************************/ static INT32 blockCopy (pageEdit, peDataPtr, direction, startLine) register xrEditor * pageEdit; register xrPageEditData * peDataPtr; INT32 direction; INT32 startLine; { INT32 lineHt; INT32 X, srcY, dstY; INT32 height, width; lineHt = peDataPtr->peFont.ascent + peDataPtr->peFont.descent + peDataPtr->peFont.leading; /* Determine the region to be moved */ X = pageEdit->editorRect.x + PADDING + BORDER; srcY = pageEdit->editorRect.y + PADDING + BORDER + (startLine * lineHt); width = pageEdit->editorRect.width - (BORDER << 1) - (PADDING << 1); if (direction == UP) { dstY = pageEdit->editorRect.y + PADDING + BORDER + ((startLine - 1) * lineHt); height = lineHt * (peDataPtr->peRowNum - startLine); } else { dstY = pageEdit->editorRect.y + PADDING + BORDER + ((startLine + 1) * lineHt); height = lineHt * (peDataPtr->peRowNum - startLine - 1); } XMoveArea (pageEdit->editorWindowId, X, srcY, X, dstY, width, height); }