diff options
Diffstat (limited to 'src/TextAction.c')
-rw-r--r-- | src/TextAction.c | 5546 |
1 files changed, 3854 insertions, 1692 deletions
diff --git a/src/TextAction.c b/src/TextAction.c index a6a8c17..2fd34de 100644 --- a/src/TextAction.c +++ b/src/TextAction.c @@ -25,282 +25,481 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. */ +/* $XFree86: xc/lib/Xaw/TextAction.c,v 3.46 2002/03/20 05:06:23 paulo Exp $ */ + +#include <stdio.h> +#include <stdlib.h> +#include <X11/Xos.h> /* for select() and struct timeval */ +#include <ctype.h> #include <X11/IntrinsicP.h> #include <X11/StringDefs.h> -#include <X11/Xutil.h> #include <X11/Xatom.h> +#include <X11/Xfuncs.h> +#include <X11/Xutil.h> +#include <X11/Xmu/Atoms.h> #include <X11/Xmu/Misc.h> -#include <X11/Xmu/StdSel.h> /* for XmuConvertStandardSelection */ -#include <X11/Xmu/Atoms.h> /* for XA_COMPOUND_TEXT */ -#include <X11/Xaw/TextP.h> +#include <X11/Xmu/StdSel.h> +#include <X11/Xmu/SysUtil.h> +#include <X11/Xaw/MultiSinkP.h> #include <X11/Xaw/MultiSrcP.h> +#include <X11/Xaw/TextP.h> +#include <X11/Xaw/TextSrcP.h> #include <X11/Xaw/XawImP.h> -#include <X11/Xfuncs.h> +#include "Private.h" #include "XawI18n.h" -#include <stdio.h> -#include <ctype.h> -#define SrcScan XawTextSourceScan -#define FindDist XawTextSinkFindDistance -#define FindPos XawTextSinkFindPosition +#define SrcScan XawTextSourceScan +#define FindDist XawTextSinkFindDistance +#define FindPos XawTextSinkFindPosition +#define MULT(w) (w->text.mult == 0 ? 4 : \ + w->text.mult == 32767 ? -4 : w->text.mult) + +#define KILL_RING_APPEND 2 +#define KILL_RING_BEGIN 3 +#define KILL_RING_YANK 100 +#define KILL_RING_YANK_DONE 98 + +#define XawTextActionMaxHexChars 100 + +/* + * Prototypes + */ +static void _DeleteOrKill(TextWidget, XawTextPosition, XawTextPosition, Bool); +static void _SelectionReceived(Widget, XtPointer, Atom*, Atom*, XtPointer, + unsigned long*, int*); +static void _LoseSelection(Widget, Atom*, char**, int*); +static void AutoFill(TextWidget); +static Boolean ConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*, + unsigned long*, int*); +static void DeleteOrKill(TextWidget, XEvent*, XawTextScanDirection, + XawTextScanType, Bool, Bool); +static void EndAction(TextWidget); +#ifndef OLDXAW +static Bool BlankLine(Widget, XawTextPosition, int*); +static int DoFormatText(TextWidget, XawTextPosition, Bool, int, + XawTextBlock*, XawTextPosition*, int, Bool); +static int FormatText(TextWidget, XawTextPosition, Bool, + XawTextPosition*, int); +static Bool GetBlockBoundaries(TextWidget, XawTextPosition*, XawTextPosition*); +#endif +static int FormRegion(TextWidget, XawTextPosition, XawTextPosition, + XawTextPosition*, int); +static void GetSelection(Widget, Time, String*, Cardinal); +static char *IfHexConvertHexElseReturnParam(char*, int*); +static void InsertNewCRs(TextWidget, XawTextPosition, XawTextPosition, + XawTextPosition*, int); +static int InsertNewLineAndBackupInternal(TextWidget); +static int LocalInsertNewLine(TextWidget, XEvent*); +static void LoseSelection(Widget, Atom*); +static void ParameterError(Widget, String); +static Bool MatchSelection(Atom, XawTextSelection*); +static void ModifySelection(TextWidget, XEvent*, XawTextSelectionMode, + XawTextSelectionAction, String*, Cardinal*); +static void Move(TextWidget, XEvent*, XawTextScanDirection, XawTextScanType, + Bool); +static void NotePosition(TextWidget, XEvent*); +static void StartAction(TextWidget, XEvent*); +static XawTextPosition StripOutOldCRs(TextWidget, XawTextPosition, + XawTextPosition, XawTextPosition*, int); +#ifndef OLDXAW +static Bool StripSpaces(TextWidget, XawTextPosition, XawTextPosition, + XawTextPosition*, int, XawTextBlock*); +static Bool Tabify(TextWidget, XawTextPosition, XawTextPosition, + XawTextPosition*, int, XawTextBlock*); +static Bool Untabify(TextWidget, XawTextPosition, XawTextPosition, + XawTextPosition*, int, XawTextBlock*); +#endif -#define XawTextActionMaxHexChars 100 +/* + * Actions + */ +static void CapitalizeWord(Widget, XEvent*, String*, Cardinal*); +static void DisplayCaret(Widget, XEvent*, String*, Cardinal*); +static void Delete(Widget, XEvent*, String*, Cardinal*); +static void DeleteBackwardChar(Widget, XEvent*, String*, Cardinal*); +static void DeleteBackwardWord(Widget, XEvent*, String*, Cardinal*); +static void DeleteCurrentSelection(Widget, XEvent*, String*, Cardinal*); +static void DeleteForwardChar(Widget, XEvent*, String*, Cardinal*); +static void DeleteForwardWord(Widget, XEvent*, String*, Cardinal*); +static void DowncaseWord(Widget, XEvent*, String*, Cardinal*); +static void ExtendAdjust(Widget, XEvent*, String*, Cardinal*); +static void ExtendEnd(Widget, XEvent*, String*, Cardinal*); +static void ExtendStart(Widget, XEvent*, String*, Cardinal*); +static void FormParagraph(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void Indent(Widget, XEvent*, String*, Cardinal*); +#endif +static void InsertChar(Widget, XEvent*, String*, Cardinal*); +static void InsertNewLine(Widget, XEvent*, String*, Cardinal*); +static void InsertNewLineAndBackup(Widget, XEvent*, String*, Cardinal*); +static void InsertNewLineAndIndent(Widget, XEvent*, String*, Cardinal*); +static void InsertSelection(Widget, XEvent*, String*, Cardinal*); +static void InsertString(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void KeyboardReset(Widget, XEvent*, String*, Cardinal*); +#endif +static void KillBackwardWord(Widget, XEvent*, String*, Cardinal*); +static void KillCurrentSelection(Widget, XEvent*, String*, Cardinal*); +static void KillForwardWord(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void KillRingYank(Widget, XEvent*, String*, Cardinal*); +#endif +static void KillToEndOfLine(Widget, XEvent*, String*, Cardinal*); +static void KillToEndOfParagraph(Widget, XEvent*, String*, Cardinal*); +static void MoveBackwardChar(Widget, XEvent*, String*, Cardinal*); +static void MoveBackwardWord(Widget, XEvent*, String*, Cardinal*); +static void MoveBackwardParagraph(Widget, XEvent*, String*, Cardinal*); +static void MoveBeginningOfFile(Widget, XEvent*, String*, Cardinal*); +static void MoveEndOfFile(Widget, XEvent*, String*, Cardinal*); +static void MoveForwardChar(Widget, XEvent*, String*, Cardinal*); +static void MoveForwardWord(Widget, XEvent*, String*, Cardinal*); +static void MoveForwardParagraph(Widget, XEvent*, String*, Cardinal*); +static void MoveNextLine(Widget, XEvent*, String*, Cardinal*); +static void MoveNextPage(Widget, XEvent*, String*, Cardinal*); +static void MovePage(TextWidget, XEvent*, XawTextScanDirection); +static void MovePreviousLine(Widget, XEvent*, String*, Cardinal*); +static void MovePreviousPage(Widget, XEvent*, String*, Cardinal*); +static void MoveLine(TextWidget, XEvent*, XawTextScanDirection); +static void MoveToLineEnd(Widget, XEvent*, String*, Cardinal*); +static void MoveToLineStart(Widget, XEvent*, String*, Cardinal*); +static void Multiply(Widget, XEvent*, String*, Cardinal*); +static void NoOp(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void Numeric(Widget, XEvent*, String*, Cardinal*); +#endif +static void Reconnect(Widget, XEvent*, String*, Cardinal*); +static void RedrawDisplay(Widget, XEvent*, String*, Cardinal*); +static void Scroll(TextWidget, XEvent*, XawTextScanDirection); +static void ScrollOneLineDown(Widget, XEvent*, String*, Cardinal*); +static void ScrollOneLineUp(Widget, XEvent*, String*, Cardinal*); +static void SelectAdjust(Widget, XEvent*, String*, Cardinal*); +static void SelectAll(Widget, XEvent*, String*, Cardinal*); +static void SelectEnd(Widget, XEvent*, String*, Cardinal*); +static void SelectSave(Widget, XEvent*, String*, Cardinal*); +static void SelectStart(Widget, XEvent*, String*, Cardinal*); +static void SelectWord(Widget, XEvent*, String*, Cardinal*); +static void SetKeyboardFocus(Widget, XEvent*, String*, Cardinal*); +static void TextEnterWindow(Widget, XEvent*, String*, Cardinal*); +static void TextFocusIn(Widget, XEvent*, String*, Cardinal*); +static void TextFocusOut(Widget, XEvent*, String*, Cardinal*); +static void TextLeaveWindow(Widget, XEvent*, String*, Cardinal*); +static void TransposeCharacters(Widget, XEvent*, String*, Cardinal*); +#ifndef OLDXAW +static void ToggleOverwrite(Widget, XEvent*, String*, Cardinal*); +static void Undo(Widget, XEvent*, String*, Cardinal*); +#endif +static void UpcaseWord(Widget, XEvent*, String*, Cardinal*); +static void DestroyFocusCallback(Widget, XtPointer, XtPointer); /* - * These are defined in TextPop.c + * External */ +void _XawTextZapSelection(TextWidget, XEvent*, Bool); -void _XawTextInsertFileAction(), _XawTextInsertFile(), _XawTextSearch(); -void _XawTextSearch(), _XawTextDoSearchAction(), _XawTextDoReplaceAction(); -void _XawTextSetField(), _XawTextPopdownSearchAction(); +/* + * Defined in TextPop.c + */ +void _XawTextInsertFileAction(Widget, XEvent*, String*, Cardinal*); +void _XawTextInsertFile(Widget, XEvent*, String*, Cardinal*); +void _XawTextSearch(Widget, XEvent*, String*, Cardinal*); +void _XawTextDoSearchAction(Widget, XEvent*, String*, Cardinal*); +void _XawTextDoReplaceAction(Widget, XEvent*, String*, Cardinal*); +void _XawTextSetField(Widget, XEvent*, String*, Cardinal*); +void _XawTextPopdownSearchAction(Widget, XEvent*, String*, Cardinal*); /* * These are defined in Text.c */ +void _XawTextAlterSelection(TextWidget, XawTextSelectionMode, + XawTextSelectionAction, String*, Cardinal*); +void _XawTextClearAndCenterDisplay(TextWidget); +void _XawTextExecuteUpdate(TextWidget); +char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition); +void _XawTextPrepareToUpdate(TextWidget); +int _XawTextReplace(TextWidget, XawTextPosition, XawTextPosition, + XawTextBlock*); +Atom *_XawTextSelectionList(TextWidget, String*, Cardinal); +void _XawTextSetSelection(TextWidget, XawTextPosition, XawTextPosition, + String*, Cardinal); +void _XawTextVScroll(TextWidget, int); +void XawTextScroll(TextWidget, int, int); +void _XawTextSetLineAndColumnNumber(TextWidget, Bool); + +#ifndef OLDXAW +/* + * Defined in TextSrc.c + */ +Bool _XawTextSrcUndo(TextSrcObject, XawTextPosition*); +Bool _XawTextSrcToggleUndo(TextSrcObject); +void _XawSourceSetUndoErase(TextSrcObject, int); +void _XawSourceSetUndoMerge(TextSrcObject, Bool); +#endif /* OLDXAW */ -char * _XawTextGetText(); -void _XawTextAlterSelection(), _XawTextVScroll(); -void _XawTextSetSelection(), _XawTextCheckResize(), _XawTextExecuteUpdate(); -void _XawTextSetScrollBars(), _XawTextClearAndCenterDisplay(); -Atom * _XawTextSelectionList(); -void _XawTextPrepareToUpdate(); -int _XawTextReplace(); +/* + * Initialization + */ +#ifndef OLDXAW +#define MAX_KILL_RINGS 1024 +XawTextKillRing *xaw_text_kill_ring; +static XawTextKillRing kill_ring_prev, kill_ring_null = { &kill_ring_prev, }; +static unsigned num_kill_rings; +#endif -static void ParameterError(w, param) - Widget w; - String param; +/* + * Implementation + */ +static void +ParameterError(Widget w, String param) { String params[2]; Cardinal num_params = 2; params[0] = XtName(w); params[1] = param; - - XtAppWarningMsg( XtWidgetToApplicationContext(w), - "parameterError", "textAction", "XawError", - "Widget: %s Parameter: %s", - params, &num_params); - XBell( XtDisplay( w ), 50 ); + + XtAppWarningMsg(XtWidgetToApplicationContext(w), + "parameterError", "textAction", "XawError", + "Widget: %s Parameter: %s", + params, &num_params); + XBell(XtDisplay(w), 50); } static void -StartAction(ctx, event) -TextWidget ctx; -XEvent *event; +StartAction(TextWidget ctx, XEvent *event) +{ +#ifndef OLDXAW + Cardinal i; + TextSrcObject src = (TextSrcObject)ctx->text.source; + + for (i = 0; i < src->textSrc.num_text; i++) + _XawTextPrepareToUpdate((TextWidget)src->textSrc.text[i]); + _XawSourceSetUndoMerge(src, False); +#else + _XawTextPrepareToUpdate(ctx); +#endif + + if (event != NULL) { + switch (event->type) { + case ButtonPress: + case ButtonRelease: + ctx->text.time = event->xbutton.time; + break; + case KeyPress: + case KeyRelease: + ctx->text.time = event->xkey.time; + break; + case MotionNotify: + ctx->text.time = event->xmotion.time; + break; + case EnterNotify: + case LeaveNotify: + ctx->text.time = event->xcrossing.time; + } + } +} + +static void +NotePosition(TextWidget ctx, XEvent *event) { - _XawTextPrepareToUpdate(ctx); - if (event != NULL) { switch (event->type) { - case ButtonPress: - case ButtonRelease: - ctx->text.time = event->xbutton.time; - break; - case KeyPress: - case KeyRelease: - ctx->text.time = event->xkey.time; - break; - case MotionNotify: - ctx->text.time = event->xmotion.time; - break; - case EnterNotify: - case LeaveNotify: - ctx->text.time = event->xcrossing.time; - } - } -} - -static void -NotePosition(ctx, event) -TextWidget ctx; -XEvent* event; -{ - switch (event->type) { - case ButtonPress: - case ButtonRelease: - ctx->text.ev_x = event->xbutton.x; - ctx->text.ev_y = event->xbutton.y; - break; - case KeyPress: - case KeyRelease: - { - XRectangle cursor; - XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); - ctx->text.ev_x = cursor.x + cursor.width / 2;; - ctx->text.ev_y = cursor.y + cursor.height / 2;; - } - break; - case MotionNotify: - ctx->text.ev_x = event->xmotion.x; - ctx->text.ev_y = event->xmotion.y; - break; - case EnterNotify: - case LeaveNotify: - 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; + case ButtonPress: + case ButtonRelease: + ctx->text.ev_x = event->xbutton.x; + ctx->text.ev_y = event->xbutton.y; + break; + case KeyPress: + case KeyRelease: { + XRectangle cursor; + XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); + ctx->text.ev_x = cursor.x + cursor.width / 2; + ctx->text.ev_y = cursor.y + cursor.height / 2; + } break; + case MotionNotify: + ctx->text.ev_x = event->xmotion.x; + ctx->text.ev_y = event->xmotion.y; + break; + case EnterNotify: + case LeaveNotify: + ctx->text.ev_x = event->xcrossing.x; + ctx->text.ev_y = event->xcrossing.y; + } } +static void +EndAction(TextWidget ctx) +{ +#ifndef OLDXAW + Cardinal i; + TextSrcObject src = (TextSrcObject)ctx->text.source; + + for (i = 0; i < src->textSrc.num_text; i++) + _XawTextExecuteUpdate((TextWidget)src->textSrc.text[i]); + + ctx->text.mult = 1; + ctx->text.numeric = False; + if (ctx->text.kill_ring) { + if (--ctx->text.kill_ring == KILL_RING_YANK_DONE) { + if (ctx->text.kill_ring_ptr) { + --ctx->text.kill_ring_ptr->refcount; + ctx->text.kill_ring_ptr = NULL; + } + } + } +#else + ctx->text.mult = 1; + _XawTextExecuteUpdate(ctx); +#endif /* OLDXAW */ +} struct _SelectionList { String* params; Cardinal count; Time time; - Boolean CT_asked; /* flag if asked XA_COMPOUND_TEXT */ - Atom selection; /* selection atom when asking XA_COMPOUND_TEXT */ + int asked; /* which selection currently has been asked for: + 0 = UTF8_STRING, 1 = COMPOUND_TEXT, 2 = STRING */ + Atom selection; /* selection atom (normally XA_PRIMARY) */ }; -static int ProbablyMB(s) - char* s; +/*ARGSUSED*/ +static void +_SelectionReceived(Widget w, XtPointer client_data, Atom *selection, + Atom *type, XtPointer value, unsigned long *length, + int *format) { - int escapes = 0; - int has_hi_bit = False; + Display *d = XtDisplay(w); + TextWidget ctx = (TextWidget)w; + XawTextBlock text; + + if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0) { + struct _SelectionList* list = (struct _SelectionList*)client_data; + + if (list != NULL) { + if (list->asked == 0) { + /* If we just asked for XA_UTF8_STRING and got no response, + we'll ask again, this time for XA_COMPOUND_TEXT. */ + list->asked++; + XtGetSelectionValue(w, list->selection, XA_COMPOUND_TEXT(d), + _SelectionReceived, + (XtPointer)list, list->time); + } else if (list->asked == 1) { + /* If we just asked for XA_COMPOUND_TEXT and got no response, + we'll ask again, this time for XA_STRING. */ + list->asked++; + XtGetSelectionValue(w, list->selection, XA_STRING, + _SelectionReceived, + (XtPointer)list, list->time); + } else { + /* We tried all possible text targets in this param. + Recurse on the tail of the params list. */ + GetSelection(w, list->time, list->params, list->count); + XtFree(client_data); + } + } + return; + } - /* if it has more than one ESC char, I assume it is COMPOUND_TEXT. - If it has at least one hi bit set character, I pretend it is multibyte. */ + StartAction(ctx, NULL); + if (XawTextFormat(ctx, XawFmtWide)) { + XTextProperty textprop; + wchar_t **wlist; + int count; + + textprop.encoding = *type; + textprop.value = (unsigned char *)value; + textprop.nitems = strlen(value); + textprop.format = 8; + + if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count) + != Success + || count < 1) { + XwcFreeStringList(wlist); + + /* Notify the user on strerr and in the insertion :) */ + fprintf(stderr, "Xaw Text Widget: An attempt was made to insert " + "an illegal selection.\n"); + + textprop.value = (unsigned char *)" >> ILLEGAL SELECTION << "; + textprop.nitems = strlen((char *) textprop.value); + if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count) + != Success + || count < 1) + return; + } + + XFree(value); + value = (XPointer)wlist[0]; + + *length = wcslen(wlist[0]); + XtFree((XtPointer)wlist); + text.format = XawFmtWide; + } else { + XTextProperty textprop; + char **list; + int count; + + textprop.encoding = *type; + textprop.value = (unsigned char *)value; + textprop.nitems = strlen(value); + textprop.format = 8; + + if (XmbTextPropertyToTextList(d, &textprop, &list, &count) + != Success + || count < 1) { + XFreeStringList(list); + + /* Notify the user on strerr and in the insertion :) */ + fprintf(stderr, "Xaw Text Widget: An attempt was made to insert " + "an illegal selection.\n"); + + textprop.value = (unsigned char *)" >> ILLEGAL SELECTION << "; + textprop.nitems = strlen((char *) textprop.value); + if (XmbTextPropertyToTextList(d, &textprop, &list, &count) + != Success + || count < 1) + return; + } - while ( (*s) != (wchar_t)0 ) { - if ( *s & 128 ) - has_hi_bit = True; - if ( *s++ == '\033' ) - escapes++; - if ( escapes >= 2 ) - return( 0 ); + XFree(value); + value = (XPointer)list[0]; + + *length = strlen(list[0]); + XtFree((XtPointer)list); + text.format = XawFmt8Bit; + } + text.ptr = (char*)value; + text.firstPos = 0; + text.length = *length; + if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { + XBell(XtDisplay(ctx), 0); + EndAction(ctx); + return; } - return( has_hi_bit ); + + ctx->text.from_left = -1; + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert, + XawstPositions, XawsdRight, text.length, True); + + EndAction(ctx); + XtFree(client_data); + XFree(value); /* the selection value should be freed with XFree */ } -static void GetSelection(); -/* ARGSUSED */ -static void -_SelectionReceived(w, client_data, selection, type, value, length, format) -Widget w; -XtPointer client_data; -Atom *selection, *type; -XtPointer 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) { - if (list->CT_asked) { - - /* If we just asked for a XA_COMPOUND_TEXT and got a null - response, we'll ask again, this time for an XA_STRING. */ - - list->CT_asked = False; - XtGetSelectionValue(w, list->selection, XA_STRING, _SelectionReceived, - (XtPointer)list, list->time); - } else { - GetSelection(w, list->time, list->params, list->count); - XtFree(client_data); - } - } - return; - } - - /* Many programs, especially old terminal emulators, give us multibyte text -but tell us it is COMPOUND_TEXT :( The following routine checks to see if the -string is a legal multibyte string in our locale using a spooky heuristic :O -and if it is we can only assume the sending client is using the same locale as -we are, and convert it. I also warn the user that the other client is evil. */ - - StartAction( ctx, (XEvent*) NULL ); - if (_XawTextFormat(ctx) == XawFmtWide) { - XTextProperty textprop; - Display *d = XtDisplay((Widget)ctx); - wchar_t **wlist; - int count; - int try_CT = 1; - - /* IS THE SELECTION IN MULTIBYTE FORMAT? */ - - if ( ProbablyMB( (char *) value ) ) { - char * list[1]; - list[0] = (char *) value; - if ( XmbTextListToTextProperty( d, (char**) list, 1, - XCompoundTextStyle, &textprop ) == Success ) - try_CT = 0; - } - - /* OR IN COMPOUND TEXT FORMAT? */ - - if ( try_CT ) { - textprop.encoding = XA_COMPOUND_TEXT(d); - textprop.value = (unsigned char *)value; - textprop.nitems = strlen(value); - textprop.format = 8; - } - - if ( XwcTextPropertyToTextList( d, &textprop, (wchar_t***) &wlist, &count ) - != Success) { - XwcFreeStringList( (wchar_t**) wlist ); - - /* Notify the user on strerr and in the insertion :) */ - textprop.value = (unsigned char *) " >> ILLEGAL SELECTION << "; - count = 1; - fprintf( stderr, "Xaw Text Widget: An attempt was made to insert an illegal selection.\n" ); - - if ( XwcTextPropertyToTextList( d, &textprop, (wchar_t***) &wlist, &count ) - != Success) return; - } - - XFree(value); - value = (XPointer)wlist[0]; - - *length = wcslen(wlist[0]); - XtFree((XtPointer)wlist); - text.format = XawFmtWide; - } else - text.format = XawFmt8Bit; - text.ptr = (char*)value; - text.firstPos = 0; - text.length = *length; - 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); - - _XawTextSetScrollBars(ctx); - EndAction(ctx); - XtFree(client_data); - XFree(value); /* the selection value should be freed with XFree */ -} - -static void -GetSelection(w, time, params, num_params) -Widget w; -Time time; -String* params; /* selections in precedence order */ -Cardinal num_params; +static void +GetSelection(Widget w, Time timev, String *params, Cardinal num_params) { Atom selection; int buffer; selection = XInternAtom(XtDisplay(w), *params, False); 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; + 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; @@ -308,1277 +507,2715 @@ Cardinal num_params; int fmt8 = 8; Atom type = XA_STRING; char *line = XFetchBuffer(XtDisplay(w), &nbytes, buffer); - if (length = nbytes) - _SelectionReceived(w, (XtPointer) NULL, &selection, &type, (XPointer)line, - &length, &fmt8); + + if ((length = nbytes) != 0L) + _SelectionReceived(w, NULL, &selection, &type, line, &length, &fmt8); else if (num_params > 1) - GetSelection(w, time, params+1, num_params-1); - } else { + GetSelection(w, timev, 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; - list->CT_asked = True; + list->time = timev; + list->asked = 0; list->selection = selection; - } else list = NULL; - XtGetSelectionValue(w, selection, XA_COMPOUND_TEXT(XtDisplay(w)), - _SelectionReceived, (XtPointer)list, time); + } + else + list = NULL; + XtGetSelectionValue(w, selection, XA_UTF8_STRING(XtDisplay(w)), + _SelectionReceived, (XtPointer)list, timev); } } -static void -InsertSelection(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; /* precedence list of selections to try */ -Cardinal* num_params; +static void +InsertSelection(Widget w, XEvent *event, String *params, Cardinal *num_params) { - StartAction((TextWidget)w, event); /* Get Time. */ - GetSelection(w, ((TextWidget)w)->text.time, params, *num_params); - EndAction((TextWidget)w); + StartAction((TextWidget)w, event); /* Get Time. */ + GetSelection(w, ((TextWidget)w)->text.time, params, *num_params); + EndAction((TextWidget)w); } -/************************************************************ - * - * Routines for Moving Around. - * - ************************************************************/ - +/* + * Routines for Moving Around + */ static void -Move(ctx, event, dir, type, include) -TextWidget ctx; -XEvent* event; -XawTextScanDirection dir; -XawTextScanType type; -Boolean include; +Move(TextWidget ctx, XEvent *event, XawTextScanDirection dir, + XawTextScanType type, Bool include) { - StartAction(ctx, event); - ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, - type, dir, ctx->text.mult, include); - EndAction(ctx); + XawTextPosition insertPos; + short mult = MULT(ctx); + + if (mult < 0) { + mult = -mult; + dir = dir == XawsdLeft ? XawsdRight : XawsdLeft; + } + + insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, + type, dir, mult, include); + + StartAction(ctx, event); + + if (ctx->text.s.left != ctx->text.s.right) + XawTextUnsetSelection((Widget)ctx); + +#ifndef OLDXAW + ctx->text.numeric = False; +#endif + ctx->text.mult = 1; + ctx->text.showposition = True; + ctx->text.from_left = -1; + ctx->text.insertPos = insertPos; + EndAction(ctx); } /*ARGSUSED*/ -static void -MoveForwardChar(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveForwardChar(Widget w, XEvent *event, String *p, Cardinal *n) { - Move((TextWidget) w, event, XawsdRight, XawstPositions, TRUE); + Move((TextWidget)w, event, XawsdRight, XawstPositions, True); } /*ARGSUSED*/ -static void -MoveBackwardChar(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveBackwardChar(Widget w, XEvent *event, String *p, Cardinal *n) { - Move((TextWidget) w, event, XawsdLeft, XawstPositions, TRUE); + Move((TextWidget)w, event, XawsdLeft, XawstPositions, True); } -/*ARGSUSED*/ -static void -MoveForwardWord(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveForwardWord(Widget w, XEvent *event, String *p, Cardinal *n) { - Move((TextWidget) w, event, XawsdRight, XawstWhiteSpace, FALSE); + if (*n && (p[0][0] == 'A' || p[0][0] == 'a')) + Move((TextWidget)w, event, XawsdRight, XawstAlphaNumeric, False); + else + Move((TextWidget)w, event, XawsdRight, XawstWhiteSpace, False); } -/*ARGSUSED*/ -static void -MoveBackwardWord(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveBackwardWord(Widget w, XEvent *event, String *p, Cardinal *n) { - Move((TextWidget) w, event, XawsdLeft, XawstWhiteSpace, FALSE); + if (*n && (p[0][0] == 'A' || p[0][0] == 'a')) + Move((TextWidget)w, event, XawsdLeft, XawstAlphaNumeric, False); + else + Move((TextWidget)w, event, XawsdLeft, XawstWhiteSpace, False); } -/*ARGSUSED*/ -static void MoveForwardParagraph(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveForwardParagraph(Widget w, XEvent *event, String *p, Cardinal *n) { - Move((TextWidget) w, event, XawsdRight, XawstParagraph, FALSE); + TextWidget ctx = (TextWidget)w; + XawTextPosition position = ctx->text.insertPos; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MoveBackwardParagraph(w, event, p, n); + return; + } + + while (mult--) { + position = SrcScan(ctx->text.source, position, + XawstEOL, XawsdRight, 1, False) - 1; + + while (position == SrcScan(ctx->text.source, position, + XawstEOL, XawsdRight, 1, False)) + if (++position > ctx->text.lastPos) { + mult = 0; + break; + } + + position = SrcScan(ctx->text.source, position, + XawstParagraph, XawsdRight, 1, True); + if (position != ctx->text.lastPos) + position = SrcScan(ctx->text.source, position - 1, + XawstEOL, XawsdLeft, 1, False); + else + break; + } + + if (position != ctx->text.insertPos) { + XawTextUnsetSelection(w); + StartAction(ctx, event); + ctx->text.showposition = True; + ctx->text.from_left = -1; + ctx->text.insertPos = position; + EndAction(ctx); + } + else + ctx->text.mult = 1; } /*ARGSUSED*/ -static void MoveBackwardParagraph(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveBackwardParagraph(Widget w, XEvent *event, String *p, Cardinal *n) { - Move((TextWidget) w, event, XawsdLeft, XawstParagraph, FALSE); + TextWidget ctx = (TextWidget)w; + XawTextPosition position = ctx->text.insertPos; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MoveForwardParagraph(w, event, p, n); + return; + } + + while (mult--) { + position = SrcScan(ctx->text.source, position, + XawstEOL, XawsdLeft, 1, False) + 1; + + while (position == SrcScan(ctx->text.source, position, + XawstEOL, XawsdLeft, 1, False)) + if (--position < 0) { + mult = 0; + break; + } + + position = SrcScan(ctx->text.source, position, + XawstParagraph, XawsdLeft, 1, True); + if (position > 0 && position < ctx->text.lastPos) + ++position; + else + break; + } + + if (position != ctx->text.insertPos) { + XawTextUnsetSelection(w); + StartAction(ctx, event); + ctx->text.showposition = True; + ctx->text.from_left = -1; + ctx->text.insertPos = position; + EndAction(ctx); + } + else + ctx->text.mult = 1; } /*ARGSUSED*/ -static void -MoveToLineEnd(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveToLineEnd(Widget w, XEvent *event, String *p, Cardinal *n) { - Move((TextWidget) w, event, XawsdRight, XawstEOL, FALSE); + Move((TextWidget)w, event, XawsdRight, XawstEOL, False); } /*ARGSUSED*/ -static void -MoveToLineStart(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveToLineStart(Widget w, XEvent *event, String *p, Cardinal *n) { - Move((TextWidget) w, event, XawsdLeft, XawstEOL, FALSE); + Move((TextWidget)w, event, XawsdLeft, XawstEOL, False); } - static void -MoveLine(ctx, event, dir) -TextWidget ctx; -XEvent* event; -XawTextScanDirection dir; +MoveLine(TextWidget ctx, XEvent *event, XawTextScanDirection dir) { - XawTextPosition new, next_line, junk; - int from_left, garbage; + XawTextPosition cnew, next_line, ltemp; + int itemp, from_left; + short mult = MULT(ctx); - StartAction(ctx, event); + StartAction(ctx, event); - if (dir == XawsdLeft) - ctx->text.mult++; + XawTextUnsetSelection((Widget)ctx); - new = SrcScan(ctx->text.source, ctx->text.insertPos, - XawstEOL, XawsdLeft, 1, FALSE); + if (dir == XawsdLeft) + mult = mult == 0 ? 5 : mult + 1; - FindDist(ctx->text.sink, new, ctx->text.margin.left, ctx->text.insertPos, - &from_left, &junk, &garbage); + cnew = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, False); - new = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir, - ctx->text.mult, (dir == XawsdRight)); + if (ctx->text.from_left < 0) + FindDist(ctx->text.sink, cnew, ctx->text.left_margin, ctx->text.insertPos, + &ctx->text.from_left, <emp, &itemp); - next_line = SrcScan(ctx->text.source, new, XawstEOL, XawsdRight, 1, FALSE); + cnew = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir, + mult, (dir == XawsdRight)); - 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; + next_line = SrcScan(ctx->text.source, cnew, XawstEOL, XawsdRight, 1, False); + + FindPos(ctx->text.sink, cnew, ctx->text.left_margin, ctx->text.from_left, + False, &ctx->text.insertPos, &from_left, &itemp); + + if (from_left < ctx->text.from_left) { + XawTextBlock block; + + XawTextSourceRead(ctx->text.source, ctx->text.insertPos, &block, 1); + if (block.length) { + if (XawTextFormat(ctx, XawFmtWide)) { + if (*(wchar_t *)block.ptr == _Xaw_atowc(XawTAB)) + ++ctx->text.insertPos; + } + else if (block.ptr[0] == XawTAB) + ++ctx->text.insertPos; + } + } - EndAction(ctx); + if (ctx->text.insertPos > next_line) + ctx->text.insertPos = next_line; + + EndAction(ctx); } -/*ARGSUSED*/ -static void -MoveNextLine(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveNextLine(Widget w, XEvent *event, String *p, Cardinal *n) { - MoveLine( (TextWidget) w, event, XawsdRight); + TextWidget ctx = (TextWidget)w; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MovePreviousLine(w, event, p, n); + return; + } + + if (ctx->text.insertPos < ctx->text.lastPos) + MoveLine(ctx, event, XawsdRight); + else + ctx->text.mult = 1; } -/*ARGSUSED*/ -static void -MovePreviousLine(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MovePreviousLine(Widget w, XEvent *event, String *p, Cardinal *n) { - MoveLine( (TextWidget) w, event, XawsdLeft); + TextWidget ctx = (TextWidget)w; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MoveNextLine(w, event, p, n); + return; + } + + if (ctx->text.lt.top != 0 || (ctx->text.lt.lines > 1 && + ctx->text.insertPos >= ctx->text.lt.info[1].position)) + MoveLine(ctx, event, XawsdLeft); + else + ctx->text.mult = 1; } /*ARGSUSED*/ static void -MoveBeginningOfFile(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +MoveBeginningOfFile(Widget w, XEvent *event, String *p, Cardinal *n) { - Move((TextWidget) w, event, XawsdLeft, XawstAll, TRUE); + Move((TextWidget)w, event, XawsdLeft, XawstAll, True); } /*ARGSUSED*/ -static void -MoveEndOfFile(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveEndOfFile(Widget w, XEvent *event, String *p, Cardinal *n) { - Move((TextWidget) w, event, XawsdRight, XawstAll, TRUE); + Move((TextWidget)w, event, XawsdRight, XawstAll, True); } -static void -Scroll(ctx, event, dir) -TextWidget ctx; -XEvent* event; -XawTextScanDirection dir; +static void +Scroll(TextWidget ctx, XEvent *event, XawTextScanDirection dir) { - StartAction(ctx, event); + short mult = MULT(ctx); + + if (mult < 0) { + mult = -mult; + dir = dir == XawsdLeft ? XawsdRight : XawsdLeft; + } + + if (ctx->text.lt.lines > 1 + && (dir == XawsdRight + || ctx->text.lastPos >= ctx->text.lt.info[1].position)) { + StartAction(ctx, event); - if (dir == XawsdLeft) - _XawTextVScroll(ctx, ctx->text.mult); - else - _XawTextVScroll(ctx, -ctx->text.mult); + if (dir == XawsdLeft) + _XawTextVScroll(ctx, mult); + else + _XawTextVScroll(ctx, -mult); - EndAction(ctx); + EndAction(ctx); + } + else { + ctx->text.mult = 1; +#ifndef OLDXAW + ctx->text.numeric = False; +#endif + } } /*ARGSUSED*/ -static void -ScrollOneLineUp(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +ScrollOneLineUp(Widget w, XEvent *event, String *p, Cardinal *n) { - Scroll( (TextWidget) w, event, XawsdLeft); + Scroll((TextWidget)w, event, XawsdLeft); } /*ARGSUSED*/ -static void -ScrollOneLineDown(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +ScrollOneLineDown(Widget w, XEvent *event, String *p, Cardinal *n) { - Scroll( (TextWidget) w, event, XawsdRight); + Scroll((TextWidget)w, event, XawsdRight); } -static void -MovePage(ctx, event, dir) -TextWidget ctx; -XEvent* event; -XawTextScanDirection dir; +static void +MovePage(TextWidget ctx, XEvent *event, XawTextScanDirection dir) { - int scroll_val = Max(1, ctx->text.lt.lines - 2); + int scroll_val = 0; + XawTextPosition old_pos; + + ctx->text.from_left = -1; + switch (dir) { + case XawsdLeft: + if (ctx->text.lt.top != 0) + scroll_val = -Max(1, ctx->text.lt.lines - 1); + break; + case XawsdRight: + if (!IsPositionVisible(ctx, Max(0, ctx->text.lastPos))) + scroll_val = Max(1, ctx->text.lt.lines - 1); + break; + } - if (dir == XawsdLeft) - scroll_val = -scroll_val; + if (scroll_val) + XawTextScroll(ctx, scroll_val, + ctx->text.left_margin - ctx->text.r_margin.left); - StartAction(ctx, event); - _XawTextVScroll(ctx, scroll_val); - ctx->text.insertPos = ctx->text.lt.top; - EndAction(ctx); + old_pos = ctx->text.insertPos; + switch (dir) { + case XawsdRight: + if (IsPositionVisible(ctx, Max(0, ctx->text.lastPos))) + ctx->text.insertPos = Max(0, ctx->text.lastPos); + else + ctx->text.insertPos = ctx->text.lt.top; + if (ctx->text.insertPos < old_pos) + ctx->text.insertPos = SrcScan(ctx->text.source, old_pos, + XawstEOL, XawsdLeft, 1, False); + break; + case XawsdLeft: + if (IsPositionVisible(ctx, 0)) + ctx->text.insertPos = 0; + else if (ctx->text.lt.lines) + ctx->text.insertPos = + ctx->text.lt.info[ctx->text.lt.lines - 1].position; + else + ctx->text.insertPos = ctx->text.lt.top; + if (ctx->text.insertPos > old_pos) + ctx->text.insertPos = SrcScan(ctx->text.source, old_pos, + XawstEOL, XawsdLeft, 1, False); + break; + } } -/*ARGSUSED*/ -static void -MoveNextPage(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MoveNextPage(Widget w, XEvent *event, String *p, Cardinal *n) { - MovePage((TextWidget) w, event, XawsdRight); + TextWidget ctx = (TextWidget)w; + short mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = -mult; + MovePreviousPage(w, event, p, n); + return; + } + + if (ctx->text.insertPos < ctx->text.lastPos) { + XawTextUnsetSelection(w); + StartAction(ctx, event); + ctx->text.clear_to_eol = True; + while (mult-- && ctx->text.insertPos < ctx->text.lastPos) + MovePage(ctx, event, XawsdRight); + EndAction(ctx); + } + else + ctx->text.mult = 1; } /*ARGSUSED*/ -static void -MovePreviousPage(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +MovePreviousPage(Widget w, XEvent *event, String *p, Cardinal *n) { - MovePage((TextWidget) w, event, XawsdLeft); -} + TextWidget ctx = (TextWidget)w; + short mult = MULT(ctx); -/************************************************************ - * - * Delete Routines. - * - ************************************************************/ + if (mult < 0) { + ctx->text.mult = -mult; + MoveNextPage(w, event, p, n); + return; + } -static Boolean -MatchSelection(selection, s) - Atom selection; - XawTextSelection* s; + if (ctx->text.insertPos > 0) { + XawTextUnsetSelection(w); + StartAction(ctx, event); + ctx->text.clear_to_eol = True; + while (mult-- && ctx->text.insertPos > 0) + MovePage(ctx, event, XawsdLeft); + EndAction(ctx); + } + else + ctx->text.mult = 1; +} + +/* + * Delete Routines + */ +static Bool +MatchSelection(Atom selection, XawTextSelection *s) { - Atom *match; - int count; + Atom *match; + int count; - for (count = 0, match = s->selections; count < s->atom_count; match++, count++) + for (count = 0, match = s->selections; count < s->atom_count; + match++, count++) if (*match == selection) - return True; - return False; + return (True); + + return (False); } #define SrcCvtSel XawTextSourceConvertSelection -static Boolean -ConvertSelection(w, selection, target, type, value, length, format) - Widget w; - Atom *selection, *target, *type; - XtPointer* value; - unsigned long* length; - int* format; -{ - Display* d = XtDisplay(w); - TextWidget ctx = (TextWidget)w; - Widget src = ctx->text.source; - XawTextEditType edit_mode; - Arg args[1]; - XawTextSelectionSalt *salt = NULL; - XawTextSelection *s; - - if (*target == XA_TARGETS(d)) { - Atom* targetP, * std_targets; - unsigned long std_length; - - if ( SrcCvtSel(src, selection, target, type, value, length, format) ) - return True; - - XmuConvertStandardSelection(w, ctx->text.time, selection, - target, type, (XPointer*)&std_targets, - &std_length, format); - - *value = XtMalloc((unsigned) sizeof(Atom)*(std_length + 7)); - targetP = *(Atom**)value; - - *length = std_length + 6; - *targetP++ = XA_STRING; - *targetP++ = XA_TEXT(d); - *targetP++ = XA_COMPOUND_TEXT(d); - *targetP++ = XA_LENGTH(d); - *targetP++ = XA_LIST_LENGTH(d); - *targetP++ = XA_CHARACTER_POSITION(d); - - XtSetArg(args[0], XtNeditType,&edit_mode); - XtGetValues(src, args, 1); - - if (edit_mode == XawtextEdit) { - *targetP++ = XA_DELETE(d); - (*length)++; - } - memcpy((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); - XtFree((char*)std_targets); - *type = XA_ATOM; - *format = 32; - return True; - } - - if ( SrcCvtSel(src, selection, target, type, value, length, format) ) - return True; - - for (salt = ctx->text.salt2; salt; salt = salt->next) - if (MatchSelection (*selection, &salt->s)) - break; - if (!salt) - return False; - s = &salt->s; - if (*target == XA_STRING || - *target == XA_TEXT(d) || - *target == XA_COMPOUND_TEXT(d)) { +static Boolean +ConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type, + XtPointer *value, unsigned long *length, int *format) +{ + Display *d = XtDisplay(w); + TextWidget ctx = (TextWidget)w; + Widget src = ctx->text.source; + XawTextEditType edit_mode; + Arg args[1]; + XawTextSelectionSalt *salt = NULL; + XawTextSelection *s; + + if (*target == XA_TARGETS(d)) { + Atom *targetP, *std_targets; + unsigned long std_length; + + if (SrcCvtSel(src, selection, target, type, value, length, format)) + return (True); + + XtSetArg(args[0], XtNeditType,&edit_mode); + XtGetValues(src, args, 1); + + XmuConvertStandardSelection(w, ctx->text.time, selection, + target, type, (XPointer *)&std_targets, + &std_length, format); + + *length = 7 + (edit_mode == XawtextEdit) + std_length; + *value = XtMalloc((unsigned)sizeof(Atom)*(*length)); + targetP = *(Atom**)value; + *targetP++ = XA_STRING; + *targetP++ = XA_TEXT(d); + *targetP++ = XA_UTF8_STRING(d); + *targetP++ = XA_COMPOUND_TEXT(d); + *targetP++ = XA_LENGTH(d); + *targetP++ = XA_LIST_LENGTH(d); + *targetP++ = XA_CHARACTER_POSITION(d); + if (edit_mode == XawtextEdit) { + *targetP++ = XA_DELETE(d); + } + memcpy((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); + XtFree((char*)std_targets); + *type = XA_ATOM; + *format = 32; + return (True); + } + + if (SrcCvtSel(src, selection, target, type, value, length, format)) + return (True); + + for (salt = ctx->text.salt2; salt; salt = salt->next) + if (MatchSelection (*selection, &salt->s)) + break; + if (!salt) + return (False); + s = &salt->s; + if (*target == XA_STRING + || *target == XA_TEXT(d) + || *target == XA_UTF8_STRING(d) + || *target == XA_COMPOUND_TEXT(d)) { if (*target == XA_TEXT(d)) { - if (_XawTextFormat(ctx) == XawFmtWide) + if (XawTextFormat(ctx, XawFmtWide)) *type = XA_COMPOUND_TEXT(d); else *type = XA_STRING; - } else { - *type = *target; } - /* - * If salt is True, the salt->contents stores CT string, + else + *type = *target; + + /* + * If salt is True, the salt->contents stores CT string, * its length is measured in bytes. - * Refer to _XawTextSaltAwaySelection(). + * Refer to _XawTextSaltAwaySelection() * * by Li Yuhong, Mar. 20, 1991. */ if (!salt) { *value = (char *)_XawTextGetSTRING(ctx, s->left, s->right); - if (_XawTextFormat(ctx) == XawFmtWide) { + if (XawTextFormat(ctx, XawFmtWide)) { XTextProperty textprop; if (XwcTextListToTextProperty(d, (wchar_t**)value, 1, XCompoundTextStyle, &textprop) - < Success) { + < Success) { XtFree(*value); - return False; + return (False); } XtFree(*value); *value = (XtPointer)textprop.value; *length = textprop.nitems; - } else { - *length = strlen(*value); } - } else { + else + *length = strlen(*value); + } + else { *value = XtMalloc((salt->length + 1) * sizeof(unsigned char)); strcpy (*value, salt->contents); *length = salt->length; } - if (_XawTextFormat(ctx) == XawFmtWide && *type == XA_STRING) { + /* Got *value,*length, now in COMPOUND_TEXT format. */ + if (XawTextFormat(ctx, XawFmtWide) && *type == XA_STRING) { XTextProperty textprop; - wchar_t** wlist; + wchar_t **wlist; int count; + textprop.encoding = XA_COMPOUND_TEXT(d); textprop.value = (unsigned char *)*value; textprop.nitems = strlen(*value); textprop.format = 8; - if (XwcTextPropertyToTextList(d, &textprop, (wchar_t***)&wlist, &count) - < Success) { + if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count) + < Success + || count < 1) { XtFree(*value); - return False; + return (False); } XtFree(*value); - if (XwcTextListToTextProperty(d, (wchar_t**)wlist, 1, - XStringStyle, &textprop) < Success) { - XwcFreeStringList( (wchar_t**) wlist ); - return False; + if (XwcTextListToTextProperty(d, wlist, 1, XStringStyle, &textprop) + < Success) { + XwcFreeStringList((wchar_t**)wlist); + return (False); } *value = (XtPointer)textprop.value; *length = textprop.nitems; - XwcFreeStringList( (wchar_t**) wlist ); + XwcFreeStringList((wchar_t**) wlist); + } else if (*type == XA_UTF8_STRING(d)) { + XTextProperty textprop; + char **list; + int count; + + textprop.encoding = XA_COMPOUND_TEXT(d); + textprop.value = (unsigned char *)*value; + textprop.nitems = strlen(*value); + textprop.format = 8; + if (Xutf8TextPropertyToTextList(d, &textprop, &list, &count) + < Success + || count < 1) { + XtFree(*value); + return (False); + } + XtFree(*value); + *value = *list; + *length = strlen(*list); + XFree(list); } *format = 8; - return True; - } - - if ( (*target == XA_LIST_LENGTH(d)) || (*target == XA_LENGTH(d)) ) { - long * temp; - - temp = (long *) XtMalloc(sizeof(long)); - if (*target == XA_LIST_LENGTH(d)) - *temp = 1L; - else /* *target == XA_LENGTH(d) */ - *temp = (long) (s->right - s->left); - - *value = (XPointer) temp; - *type = XA_INTEGER; - *length = 1L; - *format = 32; - return True; - } - - if (*target == XA_CHARACTER_POSITION(d)) { - long * temp; - - temp = (long *) XtMalloc(2 * sizeof(long)); - temp[0] = (long) (s->left + 1); - temp[1] = s->right; - *value = (XPointer) temp; - *type = XA_SPAN(d); - *length = 2L; - *format = 32; - return True; - } - - if (*target == XA_DELETE(d)) { - void _XawTextZapSelection(); /* From TextAction.c */ - - if (!salt) - _XawTextZapSelection( ctx, (XEvent *) NULL, TRUE); - *value = NULL; - *type = XA_NULL(d); - *length = 0; - *format = 32; - return True; - } - - if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type, - (XPointer *)value, length, format)) - return True; + return (True); + } + + if (*target == XA_LIST_LENGTH(d) || *target == XA_LENGTH(d)) { + long *temp; + + temp = (long *)XtMalloc(sizeof(long)); + if (*target == XA_LIST_LENGTH(d)) + *temp = 1L; + else /* *target == XA_LENGTH(d) */ + *temp = (long)(s->right - s->left); + + *value = (XPointer)temp; + *type = XA_INTEGER; + *length = 1L; + *format = 32; + return (True); + } + + if (*target == XA_CHARACTER_POSITION(d)) { + long *temp; + + temp = (long *) XtMalloc(2 * sizeof(long)); + temp[0] = (long)(s->left + 1); + temp[1] = s->right; + *value = (XPointer)temp; + *type = XA_SPAN(d); + *length = 2L; + *format = 32; + return (True); + } + + if (*target == XA_DELETE(d)) { + if (!salt) + _XawTextZapSelection(ctx, NULL, True); + *value = NULL; + *type = XA_NULL(d); + *length = 0; + *format = 32; + return (True); + } + + if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type, + (XPointer *)value, length, format)) + return (True); - /* else */ - return False; + return (False); +} + +static void +LoseSelection(Widget w, Atom *selection) +{ + _LoseSelection(w, selection, NULL, NULL); } -static void -LoseSelection(w, selection) - Widget w; - Atom* selection; +static void +_LoseSelection(Widget w, Atom *selection, char **contents, int *length) { - TextWidget ctx = (TextWidget) w; - Atom* atomP; - int i; - XawTextSelectionSalt *salt, *prevSalt, *nextSalt; + TextWidget ctx = (TextWidget)w; + Atom *atomP; + int i; + XawTextSelectionSalt *salt, *prevSalt, *nextSalt; prevSalt = 0; - for (salt = ctx->text.salt2; salt; salt = nextSalt) - { - atomP = salt->s.selections; + for (salt = ctx->text.salt2; salt; salt = nextSalt) { + atomP = salt->s.selections; nextSalt = salt->next; - for (i = 0 ; i < salt->s.atom_count; i++, atomP++) + for (i = 0 ; i < salt->s.atom_count; i++, atomP++) if (*selection == *atomP) *atomP = (Atom)0; - - while (salt->s.atom_count && - salt->s.selections[salt->s.atom_count-1] == 0) - { + + while (salt->s.atom_count + && salt->s.selections[salt->s.atom_count-1] == 0) salt->s.atom_count--; - } - - /* - * Must walk the selection list in opposite order from UnsetSelection. - */ - - atomP = salt->s.selections; - for (i = 0 ; i < salt->s.atom_count; i++, atomP++) - if (*atomP == (Atom)0) - { - *atomP = salt->s.selections[--salt->s.atom_count]; - while (salt->s.atom_count && - salt->s.selections[salt->s.atom_count-1] == 0) - salt->s.atom_count--; - } - if (salt->s.atom_count == 0) - { - XtFree ((char *) salt->s.selections); - - /* WARNING: the next line frees memory not allocated in Xaw. */ - /* Could be a serious bug. Someone look into it. */ - XtFree (salt->contents); + + /* + * Must walk the selection list in opposite order from UnsetSelection. + */ + atomP = salt->s.selections; + for (i = 0 ; i < salt->s.atom_count; i++, atomP++) + if (*atomP == (Atom)0) { + *atomP = salt->s.selections[--salt->s.atom_count]; + + while (salt->s.atom_count + && salt->s.selections[salt->s.atom_count-1] == 0) + salt->s.atom_count--; + } + if (salt->s.atom_count == 0) { +#ifndef OLDXAW + if (contents == NULL) { + XawTextKillRing *kill_ring = XtNew(XawTextKillRing); + + kill_ring->next = xaw_text_kill_ring; + kill_ring->contents = salt->contents; + kill_ring->length = salt->length; + kill_ring->format = XawFmt8Bit; + xaw_text_kill_ring = kill_ring; + kill_ring_prev.next = xaw_text_kill_ring; + + if (++num_kill_rings > MAX_KILL_RINGS) { + XawTextKillRing *tail = NULL; + + while (kill_ring->next) { + tail = kill_ring; + kill_ring = kill_ring->next; + } + if (kill_ring->refcount == 0) { + --num_kill_rings; + tail->next = NULL; + XtFree(kill_ring->contents); + XtFree((char*)kill_ring); + } + } + } + else { + *contents = salt->contents; + *length = salt->length; + } +#endif if (prevSalt) prevSalt->next = nextSalt; else ctx->text.salt2 = nextSalt; - XtFree ((char *) salt); + + XtFree((char *)salt->s.selections); + XtFree((char *)salt); } else prevSalt = salt; } } -static void -_DeleteOrKill(ctx, from, to, kill) -TextWidget ctx; -XawTextPosition from, to; -Boolean kill; +static void +_DeleteOrKill(TextWidget ctx, XawTextPosition from, XawTextPosition to, + Bool kill) { - XawTextBlock text; - - if (kill && from < to) { - XawTextSelectionSalt *salt; - Atom selection = XInternAtom(XtDisplay(ctx), "SECONDARY", False); + XawTextBlock text; - LoseSelection ((Widget) ctx, &selection); - salt = (XawTextSelectionSalt *) XtMalloc (sizeof (XawTextSelectionSalt)); - if (!salt) - return; - salt->s.selections = (Atom *) XtMalloc (sizeof (Atom)); - if (!salt->s.selections) - { - XtFree ((char *) salt); - return; +#ifndef OLDXAW + if (ctx->text.kill_ring_ptr) { + --ctx->text.kill_ring_ptr->refcount; + ctx->text.kill_ring_ptr = NULL; } - salt->s.left = from; - salt->s.right = to; - salt->contents = (char *)_XawTextGetSTRING(ctx, from, to); - if (_XawTextFormat(ctx) == XawFmtWide) { - XTextProperty textprop; - if (XwcTextListToTextProperty(XtDisplay((Widget)ctx), - (wchar_t**)(&(salt->contents)), 1, XCompoundTextStyle, - &textprop) < Success) { - XtFree(salt->contents); - salt->length = 0; - return; +#endif + if (kill && from < to) { +#ifndef OLDXAW + Bool append = False; + char *ring = NULL; + XawTextPosition old_from = from; +#endif + char *string; + int size = 0, length; + XawTextSelectionSalt *salt; + Atom selection = XInternAtom(XtDisplay(ctx), "SECONDARY", False); + +#ifndef OLDXAW + if (ctx->text.kill_ring == KILL_RING_APPEND) { + old_from = ctx->text.salt2->s.left; + append = True; } - XtFree(salt->contents); - salt->contents = (char *)textprop.value; - salt->length = textprop.nitems; - } else - salt->length = strlen (salt->contents); - salt->next = ctx->text.salt2; - ctx->text.salt2 = salt; - salt->s.selections[0] = selection; - XtOwnSelection ((Widget) ctx, selection, ctx->text.time, - ConvertSelection, LoseSelection, NULL); - salt->s.atom_count = 1; -/* - XStoreBuffer(XtDisplay(ctx), ptr, strlen(ptr), 1); - XtFree(ptr); -*/ - } - text.length = 0; - text.firstPos = 0; + else + ctx->text.kill_ring = KILL_RING_BEGIN; + + if (append) + _LoseSelection((Widget)ctx, &selection, &ring, &size); + else +#endif + LoseSelection((Widget)ctx, &selection); - text.format = _XawTextFormat(ctx); - text.ptr = ""; /* These two lines needed to make legal TextBlock */ + salt = (XawTextSelectionSalt*)XtMalloc(sizeof(XawTextSelectionSalt)); + salt->s.selections = (Atom *)XtMalloc(sizeof(Atom)); + salt->s.left = from; + salt->s.right = to; - if (_XawTextReplace(ctx, from, to, &text)) { - XBell(XtDisplay(ctx), 50); - return; - } - ctx->text.insertPos = from; - ctx->text.showposition = TRUE; + string = (char *)_XawTextGetSTRING(ctx, from, to); + + if (XawTextFormat(ctx, XawFmtWide)) { + XTextProperty textprop; + + if (XwcTextListToTextProperty(XtDisplay((Widget)ctx), + (wchar_t**)(&string), + 1, XCompoundTextStyle, + &textprop) < Success) { + XtFree(string); + XtFree((char*)salt->s.selections); + XtFree((char*)salt); + return; + } + XtFree(string); + string = (char *)textprop.value; + length = textprop.nitems; + } + else + length = strlen(string); + + salt->length = length + size; + +#ifndef OLDXAW + if (!append) + salt->contents = string; + else { + salt->contents = XtMalloc(length + size + 1); + if (from >= old_from) { + strncpy(salt->contents, ring, size); + salt->contents[size] = '\0'; + strncat(salt->contents, string, length); + } + else { + strncpy(salt->contents, string, length); + salt->contents[length] = '\0'; + strncat(salt->contents, ring, size); + } + salt->contents[length + size] = '\0'; + XtFree(ring); + XtFree(string); + } + + kill_ring_prev.contents = salt->contents; + kill_ring_prev.length = salt->length; + kill_ring_prev.format = XawFmt8Bit; +#else + salt->contents = string; +#endif + + salt->next = ctx->text.salt2; + ctx->text.salt2 = salt; + +#ifndef OLDXAW + if (append) + ctx->text.kill_ring = KILL_RING_BEGIN; +#endif + + salt->s.selections[0] = selection; + + XtOwnSelection((Widget)ctx, selection, ctx->text.time, + ConvertSelection, LoseSelection, NULL); + salt->s.atom_count = 1; + } + text.length = 0; + text.firstPos = 0; + + text.format = _XawTextFormat(ctx); + text.ptr = ""; + + if (_XawTextReplace(ctx, from, to, &text)) { + XBell(XtDisplay(ctx), 50); + return; + } + ctx->text.from_left = -1; + 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; +DeleteOrKill(TextWidget ctx, XEvent *event, XawTextScanDirection dir, + XawTextScanType type, Bool include, Bool kill) { - XawTextPosition from, to; - - StartAction(ctx, event); - to = SrcScan(ctx->text.source, ctx->text.insertPos, - type, dir, ctx->text.mult, include); + XawTextPosition from, to; + short mult = MULT(ctx); -/* - * If no movement actually happened, then bump the count and try again. - * This causes the character position at the very beginning and end of - * a boundary to act correctly. - */ + if (mult < 0) { + mult = -mult; + dir = dir == XawsdLeft ? XawsdRight : XawsdLeft; + } - if (to == ctx->text.insertPos) - to = SrcScan(ctx->text.source, ctx->text.insertPos, - type, dir, ctx->text.mult + 1, include); + StartAction(ctx, event); +#ifndef OLDXAW + if (mult == 1) + _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True); +#endif + to = SrcScan(ctx->text.source, ctx->text.insertPos, + type, dir, mult, include); + + /* + * If no movement actually happened, then bump the count and try again. + * This causes the character position at the very beginning and end of + * a boundary to act correctly + */ + if (to == ctx->text.insertPos) + to = SrcScan(ctx->text.source, ctx->text.insertPos, + type, dir, mult + 1, include); + + if (dir == XawsdLeft) { + from = to; + to = ctx->text.insertPos; + } + else + from = ctx->text.insertPos; - if (dir == XawsdLeft) { - from = to; - to = ctx->text.insertPos; - } - else - from = ctx->text.insertPos; + _DeleteOrKill(ctx, from, to, kill); + EndAction(ctx); +} - _DeleteOrKill(ctx, from, to, kill); - _XawTextSetScrollBars(ctx); - EndAction(ctx); +static void +Delete(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + + if (ctx->text.s.left != ctx->text.s.right) + DeleteCurrentSelection(w, event, p, n); + else + DeleteBackwardChar(w, event, p, n); } -/*ARGSUSED*/ -static void -DeleteForwardChar(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +DeleteChar(Widget w, XEvent *event, XawTextScanDirection dir) { - DeleteOrKill((TextWidget) w, event, XawsdRight, XawstPositions, TRUE, FALSE); + TextWidget ctx = (TextWidget)w; + short mul = MULT(ctx); + + if (mul < 0) { + ctx->text.mult = mul = -mul; + dir = dir == XawsdLeft ? XawsdRight : XawsdLeft; + } + DeleteOrKill(ctx, event, dir, XawstPositions, True, False); +#ifndef OLDXAW + if (mul == 1) + _XawSourceSetUndoErase((TextSrcObject)ctx->text.source, + dir == XawsdLeft ? -1 : 1); +#endif } /*ARGSUSED*/ static void -DeleteBackwardChar(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +DeleteForwardChar(Widget w, XEvent *event, String *p, Cardinal *n) { - DeleteOrKill((TextWidget) w, event, XawsdLeft, XawstPositions, TRUE, FALSE); + DeleteChar(w, event, XawsdRight); } /*ARGSUSED*/ -static void -DeleteForwardWord(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +DeleteBackwardChar(Widget w, XEvent *event, String *p, Cardinal *n) +{ + DeleteChar(w, event, XawsdLeft); +} + +static void +DeleteForwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XawTextScanType type; + + if (*num_params && (*params[0] == 'A' || *params[0] == 'a')) + type = XawstAlphaNumeric; + else + type = XawstWhiteSpace; + + DeleteOrKill((TextWidget)w, event, XawsdRight, type, False, False); +} + +static void +DeleteBackwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params) { - DeleteOrKill((TextWidget) w, event, - XawsdRight, XawstWhiteSpace, FALSE, FALSE); + XawTextScanType type; + + if (*num_params && (*params[0] == 'A' || *params[0] == 'a')) + type = XawstAlphaNumeric; + else + type = XawstWhiteSpace; + + DeleteOrKill((TextWidget)w, event, XawsdLeft, type, False, False); +} + +static void +KillForwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XawTextScanType type; + + if (*num_params && (*params[0] == 'A' || *params[0] == 'a')) + type = XawstAlphaNumeric; + else + type = XawstWhiteSpace; + + DeleteOrKill((TextWidget)w, event, XawsdRight, type, False, True); +} + +static void +KillBackwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XawTextScanType type; + + if (*num_params && (*params[0] == 'A' || *params[0] == 'a')) + type = XawstAlphaNumeric; + else + type = XawstWhiteSpace; + + DeleteOrKill((TextWidget) w, event, XawsdLeft, type, False, True); } /*ARGSUSED*/ -static void -DeleteBackwardWord(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +KillToEndOfLine(Widget w, XEvent *event, String *p, Cardinal *n) { - DeleteOrKill((TextWidget) w, event, - XawsdLeft, XawstWhiteSpace, FALSE, FALSE); + TextWidget ctx = (TextWidget)w; + XawTextPosition end_of_line; + XawTextScanDirection dir = XawsdRight; + short mult = MULT(ctx); + + if (mult < 0) { + dir = XawsdLeft; + mult = -mult; + } + + StartAction(ctx, event); + end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, + dir, mult, False); + if (end_of_line == ctx->text.insertPos) + end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, + dir, mult, True); + + if (dir == XawsdRight) + _DeleteOrKill(ctx, ctx->text.insertPos, end_of_line, True); + else + _DeleteOrKill(ctx, end_of_line, ctx->text.insertPos, True); + EndAction(ctx); } /*ARGSUSED*/ -static void -KillForwardWord(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +KillToEndOfParagraph(Widget w, XEvent *event, String *p, Cardinal *n) +{ + DeleteOrKill((TextWidget)w, event, XawsdRight, XawstParagraph, False, True); +} + +void +_XawTextZapSelection(TextWidget ctx, XEvent *event, Bool kill) { - DeleteOrKill((TextWidget) w, event, - XawsdRight, XawstWhiteSpace, FALSE, TRUE); + StartAction(ctx, event); + _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill); + EndAction(ctx); } /*ARGSUSED*/ -static void -KillBackwardWord(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +KillCurrentSelection(Widget w, XEvent *event, String *p, Cardinal *n) { - DeleteOrKill((TextWidget) w, event, - XawsdLeft, XawstWhiteSpace, FALSE, TRUE); + _XawTextZapSelection((TextWidget) w, event, True); } +#ifndef OLDXAW /*ARGSUSED*/ static void -KillToEndOfLine(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +KillRingYank(Widget w, XEvent *event, String *params, Cardinal *num_params) { - TextWidget ctx = (TextWidget) w; - XawTextPosition end_of_line; + TextWidget ctx = (TextWidget)w; + XawTextPosition insertPos = ctx->text.insertPos; + Bool first_yank = False; - 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); + if (ctx->text.s.left != ctx->text.s.right) + XawTextUnsetSelection((Widget)ctx); - _DeleteOrKill(ctx, ctx->text.insertPos, end_of_line, TRUE); - _XawTextSetScrollBars(ctx); - EndAction(ctx); + StartAction(ctx, event); + + if (ctx->text.kill_ring_ptr == NULL) { + ctx->text.kill_ring_ptr = &kill_ring_prev; + ++ctx->text.kill_ring_ptr->refcount; + ctx->text.s.left = ctx->text.s.right = insertPos; + first_yank = True; + } + if (ctx->text.kill_ring_ptr) { + int mul = MULT(ctx); + XawTextBlock text; + + if (!first_yank) { + if (mul < 0) + mul = 1; + --ctx->text.kill_ring_ptr->refcount; + while (mul--) { + if ((ctx->text.kill_ring_ptr = ctx->text.kill_ring_ptr->next) == NULL) + ctx->text.kill_ring_ptr = &kill_ring_null; + } + ++ctx->text.kill_ring_ptr->refcount; + } + text.firstPos = 0; + text.length = ctx->text.kill_ring_ptr->length; + text.ptr = ctx->text.kill_ring_ptr->contents; + text.format = ctx->text.kill_ring_ptr->format; + + if (_XawTextReplace(ctx, ctx->text.s.left, insertPos, &text) == XawEditDone) { + ctx->text.kill_ring = KILL_RING_YANK; + ctx->text.insertPos = ctx->text.s.left + text.length; + } + } + else + XBell(XtDisplay(w), 0); + + EndAction(ctx); } +#endif /* OLDXAW */ /*ARGSUSED*/ -static void -KillToEndOfParagraph(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +DeleteCurrentSelection(Widget w, XEvent *event, String *p, Cardinal *n) +{ + _XawTextZapSelection((TextWidget)w, event, False); +} + +#ifndef OLDXAW +#define CHECK_SAVE() \ + if (save && !save->ptr) \ + save->ptr = _XawTextGetText(ctx, save->firstPos, \ + save->firstPos + save->length) +static Bool +StripSpaces(TextWidget ctx, XawTextPosition left, XawTextPosition right, + XawTextPosition *pos, int num_pos, XawTextBlock *save) +{ + Bool done, space; + int i, cpos, count = 0; + XawTextBlock block, text; + XawTextPosition ipos, position = left, tmp = left; + + text.firstPos = 0; + text.format = XawFmt8Bit; + text.ptr = " "; + text.length = 1; + + position = XawTextSourceRead(ctx->text.source, position, + &block, right - left); + done = False; + space = False; + /* convert tabs and returns to spaces */ + while (!done) { + if (XawTextFormat(ctx, XawFmt8Bit)) { + for (i = 0; i < block.length; i++) + if (block.ptr[i] == '\t' || block.ptr[i] == '\n') { + space = True; + break; + } + } + else { + wchar_t *wptr = (wchar_t*)block.ptr; + for (i = 0; i < block.length; i++) + if (wptr[i] == _Xaw_atowc('\t') || wptr[i] == _Xaw_atowc('\n')) { + space = True; + break; + } + } + if (space) { + CHECK_SAVE(); + if (_XawTextReplace(ctx, tmp + i, tmp + i + 1, &text)) + return (False); + space = False; + } + tmp += i; + position = XawTextSourceRead(ctx->text.source, tmp, + &block, right - tmp); + if (block.length == 0 || tmp == position || tmp >= right) + done = True; + } + + text.ptr = ""; + text.length = 0; + position = tmp = left; + position = XawTextSourceRead(ctx->text.source, position, + &block, right - left); + ipos = ctx->text.insertPos; + done = False; + while (!done) { + if (XawTextFormat(ctx, XawFmt8Bit)) { + for (i = 0; i < block.length; i++) + if (block.ptr[i] == ' ') + ++count; + else if (count == 1) + count = 0; + else if (count) + break; + } + else { + wchar_t *wptr = (wchar_t*)block.ptr; + for (i = 0; i < block.length; i++) + if (wptr[i] == _Xaw_atowc(' ')) + ++count; + else if (count == 1) + count = 0; + else if (count) + break; + } + if (--count > 0) { + CHECK_SAVE(); + if (_XawTextReplace(ctx, tmp + i - count, tmp + i, &text)) + return (False); + right -= count; + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) { + if (tmp + i - count < pos[cpos]) { + if (tmp + i < pos[cpos]) + pos[cpos] -= count; + else + pos[cpos] = tmp + i - count; + } + } + } + else { + if (tmp + i - count < ipos) { + if (tmp + i < ipos) + ipos -= count; + else + ipos = tmp + i - count; + } + } + tmp += i - count; + } + else + tmp += i + 1; + count = 0; + position = XawTextSourceRead(ctx->text.source, tmp, + &block, right - tmp); + if (block.length == 0 || tmp == position || tmp >= right) + done = True; + } + if (!num_pos) + ctx->text.insertPos = ipos; + + return (True); +} + +static Bool +Tabify(TextWidget ctx, XawTextPosition left, XawTextPosition right, + XawTextPosition *pos, int num_pos, XawTextBlock *save) { - DeleteOrKill((TextWidget) w, event, XawsdRight, XawstParagraph, FALSE, TRUE); + Bool done, zero; + int i, cpos, count = 0, column = 0, offset = 0; + XawTextBlock text, block; + XawTextPosition ipos, position = left, tmp = left; + TextSinkObject sink = (TextSinkObject)ctx->text.sink; + short *char_tabs = sink->text_sink.char_tabs; + int tab_count = sink->text_sink.tab_count; + int tab_index = 0, tab_column = 0, TAB_SIZE = DEFAULT_TAB_SIZE; + + text.firstPos = 0; + text.ptr = "\t"; + text.format = XawFmt8Bit; + text.length = 1; + + position = XawTextSourceRead(ctx->text.source, position, + &block, right - left); + ipos = ctx->text.insertPos; + done = zero = False; + if (tab_count) + TAB_SIZE = *char_tabs; + while (!done) { + if (XawTextFormat(ctx, XawFmt8Bit)) { + for (i = 0; i < block.length; i++) { + ++offset; + ++column; + if (tab_count) { + if (column > tab_column + char_tabs[tab_index]) { + TAB_SIZE = tab_index < tab_count - 1 ? char_tabs[tab_index + 1] - char_tabs[tab_index] : *char_tabs; + if (++tab_index >= tab_count) { + tab_column += char_tabs[tab_count - 1]; + tab_index = 0; + } + } + } + if (block.ptr[i] == ' ') { + if (++count > TAB_SIZE) + count %= TAB_SIZE; + if ((tab_count && column == tab_column + char_tabs[tab_index]) || + (!tab_count && column % TAB_SIZE == 0)) { + if (count % (TAB_SIZE + 1) > 1) + break; + else + count = 0; + } + } + else { + if (block.ptr[i] == '\n') { + zero = True; + break; + } + count = 0; + } + } + } + else { + wchar_t *wptr = (wchar_t*)block.ptr; + for (i = 0; i < block.length; i++) { + ++offset; + ++column; + if (tab_count) { + if (column > tab_column + char_tabs[tab_index]) { + TAB_SIZE = tab_index < tab_count - 1 ? char_tabs[tab_index + 1] - char_tabs[tab_index] : *char_tabs; + if (++tab_index >= tab_count) { + tab_column += char_tabs[tab_count - 1]; + tab_index = 0; + } + } + } + if (wptr[i] == _Xaw_atowc(' ')) { + if (++count > TAB_SIZE) + count %= TAB_SIZE; + if ((tab_count && column == tab_column + char_tabs[tab_index]) || + (!tab_count && column % TAB_SIZE == 0)) { + if (count % (TAB_SIZE + 1) > 1) + break; + else + count = 0; + } + } + else { + if (wptr[i] == _Xaw_atowc('\n')) { + zero = True; + break; + } + count = 0; + } + } + } + count %= TAB_SIZE + 1; + if (!zero && count > 1 && i < block.length) { + CHECK_SAVE(); + if (_XawTextReplace(ctx, tmp + i - count + 1, tmp + i + 1, &text)) + return (False); + right -= count - 1; + offset -= count - 1; + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) { + if (tmp + i - count + 1 < pos[cpos]) { + if (tmp + i + 1 < pos[cpos]) + pos[cpos] -= count; + else + pos[cpos] = tmp + i - count + 1; + ++pos[cpos]; + } + } + } + else { + if (tmp + i - count + 1 < ipos) { + if (tmp + i + 1 < ipos) + ipos -= count; + else + ipos = tmp + i - count + 1; + ++ipos; + } + } + } + if (count) + --count; + if (zero) { + count = column = 0; + zero = False; + if (tab_count) { + tab_column = tab_index = 0; + TAB_SIZE = *char_tabs; + } + } + else if (i < block.length) + count = 0; + tmp = left + offset; + position = XawTextSourceRead(ctx->text.source, tmp, + &block, right - tmp); + if (tmp == position || tmp >= right) + done = True; + } + if (!num_pos) + ctx->text.insertPos = ipos; + + return (True); } -void -_XawTextZapSelection(ctx, event, kill) -TextWidget ctx; -XEvent* event; -Boolean kill; +static Bool +Untabify(TextWidget ctx, XawTextPosition left, XawTextPosition right, + XawTextPosition *pos, int num_pos, XawTextBlock *save) { - StartAction(ctx, event); - _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill); - _XawTextSetScrollBars(ctx); - EndAction(ctx); + Bool done, zero; + int i, cpos, count = 0, diff = 0; + XawTextBlock block, text; + XawTextPosition ipos, position = left, tmp = left; + TextSinkObject sink = (TextSinkObject)ctx->text.sink; + short *char_tabs = sink->text_sink.char_tabs; + int tab_count = sink->text_sink.tab_count; + int tab_index = 0, tab_column = 0, tab_base = 0; + static char *tabs = " "; + + text.firstPos = 0; + text.format = XawFmt8Bit; + text.ptr = tabs; + + position = XawTextSourceRead(ctx->text.source, position, + &block, right - left); + ipos = ctx->text.insertPos; + done = False; + zero = False; + while (!done) { + if (XawTextFormat(ctx, XawFmt8Bit)) + for (i = 0; i < block.length; i++) { + if (block.ptr[i] != '\t') { + ++count; + if (block.ptr[i] == '\n') { + zero = True; + break; + } + } + else + break; + } + else { + wchar_t *wptr = (wchar_t*)block.ptr; + for (i = 0; i < block.length; i++) + if (wptr[i] != _Xaw_atowc('\t')) { + ++count; + if (wptr[i] != _Xaw_atowc('\n')) { + zero = True; + break; + } + } + else + break; + } + if (!zero && i < block.length) { + if (tab_count) { + while (tab_base + tab_column <= count) { + for (; tab_index < tab_count; ++tab_index) + if (tab_base + char_tabs[tab_index] > count) { + tab_column = char_tabs[tab_index]; + break; + } + if (tab_index >= tab_count) { + tab_base += char_tabs[tab_count - 1]; + tab_column = tab_index = 0; + } + } + text.length = (tab_base + tab_column) - count; + if (text.length > 8) { + int j; + + text.ptr = XtMalloc(text.length); + for (j = 0; j < text.length; j++) + text.ptr[j] = ' '; + } + else + text.ptr = tabs; + } + else + text.length = DEFAULT_TAB_SIZE - (count % DEFAULT_TAB_SIZE); + CHECK_SAVE(); + if (_XawTextReplace(ctx, tmp + i, tmp + i + 1, &text)) { + if (tab_count && text.length > 8) + XtFree(text.ptr); + return (False); + } + if (tab_count && text.length > 8) + XtFree(text.ptr); + count += text.length; + right += text.length - 1; + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) { + if (tmp + i < pos[cpos]) { + if (tmp + i + 1 < pos[cpos]) + --pos[cpos]; + else + pos[cpos] = tmp + i; + pos[cpos] += text.length; + } + } + } + else { + if (tmp + i < ipos) { + if (tmp + i + 1 < ipos) + --ipos; + else + ipos = tmp + i; + ipos += text.length; + } + } + } + tmp = left + count + diff; + if (zero) { + diff += count; + count = 0; + zero = False; + if (tab_count) + tab_base = tab_column = tab_index = 0; + } + position = XawTextSourceRead(ctx->text.source, tmp, + &block, right - tmp); + if (tmp == position || tmp >= right) + done = True; + } + if (!num_pos) + ctx->text.insertPos = ipos; + + return (True); } +static int +FormatText(TextWidget ctx, XawTextPosition left, Bool force, + XawTextPosition *pos, int num_pos) +{ + char *ptr = NULL; + Bool freepos = False, undo, paragraph = pos != NULL; + int i, result; + XawTextBlock block, *text; + XawTextPosition end = ctx->text.lastPos, buf[32]; + TextSrcObject src = (TextSrcObject)ctx->text.source; + XawTextPosition right = SrcScan(ctx->text.source, left, XawstEOL, + XawsdRight, 1, False); + + undo = src->textSrc.enable_undo && src->textSrc.undo_state == False; + if (undo) { + if (!pos) { + num_pos = src->textSrc.num_text; + pos = XawStackAlloc(sizeof(XawTextPosition) * num_pos, buf); + for (i = 0; i < num_pos; i++) + pos[i] = ((TextWidget)src->textSrc.text[i])->text.insertPos; + freepos = True; + } + else + freepos = False; + src->textSrc.undo_state = True; + block.ptr = NULL; + block.firstPos = left; + block.length = right - left; + text = █ + } + else + text = NULL; + + result = DoFormatText(ctx, left, force, 1, text, pos, num_pos, paragraph); + if (undo && result == XawEditDone && block.ptr) { + char *lbuf, *rbuf; + unsigned llen, rlen, size; + + ptr = lbuf = block.ptr; + llen = block.length; + rlen = llen + (ctx->text.lastPos - end); + + block.firstPos = 0; + block.format = _XawTextFormat(ctx); + + rbuf = _XawTextGetText(ctx, left, left + rlen); + + size = XawTextFormat(ctx, XawFmtWide) ? sizeof(wchar_t) : sizeof(char); + if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) { + block.ptr = lbuf; + block.length = llen; + _XawTextReplace(ctx, left, left + rlen, &block); + + src->textSrc.undo_state = False; + block.ptr = rbuf; + block.length = rlen; + _XawTextReplace(ctx, left, left + llen, &block); + } + else + src->textSrc.undo_state = False; + XtFree(rbuf); + } + if (undo) { + src->textSrc.undo_state = False; + if (freepos) { + for (i = 0; i < num_pos; i++) { + TextWidget tw = (TextWidget)src->textSrc.text[i]; + tw->text.insertPos = XawMin(XawMax(0, pos[i]), tw->text.lastPos); + } + XawStackFree(pos, buf); + } + if (ptr) + XtFree(ptr); + } + + return (result); +} + +static int +DoFormatText(TextWidget ctx, XawTextPosition left, Bool force, int level, + XawTextBlock *save, XawTextPosition *pos, int num_pos, + Bool paragraph) +{ + XawTextPosition right = SrcScan(ctx->text.source, left, XawstEOL, + XawsdRight, 1, False); + XawTextPosition position, tmp, ipos; + XawTextBlock block, text; + char buf[128]; + wchar_t *wptr; + int i, count, cpos; + Bool done, force2 = force, recurse = False; + + position = XawTextSourceRead(ctx->text.source, left, &block, right - left); + if (block.length == 0 || left >= right || + (level == 1 && ((XawTextFormat(ctx, XawFmt8Bit) && + block.ptr[0] != ' ' && + block.ptr[0] != '\t' && + !isalnum(*(unsigned char*)block.ptr)) || + (XawTextFormat(ctx, XawFmtWide) && + _Xaw_atowc(XawSP) != *(wchar_t*)block.ptr && + _Xaw_atowc(XawTAB) != *(wchar_t*)block.ptr && + !iswalnum(*(wchar_t*)block.ptr))))) + return (XawEditDone); + + if (level == 1 && !paragraph) { + tmp = ctx->text.lastPos; + if (Untabify(ctx, left, right, pos, num_pos, save) == False) + return (XawEditError); + right += ctx->text.lastPos - tmp; + position = XawTextSourceRead(ctx->text.source, left, &block, + right - left); + } + + text.firstPos = 0; + text.format = XawFmt8Bit; + + ipos = ctx->text.insertPos; + count = 0; + done = False; + while (!done) { + if (XawTextFormat(ctx, XawFmt8Bit)) { + for (i = 0; i < block.length; i++) + if (block.ptr[i] == ' ') + ++count; + else { + done = True; + break; + } + } + else { + wptr = (wchar_t*)block.ptr; + for (i = 0; i < block.length; i++) + if (wptr[i] == _Xaw_atowc(' ')) + ++count; + else { + done = True; + break; + } + } + tmp = position; + position = XawTextSourceRead(ctx->text.source, position, + &block, right - position); + if (tmp == position) + done = True; + } + position = left + count; + if (count < ctx->text.left_column) { + int bytes = ctx->text.left_column - count; + + text.ptr = XawStackAlloc(bytes, buf); + text.length = bytes; + for (i = 0; i < bytes; i++) + text.ptr[i] = ' '; + CHECK_SAVE(); + if (_XawTextReplace(ctx, left, left, &text)) { + XawStackFree(text.ptr, buf); + return (XawEditError); + } + XawStackFree(text.ptr, buf); + right += bytes; + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) + if (pos[cpos] >= left) + pos[cpos] += bytes; + } + if (ipos >= left) + ipos += bytes; + count += bytes; + } + + done = False; + if (!paragraph && level == 1 + && ipos <= right && ipos - left > ctx->text.right_column) { + XawTextPosition len = ctx->text.lastPos; + int skip = ctx->text.justify == XawjustifyRight + || ctx->text.justify == XawjustifyCenter ? + ctx->text.left_column : count; + + if (pos) + for (i = 0; i < num_pos; i++) + if (pos[i] == ipos) + break; + + StripSpaces(ctx, left + skip, right, pos, num_pos, save); + right += ctx->text.lastPos - len; + if (pos && i < num_pos) + ipos = pos[i]; + else + ipos = ctx->text.insertPos; + done = ipos - left > ctx->text.right_column; + count = skip + (count == skip + 1); + } + if ((paragraph || done) && right - left > ctx->text.right_column) { + position = tmp = right; + XawTextSourceRead(ctx->text.source, position - 1, &block, 1); + if (block.length && + ((XawTextFormat(ctx, XawFmt8Bit) && + block.ptr[0] == ' ') || + (XawTextFormat(ctx, XawFmtWide) && + _Xaw_atowc(XawSP) == *(wchar_t*)block.ptr))) + --position; + while (position - left > ctx->text.right_column) { + tmp = position; + position = SrcScan(ctx->text.source, position, + XawstWhiteSpace, XawsdLeft, 1, True); + } + if (position <= left + ctx->text.left_column) + position = tmp; + if (position > left && position - left > ctx->text.left_column + && position != right) { + text.ptr = "\n"; + text.length = 1; + CHECK_SAVE(); + if (_XawTextReplace(ctx, position, position + 1, &text)) + return (XawEditError); + right = position; + recurse = True; + force = True; + } + } + + if (force) { + if (ctx->text.justify == XawjustifyCenter) + count = ctx->text.right_column - (count - ctx->text.left_column); + else + count = ctx->text.right_column; + if (count > right - left) + count -= right - left; + else + count = 0; + } + else + count = 0; + if (count > 0) { + switch (ctx->text.justify) { + case XawjustifyLeft: + break; + case XawjustifyRight: + case XawjustifyCenter: + if (ctx->text.justify == XawjustifyCenter) { + int alnum = 0; + + if (!(count & 1)) { + XawTextSourceRead(ctx->text.source, right, &block, 1); + if ((XawTextFormat(ctx, XawFmt8Bit) + && isalnum(*(unsigned char*)block.ptr)) || + (XawTextFormat(ctx, XawFmtWide) + && iswalnum(*(wchar_t*)block.ptr))) + alnum = 1; + } + count = (count + alnum) >> 1; + } + text.ptr = XawStackAlloc(count, buf); + text.length = count; + for (i = 0; i < count; i++) + text.ptr[i] = ' '; + CHECK_SAVE(); + if (_XawTextReplace(ctx, left, left, &text)) { + XawStackFree(text.ptr, buf); + return (XawEditError); + } + XawStackFree(text.ptr, buf); + position += count; + right += count; + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) + if (pos[cpos] > left) + pos[cpos] += count; + } + else if (ipos > left) + ipos += count; + break; + case XawjustifyFull: + i = 0; + tmp = left; + /*CONSTCOND*/ + while (True) { + tmp = SrcScan(ctx->text.source, tmp, XawstWhiteSpace, + XawsdRight, 1, True); + if (tmp < right) + ++i; + else + break; + } + if (i) { + double inc, ii; + int bytes, steps; + + bytes = count; + inc = ii = (count + .5) / (double)i; + + steps = count; + text.ptr = XawStackAlloc(steps, buf); + for (i = 0; i < steps; i++) + text.ptr[i] = ' '; + tmp = left; + CHECK_SAVE(); + while (bytes) { + steps = 1; + while (inc + ii < 1) { + ++steps; + inc += ii; + } + tmp = SrcScan(ctx->text.source, tmp, XawstWhiteSpace, + XawsdRight, steps, True); + if (bytes > inc) + text.length = (int)inc; + else + text.length = bytes; + bytes -= text.length; + if (_XawTextReplace(ctx, tmp, tmp, &text)) { + XawStackFree(buf, text.ptr); + return (XawEditError); + } + if (num_pos) { + for (cpos = 0; cpos < num_pos; cpos++) + if (tmp <= pos[cpos]) + pos[cpos] += text.length; + } + else if (tmp <= ipos) + ipos += text.length; + inc -= (int)inc; + inc += ii; + } + position += count; + right += count; + XawStackFree(buf, text.ptr); + } + break; + } + } + + if (!num_pos) + ctx->text.insertPos = XawMin(ipos, ctx->text.lastPos); + + return (recurse ? DoFormatText(ctx, position + 1, + ctx->text.justify != XawjustifyFull + && (force2 || paragraph), + ++level, save, pos, num_pos, paragraph) + : XawEditDone); +} +#undef CHECK_SAVE + /*ARGSUSED*/ -static void -KillCurrentSelection(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +Indent(Widget w, XEvent *event, String *params, Cardinal *num_params) { - _XawTextZapSelection( (TextWidget) w, event, TRUE); + TextWidget ctx = (TextWidget)w; + TextSrcObject src = (TextSrcObject)ctx->text.source; + XawTextPosition from, to, tmp, end = 0, *pos, *posbuf[32]; + char buf[32]; + XawTextBlock text; + int i, spaces = MULT(ctx); + char *lbuf = NULL, *rbuf; + unsigned llen = 0, rlen, size; + Bool undo = src->textSrc.enable_undo && src->textSrc.undo_state == False; + Bool format = ctx->text.auto_fill + && ctx->text.left_column < ctx->text.right_column; + + text.firstPos = 0; + text.format = XawFmt8Bit; + text.ptr = ""; + + StartAction(ctx, event); + + pos = XawStackAlloc(sizeof(XawTextPosition) * src->textSrc.num_text, posbuf); + for (i = 0; i < src->textSrc.num_text; i++) + pos[i] = ((TextWidget)src->textSrc.text[i])->text.insertPos; + + if (!GetBlockBoundaries(ctx, &from, &to)) { + EndAction(ctx); + XawStackFree(pos, posbuf); + return; + } + + if (undo) { + llen = to - from; + end = ctx->text.lastPos; + lbuf = _XawTextGetText(ctx, from, to); + src->textSrc.undo_state = True; + } + + tmp = ctx->text.lastPos; + if (!Untabify(ctx, from, to, pos, src->textSrc.num_text, NULL)) { + XBell(XtDisplay(ctx), 0); + EndAction(ctx); + XawStackFree(pos, posbuf); + if (undo) { + src->textSrc.undo_state = True; + XtFree(lbuf); + } + return; + } + to += ctx->text.lastPos - tmp; + + tmp = from; + + if (spaces > 0) { + text.ptr = XawStackAlloc(spaces, buf); + for (i = 0; i < spaces; i++) + text.ptr[i] = ' '; + + text.length = spaces; + while (tmp < to) { + _XawTextReplace(ctx, tmp, tmp, &text); + + for (i = 0; i < src->textSrc.num_text; i++) + if (tmp < pos[i]) + pos[i] += spaces; + + to += spaces; + tmp = SrcScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True); + } + XawStackFree(text.ptr, buf); + } + else { + int min = 32767; + + text.length = 0; + tmp = from; + + /* find the amount of spaces to cut */ + while (tmp < to) { + (void)BlankLine(w, tmp, &i); + if (i < min) + min = i; + tmp = SrcScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True); + } + spaces = XawMin(-spaces, min); + + /* cut the spaces */ + tmp = from; + while (tmp < to) { + _XawTextReplace(ctx, tmp, tmp + spaces, &text); + + for (i = 0; i < src->textSrc.num_text; i++) + if (tmp < pos[i]) { + if (tmp + spaces < pos[i]) + pos[i] -= spaces; + else + pos[i] = tmp; + } + + to -= spaces; + tmp = SrcScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True); + } + } + + if (!format) + Tabify(ctx, from, to, pos, src->textSrc.num_text, NULL); + + if (undo) { + rlen = llen + (ctx->text.lastPos - end); + rbuf = _XawTextGetText(ctx, from, from + rlen); + + text.format = _XawTextFormat(ctx); + size = XawTextFormat(ctx, XawFmtWide) ? sizeof(wchar_t) : sizeof(char); + if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) { + text.ptr = lbuf; + text.length = llen; + _XawTextReplace(ctx, from, from + rlen, &text); + + src->textSrc.undo_state = False; + text.ptr = rbuf; + text.length = rlen; + _XawTextReplace(ctx, from, from + llen, &text); + } + else + src->textSrc.undo_state = False; + XtFree(lbuf); + XtFree(rbuf); + } + + for (i = 0; i < src->textSrc.num_text; i++) { + TextWidget tw = (TextWidget)src->textSrc.text[i]; + + tw->text.insertPos = XawMin(XawMax(0, pos[i]), tw->text.lastPos); + } + XawStackFree(pos, posbuf); + ctx->text.showposition = True; + + EndAction(ctx); } /*ARGSUSED*/ -static void -DeleteCurrentSelection(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +ToggleOverwrite(Widget w, XEvent *event, String *params, Cardinal *num_params) { - _XawTextZapSelection( (TextWidget) w, event, FALSE); + TextWidget ctx = (TextWidget)w; + + ctx->text.overwrite = !ctx->text.overwrite; + + /* call information callback */ + _XawTextSetLineAndColumnNumber(ctx, True); } +#endif /* OLDXAW */ -/************************************************************ - * - * Insertion Routines. - * - ************************************************************/ - -static int -InsertNewLineAndBackupInternal(ctx) -TextWidget ctx; -{ - int count, error = XawEditDone; - XawTextBlock text; - - text.format = _XawTextFormat(ctx); - text.length = ctx->text.mult; - text.firstPos = 0; - - if ( text.format == XawFmtWide ) { - wchar_t* wptr; - text.ptr = XtMalloc(sizeof(wchar_t) * ctx->text.mult); - wptr = (wchar_t *)text.ptr; - for (count = 0; count < ctx->text.mult; count++ ) - wptr[count] = _Xaw_atowc(XawLF); - } - else { - text.ptr = XtMalloc(sizeof(char) * ctx->text.mult); - for (count = 0; count < ctx->text.mult; count++ ) - text.ptr[count] = XawLF; - } - - if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { - XBell( XtDisplay(ctx), 50); - error = XawEditError; - } - else - ctx->text.showposition = TRUE; +/* + * Insertion Routines + */ +static int +InsertNewLineAndBackupInternal(TextWidget ctx) +{ + int count, error = XawEditDone, mult = MULT(ctx); + XawTextPosition position; + XawTextBlock text; + char buf[32]; + + if (mult < 0) { + ctx->text.mult = 1; + return (XawEditError); + } + + text.format = _XawTextFormat(ctx); + text.length = mult; + text.firstPos = 0; + + if (text.format == XawFmtWide) { + wchar_t *wptr; + + text.ptr = XawStackAlloc(sizeof(wchar_t) * mult, buf); + wptr = (wchar_t *)text.ptr; + for (count = 0; count < mult; count++) + wptr[count] = _Xaw_atowc(XawLF); + } + else { + text.ptr = XawStackAlloc(sizeof(char) * mult, buf); + for (count = 0; count < mult; count++) + text.ptr[count] = XawLF; + } + + position = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, False); + if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { + XBell( XtDisplay(ctx), 50); + error = XawEditError; + } + else { + ctx->text.showposition = TRUE; + ctx->text.insertPos += text.length; + } + + XawStackFree(text.ptr, buf); + +#ifndef OLDXAW + if (ctx->text.auto_fill && error == XawEditDone) + (void)FormatText(ctx, position, ctx->text.justify != XawjustifyFull, + NULL, 0); +#endif - XtFree( text.ptr ); - return( error ); + return (error); } /*ARGSUSED*/ -static void -InsertNewLineAndBackup(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +static void +InsertNewLineAndBackup(Widget w, XEvent *event, String *p, Cardinal *n) { - StartAction( (TextWidget) w, event ); - (void) InsertNewLineAndBackupInternal( (TextWidget) w ); - _XawTextSetScrollBars( (TextWidget) w); - EndAction( (TextWidget) w ); + TextWidget ctx = (TextWidget)w; + XawTextPosition insertPos = ctx->text.insertPos; + + StartAction((TextWidget)w, event); + (void)InsertNewLineAndBackupInternal(ctx); + ctx->text.insertPos = SrcScan(ctx->text.source, insertPos, XawstEOL, + XawsdRight, 1, False); + EndAction((TextWidget)w); } static int -LocalInsertNewLine(ctx, event) - TextWidget ctx; - XEvent* event; +LocalInsertNewLine(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); - _XawTextSetScrollBars(ctx); - EndAction(ctx); - return(XawEditDone); + int error; + + StartAction(ctx, event); + error = InsertNewLineAndBackupInternal(ctx); + ctx->text.from_left = -1; + EndAction(ctx); + + return (error); } /*ARGSUSED*/ static void -InsertNewLine(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +InsertNewLine(Widget w, XEvent *event, String *p, Cardinal *n) { - (void) LocalInsertNewLine( (TextWidget) w, event); + (void)LocalInsertNewLine((TextWidget)w, event); } /*ARGSUSED*/ -static void -InsertNewLineAndIndent(w, event, p, n) -Widget w; -XEvent *event; -String *p; -Cardinal *n; -{ - XawTextBlock text; - XawTextPosition pos1; - int length; - TextWidget ctx = (TextWidget) w; - String line_to_ip; - - StartAction(ctx, event); - pos1 = SrcScan(ctx->text.source, ctx->text.insertPos, - XawstEOL, XawsdLeft, 1, FALSE); - - line_to_ip = _XawTextGetText(ctx, pos1, ctx->text.insertPos); - - text.format = _XawTextFormat(ctx); - text.firstPos = 0; - - if ( text.format == XawFmtWide ) { - wchar_t* ptr; - text.ptr = XtMalloc( ( 2 + wcslen((wchar_t*)line_to_ip) ) * sizeof(wchar_t) ); - - ptr = (wchar_t*)text.ptr; - ptr[0] = _Xaw_atowc( XawLF ); - wcscpy( (wchar_t*) ++ptr, (wchar_t*) line_to_ip ); - - length = wcslen((wchar_t*)text.ptr); - while ( length && ( iswspace(*ptr) || ( *ptr == _Xaw_atowc(XawTAB) ) ) ) - ptr++, length--; - *ptr = (wchar_t)0; - text.length = wcslen((wchar_t*)text.ptr); - - } else { - char *ptr; - length = strlen(line_to_ip); - text.ptr = XtMalloc( ( 2 + length ) * sizeof( char ) ); - ptr = text.ptr; - ptr[0] = XawLF; - strcpy( ++ptr, line_to_ip ); - - length++; - while ( length && ( isspace(*ptr) || ( *ptr == XawTAB ) ) ) - ptr++, length--; - *ptr = '\0'; - text.length = strlen(text.ptr); - } - XtFree( line_to_ip ); - - if (_XawTextReplace(ctx,ctx->text.insertPos, ctx->text.insertPos, &text)) { - XBell(XtDisplay(ctx), 50); +static void +InsertNewLineAndIndent(Widget w, XEvent *event, String *p, Cardinal *n) +{ + XawTextBlock text; + XawTextPosition pos1; + int length; + TextWidget ctx = (TextWidget)w; + String line_to_ip; + + StartAction(ctx, event); + pos1 = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, False); + + line_to_ip = _XawTextGetText(ctx, pos1, ctx->text.insertPos); + + text.format = _XawTextFormat(ctx); + text.firstPos = 0; + + if (text.format == XawFmtWide) { + wchar_t *ptr; + + text.ptr = XtMalloc((2 + wcslen((wchar_t*)line_to_ip)) + * sizeof(wchar_t)); + ptr = (wchar_t*)text.ptr; + ptr[0] = _Xaw_atowc(XawLF); + wcscpy((wchar_t*)++ptr, (wchar_t*)line_to_ip); + + length = wcslen((wchar_t*)text.ptr); + while (length && (iswspace(*ptr) || *ptr == _Xaw_atowc(XawTAB))) + ptr++, length--; + *ptr = (wchar_t)0; + text.length = wcslen((wchar_t*)text.ptr); + } + else { + char *ptr; + + length = strlen(line_to_ip); + text.ptr = XtMalloc((2 + length) * sizeof(char)); + ptr = text.ptr; + ptr[0] = XawLF; + strcpy(++ptr, line_to_ip); + + length++; + while (length && (isspace(*ptr) || (*ptr == XawTAB))) + ptr++, length--; + *ptr = '\0'; + text.length = strlen(text.ptr); + } + XtFree(line_to_ip); + + if (_XawTextReplace(ctx,ctx->text.insertPos, ctx->text.insertPos, &text)) { + XBell(XtDisplay(ctx), 50); + XtFree(text.ptr); + EndAction(ctx); + return; + } + XtFree(text.ptr); + ctx->text.from_left = -1; + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert, + XawstPositions, XawsdRight, text.length, True); EndAction(ctx); - return; - } - XtFree(text.ptr); - ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, - XawstPositions, XawsdRight, text.length, TRUE); - _XawTextSetScrollBars(ctx); - EndAction(ctx); } -/************************************************************ - * - * Selection Routines. - * - *************************************************************/ - -static void -SelectWord(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; -Cardinal* num_params; +/* + * Selection Routines + */ +static void +SelectWord(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); + 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; +static void +SelectAll(Widget w, XEvent *event, String *params, Cardinal *num_params) { - TextWidget ctx = (TextWidget) w; + TextWidget ctx = (TextWidget)w; - StartAction(ctx, event); - _XawTextSetSelection(ctx,zeroPosition,ctx->text.lastPos,params,*num_params); - EndAction(ctx); + 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 */ +ModifySelection(TextWidget ctx, XEvent *event, + XawTextSelectionMode mode, + XawTextSelectionAction action, + String *params, Cardinal *num_params) { - StartAction(ctx, event); - NotePosition(ctx, event); - _XawTextAlterSelection(ctx, mode, action, params, num_params); - EndAction(ctx); +#ifndef OLDXAW + int old_y = ctx->text.ev_y; +#endif + + StartAction(ctx, event); + NotePosition(ctx, event); + +#ifndef OLDXAW + if (event->type == MotionNotify) { + if (ctx->text.ev_y <= ctx->text.margin.top) { + if (old_y >= ctx->text.ev_y) + XawTextScroll(ctx, -1, 0); + } + else if (ctx->text.ev_y >= XtHeight(ctx) - ctx->text.margin.bottom) { + if (old_y <= ctx->text.ev_y + && !IsPositionVisible(ctx, ctx->text.lastPos)) + XawTextScroll(ctx, 1, 0); + } + } +#endif + ctx->text.from_left = -1; + _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 */ + +static void +SelectStart(Widget w, XEvent *event, String *params, Cardinal *num_params) { - ModifySelection((TextWidget) w, event, - XawsmTextSelect, XawactionStart, params, num_params); + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (!ctx->text.selection_state) { + ctx->text.selection_state = True; +#endif + ModifySelection(ctx, event, + XawsmTextSelect, XawactionStart, params, num_params); +#ifndef OLDXAW + } +#endif } -/* ARGSUSED */ -static void -SelectAdjust(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; /* unused */ -Cardinal* num_params; /* unused */ +static void +SelectAdjust(Widget w, XEvent *event, String *params, Cardinal *num_params) { - ModifySelection((TextWidget) w, event, - XawsmTextSelect, XawactionAdjust, params, num_params); + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (ctx->text.selection_state) +#endif + ModifySelection(ctx, event, + XawsmTextSelect, XawactionAdjust, params, num_params); } -static void -SelectEnd(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; -Cardinal* num_params; +static void +SelectEnd(Widget w, XEvent *event, String *params, Cardinal *num_params) { - ModifySelection((TextWidget) w, event, - XawsmTextSelect, XawactionEnd, params, num_params); + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (ctx->text.selection_state) { + ctx->text.selection_state = False; +#endif + ModifySelection(ctx, event, + XawsmTextSelect, XawactionEnd, params, num_params); +#ifndef OLDXAW + } +#endif } -/* ARGSUSED */ -static void -ExtendStart(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; /* unused */ -Cardinal* num_params; /* unused */ +static void +ExtendStart(Widget w, XEvent *event, String *params, Cardinal *num_params) { - ModifySelection((TextWidget) w, event, - XawsmTextExtend, XawactionStart, params, num_params); + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (!ctx->text.selection_state) { + ctx->text.selection_state = True; +#endif + ModifySelection(ctx, event, + XawsmTextExtend, XawactionStart, params, num_params); +#ifndef OLDXAW + } +#endif } -/* ARGSUSED */ -static void -ExtendAdjust(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; /* unused */ -Cardinal* num_params; /* unused */ +static void +ExtendAdjust(Widget w, XEvent *event, String *params, Cardinal *num_params) { - ModifySelection((TextWidget) w, event, - XawsmTextExtend, XawactionAdjust, params, num_params); + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (ctx->text.selection_state) +#endif + ModifySelection(ctx, event, + XawsmTextExtend, XawactionAdjust, params, num_params); } -static void -ExtendEnd(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; -Cardinal* num_params; +static void +ExtendEnd(Widget w, XEvent *event, String *params, Cardinal *num_params) { - ModifySelection((TextWidget) w, event, - XawsmTextExtend, XawactionEnd, params, num_params); + TextWidget ctx = (TextWidget)w; + +#ifndef OLDXAW + if (ctx->text.selection_state) { + ctx->text.selection_state = False; +#endif + ModifySelection(ctx, event, + XawsmTextExtend, XawactionEnd, params, num_params); +#ifndef OLDXAW + } +#endif } static void -SelectSave(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; -Cardinal* num_params; +SelectSave(Widget w, XEvent *event, String *params, Cardinal *num_params) { - int num_atoms; - Atom* sel; - Display* dpy = XtDisplay(w); - Atom selections[256]; + int num_atoms; + Atom *sel; + Display *dpy = XtDisplay(w); + Atom selections[256]; - StartAction( (TextWidget) w, event ); + StartAction((TextWidget)w, event); num_atoms = *num_params; if (num_atoms > 256) num_atoms = 256; for (sel=selections; --num_atoms >= 0; sel++, params++) *sel = XInternAtom(dpy, *params, False); num_atoms = *num_params; - _XawTextSaltAwaySelection( (TextWidget) w, selections, num_atoms ); - EndAction( (TextWidget) w ); + _XawTextSaltAwaySelection((TextWidget)w, selections, num_atoms); + EndAction((TextWidget)w); } -/************************************************************ - * - * Misc. Routines. - * - ************************************************************/ +/* + * Misc. Routines + */ +/*ARGSUSED*/ +static void +SetKeyboardFocus(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + Widget shell, parent; + + shell = parent = w; + while (parent) { + if (XtIsShell(shell = parent)) + break; + parent = XtParent(parent); + } + XtSetKeyboardFocus(shell, w); +} + +/*ARGSUSED*/ +static void +RedrawDisplay(Widget w, XEvent *event, String *p, Cardinal *n) +{ + StartAction((TextWidget)w, event); + _XawTextClearAndCenterDisplay((TextWidget)w); + EndAction((TextWidget)w); +} -/* ARGSUSED */ -static void -RedrawDisplay(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +/* This is kind of a hack, but, only one text widget can have focus at + * a time on one display. There is a problem in the implementation of the + * text widget, the scrollbars can not be adressed via editres, since they + * are not children of a subclass of composite. + * The focus variable is required to make sure only one text window will + * show a block cursor at one time. + */ +struct _focus { Display *display; Widget widget; }; +static struct _focus *focus; +static Cardinal num_focus; + +/*ARGSUSED*/ +static void +DestroyFocusCallback(Widget w, XtPointer user_data, XtPointer call_data) { - StartAction( (TextWidget) w, event); - _XawTextClearAndCenterDisplay((TextWidget) w); - EndAction( (TextWidget) w); + struct _focus *f = (struct _focus*)(user_data); + + if (f->widget == w) + f->widget = NULL; } /*ARGSUSED*/ static void -TextFocusIn (w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +TextFocusIn(Widget w, XEvent *event, String *p, Cardinal *n) { - TextWidget ctx = (TextWidget) w; + TextWidget ctx = (TextWidget)w; + Bool display_caret = ctx->text.display_caret; + int i; + + if (event->xfocus.detail == NotifyPointer) + return; - /* Let the input method know focus has arrived. */ - _XawImSetFocusValues (w, NULL, 0); - if ( event->xfocus.detail == NotifyPointer ) return; + if (event->xfocus.send_event) { + Window root, child; + int rootx, rooty, x, y; + unsigned int mask; - ctx->text.hasfocus = TRUE; + if (ctx->text.hasfocus) + return; + + if (XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, + &rootx, &rooty, &x, &y, &mask)) { + if (child) + return; + } + } + + /* Let the input method know focus has arrived. */ + _XawImSetFocusValues(w, NULL, 0); + + if (display_caret) + StartAction(ctx, event); + ctx->text.hasfocus = TRUE; + if (display_caret) + EndAction(ctx); + + for (i = 0; i < num_focus; i++) + if (focus[i].display == XtDisplay(w)) + break; + if (i >= num_focus) { + focus = (struct _focus*) + XtRealloc((XtPointer)focus, sizeof(struct _focus) * (num_focus + 1)); + i = num_focus; + focus[i].widget = NULL; + focus[i].display = XtDisplay(w); + num_focus++; + } + if (focus[i].widget != w) { + Widget old = focus[i].widget; + + focus[i].widget = w; + if (old != NULL) { + TextFocusOut(old, event, p, n); + /* TextFocusOut may set it to NULL */ + focus[i].widget = w; + } + XtAddCallback(w, XtNdestroyCallback, + DestroyFocusCallback, (XtPointer)&focus[i]); + } } /*ARGSUSED*/ static void -TextFocusOut(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; +TextFocusOut(Widget w, XEvent *event, String *p, Cardinal *n) { - TextWidget ctx = (TextWidget) w; + TextWidget ctx = (TextWidget)w; + Bool display_caret = ctx->text.display_caret; + Widget shell; + Window window; + int i, revert; + + shell = w; + while (shell) { + if (XtIsShell(shell)) + break; + shell = XtParent(shell); + } + + for (i = 0; i < num_focus; i++) + if (focus[i].display == XtDisplay(w)) + break; + XGetInputFocus(XtDisplay(w), &window, &revert); + if ((XtWindow(shell) == window && + (i < num_focus && focus[i].widget == w)) + || event->xfocus.detail == NotifyPointer) + return; + + if (i < num_focus && focus[i].widget) { + XtRemoveCallback(focus[i].widget, XtNdestroyCallback, + DestroyFocusCallback, (XtPointer)&focus[i]); + focus[i].widget = NULL; + } + + /* Let the input method know focus has left.*/ + _XawImUnsetFocus(w); - /* Let the input method know focus has left.*/ - _XawImUnsetFocus(w); - if ( event->xfocus.detail == NotifyPointer ) return; - ctx->text.hasfocus = FALSE; + if (display_caret) + StartAction(ctx, event); + ctx->text.hasfocus = FALSE; + if (display_caret) + EndAction(ctx); } /*ARGSUSED*/ static void -TextEnterWindow( w, event, params, num_params ) - Widget w; - XEvent* event; - String* params; - Cardinal* num_params; +TextEnterWindow(Widget w, XEvent *event, String *params, Cardinal *num_params) { - TextWidget ctx = (TextWidget) w; + TextWidget ctx = (TextWidget)w; - if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus && - !ctx->text.hasfocus) { + if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus + && !ctx->text.hasfocus) _XawImSetFocusValues(w, NULL, 0); - } } /*ARGSUSED*/ static void -TextLeaveWindow( w, event, params, num_params ) - Widget w; - XEvent* event; - String* params; - Cardinal* num_params; +TextLeaveWindow(Widget w, XEvent *event, String *params, Cardinal *num_params) { - TextWidget ctx = (TextWidget) w; + TextWidget ctx = (TextWidget)w; - if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus && - !ctx->text.hasfocus) { + if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus + && !ctx->text.hasfocus) _XawImUnsetFocus(w); - } } -static XComposeStatus compose_status = {NULL, 0}; - -/* Function Name: AutoFill - * Description: Breaks the line at the previous word boundry when - * called inside InsertChar. +/* + * Function: + * AutoFill * Arguments: ctx - The text widget. - * Returns: none + * + * Description: + * Breaks the line at the previous word boundry when + * called inside InsertChar. */ - static void -AutoFill(ctx) -TextWidget ctx; +AutoFill(TextWidget ctx) { - int width, height, x, line_num, max_width; - XawTextPosition ret_pos; - XawTextBlock text; + int width, height, x, line_num, max_width; + XawTextPosition ret_pos; + XawTextBlock text; + XRectangle cursor; + wchar_t wc_buf[2]; + + for (line_num = 0; line_num < ctx->text.lt.lines ; line_num++) + if (ctx->text.lt.info[line_num].position >= ctx->text.insertPos) + break; + if (line_num) + line_num--; /* backup a line. */ + + XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); + max_width = Max(0, (int)XtWidth(ctx) - RHMargins(ctx) - cursor.width); + + x = ctx->text.r_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.lt.info[line_num].position + || ret_pos >= ctx->text.insertPos || ret_pos < 1) + return; - if ( !((ctx->text.auto_fill) && (ctx->text.mult == 1)) ) - return; + XawTextSourceRead(ctx->text.source, ret_pos - 1, &text, 1); - 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. */ + if (XawTextFormat(ctx, XawFmtWide)) { + wc_buf[0] = *(wchar_t *)text.ptr; + if (wc_buf[0] != _Xaw_atowc(XawSP) && wc_buf[0] != _Xaw_atowc(XawTAB)) + /* Only eats white spaces */ + return; - max_width = Max(0, (int)(ctx->core.width - HMargins(ctx))); + text.format = XawFmtWide; + text.ptr = (char *)wc_buf; + wc_buf[0] = _Xaw_atowc(XawLF); + wc_buf[1] = 0; + } + else { + if (text.ptr[0] != XawSP && text.ptr[0] != XawTAB) + /* Only eats white spaces */ + return; - 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.format = XawFmt8Bit; - if (_XawTextFormat(ctx) == XawFmtWide) { - text.format = XawFmtWide; - text.ptr = (char *)XtMalloc(sizeof(wchar_t) * 2); - ((wchar_t*)text.ptr)[0] = _Xaw_atowc(XawLF); - ((wchar_t*)text.ptr)[1] = 0; - } else - text.ptr = "\n"; - text.length = 1; - text.firstPos = 0; + text.format = XawFmt8Bit; + text.ptr = "\n"; + } + text.length = 1; + text.firstPos = 0; - if (_XawTextReplace(ctx, ret_pos - 1, ret_pos, &text)) - XBell(XtDisplay((Widget) ctx), 0); /* Unable to edit, complain. */ + if (_XawTextReplace(ctx, ret_pos - 1, ret_pos, &text)) + XBell(XtDisplay((Widget)ctx), 0); + + if (++ctx->text.insertPos > ctx->text.lastPos) + ctx->text.insertPos = ctx->text.lastPos; } /*ARGSUSED*/ static void -InsertChar(w, event, p, n) -Widget w; -XEvent* event; -String* p; -Cardinal* n; -{ - TextWidget ctx = (TextWidget) w; - char *ptr, strbuf[BUFSIZ]; - int count, error; - KeySym keysym; - XawTextBlock text; - - if (XtIsSubclass (ctx->text.source, (WidgetClass) multiSrcObjectClass)) - text.length = _XawImWcLookupString (w, &event->xkey, - (wchar_t*) strbuf, BUFSIZ, &keysym, (Status*) &compose_status); - else - text.length = XLookupString ((XKeyEvent*)event, strbuf, BUFSIZ, &keysym, &compose_status); - - if (text.length == 0) - return; - - text.format = _XawTextFormat( ctx ); - if ( text.format == XawFmtWide ) { - text.ptr = ptr = XtMalloc(sizeof(wchar_t) * text.length * ctx->text.mult ); - for (count = 0; count < ctx->text.mult; count++ ) { - memcpy((char*) ptr, (char *)strbuf, sizeof(wchar_t) * text.length ); - ptr += sizeof(wchar_t) * text.length; - } - - } else { /* == XawFmt8Bit */ - 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; - - StartAction(ctx, event); - - error = _XawTextReplace(ctx, ctx->text.insertPos,ctx->text.insertPos, &text); +InsertChar(Widget w, XEvent *event, String *p, Cardinal *n) +{ + TextWidget ctx = (TextWidget)w; + char *ptr, strbuf[128], ptrbuf[512]; + int count, error, mult = MULT(ctx); + KeySym keysym; + XawTextBlock text; +#ifndef OLDXAW + Bool format = False; +#endif + XawTextPosition from, to; + + if (XtIsSubclass (ctx->text.source, (WidgetClass) multiSrcObjectClass)) + text.length = _XawImWcLookupString(w, &event->xkey, (wchar_t*)strbuf, + sizeof(strbuf), &keysym); + else + text.length = _XawLookupString(w, (XKeyEvent*)event, strbuf, + sizeof(strbuf), &keysym); + + if (text.length == 0) + return; - 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); + if (mult < 0) { + ctx->text.mult = 1; + return; + } - XtFree(text.ptr); - _XawTextSetScrollBars(ctx); - EndAction(ctx); -} + text.format = _XawTextFormat(ctx); + if (text.format == XawFmtWide) { + text.ptr = ptr = XawStackAlloc(sizeof(wchar_t) * text.length + * mult, ptrbuf); + for (count = 0; count < mult; count++) { + memcpy((char*)ptr, (char *)strbuf, sizeof(wchar_t) * text.length); + ptr += sizeof(wchar_t) * text.length; + } +#ifndef OLDXAW + if (mult == 1) + format = ctx->text.left_column < ctx->text.right_column; +#endif + } + else { /* == XawFmt8Bit */ + text.ptr = ptr = XawStackAlloc(text.length * mult, ptrbuf); + for (count = 0; count < mult; count++) { + strncpy(ptr, strbuf, text.length); + ptr += text.length; + } +#ifndef OLDXAW + if (mult == 1) + format = ctx->text.left_column < ctx->text.right_column; +#endif + } + text.length = text.length * mult; + text.firstPos = 0; + + StartAction(ctx, event); +#ifndef OLDXAW + if (mult == 1) + _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True); +#endif + + from = ctx->text.insertPos; +#ifndef OLDXAW + if (ctx->text.overwrite) { + XawTextPosition tmp; + + to = from + mult; + tmp = SrcScan(ctx->text.source, from, XawstEOL, XawsdRight, 1, False); + if (to > tmp) + to = tmp; + } + else +#endif + to = from; + + error = _XawTextReplace(ctx, from , to, &text); + + if (error == XawEditDone) { + ctx->text.from_left = -1; + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert, + XawstPositions, XawsdRight, + text.length, True); + if (ctx->text.auto_fill) { +#ifndef OLDXAW + if (format) + (void)FormatText(ctx, SrcScan(ctx->text.source, + ctx->text.insertPos, XawstEOL, + XawsdLeft, 1, False), False, + NULL, 0); + else +#endif + AutoFill(ctx); + } + } + else + XBell(XtDisplay(ctx), 50); + + XawStackFree(text.ptr, ptrbuf); + EndAction(ctx); + + if (error == XawEditDone && text.format == XawFmt8Bit && text.length == 1 + && (text.ptr[0] == ')' || text.ptr[0] == ']' || text.ptr[0] == '}') + && ctx->text.display_caret) { + static struct timeval tmval = {0, 500000}; + fd_set fds; + Widget source = ctx->text.source; + XawTextPosition insertPos = ctx->text.insertPos, pos, tmp, last; + char left, right = text.ptr[0]; + int level = 0; + XtAppContext app_context = XtWidgetToApplicationContext(w); + + left = right == ')' ? '(' : right == ']' ? '[' : '{'; + + last = insertPos - 1; + do { + text.ptr[0] = left; + pos = XawTextSourceSearch(source, last, XawsdLeft, &text); + if (pos == XawTextSearchError || !IsPositionVisible(ctx, pos)) + return; + text.ptr[0] = right; + tmp = pos; + do { + tmp = XawTextSourceSearch(source, tmp, XawsdRight, &text); + if (tmp == XawTextSearchError) + return; + if (tmp <= last) + ++level; + } while (++tmp <= last); + --level; + last = pos; + } while (level); + + StartAction(ctx, NULL); +#ifndef OLDXAW + _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True); +#endif + ctx->text.insertPos = pos; + EndAction(ctx); + + XSync(XtDisplay(w), False); + while (XtAppPending(app_context) & XtIMXEvent) { + XEvent ev; + if (! XtAppPeekEvent(app_context, &ev)) + break; + if (ev.type == KeyPress || ev.type == ButtonPress) + break; + XtAppProcessEvent(app_context, XtIMXEvent); + } + FD_ZERO(&fds); + FD_SET(ConnectionNumber(XtDisplay(w)), &fds); + (void)select(FD_SETSIZE, &fds, NULL, NULL, &tmval); + if (tmval.tv_usec != 500000) + usleep(40000); + + StartAction(ctx, NULL); +#ifndef OLDXAW + _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True); +#endif + ctx->text.insertPos = insertPos; + EndAction(ctx); + } +} /* IfHexConvertHexElseReturnParam() - called by InsertString * @@ -1590,78 +3227,70 @@ Cardinal* n; * * WHEN: the passed param is a legal hex string * RETURNS: a pointer to that converted, null terminated hex string; - * len_return holds the character count of conversion result + * len_return holds the character count of conversion result * * WHEN: the passed param is not a legal hex string: * RETURNS: the parameter passed; - * len_return holds the char count of param. + * len_return holds the char count of param. * * NOTE: In neither case will there be strings to free. */ - -static char* -IfHexConvertHexElseReturnParam(param, len_return) - char* param; - int* len_return; +static char * +IfHexConvertHexElseReturnParam(char *param, int *len_return) { - char *p; /* steps through param char by char */ - char c; /* holds the character pointed to by p */ - - int ind; /* steps through hexval buffer char by char */ - static char hexval[ XawTextActionMaxHexChars ]; - Boolean first_digit; - - /* reject if it doesn't begin with 0x and at least one more character. */ - - if ( ( param[0] != '0' ) || ( param[1] != 'x' ) || ( param[2] == '\0' ) ) { - *len_return = strlen( param ); - return( param ); - } - - /* Skip the 0x; go character by character shifting and adding. */ - - first_digit = True; - ind = 0; - hexval[ ind ] = '\0'; - - for ( p = param+2; ( c = *p ); p++ ) { - hexval[ ind ] *= 16; - if (c >= '0' && c <= '9') - hexval[ ind ] += c - '0'; - else if (c >= 'a' && c <= 'f') - hexval[ ind ] += c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - hexval[ ind ] += c - 'A' + 10; - else break; - - /* If we didn't break in preceding line, it was a good hex char. */ - - if ( first_digit ) - first_digit = False; - else { - first_digit = True; - if ( ++ind < XawTextActionMaxHexChars ) - hexval[ ind ] = '\0'; - else { - *len_return = strlen( param ); - return( param ); - } - } - } + char *p; /* steps through param char by char */ + char c; /* holds the character pointed to by p */ + int ind; /* steps through hexval buffer char by char */ + static char hexval[XawTextActionMaxHexChars]; + Boolean first_digit; + + /* reject if it doesn't begin with 0x and at least one more character. */ + if ((param[0] != '0') || (param[1] != 'x') || (param[2] == '\0')) { + *len_return = strlen(param); + return(param); + } - /* We quit the above loop becasue we hit a non hex. If that char is \0... */ + /* Skip the 0x; go character by character shifting and adding. */ + first_digit = True; + ind = 0; + hexval[ind] = '\0'; + + for (p = param+2; (c = *p) != '\0'; p++) { + hexval[ind] *= 16; + if (c >= '0' && c <= '9') + hexval[ind] += c - '0'; + else if (c >= 'a' && c <= 'f') + hexval[ind] += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + hexval[ind] += c - 'A' + 10; + else + break; + + /* If we didn't break in preceding line, it was a good hex char. */ + if (first_digit) + first_digit = False; + else { + first_digit = True; + if (++ind < XawTextActionMaxHexChars) + hexval[ind] = '\0'; + else { + *len_return = strlen(param); + return(param); + } + } + } - if ( ( c == '\0' ) && first_digit ) { - *len_return = strlen( hexval ); - return( hexval ); /* ...it was a legal hex string, so return it.*/ - } + /* We quit the above loop becasue we hit a non hex. If that char is \0... */ + if ((c == '\0') && first_digit) { + *len_return = strlen(hexval); + return (hexval); /* ...it was a legal hex string, so return it */ + } - /* Else, there were non-hex chars or odd digit count, so... */ + /* Else, there were non-hex chars or odd digit count, so... */ - *len_return = strlen( param ); - return( param ); /* ...return the verbatim string. */ + *len_return = strlen(param); + return (param); /* ...return the verbatim string. */ } - /* InsertString() - action * * Mostly rewritten for R6 i18n. @@ -1671,589 +3300,1122 @@ IfHexConvertHexElseReturnParam(param, len_return) * * The exception is that parameters composed of the two * characters 0x, followed only by an even number of - * hexadecimal digits will be converted to characters. */ - + * hexadecimal digits will be converted to characters */ /*ARGSUSED*/ -static void -InsertString(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; -Cardinal* num_params; +static void +InsertString(Widget w, XEvent *event, String *params, Cardinal *num_params) { - TextWidget ctx = (TextWidget) w; - XtAppContext app_con = XtWidgetToApplicationContext(w); - XawTextBlock text; - int i; - - text.firstPos = 0; - text.format = _XawTextFormat( ctx ); - - StartAction(ctx, event); - for ( i = *num_params; i; i--, params++ ) { /* DO FOR EACH PARAMETER */ - - text.ptr = IfHexConvertHexElseReturnParam( *params, &text.length ); - - if ( text.length == 0 ) continue; - - if ( _XawTextFormat( ctx ) == XawFmtWide ) { /* convert to WC */ - - int temp_len; - text.ptr = (char*) _XawTextMBToWC( XtDisplay(w), text.ptr, - &text.length ); - - if ( text.ptr == NULL ) { /* conversion error */ - XtAppWarningMsg( app_con, - "insertString", "textAction", "XawError", - "insert-string()'s parameter contents not legal in this locale.", - NULL, NULL ); - ParameterError( w, *params ); - continue; - } - - /* Double check that the new input is legal: try to convert to MB. */ - - temp_len = text.length; /* _XawTextWCToMB's 3rd arg is in_out */ - if ( _XawTextWCToMB( XtDisplay(w), (wchar_t*)text.ptr, &temp_len ) == NULL ) { - XtAppWarningMsg( app_con, - "insertString", "textAction", "XawError", - "insert-string()'s parameter contents not legal in this locale.", - NULL, NULL ); - ParameterError( w, *params ); - continue; - } - } /* convert to WC */ + TextWidget ctx = (TextWidget)w; + XtAppContext app_con = XtWidgetToApplicationContext(w); + XawTextBlock text; + int i; + + text.firstPos = 0; + text.format = _XawTextFormat(ctx); + + StartAction(ctx, event); + for (i = *num_params; i; i--, params++) { /* DO FOR EACH PARAMETER */ + text.ptr = IfHexConvertHexElseReturnParam(*params, &text.length); + + if (text.length == 0) + continue; + + if (XawTextFormat(ctx, XawFmtWide)) { /* convert to WC */ + int temp_len; + + text.ptr = (char*)_XawTextMBToWC(XtDisplay(w), text.ptr, + &text.length); + + if (text.ptr == NULL) { /* conversion error */ + XtAppWarningMsg(app_con, + "insertString", "textAction", "XawError", + "insert-string()'s parameter contents " + "not legal in this locale.", + NULL, NULL); + ParameterError(w, *params); + continue; + } + + /* Double check that the new input is legal: try to convert to MB. */ + + temp_len = text.length; /* _XawTextWCToMB's 3rd arg is in_out */ + if (_XawTextWCToMB(XtDisplay(w), (wchar_t*)text.ptr, &temp_len) + == NULL) { + XtAppWarningMsg( app_con, + "insertString", "textAction", "XawError", + "insert-string()'s parameter contents " + "not legal in this locale.", + NULL, NULL); + ParameterError(w, *params); + continue; + } + } /* convert to WC */ - if ( _XawTextReplace( ctx, ctx->text.insertPos, - ctx->text.insertPos, &text ) ) { - XBell( XtDisplay( ctx ), 50 ); - EndAction( ctx ); - return; - } + if (_XawTextReplace(ctx, ctx->text.insertPos, + ctx->text.insertPos, &text)) { + XBell(XtDisplay(ctx), 50); + EndAction(ctx); + return; + } - /* Advance insertPos to the end of the string we just inserted. */ - ctx->text.insertPos = SrcScan( ctx->text.source, ctx->text.insertPos, - XawstPositions, XawsdRight, text.length, TRUE ); + ctx->text.from_left = -1; + /* Advance insertPos to the end of the string we just inserted. */ + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.old_insert, + XawstPositions, XawsdRight, text.length, + True); - } /* DO FOR EACH PARAMETER */ + } /* DO FOR EACH PARAMETER */ - EndAction( ctx ); + EndAction(ctx); } - /* DisplayCaret() - action - * + * * The parameter list should contain one boolean value. If the * argument is true, the cursor will be displayed. If false, not. * * The exception is that EnterNotify and LeaveNotify events may * have a second argument, "always". If they do not, the cursor * is only affected if the focus member of the event is true. */ +static void +DisplayCaret(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + Bool display_caret = True; + + if ((event->type == EnterNotify || event->type == LeaveNotify) + && ((*num_params >= 2) && (strcmp(params[1], "always") == 0)) + && (!event->xcrossing.focus)) + return; -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 */ + 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); +} + +#ifndef OLDXAW +static void +Numeric(Widget w, XEvent *event, String *params, Cardinal *num_params) { - TextWidget ctx = (TextWidget)w; - Boolean display_caret = True; + TextWidget ctx = (TextWidget)w; - if ( ( event->type == EnterNotify || event->type == LeaveNotify ) && - ( ( *num_params >= 2 ) && ( strcmp( params[1], "always" ) == 0 ) ) && - ( !event->xcrossing.focus ) ) - return; + if (ctx->text.numeric) { + long mult = ctx->text.mult; - 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 (*num_params != 1 || strlen(params[0]) != 1 + || (!isdigit(params[0][0]) + && (params[0][0] != '-' || mult != 0))) { + char err_buf[256]; - 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); + if (event && (event->type == KeyPress || event->type == KeyRelease) + && params[0][0] == '-') { + InsertChar(w, event, params, num_params); + return; + } + XmuSnprintf(err_buf, sizeof(err_buf), + "numeric: Invalid argument%s'%s'", + *num_params ? ", " : "", *num_params ? params[0] : ""); + XtAppWarning(XtWidgetToApplicationContext(w), err_buf); + ctx->text.numeric = False; + ctx->text.mult = 1; + return; + } + if (params[0][0] == '-') { + ctx->text.mult = 32767; + return; + } + else if (mult == 32767) { + mult = ctx->text.mult = - (params[0][0] - '0'); + return; + } + else { + mult = mult * 10 + (params[0][0] - '0') * (mult < 0 ? -1 : 1); + ctx->text.mult = ctx->text.mult * 10 + (params[0][0] - '0') * + (mult < 0 ? -1 : 1); + } + if (mult != ctx->text.mult || mult >= 32767) { /* checks for overflow */ + XBell(XtDisplay(w), 0); + ctx->text.mult = 1; + ctx->text.numeric = False; + return; + } + } + else + InsertChar(w, event, params, num_params); } +/*ARGSUSED*/ +static void +KeyboardReset(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + + ctx->text.numeric = False; + ctx->text.mult = 1; + + (void)_XawTextSrcToggleUndo((TextSrcObject)ctx->text.source); + + if (ctx->text.kill_ring_ptr) { + --ctx->text.kill_ring_ptr->refcount; + ctx->text.kill_ring_ptr = NULL; + } + ctx->text.kill_ring = 0; + + XBell(XtDisplay(w), 0); +} +#endif /* OLDXAW */ /* Multiply() - action - * + * * 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; +/*ARGSUSED*/ +static void +Multiply(Widget w, XEvent *event, String *params, Cardinal *num_params) { - TextWidget ctx = (TextWidget) w; - int mult; + TextWidget ctx = (TextWidget)w; + int mult; - if (*num_params != 1) { - XtAppError( XtWidgetToApplicationContext( w ), - "Xaw Text Widget: multiply() takes exactly one argument."); - XBell( XtDisplay( w ), 0 ); - return; - } + if (*num_params != 1) { + XtAppError(XtWidgetToApplicationContext(w), + "Xaw Text Widget: multiply() 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 ((params[0][0] == 'r') || (params[0][0] == 'R')) { + XBell(XtDisplay(w), 0); +#ifndef OLDXAW + ctx->text.numeric = False; +#endif + ctx->text.mult = 1; + return; + } - if ( ( mult = atoi( params[0] ) ) == 0 ) { - char buf[ BUFSIZ ]; - sprintf(buf, "%s %s", "Xaw Text Widget: multiply() argument", - "must be a number greater than zero, or 'Reset'." ); - XtAppError( XtWidgetToApplicationContext( w ), buf ); - XBell( XtDisplay( w ), 50 ); - return; - } +#ifndef OLDXAW + if (params[0][0] == 's' || params[0][0] == 'S') { + ctx->text.numeric = True; + ctx->text.mult = 0; + return; + } + else +#endif + if ((mult = atoi(params[0])) == 0) { + char buf[BUFSIZ]; + + XmuSnprintf(buf, sizeof(buf), + "%s %s", "Xaw Text Widget: multiply() argument", + "must be a number greater than zero, or 'Reset'."); + XtAppError(XtWidgetToApplicationContext(w), buf); + XBell(XtDisplay(w), 50); + return; + } - ctx->text.mult *= mult; + ctx->text.mult *= mult; } - /* StripOutOldCRs() - called from FormRegion * * removes CRs in widget ctx, from from to to. * * RETURNS: the new ending location (we may add some characters), * or XawReplaceError if the widget can't be written to. */ - static XawTextPosition -StripOutOldCRs(ctx, from, to) -TextWidget ctx; -XawTextPosition from, to; +StripOutOldCRs(TextWidget ctx, XawTextPosition from, XawTextPosition to, + XawTextPosition *pos, int num_pos) { - XawTextPosition startPos, endPos, eop_begin, eop_end, temp; - Widget src = ctx->text.source; - XawTextBlock text; - char *buf; - static wchar_t wc_two_spaces[ 3 ]; - - /* Initialize our TextBlock with two spaces. */ - - text.firstPos = 0; - text.format = _XawTextFormat(ctx); - if ( text.format == XawFmt8Bit ) + XawTextPosition startPos, endPos, eop_begin, eop_end, temp; + Widget src = ctx->text.source; + XawTextBlock text; + char *buf; + static wchar_t wc_two_spaces[3]; + int idx; + + /* Initialize our TextBlock with two spaces. */ + text.firstPos = 0; + text.format = _XawTextFormat(ctx); + if (text.format == XawFmt8Bit) text.ptr= " "; - else { - wc_two_spaces[0] = _Xaw_atowc(XawSP); - wc_two_spaces[1] = _Xaw_atowc(XawSP); - wc_two_spaces[2] = 0; - text.ptr = (char*) wc_two_spaces; - } - - /* Strip out CR's. */ - - eop_begin = eop_end = startPos = endPos = from; - /* CONSTCOND */ - 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 (text.format == XawFmtWide) { - if ( (periodPos < endPos) && (((wchar_t*)buf)[0] == _Xaw_atowc('.'))) - text.length++; - } else - if ( (periodPos < endPos) && (buf[0] == '.') ) - text.length++; /* Put in two spaces. */ - - /* - * Remove all extra spaces. - */ - - for (i = 1 ; i < len; i++) - if (text.format == XawFmtWide) { - if ( !iswspace(((wchar_t*)buf)[i]) || ((periodPos + i) >= to) ) { - break; - } - } else - if ( !isspace(buf[i]) || ((periodPos + i) >= to) ) { - break; - } + wc_two_spaces[0] = _Xaw_atowc(XawSP); + wc_two_spaces[1] = _Xaw_atowc(XawSP); + wc_two_spaces[2] = 0; + text.ptr = (char*)wc_two_spaces; + } + + /* Strip out CR's. */ + eop_begin = eop_end = startPos = endPos = from; + + /* CONSTCOND */ + 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 (text.format == XawFmtWide) { + if (periodPos < endPos && ((wchar_t*)buf)[0] == _Xaw_atowc('.')) + text.length++; + } + else + if (periodPos < endPos && buf[0] == '.') + text.length++; /* Put in two spaces. */ + + /* + * Remove all extra spaces. + */ + for (i = 1 ; i < len; i++) + if (text.format == XawFmtWide) { + if (!iswspace(((wchar_t*)buf)[i]) || ((periodPos + i) >= to)) + break; + } + else if (!isspace(buf[i]) || (periodPos + i) >= to) + break; - XtFree(buf); + XtFree(buf); + + to -= (i - text.length - 1); + startPos = SrcScan(src, periodPos, XawstPositions, + XawsdRight, i, True); + if (_XawTextReplace(ctx, endPos, startPos, &text) != XawEditDone) + return (XawReplaceError); + + for (idx = 0; idx < num_pos; idx++) { + if (endPos < pos[idx]) { + if (startPos < pos[idx]) + pos[idx] -= startPos - endPos; + else + pos[idx] = endPos; + pos[idx] += text.length; + } + } - to -= (i - text.length - 1); - startPos = SrcScan(src, periodPos, XawstPositions, XawsdRight, i, TRUE); - if (_XawTextReplace(ctx, endPos, startPos, &text) != XawEditDone) - return XawReplaceError; - startPos -= i - text.length; + startPos -= i - text.length; + } } - } - return(to); -} + return (to); +} /* InsertNewCRs() - called from FormRegion * * inserts new CRs for FormRegion, thus for FormParagraph action */ - 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; - static wchar_t wide_CR[ 2 ]; - - text.firstPos = 0; - text.length = 1; - text.format = _XawTextFormat( ctx ); - - if ( text.format == XawFmt8Bit ) - text.ptr = "\n"; - else { - wide_CR[0] = _Xaw_atowc(XawLF); - wide_CR[1] = 0; - text.ptr = (char*) wide_CR; - } - - startPos = from; - /* CONSTCOND */ - 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 (text.format == XawFmtWide) { - if (!iswspace(((wchar_t*)buf)[i])) - break; - } else - if (!isspace(buf[i])) - break; - - to -= (i - 1); - endPos = SrcScan(ctx->text.source, endPos, - XawstPositions, XawsdRight, i, TRUE); - XtFree(buf); - - if (_XawTextReplace(ctx, startPos, endPos, &text)) - return; - - startPos = SrcScan(ctx->text.source, startPos, - XawstPositions, XawsdRight, 1, TRUE); - } -} +InsertNewCRs(TextWidget ctx, XawTextPosition from, XawTextPosition to, + XawTextPosition *pos, int num_pos) +{ + XawTextPosition startPos, endPos, space, eol; + XawTextBlock text; + int i, width, height, len, wwidth, idx; + char *buf; + static wchar_t wide_CR[2]; + + text.firstPos = 0; + text.length = 1; + text.format = _XawTextFormat(ctx); + + if (text.format == XawFmt8Bit) + text.ptr = "\n"; + else { + wide_CR[0] = _Xaw_atowc(XawLF); + wide_CR[1] = 0; + text.ptr = (char*)wide_CR; + } + + startPos = from; + wwidth = (int)XtWidth(ctx) - (int)HMargins(ctx); + if (ctx->text.wrap != XawtextWrapNever) { + XRectangle cursor; + + XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); + wwidth -= (int)cursor.width; + } + wwidth = XawMax(0, wwidth); + + /* CONSTCOND */ + while (TRUE) { + XawTextSinkFindPosition(ctx->text.sink, startPos, + (int)ctx->text.r_margin.left, wwidth, + True, &eol, &width, &height); + if (eol == startPos) + ++eol; + 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 (text.format == XawFmtWide) { + if (!iswspace(((wchar_t*)buf)[i])) + break; + } + else if (!isspace(buf[i])) + break; + + to -= (i - 1); + endPos = SrcScan(ctx->text.source, endPos, + XawstPositions, XawsdRight, i, True); + XtFree(buf); + + if (_XawTextReplace(ctx, startPos, endPos, &text)) + return; + + for (idx = 0; idx < num_pos; idx++) { + if (startPos < pos[idx]) { + if (endPos < pos[idx]) + pos[idx] -= endPos - startPos; + else + pos[idx] = startPos; + pos[idx] += text.length; + } + } + + startPos = SrcScan(ctx->text.source, startPos, + XawstPositions, XawsdRight, 1, True); + } +} /* FormRegion() - called by FormParagraph - * + * * oversees the work of paragraph-forming a region * - * RETURNS: XawEditDone if successful, or XawReplaceError. */ - + * Return: + * XawEditDone if successful, or XawReplaceError + */ static int -FormRegion(ctx, from, to) -TextWidget ctx; -XawTextPosition from, to; +FormRegion(TextWidget ctx, XawTextPosition from, XawTextPosition to, + XawTextPosition *pos, int num_pos) { - if ( from >= to ) return XawEditDone; +#ifndef OLDXAW + Bool format = ctx->text.auto_fill + && ctx->text.left_column < ctx->text.right_column; +#endif + + if (from >= to) + return (XawEditDone); + +#ifndef OLDXAW + if (format) { + XawTextPosition len = ctx->text.lastPos; + int inc = 0; + + if (ctx->text.justify == XawjustifyLeft || + ctx->text.justify == XawjustifyFull) { + Untabify(ctx, from, to, pos, num_pos, NULL); + to += ctx->text.lastPos - len; + len = ctx->text.insertPos; + (void)BlankLine((Widget)ctx, from, &inc); + if (from + inc >= to) + return (XawEditDone); + } + if (!StripSpaces(ctx, from + inc, to, pos, num_pos, NULL)) + return (XawReplaceError); + to += ctx->text.lastPos - len; - if ( ( to = StripOutOldCRs( ctx, from, to ) ) == XawReplaceError ) - return XawReplaceError; + FormatText(ctx, from, ctx->text.justify != XawjustifyFull, pos, num_pos); + } + else { +#endif + if ((to = StripOutOldCRs(ctx, from, to, pos, num_pos)) == XawReplaceError) + return (XawReplaceError); + InsertNewCRs(ctx, from, to, pos, num_pos); +#ifndef OLDXAW + } +#endif + ctx->text.from_left = -1; + + return (XawEditDone); +} - /* insure that the insertion point is within legal bounds */ - if ( ctx->text.insertPos > SrcScan( ctx->text.source, 0, - XawstAll, XawsdRight, 1, TRUE ) ) - ctx->text.insertPos = to; +#ifndef OLDXAW +static Bool +BlankLine(Widget w, XawTextPosition pos, int *blanks_return) +{ + int i, blanks = 0; + XawTextBlock block; + Widget src = XawTextGetSource(w); + XawTextPosition l = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False); + XawTextPosition r = SrcScan(src, pos, XawstEOL, XawsdRight, 1, False); + + while (l < r) { + l = XawTextSourceRead(src, l, &block, r - l); + if (block.length == 0) { + if (blanks_return) + *blanks_return = blanks; + return (True); + } + if (XawTextFormat((TextWidget)w, XawFmt8Bit)) { + for (i = 0; i < block.length; i++, blanks++) + if (block.ptr[i] != ' ' && + block.ptr[i] != '\t') { + if (blanks_return) + *blanks_return = blanks; + return (block.ptr[i] == '\n'); + } + } + else if (XawTextFormat((TextWidget)w, XawFmtWide)) { + for (i = 0; i < block.length; i++, blanks++) + if (_Xaw_atowc(XawSP) != ((wchar_t*)block.ptr)[i] && + _Xaw_atowc(XawTAB) != ((wchar_t*)block.ptr)[i]) { + if (blanks_return) + *blanks_return = blanks; + return (_Xaw_atowc(XawLF) == ((wchar_t*)block.ptr)[i]); + } + } + } - InsertNewCRs(ctx, from, to); - _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE); - return XawEditDone; + return (True); } +static Bool +GetBlockBoundaries(TextWidget ctx, + XawTextPosition *from_return, XawTextPosition *to_return) +{ + XawTextPosition from, to; + + if (ctx->text.auto_fill && ctx->text.left_column < ctx->text.right_column) { + if (ctx->text.s.left != ctx->text.s.right) { + from = SrcScan(ctx->text.source, + XawMin(ctx->text.s.left, ctx->text.s.right), + XawstEOL, XawsdLeft, 1, False); + to = SrcScan(ctx->text.source, + XawMax(ctx->text.s.right, ctx->text.s.right), + XawstEOL, XawsdRight, 1, False); + } + else { + XawTextBlock block; + XawTextPosition tmp; + Bool first; + + from = to = ctx->text.insertPos; + + /* find from position */ + first = True; + while (1) { + tmp = from; + from = SrcScan(ctx->text.source, from, XawstEOL, XawsdLeft, + 1 + !first, False); + XawTextSourceRead(ctx->text.source, from, &block, 1); + if (block.length == 0 || + (XawTextFormat(ctx, XawFmt8Bit) && + block.ptr[0] != ' ' && + block.ptr[0] != '\t' && + !isalnum(*(unsigned char*)block.ptr)) || + (XawTextFormat(ctx, XawFmtWide) && + _Xaw_atowc(XawSP) != *(wchar_t*)block.ptr && + _Xaw_atowc(XawTAB) != *(wchar_t*)block.ptr && + !iswalnum(*(wchar_t*)block.ptr)) || + BlankLine((Widget)ctx, from, NULL)) { + from = tmp; + break; + } + if (from == tmp && !first) + break; + first = False; + } + if (first) + return (False); + + /* find to position */ + first = True; + while (1) { + tmp = to; + to = SrcScan(ctx->text.source, to, XawstEOL, XawsdRight, + 1 + !first, False); + XawTextSourceRead(ctx->text.source, to + (to < ctx->text.lastPos), + &block, 1); + if (block.length == 0 || + (XawTextFormat(ctx, XawFmt8Bit) && + block.ptr[0] != ' ' && + block.ptr[0] != '\t' && + !isalnum(*(unsigned char*)block.ptr)) || + (XawTextFormat(ctx, XawFmtWide) && + _Xaw_atowc(XawSP) != *(wchar_t*)block.ptr && + _Xaw_atowc(XawTAB) != *(wchar_t*)block.ptr && + !iswalnum(*(wchar_t*)block.ptr)) || + BlankLine((Widget)ctx, to, NULL)) + break; + if (to == tmp && !first) + break; + first = False; + } + } + } + else { + from = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, + XawsdLeft, 1, False); + if (BlankLine((Widget)ctx, from, NULL)) + return (False); + from = SrcScan(ctx->text.source, from, XawstParagraph, + XawsdLeft, 1, False); + if (BlankLine((Widget)ctx, from, NULL)) + from = SrcScan(ctx->text.source, from, XawstEOL, + XawsdRight, 1, True); + to = SrcScan(ctx->text.source, from, XawstParagraph, + XawsdRight, 1, False); + } + + if (from < to) { + *from_return = from; + *to_return = to; + return (True); + } + + return (False); +} +#endif /* OLDXAW */ /* FormParagraph() - action * * removes and reinserts CRs to maximize line length without clipping */ - -/* ARGSUSED */ -static void -FormParagraph(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; -Cardinal* num_params; +/*ARGSUSED*/ +static void +FormParagraph(Widget w, XEvent *event, String *params, Cardinal *num_params) { - TextWidget ctx = (TextWidget) w; - XawTextPosition from, to; + TextWidget ctx = (TextWidget)w; + XawTextPosition from, to, buf[32], *pos; +#ifndef OLDXAW + XawTextPosition endPos = 0; + char *lbuf = NULL, *rbuf; + TextSrcObject src = (TextSrcObject)ctx->text.source; + Cardinal i; + Bool undo = src->textSrc.enable_undo && src->textSrc.undo_state == False; +#endif + + StartAction(ctx, event); + +#ifndef OLDXAW + pos = XawStackAlloc(sizeof(XawTextPosition) * src->textSrc.num_text, buf); + for (i = 0; i < src->textSrc.num_text; i++) + pos[i] = ((TextWidget)src->textSrc.text[i])->text.old_insert; +#else + pos = buf; + *pos = ctx->text.old_insert; +#endif + +#ifndef OLDXAW + if (!GetBlockBoundaries(ctx, &from, &to)) { + EndAction(ctx); + XawStackFree(pos, buf); + return; + } - StartAction(ctx, event); + if (undo) { + src->textSrc.undo_state = True; + lbuf = _XawTextGetText(ctx, from, to); + endPos = ctx->text.lastPos; + } - from = SrcScan( ctx->text.source, ctx->text.insertPos, - XawstParagraph, XawsdLeft, 1, FALSE ); - to = SrcScan( ctx->text.source, from, - XawstParagraph, XawsdRight, 1, FALSE ); + if (FormRegion(ctx, from, to, pos, src->textSrc.num_text) == XawReplaceError) { +#else + from = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstParagraph, XawsdLeft, 1, False); + to = SrcScan(ctx->text.source, from, + XawstParagraph, XawsdRight, 1, False); - if ( FormRegion( ctx, from, to ) == XawReplaceError ) - XBell( XtDisplay( w ), 0 ); - _XawTextSetScrollBars( ctx ); - EndAction( ctx ); -} + if (FormRegion(ctx, from, to, pos, 1) == XawReplaceError) { +#endif + XawStackFree(pos, buf); + XBell(XtDisplay(w), 0); +#ifndef OLDXAW + if (undo) { + src->textSrc.undo_state = False; + XtFree(lbuf); + } +#endif + } +#ifndef OLDXAW + else if (undo) { + /* makes the form-paragraph only one undo/redo step */ + unsigned llen, rlen, size; + XawTextBlock block; + + llen = to - from; + rlen = llen + (ctx->text.lastPos - endPos); + + block.firstPos = 0; + block.format = _XawTextFormat(ctx); + + rbuf = _XawTextGetText(ctx, from, from + rlen); + + size = XawTextFormat(ctx, XawFmtWide) ? sizeof(wchar_t) : sizeof(char); + if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) { + block.ptr = lbuf; + block.length = llen; + _XawTextReplace(ctx, from, from + rlen, &block); + + src->textSrc.undo_state = False; + block.ptr = rbuf; + block.length = rlen; + _XawTextReplace(ctx, from, from + llen, &block); + } + else + src->textSrc.undo_state = False; + XtFree(lbuf); + XtFree(rbuf); + } + + for (i = 0; i < src->textSrc.num_text; i++) { + TextWidget tw = (TextWidget)src->textSrc.text[i]; + tw->text.old_insert = tw->text.insertPos = pos[i]; + _XawTextBuildLineTable(tw, SrcScan((Widget)src, tw->text.lt.top, XawstEOL, + XawsdLeft, 1, False), False); + tw->text.clear_to_eol = True; + } +#else + ctx->text.old_insert = ctx->text.insertPos = *pos; + _XawTextBuildLineTable(ctx, SrcScan(ctx->text.source, ctx->text.lt.top, + XawstEOL, XawsdLeft, 1, False), False); + ctx->text.clear_to_eol = True; +#endif + XawStackFree(pos, buf); + ctx->text.showposition = True; + + EndAction(ctx); +} /* TransposeCharacters() - action * * Swaps the character to the left of the mark - * with the character to the right of the mark. */ - -/* 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; - char* buf; - 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 ); - - /* Make sure we aren't at the very beginning or end of the buffer. */ - - if ( ( start == ctx->text.insertPos ) || ( end == ctx->text.insertPos ) ) { - XBell( XtDisplay( w ), 0 ); /* complain. */ - EndAction( ctx ); - return; - } - - ctx->text.insertPos = end; - - text.firstPos = 0; - text.format = _XawTextFormat(ctx); - - /* Retrieve text and swap the characters. */ - - if ( text.format == XawFmtWide) { - wchar_t wc; - wchar_t* wbuf; - - wbuf = (wchar_t*) _XawTextGetText(ctx, start, end); - text.length = wcslen( wbuf ); - wc = wbuf[ 0 ]; - for ( i = 1; i < text.length; i++ ) - wbuf[ i-1 ] = wbuf[ i ]; - wbuf[ i-1 ] = wc; - buf = (char*) wbuf; /* so that it gets assigned and freed */ - - } else { /* thus text.format == XawFmt8Bit */ - char c; - buf = _XawTextGetText( ctx, start, end ); - text.length = strlen( buf ); - c = buf[ 0 ]; - for ( i = 1; i < text.length; i++ ) - buf[ i-1 ] = buf[ i ]; - buf[ i-1 ] = c; - } - - text.ptr = buf; - - /* Store new text in source. */ - - if (_XawTextReplace (ctx, start, end, &text)) /* Unable to edit, complain. */ - XBell(XtDisplay(w), 0); - XtFree((char *) buf); - EndAction(ctx); + * with the character to the right of the mark */ +/*ARGSUSED*/ +static void +TransposeCharacters(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition start, end; + XawTextBlock text; + char *buf; + int i, mult = MULT(ctx); + + if (mult < 0) { + ctx->text.mult = 1; + return; + } + + 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, mult, True); + + /* Make sure we aren't at the very beginning or end of the buffer. */ + + if (start == ctx->text.insertPos || end == ctx->text.insertPos) { + XBell(XtDisplay(w), 0); /* complain. */ + EndAction(ctx); + return; + } + + ctx->text.from_left = -1; + ctx->text.insertPos = end; + + text.firstPos = 0; + text.format = _XawTextFormat(ctx); + + /* Retrieve text and swap the characters. */ + if (text.format == XawFmtWide) { + wchar_t wc; + wchar_t *wbuf; + + wbuf = (wchar_t*)_XawTextGetText(ctx, start, end); + text.length = wcslen(wbuf); + wc = wbuf[0]; + for (i = 1; i < text.length; i++) + wbuf[i - 1] = wbuf[i]; + wbuf[i - 1] = wc; + buf = (char*)wbuf; /* so that it gets assigned and freed */ + } + else { /* thus text.format == XawFmt8Bit */ + char c; + + buf = _XawTextGetText(ctx, start, end); + text.length = strlen(buf); + c = buf[0]; + for (i = 1; i < text.length; i++) + buf[i - 1] = buf[i]; + buf[i - 1] = c; + } + + text.ptr = buf; + + /* Store new text in source. */ + + if (_XawTextReplace (ctx, start, end, &text)) + XBell(XtDisplay(w), 0); + XtFree((char *)buf); + EndAction(ctx); } +#ifndef OLDXAW +/*ARGSUSED*/ +static void +Undo(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + TextWidget ctx = (TextWidget)w; + int mul = MULT(ctx); + Bool toggle = False; + + if (mul < 0) { + toggle = True; + _XawTextSrcToggleUndo((TextSrcObject)ctx->text.source); + ctx->text.mult = mul = -mul; + } + + StartAction(ctx, event); + for (; mul; --mul) + if (!_XawTextSrcUndo((TextSrcObject)ctx->text.source, &ctx->text.insertPos)) + break; + ctx->text.showposition = True; + + if (toggle) + _XawTextSrcToggleUndo((TextSrcObject)ctx->text.source); + EndAction(ctx); +} +#endif /* NoOp() - action * This action performs no action, and allows the user or * application programmer to unbind a translation. * * Note: If the parameter list contains the string "RingBell" then - * this action will ring the bell. + * this action will ring the bell. */ - /*ARGSUSED*/ static void -NoOp(w, event, params, num_params) -Widget w; -XEvent* event; -String* params; -Cardinal* num_params; +NoOp(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; + case 'R': + case 'r': + XBell(XtDisplay(w), 0); + /*FALLTROUGH*/ + default: + break; } } - + /* Reconnect() - action * This reconnects to the input method. The user will typically call * this action if/when connection has been severed, or when the app - * was started up before an IM was started up. + * was started up before an IM was started up */ +/*ARGSUSED*/ +static void +Reconnect(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + _XawImReconnect(w); +} + +#define CAPITALIZE 1 +#define DOWNCASE 2 +#define UPCASE 3 + +#ifdef NO_LIBC_I18N +static int +ToLower(int ch) +{ + char buf[2]; + + *buf = ch; + XmuNCopyISOLatin1Lowered(buf, buf, sizeof(buf)); + + return (*buf); +} + +static int +ToUpper(int ch) +{ + char buf[2]; + + *buf = ch; + XmuNCopyISOLatin1Uppered(buf, buf, sizeof(buf)); + + return (*buf); +} + +static int +IsAlnum(int ch) +{ + return ((ch >= '0' && ch <= '9') || ToUpper(ch) != ch || ToLower(ch) != ch); +} + +static int +IsLower(int ch) +{ + char upbuf[2]; + char lobuf[2]; + + *upbuf = *lobuf = ch; + XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf)); + XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf)); + + return (*lobuf != *upbuf && ch == *lobuf); +} + +static int +IsUpper(int ch) +{ + char upbuf[2]; + char lobuf[2]; + + *upbuf = *lobuf = ch; + XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf)); + XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf)); + + return (*lobuf != *upbuf && ch == *upbuf); +} +#else +#define ToLower tolower +#define ToUpper toupper +#define IsAlnum isalnum +#define IsLower islower +#define IsUpper isupper +#endif + +static void +CaseProc(Widget w, XEvent *event, int cmd) +{ + TextWidget ctx = (TextWidget)w; + short mul = MULT(ctx); + XawTextPosition left, right; + XawTextBlock block; + Bool changed = False; + unsigned char ch, mb[sizeof(wchar_t)]; + int i, count; + + if (mul > 0) + right = SrcScan(ctx->text.source, left = ctx->text.insertPos, + XawstAlphaNumeric, XawsdRight, mul, False); + else + left = SrcScan(ctx->text.source, right = ctx->text.insertPos, + XawstAlphaNumeric, XawsdLeft, 1 + -mul, False); + block.firstPos = 0; + block.format = _XawTextFormat(ctx); + block.length = right - left; + block.ptr = _XawTextGetText(ctx, left, right); + + count = 0; + if (block.format == XawFmt8Bit) + for (i = 0; i < block.length; i++) { + if (!IsAlnum(*mb = (unsigned char)block.ptr[i])) + count = 0; + else if (++count == 1 || cmd != CAPITALIZE) { + ch = cmd == DOWNCASE ? ToLower(*mb) : ToUpper(*mb); + if (ch != *mb) { + changed = True; + block.ptr[i] = ch; + } + } + else if (cmd == CAPITALIZE) { + if ((ch = ToLower(*mb)) != *mb) { + changed = True; + block.ptr[i] = ch; + } + } + } + else + for (i = 0; i < block.length; i++) { + wctomb((char*)mb, ((wchar_t*)block.ptr)[i]); + if (!IsAlnum(*mb)) + count = 0; + else if (++count == 1 || cmd != CAPITALIZE) { + ch = cmd == DOWNCASE ? ToLower(*mb) : ToUpper(*mb); + if (ch != *mb) { + changed = True; + ((wchar_t*)block.ptr)[i] = _Xaw_atowc(ch); + } + } + else if (cmd == CAPITALIZE) { + if ((ch = ToLower(*mb)) != *mb) { + changed = True; + ((wchar_t*)block.ptr)[i] = _Xaw_atowc(ch); + } + } + } + + StartAction(ctx, event); + if (changed && _XawTextReplace(ctx, left, right, &block) != XawEditDone) + XBell(XtDisplay(ctx), 0); + ctx->text.insertPos = right; + EndAction(ctx); + + XtFree(block.ptr); +} /*ARGSUSED*/ static void -Reconnect( w, event, params, num_params ) - Widget w; - XEvent* event; - String* params; - Cardinal* num_params; +CapitalizeWord(Widget w, XEvent *event, String *params, Cardinal *num_params) { - _XawImReconnect( w ); + CaseProc(w, event, CAPITALIZE); } - -XtActionsRec _XawTextActionsTable[] = { +/*ARGSUSED*/ +static void +DowncaseWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CaseProc(w, event, DOWNCASE); +} -/* motion bindings */ - - {"forward-character", MoveForwardChar}, - {"backward-character", MoveBackwardChar}, - {"forward-word", MoveForwardWord}, - {"backward-word", MoveBackwardWord}, - {"forward-paragraph", MoveForwardParagraph}, - {"backward-paragraph", MoveBackwardParagraph}, - {"beginning-of-line", MoveToLineStart}, - {"end-of-line", MoveToLineEnd}, - {"next-line", MoveNextLine}, - {"previous-line", MovePreviousLine}, - {"next-page", MoveNextPage}, - {"previous-page", MovePreviousPage}, - {"beginning-of-file", MoveBeginningOfFile}, - {"end-of-file", MoveEndOfFile}, - {"scroll-one-line-up", ScrollOneLineUp}, - {"scroll-one-line-down", ScrollOneLineDown}, - -/* delete bindings */ - - {"delete-next-character", DeleteForwardChar}, - {"delete-previous-character", DeleteBackwardChar}, - {"delete-next-word", DeleteForwardWord}, - {"delete-previous-word", DeleteBackwardWord}, - {"delete-selection", DeleteCurrentSelection}, - -/* kill bindings */ - - {"kill-word", KillForwardWord}, - {"backward-kill-word", KillBackwardWord}, - {"kill-selection", KillCurrentSelection}, - {"kill-to-end-of-line", KillToEndOfLine}, - {"kill-to-end-of-paragraph", KillToEndOfParagraph}, - -/* new line stuff */ - - {"newline-and-indent", InsertNewLineAndIndent}, - {"newline-and-backup", InsertNewLineAndBackup}, - {"newline", InsertNewLine}, - -/* Selection stuff */ - - {"select-word", SelectWord}, - {"select-all", SelectAll}, - {"select-start", SelectStart}, - {"select-adjust", SelectAdjust}, - {"select-end", SelectEnd}, +/*ARGSUSED*/ +static void +UpcaseWord(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + CaseProc(w, event, UPCASE); +} +#undef CAPITALIZE +#undef DOWNCASE +#undef UPCASE + +XtActionsRec _XawTextActionsTable[] = { + /* motion */ + {"forward-character", MoveForwardChar}, + {"backward-character", MoveBackwardChar}, + {"forward-word", MoveForwardWord}, + {"backward-word", MoveBackwardWord}, + {"forward-paragraph", MoveForwardParagraph}, + {"backward-paragraph", MoveBackwardParagraph}, + {"beginning-of-line", MoveToLineStart}, + {"end-of-line", MoveToLineEnd}, + {"next-line", MoveNextLine}, + {"previous-line", MovePreviousLine}, + {"next-page", MoveNextPage}, + {"previous-page", MovePreviousPage}, + {"beginning-of-file", MoveBeginningOfFile}, + {"end-of-file", MoveEndOfFile}, + {"scroll-one-line-up", ScrollOneLineUp}, + {"scroll-one-line-down", ScrollOneLineDown}, + + /* delete */ + {"delete-next-character", DeleteForwardChar}, + {"delete-previous-character", DeleteBackwardChar}, + {"delete-next-word", DeleteForwardWord}, + {"delete-previous-word", DeleteBackwardWord}, + {"delete-selection", DeleteCurrentSelection}, + {"delete", Delete}, + + /* kill */ + {"kill-word", KillForwardWord}, + {"backward-kill-word", KillBackwardWord}, + {"kill-selection", KillCurrentSelection}, + {"kill-to-end-of-line", KillToEndOfLine}, + {"kill-to-end-of-paragraph", KillToEndOfParagraph}, + + /* new line */ + {"newline-and-indent", InsertNewLineAndIndent}, + {"newline-and-backup", InsertNewLineAndBackup}, + {"newline", InsertNewLine}, + + /* selection */ + {"select-word", SelectWord}, + {"select-all", SelectAll}, + {"select-start", SelectStart}, + {"select-adjust", SelectAdjust}, + {"select-end", SelectEnd}, {"select-save", SelectSave}, - {"extend-start", ExtendStart}, - {"extend-adjust", ExtendAdjust}, + {"extend-start", ExtendStart}, + {"extend-adjust", ExtendAdjust}, {"extend-end", ExtendEnd}, {"insert-selection", InsertSelection}, -/* Miscellaneous */ - - {"redraw-display", RedrawDisplay}, - {"insert-file", _XawTextInsertFile}, - {"search", _XawTextSearch}, - {"insert-char", InsertChar}, + /* miscellaneous */ + {"redraw-display", RedrawDisplay}, + {"insert-file", _XawTextInsertFile}, + {"search", _XawTextSearch}, + {"insert-char", InsertChar}, {"insert-string", InsertString}, - {"focus-in", TextFocusIn}, - {"focus-out", TextFocusOut}, - {"enter-window", TextEnterWindow}, - {"leave-window", TextLeaveWindow}, + {"focus-in", TextFocusIn}, + {"focus-out", TextFocusOut}, + {"enter-window", TextEnterWindow}, + {"leave-window", TextLeaveWindow}, {"display-caret", DisplayCaret}, - {"multiply", Multiply}, - {"form-paragraph", FormParagraph}, - {"transpose-characters", TransposeCharacters}, - {"no-op", NoOp}, - -/* Action to bind special translations for text Dialogs. */ - - {"InsertFileAction", _XawTextInsertFileAction}, - {"DoSearchAction", _XawTextDoSearchAction}, - {"DoReplaceAction", _XawTextDoReplaceAction}, - {"SetField", _XawTextSetField}, - {"PopdownSearchAction", _XawTextPopdownSearchAction}, - -/* Reconnect to Input Method */ - {"reconnect-im", Reconnect} /* Li Yuhong, Omron KK, 1991 */ + {"multiply", Multiply}, + {"form-paragraph", FormParagraph}, + {"transpose-characters", TransposeCharacters}, + {"set-keyboard-focus", SetKeyboardFocus}, +#ifndef OLDXAW + {"numeric", Numeric}, + {"undo", Undo}, + {"keyboard-reset", KeyboardReset}, + {"kill-ring-yank", KillRingYank}, + {"toggle-overwrite", ToggleOverwrite}, + {"indent", Indent}, +#endif + {"no-op", NoOp}, + + /* case transformations */ + {"capitalize-word", CapitalizeWord}, + {"downcase-word", DowncaseWord}, + {"upcase-word", UpcaseWord}, + + /* action to bind translations for text dialogs */ + {"InsertFileAction", _XawTextInsertFileAction}, + {"DoSearchAction", _XawTextDoSearchAction}, + {"DoReplaceAction", _XawTextDoReplaceAction}, + {"SetField", _XawTextSetField}, + {"PopdownSearchAction", _XawTextPopdownSearchAction}, + + /* reconnect to Input Method */ + {"reconnect-im", Reconnect} /* Li Yuhong, Omron KK, 1991 */ }; Cardinal _XawTextActionsTableCount = XtNumber(_XawTextActionsTable); |