#if (!defined(lint) && !defined(SABER)) static char Xrcsid[] = "$XConsortium: TextAction.c,v 1.23 89/12/10 11:30:43 rws Exp $"; #endif /* lint && SABER */ /*********************************************************** Copyright 1989 by the Massachusetts Institute of Technology, Cambridge, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of Digital or MIT not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* * NOTE: There are some ASCII Dependancies on '\n' and '\0' that I * am not too thrilled with. There is also the implicit assumption * that the individual characters will fit inside a "char". * It would be nice if we could generalize this a but more. If * anyone out there comes up with an implementation of this stuff * that has no dependency on ASCII, please send the code back to us. * * Chris D. Peterson * MIT X Consortium */ #include #include /* For atoi() */ #include #include /* For XFetchBuffer() */ #include #include #include #include #include #include <./Xaw3_1TextP.h> #define SrcScan XawTextSourceScan #define FindDist XawTextSinkFindDistance #define FindPos XawTextSinkFindPosition /* * These are defined in TextPop.c */ void _XawTextInsertFileAction(), _XawTextInsertFile(), _XawTextSearch(); void _XawTextSearch(), _XawTextDoSearchAction(), _XawTextDoReplaceAction(); void _XawTextSetField(), _XawTextPopdownSearchAction(); /* * These are defined in Text.c */ char * _XawTextGetText(); void _XawTextBuildLineTable(), _XawTextAlterSelection(), _XawTextVScroll(); void _XawTextSetSelection(), _XawTextCheckResize(), _XawTextExecuteUpdate(); void _XawTextSetScrollBars(), _XawTextClearAndCenterDisplay(); Atom *_XawTextSelectionList(); void _XawTextPrepareToUpdate(TextWidget ctx); int _XawTextReplace(TextWidget ctx, XawTextPosition pos1, XawTextPosition pos2, XawTextBlock *text); static void StartAction(ctx, event) TextWidget ctx; XEvent *event; { _XawTextPrepareToUpdate(ctx); if (event != NULL) { switch (event->type) { case ButtonPress: case ButtonRelease: ctx->text.time = event->xbutton.time; ctx->text.ev_x = event->xbutton.x; ctx->text.ev_y = event->xbutton.y; break; case KeyPress: case KeyRelease: ctx->text.time = event->xkey.time; ctx->text.ev_x = event->xkey.x; ctx->text.ev_y = event->xkey.y; break; case MotionNotify: ctx->text.time = event->xmotion.time; ctx->text.ev_x = event->xmotion.x; ctx->text.ev_y = event->xmotion.y; break; case EnterNotify: case LeaveNotify: ctx->text.time = event->xcrossing.time; ctx->text.ev_x = event->xcrossing.x; ctx->text.ev_y = event->xcrossing.y; } } } static void EndAction(ctx) TextWidget ctx; { _XawTextCheckResize(ctx); _XawTextExecuteUpdate(ctx); ctx->text.mult = 1; } #ifdef XAW_BC /* * These functions are superceeded by insert-selection. */ static void StuffFromBuffer(ctx, buffer) TextWidget ctx; int buffer; { XawTextBlock text; text.ptr = XFetchBuffer(XtDisplay(ctx), &(text.length), buffer); text.firstPos = 0; if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { XBell(XtDisplay(ctx), 0); return; } ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, XawsdRight, text.length, TRUE); XtFree(text.ptr); } static void UnKill(ctx, event) TextWidget ctx; XEvent *event; { StartAction(ctx, event); StuffFromBuffer(ctx, 1); EndAction(ctx); } static void Stuff(ctx, event) TextWidget ctx; XEvent *event; { StartAction(ctx, event); StuffFromBuffer(ctx, 0); EndAction(ctx); } #endif /* XAW_BC */ struct _SelectionList { String *params; Cardinal count; Time time; }; static void GetSelection(); /* ARGSUSED */ static void _SelectionReceived(w, client_data, selection, type, value, length, format) Widget w; caddr_t client_data; Atom *selection, *type; caddr_t value; unsigned long *length; int *format; { TextWidget ctx = (TextWidget)w; XawTextBlock text; if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0) { struct _SelectionList* list = (struct _SelectionList*)client_data; if (list != NULL) { GetSelection(w, list->time, list->params, list->count); XtFree(client_data); } return; } StartAction(ctx, (XEvent *)NULL); text.ptr = (char*)value; text.firstPos = 0; text.length = *length; text.format = FMT8BIT; if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { XBell(XtDisplay(ctx), 0); return; } ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, XawsdRight, text.length, TRUE); EndAction(ctx); _XawTextSetScrollBars(ctx); XtFree(client_data); XtFree(value); } static void GetSelection(w, time, params, num_params) Widget w; Time time; String *params; /* selections in precedence order */ Cardinal num_params; { Atom selection; int buffer; XmuInternStrings(XtDisplay(w), params, (Cardinal)1, &selection); switch (selection) { case XA_CUT_BUFFER0: buffer = 0; break; case XA_CUT_BUFFER1: buffer = 1; break; case XA_CUT_BUFFER2: buffer = 2; break; case XA_CUT_BUFFER3: buffer = 3; break; case XA_CUT_BUFFER4: buffer = 4; break; case XA_CUT_BUFFER5: buffer = 5; break; case XA_CUT_BUFFER6: buffer = 6; break; case XA_CUT_BUFFER7: buffer = 7; break; default: buffer = -1; } if (buffer >= 0) { int nbytes; unsigned long length; int fmt8 = 8; Atom type = XA_STRING; char *line = XFetchBuffer(XtDisplay(w), &nbytes, buffer); if (length = nbytes) _SelectionReceived(w, (caddr_t)NULL, &selection, &type, (caddr_t)line, &length, &fmt8); else if (num_params > 1) GetSelection(w, time, params+1, num_params-1); } else { struct _SelectionList* list; if (--num_params) { list = XtNew(struct _SelectionList); list->params = params + 1; list->count = num_params; list->time = time; } else list = NULL; XtGetSelectionValue(w, selection, XA_STRING, (XtSelectionCallbackProc)_SelectionReceived, (caddr_t)list, time); } } static void InsertSelection(w, event, params, num_params) Widget w; XEvent *event; String *params; /* precedence list of selections to try */ Cardinal *num_params; { StartAction((TextWidget)w, event); /* Get Time. */ GetSelection(w, ((TextWidget)w)->text.time, params, *num_params); EndAction((TextWidget)w); } /************************************************************ * * Routines for Moving Around. * ************************************************************/ static void Move(ctx, event, dir, type, include) TextWidget ctx; XEvent *event; XawTextScanDirection dir; XawTextScanType type; Boolean include; { StartAction(ctx, event); ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, type, dir, ctx->text.mult, include); EndAction(ctx); } static void MoveForwardChar(w, event) Widget w; XEvent *event; { Move((TextWidget) w, event, XawsdRight, XawstPositions, TRUE); } static void MoveBackwardChar(w, event) Widget w; XEvent *event; { Move((TextWidget) w, event, XawsdLeft, XawstPositions, TRUE); } static void MoveForwardWord(w, event) Widget w; XEvent *event; { Move((TextWidget) w, event, XawsdRight, XawstWhiteSpace, FALSE); } static void MoveBackwardWord(w, event) Widget w; XEvent *event; { Move((TextWidget) w, event, XawsdLeft, XawstWhiteSpace, FALSE); } static void MoveForwardParagraph(w, event) Widget w; XEvent *event; { Move((TextWidget) w, event, XawsdRight, XawstParagraph, FALSE); } static void MoveBackwardParagraph(w, event) Widget w; XEvent *event; { Move((TextWidget) w, event, XawsdLeft, XawstParagraph, FALSE); } static void MoveToLineEnd(w, event) Widget w; XEvent *event; { Move((TextWidget) w, event, XawsdRight, XawstEOL, FALSE); } static void MoveToLineStart(w, event) Widget w; XEvent *event; { Move((TextWidget) w, event, XawsdLeft, XawstEOL, FALSE); } static void MoveLine(ctx, event, dir) TextWidget ctx; XEvent *event; XawTextScanDirection dir; { XawTextPosition new, next_line, junk; int from_left, garbage; StartAction(ctx, event); if (dir == XawsdLeft) ctx->text.mult++; new = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, XawsdLeft, 1, FALSE); FindDist(ctx->text.sink, new, ctx->text.margin.left, ctx->text.insertPos, &from_left, &junk, &garbage); new = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir, ctx->text.mult, (dir == XawsdRight)); next_line = SrcScan(ctx->text.source, new, XawstEOL, XawsdRight, 1, FALSE); FindPos(ctx->text.sink, new, ctx->text.margin.left, from_left, FALSE, &(ctx->text.insertPos), &garbage, &garbage); if (ctx->text.insertPos > next_line) ctx->text.insertPos = next_line; EndAction(ctx); } static void MoveNextLine(w, event) Widget w; XEvent *event; { MoveLine( (TextWidget) w, event, XawsdRight); } static void MovePreviousLine(w, event) Widget w; XEvent *event; { MoveLine( (TextWidget) w, event, XawsdLeft); } static void MoveBeginningOfFile(w, event) Widget w; XEvent *event; { Move((TextWidget) w, event, XawsdLeft, XawstAll, TRUE); } static void MoveEndOfFile(w, event) Widget w; XEvent *event; { Move((TextWidget) w, event, XawsdRight, XawstAll, TRUE); } static void Scroll(ctx, event, dir) TextWidget ctx; XEvent *event; XawTextScanDirection dir; { StartAction(ctx, event); if (dir == XawsdLeft) _XawTextVScroll(ctx, ctx->text.mult); else _XawTextVScroll(ctx, -ctx->text.mult); EndAction(ctx); } static void ScrollOneLineUp(w, event) Widget w; XEvent *event; { Scroll( (TextWidget) w, event, XawsdLeft); } static void ScrollOneLineDown(w, event) Widget w; XEvent *event; { Scroll( (TextWidget) w, event, XawsdRight); } static void MovePage(ctx, event, dir) TextWidget ctx; XEvent *event; XawTextScanDirection dir; { int scroll_val = Max(1, ctx->text.lt.lines - 2); if (dir == XawsdLeft) scroll_val = -scroll_val; StartAction(ctx, event); _XawTextVScroll(ctx, scroll_val); ctx->text.insertPos = ctx->text.lt.top; EndAction(ctx); } static void MoveNextPage(w, event) Widget w; XEvent *event; { MovePage((TextWidget) w, event, XawsdRight); } static void MovePreviousPage(w, event) Widget w; XEvent *event; { MovePage((TextWidget) w, event, XawsdLeft); } /************************************************************ * * Delete Routines. * ************************************************************/ static void _DeleteOrKill(ctx, from, to, kill) TextWidget ctx; XawTextPosition from, to; Boolean kill; { XawTextBlock text; char *ptr; if (kill && from < to) { ptr = _XawTextGetText(ctx, from, to); XStoreBuffer(XtDisplay(ctx), ptr, strlen(ptr), 1); XtFree(ptr); } text.length = 0; text.firstPos = 0; if (_XawTextReplace(ctx, from, to, &text)) { XBell(XtDisplay(ctx), 50); return; } ctx->text.insertPos = from; ctx->text.showposition = TRUE; } static void DeleteOrKill(ctx, event, dir, type, include, kill) TextWidget ctx; XEvent *event; XawTextScanDirection dir; XawTextScanType type; Boolean include, kill; { XawTextPosition from, to; StartAction(ctx, event); to = SrcScan(ctx->text.source, ctx->text.insertPos, type, dir, ctx->text.mult, include); if (dir == XawsdLeft) { from = to; to = ctx->text.insertPos; } else from = ctx->text.insertPos; _DeleteOrKill(ctx, from, to, kill); _XawTextSetScrollBars(ctx); EndAction(ctx); } static void DeleteForwardChar(w, event) Widget w; XEvent *event; { DeleteOrKill((TextWidget) w, event, XawsdRight, XawstPositions, TRUE, FALSE); } static void DeleteBackwardChar(w, event) Widget w; XEvent *event; { DeleteOrKill((TextWidget) w, event, XawsdLeft, XawstPositions, TRUE, FALSE); } static void DeleteForwardWord(w, event) Widget w; XEvent *event; { DeleteOrKill((TextWidget) w, event, XawsdRight, XawstWhiteSpace, FALSE, FALSE); } static void DeleteBackwardWord(w, event) Widget w; XEvent *event; { DeleteOrKill((TextWidget) w, event, XawsdLeft, XawstWhiteSpace, FALSE, FALSE); } static void KillForwardWord(w, event) Widget w; XEvent *event; { DeleteOrKill((TextWidget) w, event, XawsdRight, XawstWhiteSpace, FALSE, TRUE); } static void KillBackwardWord(w, event) TextWidget w; XEvent *event; { DeleteOrKill((TextWidget) w, event, XawsdLeft, XawstWhiteSpace, FALSE, TRUE); } static void KillToEndOfLine(w, event) Widget w; XEvent *event; { TextWidget ctx = (TextWidget) w; XawTextPosition end_of_line; StartAction(ctx, event); end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, XawsdRight, ctx->text.mult, FALSE); if (end_of_line == ctx->text.insertPos) end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, XawsdRight, ctx->text.mult, TRUE); _DeleteOrKill(ctx, ctx->text.insertPos, end_of_line, TRUE); EndAction(ctx); _XawTextSetScrollBars(ctx); } static void KillToEndOfParagraph(w, event) Widget w; XEvent *event; { DeleteOrKill((TextWidget) w, event, XawsdRight, XawstParagraph, FALSE, TRUE); } void _XawTextZapSelection(ctx, event, kill) TextWidget ctx; XEvent *event; Boolean kill; { StartAction(ctx, event); _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill); EndAction(ctx); _XawTextSetScrollBars(ctx); } static void KillCurrentSelection(w, event) Widget w; XEvent *event; { _XawTextZapSelection( (TextWidget) w, event, TRUE); } static void DeleteCurrentSelection(w, event) Widget w; XEvent *event; { _XawTextZapSelection( (TextWidget) w, event, FALSE); } /************************************************************ * * Insertion Routines. * ************************************************************/ static int InsertNewLineAndBackupInternal(ctx) TextWidget ctx; { int count, error = XawEditDone; XawTextBlock text; char *buf, *ptr; ptr = buf = XtMalloc(sizeof(char) * ctx->text.mult); for (count = 0; count < ctx->text.mult; count++, ptr++) ptr[0] = '\n'; text.length = ctx->text.mult; text.ptr = buf; text.firstPos = 0; text.format = FMT8BIT; if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { XBell( XtDisplay(ctx), 50); error = XawEditError; } else ctx->text.showposition = TRUE; XtFree(buf); return(error); } static void InsertNewLineAndBackup(w, event) Widget w; XEvent *event; { StartAction( (TextWidget) w, event ); (void) InsertNewLineAndBackupInternal( (TextWidget) w ); EndAction( (TextWidget) w ); _XawTextSetScrollBars( (TextWidget) w); } static int LocalInsertNewLine(ctx, event) TextWidget ctx; XEvent *event; { StartAction(ctx, event); if (InsertNewLineAndBackupInternal(ctx) == XawEditError) return(XawEditError); ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, XawsdRight, ctx->text.mult, TRUE); EndAction(ctx); _XawTextSetScrollBars(ctx); return(XawEditDone); } static void InsertNewLine(w, event) Widget w; XEvent *event; { (void) LocalInsertNewLine( (TextWidget) w, event); } static void InsertNewLineAndIndent(w, event) Widget w; XEvent *event; { XawTextBlock text; XawTextPosition pos1, pos2; TextWidget ctx = (TextWidget) w; StartAction(ctx, event); pos1 = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, XawsdLeft, 1, FALSE); pos2 = SrcScan(ctx->text.source, pos1, XawstEOL, XawsdLeft, 1, TRUE); pos2 = SrcScan(ctx->text.source, pos2, XawstWhiteSpace, XawsdRight, 1, TRUE); text.ptr = _XawTextGetText(ctx, pos1, pos2); text.length = strlen(text.ptr); if (LocalInsertNewLine(ctx, event)) return; text.firstPos = 0; if (_XawTextReplace(ctx,ctx->text.insertPos, ctx->text.insertPos, &text)) { XBell(XtDisplay(ctx), 50); EndAction(ctx); return; } ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, XawsdRight, text.length, TRUE); XtFree(text.ptr); EndAction(ctx); _XawTextSetScrollBars(ctx); } /************************************************************ * * Selection Routines. * *************************************************************/ static void SelectWord(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { TextWidget ctx = (TextWidget) w; XawTextPosition l, r; StartAction(ctx, event); l = SrcScan(ctx->text.source, ctx->text.insertPos, XawstWhiteSpace, XawsdLeft, 1, FALSE); r = SrcScan(ctx->text.source, l, XawstWhiteSpace, XawsdRight, 1, FALSE); _XawTextSetSelection(ctx, l, r, params, *num_params); EndAction(ctx); } static void SelectAll(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { TextWidget ctx = (TextWidget) w; StartAction(ctx, event); _XawTextSetSelection(ctx,zeroPosition,ctx->text.lastPos,params,*num_params); EndAction(ctx); } static void ModifySelection(ctx, event, mode, action, params, num_params) TextWidget ctx; XEvent *event; XawTextSelectionMode mode; XawTextSelectionAction action; String *params; /* unused */ Cardinal *num_params; /* unused */ { StartAction(ctx, event); _XawTextAlterSelection(ctx, mode, action, params, num_params); EndAction(ctx); } /* ARGSUSED */ static void SelectStart(w, event, params, num_params) Widget w; XEvent *event; String *params; /* unused */ Cardinal *num_params; /* unused */ { ModifySelection((TextWidget) w, event, XawsmTextSelect, XawactionStart, params, num_params); } /* ARGSUSED */ static void SelectAdjust(w, event, params, num_params) Widget w; XEvent *event; String *params; /* unused */ Cardinal *num_params; /* unused */ { ModifySelection((TextWidget) w, event, XawsmTextSelect, XawactionAdjust, params, num_params); } static void SelectEnd(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { ModifySelection((TextWidget) w, event, XawsmTextSelect, XawactionEnd, params, num_params); } /* ARGSUSED */ static void ExtendStart(w, event, params, num_params) Widget w; XEvent *event; String *params; /* unused */ Cardinal *num_params; /* unused */ { ModifySelection((TextWidget) w, event, XawsmTextExtend, XawactionStart, params, num_params); } /* ARGSUSED */ static void ExtendAdjust(w, event, params, num_params) Widget w; XEvent *event; String *params; /* unused */ Cardinal *num_params; /* unused */ { ModifySelection((TextWidget) w, event, XawsmTextExtend, XawactionAdjust, params, num_params); } static void ExtendEnd(w, event, params, num_params) TextWidget w; XEvent *event; String *params; Cardinal *num_params; { ModifySelection((TextWidget) w, event, XawsmTextExtend, XawactionEnd, params, num_params); } /************************************************************ * * Misc. Routines. * ************************************************************/ /* ARGSUSED */ static void RedrawDisplay(w, event) Widget w; XEvent *event; { StartAction( (TextWidget) w, event); _XawTextClearAndCenterDisplay((TextWidget) w); EndAction( (TextWidget) w); } /*ARGSUSED*/ static void TextFocusIn (w, event) TextWidget w; XEvent *event; { TextWidget ctx = (TextWidget) w; ctx->text.hasfocus = TRUE; } /*ARGSUSED*/ static void TextFocusOut(w, event) TextWidget w; XEvent *event; { TextWidget ctx = (TextWidget) w; ctx->text.hasfocus = FALSE; } static XComposeStatus compose_status = {NULL, 0}; /* Function Name: AutoFill * Description: Breaks the line at the previous word boundry when * called inside InsertChar. * Arguments: ctx - The text widget. * Returns: none */ static void AutoFill(ctx) TextWidget ctx; { int width, height, x, line_num, max_width; XawTextPosition ret_pos; XawTextBlock text; if ( !((ctx->text.auto_fill) && (ctx->text.mult == 1)) ) return; for ( line_num = 0; line_num < ctx->text.lt.lines ; line_num++) if ( ctx->text.lt.info[line_num].position >= ctx->text.insertPos ) break; line_num--; /* backup a line. */ max_width = Max(0, ctx->core.width - HMargins(ctx)); x = ctx->text.margin.left; XawTextSinkFindPosition( ctx->text.sink,ctx->text.lt.info[line_num].position, x, max_width, TRUE, &ret_pos, &width, &height); if ( ret_pos >= ctx->text.insertPos ) return; text.ptr = "\n"; text.length = 1; text.firstPos = 0; text.format = FMT8BIT; _XawTextReplace(ctx, ret_pos - 1, ret_pos, &text); } static void InsertChar(w, event) Widget w; XEvent *event; { TextWidget ctx = (TextWidget) w; char *ptr, strbuf[BUFSIZ]; int count, error; KeySym keysym; XawTextBlock text; if ( (text.length = XLookupString (&event->xkey, strbuf, BUFSIZ, &keysym, &compose_status)) == 0) { return; } text.ptr = ptr = XtMalloc(sizeof(char) * text.length * ctx->text.mult); for (count = 0 ; count < ctx->text.mult ; count++) { strncpy(ptr, strbuf, text.length); ptr += text.length; } text.length = text.length * ctx->text.mult; text.firstPos = 0; text.format = FMT8BIT; StartAction(ctx, event); error = _XawTextReplace(ctx, ctx->text.insertPos,ctx->text.insertPos, &text); if (error == XawEditDone) { ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, XawsdRight, text.length, TRUE); AutoFill(ctx); } else XBell(XtDisplay(ctx), 50); XtFree(text.ptr); EndAction(ctx); _XawTextSetScrollBars(ctx); } /*ARGSUSED*/ static void InsertString(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { TextWidget ctx = (TextWidget) w; XawTextBlock text; int i; text.firstPos = 0; StartAction(ctx, event); for (i = *num_params; i; i--, params++) { unsigned char hexval; if ((*params)[0] == '0' && (*params)[1] == 'x' && (*params)[2] != '\0') { char c, *p; hexval = 0; for (p = *params+2; (c = *p); p++) { hexval *= 16; if (c >= '0' && c <= '9') hexval += c - '0'; else if (c >= 'a' && c <= 'f') hexval += c - 'a' + 10; else if (c >= 'A' && c <= 'F') hexval += c - 'A' + 10; else break; } if (c == '\0') { text.ptr = (char*)&hexval; text.length = 1; } else text.length = strlen(text.ptr = *params); } else text.length = strlen(text.ptr = *params); if (text.length == 0) continue; if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { XBell(XtDisplay(ctx), 50); EndAction(ctx); return; } ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, XawsdRight, text.length, TRUE); } EndAction(ctx); } static void DisplayCaret(w, event, params, num_params) Widget w; XEvent *event; /* CrossingNotify special-cased */ String *params; /* Off, False, No, On, True, Yes, etc. */ Cardinal *num_params; /* 0, 1 or 2 */ { TextWidget ctx = (TextWidget)w; Boolean display_caret = True; if (event->type == EnterNotify || event->type == LeaveNotify) { /* for Crossing events, the default case is to check the focus * field and only change the caret when focus==True. A second * argument of "always" will cause the focus field to be ignored. */ Boolean check_focus = True; if (*num_params == 2 && strcmp(params[1], "always") == 0) check_focus = False; if (check_focus && !event->xcrossing.focus) return; } if (*num_params > 0) { /* default arg is "True" */ XrmValue from, to; from.size = strlen(from.addr = params[0]); XtConvert(w, XtRString, &from, XtRBoolean, &to); if (to.addr != NULL) display_caret = *(Boolean*)to.addr; if (ctx->text.display_caret == display_caret) return; } StartAction(ctx, event); ctx->text.display_caret = display_caret; EndAction(ctx); } /* Function Name: Multiply * Description: Multiplies the current action by the number passed. * Arguments: w - the text widget. * event - ** NOT USED **. * params, num_params - The parameter list, see below. * Returns: none. * * Parameter list; * * The parameter list may contain either a number or the string 'Reset'. * * A number will multiply the current multiplication factor by that number. * Many of the text widget actions will will perform n actions, where n is * the multiplication factor. * * The string reset will reset the mutiplication factor to 1. * */ /* ARGSUSED */ static void Multiply(w, event, params, num_params) Widget w; XEvent *event; String * params; Cardinal * num_params; { TextWidget ctx = (TextWidget) w; int mult; if (*num_params != 1) { XtAppError(XtWidgetToApplicationContext(w), "The multiply action takes exactly one argument."); XBell(XtDisplay(w), 0); return; } if ( (params[0][0] == 'r') || (params[0][0] == 'R') ) { XBell(XtDisplay(w), 0); ctx->text.mult = 1; return; } if ( (mult = atoi(params[0])) == 0 ) { char buf[BUFSIZ]; sprintf(buf, "%s %s", "Text Widget: The multiply action's argument", "must be a number greater than zero, or 'Reset'."); XtAppError(XtWidgetToApplicationContext(w), buf); XBell(XtDisplay(w), 0); return; } ctx->text.mult *= mult; } /* Function Name: StripOutOldCRs * Description: strips out the old carrige returns. * Arguments: ctx - the text widget. * from - starting point. * to - the ending point * Returns: the new ending location (we may add some caracters). */ static XawTextPosition StripOutOldCRs(ctx, from, to) TextWidget ctx; XawTextPosition from, to; { XawTextPosition startPos, endPos, eop_begin, eop_end, temp; Widget src = ctx->text.source; XawTextBlock text; char *buf; text.ptr= " "; text.firstPos = 0; text.format = FMT8BIT; /* * Strip out CR's. */ eop_begin = eop_end = startPos = endPos = from; while (TRUE) { endPos=SrcScan(src, startPos, XawstEOL, XawsdRight, 1, FALSE); temp=SrcScan(src, endPos, XawstWhiteSpace, XawsdLeft, 1, FALSE); temp=SrcScan(src, temp, XawstWhiteSpace, XawsdRight, 1, FALSE); if (temp > startPos) endPos = temp; if (endPos >= to) break; if (endPos >= eop_begin) { startPos = eop_end; eop_begin = SrcScan(src, startPos, XawstParagraph, XawsdRight, 1, FALSE); eop_end = SrcScan(src, startPos, XawstParagraph, XawsdRight, 1, TRUE); } else { XawTextPosition periodPos, next_word; int i, len; periodPos= SrcScan(src, endPos, XawstPositions, XawsdLeft, 1, TRUE); next_word = SrcScan(src, endPos, XawstWhiteSpace, XawsdRight, 1, FALSE); len = next_word - periodPos; text.length = 1; buf = _XawTextGetText(ctx, periodPos, next_word); if ( (periodPos < endPos) && (buf[0] == '.') ) text.length++; /* Put in two spaces. */ /* * Remove all extra spaces. */ for (i = 1 ; i < len; i++) if ( !isspace(buf[i]) || ((periodPos + i) >= to) ) { break; } XtFree(buf); to -= (i - text.length - 1); startPos = SrcScan(src, periodPos, XawstPositions, XawsdRight, i, TRUE); _XawTextReplace(ctx, endPos, startPos, &text); startPos -= i - text.length; } } return(to); } /* Function Name: InsertNewCRs * Description: Inserts the new Carrige Returns. * Arguments: ctx - the text widget. * from, to - the ends of the region. * Returns: none */ static void InsertNewCRs(ctx, from, to) TextWidget ctx; XawTextPosition from, to; { XawTextPosition startPos, endPos, space, eol; XawTextBlock text; int i, width, height, len; char * buf; text.ptr = "\n"; text.length = 1; text.firstPos = 0; text.format = FMT8BIT; startPos = from; while (TRUE) { XawTextSinkFindPosition( ctx->text.sink, startPos, (int) ctx->text.margin.left, (int) (ctx->core.width - HMargins(ctx)), TRUE, &eol, &width, &height); if (eol >= to) break; eol = SrcScan(ctx->text.source, eol, XawstPositions, XawsdLeft, 1, TRUE); space= SrcScan(ctx->text.source, eol, XawstWhiteSpace, XawsdRight, 1,TRUE); startPos = endPos = eol; if (eol == space) return; len = (int) (space - eol); buf = _XawTextGetText(ctx, eol, space); for ( i = 0 ; i < len ; i++) if (!isspace(buf[i])) break; to -= (i - 1); endPos = SrcScan(ctx->text.source, endPos, XawstPositions, XawsdRight, i, TRUE); XtFree(buf); _XawTextReplace(ctx, startPos, endPos, &text); startPos = SrcScan(ctx->text.source, startPos, XawstPositions, XawsdRight, 1, TRUE); } } /* Function Name: FormRegion * Description: Forms up the region specified. * Arguments: ctx - the text widget. * from, to - the ends of the region. * Returns: none. */ static void FormRegion(ctx, from, to) TextWidget ctx; XawTextPosition from, to; { if (from >= to) return; to = StripOutOldCRs(ctx, from, to); InsertNewCRs(ctx, from, to); _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE); } /* Function Name: FromParagraph. * Description: reforms up the current paragraph. * Arguments: w - the text widget. * event - the X event. * params, num_params *** NOT USED ***. * Returns: none */ /* ARGSUSED */ static void FormParagraph(w, event, params, num_params) Widget w; XEvent *event; String * params; Cardinal * num_params; { TextWidget ctx = (TextWidget) w; XawTextPosition from, to; StartAction(ctx, event); from = SrcScan(ctx->text.source, ctx->text.insertPos, XawstParagraph, XawsdLeft, 1, FALSE); to = SrcScan(ctx->text.source, from, XawstParagraph, XawsdRight, 1, FALSE); FormRegion(ctx, from, to); EndAction(ctx); _XawTextSetScrollBars(ctx); } /* Function Name: TransposeCharacters * Description: Swaps the character to the left of the mark with * the character to the right of the mark. * Arguments: w - the text widget. * event - the event that cause this action. * params, num_params *** NOT USED ***. * Returns: none. */ /* ARGSUSED */ static void TransposeCharacters(w, event, params, num_params) Widget w; XEvent *event; String * params; Cardinal * num_params; { TextWidget ctx = (TextWidget) w; XawTextPosition start, end; XawTextBlock text; unsigned char * buf, c; int i; StartAction(ctx, event); /* * Get bounds. */ start = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, XawsdLeft, 1, TRUE); end = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, XawsdRight, ctx->text.mult, TRUE); if ( (start == ctx->text.insertPos) || (end == ctx->text.insertPos) ) XBell(XtDisplay(w), 0); /* complain. */ else { ctx->text.insertPos = end; /* * Retrieve text and swap the characters. */ buf = (unsigned char *) _XawTextGetText(ctx, start, end); text.length = strlen((const char *)buf); text.firstPos = 0; text.format = FMT8BIT; c = buf[0]; for (i = 1 ; i < text.length ; i++) buf[i - 1] = buf[i]; buf[i - 1] = c; /* * Store new text is source. */ text.ptr = (char *) buf; _XawTextReplace (ctx, start, end, &text); XtFree((caddr_t)buf); } EndAction(ctx); } /* Function Name: NoOp * Description: This action performs no action, and allows * the user or application programmer to unbind a * translation. * Arguments: w - the text widget. * event - *** UNUSED ***. * parms and num_params - the action parameters. * Returns: none. * * Note: If the parameter list contains the string "RingBell" then * this action will ring the bell. */ static void NoOp(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { if (*num_params != 1) return; switch(params[0][0]) { case 'R': case 'r': XBell(XtDisplay(w), 0); default: /* Fall Through */ break; } } /* Action Table */ XtActionsRec textActionsTable[] = { /* motion bindings */ {"forward-character", (XtActionProc)MoveForwardChar}, {"backward-character", (XtActionProc)MoveBackwardChar}, {"forward-word", (XtActionProc)MoveForwardWord}, {"backward-word", (XtActionProc)MoveBackwardWord}, {"forward-paragraph", (XtActionProc)MoveForwardParagraph}, {"backward-paragraph", (XtActionProc)MoveBackwardParagraph}, {"beginning-of-line", (XtActionProc)MoveToLineStart}, {"end-of-line", (XtActionProc)MoveToLineEnd}, {"next-line", (XtActionProc)MoveNextLine}, {"previous-line", (XtActionProc)MovePreviousLine}, {"next-page", (XtActionProc)MoveNextPage}, {"previous-page", (XtActionProc)MovePreviousPage}, {"beginning-of-file", (XtActionProc)MoveBeginningOfFile}, {"end-of-file", (XtActionProc)MoveEndOfFile}, {"scroll-one-line-up", (XtActionProc)ScrollOneLineUp}, {"scroll-one-line-down", (XtActionProc)ScrollOneLineDown}, /* delete bindings */ {"delete-next-character", (XtActionProc)DeleteForwardChar}, {"delete-previous-character", (XtActionProc)DeleteBackwardChar}, {"delete-next-word", (XtActionProc)DeleteForwardWord}, {"delete-previous-word", (XtActionProc)DeleteBackwardWord}, {"delete-selection", (XtActionProc)DeleteCurrentSelection}, /* kill bindings */ {"kill-word", (XtActionProc)KillForwardWord}, {"backward-kill-word", (XtActionProc)KillBackwardWord}, {"kill-selection", (XtActionProc)KillCurrentSelection}, {"kill-to-end-of-line", (XtActionProc)KillToEndOfLine}, {"kill-to-end-of-paragraph", (XtActionProc)KillToEndOfParagraph}, #ifdef XAW_BC /* unkill bindings */ {"unkill", (XtActionProc)UnKill}, {"stuff", (XtActionProc)Stuff}, #endif /* XAW_BC */ /* new line stuff */ {"newline-and-indent", (XtActionProc)InsertNewLineAndIndent}, {"newline-and-backup", (XtActionProc)InsertNewLineAndBackup}, {"newline", (XtActionProc)InsertNewLine}, /* Selection stuff */ {"select-word", (XtActionProc)SelectWord}, {"select-all", (XtActionProc)SelectAll}, {"select-start", (XtActionProc)SelectStart}, {"select-adjust", (XtActionProc)SelectAdjust}, {"select-end", (XtActionProc)SelectEnd}, {"extend-start", (XtActionProc)ExtendStart}, {"extend-adjust", (XtActionProc)ExtendAdjust}, {"extend-end", (XtActionProc)ExtendEnd}, {"insert-selection", (XtActionProc)InsertSelection}, /* Miscellaneous */ {"redraw-display", (XtActionProc)RedrawDisplay}, {"insert-file", (XtActionProc)_XawTextInsertFile}, {"search", (XtActionProc)_XawTextSearch}, {"insert-char", (XtActionProc)InsertChar}, {"insert-string", (XtActionProc)InsertString}, {"focus-in", (XtActionProc)TextFocusIn}, {"focus-out", (XtActionProc)TextFocusOut}, {"display-caret", (XtActionProc)DisplayCaret}, {"multiply", (XtActionProc)Multiply}, {"form-paragraph", (XtActionProc)FormParagraph}, {"transpose-characters", (XtActionProc)TransposeCharacters}, {"no-op", (XtActionProc)NoOp}, /* Action to bind special translations for text Dialogs. */ {"InsertFileAction", (XtActionProc)_XawTextInsertFileAction}, {"DoSearchAction", (XtActionProc)_XawTextDoSearchAction}, {"DoReplaceAction", (XtActionProc)_XawTextDoReplaceAction}, {"SetField", (XtActionProc)_XawTextSetField}, {"PopdownSearchAction", (XtActionProc)_XawTextPopdownSearchAction}, }; Cardinal textActionsTableCount = XtNumber(textActionsTable);