aboutsummaryrefslogtreecommitdiff
path: root/libXaw/src/TextAction.c
diff options
context:
space:
mode:
Diffstat (limited to 'libXaw/src/TextAction.c')
-rw-r--r--libXaw/src/TextAction.c8800
1 files changed, 4402 insertions, 4398 deletions
diff --git a/libXaw/src/TextAction.c b/libXaw/src/TextAction.c
index 47c6ce62b..2e55f662e 100644
--- a/libXaw/src/TextAction.c
+++ b/libXaw/src/TextAction.c
@@ -1,4398 +1,4402 @@
-/*
-
-Copyright 1989, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#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/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>
-#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 "Private.h"
-#include "XawI18n.h"
-
-#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
-
-/*
- * 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);
-
-/*
- * External
- */
-void _XawTextZapSelection(TextWidget, XEvent*, Bool);
-
-/*
- * 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 */
-
-/*
- * 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
-
-/*
- * 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);
-}
-
-static void
-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)
-{
- 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(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;
- int asked; /* which selection currently has been asked for:
- 0 = UTF8_STRING, 1 = COMPOUND_TEXT, 2 = STRING */
- Atom selection; /* selection atom (normally XA_PRIMARY) */
-};
-
-/*ARGSUSED*/
-static void
-_SelectionReceived(Widget w, XtPointer client_data, Atom *selection,
- Atom *type, XtPointer value, unsigned long *length,
- int *format)
-{
- 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;
- }
-
- 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;
- }
- 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;
- }
-
- 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(Widget w, Time timev, String *params, Cardinal num_params)
-{
- Display *d = XtDisplay(w);
- TextWidget ctx = (TextWidget)w;
- 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;
- }
- if (buffer >= 0) {
- int nbytes;
- unsigned long length;
- int fmt8 = 8;
- Atom type = XA_STRING;
- char *line = XFetchBuffer(XtDisplay(w), &nbytes, buffer);
-
- if ((length = nbytes) != 0L)
- _SelectionReceived(w, NULL, &selection, &type, line, &length, &fmt8);
- else if (num_params > 1)
- 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 = timev;
- list->asked = 0;
- list->selection = selection;
- }
- else
- list = NULL;
- XtGetSelectionValue(w, selection, XawTextFormat(ctx, XawFmtWide) ?
- XA_UTF8_STRING(d) : XA_TEXT(d),
- _SelectionReceived, (XtPointer)list, timev);
- }
-}
-
-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);
-}
-
-/*
- * Routines for Moving Around
- */
-static void
-Move(TextWidget ctx, XEvent *event, XawTextScanDirection dir,
- XawTextScanType type, Bool include)
-{
- 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(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdRight, XawstPositions, True);
-}
-
-/*ARGSUSED*/
-static void
-MoveBackwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdLeft, XawstPositions, True);
-}
-
-static void
-MoveForwardWord(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- 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);
-}
-
-static void
-MoveBackwardWord(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- 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);
-}
-
-static void
-MoveForwardParagraph(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- 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(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- 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(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdRight, XawstEOL, False);
-}
-
-/*ARGSUSED*/
-static void
-MoveToLineStart(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdLeft, XawstEOL, False);
-}
-
-static void
-MoveLine(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
-{
- XawTextPosition cnew, next_line, ltemp;
- int itemp, from_left;
- short mult = MULT(ctx);
-
- StartAction(ctx, event);
-
- XawTextUnsetSelection((Widget)ctx);
-
- if (dir == XawsdLeft)
- mult = mult == 0 ? 5 : mult + 1;
-
- cnew = SrcScan(ctx->text.source, ctx->text.insertPos,
- XawstEOL, XawsdLeft, 1, False);
-
- if (ctx->text.from_left < 0)
- FindDist(ctx->text.sink, cnew, ctx->text.left_margin, ctx->text.insertPos,
- &ctx->text.from_left, &ltemp, &itemp);
-
- cnew = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir,
- mult, (dir == XawsdRight));
-
- 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;
- }
- }
-
- if (ctx->text.insertPos > next_line)
- ctx->text.insertPos = next_line;
-
- EndAction(ctx);
-}
-
-static void
-MoveNextLine(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- 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;
-}
-
-static void
-MovePreviousLine(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- 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(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdLeft, XawstAll, True);
-}
-
-/*ARGSUSED*/
-static void
-MoveEndOfFile(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Move((TextWidget)w, event, XawsdRight, XawstAll, True);
-}
-
-static void
-Scroll(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
-{
- 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, mult);
- else
- _XawTextVScroll(ctx, -mult);
-
- EndAction(ctx);
- }
- else {
- ctx->text.mult = 1;
-#ifndef OLDXAW
- ctx->text.numeric = False;
-#endif
- }
-}
-
-/*ARGSUSED*/
-static void
-ScrollOneLineUp(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Scroll((TextWidget)w, event, XawsdLeft);
-}
-
-/*ARGSUSED*/
-static void
-ScrollOneLineDown(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- Scroll((TextWidget)w, event, XawsdRight);
-}
-
-static void
-MovePage(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
-{
- 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 (scroll_val)
- XawTextScroll(ctx, scroll_val,
- ctx->text.left_margin - ctx->text.r_margin.left);
-
- 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;
- }
-}
-
-static void
-MoveNextPage(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- 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(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- ctx->text.mult = -mult;
- MoveNextPage(w, event, p, n);
- return;
- }
-
- 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;
-
- for (count = 0, match = s->selections; count < s->atom_count;
- match++, count++)
- if (*match == selection)
- return (True);
-
- return (False);
-}
-
-#define SrcCvtSel XawTextSourceConvertSelection
-
-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))
- *type = XA_COMPOUND_TEXT(d);
- else
- *type = XA_STRING;
- }
- else
- *type = *target;
-
- /*
- * If salt is True, the salt->contents stores CT string,
- * its length is measured in bytes.
- * Refer to _XawTextSaltAwaySelection()
- *
- * by Li Yuhong, Mar. 20, 1991.
- */
- if (!salt) {
- *value = (char *)_XawTextGetSTRING(ctx, s->left, s->right);
- if (XawTextFormat(ctx, XawFmtWide)) {
- XTextProperty textprop;
- if (XwcTextListToTextProperty(d, (wchar_t**)value, 1,
- XCompoundTextStyle, &textprop)
- < Success) {
- XtFree(*value);
- return (False);
- }
- XtFree(*value);
- *value = (XtPointer)textprop.value;
- *length = textprop.nitems;
- }
- else
- *length = strlen(*value);
- }
- else {
- *value = XtMalloc((salt->length + 1) * sizeof(unsigned char));
- strcpy (*value, salt->contents);
- *length = salt->length;
- }
- /* Got *value,*length, now in COMPOUND_TEXT format. */
- if (XawTextFormat(ctx, XawFmtWide)) {
- if (*type == XA_STRING) {
- XTextProperty textprop;
- 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, &wlist, &count)
- < Success
- || count < 1) {
- XtFree(*value);
- return (False);
- }
- XtFree(*value);
- 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);
- }
- 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)) {
- 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);
-
- return (False);
-}
-
-static void
-LoseSelection(Widget w, Atom *selection)
-{
- _LoseSelection(w, selection, NULL, NULL);
-}
-
-static void
-_LoseSelection(Widget w, Atom *selection, char **contents, int *length)
-{
- 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;
- nextSalt = salt->next;
- 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)
- 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) {
-#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->s.selections);
- XtFree((char *)salt);
- }
- else
- prevSalt = salt;
- }
-}
-
-static void
-_DeleteOrKill(TextWidget ctx, XawTextPosition from, XawTextPosition to,
- Bool kill)
-{
- XawTextBlock text;
-
-#ifndef OLDXAW
- if (ctx->text.kill_ring_ptr) {
- --ctx->text.kill_ring_ptr->refcount;
- ctx->text.kill_ring_ptr = NULL;
- }
-#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;
- }
- else
- ctx->text.kill_ring = KILL_RING_BEGIN;
-
- if (append)
- _LoseSelection((Widget)ctx, &selection, &ring, &size);
- else
-#endif
- LoseSelection((Widget)ctx, &selection);
-
- salt = (XawTextSelectionSalt*)XtMalloc(sizeof(XawTextSelectionSalt));
- salt->s.selections = (Atom *)XtMalloc(sizeof(Atom));
- salt->s.left = from;
- salt->s.right = to;
-
- 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(TextWidget ctx, XEvent *event, XawTextScanDirection dir,
- XawTextScanType type, Bool include, Bool kill)
-{
- XawTextPosition from, to;
- short mult = MULT(ctx);
-
- if (mult < 0) {
- mult = -mult;
- dir = dir == XawsdLeft ? XawsdRight : XawsdLeft;
- }
-
- 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;
-
- _DeleteOrKill(ctx, from, to, kill);
- 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);
-}
-
-static void
-DeleteChar(Widget w, XEvent *event, XawTextScanDirection dir)
-{
- 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
-DeleteForwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- DeleteChar(w, event, XawsdRight);
-}
-
-/*ARGSUSED*/
-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)
-{
- 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
-KillToEndOfLine(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- 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
-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)
-{
- StartAction(ctx, event);
- _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill);
- EndAction(ctx);
-}
-
-/*ARGSUSED*/
-static void
-KillCurrentSelection(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- _XawTextZapSelection((TextWidget) w, event, True);
-}
-
-#ifndef OLDXAW
-/*ARGSUSED*/
-static void
-KillRingYank(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
- XawTextPosition insertPos = ctx->text.insertPos;
- Bool first_yank = False;
-
- if (ctx->text.s.left != ctx->text.s.right)
- XawTextUnsetSelection((Widget)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
-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)
-{
- 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);
-}
-
-static Bool
-Untabify(TextWidget ctx, XawTextPosition left, XawTextPosition right,
- XawTextPosition *pos, int num_pos, XawTextBlock *save)
-{
- 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 = &block;
- }
- 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
-Indent(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- 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
-ToggleOverwrite(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
- ctx->text.overwrite = !ctx->text.overwrite;
-
- /* call information callback */
- _XawTextSetLineAndColumnNumber(ctx, True);
-}
-#endif /* OLDXAW */
-
-/*
- * Insertion Routines
- */
-static int
-InsertNewLineAndBackupInternal(TextWidget ctx)
-{
- int count, error = XawEditDone, mult = MULT(ctx);
-#ifndef OLDXAW
- XawTextPosition position;
-#endif
- 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;
- }
-
-#ifndef OLDXAW
- position = SrcScan(ctx->text.source, ctx->text.insertPos,
- XawstEOL, XawsdLeft, 1, False);
-#endif
- 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
-
- return (error);
-}
-
-/*ARGSUSED*/
-static void
-InsertNewLineAndBackup(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- 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(TextWidget ctx, XEvent *event)
-{
- int error;
-
- StartAction(ctx, event);
- error = InsertNewLineAndBackupInternal(ctx);
- ctx->text.from_left = -1;
- EndAction(ctx);
-
- return (error);
-}
-
-/*ARGSUSED*/
-static void
-InsertNewLine(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- (void)LocalInsertNewLine((TextWidget)w, event);
-}
-
-/*ARGSUSED*/
-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);
-}
-
-/*
- * 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);
-}
-
-static void
-SelectAll(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
- StartAction(ctx, event);
- _XawTextSetSelection(ctx,zeroPosition,ctx->text.lastPos,params,*num_params);
- EndAction(ctx);
-}
-
-static void
-ModifySelection(TextWidget ctx, XEvent *event,
- XawTextSelectionMode mode,
- XawTextSelectionAction action,
- String *params, Cardinal *num_params)
-{
-#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);
-}
-
-static void
-SelectStart(Widget w, XEvent *event, String *params, Cardinal *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
-}
-
-static void
-SelectAdjust(Widget w, XEvent *event, String *params, Cardinal *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(Widget w, XEvent *event, String *params, Cardinal *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
-}
-
-static void
-ExtendStart(Widget w, XEvent *event, String *params, Cardinal *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
-}
-
-static void
-ExtendAdjust(Widget w, XEvent *event, String *params, Cardinal *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(Widget w, XEvent *event, String *params, Cardinal *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(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- int num_atoms;
- Atom *sel;
- Display *dpy = XtDisplay(w);
- Atom selections[256];
-
- 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);
-}
-
-/*
- * 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);
-}
-
-/* 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)
-{
- struct _focus *f = (struct _focus*)(user_data);
-
- if (f->widget == w)
- f->widget = NULL;
-}
-
-/*ARGSUSED*/
-static void
-TextFocusIn(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- TextWidget ctx = (TextWidget)w;
- Bool display_caret = ctx->text.display_caret;
- int i;
-
- if (event->xfocus.detail == NotifyPointer)
- return;
-
- if (event->xfocus.send_event) {
- Window root, child;
- int rootx, rooty, x, y;
- unsigned int mask;
-
- 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(Widget w, XEvent *event, String *p, Cardinal *n)
-{
- 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);
-
- if (display_caret)
- StartAction(ctx, event);
- ctx->text.hasfocus = FALSE;
- if (display_caret)
- EndAction(ctx);
-}
-
-/*ARGSUSED*/
-static void
-TextEnterWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
- if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus
- && !ctx->text.hasfocus)
- _XawImSetFocusValues(w, NULL, 0);
-}
-
-/*ARGSUSED*/
-static void
-TextLeaveWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- TextWidget ctx = (TextWidget)w;
-
- if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus
- && !ctx->text.hasfocus)
- _XawImUnsetFocus(w);
-}
-
-/*
- * Function:
- * AutoFill
- * Arguments: ctx - The text widget.
- *
- * Description:
- * Breaks the line at the previous word boundry when
- * called inside InsertChar.
- */
-static void
-AutoFill(TextWidget ctx)
-{
- 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;
-
- XawTextSourceRead(ctx->text.source, ret_pos - 1, &text, 1);
-
- 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;
-
- 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;
-
- 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);
-
- if (++ctx->text.insertPos > ctx->text.lastPos)
- ctx->text.insertPos = ctx->text.lastPos;
-}
-
-/*ARGSUSED*/
-static void
-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 (mult < 0) {
- ctx->text.mult = 1;
- return;
- }
-
- 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
- *
- * i18n requires the ability to specify multiple characters in a hexa-
- * decimal string at once. Since Insert was already too long, I made
- * this a seperate routine.
- *
- * A legal hex string in MBNF: '0' 'x' ( HEX-DIGIT HEX-DIGIT )+ '\0'
- *
- * 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
- *
- * WHEN: the passed param is not a legal hex string:
- * RETURNS: the parameter passed;
- * len_return holds the char count of param.
- *
- * NOTE: In neither case will there be strings to free. */
-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) != '\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);
- }
- }
- }
-
- /* 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... */
-
- *len_return = strlen(param);
- return (param); /* ...return the verbatim string. */
-}
-
-/* InsertString() - action
- *
- * Mostly rewritten for R6 i18n.
- *
- * Each parameter, in turn, will be insert at the inputPos
- * and the inputPos advances to the insertion's end.
- *
- * 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 */
-/*ARGSUSED*/
-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 */
-
- if (_XawTextReplace(ctx, ctx->text.insertPos,
- ctx->text.insertPos, &text)) {
- XBell(XtDisplay(ctx), 50);
- EndAction(ctx);
- return;
- }
-
- 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 */
-
- 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;
-
- 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;
-
- if (ctx->text.numeric) {
- long mult = ctx->text.mult;
-
- if (*num_params != 1 || strlen(params[0]) != 1
- || (!isdigit(params[0][0])
- && (params[0][0] != '-' || mult != 0))) {
- char err_buf[256];
-
- 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(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- 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 ((params[0][0] == 'r') || (params[0][0] == 'R')) {
- XBell(XtDisplay(w), 0);
-#ifndef OLDXAW
- ctx->text.numeric = False;
-#endif
- ctx->text.mult = 1;
- 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;
-}
-
-/* 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(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];
- 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;
-
- 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;
- }
- }
-
- startPos -= i - text.length;
- }
- }
-
- return (to);
-}
-
-/* InsertNewCRs() - called from FormRegion
- *
- * inserts new CRs for FormRegion, thus for FormParagraph action */
-static void
-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
- *
- * Return:
- * XawEditDone if successful, or XawReplaceError
- */
-static int
-FormRegion(TextWidget ctx, XawTextPosition from, XawTextPosition to,
- XawTextPosition *pos, int num_pos)
-{
-#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;
-
- 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);
-}
-
-#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]);
- }
- }
- }
-
- 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(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- 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;
- }
-
- if (undo) {
- src->textSrc.undo_state = True;
- lbuf = _XawTextGetText(ctx, from, to);
- endPos = ctx->text.lastPos;
- }
-
- 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, 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(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.
- */
-/*ARGSUSED*/
-static void
-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);
- /*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
- */
-/*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
-CapitalizeWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CaseProc(w, event, CAPITALIZE);
-}
-
-/*ARGSUSED*/
-static void
-DowncaseWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
-{
- CaseProc(w, event, DOWNCASE);
-}
-
-/*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-end", ExtendEnd},
- {"insert-selection", InsertSelection},
-
- /* 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},
- {"display-caret", DisplayCaret},
- {"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);
+/*
+
+Copyright 1989, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#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/Xatom.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xutil.h>
+#include <X11/Xwinsock.h>
+#include <X11/Xmu/Atoms.h>
+#include <X11/Xmu/Misc.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 "Private.h"
+#include "XawI18n.h"
+
+#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
+
+#ifdef _MSC_VER
+#define usleep(time) Sleep(time)
+#endif
+/*
+ * 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
+
+/*
+ * 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);
+
+/*
+ * External
+ */
+void _XawTextZapSelection(TextWidget, XEvent*, Bool);
+
+/*
+ * 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 */
+
+/*
+ * 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
+
+/*
+ * 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);
+}
+
+static void
+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)
+{
+ 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(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;
+ int asked; /* which selection currently has been asked for:
+ 0 = UTF8_STRING, 1 = COMPOUND_TEXT, 2 = STRING */
+ Atom selection; /* selection atom (normally XA_PRIMARY) */
+};
+
+/*ARGSUSED*/
+static void
+_SelectionReceived(Widget w, XtPointer client_data, Atom *selection,
+ Atom *type, XtPointer value, unsigned long *length,
+ int *format)
+{
+ 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;
+ }
+
+ 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;
+ }
+ 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;
+ }
+
+ 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(Widget w, Time timev, String *params, Cardinal num_params)
+{
+ Display *d = XtDisplay(w);
+ TextWidget ctx = (TextWidget)w;
+ 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;
+ }
+ if (buffer >= 0) {
+ int nbytes;
+ unsigned long length;
+ int fmt8 = 8;
+ Atom type = XA_STRING;
+ char *line = XFetchBuffer(XtDisplay(w), &nbytes, buffer);
+
+ if ((length = nbytes) != 0L)
+ _SelectionReceived(w, NULL, &selection, &type, line, &length, &fmt8);
+ else if (num_params > 1)
+ 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 = timev;
+ list->asked = 0;
+ list->selection = selection;
+ }
+ else
+ list = NULL;
+ XtGetSelectionValue(w, selection, XawTextFormat(ctx, XawFmtWide) ?
+ XA_UTF8_STRING(d) : XA_TEXT(d),
+ _SelectionReceived, (XtPointer)list, timev);
+ }
+}
+
+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);
+}
+
+/*
+ * Routines for Moving Around
+ */
+static void
+Move(TextWidget ctx, XEvent *event, XawTextScanDirection dir,
+ XawTextScanType type, Bool include)
+{
+ 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(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ Move((TextWidget)w, event, XawsdRight, XawstPositions, True);
+}
+
+/*ARGSUSED*/
+static void
+MoveBackwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ Move((TextWidget)w, event, XawsdLeft, XawstPositions, True);
+}
+
+static void
+MoveForwardWord(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ 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);
+}
+
+static void
+MoveBackwardWord(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ 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);
+}
+
+static void
+MoveForwardParagraph(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ 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(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ 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(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ Move((TextWidget)w, event, XawsdRight, XawstEOL, False);
+}
+
+/*ARGSUSED*/
+static void
+MoveToLineStart(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ Move((TextWidget)w, event, XawsdLeft, XawstEOL, False);
+}
+
+static void
+MoveLine(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
+{
+ XawTextPosition cnew, next_line, ltemp;
+ int itemp, from_left;
+ short mult = MULT(ctx);
+
+ StartAction(ctx, event);
+
+ XawTextUnsetSelection((Widget)ctx);
+
+ if (dir == XawsdLeft)
+ mult = mult == 0 ? 5 : mult + 1;
+
+ cnew = SrcScan(ctx->text.source, ctx->text.insertPos,
+ XawstEOL, XawsdLeft, 1, False);
+
+ if (ctx->text.from_left < 0)
+ FindDist(ctx->text.sink, cnew, ctx->text.left_margin, ctx->text.insertPos,
+ &ctx->text.from_left, &ltemp, &itemp);
+
+ cnew = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir,
+ mult, (dir == XawsdRight));
+
+ 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;
+ }
+ }
+
+ if (ctx->text.insertPos > next_line)
+ ctx->text.insertPos = next_line;
+
+ EndAction(ctx);
+}
+
+static void
+MoveNextLine(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ 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;
+}
+
+static void
+MovePreviousLine(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ 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(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ Move((TextWidget)w, event, XawsdLeft, XawstAll, True);
+}
+
+/*ARGSUSED*/
+static void
+MoveEndOfFile(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ Move((TextWidget)w, event, XawsdRight, XawstAll, True);
+}
+
+static void
+Scroll(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
+{
+ 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, mult);
+ else
+ _XawTextVScroll(ctx, -mult);
+
+ EndAction(ctx);
+ }
+ else {
+ ctx->text.mult = 1;
+#ifndef OLDXAW
+ ctx->text.numeric = False;
+#endif
+ }
+}
+
+/*ARGSUSED*/
+static void
+ScrollOneLineUp(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ Scroll((TextWidget)w, event, XawsdLeft);
+}
+
+/*ARGSUSED*/
+static void
+ScrollOneLineDown(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ Scroll((TextWidget)w, event, XawsdRight);
+}
+
+static void
+MovePage(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
+{
+ 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 (scroll_val)
+ XawTextScroll(ctx, scroll_val,
+ ctx->text.left_margin - ctx->text.r_margin.left);
+
+ 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;
+ }
+}
+
+static void
+MoveNextPage(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ 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(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ TextWidget ctx = (TextWidget)w;
+ short mult = MULT(ctx);
+
+ if (mult < 0) {
+ ctx->text.mult = -mult;
+ MoveNextPage(w, event, p, n);
+ return;
+ }
+
+ 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;
+
+ for (count = 0, match = s->selections; count < s->atom_count;
+ match++, count++)
+ if (*match == selection)
+ return (True);
+
+ return (False);
+}
+
+#define SrcCvtSel XawTextSourceConvertSelection
+
+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))
+ *type = XA_COMPOUND_TEXT(d);
+ else
+ *type = XA_STRING;
+ }
+ else
+ *type = *target;
+
+ /*
+ * If salt is True, the salt->contents stores CT string,
+ * its length is measured in bytes.
+ * Refer to _XawTextSaltAwaySelection()
+ *
+ * by Li Yuhong, Mar. 20, 1991.
+ */
+ if (!salt) {
+ *value = (char *)_XawTextGetSTRING(ctx, s->left, s->right);
+ if (XawTextFormat(ctx, XawFmtWide)) {
+ XTextProperty textprop;
+ if (XwcTextListToTextProperty(d, (wchar_t**)value, 1,
+ XCompoundTextStyle, &textprop)
+ < Success) {
+ XtFree(*value);
+ return (False);
+ }
+ XtFree(*value);
+ *value = (XtPointer)textprop.value;
+ *length = textprop.nitems;
+ }
+ else
+ *length = strlen(*value);
+ }
+ else {
+ *value = XtMalloc((salt->length + 1) * sizeof(unsigned char));
+ strcpy (*value, salt->contents);
+ *length = salt->length;
+ }
+ /* Got *value,*length, now in COMPOUND_TEXT format. */
+ if (XawTextFormat(ctx, XawFmtWide)) {
+ if (*type == XA_STRING) {
+ XTextProperty textprop;
+ 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, &wlist, &count)
+ < Success
+ || count < 1) {
+ XtFree(*value);
+ return (False);
+ }
+ XtFree(*value);
+ 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);
+ }
+ 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)) {
+ 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);
+
+ return (False);
+}
+
+static void
+LoseSelection(Widget w, Atom *selection)
+{
+ _LoseSelection(w, selection, NULL, NULL);
+}
+
+static void
+_LoseSelection(Widget w, Atom *selection, char **contents, int *length)
+{
+ 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;
+ nextSalt = salt->next;
+ 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)
+ 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) {
+#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->s.selections);
+ XtFree((char *)salt);
+ }
+ else
+ prevSalt = salt;
+ }
+}
+
+static void
+_DeleteOrKill(TextWidget ctx, XawTextPosition from, XawTextPosition to,
+ Bool kill)
+{
+ XawTextBlock text;
+
+#ifndef OLDXAW
+ if (ctx->text.kill_ring_ptr) {
+ --ctx->text.kill_ring_ptr->refcount;
+ ctx->text.kill_ring_ptr = NULL;
+ }
+#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;
+ }
+ else
+ ctx->text.kill_ring = KILL_RING_BEGIN;
+
+ if (append)
+ _LoseSelection((Widget)ctx, &selection, &ring, &size);
+ else
+#endif
+ LoseSelection((Widget)ctx, &selection);
+
+ salt = (XawTextSelectionSalt*)XtMalloc(sizeof(XawTextSelectionSalt));
+ salt->s.selections = (Atom *)XtMalloc(sizeof(Atom));
+ salt->s.left = from;
+ salt->s.right = to;
+
+ 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(TextWidget ctx, XEvent *event, XawTextScanDirection dir,
+ XawTextScanType type, Bool include, Bool kill)
+{
+ XawTextPosition from, to;
+ short mult = MULT(ctx);
+
+ if (mult < 0) {
+ mult = -mult;
+ dir = dir == XawsdLeft ? XawsdRight : XawsdLeft;
+ }
+
+ 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;
+
+ _DeleteOrKill(ctx, from, to, kill);
+ 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);
+}
+
+static void
+DeleteChar(Widget w, XEvent *event, XawTextScanDirection dir)
+{
+ 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
+DeleteForwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ DeleteChar(w, event, XawsdRight);
+}
+
+/*ARGSUSED*/
+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)
+{
+ 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
+KillToEndOfLine(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ 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
+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)
+{
+ StartAction(ctx, event);
+ _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill);
+ EndAction(ctx);
+}
+
+/*ARGSUSED*/
+static void
+KillCurrentSelection(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ _XawTextZapSelection((TextWidget) w, event, True);
+}
+
+#ifndef OLDXAW
+/*ARGSUSED*/
+static void
+KillRingYank(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ TextWidget ctx = (TextWidget)w;
+ XawTextPosition insertPos = ctx->text.insertPos;
+ Bool first_yank = False;
+
+ if (ctx->text.s.left != ctx->text.s.right)
+ XawTextUnsetSelection((Widget)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
+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)
+{
+ 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);
+}
+
+static Bool
+Untabify(TextWidget ctx, XawTextPosition left, XawTextPosition right,
+ XawTextPosition *pos, int num_pos, XawTextBlock *save)
+{
+ 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 = &block;
+ }
+ 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
+Indent(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ 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
+ToggleOverwrite(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ ctx->text.overwrite = !ctx->text.overwrite;
+
+ /* call information callback */
+ _XawTextSetLineAndColumnNumber(ctx, True);
+}
+#endif /* OLDXAW */
+
+/*
+ * Insertion Routines
+ */
+static int
+InsertNewLineAndBackupInternal(TextWidget ctx)
+{
+ int count, error = XawEditDone, mult = MULT(ctx);
+#ifndef OLDXAW
+ XawTextPosition position;
+#endif
+ 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;
+ }
+
+#ifndef OLDXAW
+ position = SrcScan(ctx->text.source, ctx->text.insertPos,
+ XawstEOL, XawsdLeft, 1, False);
+#endif
+ 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
+
+ return (error);
+}
+
+/*ARGSUSED*/
+static void
+InsertNewLineAndBackup(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ 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(TextWidget ctx, XEvent *event)
+{
+ int error;
+
+ StartAction(ctx, event);
+ error = InsertNewLineAndBackupInternal(ctx);
+ ctx->text.from_left = -1;
+ EndAction(ctx);
+
+ return (error);
+}
+
+/*ARGSUSED*/
+static void
+InsertNewLine(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ (void)LocalInsertNewLine((TextWidget)w, event);
+}
+
+/*ARGSUSED*/
+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);
+}
+
+/*
+ * 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);
+}
+
+static void
+SelectAll(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ StartAction(ctx, event);
+ _XawTextSetSelection(ctx,zeroPosition,ctx->text.lastPos,params,*num_params);
+ EndAction(ctx);
+}
+
+static void
+ModifySelection(TextWidget ctx, XEvent *event,
+ XawTextSelectionMode mode,
+ XawTextSelectionAction action,
+ String *params, Cardinal *num_params)
+{
+#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);
+}
+
+static void
+SelectStart(Widget w, XEvent *event, String *params, Cardinal *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
+}
+
+static void
+SelectAdjust(Widget w, XEvent *event, String *params, Cardinal *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(Widget w, XEvent *event, String *params, Cardinal *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
+}
+
+static void
+ExtendStart(Widget w, XEvent *event, String *params, Cardinal *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
+}
+
+static void
+ExtendAdjust(Widget w, XEvent *event, String *params, Cardinal *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(Widget w, XEvent *event, String *params, Cardinal *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(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ int num_atoms;
+ Atom *sel;
+ Display *dpy = XtDisplay(w);
+ Atom selections[256];
+
+ 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);
+}
+
+/*
+ * 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);
+}
+
+/* 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)
+{
+ struct _focus *f = (struct _focus*)(user_data);
+
+ if (f->widget == w)
+ f->widget = NULL;
+}
+
+/*ARGSUSED*/
+static void
+TextFocusIn(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ TextWidget ctx = (TextWidget)w;
+ Bool display_caret = ctx->text.display_caret;
+ int i;
+
+ if (event->xfocus.detail == NotifyPointer)
+ return;
+
+ if (event->xfocus.send_event) {
+ Window root, child;
+ int rootx, rooty, x, y;
+ unsigned int mask;
+
+ 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(Widget w, XEvent *event, String *p, Cardinal *n)
+{
+ 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);
+
+ if (display_caret)
+ StartAction(ctx, event);
+ ctx->text.hasfocus = FALSE;
+ if (display_caret)
+ EndAction(ctx);
+}
+
+/*ARGSUSED*/
+static void
+TextEnterWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus
+ && !ctx->text.hasfocus)
+ _XawImSetFocusValues(w, NULL, 0);
+}
+
+/*ARGSUSED*/
+static void
+TextLeaveWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus
+ && !ctx->text.hasfocus)
+ _XawImUnsetFocus(w);
+}
+
+/*
+ * Function:
+ * AutoFill
+ * Arguments: ctx - The text widget.
+ *
+ * Description:
+ * Breaks the line at the previous word boundry when
+ * called inside InsertChar.
+ */
+static void
+AutoFill(TextWidget ctx)
+{
+ 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;
+
+ XawTextSourceRead(ctx->text.source, ret_pos - 1, &text, 1);
+
+ 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;
+
+ 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;
+
+ 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);
+
+ if (++ctx->text.insertPos > ctx->text.lastPos)
+ ctx->text.insertPos = ctx->text.lastPos;
+}
+
+/*ARGSUSED*/
+static void
+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 (mult < 0) {
+ ctx->text.mult = 1;
+ return;
+ }
+
+ 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
+ *
+ * i18n requires the ability to specify multiple characters in a hexa-
+ * decimal string at once. Since Insert was already too long, I made
+ * this a seperate routine.
+ *
+ * A legal hex string in MBNF: '0' 'x' ( HEX-DIGIT HEX-DIGIT )+ '\0'
+ *
+ * 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
+ *
+ * WHEN: the passed param is not a legal hex string:
+ * RETURNS: the parameter passed;
+ * len_return holds the char count of param.
+ *
+ * NOTE: In neither case will there be strings to free. */
+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) != '\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);
+ }
+ }
+ }
+
+ /* 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... */
+
+ *len_return = strlen(param);
+ return (param); /* ...return the verbatim string. */
+}
+
+/* InsertString() - action
+ *
+ * Mostly rewritten for R6 i18n.
+ *
+ * Each parameter, in turn, will be insert at the inputPos
+ * and the inputPos advances to the insertion's end.
+ *
+ * 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 */
+/*ARGSUSED*/
+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 */
+
+ if (_XawTextReplace(ctx, ctx->text.insertPos,
+ ctx->text.insertPos, &text)) {
+ XBell(XtDisplay(ctx), 50);
+ EndAction(ctx);
+ return;
+ }
+
+ 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 */
+
+ 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;
+
+ 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;
+
+ if (ctx->text.numeric) {
+ long mult = ctx->text.mult;
+
+ if (*num_params != 1 || strlen(params[0]) != 1
+ || (!isdigit(params[0][0])
+ && (params[0][0] != '-' || mult != 0))) {
+ char err_buf[256];
+
+ 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(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ 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 ((params[0][0] == 'r') || (params[0][0] == 'R')) {
+ XBell(XtDisplay(w), 0);
+#ifndef OLDXAW
+ ctx->text.numeric = False;
+#endif
+ ctx->text.mult = 1;
+ 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;
+}
+
+/* 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(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];
+ 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;
+
+ 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;
+ }
+ }
+
+ startPos -= i - text.length;
+ }
+ }
+
+ return (to);
+}
+
+/* InsertNewCRs() - called from FormRegion
+ *
+ * inserts new CRs for FormRegion, thus for FormParagraph action */
+static void
+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
+ *
+ * Return:
+ * XawEditDone if successful, or XawReplaceError
+ */
+static int
+FormRegion(TextWidget ctx, XawTextPosition from, XawTextPosition to,
+ XawTextPosition *pos, int num_pos)
+{
+#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;
+
+ 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);
+}
+
+#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]);
+ }
+ }
+ }
+
+ 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(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ 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;
+ }
+
+ if (undo) {
+ src->textSrc.undo_state = True;
+ lbuf = _XawTextGetText(ctx, from, to);
+ endPos = ctx->text.lastPos;
+ }
+
+ 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, 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(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.
+ */
+/*ARGSUSED*/
+static void
+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);
+ /*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
+ */
+/*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
+CapitalizeWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ CaseProc(w, event, CAPITALIZE);
+}
+
+/*ARGSUSED*/
+static void
+DowncaseWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ CaseProc(w, event, DOWNCASE);
+}
+
+/*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-end", ExtendEnd},
+ {"insert-selection", InsertSelection},
+
+ /* 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},
+ {"display-caret", DisplayCaret},
+ {"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);