|
|
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);
}