4429 lines
113 KiB
C
4429 lines
113 KiB
C
/* $Xorg: TextAction.c,v 1.4 2001/02/09 02:03:46 xorgcvs Exp $ */
|
|
|
|
/*
|
|
|
|
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.
|
|
|
|
*/
|
|
/* $XFree86: xc/lib/Xaw/TextAction.c,v 3.46tsi Exp $ */
|
|
|
|
#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;
|
|
} else {
|
|
XTextProperty textprop;
|
|
char **list;
|
|
int count;
|
|
|
|
textprop.encoding = *type;
|
|
textprop.value = (unsigned char *)value;
|
|
textprop.nitems = strlen(value);
|
|
textprop.format = 8;
|
|
|
|
if (XmbTextPropertyToTextList(d, &textprop, &list, &count)
|
|
!= Success
|
|
|| count < 1) {
|
|
XFreeStringList(list);
|
|
|
|
/* Notify the user on strerr and in the insertion :) */
|
|
fprintf(stderr, "Xaw Text Widget: An attempt was made to insert "
|
|
"an illegal selection.\n");
|
|
|
|
textprop.value = (unsigned char *)" >> ILLEGAL SELECTION << ";
|
|
textprop.nitems = strlen((char *) textprop.value);
|
|
if (XmbTextPropertyToTextList(d, &textprop, &list, &count)
|
|
!= Success
|
|
|| count < 1)
|
|
return;
|
|
}
|
|
|
|
XFree(value);
|
|
value = (XPointer)list[0];
|
|
|
|
*length = strlen(list[0]);
|
|
XtFree((XtPointer)list);
|
|
text.format = XawFmt8Bit;
|
|
}
|
|
text.ptr = (char*)value;
|
|
text.firstPos = 0;
|
|
text.length = *length;
|
|
if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
|
|
XBell(XtDisplay(ctx), 0);
|
|
EndAction(ctx);
|
|
return;
|
|
}
|
|
|
|
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)
|
|
{
|
|
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, XA_UTF8_STRING(XtDisplay(w)),
|
|
_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, <emp, &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) && *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 = █
|
|
}
|
|
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);
|