diff options
Diffstat (limited to 'libXaw/src/Text.c')
-rw-r--r-- | libXaw/src/Text.c | 8320 |
1 files changed, 4158 insertions, 4162 deletions
diff --git a/libXaw/src/Text.c b/libXaw/src/Text.c index 2fd9d3fb6..b95231c56 100644 --- a/libXaw/src/Text.c +++ b/libXaw/src/Text.c @@ -1,4162 +1,4158 @@ -/* $Xorg: Text.c,v 1.4 2001/02/09 02:03:46 xorgcvs Exp $ */ - -/*********************************************************** - -Copyright 1987, 1988, 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. - - -Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -/* - * Copyright (c) 1998 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * 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 XFREE86 PROJECT 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 XFree86 Project 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 - * XFree86 Project. - */ - -/* $XFree86: xc/lib/Xaw/Text.c,v 3.53tsi Exp $ */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <stdio.h> -#include <X11/IntrinsicP.h> -#include <X11/StringDefs.h> -#include <X11/Shell.h> -#include <X11/Xatom.h> -#include <X11/Xfuncs.h> -#include <X11/Xutil.h> -#include <X11/Xmu/Misc.h> -#include <X11/Xmu/SysUtil.h> -#include <X11/Xmu/Xmu.h> -#include <X11/Xaw/Cardinals.h> -#include <X11/Xaw/MultiSinkP.h> -#include <X11/Xaw/TextP.h> -#include <X11/Xaw/TextSrcP.h> -#include <X11/Xaw/TextSinkP.h> -#include <X11/Xaw/Scrollbar.h> -#include <X11/Xaw/XawImP.h> -#include <X11/Xaw/XawInit.h> -#include "Private.h" -#include "XawI18n.h" - -#ifndef MAX_LEN_CT -#define MAX_LEN_CT 6 /* for sequence: ESC $ ( A \xx \xx */ -#endif - -unsigned long FMT8BIT = 0L; -unsigned long XawFmt8Bit = 0L; -unsigned long XawFmtWide = 0L; - -#define SinkClearToBG _XawTextSinkClearToBackground - -#define SrcScan XawTextSourceScan -#define SrcRead XawTextSourceRead -#define SrcReplace XawTextSourceReplace -#define SrcSearch XawTextSourceSearch -#define SrcCvtSel XawTextSourceConvertSelection -#define SrcSetSelection XawTextSourceSetSelection - -#define MULTI_CLICK_TIME 500L - -#define SRC_CHANGE_NONE 0 -#define SRC_CHANGE_AFTER 1 -#define SRC_CHANGE_BEFORE 2 -#define SRC_CHANGE_OVERLAP 3 - -#define Superclass (&simpleClassRec) - -/* - * Compute a the maximum length of a cut buffer that we can pass at any - * time. The 64 allows for the overhead of the Change Property request. - */ -#define MAX_CUT_LEN(dpy) (XMaxRequestSize(dpy) - 64) - -#define ClearWindow(ctx) \ - _XawTextNeedsUpdating((ctx), \ - (ctx)->text.lt.top, \ - (ctx)->text.lt.info[ctx->text.lt.lines].position) - -/* - * Class Methods - */ -static void XawTextClassInitialize(void); -static void XawTextInitialize(Widget, Widget, ArgList, Cardinal*); -static void XawTextRealize(Widget, XtValueMask*, XSetWindowAttributes*); -static void XawTextDestroy(Widget); -static void XawTextResize(Widget); -static void XawTextExpose(Widget, XEvent*, Region); -static Boolean XawTextSetValues(Widget, Widget, Widget, ArgList, Cardinal*); -static void XawTextGetValuesHook(Widget, ArgList, Cardinal*); -static Bool XawTextChangeSensitive(Widget); - -/* - * Prototypes - */ -static XawTextPosition _BuildLineTable(TextWidget, XawTextPosition, int); -static void _CreateCutBuffers(Display*); -static Boolean TextConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*, - unsigned long*, int*); -static int CountLines(TextWidget, XawTextPosition, XawTextPosition); -static void CreateHScrollBar(TextWidget); -static void CreateVScrollBar(TextWidget); -static void CvtStringToScrollMode(XrmValuePtr, Cardinal*, - XrmValuePtr, XrmValuePtr); -static Boolean CvtScrollModeToString(Display*, XrmValue*, Cardinal*, - XrmValue*, XrmValue*, XtPointer*); -static void CvtStringToWrapMode(XrmValuePtr, Cardinal*, - XrmValuePtr, XrmValuePtr); -static Boolean CvtWrapModeToString(Display*, XrmValue*, Cardinal*, - XrmValue*, XrmValue*, XtPointer*); -static Boolean CvtStringToJustifyMode(Display*, XrmValue*, Cardinal*, - XrmValue*, XrmValue*, XtPointer*); -static Boolean CvtJustifyModeToString(Display*, XrmValue*, Cardinal*, - XrmValue*, XrmValue*, XtPointer*); -static void DestroyHScrollBar(TextWidget); -static void DestroyVScrollBar(TextWidget); -#ifndef OLDXAW -static void DisplayText(Widget, XawTextPosition, XawTextPosition); -#endif -static void OldDisplayText(Widget, XawTextPosition, XawTextPosition); -static void DisplayTextWindow(Widget); -static void DoCopyArea(TextWidget, int, int, unsigned int, unsigned int, - int, int); -static void DoSelection(TextWidget, XawTextPosition, Time, Bool); -static void ExtendSelection(TextWidget, XawTextPosition, Bool); -static XawTextPosition FindGoodPosition(TextWidget, XawTextPosition); -static void FlushUpdate(TextWidget); -static int GetCutBufferNumber(Atom); -static int GetMaxTextWidth(TextWidget); -static unsigned int GetWidestLine(TextWidget); -static void HScroll(Widget, XtPointer, XtPointer); -static void HJump(Widget, XtPointer, XtPointer); -static void InsertCursor(Widget, XawTextInsertState); -static Bool LineAndXYForPosition(TextWidget, XawTextPosition, int*, - int*, int*); -static int LineForPosition(TextWidget, XawTextPosition); -static void TextLoseSelection(Widget, Atom*); -static Bool MatchSelection(Atom, XawTextSelection*); -static void ModifySelection(TextWidget, XawTextPosition, XawTextPosition); -static XawTextPosition PositionForXY(TextWidget, int, int); -static void PositionHScrollBar(TextWidget); -static void PositionVScrollBar(TextWidget); -#ifndef OLDXAW -static int ResolveColumnNumber(TextWidget); -static int ResolveLineNumber(TextWidget); -#endif -static void _SetSelection(TextWidget, XawTextPosition, XawTextPosition, - Atom*, Cardinal); -static void TextSinkResize(Widget); -static void UpdateTextInRectangle(TextWidget, XRectangle*); -static void UpdateTextInLine(TextWidget, int, int, int); -static void VScroll(Widget, XtPointer, XtPointer); -static void VJump(Widget, XtPointer, XtPointer); - -/* - * External - */ -void _XawTextAlterSelection(TextWidget, - XawTextSelectionMode, XawTextSelectionAction, - String*, Cardinal*); -void _XawTextCheckResize(TextWidget); -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 _XawTextSetScrollBars(TextWidget); -void _XawTextSetSelection(TextWidget, XawTextPosition, XawTextPosition, - String*, Cardinal); -void _XawTextVScroll(TextWidget, int); -void XawTextScroll(TextWidget, int, int); -void _XawTextSetSource(Widget, Widget, XawTextPosition, XawTextPosition); -#ifndef OLDXAW -void _XawTextSetLineAndColumnNumber(TextWidget, Bool); -#endif -void _XawTextSourceChanged(Widget, XawTextPosition, XawTextPosition, - XawTextBlock*, int); - -/* Not used by other modules, but were extern on previous versions - * of the library - */ -void _XawTextShowPosition(TextWidget); - -/* - * From TextAction.c - */ -extern void _XawTextZapSelection(TextWidget, XEvent*, Bool); - -/* - * From TextSrc.c - */ -void _XawSourceAddText(Widget, Widget); -void _XawSourceRemoveText(Widget, Widget, Bool); -Bool _XawTextSourceNewLineAtEOF(Widget); - -/* - * From TextSink.c - */ -void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned); -void _XawTextSinkDisplayText(Widget, int, int, XawTextPosition, XawTextPosition, - Bool); - -/**************************************************************** - * - * Full class record constant - * - ****************************************************************/ -/* - * From TextTr.c - */ -static XawTextSelectType defaultSelectTypes[] = { - XawselectPosition, XawselectAlphaNumeric, XawselectWord, XawselectLine, - XawselectParagraph, XawselectAll, XawselectNull, -}; - -static XPointer defaultSelectTypesPtr = (XPointer)defaultSelectTypes; -static Dimension defWidth = 100; -static Dimension defHeight = DEFAULT_TEXT_HEIGHT; - -#define offset(field) XtOffsetOf(TextRec, field) -static XtResource resources[] = { - { - XtNwidth, - XtCWidth, - XtRDimension, - sizeof(Dimension), - offset(core.width), - XtRDimension, - (XtPointer)&defWidth - }, - { - XtNcursor, - XtCCursor, - XtRCursor, - sizeof(Cursor), - offset(simple.cursor), - XtRString, - "xterm" - }, - { - XtNheight, - XtCHeight, - XtRDimension, - sizeof(Dimension), - offset(core.height), - XtRDimension, - (XtPointer)&defHeight - }, - { - XtNdisplayPosition, - XtCTextPosition, - XtRInt, - sizeof(XawTextPosition), - offset(text.lt.top), - XtRImmediate, - (XtPointer)0 - }, - { - XtNinsertPosition, - XtCTextPosition, - XtRInt, - sizeof(XawTextPosition), - offset(text.insertPos), - XtRImmediate, - (XtPointer)0 - }, - { - XtNleftMargin, - XtCMargin, - XtRPosition, - sizeof(Position), - offset(text.r_margin.left), - XtRImmediate, - (XtPointer)2 - }, - { - XtNrightMargin, - XtCMargin, - XtRPosition, - sizeof(Position), - offset(text.r_margin.right), - XtRImmediate, - (XtPointer)4 - }, - { - XtNtopMargin, - XtCMargin, - XtRPosition, - sizeof(Position), - offset(text.r_margin.top), - XtRImmediate, - (XtPointer)2 - }, - { - XtNbottomMargin, - XtCMargin, - XtRPosition, - sizeof(Position), - offset(text.r_margin.bottom), - XtRImmediate, - (XtPointer)2 - }, - { - XtNselectTypes, - XtCSelectTypes, - XtRPointer, - sizeof(XawTextSelectType*), - offset(text.sarray), - XtRPointer, - (XtPointer)&defaultSelectTypesPtr - }, - { - XtNtextSource, - XtCTextSource, - XtRWidget, - sizeof(Widget), - offset(text.source), - XtRImmediate, - NULL - }, - { - XtNtextSink, - XtCTextSink, - XtRWidget, - sizeof(Widget), - offset(text.sink), - XtRImmediate, - NULL - }, - { - XtNdisplayCaret, - XtCOutput, - XtRBoolean, - sizeof(Boolean), - offset(text.display_caret), - XtRImmediate, - (XtPointer)True - }, - { - XtNscrollVertical, - XtCScroll, - XtRScrollMode, - sizeof(XawTextScrollMode), - offset(text.scroll_vert), - XtRImmediate, - (XtPointer)False - }, - { - XtNscrollHorizontal, - XtCScroll, - XtRScrollMode, - sizeof(XawTextScrollMode), - offset(text.scroll_horiz), - XtRImmediate, - (XtPointer)False - }, - { - XtNwrap, - XtCWrap, - XtRWrapMode, - sizeof(XawTextWrapMode), - offset(text.wrap), - XtRImmediate, - (XtPointer)XawtextWrapNever - }, - { - XtNautoFill, - XtCAutoFill, - XtRBoolean, - sizeof(Boolean), - offset(text.auto_fill), - XtRImmediate, - (XtPointer)False - }, -#ifndef OLDXAW - { - XtNpositionCallback, - XtCCallback, - XtRCallback, - sizeof(XtPointer), - offset(text.position_callbacks), - XtRCallback, - NULL - }, - { - XtNleftColumn, - XtCColumn, - XtRShort, - sizeof(short), - offset(text.left_column), - XtRImmediate, - (XtPointer)0 - }, - { - XtNrightColumn, - XtCColumn, - XtRShort, - sizeof(short), - offset(text.right_column), - XtRImmediate, - (XtPointer)0 - }, - { - XtNjustifyMode, - XtCJustifyMode, - XtRJustifyMode, - sizeof(XawTextJustifyMode), - offset(text.justify), - XtRImmediate, - (XtPointer)XawjustifyLeft - }, -#endif /* OLDXAW */ -}; -#undef offset - -#define done(address, type) \ - { toVal->size = sizeof(type); toVal->addr = (XPointer)address; } - -static XrmQuark QWrapNever, QWrapLine, QWrapWord; -#ifndef notdef -static XrmQuark QScrollNever, QScrollWhenNeeded, QScrollAlways; -#endif -static XrmQuark QJustifyLeft, QJustifyRight, QJustifyCenter, QJustifyFull; - -/*ARGSUSED*/ -static void -CvtStringToScrollMode(XrmValuePtr args, Cardinal *num_args, - XrmValuePtr fromVal, XrmValuePtr toVal) -{ - static XawTextScrollMode scrollMode = XawtextScrollNever; - XrmQuark q; - char name[32]; - - XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); - q = XrmStringToQuark(name); - - if (q == QScrollNever || q == QScrollWhenNeeded) - scrollMode = XawtextScrollNever; - else if (q == QScrollAlways) - scrollMode = XawtextScrollAlways; - else if (strcmp(name, "true") == 0 || strcmp(name, "1") == 0) - scrollMode = XawtextScrollAlways; - else if (strcmp(name, "false") == 0 || strcmp(name, "0") == 0) - scrollMode = XawtextScrollNever; - else - XtStringConversionWarning((char *)fromVal->addr, XtRScrollMode); - - done(&scrollMode, XawTextScrollMode); -} - -/*ARGSUSED*/ -static Boolean -CvtScrollModeToString(Display *dpy, XrmValue *args, Cardinal *num_args, - XrmValue *fromVal, XrmValue *toVal, XtPointer *data) -{ - static char *buffer; - Cardinal size; - - switch (*(XawTextScrollMode *)fromVal->addr) { - case XawtextScrollNever: - case XawtextScrollWhenNeeded: - buffer = XtEtextScrollNever; - break; - case XawtextScrollAlways: - buffer = XtEtextScrollAlways; - break; - default: - XawTypeToStringWarning(dpy, XtRScrollMode); - toVal->addr = NULL; - toVal->size = 0; - return (False); - } - size = strlen(buffer) + 1; - if (toVal->addr != NULL) { - if (toVal->size < size) { - toVal->size = size; - return (False); - } - strcpy((char *)toVal->addr, buffer); - } - else - toVal->addr = (XPointer)buffer; - toVal->size = sizeof(String); - - return (True); -} - -/*ARGSUSED*/ -static void -CvtStringToWrapMode(XrmValuePtr args, Cardinal *num_args, - XrmValuePtr fromVal, XrmValuePtr toVal) -{ - static XawTextWrapMode wrapMode = XawtextWrapNever; - XrmQuark q; - char lowerName[6]; - - XmuNCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr, - sizeof(lowerName)); - q = XrmStringToQuark(lowerName); - - if (q == QWrapNever) - wrapMode = XawtextWrapNever; - else if (q == QWrapLine) - wrapMode = XawtextWrapLine; - else if (q == QWrapWord) - wrapMode = XawtextWrapWord; - else - XtStringConversionWarning((char *)fromVal->addr, XtRWrapMode); - - done(&wrapMode, XawTextWrapMode); -} - -/*ARGSUSED*/ -static Boolean -CvtWrapModeToString(Display *dpy, XrmValue *args, Cardinal *num_args, - XrmValue *fromVal, XrmValue *toVal, XtPointer *data) -{ - static char *buffer; - Cardinal size; - - switch (*(XawTextWrapMode *)fromVal->addr) { - case XawtextWrapNever: - buffer = XtEtextWrapNever; - break; - case XawtextWrapLine: - buffer = XtEtextWrapLine; - break; - case XawtextWrapWord: - buffer = XtEtextWrapWord; - break; - default: - XawTypeToStringWarning(dpy, XtRWrapMode); - toVal->addr = NULL; - toVal->size = 0; - return (False); - } - size = strlen(buffer) + 1; - if (toVal->addr != NULL) { - if (toVal->size < size) { - toVal->size = size; - return (False); - } - strcpy((char *)toVal->addr, buffer); - } - else - toVal->addr = (XPointer)buffer; - toVal->size = sizeof(String); - - return (True); -} - -/*ARGSUSED*/ -static Boolean -CvtStringToJustifyMode(Display *dpy, XrmValue *args, Cardinal *num_args, - XrmValue *fromVal, XrmValue *toVal, XtPointer *data) -{ - XawTextJustifyMode justify; - XrmQuark q; - char lowerName[8]; - - XmuNCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr, - sizeof(lowerName)); - q = XrmStringToQuark(lowerName); - - if (q == QJustifyLeft) - justify = XawjustifyLeft; - else if (q == QJustifyRight) - justify = XawjustifyRight; - else if (q == QJustifyCenter) - justify = XawjustifyCenter; - else if(q == QJustifyFull) - justify = XawjustifyFull; - else { - XtStringConversionWarning((char *)fromVal->addr, XtRJustifyMode); - return (False); - } - - toVal->size = sizeof(XawTextJustifyMode); - *(XawTextJustifyMode *)(toVal->addr) = justify; - - return (True); -} - - -/*ARGSUSED*/ -static Boolean -CvtJustifyModeToString(Display *dpy, XrmValue *args, Cardinal *num_args, - XrmValue *fromVal, XrmValue *toVal, XtPointer *data) -{ - static char *buffer; - Cardinal size; - - switch (*(XawTextJustifyMode *)fromVal->addr) { - case XawjustifyLeft: - buffer = XtEtextJustifyLeft; - break; - case XawjustifyRight: - buffer = XtEtextJustifyRight; - break; - case XawjustifyCenter: - buffer = XtEtextJustifyCenter; - break; - case XawjustifyFull: - buffer = XtEtextJustifyFull; - break; - default: - XawTypeToStringWarning(dpy, XtRJustifyMode); - toVal->addr = NULL; - toVal->size = 0; - return (False); - } - size = strlen(buffer) + 1; - if (toVal->addr != NULL) { - if (toVal->size < size) { - toVal->size = size; - return (False); - } - strcpy((char *)toVal->addr, buffer); - } - else - toVal->addr = (XPointer)buffer; - toVal->size = sizeof(String); - - return (True); -} - -#undef done - -static void -XawTextClassInitialize(void) -{ - if (!XawFmt8Bit) - FMT8BIT = XawFmt8Bit = XrmPermStringToQuark("FMT8BIT"); - if (!XawFmtWide) - XawFmtWide = XrmPermStringToQuark("FMTWIDE"); - - XawInitializeWidgetSet(); - - textClassRec.core_class.num_actions = _XawTextActionsTableCount; - - QWrapNever = XrmPermStringToQuark(XtEtextWrapNever); - QWrapLine = XrmPermStringToQuark(XtEtextWrapLine); - QWrapWord = XrmPermStringToQuark(XtEtextWrapWord); - XtAddConverter(XtRString, XtRWrapMode, CvtStringToWrapMode, NULL, 0); - XtSetTypeConverter(XtRWrapMode, XtRString, CvtWrapModeToString, - NULL, 0, XtCacheNone, NULL); - QScrollNever = XrmPermStringToQuark(XtEtextScrollNever); - QScrollWhenNeeded = XrmPermStringToQuark(XtEtextScrollWhenNeeded); - QScrollAlways = XrmPermStringToQuark(XtEtextScrollAlways); - XtAddConverter(XtRString, XtRScrollMode, CvtStringToScrollMode, - NULL, 0); - XtSetTypeConverter(XtRScrollMode, XtRString, CvtScrollModeToString, - NULL, 0, XtCacheNone, NULL); - QJustifyLeft = XrmPermStringToQuark(XtEtextJustifyLeft); - QJustifyRight = XrmPermStringToQuark(XtEtextJustifyRight); - QJustifyCenter = XrmPermStringToQuark(XtEtextJustifyCenter); - QJustifyFull = XrmPermStringToQuark(XtEtextJustifyFull); - XtSetTypeConverter(XtRString, XtRJustifyMode, CvtStringToJustifyMode, - NULL, 0, XtCacheNone, NULL); - XtSetTypeConverter(XtRJustifyMode, XtRString, CvtJustifyModeToString, - NULL, 0, XtCacheNone, NULL); -} - -/* - * Function: - * PositionHScrollBar - * - * Parameters: - * ctx - text widget - * - * Description: - * Positions the Horizontal scrollbar. - */ -static void -PositionHScrollBar(TextWidget ctx) -{ - Widget hbar = ctx->text.hbar, vbar = ctx->text.vbar; - Position x, y; - Dimension width, height; - - if (ctx->text.hbar == NULL) - return; - - if (vbar != NULL) - x = XtWidth(vbar); - else - x = -XtBorderWidth(hbar); - y = XtHeight(ctx) - XtHeight(hbar) - XtBorderWidth(hbar); - if (vbar != NULL) { - width = XtWidth(ctx) - XtWidth(vbar) - XtBorderWidth(vbar); - if (width > XtWidth(ctx)) - width = XtWidth(ctx); - } - else - width = XtWidth(ctx); - height = XtHeight(hbar); - - XtConfigureWidget(hbar, x, y, width, height, XtBorderWidth(hbar)); -} - -/* - * Function: - * PositionVScrollBar - * - * Parameters: - * ctx - text widget - * - * Description: - * Positions the Vertical scrollbar. - */ -static void -PositionVScrollBar(TextWidget ctx) -{ - Widget vbar = ctx->text.vbar; - Position x, y; - Dimension width, height; - - if (vbar == NULL) - return; - - x = y = -XtBorderWidth(vbar); - height = XtHeight(ctx); - width = XtWidth(vbar); - - XtConfigureWidget(vbar, x, y, width, height, XtBorderWidth(vbar)); -} - -static void -CreateVScrollBar(TextWidget ctx) -{ - Widget vbar; - - if (ctx->text.vbar != NULL) - return; - - ctx->text.vbar = vbar = - XtCreateWidget("vScrollbar", scrollbarWidgetClass, (Widget)ctx, NULL, 0); - XtAddCallback(vbar, XtNscrollProc, VScroll, (XtPointer)ctx); - XtAddCallback(vbar, XtNjumpProc, VJump, (XtPointer)ctx); - - ctx->text.r_margin.left += XtWidth(vbar) + XtBorderWidth(vbar); - ctx->text.left_margin = ctx->text.margin.left = ctx->text.r_margin.left; - - PositionVScrollBar(ctx); - PositionHScrollBar(ctx); - TextSinkResize(ctx->text.sink); - - if (XtIsRealized((Widget)ctx)) { - XtRealizeWidget(vbar); - XtMapWidget(vbar); - } - XtSetKeyboardFocus(vbar, (Widget)ctx); -} - -/* - * Function: - * DestroyVScrollBar - * - * Parameters: - * ctx - parent text widget - * - * Description: - * Removes vertical ScrollBar. - */ -static void -DestroyVScrollBar(TextWidget ctx) -{ - Widget vbar = ctx->text.vbar; - - if (vbar == NULL) - return; - - ctx->text.r_margin.left -= XtWidth(vbar) + XtBorderWidth(vbar); - ctx->text.left_margin = ctx->text.margin.left = ctx->text.r_margin.left; - - XtDestroyWidget(vbar); - ctx->text.vbar = NULL; - if (!ctx->core.being_destroyed) { - PositionHScrollBar(ctx); - TextSinkResize(ctx->text.sink); - } -} - -static void -CreateHScrollBar(TextWidget ctx) -{ - Arg args[1]; - Widget hbar; - int bottom; - - if (ctx->text.hbar != NULL) - return; - - XtSetArg(args[0], XtNorientation, XtorientHorizontal); - ctx->text.hbar = hbar = - XtCreateWidget("hScrollbar", scrollbarWidgetClass, (Widget)ctx, args, 1); - XtAddCallback(hbar, XtNscrollProc, HScroll, (XtPointer)ctx); - XtAddCallback(hbar, XtNjumpProc, HJump, (XtPointer)ctx); - - bottom = ctx->text.r_margin.bottom + XtHeight(hbar) + XtBorderWidth(hbar); - - ctx->text.margin.bottom = ctx->text.r_margin.bottom = bottom; - - PositionHScrollBar(ctx); - TextSinkResize(ctx->text.sink); - - if (XtIsRealized((Widget)ctx)) { - XtRealizeWidget(hbar); - XtMapWidget(hbar); - } - XtSetKeyboardFocus(hbar, (Widget)ctx); -} - -/* - * Function: - * DestroyHScrollBar - * - * Parameters: - * ctx - parent text widget - * - * Description: - * Removes horizontal ScrollBar. - */ -static void -DestroyHScrollBar(TextWidget ctx) -{ - Widget hbar = ctx->text.hbar; - - if (hbar == NULL) - return; - - ctx->text.r_margin.bottom -= XtHeight(hbar) + XtBorderWidth(hbar); - ctx->text.margin.bottom = ctx->text.r_margin.bottom; - - XtDestroyWidget(hbar); - ctx->text.hbar = NULL; - if (!ctx->core.being_destroyed) - TextSinkResize(ctx->text.sink); -} - -/*ARGSUSED*/ -static void -XawTextInitialize(Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - TextWidget ctx = (TextWidget)cnew; - - ctx->text.lt.lines = 0; - ctx->text.lt.info = (XawTextLineTableEntry *) - XtCalloc(1, sizeof(XawTextLineTableEntry)); -#ifndef OLDXAW - ctx->text.lt.base_line = 1; -#endif - (void)bzero(&ctx->text.origSel, sizeof(XawTextSelection)); - (void)bzero(&ctx->text.s, sizeof(XawTextSelection)); - ctx->text.s.type = XawselectPosition; - ctx->text.salt = NULL; - ctx->text.hbar = ctx->text.vbar = NULL; - ctx->text.lasttime = 0; - ctx->text.time = 0; - ctx->text.showposition = True; - ctx->text.lastPos = ctx->text.source != NULL ? - XawTextGetLastPosition(ctx) : 0; - ctx->text.file_insert = NULL; - ctx->text.search = NULL; - ctx->text.update = XmuNewScanline(0, 0, 0); - ctx->text.gc = XtGetGC(cnew, 0, 0); - ctx->text.hasfocus = False; - ctx->text.margin = ctx->text.r_margin; /* Strucure copy */ - ctx->text.left_margin = ctx->text.r_margin.left; - ctx->text.update_disabled = False; - ctx->text.clear_to_eol = True; - ctx->text.old_insert = -1; - ctx->text.mult = 1; - ctx->text.salt2 = NULL; - ctx->text.from_left = -1; - -#ifndef OLDXAW - ctx->text.numeric = False; - ctx->text.selection_state = False; - ctx->text.kill_ring = 0; - - ctx->text.line_number = -1; - ctx->text.column_number = -1; - ctx->text.source_changed = SRC_CHANGE_NONE; - - ctx->text.kill_ring_ptr = NULL; - ctx->text.overwrite = False; -#endif - - if (XtHeight(ctx) == DEFAULT_TEXT_HEIGHT) { - XtHeight(ctx) = VMargins(ctx); - if (ctx->text.sink != NULL) - XtHeight(ctx) += XawTextSinkMaxHeight(ctx->text.sink, 1); - } - - if (ctx->text.scroll_vert == XawtextScrollAlways) - CreateVScrollBar(ctx); - if (ctx->text.scroll_horiz == XawtextScrollAlways) - CreateHScrollBar(ctx); - -#ifndef OLDXAW - if (ctx->text.left_column < 0) - ctx->text.left_column = 0; - if (ctx->text.right_column < 0) - ctx->text.right_column = 0; -#endif -} - -static void -XawTextRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attr) -{ - TextWidget ctx = (TextWidget)w; - - (*textClassRec.core_class.superclass->core_class.realize)(w, mask, attr); - - if (ctx->text.hbar != NULL) { - XtRealizeWidget(ctx->text.hbar); - XtMapWidget(ctx->text.hbar); - } - - if (ctx->text.vbar != NULL) { - XtRealizeWidget(ctx->text.vbar); - XtMapWidget(ctx->text.vbar); - } - - _XawTextBuildLineTable(ctx, ctx->text.lt.top, True); - -#ifndef OLDXAW - _XawTextSetLineAndColumnNumber(ctx, True); -#endif -} - -/* Utility routines for support of Text */ -static void -_CreateCutBuffers(Display *d) -{ - static struct _DisplayRec { - struct _DisplayRec *next; - Display *dpy; - } *dpy_list = NULL; - struct _DisplayRec *dpy_ptr; - - for (dpy_ptr = dpy_list; dpy_ptr != NULL; dpy_ptr = dpy_ptr->next) - if (dpy_ptr->dpy == d) - return; - - dpy_ptr = XtNew(struct _DisplayRec); - dpy_ptr->next = dpy_list; - dpy_ptr->dpy = d; - dpy_list = dpy_ptr; - -#define Create(buffer) \ - XChangeProperty(d, RootWindow(d, 0), buffer, XA_STRING, 8, \ - PropModeAppend, NULL, 0); - - Create(XA_CUT_BUFFER0); - Create(XA_CUT_BUFFER1); - Create(XA_CUT_BUFFER2); - Create(XA_CUT_BUFFER3); - Create(XA_CUT_BUFFER4); - Create(XA_CUT_BUFFER5); - Create(XA_CUT_BUFFER6); - Create(XA_CUT_BUFFER7); - -#undef Create -} - -/* - * Procedure to manage insert cursor visibility for editable text. It uses - * the value of ctx->insertPos and an implicit argument. In the event that - * position is immediately preceded by an eol graphic, then the insert cursor - * is displayed at the beginning of the next line. - */ -static void -InsertCursor(Widget w, XawTextInsertState state) -{ - TextWidget ctx = (TextWidget)w; - int x, y; - int line; - - if (ctx->text.lt.lines < 1) - return; - - if (ctx->text.display_caret && - LineAndXYForPosition(ctx, ctx->text.insertPos, &line, &x, &y)) { - if (line < ctx->text.lt.lines) - y += (ctx->text.lt.info[line + 1].y - ctx->text.lt.info[line].y) + 1; - else - y += (ctx->text.lt.info[line].y - ctx->text.lt.info[line - 1].y) + 1; - - XawTextSinkInsertCursor(ctx->text.sink, x, y, state); - } - - /* Keep Input Method up to speed */ - if (ctx->simple.international) { - Arg list[1]; - - XtSetArg(list[0], XtNinsertPosition, ctx->text.insertPos); - _XawImSetValues(w, list, 1); - } -} - -/* - * Procedure to register a span of text that is no longer valid on the display - * It is used to avoid a number of small, and potentially overlapping, screen - * updates. -*/ -void -_XawTextNeedsUpdating(TextWidget ctx, - XawTextPosition left, XawTextPosition right) -{ - XmuSegment segment; - - if (left >= right) - return; - - segment.x1 = (int)left; - segment.x2 = (int)right; - (void)XmuScanlineOrSegment(ctx->text.update, &segment); -} - -/* - * Procedure to read a span of text in Ascii form. This is purely a hack and - * we probably need to add a function to sources to provide this functionality. - * [note: this is really a private procedure but is used in multiple modules]. - */ -char * -_XawTextGetText(TextWidget ctx, XawTextPosition left, XawTextPosition right) -{ - char *result, *tempResult; - XawTextBlock text; - int bytes; - - if (XawTextFormat(ctx, XawFmt8Bit)) - bytes = sizeof(unsigned char); - else if (XawTextFormat(ctx, XawFmtWide)) - bytes = sizeof(wchar_t); - else /* if there is another fomat, add here */ - bytes = 1; - - /* leave space for ZERO */ - tempResult = result = XtMalloc((unsigned)(right - left + ONE) * bytes); - - while (left < right) { - left = SrcRead(ctx->text.source, left, &text, (int)(right - left)); - if (!text.length) - break; - memmove(tempResult, text.ptr, (unsigned)(text.length * bytes)); - tempResult += text.length * bytes; - } - - if (bytes == sizeof(wchar_t)) - *((wchar_t*)tempResult) = (wchar_t)0; - else - *tempResult = '\0'; - - return (result); -} - -/* Like _XawTextGetText, but enforces ICCCM STRING type encoding. This - * routine is currently used to put just the ASCII chars in the selection - * into a cut buffer. - */ -char * -_XawTextGetSTRING(TextWidget ctx, XawTextPosition left, XawTextPosition right) -{ - unsigned char *s; - unsigned char c; - long i, j, n; - wchar_t *ws, wc; - - /* allow ESC in accordance with ICCCM */ - if (XawTextFormat(ctx, XawFmtWide)) { - MultiSinkObject sink = (MultiSinkObject)ctx->text.sink; - ws = (wchar_t *)_XawTextGetText(ctx, left, right); - n = wcslen(ws); - for (j = 0, i = 0; j < n; j++) { - wc = ws[j]; - if (XwcTextEscapement (sink->multi_sink.fontset, &wc, 1) - || (wc == _Xaw_atowc(XawTAB)) || (wc == _Xaw_atowc(XawLF)) - || (wc == _Xaw_atowc(XawESC))) - ws[i++] = wc; - } - ws[i] = (wchar_t)0; - return ((char *)ws); - } - else { - s = (unsigned char *)_XawTextGetText(ctx, left, right); - /* only HT and NL control chars are allowed, strip out others */ - n = strlen((char *)s); - i = 0; - for (j = 0; j < n; j++) { - c = s[j]; - if (((c >= 0x20) && c <= 0x7f) - ||(c >= 0xa0) || (c == XawTAB) || (c == XawLF) - || (c == XawESC)) { - s[i] = c; - i++; - } - } - s[i] = 0; - - return ((char *)s); - } -} - -/* - * This routine maps an x and y position in a window that is displaying text - * into the corresponding position in the source. - */ -static XawTextPosition -PositionForXY(TextWidget ctx, int x, int y) -{ - int fromx, line, width, height; - XawTextPosition position; - - if (ctx->text.lt.lines == 0) - return (0); - - for (line = 0; line < ctx->text.lt.lines - 1; line++) { - if (y <= ctx->text.lt.info[line + 1].y) - break; - } - position = ctx->text.lt.info[line].position; - if (position >= ctx->text.lastPos) - return (ctx->text.lastPos); - fromx = ctx->text.left_margin; - XawTextSinkFindPosition(ctx->text.sink, position, fromx, x - fromx, - False, &position, &width, &height); - - if (position > ctx->text.lastPos) - return (ctx->text.lastPos); - - if (position >= ctx->text.lt.info[line + 1].position) - position = SrcScan(ctx->text.source, ctx->text.lt.info[line + 1].position, - XawstPositions, XawsdLeft, 1, True); - - return (position); -} - -/* - * This routine maps a source position in to the corresponding line number - * of the text that is displayed in the window. - */ -static int -LineForPosition(TextWidget ctx, XawTextPosition position) -{ - int line; - - for (line = 0; line < ctx->text.lt.lines; line++) - if (position < ctx->text.lt.info[line + 1].position) - break; - - return (line); -} - -/* - * This routine maps a source position into the corresponding line number - * and the x, y coordinates of the text that is displayed in the window. - */ -static Bool -LineAndXYForPosition(TextWidget ctx, XawTextPosition pos, - int *line, int *x, int *y) -{ - XawTextPosition linePos, endPos; - Boolean visible; - int realW, realH; - - *line = 0; - *x = ctx->text.left_margin; - *y = ctx->text.margin.top + 1; - if ((visible = IsPositionVisible(ctx, pos)) != False) { - *line = LineForPosition(ctx, pos); - *y = ctx->text.lt.info[*line].y; - linePos = ctx->text.lt.info[*line].position; - XawTextSinkFindDistance(ctx->text.sink, linePos, - *x, pos, &realW, &endPos, &realH); - *x += realW; - } - - return (visible); -} - -/* - * This routine builds a line table. It does this by starting at the - * specified position and measuring text to determine the staring position - * of each line to be displayed. It also determines and saves in the - * linetable all the required metrics for displaying a given line (e.g. - * x offset, y offset, line length, etc.). - */ -void -_XawTextBuildLineTable(TextWidget ctx, XawTextPosition position, - _XtBoolean force_rebuild) -{ - Dimension height = 0; - int lines = 0; - Cardinal size; - - if ((int)XtHeight(ctx) > VMargins(ctx)) { - height = XtHeight(ctx) - VMargins(ctx); - lines = XawTextSinkMaxLines(ctx->text.sink, height); - } - size = sizeof(XawTextLineTableEntry) * (lines + 1); - - if (lines != ctx->text.lt.lines || ctx->text.lt.info == NULL) { - ctx->text.lt.info = (XawTextLineTableEntry *) - XtRealloc((char *)ctx->text.lt.info, size); - ctx->text.lt.lines = lines; - force_rebuild = True; - } - - if (force_rebuild) { - (void)bzero((char *)ctx->text.lt.info, size); - /* force a text update in the first text line if it is visible */ - ctx->text.lt.info[0].position = (XawTextPosition)-1; - } - if (position != ctx->text.lt.info[0].position) { - (void)_BuildLineTable(ctx, position, 0); - ctx->text.clear_to_eol = True; - } -} - -/* - * We may need to resize the line table here, since there maybe lines with - * different fonts (that can be shorter or taller than the default one) - */ -static XawTextPosition -_BuildLineTable(TextWidget ctx, XawTextPosition position, int line) -{ - XawTextLineTableEntry *lt = ctx->text.lt.info + line; - XawTextPosition end, update_from = -1; - Position y; - int wwidth, width, height; -#ifndef OLDXAW - Widget src = ctx->text.source; -#endif - int max_y = (int)XtHeight(ctx) - (int)ctx->text.margin.bottom; - - if (ctx->text.wrap == XawtextWrapNever) - wwidth = 0x7fffffff; - else - wwidth = GetMaxTextWidth(ctx); - - /* XXX y may change, due to font size changes. See later */ - y = line == 0 ? ctx->text.margin.top : lt->y; - -#ifndef OLDXAW - if (ctx->text.lt.base_line < 0) { - if (line == 0) - ctx->text.lt.top = position; - } - else if (line == 0) { - XawTextPosition pos = ctx->text.lt.top; - int base_line = ctx->text.lt.base_line; - - if (position == 0) - base_line = 1; - else if (ctx->text.lt.base_line == 0 || - ctx->text.source_changed == SRC_CHANGE_OVERLAP) { - pos = 0; - base_line = 1; - - while (pos < position) { - pos = SrcScan(src, pos, XawstEOL, XawsdRight, 1, True); - if (pos <= position) { - ++base_line; - if (pos == ctx->text.lastPos) { - base_line -= !_XawTextSourceNewLineAtEOF(src); - break; - } - } - } - } - else if (ctx->text.wrap == XawtextWrapNever - && IsPositionVisible(ctx, position)) - base_line += LineForPosition(ctx, position); - else if (pos < position) { - while (pos < position) { - pos = SrcScan(src, pos, XawstEOL, XawsdRight, 1, True); - if (pos <= position) { - ++base_line; - if (pos == ctx->text.lastPos) { - base_line -= !_XawTextSourceNewLineAtEOF(src); - break; - } - } - } - } - else if (pos > position) { - while (pos > position) { - pos = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False); - if (--pos >= position) - --base_line; - } - } - - ctx->text.lt.top = position; - ctx->text.lt.base_line = base_line; - } -#else - if (line == 0) - ctx->text.lt.top = position; -#endif - - /* CONSTCOND */ - while (True) { - XawTextSinkFindPosition(ctx->text.sink, position, ctx->text.left_margin, - wwidth, ctx->text.wrap == XawtextWrapWord, - &end, &width, &height); - - if (lt->position != position) { - _XawTextNeedsUpdating(ctx, position, - end <= position ? position + 1 : end); - ctx->text.clear_to_eol = True; - lt->position = position; - } - if (lt->y != y) { - if (update_from < 0) - update_from = line == 0 ? - ctx->text.lt.info[0].position : - ctx->text.lt.info[line - 1].position; - lt->y = y; - ctx->text.clear_to_eol = True; - } - if (lt->textWidth != width) { - if (lt->textWidth > width) - ctx->text.clear_to_eol = True; - lt->textWidth = width; - } - y += height; - - if (end > ctx->text.lastPos) { - position = end; - ctx->text.clear_to_eol = True; - _XawTextNeedsUpdating(ctx, end, end + ctx->text.lt.lines - line); - while (line++ < ctx->text.lt.lines) { - if (line > 1 && y > max_y) { - ctx->text.lt.lines = line - 1; - break; - } - ++lt; - if (lt->y != y) { - if (update_from < 0) - update_from = line < 2 ? - ctx->text.lt.info[0].position : - ctx->text.lt.info[line - 2].position; - lt->y = y; - } - lt->position = ++position; - lt->textWidth = 0; - y += height; - } - if (update_from >= 0) - _XawTextNeedsUpdating(ctx, update_from, - ctx->text.lt.info[ctx->text.lt.lines].position); - _XawTextSetScrollBars(ctx); - - return (ctx->text.lastPos); - } - - if (line && y > max_y) - /* will return in the next loop */ - ctx->text.lt.lines = line; - - if (++line > ctx->text.lt.lines && y < max_y) { - /* grow the line table */ - ctx->text.lt.info = (XawTextLineTableEntry *) - XtRealloc((char *)ctx->text.lt.info, - sizeof(XawTextLineTableEntry) * (line + 1)); - lt = ctx->text.lt.info + line; - bzero(lt, sizeof(XawTextLineTableEntry)); - ++ctx->text.lt.lines; - } - else - ++lt; - if (position == end) - ++position; - else - position = end; - - if (line > ctx->text.lt.lines) { - if (update_from >= 0) - _XawTextNeedsUpdating(ctx, update_from, - ctx->text.lt.info[ctx->text.lt.lines].position); - _XawTextSetScrollBars(ctx); - - return (position); - } - } - /*NOTREACHED*/ -} - -/* - * Function: - * GetWidestLine - * - * Parameters: - * ctx - text widget - * - * Description: - * Returns the width (in pixels) of the widest line that - * is currently visable. - * - * Returns: - * The width of the widest line - */ -static unsigned int -GetWidestLine(TextWidget ctx) -{ - int i; - unsigned int widest; - XawTextLineTablePtr lt = &(ctx->text.lt); - - for (i = 0, widest = 0; i < lt->lines; i++) - if (widest < lt->info[i].textWidth) - widest = lt->info[i].textWidth; - - return (widest); -} - -/* - * This routine is used by Text to notify an associated scrollbar of the - * correct metrics (position and shown fraction) for the text being currently - * displayed in the window. - */ -void -_XawTextSetScrollBars(TextWidget ctx) -{ - float first, last, denom, widest; - - if (ctx->text.scroll_vert == XawtextScrollAlways) { - if (ctx->text.lastPos == 0) - first = 0.0; - else - first = ctx->text.lt.top / (float)ctx->text.lastPos; - - if (ctx->text.lt.info[ctx->text.lt.lines].position < ctx->text.lastPos) - last = ctx->text.lt.info[ctx->text.lt.lines].position / - (float)ctx->text.lastPos; - else - last = 1.0; - - XawScrollbarSetThumb(ctx->text.vbar, first, last - first); - } - - if (ctx->text.scroll_horiz == XawtextScrollAlways) { - denom = GetWidestLine(ctx); - if (denom <= 0) - denom = (int)XtWidth(ctx) - RHMargins(ctx); - if (denom <= 0) - denom = 1; - widest = ((int)XtWidth(ctx) - RHMargins(ctx)) / denom; - first = ctx->text.r_margin.left - ctx->text.left_margin; - first /= denom; - - XawScrollbarSetThumb(ctx->text.hbar, first, widest); - } -} - -static void -DoCopyArea(TextWidget ctx, int src_x, int src_y, - unsigned int width, unsigned int height, int dst_x, int dst_y) -{ - int x1, y1, x2, y2; - - x1 = ctx->text.r_margin.left; - y1 = ctx->text.r_margin.top; - x2 = XtWidth(ctx) - ctx->text.r_margin.right; - y2 = XtHeight(ctx) - ctx->text.r_margin.bottom; - - if (x1 >= x2 || y1 >= y2) - return; - - src_x = XawMax(x1, XawMin(src_x, x2)); - src_y = XawMax(y1, XawMin(src_y, y2)); - dst_x = XawMax(x1, XawMin(dst_x, x2)); - dst_y = XawMax(y1, XawMin(dst_y, y2)); - width = XawMax(0, XawMin(x2 - dst_x, (int)width)); - height = XawMax(0, XawMin(y2 - dst_y, (int)height)); - - XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), ctx->text.gc, - src_x, src_y, width, height, dst_x, dst_y); -} - -/* - * Function: - * XawTextScroll - * - * Parameters: - * ctx - text widget - * vlines - number of lines to scroll vertically - * hpixels - number of pixels to scroll horizontally - * - * Description: - * Generic function for scrolling the text window. - * Allows vertical and horizontal scroll at the same time. - */ -void -XawTextScroll(TextWidget ctx, int vlines, int hpixels) -{ - XawTextPosition top, tmp, update_from, update_to; - XawTextLineTable *lt; - Arg arglist[1]; - int y0, y1, y2, count, dim, wwidth, lines = ctx->text.lt.lines; - int vwidth, vheight; /* visible width and height */ - Bool scroll; - - vwidth = (int)XtWidth(ctx) - RHMargins(ctx); - vheight = (int)XtHeight(ctx) - RVMargins(ctx); - lt = &ctx->text.lt; - - if (!lt || vwidth <= 0 || vheight <= 0) - return; - - if ((scroll = ctx->core.background_pixmap == XtUnspecifiedPixmap) == True) { - dim = lt->info[1].y - lt->info[0].y; - for (count = 1; count < lt->lines - 1; count++) - if (lt->info[count + 1].y - lt->info[count].y != dim) { - scroll = False; - break; - } - } - - wwidth = GetMaxTextWidth(ctx); - - /* - * Do the horizontall scrolling - */ - if (hpixels < 0 && ctx->text.left_margin - hpixels > ctx->text.r_margin.left) - hpixels = ctx->text.left_margin - ctx->text.r_margin.left; - ctx->text.left_margin -= hpixels; - - update_from = lt->top; /* remember the old value */ - /* - * Checks the requested number of lines and calculates the top - * of the line table - */ - if (vlines < 0) { /* VScroll Up */ - if (IsPositionVisible(ctx, 0)) - vlines = 0; - else if (ctx->text.wrap != XawtextWrapNever) { - XawTextPosition end; - int n_lines = 0; - - count = -vlines; - end = lt->top; - while (n_lines < count) { - top = SrcScan(ctx->text.source, end, XawstEOL, - XawsdLeft, 2, False); - n_lines += CountLines(ctx, top, end); - end = top; - } - - while (count++ < n_lines) { - tmp = top; - XawTextSinkFindPosition(ctx->text.sink, top, - ctx->text.left_margin, - wwidth,ctx->text.wrap == XawtextWrapWord, - &top, &dim, &dim); - if (tmp == top) - ++top; - } - } - else - top = SrcScan(ctx->text.source, lt->top, XawstEOL, - XawsdLeft, -vlines + 1, False); - if (-vlines >= ctx->text.lt.lines) - scroll = False; - } - else if (vlines > 0) { /* VScroll Down */ - if (LineForPosition(ctx, ctx->text.lastPos) == 0) - vlines = 0; - if (vlines < lt->lines) - top = XawMin(lt->info[vlines].position, ctx->text.lastPos); - else if (ctx->text.wrap == XawtextWrapNever) - top = SrcScan(ctx->text.source, - SrcScan(ctx->text.source, lt->top, - XawstEOL, XawsdRight, vlines, - True), - XawstEOL, XawsdLeft, 1, False); - else { - top = lt->top; - count = 0; - while (count++ < vlines) { - tmp = top; - XawTextSinkFindPosition(ctx->text.sink, top, - ctx->text.left_margin, - wwidth, ctx->text.wrap == XawtextWrapWord, - &top, &dim, &dim); - if (tmp == top) - ++top; - } - } - if (vlines >= ctx->text.lt.lines - || lt->info[vlines].position >= ctx->text.lastPos) - scroll = False; - } - - if (!vlines) { - if (hpixels) { - ClearWindow(ctx); - ctx->text.clear_to_eol = True; - } - _XawTextSetScrollBars(ctx); - return; - } - - /* Flushes any pending updates. Normally, there may be a call to - * XawTextUnsetSelection not yet updated. - */ - if (!hpixels && scroll) { - ctx->text.clear_to_eol = True; - FlushUpdate(ctx); - } - - /* - * Rebuild the line table, doing the vertical scroll - */ - (void)_BuildLineTable(ctx, top, 0); - lt = &ctx->text.lt; - if (scroll) { - for (count = 0; count < lt->lines - 1; count++) - if (lt->info[count + 1].y - lt->info[count].y != dim) { - scroll = False; - break; - } - } - - XtSetArg(arglist[0], XtNinsertPosition, lt->top + lt->lines); - _XawImSetValues((Widget)ctx, arglist, 1); - - if (hpixels || !scroll || lines != lt->lines) - return; - - /* _BuildLineTable updates everything if the top position changes. - * It is not required here. - */ - (void)XmuScanlineXor(ctx->text.update, ctx->text.update); - if (vlines < 0 && IsPositionVisible(ctx, 0)) - vlines = -LineForPosition(ctx, update_from); - - y0 = ctx->text.r_margin.top; - if (vlines < 0) { - update_from = lt->top; - update_to = lt->info[-vlines + 1].position - 1; - y1 = lt->info[lt->lines + vlines].y; - y2 = lt->info[-vlines].y; - DoCopyArea(ctx, ctx->text.r_margin.left, y0, vwidth, - y1 - y0, - ctx->text.r_margin.left, y2); - } - else { - update_from = lt->info[lt->lines - vlines].position; - update_to = lt->info[lt->lines].position; - y1 = lt->info[lt->lines - vlines].y; - y2 = lt->info[vlines].y; - DoCopyArea(ctx, ctx->text.r_margin.left, y2, - vwidth, lt->info[lt->lines].y - y2, - ctx->text.r_margin.left, y0); - } - _XawTextNeedsUpdating(ctx, update_from, update_to); - ctx->text.clear_to_eol = True; -} - -/* - * The routine will scroll the displayed text by lines. If the arg is - * positive, move up; otherwise, move down. [note: this is really a private - * procedure but is used in multiple modules]. - */ -void -_XawTextVScroll(TextWidget ctx, int n) -{ - XawTextScroll(ctx, n, 0); -} - -/*ARGSUSED*/ -static void -HScroll(Widget w, XtPointer closure, XtPointer callData) -{ - TextWidget ctx = (TextWidget)closure; - long pixels = (long)callData; - - if (pixels > 0) { - long max; - - max = (int)GetWidestLine(ctx) + ctx->text.left_margin - - ctx->text.r_margin.left; - max = XawMax(0, max); - pixels = XawMin(pixels, max); - } - - if (pixels) { - _XawTextPrepareToUpdate(ctx); - XawTextScroll(ctx, 0, pixels); - _XawTextExecuteUpdate(ctx); - } -} - -/*ARGSUSED*/ -static void -HJump(Widget w, XtPointer closure, XtPointer callData) -{ - TextWidget ctx = (TextWidget)closure; - float percent = *(float *)callData; - long pixels; - - pixels = ctx->text.left_margin - - (ctx->text.r_margin.left - (int)(percent * GetWidestLine(ctx))); - - HScroll(w, (XtPointer)ctx, (XtPointer)pixels); -} - -/* - * Function: - * UpdateTextInLine - * - * Parameters: - * ctx - text widget - * line - line to update - * x1 - left pixel - * x2 - right pixel - * - * Description: - * Updates the text in the given line and pixel interval - */ -static void -UpdateTextInLine(TextWidget ctx, int line, int x1, int x2) -{ - XawTextLineTableEntry *lt = ctx->text.lt.info + line; - XawTextPosition left, right; - int from_x, width, height; - - if (lt->position >= ctx->text.lastPos - || ctx->text.left_margin > x2 - || (int)lt->textWidth + ctx->text.left_margin < x1) { - /* Mark line to be cleared */ - if (ctx->text.clear_to_eol) - _XawTextNeedsUpdating(ctx, lt->position, lt->position + 1); - return; - } - - from_x = ctx->text.left_margin; - XawTextSinkFindPosition(ctx->text.sink, lt->position, - from_x, x1 - from_x, - False, &left, &width, &height); - if (line == ctx->text.lt.lines) - right = -1; - else if (x2 >= lt->textWidth - from_x) - right = lt[1].position - 1; - else { - from_x += width; - XawTextSinkFindPosition(ctx->text.sink, left, - from_x, x2 - from_x, - False, &right, &width, &height); - } - - if ((right < 0) || (right + 1 <= lt[1].position)) - ++right; - - /* Mark text interval to be repainted */ - _XawTextNeedsUpdating(ctx, left, right); -} - -/* - * The routine will scroll the displayed text by pixels. If the calldata is - * positive, move up; otherwise, move down. - */ -/*ARGSUSED*/ -static void -VScroll(Widget w, XtPointer closure, XtPointer callData) -{ - TextWidget ctx = (TextWidget)closure; - long height, lines = (long)callData; - - height = XtHeight(ctx) - VMargins(ctx); - if (height < 1) - height = 1; - lines = (lines * ctx->text.lt.lines) / height; - _XawTextPrepareToUpdate(ctx); - XawTextScroll(ctx, lines, 0); - _XawTextExecuteUpdate(ctx); -} - -/*ARGSUSED*/ -static void -VJump(Widget w, XtPointer closure, XtPointer callData) -{ - float percent = *(float *)callData; - TextWidget ctx = (TextWidget)closure; - XawTextPosition top, last, position, tmp; - XawTextLineTable *lt = &(ctx->text.lt); - int dim, vlines = 0, wwidth = GetMaxTextWidth(ctx); - Bool scroll = True; - - position = percent * ctx->text.lastPos; - top = lt->top; - - if (!lt->lines || (position >= lt->top && position < lt->info[1].position)) { - _XawTextSetScrollBars(ctx); - return; - } - -#ifndef OLDXAW - ctx->text.lt.base_line = -1; -#endif - - if (position > lt->top) { /* VScroll Up */ - if (position > lt->top && position < lt->info[lt->lines].position) - vlines = LineForPosition(ctx, position); - else { - scroll = False; - top = SrcScan(ctx->text.source, position, XawstEOL, - XawsdLeft, 1, False); - if (ctx->text.wrap != XawtextWrapNever) { - last = top; - while (last < position) { - tmp = last; - XawTextSinkFindPosition(ctx->text.sink, last, - ctx->text.left_margin, wwidth, - ctx->text.wrap == XawtextWrapWord, - &last, &dim, &dim); - if (last == tmp) - ++last; - if (last < position) - top = last; - } - } - } - } - else { /* VScroll Down */ - /* - * Calculates the number of lines - */ - while (top > position) { - last = top; - top = SrcScan(ctx->text.source, top, XawstEOL, - XawsdLeft, 2, False); - vlines -= CountLines(ctx, top, last); - if (-vlines >= ctx->text.lt.lines) { - scroll = False; - top = SrcScan(ctx->text.source, position, XawstEOL, - XawsdLeft, 1, False); - break; - } - } - /* - * Normalize - */ - if (ctx->text.wrap != XawtextWrapNever) { - last = top; - while (last < position) { - tmp = last; - XawTextSinkFindPosition(ctx->text.sink, last, - ctx->text.left_margin, - wwidth, - ctx->text.wrap == XawtextWrapWord, - &last, &dim, &dim); - if (last == tmp) - ++last; - if (last < position) - top = last; - ++vlines; - } - } - } - - if (vlines || !scroll) { - _XawTextPrepareToUpdate(ctx); - if (scroll) - XawTextScroll(ctx, vlines, 0); - else - _BuildLineTable(ctx, top, 0); - _XawTextExecuteUpdate(ctx); - } -} - -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); -} - -static Boolean -TextConvertSelection(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, ONE); - - 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); - } - (void)memmove((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); - - if (MatchSelection(*selection, &ctx->text.s)) - s = &ctx->text.s; - else { - for (salt = ctx->text.salt; 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 = _XawTextGetSTRING(ctx, s->left, s->right); - if (XawTextFormat(ctx, XawFmtWide)) { - XTextProperty textprop; - if (XwcTextListToTextProperty(d, (wchar_t **)value, 1, - XCompoundTextStyle, &textprop) - < Success) { - XtFree((char *)*value); - return (False); - } - XtFree((char *)*value); - *value = (XtPointer)textprop.value; - *length = textprop.nitems; - } - else - *length = strlen((char *)*value); - } - else { - *value = XtMalloc((salt->length + 1) * sizeof(unsigned char)); - strcpy ((char *)*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((char *)*value); - return (False); - } - XtFree((char *)*value); - if (XwcTextListToTextProperty(d, wlist, 1, XStringStyle, &textprop) - < Success) { - XwcFreeStringList((wchar_t**) wlist); - return (False); - } - *value = (XtPointer)textprop.value; - *length = textprop.nitems; - XwcFreeStringList(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((char *)*value); - return (False); - } - XtFree((char *)*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((unsigned)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((unsigned)(2 * sizeof(long))); - temp[0] = (long)(s->left + 1); - temp[1] = s->right; - *value = (XPointer)temp; - *type = XA_SPAN(d); - *length = 2L; - *format = 32; - return (True); - } - - if (*target == XA_DELETE(d)) { - if (!salt) - _XawTextZapSelection(ctx, NULL, True); - *value = NULL; - *type = XA_NULL(d); - *length = 0; - *format = 32; - return (True); - } - - if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type, - (XPointer *)value, length, format)) - return (True); - - /* else */ - return (False); -} - -/* - * Function: - * GetCutBuffferNumber - * - * Parameters: - * atom - atom to check - * - * Description: - * Returns the number of the cut buffer. - * - * Returns: - * The number of the cut buffer representing this atom or NOT_A_CUT_BUFFER - */ -#define NOT_A_CUT_BUFFER -1 -static int -GetCutBufferNumber(Atom atom) -{ - if (atom == XA_CUT_BUFFER0) return (0); - if (atom == XA_CUT_BUFFER1) return (1); - if (atom == XA_CUT_BUFFER2) return (2); - if (atom == XA_CUT_BUFFER3) return (3); - if (atom == XA_CUT_BUFFER4) return (4); - if (atom == XA_CUT_BUFFER5) return (5); - if (atom == XA_CUT_BUFFER6) return (6); - if (atom == XA_CUT_BUFFER7) return (7); - return (NOT_A_CUT_BUFFER); -} - -static void -TextLoseSelection(Widget w, Atom *selection) -{ - TextWidget ctx = (TextWidget)w; - Atom *atomP; - int i; - XawTextSelectionSalt*salt, *prevSalt, *nextSalt; - - atomP = ctx->text.s.selections; - for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++) - if ((*selection == *atomP) - || (GetCutBufferNumber(*atomP) != NOT_A_CUT_BUFFER)) - *atomP = (Atom)0; - - while (ctx->text.s.atom_count - && ctx->text.s.selections[ctx->text.s.atom_count - 1] == 0) - ctx->text.s.atom_count--; - - /* - * Must walk the selection list in opposite order from UnsetSelection - */ - atomP = ctx->text.s.selections; - for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++) - if (*atomP == (Atom)0) { - *atomP = ctx->text.s.selections[--ctx->text.s.atom_count]; - while (ctx->text.s.atom_count - && ctx->text.s.selections[ctx->text.s.atom_count-1] == 0) - ctx->text.s.atom_count--; - } - - if (ctx->text.s.atom_count == 0) - ModifySelection(ctx, ctx->text.insertPos, ctx->text.insertPos); - - prevSalt = 0; - for (salt = ctx->text.salt; 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) { - XtFree ((char *) salt->s.selections); - XtFree (salt->contents); - if (prevSalt) - prevSalt->next = nextSalt; - else - ctx->text.salt = nextSalt; - XtFree((char *)salt); - } - else - prevSalt = salt; - } -} - -void -_XawTextSaltAwaySelection(TextWidget ctx, Atom *selections, int num_atoms) -{ - XawTextSelectionSalt *salt; - int i, j; - - for (i = 0; i < num_atoms; i++) - TextLoseSelection((Widget)ctx, selections + i); - if (num_atoms == 0) - return; - salt = (XawTextSelectionSalt *) - XtMalloc((unsigned)sizeof(XawTextSelectionSalt)); - if (!salt) - return; - salt->s.selections = (Atom *)XtMalloc((unsigned)(num_atoms * sizeof(Atom))); - if (!salt->s.selections) { - XtFree((char *)salt); - return; - } - salt->s.left = ctx->text.s.left; - salt->s.right = ctx->text.s.right; - salt->s.type = ctx->text.s.type; - salt->contents = _XawTextGetSTRING(ctx, ctx->text.s.left, ctx->text.s.right); - if (XawTextFormat(ctx, XawFmtWide)) { - XTextProperty textprop; - if (XwcTextListToTextProperty(XtDisplay((Widget)ctx), - (wchar_t**)(&(salt->contents)), 1, - XCompoundTextStyle, - &textprop) < Success) { - XtFree(salt->contents); - salt->length = 0; - return; - } - XtFree(salt->contents); - salt->contents = (char *)textprop.value; - salt->length = textprop.nitems; - } - else - salt->length = strlen (salt->contents); - salt->next = ctx->text.salt; - ctx->text.salt = salt; - j = 0; - for (i = 0; i < num_atoms; i++) { - if (GetCutBufferNumber (selections[i]) == NOT_A_CUT_BUFFER) { - salt->s.selections[j++] = selections[i]; - XtOwnSelection((Widget)ctx, selections[i], ctx->text.time, - TextConvertSelection, TextLoseSelection, NULL); - } - } - salt->s.atom_count = j; -} - -static void -_SetSelection(TextWidget ctx, XawTextPosition left, XawTextPosition right, - Atom *selections, Cardinal count) -{ -#ifndef OLDXAW - Cardinal i; - XawTextPosition pos; - TextSrcObject src = (TextSrcObject)ctx->text.source; - - for (i = 0; i < src->textSrc.num_text; i++) { - TextWidget tw = (TextWidget)src->textSrc.text[i]; - Bool needs_updating = tw->text.old_insert < 0; - Bool showposition = tw->text.showposition; - - if (needs_updating) { - tw->text.showposition = False; - _XawTextPrepareToUpdate(tw); - } -#else - TextWidget tw = ctx; - XawTextPosition pos; -#endif /* OLDXAW */ - - if (left < tw->text.s.left) { - pos = Min(right, tw->text.s.left); - _XawTextNeedsUpdating(tw, left, pos); - } - if (left > tw->text.s.left) { - pos = Min(left, tw->text.s.right); - _XawTextNeedsUpdating(tw, tw->text.s.left, pos); - } - if (right < tw->text.s.right) { - pos = Max(right, tw->text.s.left); - _XawTextNeedsUpdating(tw, pos, tw->text.s.right); - } - if (right > tw->text.s.right) { - pos = Max(left, tw->text.s.right); - _XawTextNeedsUpdating(tw, pos, right); - } - - tw->text.s.left = left; - tw->text.s.right = right; - -#ifndef OLDXAW - if (needs_updating) { - _XawTextExecuteUpdate(tw); - tw->text.showposition = showposition; - } - } -#endif /* OLDXAW */ - - SrcSetSelection(ctx->text.source, left, right, - (count == 0) ? None : selections[0]); - - if (left < right) { - Widget w = (Widget)ctx; - int buffer; - - while (count) { - Atom selection = selections[--count]; - - /* - * If this is a cut buffer - */ - if ((buffer = GetCutBufferNumber(selection)) != NOT_A_CUT_BUFFER) { - unsigned char *ptr, *tptr; - unsigned int amount, max_len = MAX_CUT_LEN(XtDisplay(w)); - unsigned long len; - - tptr= ptr= (unsigned char *)_XawTextGetSTRING(ctx, - ctx->text.s.left, - ctx->text.s.right); - if (XawTextFormat(ctx, XawFmtWide)) { - /* - * Only XA_STRING(Latin 1) is allowed in CUT_BUFFER, - * so we get it from wchar string, then free the wchar string - */ - XTextProperty textprop; - - if (XwcTextListToTextProperty(XtDisplay(w), (wchar_t**)&ptr, - 1, XStringStyle, &textprop) - < Success){ - XtFree((char *)ptr); - return; - } - XtFree((char *)ptr); - tptr = ptr = textprop.value; - } - if (buffer == 0) { - _CreateCutBuffers(XtDisplay(w)); - XRotateBuffers(XtDisplay(w), 1); - } - amount = Min ((len = strlen((char *)ptr)), max_len); - XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0), - selection, XA_STRING, 8, PropModeReplace, - ptr, amount); - - while (len > max_len) { - len -= max_len; - tptr += max_len; - amount = Min (len, max_len); - XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0), - selection, XA_STRING, 8, PropModeAppend, - tptr, amount); - } - XtFree ((char *)ptr); - } - else /* This is a real selection */ - XtOwnSelection(w, selection, ctx->text.time, TextConvertSelection, - TextLoseSelection, NULL); - } - } - else - XawTextUnsetSelection((Widget)ctx); -} - -#ifndef OLDXAW -void -_XawTextSetLineAndColumnNumber(TextWidget ctx, Bool force) -{ - int line_number, column_number; - - if (ctx->text.old_insert != ctx->text.insertPos && - ctx->text.lt.base_line < 0) { - ctx->text.lt.base_line = 0; - (void)_BuildLineTable(ctx, ctx->text.lt.top, 0); - } - - line_number = ResolveLineNumber(ctx); - column_number = ResolveColumnNumber(ctx); - - if (force || (ctx->text.column_number != column_number - || ctx->text.line_number != line_number)) { - XawTextPositionInfo info; - - ctx->text.line_number = info.line_number = line_number; - ctx->text.column_number = info.column_number = column_number; - info.insert_position = ctx->text.insertPos; - info.last_position = ctx->text.lastPos; - info.overwrite_mode = ctx->text.overwrite; - - XtCallCallbacks((Widget)ctx, XtNpositionCallback, (XtPointer)&info); - } -} - -static int -ResolveColumnNumber(TextWidget ctx) -{ - Widget src = ctx->text.source; - short column_number = 0; - XawTextPosition position; - XawTextBlock block; - unsigned long format = _XawTextFormat(ctx); - 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; - - if (ctx->text.lt.base_line < 1) - return (ctx->text.column_number); - - position = SrcScan(src, ctx->text.insertPos, XawstEOL, XawsdLeft, 1, False); - XawTextSourceRead(src, position, &block, ctx->text.insertPos - position); - - for (; position < ctx->text.insertPos; position++) { - if (position - block.firstPos >= block.length) - XawTextSourceRead(src, position, &block, ctx->text.insertPos - position); - if ((format == XawFmt8Bit && block.ptr[position - block.firstPos] == '\t') || - (format == XawFmtWide && ((wchar_t*)block.ptr)[position - block.firstPos] == _Xaw_atowc(XawTAB))) { - while (tab_base + tab_column <= column_number) { - if (tab_count) { - for (; tab_index < tab_count; ++tab_index) - if (tab_base + char_tabs[tab_index] > column_number) { - tab_column = char_tabs[tab_index]; - break; - } - if (tab_index >= tab_count) { - tab_base += char_tabs[tab_count - 1]; - tab_column = tab_index = 0; - } - } - else - tab_column += DEFAULT_TAB_SIZE; - } - column_number = tab_base + tab_column; - } - else - ++column_number; - if (column_number >= 16384) { - column_number = 16383; - break; - } - } - - return (column_number); -} -#endif /* OLDXAW */ - -void -_XawTextSourceChanged(Widget w, XawTextPosition left, XawTextPosition right, - XawTextBlock *block, int lines) -{ - TextWidget ctx = (TextWidget)w; - Widget src = ctx->text.source; - XawTextPosition update_from, update_to, top; - Boolean update_disabled; - int delta, line, line_from; - - if (left < ctx->text.old_insert) { - XawTextPosition old_insert = ctx->text.old_insert; - - if (right < ctx->text.old_insert) - old_insert -= right - left; - else - old_insert = left; - - ctx->text.insertPos = old_insert + block->length; - } -#ifndef OLDXAW - if (left <= ctx->text.lt.top) { - if (left + block->length - (right - left) < ctx->text.lt.top) { - ctx->text.source_changed = SRC_CHANGE_BEFORE; - ctx->text.lt.base_line += lines; - } - else - ctx->text.source_changed = SRC_CHANGE_OVERLAP; - } - else - ctx->text.source_changed = SRC_CHANGE_AFTER; -#endif - - update_from = left; - update_to = left + block->length; - update_to = SrcScan(src, update_to, XawstEOL, XawsdRight, 1, False); - delta = block->length - (right - left); - if (delta < 0) - ctx->text.clear_to_eol = True; - if (update_to == update_from) - ++update_to; - update_disabled = ctx->text.update_disabled; - ctx->text.update_disabled = True; - ctx->text.lastPos = XawTextGetLastPosition(ctx); - top = ctx->text.lt.info[0].position; - - XawTextUnsetSelection((Widget)ctx); - - if (delta) { - int i; - XmuSegment *seg; - - for (seg = ctx->text.update->segment; seg; seg = seg->next) { - if (seg->x1 > (int)left) - break; - else if (seg->x2 > (int)left) { - seg->x2 += delta; - seg = seg->next; - break; - } - } - for (; seg; seg = seg->next) { - seg->x1 += delta; - seg->x2 += delta; - } - XmuOptimizeScanline(ctx->text.update); - - for (i = 0; i <= ctx->text.lt.lines; i++) - if (ctx->text.lt.info[i].position > left) - break; - for (; i <= ctx->text.lt.lines; i++) - ctx->text.lt.info[i].position += delta; - } - - if (top != ctx->text.lt.info[0].position) { - line_from = line = 0; - ctx->text.lt.top = top = SrcScan(src, ctx->text.lt.info[0].position, - XawstEOL, XawsdLeft, 1, False); - update_from = top; - } - else { - line_from = line = LineForPosition(ctx, update_from + delta); - top = ctx->text.lt.info[line].position; - } - - if (line > 0 && ctx->text.wrap == XawtextWrapWord) { - --line; - top = ctx->text.lt.info[line].position; - } - - (void)_BuildLineTable(ctx, top, line); - - if (ctx->text.wrap == XawtextWrapWord) { - if (line_from != LineForPosition(ctx, update_from) - || line_from != LineForPosition(ctx, update_to)) { - ctx->text.clear_to_eol = True; - update_from = SrcScan(src, update_from, - XawstWhiteSpace, XawsdLeft, 1, True); - if (update_to >= ctx->text.lastPos) - /* this is not an error, it just tells _BuildLineTable to - * clear to the bottom of the window. The value of update_to - * should not be > ctx->text.lastPos. - */ - ++update_to; - } - } - else if (!ctx->text.clear_to_eol) { - if (LineForPosition(ctx, update_from) - != LineForPosition(ctx, update_to)) - ctx->text.clear_to_eol = True; - } - - _XawTextNeedsUpdating(ctx, update_from, update_to); - ctx->text.update_disabled = update_disabled; -} - -/* - * Function: - * _XawTextReplace - * - * Parameters: - * ctx - text widget - * left - left offset - * right - right offset - * block - text block - * - * Description: - * Replaces the text between left and right by the text in block. - * Does all the required calculations of offsets, and rebuild the - * the line table, from the insertion point (or previous line, if - * wrap mode is 'word'). - * - * Returns: - * XawEditDone - success - * any other value - error code - */ -int -_XawTextReplace(TextWidget ctx, XawTextPosition left, XawTextPosition right, - XawTextBlock *block) -{ - Arg args[1]; - Widget src; - XawTextEditType edit_mode; - - if (left == right && block->length == 0) - return (XawEditDone); - - src = ctx->text.source; - XtSetArg(args[0], XtNeditType, &edit_mode); - XtGetValues(src, args, 1); - - if (edit_mode == XawtextAppend) { - if (block->length == 0) - return (XawEditError); - ctx->text.insertPos = ctx->text.lastPos; - } - -#ifndef OLDXAW - return (SrcReplace(src, left, right, block)); -#else - if (SrcReplace(src, left, right, block) == XawEditDone) { - _XawTextSourceChanged((Widget)ctx, left, right, block, 0); - - return (XawEditDone); - } - - return (XawEditError); -#endif -} - -/* - * This routine will display text between two arbitrary source positions. - * In the event that this span contains highlighted text for the selection, - * only that portion will be displayed highlighted. - */ -static void -OldDisplayText(Widget w, XawTextPosition left, XawTextPosition right) -{ - static XmuSegment segment; - static XmuScanline next; - static XmuScanline scanline = {0, &segment, &next}; - static XmuArea area = {&scanline}; - - TextWidget ctx = (TextWidget)w; - int x, y, line; - XawTextPosition start, end, last, final; - XmuScanline *scan; - XmuSegment *seg; - XmuArea *clip = NULL; - Bool cleol = ctx->text.clear_to_eol; - Bool has_selection = ctx->text.s.right > ctx->text.s.left; - - left = left < ctx->text.lt.top ? ctx->text.lt.top : left; - - if (left > right || !LineAndXYForPosition(ctx, left, &line, &x, &y)) - return; - - last = XawTextGetLastPosition(ctx); - segment.x2 = (int)XtWidth(ctx) - ctx->text.r_margin.right; - - if (cleol) - clip = XmuCreateArea(); - - for (start = left; start < right && line < ctx->text.lt.lines; line++) { - if ((end = ctx->text.lt.info[line + 1].position) > right) - end = right; - - final = end; - if (end > last) - end = last; - - if (end > start) { - if (!has_selection - || (start >= ctx->text.s.right || end <= ctx->text.s.left)) - _XawTextSinkDisplayText(ctx->text.sink, x, y, start, end, False); - else if (start >= ctx->text.s.left && end <= ctx->text.s.right) - _XawTextSinkDisplayText(ctx->text.sink, x, y, start, end, True); - else { - OldDisplayText(w, start, ctx->text.s.left); - OldDisplayText(w, Max(start, ctx->text.s.left), - Min(end, ctx->text.s.right)); - OldDisplayText(w, ctx->text.s.right, end); - } - } - - x = ctx->text.left_margin; - if (cleol) { - segment.x1 = ctx->text.lt.info[line].textWidth + x; - if (XmuValidSegment(&segment)) { - scanline.y = y; - next.y = ctx->text.lt.info[line + 1].y; - XmuAreaOr(clip, &area); - } - } - - start = final; - y = ctx->text.lt.info[line + 1].y; - } - - if (cleol) { - for (scan = clip->scanline; scan && scan->next; scan = scan->next) - for (seg = scan->segment; seg; seg = seg->next) - SinkClearToBG(ctx->text.sink, - seg->x1, scan->y, - seg->x2 - seg->x1, scan->next->y - scan->y); - XmuDestroyArea(clip); - } -} - -#ifndef OLDXAW -/*ARGSUSED*/ -static void -DisplayText(Widget w, XawTextPosition left, XawTextPosition right) -{ - static XmuSegment segment; - static XmuScanline next; - static XmuScanline scanline = {0, &segment, &next}; - static XmuArea area = {&scanline}; - - TextWidget ctx = (TextWidget)w; - int y, line; - XawTextPosition from, to, lastPos; - Bool cleol = ctx->text.clear_to_eol; - Bool has_selection = ctx->text.s.right > ctx->text.s.left; - XawTextPaintList *paint_list; - - left = left < ctx->text.lt.top ? ctx->text.lt.top : left; - - if (left > right || !IsPositionVisible(ctx, left)) - return; - - line = LineForPosition(ctx, left); - y = ctx->text.lt.info[line].y; - segment.x2 = (int)XtWidth(ctx) - ctx->text.r_margin.right; - lastPos = XawTextGetLastPosition(ctx); - - paint_list = ((TextSinkObject)ctx->text.sink)->text_sink.paint; - - for (from = left; from < right && line < ctx->text.lt.lines; line++) { - if ((to = ctx->text.lt.info[line + 1].position) > right) - to = right; - - if (to > lastPos) - to = lastPos; - - if (from < to) { - if (!has_selection - || (from >= ctx->text.s.right || to <= ctx->text.s.left)) - XawTextSinkPreparePaint(ctx->text.sink, y, line, from, to, False); - else if (from >= ctx->text.s.left && to <= ctx->text.s.right) - XawTextSinkPreparePaint(ctx->text.sink, y, line, from, to, True); - else { - XawTextSinkPreparePaint(ctx->text.sink, y, line, from, - ctx->text.s.left, False); - XawTextSinkPreparePaint(ctx->text.sink, y, line, - XawMax(from, ctx->text.s.left), - XawMin(to, ctx->text.s.right), True); - XawTextSinkPreparePaint(ctx->text.sink, y, line, - ctx->text.s.right, to, False); - } - } - - if (cleol) { - segment.x1 = ctx->text.lt.info[line].textWidth + ctx->text.left_margin; - if (XmuValidSegment(&segment)) { - scanline.y = y; - next.y = ctx->text.lt.info[line + 1].y; - XmuAreaOr(paint_list->clip, &area); - } - } - y = ctx->text.lt.info[line + 1].y; - from = to; - } - - /* clear to the bottom of the window */ - if (cleol && line >= ctx->text.lt.lines) { - segment.x1 = ctx->text.left_margin; - if (XmuValidSegment(&segment)) { - scanline.y = y; - next.y = (int)XtHeight(ctx) - (int)ctx->text.margin.bottom; - XmuAreaOr(paint_list->clip, &area); - } - } -} -#endif - -/* - * This routine implements multi-click selection in a hardwired manner. - * It supports multi-click entity cycling (char, word, line, file) and mouse - * motion adjustment of the selected entitie (i.e. select a word then, with - * button still down, adjust wich word you really meant by moving the mouse). - * [NOTE: This routine is to be replaced by a set of procedures that - * will allows clients to implements a wide class of draw through and - * multi-click selection user interfaces.] - */ -static void -DoSelection(TextWidget ctx, XawTextPosition pos, Time time, Bool motion) -{ - XawTextPosition newLeft, newRight; - XawTextSelectType newType, *sarray; - Widget src = ctx->text.source; - - if (motion) - newType = ctx->text.s.type; - else { - if ((abs((long) time - (long) ctx->text.lasttime) < MULTI_CLICK_TIME) - && (pos >= ctx->text.s.left && pos <= ctx->text.s.right)) { - sarray = ctx->text.sarray; - for (; *sarray != XawselectNull && *sarray != ctx->text.s.type; - sarray++) - ; - if (*sarray == XawselectNull) - newType = *(ctx->text.sarray); - else { - newType = *(sarray + 1); - if (newType == XawselectNull) - newType = *(ctx->text.sarray); - } - } - else /* single-click event */ - newType = *(ctx->text.sarray); - - ctx->text.lasttime = time; - } - switch (newType) { - case XawselectPosition: - newLeft = newRight = pos; - break; - case XawselectChar: - newLeft = pos; - newRight = SrcScan(src, pos, XawstPositions, XawsdRight, 1, False); - break; - case XawselectWord: - case XawselectParagraph: - case XawselectAlphaNumeric: { - XawTextScanType stype; - - if (newType == XawselectWord) - stype = XawstWhiteSpace; - else if (newType == XawselectParagraph) - stype = XawstParagraph; - else - stype = XawstAlphaNumeric; - - /* - * Somewhat complicated, but basically I treat the space between - * two objects as another object. The object that I am currently - * in then becomes the end of the selection. - * - * Chris Peterson - 4/19/90. - */ - newRight = SrcScan(ctx->text.source, pos, stype, - XawsdRight, 1, False); - newRight = SrcScan(ctx->text.source, newRight, stype, - XawsdLeft, 1, False); - - if (pos != newRight) - newLeft = SrcScan(ctx->text.source, pos, stype, - XawsdLeft, 1, False); - else - newLeft = pos; - - newLeft =SrcScan(ctx->text.source, newLeft, stype, - XawsdRight, 1, False); - - if (newLeft > newRight) { - XawTextPosition temp = newLeft; - newLeft = newRight; - newRight = temp; - } - } break; - case XawselectLine: - newLeft = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False); - newRight = SrcScan(src, pos, XawstEOL, XawsdRight, 1, False); - break; - case XawselectAll: - newLeft = SrcScan(src, pos, XawstAll, XawsdLeft, 1, False); - newRight = SrcScan(src, pos, XawstAll, XawsdRight, 1, False); - break; - default: - XtAppWarning(XtWidgetToApplicationContext((Widget) ctx), - "Text Widget: empty selection array."); - return; - } - - if (newLeft != ctx->text.s.left || newRight != ctx->text.s.right - || newType != ctx->text.s.type) { - ModifySelection(ctx, newLeft, newRight); - if (pos - ctx->text.s.left < ctx->text.s.right - pos) - ctx->text.insertPos = newLeft; - else - ctx->text.insertPos = newRight; - ctx->text.s.type = newType; - } - if (!motion) { /* setup so we can freely mix select extend calls*/ - ctx->text.origSel.type = ctx->text.s.type; - ctx->text.origSel.left = ctx->text.s.left; - ctx->text.origSel.right = ctx->text.s.right; - - if (pos >= ctx->text.s.left + (ctx->text.s.right - ctx->text.s.left) / 2) - ctx->text.extendDir = XawsdRight; - else - ctx->text.extendDir = XawsdLeft; - } -} - -/* - * This routine implements extension of the currently selected text in - * the "current" mode (i.e. char word, line, etc.). It worries about - * extending from either end of the selection and handles the case when you - * cross through the "center" of the current selection (e.g. switch which - * end you are extending!). - */ -static void -ExtendSelection(TextWidget ctx, XawTextPosition pos, Bool motion) -{ - XawTextScanDirection dir; - - if (!motion) { /* setup for extending selection */ - if (ctx->text.s.left == ctx->text.s.right) /* no current selection. */ - ctx->text.s.left = ctx->text.s.right = ctx->text.insertPos; - else { - ctx->text.origSel.left = ctx->text.s.left; - ctx->text.origSel.right = ctx->text.s.right; - } - - ctx->text.origSel.type = ctx->text.s.type; - - if (pos >= ctx->text.s.left + (ctx->text.s.right - ctx->text.s.left) / 2) - ctx->text.extendDir = XawsdRight; - else - ctx->text.extendDir = XawsdLeft; - } - else /* check for change in extend direction */ - if ((ctx->text.extendDir == XawsdRight && - pos <= ctx->text.origSel.left) || - (ctx->text.extendDir == XawsdLeft && - pos >= ctx->text.origSel.right)) { - ctx->text.extendDir = (ctx->text.extendDir == XawsdRight) ? - XawsdLeft : XawsdRight; - ModifySelection(ctx, ctx->text.origSel.left, ctx->text.origSel.right); - } - - dir = ctx->text.extendDir; - switch (ctx->text.s.type) { - case XawselectWord: - case XawselectParagraph: - case XawselectAlphaNumeric: { - XawTextPosition left_pos, right_pos; - XawTextScanType stype; - - if (ctx->text.s.type == XawselectWord) - stype = XawstWhiteSpace; - else if (ctx->text.s.type == XawselectParagraph) - stype = XawstParagraph; - else - stype = XawstAlphaNumeric; - - /* - * Somewhat complicated, but basically I treat the space between - * two objects as another object. The object that I am currently - * in then becomes the end of the selection. - * - * Chris Peterson - 4/19/90. - */ - right_pos = SrcScan(ctx->text.source, pos, stype, - XawsdRight, 1, False); - right_pos =SrcScan(ctx->text.source, right_pos, stype, - XawsdLeft, 1, False); - - if (pos != right_pos) - left_pos = SrcScan(ctx->text.source, pos, stype, - XawsdLeft, 1, False); - else - left_pos = pos; - - left_pos =SrcScan(ctx->text.source, left_pos, stype, - XawsdRight, 1, False); - - if (dir == XawsdLeft) - pos = Min(left_pos, right_pos); - else /* dir == XawsdRight */ - pos = Max(left_pos, right_pos); - } break; - case XawselectLine: - pos = SrcScan(ctx->text.source, pos, XawstEOL, - dir, 1, dir == XawsdRight); - break; - case XawselectAll: - pos = ctx->text.insertPos; - /*FALLTHROUGH*/ - case XawselectPosition: - default: - break; - } - - if (dir == XawsdRight) - ModifySelection(ctx, ctx->text.s.left, pos); - else - ModifySelection(ctx, pos, ctx->text.s.right); - - ctx->text.insertPos = pos; -} - -/* - * Function: - * _XawTextClearAndCenterDisplay - * - * Parameters: - * ctx - text widget - * - * Description: - * Redraws the display with the cursor in insert point - * centered vertically. - */ -void -_XawTextClearAndCenterDisplay(TextWidget ctx) -{ - int left_margin = ctx->text.left_margin; - Bool visible = IsPositionVisible(ctx, ctx->text.insertPos); - - _XawTextShowPosition(ctx); - - if (XtIsRealized((Widget)ctx) && visible && - left_margin == ctx->text.left_margin) { - int insert_line = LineForPosition(ctx, ctx->text.insertPos); - int scroll_by = insert_line - (ctx->text.lt.lines >> 1); - Boolean clear_to_eol = ctx->text.clear_to_eol; - - XawTextScroll(ctx, scroll_by, 0); - SinkClearToBG(ctx->text.sink, 0, 0, XtWidth(ctx), XtHeight(ctx)); - ClearWindow(ctx); - clear_to_eol = ctx->text.clear_to_eol; - ctx->text.clear_to_eol = False; - FlushUpdate(ctx); - ctx->text.clear_to_eol = clear_to_eol; - } -} - -/* - * Internal redisplay entire window - * Legal to call only if widget is realized - */ -static void -DisplayTextWindow(Widget w) -{ - TextWidget ctx = (TextWidget)w; - - _XawTextBuildLineTable(ctx, ctx->text.lt.top, False); - ClearWindow(ctx); -} - -static void -TextSinkResize(Widget w) -{ - if (w && XtClass(w)->core_class.resize) - XtClass(w)->core_class.resize(w); -} - -/* ARGSUSED */ -void -_XawTextCheckResize(TextWidget ctx) -{ - return; -} - -/* - * Converts (params, num_params) to a list of atoms & caches the - * list in the TextWidget instance. - */ -Atom * -_XawTextSelectionList(TextWidget ctx, String *list, Cardinal nelems) -{ - Atom *sel = ctx->text.s.selections; - Display *dpy = XtDisplay((Widget)ctx); - int n; - - if (nelems > (Cardinal)ctx->text.s.array_size) { - sel = (Atom *)XtRealloc((char *)sel, sizeof(Atom) * nelems); - ctx->text.s.array_size = nelems; - ctx->text.s.selections = sel; - } - for (n = nelems; --n >= 0; sel++, list++) - *sel = XInternAtom(dpy, *list, False); - ctx->text.s.atom_count = nelems; - - return (ctx->text.s.selections); -} - -/* - * Function: - * SetSelection - * - * Parameters: - * ctx - text widget - * defaultSel - default selection - * l - left and right ends of the selection - * r - "" - * list - the selection list (as strings). - * nelems - "" - * - * Description: - * Sets the current selection. - * - * Note: - * if (ctx->text.s.left >= ctx->text.s.right) then the selection is unset - */ -void -_XawTextSetSelection(TextWidget ctx, XawTextPosition l, XawTextPosition r, - String *list, Cardinal nelems) -{ - if (nelems == 1 && !strcmp (list[0], "none")) - return; - if (nelems == 0) { - String defaultSel = "PRIMARY"; - list = &defaultSel; - nelems = 1; - } - _SetSelection(ctx, l, r, _XawTextSelectionList(ctx, list, nelems), nelems); -} - -/* - * Function: - * ModifySelection - * - * Parameters: - * ctx - text widget - * left - left and right ends of the selection - * right - "" - * - * Description: - * Modifies the current selection. - * - * Note: - * if (ctx->text.s.left >= ctx->text.s.right) then the selection is unset - */ -static void -ModifySelection(TextWidget ctx, XawTextPosition left, XawTextPosition right) -{ - if (left == right) - ctx->text.insertPos = left; - _SetSelection(ctx, left, right, NULL, 0); -} - -/* - * This routine is used to perform various selection functions. The goal is - * to be able to specify all the more popular forms of draw-through and - * multi-click selection user interfaces from the outside. - */ -void -_XawTextAlterSelection(TextWidget ctx, XawTextSelectionMode mode, - XawTextSelectionAction action, String *params, - Cardinal *num_params) -{ - XawTextPosition position; - Boolean flag; - - /* - * This flag is used by TextPop.c:DoReplace() to determine if the selection - * is okay to use, or if it has been modified. - */ - if (ctx->text.search != NULL) - ctx->text.search->selection_changed = True; - - position = PositionForXY(ctx, (int) ctx->text.ev_x, (int) ctx->text.ev_y); - - flag = (action != XawactionStart); - if (mode == XawsmTextSelect) - DoSelection(ctx, position, ctx->text.time, flag); - else /* mode == XawsmTextExtend */ - ExtendSelection (ctx, position, flag); - - if (action == XawactionEnd) - _XawTextSetSelection(ctx, ctx->text.s.left, ctx->text.s.right, - params, *num_params); -} - -/* - * Function: - * UpdateTextInRectangle - * - * Parameters: - * ctx - the text widget - * rect - rectangle - * - * Description: - * Updates the text in the given rectangle - */ -static void -UpdateTextInRectangle(TextWidget ctx, XRectangle *rect) -{ - XawTextLineTable *lt; - int line, y1, y2, x2; - - y1 = rect->y; - y2 = y1 + rect->height; - x2 = rect->x + rect->width; - - for (line = 0, lt = &ctx->text.lt; line < lt->lines; line++) - if (lt->info[line + 1].y > y1) - break; - for (; line <= lt->lines; line++) { - if (lt->info[line].y > y2) - break; - UpdateTextInLine(ctx, line, rect->x, x2); - } -} - -/* - * This routine processes all "expose region" XEvents. In general, its job - * is to the best job at minimal re-paint of the text, displayed in the - * window, that it can. - */ -/* ARGSUSED */ -static void -XawTextExpose(Widget w, XEvent *event, Region region) -{ - TextWidget ctx = (TextWidget)w; - Boolean clear_to_eol; - XRectangle expose; - - if (event->type == Expose) { - expose.x = event->xexpose.x; - expose.y = event->xexpose.y; - expose.width = event->xexpose.width; - expose.height = event->xexpose.height; - } - else if (event->type == GraphicsExpose) { - expose.x = event->xgraphicsexpose.x; - expose.y = event->xgraphicsexpose.y; - expose.width = event->xgraphicsexpose.width; - expose.height = event->xgraphicsexpose.height; - } - else - return; - - _XawTextPrepareToUpdate(ctx); - - if (Superclass->core_class.expose) - (*Superclass->core_class.expose)(w, event, region); - - clear_to_eol = ctx->text.clear_to_eol; - ctx->text.clear_to_eol = False; - - UpdateTextInRectangle(ctx, &expose); - XawTextSinkGetCursorBounds(ctx->text.sink, &expose); - UpdateTextInRectangle(ctx, &expose); - SinkClearToBG(ctx->text.sink, expose.x, expose.y, - expose.width, expose.height); - _XawTextExecuteUpdate(ctx); - ctx->text.clear_to_eol = clear_to_eol; -} - -/* - * This routine does all setup required to syncronize batched screen updates - */ -void -_XawTextPrepareToUpdate(TextWidget ctx) -{ - if (ctx->text.old_insert < 0) { - InsertCursor((Widget)ctx, XawisOff); - ctx->text.showposition = False; - ctx->text.old_insert = ctx->text.insertPos; - ctx->text.clear_to_eol = False; -#ifndef OLDXAW - ctx->text.source_changed = SRC_CHANGE_NONE; -#endif - } -} - -/* - * This is a private utility routine used by _XawTextExecuteUpdate. It - * processes all the outstanding update requests and merges update - * ranges where possible. - */ -static void -FlushUpdate(TextWidget ctx) -{ - XmuSegment *seg; - void (*display_text)(Widget, XawTextPosition, XawTextPosition); - - if (XtIsRealized((Widget)ctx)) { - ctx->text.s.right = XawMin(ctx->text.s.right, ctx->text.lastPos); - ctx->text.s.left = XawMin(ctx->text.s.left, ctx->text.s.right); - -#ifndef OLDXAW - if (XawTextSinkBeginPaint(ctx->text.sink) == False) -#endif - display_text = OldDisplayText; -#ifndef OLDXAW - else - display_text = DisplayText; -#endif - for (seg = ctx->text.update->segment; seg; seg = seg->next) - (*display_text)((Widget)ctx, - (XawTextPosition)seg->x1, - (XawTextPosition)seg->x2); -#ifndef OLDXAW - if (display_text != OldDisplayText) { - XawTextSinkDoPaint(ctx->text.sink); - XawTextSinkEndPaint(ctx->text.sink); - } -#endif - } - (void)XmuScanlineXor(ctx->text.update, ctx->text.update); -} - -static int -CountLines(TextWidget ctx, XawTextPosition left, XawTextPosition right) -{ - if (ctx->text.wrap == XawtextWrapNever || left >= right) - return (1); - else { - XawTextPosition tmp; - int dim, lines = 0, wwidth = GetMaxTextWidth(ctx); - - while (left < right) { - tmp = left; - XawTextSinkFindPosition(ctx->text.sink, left, - ctx->text.left_margin, - wwidth, ctx->text.wrap == XawtextWrapWord, - &left, &dim, &dim); - ++lines; - if (tmp == left) - ++left; - } - - return (lines); - } - /*NOTREACHED*/ -} - -static int -GetMaxTextWidth(TextWidget ctx) -{ - XRectangle cursor; - int width; - - XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); - width = (int)XtWidth(ctx) - RHMargins(ctx) - cursor.width; - - return (XawMax(0, width)); -} - -/* - * Function: - * _XawTextShowPosition - * - * Parameters: - * ctx - the text widget to show the position - * - * Description: - * Makes sure the text cursor visible, scrolling the text window - * if required. - */ -void -_XawTextShowPosition(TextWidget ctx) -{ - /* - * Variable scroll is used to avoid scanning large files to calculate - * line offsets - */ - int hpixels, vlines; - XawTextPosition first, last, top, tmp; - Bool visible, scroll; - - if (!XtIsRealized((Widget)ctx)) - return; - - /* - * Checks if a horizontal scroll is required - */ - if (ctx->text.wrap == XawtextWrapNever) { - int x, vwidth, distance, dim; - XRectangle rect; - - vwidth = (int)XtWidth(ctx) - RHMargins(ctx); - last = SrcScan(ctx->text.source, ctx->text.insertPos, - XawstEOL, XawsdLeft, 1, False); - XawTextSinkFindDistance(ctx->text.sink, last, - ctx->text.left_margin, - ctx->text.insertPos, - &distance, &first, &dim); - XawTextSinkGetCursorBounds(ctx->text.sink, &rect); - x = ctx->text.left_margin - ctx->text.r_margin.left; - - if (x + distance + rect.width > vwidth) - hpixels = x + distance + rect.width - vwidth + (vwidth >> 2); - else if (x + distance < 0) - hpixels = x + distance - (vwidth >> 2); - else - hpixels = 0; - } - else - hpixels = 0; - - visible = IsPositionVisible(ctx, ctx->text.insertPos); - - /* - * If the cursor is already visible - */ - if (!hpixels && visible) - return; - - scroll = ctx->core.background_pixmap == XtUnspecifiedPixmap && !hpixels; - vlines = 0; - first = ctx->text.lt.top; - - /* - * Needs to scroll the text window - */ - if (visible) - top = ctx->text.lt.top; - else { - top = SrcScan(ctx->text.source, ctx->text.insertPos, - XawstEOL, XawsdLeft, 1, False); - - /* - * Finds the nearest left position from ctx->text.insertPos - */ - if (ctx->text.wrap != XawtextWrapNever) { - int dim, vwidth = GetMaxTextWidth(ctx); - - last = top; - /*CONSTCOND*/ - while (1) { - tmp = last; - XawTextSinkFindPosition(ctx->text.sink, last, - ctx->text.left_margin, vwidth, - ctx->text.wrap == XawtextWrapWord, - &last, &dim, &dim); - if (last == tmp) - ++last; - if (last <= ctx->text.insertPos) - top = last; - else - break; - } - } - } - - if (scroll) { - if (ctx->text.insertPos < first) { /* Scroll Down */ - while (first > top) { - last = first; - first = SrcScan(ctx->text.source, first, - XawstEOL, XawsdLeft, 2, False); - vlines -= CountLines(ctx, first, last); - if (-vlines >= ctx->text.lt.lines) { - scroll = False; - break; - } - } - } - else if (!visible) { /* Scroll Up */ - while (first < top) { - last = first; - first = SrcScan(ctx->text.source, first, - XawstEOL, XawsdRight, 1, True); - vlines += CountLines(ctx, last, first); - if (vlines > ctx->text.lt.lines) { - scroll = False; - break; - } - } - } - else - scroll = False; - } - - /* - * If a portion of the text that will be scrolled is visible - */ - if (scroll) - XawTextScroll(ctx, vlines ? vlines - (ctx->text.lt.lines >> 1) : 0, 0); - /* - * Else redraw the entire text window - */ - else { - ctx->text.left_margin -= hpixels; - if (ctx->text.left_margin > ctx->text.r_margin.left) - ctx->text.left_margin = ctx->text.margin.left = - ctx->text.r_margin.left; - - if (!visible) { - vlines = ctx->text.lt.lines >> 1; - if (vlines) - top = SrcScan(ctx->text.source, ctx->text.insertPos, - XawstEOL, XawsdLeft, vlines + 1, False); - - if (ctx->text.wrap != XawtextWrapNever) { - int dim; - int n_lines = CountLines(ctx, top, ctx->text.insertPos); - int vwidth = GetMaxTextWidth(ctx); - - while (n_lines-- > vlines) { - tmp = top; - XawTextSinkFindPosition(ctx->text.sink, top, - ctx->text.left_margin, - vwidth, - ctx->text.wrap == XawtextWrapWord, - &top, &dim, &dim); - if (tmp == top) - ++top; - } - } - _XawTextBuildLineTable(ctx, top, True); - } - else - ClearWindow(ctx); - } - ctx->text.clear_to_eol = True; -} - -#ifndef OLDXAW -static int -ResolveLineNumber(TextWidget ctx) -{ - int line_number = ctx->text.lt.base_line; - XawTextPosition position = ctx->text.lt.top; - - if (ctx->text.lt.base_line < 1) - return (ctx->text.line_number); - - if (ctx->text.wrap == XawtextWrapNever - && IsPositionVisible(ctx, ctx->text.insertPos)) - line_number += LineForPosition(ctx, ctx->text.insertPos); - else if (position < ctx->text.insertPos) { - while (position < ctx->text.insertPos) { - position = SrcScan(ctx->text.source, position, - XawstEOL, XawsdRight, 1, True); - if (position <= ctx->text.insertPos) { - ++line_number; - if (position == ctx->text.lastPos) { - line_number -= !_XawTextSourceNewLineAtEOF(ctx->text.source); - break; - } - } - } - } - else if (position > ctx->text.insertPos) { - while (position > ctx->text.insertPos) { - position = SrcScan(ctx->text.source, position, - XawstEOL, XawsdLeft, 1, False); - if (--position >= ctx->text.insertPos) - --line_number; - } - } - - return (line_number); -} -#endif - -/* - * This routine causes all batched screen updates to be performed - */ -void -_XawTextExecuteUpdate(TextWidget ctx) -{ - if (ctx->text.update_disabled || ctx->text.old_insert < 0) - return; - - if(ctx->text.old_insert != ctx->text.insertPos || ctx->text.showposition) - _XawTextShowPosition(ctx); - - FlushUpdate(ctx); - InsertCursor((Widget)ctx, XawisOn); - ctx->text.old_insert = -1; -#ifndef OLDXAW - _XawTextSetLineAndColumnNumber(ctx, False); -#endif -} - -static void -XawTextDestroy(Widget w) -{ - TextWidget ctx = (TextWidget)w; - - DestroyHScrollBar(ctx); - DestroyVScrollBar(ctx); - - XtFree((char *)ctx->text.s.selections); - XtFree((char *)ctx->text.lt.info); - XtFree((char *)ctx->text.search); - XmuDestroyScanline(ctx->text.update); - XtReleaseGC((Widget)ctx, ctx->text.gc); -} - -/* - * by the time we are managed (and get this far) we had better - * have both a source and a sink - */ -static void -XawTextResize(Widget w) -{ - TextWidget ctx = (TextWidget)w; - - PositionVScrollBar(ctx); - PositionHScrollBar(ctx); - TextSinkResize(ctx->text.sink); - - ctx->text.showposition = True; - _XawTextBuildLineTable(ctx, ctx->text.lt.top, True); -} - -/* - * This routine allow the application program to Set attributes. - */ -/*ARGSUSED*/ -static Boolean -XawTextSetValues(Widget current, Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - TextWidget oldtw = (TextWidget)current; - TextWidget newtw = (TextWidget)cnew; - Boolean redisplay = False; - Boolean display_caret = newtw->text.display_caret; -#ifndef OLDXAW - Boolean show_lc = False; -#endif - - newtw->text.display_caret = oldtw->text.display_caret; - _XawTextPrepareToUpdate(newtw); - newtw->text.display_caret = display_caret; - - if (oldtw->text.r_margin.left != newtw->text.r_margin.left) { - newtw->text.left_margin = newtw->text.margin.left = - newtw->text.r_margin.left; - if (newtw->text.vbar != NULL) { - newtw->text.left_margin += XtWidth(newtw->text.vbar) + - XtBorderWidth(newtw->text.vbar); - } - redisplay = True; - } - - if (oldtw->text.scroll_vert != newtw->text.scroll_vert) { - if (newtw->text.scroll_vert == XawtextScrollAlways) - CreateVScrollBar(newtw); - else - DestroyVScrollBar(newtw); - - redisplay = True; - } - - if (oldtw->text.r_margin.bottom != newtw->text.r_margin.bottom) { - newtw->text.margin.bottom = newtw->text.r_margin.bottom; - if (newtw->text.hbar != NULL) - newtw->text.margin.bottom += newtw->text.hbar->core.height + - newtw->text.hbar->core.border_width; - redisplay = True; - } - - if (oldtw->text.scroll_horiz != newtw->text.scroll_horiz) { - if (newtw->text.scroll_horiz == XawtextScrollAlways) - CreateHScrollBar(newtw); - else - DestroyHScrollBar(newtw); - - redisplay = True; - } - - if (oldtw->text.source != newtw->text.source) { -#ifndef OLDXAW - show_lc = True; - _XawSourceRemoveText(oldtw->text.source, cnew, - oldtw->text.source && - XtParent(oldtw->text.source) == cnew); - _XawSourceAddText(newtw->text.source, cnew); -#endif - _XawTextSetSource((Widget)newtw, newtw->text.source, newtw->text.lt.top, - newtw->text.insertPos); - } - - newtw->text.redisplay_needed = False; - XtSetValues((Widget)newtw->text.source, args, *num_args); - XtSetValues((Widget)newtw->text.sink, args, *num_args); - - if (oldtw->text.wrap != newtw->text.wrap - || oldtw->text.lt.top != newtw->text.lt.top - || oldtw->text.insertPos != newtw->text.insertPos - || oldtw->text.r_margin.right != newtw->text.r_margin.right - || oldtw->text.r_margin.top != newtw->text.r_margin.top - || oldtw->text.sink != newtw->text.sink - || newtw->text.redisplay_needed) { - if (oldtw->text.wrap != newtw->text.wrap) { - newtw->text.left_margin = newtw->text.margin.left = - newtw->text.r_margin.left; - if (oldtw->text.lt.top == newtw->text.lt.top) - newtw->text.lt.top = SrcScan(newtw->text.source, 0, XawstEOL, - XawsdLeft, 1, False); - } - newtw->text.showposition = True; -#ifndef OLDXAW - show_lc = True; - newtw->text.source_changed = SRC_CHANGE_OVERLAP; -#endif - _XawTextBuildLineTable(newtw, newtw->text.lt.top, True); - redisplay = True; - } - -#ifndef OLDXAW - if (newtw->text.left_column < 0) - newtw->text.left_column = 0; - if (newtw->text.right_column < 0) - newtw->text.right_column = 0; -#endif - - _XawTextExecuteUpdate(newtw); - -#ifndef OLDXAW - if (show_lc) - _XawTextSetLineAndColumnNumber(newtw, True); -#endif - - if (redisplay) - _XawTextSetScrollBars(newtw); - - return (redisplay); -} - -/* invoked by the Simple widget's SetValues */ -static Bool -XawTextChangeSensitive(Widget w) -{ - Arg args[1]; - TextWidget tw = (TextWidget)w; - - (*(&simpleClassRec)->simple_class.change_sensitive)(w); - - XtSetArg(args[0], XtNancestorSensitive, - (tw->core.ancestor_sensitive && tw->core.sensitive)); - if (tw->text.vbar) - XtSetValues(tw->text.vbar, args, ONE); - if (tw->text.hbar) - XtSetValues(tw->text.hbar, args, ONE); - return (False); -} - -/* - * Function: - * XawTextGetValuesHook - * - * Parameters: - * w - Text Widget - * args - argument list - * num_args - number of args - * - * Description: - * This is a get values hook routine that gets the - * values in the text source and sink. - */ -static void -XawTextGetValuesHook(Widget w, ArgList args, Cardinal *num_args) -{ - XtGetValues(((TextWidget)w)->text.source, args, *num_args); - XtGetValues(((TextWidget)w)->text.sink, args, *num_args); -} - -/* - * Function: - * FindGoodPosition - * - * Parameters: - * pos - any position - * - * Description: - * Returns a valid position given any postition. - * - * Returns: - * A position between (0 and lastPos) - */ -static XawTextPosition -FindGoodPosition(TextWidget ctx, XawTextPosition pos) -{ - if (pos < 0) - return (0); - return (((pos > ctx->text.lastPos) ? ctx->text.lastPos : pos)); -} - -/* Li wrote this so the IM can find a given text position's screen position */ -void -_XawTextPosToXY(Widget w, XawTextPosition pos, Position *x, Position *y) -{ - int line, ix, iy; - - LineAndXYForPosition((TextWidget)w, pos, &line, &ix, &iy); - *x = ix; - *y = iy; -} - -/******************************************************************* -The following routines provide procedural interfaces to Text window state -setting and getting. They need to be redone so than the args code can use -them. I suggest we create a complete set that takes the context as an -argument and then have the public version lookup the context and call the -internal one. The major value of this set is that they have actual application -clients and therefore the functionality provided is required for any future -version of Text. -********************************************************************/ -void -XawTextDisplay(Widget w) -{ - TextWidget ctx = (TextWidget)w; - - if (!XtIsRealized(w)) - return; - - _XawTextPrepareToUpdate(ctx); - ctx->text.clear_to_eol = True; - DisplayTextWindow(w); - _XawTextExecuteUpdate(ctx); -} - -void -XawTextSetSelectionArray(Widget w, XawTextSelectType *sarray) -{ - ((TextWidget)w)->text.sarray = sarray; -} - -void -XawTextGetSelectionPos(Widget w, XawTextPosition *left, XawTextPosition *right) -{ - *left = ((TextWidget)w)->text.s.left; - *right = ((TextWidget)w)->text.s.right; -} - -void -_XawTextSetSource(Widget w, Widget source, - XawTextPosition top, XawTextPosition startPos) -{ - TextWidget ctx = (TextWidget)w; -#ifndef OLDXAW - Bool resolve = False; -#endif - -#ifndef OLDXAW - if (source != ctx->text.source) - _XawSourceRemoveText(ctx->text.source, w, ctx->text.source && - XtParent(ctx->text.source) == w); - _XawSourceAddText(source, w); - - if (source != ctx->text.source || ctx->text.insertPos != startPos) - resolve = True; - - ctx->text.source_changed = SRC_CHANGE_OVERLAP; -#endif - ctx->text.source = source; - ctx->text.s.left = ctx->text.s.right = 0; - ctx->text.lastPos = GETLASTPOS; - top = FindGoodPosition(ctx, top); - startPos = FindGoodPosition(ctx, startPos); - ctx->text.insertPos = ctx->text.old_insert = startPos; - _XawTextPrepareToUpdate(ctx); - - _XawTextBuildLineTable(ctx, top, True); - - _XawTextExecuteUpdate(ctx); -#ifndef OLDXAW - if (resolve) - _XawTextSetLineAndColumnNumber(ctx, True); -#endif -} - -void -XawTextSetSource(Widget w, Widget source, XawTextPosition top) -{ - _XawTextSetSource(w, source, top, top); -} - -/* - * This public routine deletes the text from startPos to endPos in a source and - * then inserts, at startPos, the text that was passed. As a side effect it - * "invalidates" that portion of the displayed text (if any), so that things - * will be repainted properly. - */ -int -XawTextReplace(Widget w, XawTextPosition startPos, XawTextPosition endPos, - XawTextBlock *text) -{ - TextWidget ctx = (TextWidget)w; - int result; -#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]); -#else - _XawTextPrepareToUpdate(ctx); -#endif - - endPos = FindGoodPosition(ctx, endPos); - startPos = FindGoodPosition(ctx, startPos); - result = _XawTextReplace(ctx, startPos, endPos, text); - -#ifndef OLDXAW - for (i = 0; i < src->textSrc.num_text; i++) - _XawTextExecuteUpdate((TextWidget)src->textSrc.text[i]); -#else - _XawTextExecuteUpdate(ctx); -#endif - - return (result); -} - -XawTextPosition -XawTextTopPosition(Widget w) -{ - return (((TextWidget)w)->text.lt.top); -} - -XawTextPosition -XawTextLastPosition(Widget w) -{ - return (((TextWidget)w)->text.lastPos); -} - -void -XawTextSetInsertionPoint(Widget w, XawTextPosition position) -{ - TextWidget ctx = (TextWidget)w; - - _XawTextPrepareToUpdate(ctx); - ctx->text.insertPos = FindGoodPosition(ctx, position); - ctx->text.showposition = True; - ctx->text.from_left = -1; - - _XawTextExecuteUpdate(ctx); -#ifndef OLDXAW - _XawTextSetLineAndColumnNumber(ctx, False); -#endif -} - -XawTextPosition -XawTextGetInsertionPoint(Widget w) -{ - return (((TextWidget)w)->text.insertPos); -} - -/* - * Note: Must walk the selection list in opposite order from TextLoseSelection - */ -void -XawTextUnsetSelection(Widget w) -{ - TextWidget ctx = (TextWidget)w; - - while (ctx->text.s.atom_count != 0) { - Atom sel = ctx->text.s.selections[ctx->text.s.atom_count - 1]; - - if (sel != (Atom) 0) { - /* - * As selections are lost the atom_count will decrement - */ - if (GetCutBufferNumber(sel) == NOT_A_CUT_BUFFER) - XtDisownSelection(w, sel, ctx->text.time); - TextLoseSelection(w, &sel); /* In case this is a cut buffer, or - XtDisownSelection failed to call us */ - } - } -} - -void -XawTextSetSelection(Widget w, XawTextPosition left, XawTextPosition right) -{ - TextWidget ctx = (TextWidget)w; - - _XawTextPrepareToUpdate(ctx); - _XawTextSetSelection(ctx, FindGoodPosition(ctx, left), - FindGoodPosition(ctx, right), NULL, 0); - _XawTextExecuteUpdate(ctx); -} - -void -XawTextInvalidate(Widget w, XawTextPosition from, XawTextPosition to) -{ - TextWidget ctx = (TextWidget)w; - - from = FindGoodPosition(ctx, from); - to = FindGoodPosition(ctx, to); - ctx->text.lastPos = GETLASTPOS; - _XawTextPrepareToUpdate(ctx); - _XawTextNeedsUpdating(ctx, from, to); - _XawTextExecuteUpdate(ctx); -} - -/*ARGSUSED*/ -void -XawTextDisableRedisplay(Widget w) -{ - ((TextWidget)w)->text.update_disabled = True; - _XawTextPrepareToUpdate((TextWidget)w); -} - -void -XawTextEnableRedisplay(Widget w) -{ - TextWidget ctx = (TextWidget)w; - XawTextPosition lastPos; - - if (!ctx->text.update_disabled) - return; - - ctx->text.update_disabled = False; - lastPos = ctx->text.lastPos = GETLASTPOS; - ctx->text.lt.top = FindGoodPosition(ctx, ctx->text.lt.top); - ctx->text.insertPos = FindGoodPosition(ctx, ctx->text.insertPos); - - if (ctx->text.s.left > lastPos || ctx->text.s.right > lastPos) - ctx->text.s.left = ctx->text.s.right = 0; - - _XawTextExecuteUpdate(ctx); -} - -Widget -XawTextGetSource(Widget w) -{ - return (((TextWidget)w)->text.source); -} - -Widget -XawTextGetSink(Widget w) -{ - return (((TextWidget)w)->text.sink); -} - -void -XawTextDisplayCaret(Widget w, -#if NeedWidePrototypes - int display_caret -#else - Boolean display_caret -#endif -) -{ - TextWidget ctx = (TextWidget)w; - - if (XtIsRealized(w)) { - _XawTextPrepareToUpdate(ctx); - ctx->text.display_caret = display_caret; - _XawTextExecuteUpdate(ctx); - } - else - ctx->text.display_caret = display_caret; -} - -/* - * Function: - * XawTextSearch - * - * Parameters: - * w - text widget - * dir - direction to search - * text - text block containing info about the string to search for - * - * Description: - * Searches for the given text block. - * - * Returns: - * The position of the text found, or XawTextSearchError on an error - */ -XawTextPosition -XawTextSearch(Widget w, -#if NeedWidePrototypes - int dir, -#else - XawTextScanDirection dir, -#endif - XawTextBlock *text) -{ - TextWidget ctx = (TextWidget)w; - - return (SrcSearch(ctx->text.source, ctx->text.insertPos, dir, text)); -} - -TextClassRec textClassRec = { - /* core */ - { - (WidgetClass)&simpleClassRec, /* superclass */ - "Text", /* class_name */ - sizeof(TextRec), /* widget_size */ - XawTextClassInitialize, /* class_initialize */ - NULL, /* class_part_init */ - False, /* class_inited */ - XawTextInitialize, /* initialize */ - NULL, /* initialize_hook */ - XawTextRealize, /* realize */ - _XawTextActionsTable, /* actions */ - 0, /* num_actions */ - resources, /* resources */ - XtNumber(resources), /* num_resource */ - NULLQUARK, /* xrm_class */ - True, /* compress_motion */ - XtExposeGraphicsExpose | /* compress_exposure */ - XtExposeNoExpose, - True, /* compress_enterleave */ - False, /* visible_interest */ - XawTextDestroy, /* destroy */ - XawTextResize, /* resize */ - XawTextExpose, /* expose */ - XawTextSetValues, /* set_values */ - NULL, /* set_values_hook */ - XtInheritSetValuesAlmost, /* set_values_almost */ - XawTextGetValuesHook, /* get_values_hook */ - NULL, /* accept_focus */ - XtVersion, /* version */ - NULL, /* callback_private */ - _XawDefaultTextTranslations, /* tm_table */ - XtInheritQueryGeometry, /* query_geometry */ - XtInheritDisplayAccelerator, /* display_accelerator */ - NULL, /* extension */ - }, - /* simple */ - { - XawTextChangeSensitive, /* change_sensitive */ - }, - /* text */ - { - NULL, /* extension */ - } -}; - -WidgetClass textWidgetClass = (WidgetClass)&textClassRec; +/***********************************************************
+
+Copyright 1987, 1988, 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.
+
+
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+ * Copyright (c) 1998 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * 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 XFREE86 PROJECT 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 XFree86 Project 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
+ * XFree86 Project.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/Xatom.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/Misc.h>
+#include <X11/Xmu/SysUtil.h>
+#include <X11/Xmu/Xmu.h>
+#include <X11/Xaw/Cardinals.h>
+#include <X11/Xaw/MultiSinkP.h>
+#include <X11/Xaw/TextP.h>
+#include <X11/Xaw/TextSrcP.h>
+#include <X11/Xaw/TextSinkP.h>
+#include <X11/Xaw/Scrollbar.h>
+#include <X11/Xaw/XawImP.h>
+#include <X11/Xaw/XawInit.h>
+#include "Private.h"
+#include "XawI18n.h"
+
+#ifndef MAX_LEN_CT
+#define MAX_LEN_CT 6 /* for sequence: ESC $ ( A \xx \xx */
+#endif
+
+unsigned long FMT8BIT = 0L;
+unsigned long XawFmt8Bit = 0L;
+unsigned long XawFmtWide = 0L;
+
+#define SinkClearToBG _XawTextSinkClearToBackground
+
+#define SrcScan XawTextSourceScan
+#define SrcRead XawTextSourceRead
+#define SrcReplace XawTextSourceReplace
+#define SrcSearch XawTextSourceSearch
+#define SrcCvtSel XawTextSourceConvertSelection
+#define SrcSetSelection XawTextSourceSetSelection
+
+#define MULTI_CLICK_TIME 500L
+
+#define SRC_CHANGE_NONE 0
+#define SRC_CHANGE_AFTER 1
+#define SRC_CHANGE_BEFORE 2
+#define SRC_CHANGE_OVERLAP 3
+
+#define Superclass (&simpleClassRec)
+
+/*
+ * Compute a the maximum length of a cut buffer that we can pass at any
+ * time. The 64 allows for the overhead of the Change Property request.
+ */
+#define MAX_CUT_LEN(dpy) (XMaxRequestSize(dpy) - 64)
+
+#define ClearWindow(ctx) \
+ _XawTextNeedsUpdating((ctx), \
+ (ctx)->text.lt.top, \
+ (ctx)->text.lt.info[ctx->text.lt.lines].position)
+
+/*
+ * Class Methods
+ */
+static void XawTextClassInitialize(void);
+static void XawTextInitialize(Widget, Widget, ArgList, Cardinal*);
+static void XawTextRealize(Widget, XtValueMask*, XSetWindowAttributes*);
+static void XawTextDestroy(Widget);
+static void XawTextResize(Widget);
+static void XawTextExpose(Widget, XEvent*, Region);
+static Boolean XawTextSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
+static void XawTextGetValuesHook(Widget, ArgList, Cardinal*);
+static Bool XawTextChangeSensitive(Widget);
+
+/*
+ * Prototypes
+ */
+static XawTextPosition _BuildLineTable(TextWidget, XawTextPosition, int);
+static void _CreateCutBuffers(Display*);
+static Boolean TextConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*,
+ unsigned long*, int*);
+static int CountLines(TextWidget, XawTextPosition, XawTextPosition);
+static void CreateHScrollBar(TextWidget);
+static void CreateVScrollBar(TextWidget);
+static void CvtStringToScrollMode(XrmValuePtr, Cardinal*,
+ XrmValuePtr, XrmValuePtr);
+static Boolean CvtScrollModeToString(Display*, XrmValue*, Cardinal*,
+ XrmValue*, XrmValue*, XtPointer*);
+static void CvtStringToWrapMode(XrmValuePtr, Cardinal*,
+ XrmValuePtr, XrmValuePtr);
+static Boolean CvtWrapModeToString(Display*, XrmValue*, Cardinal*,
+ XrmValue*, XrmValue*, XtPointer*);
+static Boolean CvtStringToJustifyMode(Display*, XrmValue*, Cardinal*,
+ XrmValue*, XrmValue*, XtPointer*);
+static Boolean CvtJustifyModeToString(Display*, XrmValue*, Cardinal*,
+ XrmValue*, XrmValue*, XtPointer*);
+static void DestroyHScrollBar(TextWidget);
+static void DestroyVScrollBar(TextWidget);
+#ifndef OLDXAW
+static void DisplayText(Widget, XawTextPosition, XawTextPosition);
+#endif
+static void OldDisplayText(Widget, XawTextPosition, XawTextPosition);
+static void DisplayTextWindow(Widget);
+static void DoCopyArea(TextWidget, int, int, unsigned int, unsigned int,
+ int, int);
+static void DoSelection(TextWidget, XawTextPosition, Time, Bool);
+static void ExtendSelection(TextWidget, XawTextPosition, Bool);
+static XawTextPosition FindGoodPosition(TextWidget, XawTextPosition);
+static void FlushUpdate(TextWidget);
+static int GetCutBufferNumber(Atom);
+static int GetMaxTextWidth(TextWidget);
+static unsigned int GetWidestLine(TextWidget);
+static void HScroll(Widget, XtPointer, XtPointer);
+static void HJump(Widget, XtPointer, XtPointer);
+static void InsertCursor(Widget, XawTextInsertState);
+static Bool LineAndXYForPosition(TextWidget, XawTextPosition, int*,
+ int*, int*);
+static int LineForPosition(TextWidget, XawTextPosition);
+static void TextLoseSelection(Widget, Atom*);
+static Bool MatchSelection(Atom, XawTextSelection*);
+static void ModifySelection(TextWidget, XawTextPosition, XawTextPosition);
+static XawTextPosition PositionForXY(TextWidget, int, int);
+static void PositionHScrollBar(TextWidget);
+static void PositionVScrollBar(TextWidget);
+#ifndef OLDXAW
+static int ResolveColumnNumber(TextWidget);
+static int ResolveLineNumber(TextWidget);
+#endif
+static void _SetSelection(TextWidget, XawTextPosition, XawTextPosition,
+ Atom*, Cardinal);
+static void TextSinkResize(Widget);
+static void UpdateTextInRectangle(TextWidget, XRectangle*);
+static void UpdateTextInLine(TextWidget, int, int, int);
+static void VScroll(Widget, XtPointer, XtPointer);
+static void VJump(Widget, XtPointer, XtPointer);
+
+/*
+ * External
+ */
+void _XawTextAlterSelection(TextWidget,
+ XawTextSelectionMode, XawTextSelectionAction,
+ String*, Cardinal*);
+void _XawTextCheckResize(TextWidget);
+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 _XawTextSetScrollBars(TextWidget);
+void _XawTextSetSelection(TextWidget, XawTextPosition, XawTextPosition,
+ String*, Cardinal);
+void _XawTextVScroll(TextWidget, int);
+void XawTextScroll(TextWidget, int, int);
+void _XawTextSetSource(Widget, Widget, XawTextPosition, XawTextPosition);
+#ifndef OLDXAW
+void _XawTextSetLineAndColumnNumber(TextWidget, Bool);
+#endif
+void _XawTextSourceChanged(Widget, XawTextPosition, XawTextPosition,
+ XawTextBlock*, int);
+
+/* Not used by other modules, but were extern on previous versions
+ * of the library
+ */
+void _XawTextShowPosition(TextWidget);
+
+/*
+ * From TextAction.c
+ */
+extern void _XawTextZapSelection(TextWidget, XEvent*, Bool);
+
+/*
+ * From TextSrc.c
+ */
+void _XawSourceAddText(Widget, Widget);
+void _XawSourceRemoveText(Widget, Widget, Bool);
+Bool _XawTextSourceNewLineAtEOF(Widget);
+
+/*
+ * From TextSink.c
+ */
+void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned);
+void _XawTextSinkDisplayText(Widget, int, int, XawTextPosition, XawTextPosition,
+ Bool);
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+/*
+ * From TextTr.c
+ */
+static XawTextSelectType defaultSelectTypes[] = {
+ XawselectPosition, XawselectAlphaNumeric, XawselectWord, XawselectLine,
+ XawselectParagraph, XawselectAll, XawselectNull,
+};
+
+static XPointer defaultSelectTypesPtr = (XPointer)defaultSelectTypes;
+static Dimension defWidth = 100;
+static Dimension defHeight = DEFAULT_TEXT_HEIGHT;
+
+#define offset(field) XtOffsetOf(TextRec, field)
+static XtResource resources[] = {
+ {
+ XtNwidth,
+ XtCWidth,
+ XtRDimension,
+ sizeof(Dimension),
+ offset(core.width),
+ XtRDimension,
+ (XtPointer)&defWidth
+ },
+ {
+ XtNcursor,
+ XtCCursor,
+ XtRCursor,
+ sizeof(Cursor),
+ offset(simple.cursor),
+ XtRString,
+ "xterm"
+ },
+ {
+ XtNheight,
+ XtCHeight,
+ XtRDimension,
+ sizeof(Dimension),
+ offset(core.height),
+ XtRDimension,
+ (XtPointer)&defHeight
+ },
+ {
+ XtNdisplayPosition,
+ XtCTextPosition,
+ XtRInt,
+ sizeof(XawTextPosition),
+ offset(text.lt.top),
+ XtRImmediate,
+ (XtPointer)0
+ },
+ {
+ XtNinsertPosition,
+ XtCTextPosition,
+ XtRInt,
+ sizeof(XawTextPosition),
+ offset(text.insertPos),
+ XtRImmediate,
+ (XtPointer)0
+ },
+ {
+ XtNleftMargin,
+ XtCMargin,
+ XtRPosition,
+ sizeof(Position),
+ offset(text.r_margin.left),
+ XtRImmediate,
+ (XtPointer)2
+ },
+ {
+ XtNrightMargin,
+ XtCMargin,
+ XtRPosition,
+ sizeof(Position),
+ offset(text.r_margin.right),
+ XtRImmediate,
+ (XtPointer)4
+ },
+ {
+ XtNtopMargin,
+ XtCMargin,
+ XtRPosition,
+ sizeof(Position),
+ offset(text.r_margin.top),
+ XtRImmediate,
+ (XtPointer)2
+ },
+ {
+ XtNbottomMargin,
+ XtCMargin,
+ XtRPosition,
+ sizeof(Position),
+ offset(text.r_margin.bottom),
+ XtRImmediate,
+ (XtPointer)2
+ },
+ {
+ XtNselectTypes,
+ XtCSelectTypes,
+ XtRPointer,
+ sizeof(XawTextSelectType*),
+ offset(text.sarray),
+ XtRPointer,
+ (XtPointer)&defaultSelectTypesPtr
+ },
+ {
+ XtNtextSource,
+ XtCTextSource,
+ XtRWidget,
+ sizeof(Widget),
+ offset(text.source),
+ XtRImmediate,
+ NULL
+ },
+ {
+ XtNtextSink,
+ XtCTextSink,
+ XtRWidget,
+ sizeof(Widget),
+ offset(text.sink),
+ XtRImmediate,
+ NULL
+ },
+ {
+ XtNdisplayCaret,
+ XtCOutput,
+ XtRBoolean,
+ sizeof(Boolean),
+ offset(text.display_caret),
+ XtRImmediate,
+ (XtPointer)True
+ },
+ {
+ XtNscrollVertical,
+ XtCScroll,
+ XtRScrollMode,
+ sizeof(XawTextScrollMode),
+ offset(text.scroll_vert),
+ XtRImmediate,
+ (XtPointer)False
+ },
+ {
+ XtNscrollHorizontal,
+ XtCScroll,
+ XtRScrollMode,
+ sizeof(XawTextScrollMode),
+ offset(text.scroll_horiz),
+ XtRImmediate,
+ (XtPointer)False
+ },
+ {
+ XtNwrap,
+ XtCWrap,
+ XtRWrapMode,
+ sizeof(XawTextWrapMode),
+ offset(text.wrap),
+ XtRImmediate,
+ (XtPointer)XawtextWrapNever
+ },
+ {
+ XtNautoFill,
+ XtCAutoFill,
+ XtRBoolean,
+ sizeof(Boolean),
+ offset(text.auto_fill),
+ XtRImmediate,
+ (XtPointer)False
+ },
+#ifndef OLDXAW
+ {
+ XtNpositionCallback,
+ XtCCallback,
+ XtRCallback,
+ sizeof(XtPointer),
+ offset(text.position_callbacks),
+ XtRCallback,
+ NULL
+ },
+ {
+ XtNleftColumn,
+ XtCColumn,
+ XtRShort,
+ sizeof(short),
+ offset(text.left_column),
+ XtRImmediate,
+ (XtPointer)0
+ },
+ {
+ XtNrightColumn,
+ XtCColumn,
+ XtRShort,
+ sizeof(short),
+ offset(text.right_column),
+ XtRImmediate,
+ (XtPointer)0
+ },
+ {
+ XtNjustifyMode,
+ XtCJustifyMode,
+ XtRJustifyMode,
+ sizeof(XawTextJustifyMode),
+ offset(text.justify),
+ XtRImmediate,
+ (XtPointer)XawjustifyLeft
+ },
+#endif /* OLDXAW */
+};
+#undef offset
+
+#define done(address, type) \
+ { toVal->size = sizeof(type); toVal->addr = (XPointer)address; }
+
+static XrmQuark QWrapNever, QWrapLine, QWrapWord;
+#ifndef notdef
+static XrmQuark QScrollNever, QScrollWhenNeeded, QScrollAlways;
+#endif
+static XrmQuark QJustifyLeft, QJustifyRight, QJustifyCenter, QJustifyFull;
+
+/*ARGSUSED*/
+static void
+CvtStringToScrollMode(XrmValuePtr args, Cardinal *num_args,
+ XrmValuePtr fromVal, XrmValuePtr toVal)
+{
+ static XawTextScrollMode scrollMode = XawtextScrollNever;
+ XrmQuark q;
+ char name[32];
+
+ XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name));
+ q = XrmStringToQuark(name);
+
+ if (q == QScrollNever || q == QScrollWhenNeeded)
+ scrollMode = XawtextScrollNever;
+ else if (q == QScrollAlways)
+ scrollMode = XawtextScrollAlways;
+ else if (strcmp(name, "true") == 0 || strcmp(name, "1") == 0)
+ scrollMode = XawtextScrollAlways;
+ else if (strcmp(name, "false") == 0 || strcmp(name, "0") == 0)
+ scrollMode = XawtextScrollNever;
+ else
+ XtStringConversionWarning((char *)fromVal->addr, XtRScrollMode);
+
+ done(&scrollMode, XawTextScrollMode);
+}
+
+/*ARGSUSED*/
+static Boolean
+CvtScrollModeToString(Display *dpy, XrmValue *args, Cardinal *num_args,
+ XrmValue *fromVal, XrmValue *toVal, XtPointer *data)
+{
+ static char *buffer;
+ Cardinal size;
+
+ switch (*(XawTextScrollMode *)fromVal->addr) {
+ case XawtextScrollNever:
+ case XawtextScrollWhenNeeded:
+ buffer = XtEtextScrollNever;
+ break;
+ case XawtextScrollAlways:
+ buffer = XtEtextScrollAlways;
+ break;
+ default:
+ XawTypeToStringWarning(dpy, XtRScrollMode);
+ toVal->addr = NULL;
+ toVal->size = 0;
+ return (False);
+ }
+ size = strlen(buffer) + 1;
+ if (toVal->addr != NULL) {
+ if (toVal->size < size) {
+ toVal->size = size;
+ return (False);
+ }
+ strcpy((char *)toVal->addr, buffer);
+ }
+ else
+ toVal->addr = (XPointer)buffer;
+ toVal->size = sizeof(String);
+
+ return (True);
+}
+
+/*ARGSUSED*/
+static void
+CvtStringToWrapMode(XrmValuePtr args, Cardinal *num_args,
+ XrmValuePtr fromVal, XrmValuePtr toVal)
+{
+ static XawTextWrapMode wrapMode = XawtextWrapNever;
+ XrmQuark q;
+ char lowerName[6];
+
+ XmuNCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr,
+ sizeof(lowerName));
+ q = XrmStringToQuark(lowerName);
+
+ if (q == QWrapNever)
+ wrapMode = XawtextWrapNever;
+ else if (q == QWrapLine)
+ wrapMode = XawtextWrapLine;
+ else if (q == QWrapWord)
+ wrapMode = XawtextWrapWord;
+ else
+ XtStringConversionWarning((char *)fromVal->addr, XtRWrapMode);
+
+ done(&wrapMode, XawTextWrapMode);
+}
+
+/*ARGSUSED*/
+static Boolean
+CvtWrapModeToString(Display *dpy, XrmValue *args, Cardinal *num_args,
+ XrmValue *fromVal, XrmValue *toVal, XtPointer *data)
+{
+ static char *buffer;
+ Cardinal size;
+
+ switch (*(XawTextWrapMode *)fromVal->addr) {
+ case XawtextWrapNever:
+ buffer = XtEtextWrapNever;
+ break;
+ case XawtextWrapLine:
+ buffer = XtEtextWrapLine;
+ break;
+ case XawtextWrapWord:
+ buffer = XtEtextWrapWord;
+ break;
+ default:
+ XawTypeToStringWarning(dpy, XtRWrapMode);
+ toVal->addr = NULL;
+ toVal->size = 0;
+ return (False);
+ }
+ size = strlen(buffer) + 1;
+ if (toVal->addr != NULL) {
+ if (toVal->size < size) {
+ toVal->size = size;
+ return (False);
+ }
+ strcpy((char *)toVal->addr, buffer);
+ }
+ else
+ toVal->addr = (XPointer)buffer;
+ toVal->size = sizeof(String);
+
+ return (True);
+}
+
+/*ARGSUSED*/
+static Boolean
+CvtStringToJustifyMode(Display *dpy, XrmValue *args, Cardinal *num_args,
+ XrmValue *fromVal, XrmValue *toVal, XtPointer *data)
+{
+ XawTextJustifyMode justify;
+ XrmQuark q;
+ char lowerName[8];
+
+ XmuNCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr,
+ sizeof(lowerName));
+ q = XrmStringToQuark(lowerName);
+
+ if (q == QJustifyLeft)
+ justify = XawjustifyLeft;
+ else if (q == QJustifyRight)
+ justify = XawjustifyRight;
+ else if (q == QJustifyCenter)
+ justify = XawjustifyCenter;
+ else if(q == QJustifyFull)
+ justify = XawjustifyFull;
+ else {
+ XtStringConversionWarning((char *)fromVal->addr, XtRJustifyMode);
+ return (False);
+ }
+
+ toVal->size = sizeof(XawTextJustifyMode);
+ *(XawTextJustifyMode *)(toVal->addr) = justify;
+
+ return (True);
+}
+
+
+/*ARGSUSED*/
+static Boolean
+CvtJustifyModeToString(Display *dpy, XrmValue *args, Cardinal *num_args,
+ XrmValue *fromVal, XrmValue *toVal, XtPointer *data)
+{
+ static char *buffer;
+ Cardinal size;
+
+ switch (*(XawTextJustifyMode *)fromVal->addr) {
+ case XawjustifyLeft:
+ buffer = XtEtextJustifyLeft;
+ break;
+ case XawjustifyRight:
+ buffer = XtEtextJustifyRight;
+ break;
+ case XawjustifyCenter:
+ buffer = XtEtextJustifyCenter;
+ break;
+ case XawjustifyFull:
+ buffer = XtEtextJustifyFull;
+ break;
+ default:
+ XawTypeToStringWarning(dpy, XtRJustifyMode);
+ toVal->addr = NULL;
+ toVal->size = 0;
+ return (False);
+ }
+ size = strlen(buffer) + 1;
+ if (toVal->addr != NULL) {
+ if (toVal->size < size) {
+ toVal->size = size;
+ return (False);
+ }
+ strcpy((char *)toVal->addr, buffer);
+ }
+ else
+ toVal->addr = (XPointer)buffer;
+ toVal->size = sizeof(String);
+
+ return (True);
+}
+
+#undef done
+
+static void
+XawTextClassInitialize(void)
+{
+ if (!XawFmt8Bit)
+ FMT8BIT = XawFmt8Bit = XrmPermStringToQuark("FMT8BIT");
+ if (!XawFmtWide)
+ XawFmtWide = XrmPermStringToQuark("FMTWIDE");
+
+ XawInitializeWidgetSet();
+
+ textClassRec.core_class.num_actions = _XawTextActionsTableCount;
+
+ QWrapNever = XrmPermStringToQuark(XtEtextWrapNever);
+ QWrapLine = XrmPermStringToQuark(XtEtextWrapLine);
+ QWrapWord = XrmPermStringToQuark(XtEtextWrapWord);
+ XtAddConverter(XtRString, XtRWrapMode, CvtStringToWrapMode, NULL, 0);
+ XtSetTypeConverter(XtRWrapMode, XtRString, CvtWrapModeToString,
+ NULL, 0, XtCacheNone, NULL);
+ QScrollNever = XrmPermStringToQuark(XtEtextScrollNever);
+ QScrollWhenNeeded = XrmPermStringToQuark(XtEtextScrollWhenNeeded);
+ QScrollAlways = XrmPermStringToQuark(XtEtextScrollAlways);
+ XtAddConverter(XtRString, XtRScrollMode, CvtStringToScrollMode,
+ NULL, 0);
+ XtSetTypeConverter(XtRScrollMode, XtRString, CvtScrollModeToString,
+ NULL, 0, XtCacheNone, NULL);
+ QJustifyLeft = XrmPermStringToQuark(XtEtextJustifyLeft);
+ QJustifyRight = XrmPermStringToQuark(XtEtextJustifyRight);
+ QJustifyCenter = XrmPermStringToQuark(XtEtextJustifyCenter);
+ QJustifyFull = XrmPermStringToQuark(XtEtextJustifyFull);
+ XtSetTypeConverter(XtRString, XtRJustifyMode, CvtStringToJustifyMode,
+ NULL, 0, XtCacheNone, NULL);
+ XtSetTypeConverter(XtRJustifyMode, XtRString, CvtJustifyModeToString,
+ NULL, 0, XtCacheNone, NULL);
+}
+
+/*
+ * Function:
+ * PositionHScrollBar
+ *
+ * Parameters:
+ * ctx - text widget
+ *
+ * Description:
+ * Positions the Horizontal scrollbar.
+ */
+static void
+PositionHScrollBar(TextWidget ctx)
+{
+ Widget hbar = ctx->text.hbar, vbar = ctx->text.vbar;
+ Position x, y;
+ Dimension width, height;
+
+ if (ctx->text.hbar == NULL)
+ return;
+
+ if (vbar != NULL)
+ x = XtWidth(vbar);
+ else
+ x = -XtBorderWidth(hbar);
+ y = XtHeight(ctx) - XtHeight(hbar) - XtBorderWidth(hbar);
+ if (vbar != NULL) {
+ width = XtWidth(ctx) - XtWidth(vbar) - XtBorderWidth(vbar);
+ if (width > XtWidth(ctx))
+ width = XtWidth(ctx);
+ }
+ else
+ width = XtWidth(ctx);
+ height = XtHeight(hbar);
+
+ XtConfigureWidget(hbar, x, y, width, height, XtBorderWidth(hbar));
+}
+
+/*
+ * Function:
+ * PositionVScrollBar
+ *
+ * Parameters:
+ * ctx - text widget
+ *
+ * Description:
+ * Positions the Vertical scrollbar.
+ */
+static void
+PositionVScrollBar(TextWidget ctx)
+{
+ Widget vbar = ctx->text.vbar;
+ Position x, y;
+ Dimension width, height;
+
+ if (vbar == NULL)
+ return;
+
+ x = y = -XtBorderWidth(vbar);
+ height = XtHeight(ctx);
+ width = XtWidth(vbar);
+
+ XtConfigureWidget(vbar, x, y, width, height, XtBorderWidth(vbar));
+}
+
+static void
+CreateVScrollBar(TextWidget ctx)
+{
+ Widget vbar;
+
+ if (ctx->text.vbar != NULL)
+ return;
+
+ ctx->text.vbar = vbar =
+ XtCreateWidget("vScrollbar", scrollbarWidgetClass, (Widget)ctx, NULL, 0);
+ XtAddCallback(vbar, XtNscrollProc, VScroll, (XtPointer)ctx);
+ XtAddCallback(vbar, XtNjumpProc, VJump, (XtPointer)ctx);
+
+ ctx->text.r_margin.left += XtWidth(vbar) + XtBorderWidth(vbar);
+ ctx->text.left_margin = ctx->text.margin.left = ctx->text.r_margin.left;
+
+ PositionVScrollBar(ctx);
+ PositionHScrollBar(ctx);
+ TextSinkResize(ctx->text.sink);
+
+ if (XtIsRealized((Widget)ctx)) {
+ XtRealizeWidget(vbar);
+ XtMapWidget(vbar);
+ }
+ XtSetKeyboardFocus(vbar, (Widget)ctx);
+}
+
+/*
+ * Function:
+ * DestroyVScrollBar
+ *
+ * Parameters:
+ * ctx - parent text widget
+ *
+ * Description:
+ * Removes vertical ScrollBar.
+ */
+static void
+DestroyVScrollBar(TextWidget ctx)
+{
+ Widget vbar = ctx->text.vbar;
+
+ if (vbar == NULL)
+ return;
+
+ ctx->text.r_margin.left -= XtWidth(vbar) + XtBorderWidth(vbar);
+ ctx->text.left_margin = ctx->text.margin.left = ctx->text.r_margin.left;
+
+ XtDestroyWidget(vbar);
+ ctx->text.vbar = NULL;
+ if (!ctx->core.being_destroyed) {
+ PositionHScrollBar(ctx);
+ TextSinkResize(ctx->text.sink);
+ }
+}
+
+static void
+CreateHScrollBar(TextWidget ctx)
+{
+ Arg args[1];
+ Widget hbar;
+ int bottom;
+
+ if (ctx->text.hbar != NULL)
+ return;
+
+ XtSetArg(args[0], XtNorientation, XtorientHorizontal);
+ ctx->text.hbar = hbar =
+ XtCreateWidget("hScrollbar", scrollbarWidgetClass, (Widget)ctx, args, 1);
+ XtAddCallback(hbar, XtNscrollProc, HScroll, (XtPointer)ctx);
+ XtAddCallback(hbar, XtNjumpProc, HJump, (XtPointer)ctx);
+
+ bottom = ctx->text.r_margin.bottom + XtHeight(hbar) + XtBorderWidth(hbar);
+
+ ctx->text.margin.bottom = ctx->text.r_margin.bottom = bottom;
+
+ PositionHScrollBar(ctx);
+ TextSinkResize(ctx->text.sink);
+
+ if (XtIsRealized((Widget)ctx)) {
+ XtRealizeWidget(hbar);
+ XtMapWidget(hbar);
+ }
+ XtSetKeyboardFocus(hbar, (Widget)ctx);
+}
+
+/*
+ * Function:
+ * DestroyHScrollBar
+ *
+ * Parameters:
+ * ctx - parent text widget
+ *
+ * Description:
+ * Removes horizontal ScrollBar.
+ */
+static void
+DestroyHScrollBar(TextWidget ctx)
+{
+ Widget hbar = ctx->text.hbar;
+
+ if (hbar == NULL)
+ return;
+
+ ctx->text.r_margin.bottom -= XtHeight(hbar) + XtBorderWidth(hbar);
+ ctx->text.margin.bottom = ctx->text.r_margin.bottom;
+
+ XtDestroyWidget(hbar);
+ ctx->text.hbar = NULL;
+ if (!ctx->core.being_destroyed)
+ TextSinkResize(ctx->text.sink);
+}
+
+/*ARGSUSED*/
+static void
+XawTextInitialize(Widget request, Widget cnew,
+ ArgList args, Cardinal *num_args)
+{
+ TextWidget ctx = (TextWidget)cnew;
+
+ ctx->text.lt.lines = 0;
+ ctx->text.lt.info = (XawTextLineTableEntry *)
+ XtCalloc(1, sizeof(XawTextLineTableEntry));
+#ifndef OLDXAW
+ ctx->text.lt.base_line = 1;
+#endif
+ (void)bzero(&ctx->text.origSel, sizeof(XawTextSelection));
+ (void)bzero(&ctx->text.s, sizeof(XawTextSelection));
+ ctx->text.s.type = XawselectPosition;
+ ctx->text.salt = NULL;
+ ctx->text.hbar = ctx->text.vbar = NULL;
+ ctx->text.lasttime = 0;
+ ctx->text.time = 0;
+ ctx->text.showposition = True;
+ ctx->text.lastPos = ctx->text.source != NULL ?
+ XawTextGetLastPosition(ctx) : 0;
+ ctx->text.file_insert = NULL;
+ ctx->text.search = NULL;
+ ctx->text.update = XmuNewScanline(0, 0, 0);
+ ctx->text.gc = XtGetGC(cnew, 0, 0);
+ ctx->text.hasfocus = False;
+ ctx->text.margin = ctx->text.r_margin; /* Strucure copy */
+ ctx->text.left_margin = ctx->text.r_margin.left;
+ ctx->text.update_disabled = False;
+ ctx->text.clear_to_eol = True;
+ ctx->text.old_insert = -1;
+ ctx->text.mult = 1;
+ ctx->text.salt2 = NULL;
+ ctx->text.from_left = -1;
+
+#ifndef OLDXAW
+ ctx->text.numeric = False;
+ ctx->text.selection_state = False;
+ ctx->text.kill_ring = 0;
+
+ ctx->text.line_number = -1;
+ ctx->text.column_number = -1;
+ ctx->text.source_changed = SRC_CHANGE_NONE;
+
+ ctx->text.kill_ring_ptr = NULL;
+ ctx->text.overwrite = False;
+#endif
+
+ if (XtHeight(ctx) == DEFAULT_TEXT_HEIGHT) {
+ XtHeight(ctx) = VMargins(ctx);
+ if (ctx->text.sink != NULL)
+ XtHeight(ctx) += XawTextSinkMaxHeight(ctx->text.sink, 1);
+ }
+
+ if (ctx->text.scroll_vert == XawtextScrollAlways)
+ CreateVScrollBar(ctx);
+ if (ctx->text.scroll_horiz == XawtextScrollAlways)
+ CreateHScrollBar(ctx);
+
+#ifndef OLDXAW
+ if (ctx->text.left_column < 0)
+ ctx->text.left_column = 0;
+ if (ctx->text.right_column < 0)
+ ctx->text.right_column = 0;
+#endif
+}
+
+static void
+XawTextRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attr)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ (*textClassRec.core_class.superclass->core_class.realize)(w, mask, attr);
+
+ if (ctx->text.hbar != NULL) {
+ XtRealizeWidget(ctx->text.hbar);
+ XtMapWidget(ctx->text.hbar);
+ }
+
+ if (ctx->text.vbar != NULL) {
+ XtRealizeWidget(ctx->text.vbar);
+ XtMapWidget(ctx->text.vbar);
+ }
+
+ _XawTextBuildLineTable(ctx, ctx->text.lt.top, True);
+
+#ifndef OLDXAW
+ _XawTextSetLineAndColumnNumber(ctx, True);
+#endif
+}
+
+/* Utility routines for support of Text */
+static void
+_CreateCutBuffers(Display *d)
+{
+ static struct _DisplayRec {
+ struct _DisplayRec *next;
+ Display *dpy;
+ } *dpy_list = NULL;
+ struct _DisplayRec *dpy_ptr;
+
+ for (dpy_ptr = dpy_list; dpy_ptr != NULL; dpy_ptr = dpy_ptr->next)
+ if (dpy_ptr->dpy == d)
+ return;
+
+ dpy_ptr = XtNew(struct _DisplayRec);
+ dpy_ptr->next = dpy_list;
+ dpy_ptr->dpy = d;
+ dpy_list = dpy_ptr;
+
+#define Create(buffer) \
+ XChangeProperty(d, RootWindow(d, 0), buffer, XA_STRING, 8, \
+ PropModeAppend, NULL, 0);
+
+ Create(XA_CUT_BUFFER0);
+ Create(XA_CUT_BUFFER1);
+ Create(XA_CUT_BUFFER2);
+ Create(XA_CUT_BUFFER3);
+ Create(XA_CUT_BUFFER4);
+ Create(XA_CUT_BUFFER5);
+ Create(XA_CUT_BUFFER6);
+ Create(XA_CUT_BUFFER7);
+
+#undef Create
+}
+
+/*
+ * Procedure to manage insert cursor visibility for editable text. It uses
+ * the value of ctx->insertPos and an implicit argument. In the event that
+ * position is immediately preceded by an eol graphic, then the insert cursor
+ * is displayed at the beginning of the next line.
+ */
+static void
+InsertCursor(Widget w, XawTextInsertState state)
+{
+ TextWidget ctx = (TextWidget)w;
+ int x, y;
+ int line;
+
+ if (ctx->text.lt.lines < 1)
+ return;
+
+ if (ctx->text.display_caret &&
+ LineAndXYForPosition(ctx, ctx->text.insertPos, &line, &x, &y)) {
+ if (line < ctx->text.lt.lines)
+ y += (ctx->text.lt.info[line + 1].y - ctx->text.lt.info[line].y) + 1;
+ else
+ y += (ctx->text.lt.info[line].y - ctx->text.lt.info[line - 1].y) + 1;
+
+ XawTextSinkInsertCursor(ctx->text.sink, x, y, state);
+ }
+
+ /* Keep Input Method up to speed */
+ if (ctx->simple.international) {
+ Arg list[1];
+
+ XtSetArg(list[0], XtNinsertPosition, ctx->text.insertPos);
+ _XawImSetValues(w, list, 1);
+ }
+}
+
+/*
+ * Procedure to register a span of text that is no longer valid on the display
+ * It is used to avoid a number of small, and potentially overlapping, screen
+ * updates.
+*/
+void
+_XawTextNeedsUpdating(TextWidget ctx,
+ XawTextPosition left, XawTextPosition right)
+{
+ XmuSegment segment;
+
+ if (left >= right)
+ return;
+
+ segment.x1 = (int)left;
+ segment.x2 = (int)right;
+ (void)XmuScanlineOrSegment(ctx->text.update, &segment);
+}
+
+/*
+ * Procedure to read a span of text in Ascii form. This is purely a hack and
+ * we probably need to add a function to sources to provide this functionality.
+ * [note: this is really a private procedure but is used in multiple modules].
+ */
+char *
+_XawTextGetText(TextWidget ctx, XawTextPosition left, XawTextPosition right)
+{
+ char *result, *tempResult;
+ XawTextBlock text;
+ int bytes;
+
+ if (XawTextFormat(ctx, XawFmt8Bit))
+ bytes = sizeof(unsigned char);
+ else if (XawTextFormat(ctx, XawFmtWide))
+ bytes = sizeof(wchar_t);
+ else /* if there is another fomat, add here */
+ bytes = 1;
+
+ /* leave space for ZERO */
+ tempResult = result = XtMalloc((unsigned)(right - left + ONE) * bytes);
+
+ while (left < right) {
+ left = SrcRead(ctx->text.source, left, &text, (int)(right - left));
+ if (!text.length)
+ break;
+ memmove(tempResult, text.ptr, (unsigned)(text.length * bytes));
+ tempResult += text.length * bytes;
+ }
+
+ if (bytes == sizeof(wchar_t))
+ *((wchar_t*)tempResult) = (wchar_t)0;
+ else
+ *tempResult = '\0';
+
+ return (result);
+}
+
+/* Like _XawTextGetText, but enforces ICCCM STRING type encoding. This
+ * routine is currently used to put just the ASCII chars in the selection
+ * into a cut buffer.
+ */
+char *
+_XawTextGetSTRING(TextWidget ctx, XawTextPosition left, XawTextPosition right)
+{
+ unsigned char *s;
+ unsigned char c;
+ long i, j, n;
+ wchar_t *ws, wc;
+
+ /* allow ESC in accordance with ICCCM */
+ if (XawTextFormat(ctx, XawFmtWide)) {
+ MultiSinkObject sink = (MultiSinkObject)ctx->text.sink;
+ ws = (wchar_t *)_XawTextGetText(ctx, left, right);
+ n = wcslen(ws);
+ for (j = 0, i = 0; j < n; j++) {
+ wc = ws[j];
+ if (XwcTextEscapement (sink->multi_sink.fontset, &wc, 1)
+ || (wc == _Xaw_atowc(XawTAB)) || (wc == _Xaw_atowc(XawLF))
+ || (wc == _Xaw_atowc(XawESC)))
+ ws[i++] = wc;
+ }
+ ws[i] = (wchar_t)0;
+ return ((char *)ws);
+ }
+ else {
+ s = (unsigned char *)_XawTextGetText(ctx, left, right);
+ /* only HT and NL control chars are allowed, strip out others */
+ n = strlen((char *)s);
+ i = 0;
+ for (j = 0; j < n; j++) {
+ c = s[j];
+ if (((c >= 0x20) && c <= 0x7f)
+ ||(c >= 0xa0) || (c == XawTAB) || (c == XawLF)
+ || (c == XawESC)) {
+ s[i] = c;
+ i++;
+ }
+ }
+ s[i] = 0;
+
+ return ((char *)s);
+ }
+}
+
+/*
+ * This routine maps an x and y position in a window that is displaying text
+ * into the corresponding position in the source.
+ */
+static XawTextPosition
+PositionForXY(TextWidget ctx, int x, int y)
+{
+ int fromx, line, width, height;
+ XawTextPosition position;
+
+ if (ctx->text.lt.lines == 0)
+ return (0);
+
+ for (line = 0; line < ctx->text.lt.lines - 1; line++) {
+ if (y <= ctx->text.lt.info[line + 1].y)
+ break;
+ }
+ position = ctx->text.lt.info[line].position;
+ if (position >= ctx->text.lastPos)
+ return (ctx->text.lastPos);
+ fromx = ctx->text.left_margin;
+ XawTextSinkFindPosition(ctx->text.sink, position, fromx, x - fromx,
+ False, &position, &width, &height);
+
+ if (position > ctx->text.lastPos)
+ return (ctx->text.lastPos);
+
+ if (position >= ctx->text.lt.info[line + 1].position)
+ position = SrcScan(ctx->text.source, ctx->text.lt.info[line + 1].position,
+ XawstPositions, XawsdLeft, 1, True);
+
+ return (position);
+}
+
+/*
+ * This routine maps a source position in to the corresponding line number
+ * of the text that is displayed in the window.
+ */
+static int
+LineForPosition(TextWidget ctx, XawTextPosition position)
+{
+ int line;
+
+ for (line = 0; line < ctx->text.lt.lines; line++)
+ if (position < ctx->text.lt.info[line + 1].position)
+ break;
+
+ return (line);
+}
+
+/*
+ * This routine maps a source position into the corresponding line number
+ * and the x, y coordinates of the text that is displayed in the window.
+ */
+static Bool
+LineAndXYForPosition(TextWidget ctx, XawTextPosition pos,
+ int *line, int *x, int *y)
+{
+ XawTextPosition linePos, endPos;
+ Boolean visible;
+ int realW, realH;
+
+ *line = 0;
+ *x = ctx->text.left_margin;
+ *y = ctx->text.margin.top + 1;
+ if ((visible = IsPositionVisible(ctx, pos)) != False) {
+ *line = LineForPosition(ctx, pos);
+ *y = ctx->text.lt.info[*line].y;
+ linePos = ctx->text.lt.info[*line].position;
+ XawTextSinkFindDistance(ctx->text.sink, linePos,
+ *x, pos, &realW, &endPos, &realH);
+ *x += realW;
+ }
+
+ return (visible);
+}
+
+/*
+ * This routine builds a line table. It does this by starting at the
+ * specified position and measuring text to determine the staring position
+ * of each line to be displayed. It also determines and saves in the
+ * linetable all the required metrics for displaying a given line (e.g.
+ * x offset, y offset, line length, etc.).
+ */
+void
+_XawTextBuildLineTable(TextWidget ctx, XawTextPosition position,
+ _XtBoolean force_rebuild)
+{
+ Dimension height = 0;
+ int lines = 0;
+ Cardinal size;
+
+ if ((int)XtHeight(ctx) > VMargins(ctx)) {
+ height = XtHeight(ctx) - VMargins(ctx);
+ lines = XawTextSinkMaxLines(ctx->text.sink, height);
+ }
+ size = sizeof(XawTextLineTableEntry) * (lines + 1);
+
+ if (lines != ctx->text.lt.lines || ctx->text.lt.info == NULL) {
+ ctx->text.lt.info = (XawTextLineTableEntry *)
+ XtRealloc((char *)ctx->text.lt.info, size);
+ ctx->text.lt.lines = lines;
+ force_rebuild = True;
+ }
+
+ if (force_rebuild) {
+ (void)bzero((char *)ctx->text.lt.info, size);
+ /* force a text update in the first text line if it is visible */
+ ctx->text.lt.info[0].position = (XawTextPosition)-1;
+ }
+ if (position != ctx->text.lt.info[0].position) {
+ (void)_BuildLineTable(ctx, position, 0);
+ ctx->text.clear_to_eol = True;
+ }
+}
+
+/*
+ * We may need to resize the line table here, since there maybe lines with
+ * different fonts (that can be shorter or taller than the default one)
+ */
+static XawTextPosition
+_BuildLineTable(TextWidget ctx, XawTextPosition position, int line)
+{
+ XawTextLineTableEntry *lt = ctx->text.lt.info + line;
+ XawTextPosition end, update_from = -1;
+ Position y;
+ int wwidth, width, height;
+#ifndef OLDXAW
+ Widget src = ctx->text.source;
+#endif
+ int max_y = (int)XtHeight(ctx) - (int)ctx->text.margin.bottom;
+
+ if (ctx->text.wrap == XawtextWrapNever)
+ wwidth = 0x7fffffff;
+ else
+ wwidth = GetMaxTextWidth(ctx);
+
+ /* XXX y may change, due to font size changes. See later */
+ y = line == 0 ? ctx->text.margin.top : lt->y;
+
+#ifndef OLDXAW
+ if (ctx->text.lt.base_line < 0) {
+ if (line == 0)
+ ctx->text.lt.top = position;
+ }
+ else if (line == 0) {
+ XawTextPosition pos = ctx->text.lt.top;
+ int base_line = ctx->text.lt.base_line;
+
+ if (position == 0)
+ base_line = 1;
+ else if (ctx->text.lt.base_line == 0 ||
+ ctx->text.source_changed == SRC_CHANGE_OVERLAP) {
+ pos = 0;
+ base_line = 1;
+
+ while (pos < position) {
+ pos = SrcScan(src, pos, XawstEOL, XawsdRight, 1, True);
+ if (pos <= position) {
+ ++base_line;
+ if (pos == ctx->text.lastPos) {
+ base_line -= !_XawTextSourceNewLineAtEOF(src);
+ break;
+ }
+ }
+ }
+ }
+ else if (ctx->text.wrap == XawtextWrapNever
+ && IsPositionVisible(ctx, position))
+ base_line += LineForPosition(ctx, position);
+ else if (pos < position) {
+ while (pos < position) {
+ pos = SrcScan(src, pos, XawstEOL, XawsdRight, 1, True);
+ if (pos <= position) {
+ ++base_line;
+ if (pos == ctx->text.lastPos) {
+ base_line -= !_XawTextSourceNewLineAtEOF(src);
+ break;
+ }
+ }
+ }
+ }
+ else if (pos > position) {
+ while (pos > position) {
+ pos = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False);
+ if (--pos >= position)
+ --base_line;
+ }
+ }
+
+ ctx->text.lt.top = position;
+ ctx->text.lt.base_line = base_line;
+ }
+#else
+ if (line == 0)
+ ctx->text.lt.top = position;
+#endif
+
+ /* CONSTCOND */
+ while (True) {
+ XawTextSinkFindPosition(ctx->text.sink, position, ctx->text.left_margin,
+ wwidth, ctx->text.wrap == XawtextWrapWord,
+ &end, &width, &height);
+
+ if (lt->position != position) {
+ _XawTextNeedsUpdating(ctx, position,
+ end <= position ? position + 1 : end);
+ ctx->text.clear_to_eol = True;
+ lt->position = position;
+ }
+ if (lt->y != y) {
+ if (update_from < 0)
+ update_from = line == 0 ?
+ ctx->text.lt.info[0].position :
+ ctx->text.lt.info[line - 1].position;
+ lt->y = y;
+ ctx->text.clear_to_eol = True;
+ }
+ if (lt->textWidth != width) {
+ if (lt->textWidth > width)
+ ctx->text.clear_to_eol = True;
+ lt->textWidth = width;
+ }
+ y += height;
+
+ if (end > ctx->text.lastPos) {
+ position = end;
+ ctx->text.clear_to_eol = True;
+ _XawTextNeedsUpdating(ctx, end, end + ctx->text.lt.lines - line);
+ while (line++ < ctx->text.lt.lines) {
+ if (line > 1 && y > max_y) {
+ ctx->text.lt.lines = line - 1;
+ break;
+ }
+ ++lt;
+ if (lt->y != y) {
+ if (update_from < 0)
+ update_from = line < 2 ?
+ ctx->text.lt.info[0].position :
+ ctx->text.lt.info[line - 2].position;
+ lt->y = y;
+ }
+ lt->position = ++position;
+ lt->textWidth = 0;
+ y += height;
+ }
+ if (update_from >= 0)
+ _XawTextNeedsUpdating(ctx, update_from,
+ ctx->text.lt.info[ctx->text.lt.lines].position);
+ _XawTextSetScrollBars(ctx);
+
+ return (ctx->text.lastPos);
+ }
+
+ if (line && y > max_y)
+ /* will return in the next loop */
+ ctx->text.lt.lines = line;
+
+ if (++line > ctx->text.lt.lines && y < max_y) {
+ /* grow the line table */
+ ctx->text.lt.info = (XawTextLineTableEntry *)
+ XtRealloc((char *)ctx->text.lt.info,
+ sizeof(XawTextLineTableEntry) * (line + 1));
+ lt = ctx->text.lt.info + line;
+ bzero(lt, sizeof(XawTextLineTableEntry));
+ ++ctx->text.lt.lines;
+ }
+ else
+ ++lt;
+ if (position == end)
+ ++position;
+ else
+ position = end;
+
+ if (line > ctx->text.lt.lines) {
+ if (update_from >= 0)
+ _XawTextNeedsUpdating(ctx, update_from,
+ ctx->text.lt.info[ctx->text.lt.lines].position);
+ _XawTextSetScrollBars(ctx);
+
+ return (position);
+ }
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * Function:
+ * GetWidestLine
+ *
+ * Parameters:
+ * ctx - text widget
+ *
+ * Description:
+ * Returns the width (in pixels) of the widest line that
+ * is currently visable.
+ *
+ * Returns:
+ * The width of the widest line
+ */
+static unsigned int
+GetWidestLine(TextWidget ctx)
+{
+ int i;
+ unsigned int widest;
+ XawTextLineTablePtr lt = &(ctx->text.lt);
+
+ for (i = 0, widest = 0; i < lt->lines; i++)
+ if (widest < lt->info[i].textWidth)
+ widest = lt->info[i].textWidth;
+
+ return (widest);
+}
+
+/*
+ * This routine is used by Text to notify an associated scrollbar of the
+ * correct metrics (position and shown fraction) for the text being currently
+ * displayed in the window.
+ */
+void
+_XawTextSetScrollBars(TextWidget ctx)
+{
+ float first, last, denom, widest;
+
+ if (ctx->text.scroll_vert == XawtextScrollAlways) {
+ if (ctx->text.lastPos == 0)
+ first = 0.0;
+ else
+ first = ctx->text.lt.top / (float)ctx->text.lastPos;
+
+ if (ctx->text.lt.info[ctx->text.lt.lines].position < ctx->text.lastPos)
+ last = ctx->text.lt.info[ctx->text.lt.lines].position /
+ (float)ctx->text.lastPos;
+ else
+ last = 1.0;
+
+ XawScrollbarSetThumb(ctx->text.vbar, first, last - first);
+ }
+
+ if (ctx->text.scroll_horiz == XawtextScrollAlways) {
+ denom = GetWidestLine(ctx);
+ if (denom <= 0)
+ denom = (int)XtWidth(ctx) - RHMargins(ctx);
+ if (denom <= 0)
+ denom = 1;
+ widest = ((int)XtWidth(ctx) - RHMargins(ctx)) / denom;
+ first = ctx->text.r_margin.left - ctx->text.left_margin;
+ first /= denom;
+
+ XawScrollbarSetThumb(ctx->text.hbar, first, widest);
+ }
+}
+
+static void
+DoCopyArea(TextWidget ctx, int src_x, int src_y,
+ unsigned int width, unsigned int height, int dst_x, int dst_y)
+{
+ int x1, y1, x2, y2;
+
+ x1 = ctx->text.r_margin.left;
+ y1 = ctx->text.r_margin.top;
+ x2 = XtWidth(ctx) - ctx->text.r_margin.right;
+ y2 = XtHeight(ctx) - ctx->text.r_margin.bottom;
+
+ if (x1 >= x2 || y1 >= y2)
+ return;
+
+ src_x = XawMax(x1, XawMin(src_x, x2));
+ src_y = XawMax(y1, XawMin(src_y, y2));
+ dst_x = XawMax(x1, XawMin(dst_x, x2));
+ dst_y = XawMax(y1, XawMin(dst_y, y2));
+ width = XawMax(0, XawMin(x2 - dst_x, (int)width));
+ height = XawMax(0, XawMin(y2 - dst_y, (int)height));
+
+ XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), ctx->text.gc,
+ src_x, src_y, width, height, dst_x, dst_y);
+}
+
+/*
+ * Function:
+ * XawTextScroll
+ *
+ * Parameters:
+ * ctx - text widget
+ * vlines - number of lines to scroll vertically
+ * hpixels - number of pixels to scroll horizontally
+ *
+ * Description:
+ * Generic function for scrolling the text window.
+ * Allows vertical and horizontal scroll at the same time.
+ */
+void
+XawTextScroll(TextWidget ctx, int vlines, int hpixels)
+{
+ XawTextPosition top, tmp, update_from, update_to;
+ XawTextLineTable *lt;
+ Arg arglist[1];
+ int y0, y1, y2, count, dim, wwidth, lines = ctx->text.lt.lines;
+ int vwidth, vheight; /* visible width and height */
+ Bool scroll;
+
+ vwidth = (int)XtWidth(ctx) - RHMargins(ctx);
+ vheight = (int)XtHeight(ctx) - RVMargins(ctx);
+ lt = &ctx->text.lt;
+
+ if (!lt || vwidth <= 0 || vheight <= 0)
+ return;
+
+ if ((scroll = ctx->core.background_pixmap == XtUnspecifiedPixmap) == True) {
+ dim = lt->info[1].y - lt->info[0].y;
+ for (count = 1; count < lt->lines - 1; count++)
+ if (lt->info[count + 1].y - lt->info[count].y != dim) {
+ scroll = False;
+ break;
+ }
+ }
+
+ wwidth = GetMaxTextWidth(ctx);
+
+ /*
+ * Do the horizontall scrolling
+ */
+ if (hpixels < 0 && ctx->text.left_margin - hpixels > ctx->text.r_margin.left)
+ hpixels = ctx->text.left_margin - ctx->text.r_margin.left;
+ ctx->text.left_margin -= hpixels;
+
+ update_from = lt->top; /* remember the old value */
+ /*
+ * Checks the requested number of lines and calculates the top
+ * of the line table
+ */
+ if (vlines < 0) { /* VScroll Up */
+ if (IsPositionVisible(ctx, 0))
+ vlines = 0;
+ else if (ctx->text.wrap != XawtextWrapNever) {
+ XawTextPosition end;
+ int n_lines = 0;
+
+ count = -vlines;
+ end = lt->top;
+ while (n_lines < count) {
+ top = SrcScan(ctx->text.source, end, XawstEOL,
+ XawsdLeft, 2, False);
+ n_lines += CountLines(ctx, top, end);
+ end = top;
+ }
+
+ while (count++ < n_lines) {
+ tmp = top;
+ XawTextSinkFindPosition(ctx->text.sink, top,
+ ctx->text.left_margin,
+ wwidth,ctx->text.wrap == XawtextWrapWord,
+ &top, &dim, &dim);
+ if (tmp == top)
+ ++top;
+ }
+ }
+ else
+ top = SrcScan(ctx->text.source, lt->top, XawstEOL,
+ XawsdLeft, -vlines + 1, False);
+ if (-vlines >= ctx->text.lt.lines)
+ scroll = False;
+ }
+ else if (vlines > 0) { /* VScroll Down */
+ if (LineForPosition(ctx, ctx->text.lastPos) == 0)
+ vlines = 0;
+ if (vlines < lt->lines)
+ top = XawMin(lt->info[vlines].position, ctx->text.lastPos);
+ else if (ctx->text.wrap == XawtextWrapNever)
+ top = SrcScan(ctx->text.source,
+ SrcScan(ctx->text.source, lt->top,
+ XawstEOL, XawsdRight, vlines,
+ True),
+ XawstEOL, XawsdLeft, 1, False);
+ else {
+ top = lt->top;
+ count = 0;
+ while (count++ < vlines) {
+ tmp = top;
+ XawTextSinkFindPosition(ctx->text.sink, top,
+ ctx->text.left_margin,
+ wwidth, ctx->text.wrap == XawtextWrapWord,
+ &top, &dim, &dim);
+ if (tmp == top)
+ ++top;
+ }
+ }
+ if (vlines >= ctx->text.lt.lines
+ || lt->info[vlines].position >= ctx->text.lastPos)
+ scroll = False;
+ }
+
+ if (!vlines) {
+ if (hpixels) {
+ ClearWindow(ctx);
+ ctx->text.clear_to_eol = True;
+ }
+ _XawTextSetScrollBars(ctx);
+ return;
+ }
+
+ /* Flushes any pending updates. Normally, there may be a call to
+ * XawTextUnsetSelection not yet updated.
+ */
+ if (!hpixels && scroll) {
+ ctx->text.clear_to_eol = True;
+ FlushUpdate(ctx);
+ }
+
+ /*
+ * Rebuild the line table, doing the vertical scroll
+ */
+ (void)_BuildLineTable(ctx, top, 0);
+ lt = &ctx->text.lt;
+ if (scroll) {
+ for (count = 0; count < lt->lines - 1; count++)
+ if (lt->info[count + 1].y - lt->info[count].y != dim) {
+ scroll = False;
+ break;
+ }
+ }
+
+ XtSetArg(arglist[0], XtNinsertPosition, lt->top + lt->lines);
+ _XawImSetValues((Widget)ctx, arglist, 1);
+
+ if (hpixels || !scroll || lines != lt->lines)
+ return;
+
+ /* _BuildLineTable updates everything if the top position changes.
+ * It is not required here.
+ */
+ (void)XmuScanlineXor(ctx->text.update, ctx->text.update);
+ if (vlines < 0 && IsPositionVisible(ctx, 0))
+ vlines = -LineForPosition(ctx, update_from);
+
+ y0 = ctx->text.r_margin.top;
+ if (vlines < 0) {
+ update_from = lt->top;
+ update_to = lt->info[-vlines + 1].position - 1;
+ y1 = lt->info[lt->lines + vlines].y;
+ y2 = lt->info[-vlines].y;
+ DoCopyArea(ctx, ctx->text.r_margin.left, y0, vwidth,
+ y1 - y0,
+ ctx->text.r_margin.left, y2);
+ }
+ else {
+ update_from = lt->info[lt->lines - vlines].position;
+ update_to = lt->info[lt->lines].position;
+ y1 = lt->info[lt->lines - vlines].y;
+ y2 = lt->info[vlines].y;
+ DoCopyArea(ctx, ctx->text.r_margin.left, y2,
+ vwidth, lt->info[lt->lines].y - y2,
+ ctx->text.r_margin.left, y0);
+ }
+ _XawTextNeedsUpdating(ctx, update_from, update_to);
+ ctx->text.clear_to_eol = True;
+}
+
+/*
+ * The routine will scroll the displayed text by lines. If the arg is
+ * positive, move up; otherwise, move down. [note: this is really a private
+ * procedure but is used in multiple modules].
+ */
+void
+_XawTextVScroll(TextWidget ctx, int n)
+{
+ XawTextScroll(ctx, n, 0);
+}
+
+/*ARGSUSED*/
+static void
+HScroll(Widget w, XtPointer closure, XtPointer callData)
+{
+ TextWidget ctx = (TextWidget)closure;
+ long pixels = (long)callData;
+
+ if (pixels > 0) {
+ long max;
+
+ max = (int)GetWidestLine(ctx) + ctx->text.left_margin -
+ ctx->text.r_margin.left;
+ max = XawMax(0, max);
+ pixels = XawMin(pixels, max);
+ }
+
+ if (pixels) {
+ _XawTextPrepareToUpdate(ctx);
+ XawTextScroll(ctx, 0, pixels);
+ _XawTextExecuteUpdate(ctx);
+ }
+}
+
+/*ARGSUSED*/
+static void
+HJump(Widget w, XtPointer closure, XtPointer callData)
+{
+ TextWidget ctx = (TextWidget)closure;
+ float percent = *(float *)callData;
+ long pixels;
+
+ pixels = ctx->text.left_margin -
+ (ctx->text.r_margin.left - (int)(percent * GetWidestLine(ctx)));
+
+ HScroll(w, (XtPointer)ctx, (XtPointer)pixels);
+}
+
+/*
+ * Function:
+ * UpdateTextInLine
+ *
+ * Parameters:
+ * ctx - text widget
+ * line - line to update
+ * x1 - left pixel
+ * x2 - right pixel
+ *
+ * Description:
+ * Updates the text in the given line and pixel interval
+ */
+static void
+UpdateTextInLine(TextWidget ctx, int line, int x1, int x2)
+{
+ XawTextLineTableEntry *lt = ctx->text.lt.info + line;
+ XawTextPosition left, right;
+ int from_x, width, height;
+
+ if (lt->position >= ctx->text.lastPos
+ || ctx->text.left_margin > x2
+ || (int)lt->textWidth + ctx->text.left_margin < x1) {
+ /* Mark line to be cleared */
+ if (ctx->text.clear_to_eol)
+ _XawTextNeedsUpdating(ctx, lt->position, lt->position + 1);
+ return;
+ }
+
+ from_x = ctx->text.left_margin;
+ XawTextSinkFindPosition(ctx->text.sink, lt->position,
+ from_x, x1 - from_x,
+ False, &left, &width, &height);
+ if (line == ctx->text.lt.lines)
+ right = -1;
+ else if (x2 >= lt->textWidth - from_x)
+ right = lt[1].position - 1;
+ else {
+ from_x += width;
+ XawTextSinkFindPosition(ctx->text.sink, left,
+ from_x, x2 - from_x,
+ False, &right, &width, &height);
+ }
+
+ if ((right < 0) || (right + 1 <= lt[1].position))
+ ++right;
+
+ /* Mark text interval to be repainted */
+ _XawTextNeedsUpdating(ctx, left, right);
+}
+
+/*
+ * The routine will scroll the displayed text by pixels. If the calldata is
+ * positive, move up; otherwise, move down.
+ */
+/*ARGSUSED*/
+static void
+VScroll(Widget w, XtPointer closure, XtPointer callData)
+{
+ TextWidget ctx = (TextWidget)closure;
+ long height, lines = (long)callData;
+
+ height = XtHeight(ctx) - VMargins(ctx);
+ if (height < 1)
+ height = 1;
+ lines = (lines * ctx->text.lt.lines) / height;
+ _XawTextPrepareToUpdate(ctx);
+ XawTextScroll(ctx, lines, 0);
+ _XawTextExecuteUpdate(ctx);
+}
+
+/*ARGSUSED*/
+static void
+VJump(Widget w, XtPointer closure, XtPointer callData)
+{
+ float percent = *(float *)callData;
+ TextWidget ctx = (TextWidget)closure;
+ XawTextPosition top, last, position, tmp;
+ XawTextLineTable *lt = &(ctx->text.lt);
+ int dim, vlines = 0, wwidth = GetMaxTextWidth(ctx);
+ Bool scroll = True;
+
+ position = percent * ctx->text.lastPos;
+ top = lt->top;
+
+ if (!lt->lines || (position >= lt->top && position < lt->info[1].position)) {
+ _XawTextSetScrollBars(ctx);
+ return;
+ }
+
+#ifndef OLDXAW
+ ctx->text.lt.base_line = -1;
+#endif
+
+ if (position > lt->top) { /* VScroll Up */
+ if (position > lt->top && position < lt->info[lt->lines].position)
+ vlines = LineForPosition(ctx, position);
+ else {
+ scroll = False;
+ top = SrcScan(ctx->text.source, position, XawstEOL,
+ XawsdLeft, 1, False);
+ if (ctx->text.wrap != XawtextWrapNever) {
+ last = top;
+ while (last < position) {
+ tmp = last;
+ XawTextSinkFindPosition(ctx->text.sink, last,
+ ctx->text.left_margin, wwidth,
+ ctx->text.wrap == XawtextWrapWord,
+ &last, &dim, &dim);
+ if (last == tmp)
+ ++last;
+ if (last < position)
+ top = last;
+ }
+ }
+ }
+ }
+ else { /* VScroll Down */
+ /*
+ * Calculates the number of lines
+ */
+ while (top > position) {
+ last = top;
+ top = SrcScan(ctx->text.source, top, XawstEOL,
+ XawsdLeft, 2, False);
+ vlines -= CountLines(ctx, top, last);
+ if (-vlines >= ctx->text.lt.lines) {
+ scroll = False;
+ top = SrcScan(ctx->text.source, position, XawstEOL,
+ XawsdLeft, 1, False);
+ break;
+ }
+ }
+ /*
+ * Normalize
+ */
+ if (ctx->text.wrap != XawtextWrapNever) {
+ last = top;
+ while (last < position) {
+ tmp = last;
+ XawTextSinkFindPosition(ctx->text.sink, last,
+ ctx->text.left_margin,
+ wwidth,
+ ctx->text.wrap == XawtextWrapWord,
+ &last, &dim, &dim);
+ if (last == tmp)
+ ++last;
+ if (last < position)
+ top = last;
+ ++vlines;
+ }
+ }
+ }
+
+ if (vlines || !scroll) {
+ _XawTextPrepareToUpdate(ctx);
+ if (scroll)
+ XawTextScroll(ctx, vlines, 0);
+ else
+ _BuildLineTable(ctx, top, 0);
+ _XawTextExecuteUpdate(ctx);
+ }
+}
+
+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);
+}
+
+static Boolean
+TextConvertSelection(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, ONE);
+
+ 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);
+ }
+ (void)memmove((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);
+
+ if (MatchSelection(*selection, &ctx->text.s))
+ s = &ctx->text.s;
+ else {
+ for (salt = ctx->text.salt; 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 = _XawTextGetSTRING(ctx, s->left, s->right);
+ if (XawTextFormat(ctx, XawFmtWide)) {
+ XTextProperty textprop;
+ if (XwcTextListToTextProperty(d, (wchar_t **)value, 1,
+ XCompoundTextStyle, &textprop)
+ < Success) {
+ XtFree((char *)*value);
+ return (False);
+ }
+ XtFree((char *)*value);
+ *value = (XtPointer)textprop.value;
+ *length = textprop.nitems;
+ }
+ else
+ *length = strlen((char *)*value);
+ }
+ else {
+ *value = XtMalloc((salt->length + 1) * sizeof(unsigned char));
+ strcpy ((char *)*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((char *)*value);
+ return (False);
+ }
+ XtFree((char *)*value);
+ if (XwcTextListToTextProperty(d, wlist, 1, XStringStyle, &textprop)
+ < Success) {
+ XwcFreeStringList((wchar_t**) wlist);
+ return (False);
+ }
+ *value = (XtPointer)textprop.value;
+ *length = textprop.nitems;
+ XwcFreeStringList(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((char *)*value);
+ return (False);
+ }
+ XtFree((char *)*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((unsigned)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((unsigned)(2 * sizeof(long)));
+ temp[0] = (long)(s->left + 1);
+ temp[1] = s->right;
+ *value = (XPointer)temp;
+ *type = XA_SPAN(d);
+ *length = 2L;
+ *format = 32;
+ return (True);
+ }
+
+ if (*target == XA_DELETE(d)) {
+ if (!salt)
+ _XawTextZapSelection(ctx, NULL, True);
+ *value = NULL;
+ *type = XA_NULL(d);
+ *length = 0;
+ *format = 32;
+ return (True);
+ }
+
+ if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type,
+ (XPointer *)value, length, format))
+ return (True);
+
+ /* else */
+ return (False);
+}
+
+/*
+ * Function:
+ * GetCutBuffferNumber
+ *
+ * Parameters:
+ * atom - atom to check
+ *
+ * Description:
+ * Returns the number of the cut buffer.
+ *
+ * Returns:
+ * The number of the cut buffer representing this atom or NOT_A_CUT_BUFFER
+ */
+#define NOT_A_CUT_BUFFER -1
+static int
+GetCutBufferNumber(Atom atom)
+{
+ if (atom == XA_CUT_BUFFER0) return (0);
+ if (atom == XA_CUT_BUFFER1) return (1);
+ if (atom == XA_CUT_BUFFER2) return (2);
+ if (atom == XA_CUT_BUFFER3) return (3);
+ if (atom == XA_CUT_BUFFER4) return (4);
+ if (atom == XA_CUT_BUFFER5) return (5);
+ if (atom == XA_CUT_BUFFER6) return (6);
+ if (atom == XA_CUT_BUFFER7) return (7);
+ return (NOT_A_CUT_BUFFER);
+}
+
+static void
+TextLoseSelection(Widget w, Atom *selection)
+{
+ TextWidget ctx = (TextWidget)w;
+ Atom *atomP;
+ int i;
+ XawTextSelectionSalt*salt, *prevSalt, *nextSalt;
+
+ atomP = ctx->text.s.selections;
+ for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++)
+ if ((*selection == *atomP)
+ || (GetCutBufferNumber(*atomP) != NOT_A_CUT_BUFFER))
+ *atomP = (Atom)0;
+
+ while (ctx->text.s.atom_count
+ && ctx->text.s.selections[ctx->text.s.atom_count - 1] == 0)
+ ctx->text.s.atom_count--;
+
+ /*
+ * Must walk the selection list in opposite order from UnsetSelection
+ */
+ atomP = ctx->text.s.selections;
+ for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++)
+ if (*atomP == (Atom)0) {
+ *atomP = ctx->text.s.selections[--ctx->text.s.atom_count];
+ while (ctx->text.s.atom_count
+ && ctx->text.s.selections[ctx->text.s.atom_count-1] == 0)
+ ctx->text.s.atom_count--;
+ }
+
+ if (ctx->text.s.atom_count == 0)
+ ModifySelection(ctx, ctx->text.insertPos, ctx->text.insertPos);
+
+ prevSalt = 0;
+ for (salt = ctx->text.salt; 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) {
+ XtFree ((char *) salt->s.selections);
+ XtFree (salt->contents);
+ if (prevSalt)
+ prevSalt->next = nextSalt;
+ else
+ ctx->text.salt = nextSalt;
+ XtFree((char *)salt);
+ }
+ else
+ prevSalt = salt;
+ }
+}
+
+void
+_XawTextSaltAwaySelection(TextWidget ctx, Atom *selections, int num_atoms)
+{
+ XawTextSelectionSalt *salt;
+ int i, j;
+
+ for (i = 0; i < num_atoms; i++)
+ TextLoseSelection((Widget)ctx, selections + i);
+ if (num_atoms == 0)
+ return;
+ salt = (XawTextSelectionSalt *)
+ XtMalloc((unsigned)sizeof(XawTextSelectionSalt));
+ if (!salt)
+ return;
+ salt->s.selections = (Atom *)XtMalloc((unsigned)(num_atoms * sizeof(Atom)));
+ if (!salt->s.selections) {
+ XtFree((char *)salt);
+ return;
+ }
+ salt->s.left = ctx->text.s.left;
+ salt->s.right = ctx->text.s.right;
+ salt->s.type = ctx->text.s.type;
+ salt->contents = _XawTextGetSTRING(ctx, ctx->text.s.left, ctx->text.s.right);
+ if (XawTextFormat(ctx, XawFmtWide)) {
+ XTextProperty textprop;
+ if (XwcTextListToTextProperty(XtDisplay((Widget)ctx),
+ (wchar_t**)(&(salt->contents)), 1,
+ XCompoundTextStyle,
+ &textprop) < Success) {
+ XtFree(salt->contents);
+ salt->length = 0;
+ return;
+ }
+ XtFree(salt->contents);
+ salt->contents = (char *)textprop.value;
+ salt->length = textprop.nitems;
+ }
+ else
+ salt->length = strlen (salt->contents);
+ salt->next = ctx->text.salt;
+ ctx->text.salt = salt;
+ j = 0;
+ for (i = 0; i < num_atoms; i++) {
+ if (GetCutBufferNumber (selections[i]) == NOT_A_CUT_BUFFER) {
+ salt->s.selections[j++] = selections[i];
+ XtOwnSelection((Widget)ctx, selections[i], ctx->text.time,
+ TextConvertSelection, TextLoseSelection, NULL);
+ }
+ }
+ salt->s.atom_count = j;
+}
+
+static void
+_SetSelection(TextWidget ctx, XawTextPosition left, XawTextPosition right,
+ Atom *selections, Cardinal count)
+{
+#ifndef OLDXAW
+ Cardinal i;
+ XawTextPosition pos;
+ TextSrcObject src = (TextSrcObject)ctx->text.source;
+
+ for (i = 0; i < src->textSrc.num_text; i++) {
+ TextWidget tw = (TextWidget)src->textSrc.text[i];
+ Bool needs_updating = tw->text.old_insert < 0;
+ Bool showposition = tw->text.showposition;
+
+ if (needs_updating) {
+ tw->text.showposition = False;
+ _XawTextPrepareToUpdate(tw);
+ }
+#else
+ TextWidget tw = ctx;
+ XawTextPosition pos;
+#endif /* OLDXAW */
+
+ if (left < tw->text.s.left) {
+ pos = Min(right, tw->text.s.left);
+ _XawTextNeedsUpdating(tw, left, pos);
+ }
+ if (left > tw->text.s.left) {
+ pos = Min(left, tw->text.s.right);
+ _XawTextNeedsUpdating(tw, tw->text.s.left, pos);
+ }
+ if (right < tw->text.s.right) {
+ pos = Max(right, tw->text.s.left);
+ _XawTextNeedsUpdating(tw, pos, tw->text.s.right);
+ }
+ if (right > tw->text.s.right) {
+ pos = Max(left, tw->text.s.right);
+ _XawTextNeedsUpdating(tw, pos, right);
+ }
+
+ tw->text.s.left = left;
+ tw->text.s.right = right;
+
+#ifndef OLDXAW
+ if (needs_updating) {
+ _XawTextExecuteUpdate(tw);
+ tw->text.showposition = showposition;
+ }
+ }
+#endif /* OLDXAW */
+
+ SrcSetSelection(ctx->text.source, left, right,
+ (count == 0) ? None : selections[0]);
+
+ if (left < right) {
+ Widget w = (Widget)ctx;
+ int buffer;
+
+ while (count) {
+ Atom selection = selections[--count];
+
+ /*
+ * If this is a cut buffer
+ */
+ if ((buffer = GetCutBufferNumber(selection)) != NOT_A_CUT_BUFFER) {
+ unsigned char *ptr, *tptr;
+ unsigned int amount, max_len = MAX_CUT_LEN(XtDisplay(w));
+ unsigned long len;
+
+ tptr= ptr= (unsigned char *)_XawTextGetSTRING(ctx,
+ ctx->text.s.left,
+ ctx->text.s.right);
+ if (XawTextFormat(ctx, XawFmtWide)) {
+ /*
+ * Only XA_STRING(Latin 1) is allowed in CUT_BUFFER,
+ * so we get it from wchar string, then free the wchar string
+ */
+ XTextProperty textprop;
+
+ if (XwcTextListToTextProperty(XtDisplay(w), (wchar_t**)&ptr,
+ 1, XStringStyle, &textprop)
+ < Success){
+ XtFree((char *)ptr);
+ return;
+ }
+ XtFree((char *)ptr);
+ tptr = ptr = textprop.value;
+ }
+ if (buffer == 0) {
+ _CreateCutBuffers(XtDisplay(w));
+ XRotateBuffers(XtDisplay(w), 1);
+ }
+ amount = Min ((len = strlen((char *)ptr)), max_len);
+ XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0),
+ selection, XA_STRING, 8, PropModeReplace,
+ ptr, amount);
+
+ while (len > max_len) {
+ len -= max_len;
+ tptr += max_len;
+ amount = Min (len, max_len);
+ XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0),
+ selection, XA_STRING, 8, PropModeAppend,
+ tptr, amount);
+ }
+ XtFree ((char *)ptr);
+ }
+ else /* This is a real selection */
+ XtOwnSelection(w, selection, ctx->text.time, TextConvertSelection,
+ TextLoseSelection, NULL);
+ }
+ }
+ else
+ XawTextUnsetSelection((Widget)ctx);
+}
+
+#ifndef OLDXAW
+void
+_XawTextSetLineAndColumnNumber(TextWidget ctx, Bool force)
+{
+ int line_number, column_number;
+
+ if (ctx->text.old_insert != ctx->text.insertPos &&
+ ctx->text.lt.base_line < 0) {
+ ctx->text.lt.base_line = 0;
+ (void)_BuildLineTable(ctx, ctx->text.lt.top, 0);
+ }
+
+ line_number = ResolveLineNumber(ctx);
+ column_number = ResolveColumnNumber(ctx);
+
+ if (force || (ctx->text.column_number != column_number
+ || ctx->text.line_number != line_number)) {
+ XawTextPositionInfo info;
+
+ ctx->text.line_number = info.line_number = line_number;
+ ctx->text.column_number = info.column_number = column_number;
+ info.insert_position = ctx->text.insertPos;
+ info.last_position = ctx->text.lastPos;
+ info.overwrite_mode = ctx->text.overwrite;
+
+ XtCallCallbacks((Widget)ctx, XtNpositionCallback, (XtPointer)&info);
+ }
+}
+
+static int
+ResolveColumnNumber(TextWidget ctx)
+{
+ Widget src = ctx->text.source;
+ short column_number = 0;
+ XawTextPosition position;
+ XawTextBlock block;
+ unsigned long format = _XawTextFormat(ctx);
+ 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;
+
+ if (ctx->text.lt.base_line < 1)
+ return (ctx->text.column_number);
+
+ position = SrcScan(src, ctx->text.insertPos, XawstEOL, XawsdLeft, 1, False);
+ XawTextSourceRead(src, position, &block, ctx->text.insertPos - position);
+
+ for (; position < ctx->text.insertPos; position++) {
+ if (position - block.firstPos >= block.length)
+ XawTextSourceRead(src, position, &block, ctx->text.insertPos - position);
+ if ((format == XawFmt8Bit && block.ptr[position - block.firstPos] == '\t') ||
+ (format == XawFmtWide && ((wchar_t*)block.ptr)[position - block.firstPos] == _Xaw_atowc(XawTAB))) {
+ while (tab_base + tab_column <= column_number) {
+ if (tab_count) {
+ for (; tab_index < tab_count; ++tab_index)
+ if (tab_base + char_tabs[tab_index] > column_number) {
+ tab_column = char_tabs[tab_index];
+ break;
+ }
+ if (tab_index >= tab_count) {
+ tab_base += char_tabs[tab_count - 1];
+ tab_column = tab_index = 0;
+ }
+ }
+ else
+ tab_column += DEFAULT_TAB_SIZE;
+ }
+ column_number = tab_base + tab_column;
+ }
+ else
+ ++column_number;
+ if (column_number >= 16384) {
+ column_number = 16383;
+ break;
+ }
+ }
+
+ return (column_number);
+}
+#endif /* OLDXAW */
+
+void
+_XawTextSourceChanged(Widget w, XawTextPosition left, XawTextPosition right,
+ XawTextBlock *block, int lines)
+{
+ TextWidget ctx = (TextWidget)w;
+ Widget src = ctx->text.source;
+ XawTextPosition update_from, update_to, top;
+ Boolean update_disabled;
+ int delta, line, line_from;
+
+ if (left < ctx->text.old_insert) {
+ XawTextPosition old_insert = ctx->text.old_insert;
+
+ if (right < ctx->text.old_insert)
+ old_insert -= right - left;
+ else
+ old_insert = left;
+
+ ctx->text.insertPos = old_insert + block->length;
+ }
+#ifndef OLDXAW
+ if (left <= ctx->text.lt.top) {
+ if (left + block->length - (right - left) < ctx->text.lt.top) {
+ ctx->text.source_changed = SRC_CHANGE_BEFORE;
+ ctx->text.lt.base_line += lines;
+ }
+ else
+ ctx->text.source_changed = SRC_CHANGE_OVERLAP;
+ }
+ else
+ ctx->text.source_changed = SRC_CHANGE_AFTER;
+#endif
+
+ update_from = left;
+ update_to = left + block->length;
+ update_to = SrcScan(src, update_to, XawstEOL, XawsdRight, 1, False);
+ delta = block->length - (right - left);
+ if (delta < 0)
+ ctx->text.clear_to_eol = True;
+ if (update_to == update_from)
+ ++update_to;
+ update_disabled = ctx->text.update_disabled;
+ ctx->text.update_disabled = True;
+ ctx->text.lastPos = XawTextGetLastPosition(ctx);
+ top = ctx->text.lt.info[0].position;
+
+ XawTextUnsetSelection((Widget)ctx);
+
+ if (delta) {
+ int i;
+ XmuSegment *seg;
+
+ for (seg = ctx->text.update->segment; seg; seg = seg->next) {
+ if (seg->x1 > (int)left)
+ break;
+ else if (seg->x2 > (int)left) {
+ seg->x2 += delta;
+ seg = seg->next;
+ break;
+ }
+ }
+ for (; seg; seg = seg->next) {
+ seg->x1 += delta;
+ seg->x2 += delta;
+ }
+ XmuOptimizeScanline(ctx->text.update);
+
+ for (i = 0; i <= ctx->text.lt.lines; i++)
+ if (ctx->text.lt.info[i].position > left)
+ break;
+ for (; i <= ctx->text.lt.lines; i++)
+ ctx->text.lt.info[i].position += delta;
+ }
+
+ if (top != ctx->text.lt.info[0].position) {
+ line_from = line = 0;
+ ctx->text.lt.top = top = SrcScan(src, ctx->text.lt.info[0].position,
+ XawstEOL, XawsdLeft, 1, False);
+ update_from = top;
+ }
+ else {
+ line_from = line = LineForPosition(ctx, update_from + delta);
+ top = ctx->text.lt.info[line].position;
+ }
+
+ if (line > 0 && ctx->text.wrap == XawtextWrapWord) {
+ --line;
+ top = ctx->text.lt.info[line].position;
+ }
+
+ (void)_BuildLineTable(ctx, top, line);
+
+ if (ctx->text.wrap == XawtextWrapWord) {
+ if (line_from != LineForPosition(ctx, update_from)
+ || line_from != LineForPosition(ctx, update_to)) {
+ ctx->text.clear_to_eol = True;
+ update_from = SrcScan(src, update_from,
+ XawstWhiteSpace, XawsdLeft, 1, True);
+ if (update_to >= ctx->text.lastPos)
+ /* this is not an error, it just tells _BuildLineTable to
+ * clear to the bottom of the window. The value of update_to
+ * should not be > ctx->text.lastPos.
+ */
+ ++update_to;
+ }
+ }
+ else if (!ctx->text.clear_to_eol) {
+ if (LineForPosition(ctx, update_from)
+ != LineForPosition(ctx, update_to))
+ ctx->text.clear_to_eol = True;
+ }
+
+ _XawTextNeedsUpdating(ctx, update_from, update_to);
+ ctx->text.update_disabled = update_disabled;
+}
+
+/*
+ * Function:
+ * _XawTextReplace
+ *
+ * Parameters:
+ * ctx - text widget
+ * left - left offset
+ * right - right offset
+ * block - text block
+ *
+ * Description:
+ * Replaces the text between left and right by the text in block.
+ * Does all the required calculations of offsets, and rebuild the
+ * the line table, from the insertion point (or previous line, if
+ * wrap mode is 'word').
+ *
+ * Returns:
+ * XawEditDone - success
+ * any other value - error code
+ */
+int
+_XawTextReplace(TextWidget ctx, XawTextPosition left, XawTextPosition right,
+ XawTextBlock *block)
+{
+ Arg args[1];
+ Widget src;
+ XawTextEditType edit_mode;
+
+ if (left == right && block->length == 0)
+ return (XawEditDone);
+
+ src = ctx->text.source;
+ XtSetArg(args[0], XtNeditType, &edit_mode);
+ XtGetValues(src, args, 1);
+
+ if (edit_mode == XawtextAppend) {
+ if (block->length == 0)
+ return (XawEditError);
+ ctx->text.insertPos = ctx->text.lastPos;
+ }
+
+#ifndef OLDXAW
+ return (SrcReplace(src, left, right, block));
+#else
+ if (SrcReplace(src, left, right, block) == XawEditDone) {
+ _XawTextSourceChanged((Widget)ctx, left, right, block, 0);
+
+ return (XawEditDone);
+ }
+
+ return (XawEditError);
+#endif
+}
+
+/*
+ * This routine will display text between two arbitrary source positions.
+ * In the event that this span contains highlighted text for the selection,
+ * only that portion will be displayed highlighted.
+ */
+static void
+OldDisplayText(Widget w, XawTextPosition left, XawTextPosition right)
+{
+ static XmuSegment segment;
+ static XmuScanline next;
+ static XmuScanline scanline = {0, &segment, &next};
+ static XmuArea area = {&scanline};
+
+ TextWidget ctx = (TextWidget)w;
+ int x, y, line;
+ XawTextPosition start, end, last, final;
+ XmuScanline *scan;
+ XmuSegment *seg;
+ XmuArea *clip = NULL;
+ Bool cleol = ctx->text.clear_to_eol;
+ Bool has_selection = ctx->text.s.right > ctx->text.s.left;
+
+ left = left < ctx->text.lt.top ? ctx->text.lt.top : left;
+
+ if (left > right || !LineAndXYForPosition(ctx, left, &line, &x, &y))
+ return;
+
+ last = XawTextGetLastPosition(ctx);
+ segment.x2 = (int)XtWidth(ctx) - ctx->text.r_margin.right;
+
+ if (cleol)
+ clip = XmuCreateArea();
+
+ for (start = left; start < right && line < ctx->text.lt.lines; line++) {
+ if ((end = ctx->text.lt.info[line + 1].position) > right)
+ end = right;
+
+ final = end;
+ if (end > last)
+ end = last;
+
+ if (end > start) {
+ if (!has_selection
+ || (start >= ctx->text.s.right || end <= ctx->text.s.left))
+ _XawTextSinkDisplayText(ctx->text.sink, x, y, start, end, False);
+ else if (start >= ctx->text.s.left && end <= ctx->text.s.right)
+ _XawTextSinkDisplayText(ctx->text.sink, x, y, start, end, True);
+ else {
+ OldDisplayText(w, start, ctx->text.s.left);
+ OldDisplayText(w, Max(start, ctx->text.s.left),
+ Min(end, ctx->text.s.right));
+ OldDisplayText(w, ctx->text.s.right, end);
+ }
+ }
+
+ x = ctx->text.left_margin;
+ if (cleol) {
+ segment.x1 = ctx->text.lt.info[line].textWidth + x;
+ if (XmuValidSegment(&segment)) {
+ scanline.y = y;
+ next.y = ctx->text.lt.info[line + 1].y;
+ XmuAreaOr(clip, &area);
+ }
+ }
+
+ start = final;
+ y = ctx->text.lt.info[line + 1].y;
+ }
+
+ if (cleol) {
+ for (scan = clip->scanline; scan && scan->next; scan = scan->next)
+ for (seg = scan->segment; seg; seg = seg->next)
+ SinkClearToBG(ctx->text.sink,
+ seg->x1, scan->y,
+ seg->x2 - seg->x1, scan->next->y - scan->y);
+ XmuDestroyArea(clip);
+ }
+}
+
+#ifndef OLDXAW
+/*ARGSUSED*/
+static void
+DisplayText(Widget w, XawTextPosition left, XawTextPosition right)
+{
+ static XmuSegment segment;
+ static XmuScanline next;
+ static XmuScanline scanline = {0, &segment, &next};
+ static XmuArea area = {&scanline};
+
+ TextWidget ctx = (TextWidget)w;
+ int y, line;
+ XawTextPosition from, to, lastPos;
+ Bool cleol = ctx->text.clear_to_eol;
+ Bool has_selection = ctx->text.s.right > ctx->text.s.left;
+ XawTextPaintList *paint_list;
+
+ left = left < ctx->text.lt.top ? ctx->text.lt.top : left;
+
+ if (left > right || !IsPositionVisible(ctx, left))
+ return;
+
+ line = LineForPosition(ctx, left);
+ y = ctx->text.lt.info[line].y;
+ segment.x2 = (int)XtWidth(ctx) - ctx->text.r_margin.right;
+ lastPos = XawTextGetLastPosition(ctx);
+
+ paint_list = ((TextSinkObject)ctx->text.sink)->text_sink.paint;
+
+ for (from = left; from < right && line < ctx->text.lt.lines; line++) {
+ if ((to = ctx->text.lt.info[line + 1].position) > right)
+ to = right;
+
+ if (to > lastPos)
+ to = lastPos;
+
+ if (from < to) {
+ if (!has_selection
+ || (from >= ctx->text.s.right || to <= ctx->text.s.left))
+ XawTextSinkPreparePaint(ctx->text.sink, y, line, from, to, False);
+ else if (from >= ctx->text.s.left && to <= ctx->text.s.right)
+ XawTextSinkPreparePaint(ctx->text.sink, y, line, from, to, True);
+ else {
+ XawTextSinkPreparePaint(ctx->text.sink, y, line, from,
+ ctx->text.s.left, False);
+ XawTextSinkPreparePaint(ctx->text.sink, y, line,
+ XawMax(from, ctx->text.s.left),
+ XawMin(to, ctx->text.s.right), True);
+ XawTextSinkPreparePaint(ctx->text.sink, y, line,
+ ctx->text.s.right, to, False);
+ }
+ }
+
+ if (cleol) {
+ segment.x1 = ctx->text.lt.info[line].textWidth + ctx->text.left_margin;
+ if (XmuValidSegment(&segment)) {
+ scanline.y = y;
+ next.y = ctx->text.lt.info[line + 1].y;
+ XmuAreaOr(paint_list->clip, &area);
+ }
+ }
+ y = ctx->text.lt.info[line + 1].y;
+ from = to;
+ }
+
+ /* clear to the bottom of the window */
+ if (cleol && line >= ctx->text.lt.lines) {
+ segment.x1 = ctx->text.left_margin;
+ if (XmuValidSegment(&segment)) {
+ scanline.y = y;
+ next.y = (int)XtHeight(ctx) - (int)ctx->text.margin.bottom;
+ XmuAreaOr(paint_list->clip, &area);
+ }
+ }
+}
+#endif
+
+/*
+ * This routine implements multi-click selection in a hardwired manner.
+ * It supports multi-click entity cycling (char, word, line, file) and mouse
+ * motion adjustment of the selected entitie (i.e. select a word then, with
+ * button still down, adjust wich word you really meant by moving the mouse).
+ * [NOTE: This routine is to be replaced by a set of procedures that
+ * will allows clients to implements a wide class of draw through and
+ * multi-click selection user interfaces.]
+ */
+static void
+DoSelection(TextWidget ctx, XawTextPosition pos, Time time, Bool motion)
+{
+ XawTextPosition newLeft, newRight;
+ XawTextSelectType newType, *sarray;
+ Widget src = ctx->text.source;
+
+ if (motion)
+ newType = ctx->text.s.type;
+ else {
+ if ((abs((long) time - (long) ctx->text.lasttime) < MULTI_CLICK_TIME)
+ && (pos >= ctx->text.s.left && pos <= ctx->text.s.right)) {
+ sarray = ctx->text.sarray;
+ for (; *sarray != XawselectNull && *sarray != ctx->text.s.type;
+ sarray++)
+ ;
+ if (*sarray == XawselectNull)
+ newType = *(ctx->text.sarray);
+ else {
+ newType = *(sarray + 1);
+ if (newType == XawselectNull)
+ newType = *(ctx->text.sarray);
+ }
+ }
+ else /* single-click event */
+ newType = *(ctx->text.sarray);
+
+ ctx->text.lasttime = time;
+ }
+ switch (newType) {
+ case XawselectPosition:
+ newLeft = newRight = pos;
+ break;
+ case XawselectChar:
+ newLeft = pos;
+ newRight = SrcScan(src, pos, XawstPositions, XawsdRight, 1, False);
+ break;
+ case XawselectWord:
+ case XawselectParagraph:
+ case XawselectAlphaNumeric: {
+ XawTextScanType stype;
+
+ if (newType == XawselectWord)
+ stype = XawstWhiteSpace;
+ else if (newType == XawselectParagraph)
+ stype = XawstParagraph;
+ else
+ stype = XawstAlphaNumeric;
+
+ /*
+ * Somewhat complicated, but basically I treat the space between
+ * two objects as another object. The object that I am currently
+ * in then becomes the end of the selection.
+ *
+ * Chris Peterson - 4/19/90.
+ */
+ newRight = SrcScan(ctx->text.source, pos, stype,
+ XawsdRight, 1, False);
+ newRight = SrcScan(ctx->text.source, newRight, stype,
+ XawsdLeft, 1, False);
+
+ if (pos != newRight)
+ newLeft = SrcScan(ctx->text.source, pos, stype,
+ XawsdLeft, 1, False);
+ else
+ newLeft = pos;
+
+ newLeft =SrcScan(ctx->text.source, newLeft, stype,
+ XawsdRight, 1, False);
+
+ if (newLeft > newRight) {
+ XawTextPosition temp = newLeft;
+ newLeft = newRight;
+ newRight = temp;
+ }
+ } break;
+ case XawselectLine:
+ newLeft = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, False);
+ newRight = SrcScan(src, pos, XawstEOL, XawsdRight, 1, False);
+ break;
+ case XawselectAll:
+ newLeft = SrcScan(src, pos, XawstAll, XawsdLeft, 1, False);
+ newRight = SrcScan(src, pos, XawstAll, XawsdRight, 1, False);
+ break;
+ default:
+ XtAppWarning(XtWidgetToApplicationContext((Widget) ctx),
+ "Text Widget: empty selection array.");
+ return;
+ }
+
+ if (newLeft != ctx->text.s.left || newRight != ctx->text.s.right
+ || newType != ctx->text.s.type) {
+ ModifySelection(ctx, newLeft, newRight);
+ if (pos - ctx->text.s.left < ctx->text.s.right - pos)
+ ctx->text.insertPos = newLeft;
+ else
+ ctx->text.insertPos = newRight;
+ ctx->text.s.type = newType;
+ }
+ if (!motion) { /* setup so we can freely mix select extend calls*/
+ ctx->text.origSel.type = ctx->text.s.type;
+ ctx->text.origSel.left = ctx->text.s.left;
+ ctx->text.origSel.right = ctx->text.s.right;
+
+ if (pos >= ctx->text.s.left + (ctx->text.s.right - ctx->text.s.left) / 2)
+ ctx->text.extendDir = XawsdRight;
+ else
+ ctx->text.extendDir = XawsdLeft;
+ }
+}
+
+/*
+ * This routine implements extension of the currently selected text in
+ * the "current" mode (i.e. char word, line, etc.). It worries about
+ * extending from either end of the selection and handles the case when you
+ * cross through the "center" of the current selection (e.g. switch which
+ * end you are extending!).
+ */
+static void
+ExtendSelection(TextWidget ctx, XawTextPosition pos, Bool motion)
+{
+ XawTextScanDirection dir;
+
+ if (!motion) { /* setup for extending selection */
+ if (ctx->text.s.left == ctx->text.s.right) /* no current selection. */
+ ctx->text.s.left = ctx->text.s.right = ctx->text.insertPos;
+ else {
+ ctx->text.origSel.left = ctx->text.s.left;
+ ctx->text.origSel.right = ctx->text.s.right;
+ }
+
+ ctx->text.origSel.type = ctx->text.s.type;
+
+ if (pos >= ctx->text.s.left + (ctx->text.s.right - ctx->text.s.left) / 2)
+ ctx->text.extendDir = XawsdRight;
+ else
+ ctx->text.extendDir = XawsdLeft;
+ }
+ else /* check for change in extend direction */
+ if ((ctx->text.extendDir == XawsdRight &&
+ pos <= ctx->text.origSel.left) ||
+ (ctx->text.extendDir == XawsdLeft &&
+ pos >= ctx->text.origSel.right)) {
+ ctx->text.extendDir = (ctx->text.extendDir == XawsdRight) ?
+ XawsdLeft : XawsdRight;
+ ModifySelection(ctx, ctx->text.origSel.left, ctx->text.origSel.right);
+ }
+
+ dir = ctx->text.extendDir;
+ switch (ctx->text.s.type) {
+ case XawselectWord:
+ case XawselectParagraph:
+ case XawselectAlphaNumeric: {
+ XawTextPosition left_pos, right_pos;
+ XawTextScanType stype;
+
+ if (ctx->text.s.type == XawselectWord)
+ stype = XawstWhiteSpace;
+ else if (ctx->text.s.type == XawselectParagraph)
+ stype = XawstParagraph;
+ else
+ stype = XawstAlphaNumeric;
+
+ /*
+ * Somewhat complicated, but basically I treat the space between
+ * two objects as another object. The object that I am currently
+ * in then becomes the end of the selection.
+ *
+ * Chris Peterson - 4/19/90.
+ */
+ right_pos = SrcScan(ctx->text.source, pos, stype,
+ XawsdRight, 1, False);
+ right_pos =SrcScan(ctx->text.source, right_pos, stype,
+ XawsdLeft, 1, False);
+
+ if (pos != right_pos)
+ left_pos = SrcScan(ctx->text.source, pos, stype,
+ XawsdLeft, 1, False);
+ else
+ left_pos = pos;
+
+ left_pos =SrcScan(ctx->text.source, left_pos, stype,
+ XawsdRight, 1, False);
+
+ if (dir == XawsdLeft)
+ pos = Min(left_pos, right_pos);
+ else /* dir == XawsdRight */
+ pos = Max(left_pos, right_pos);
+ } break;
+ case XawselectLine:
+ pos = SrcScan(ctx->text.source, pos, XawstEOL,
+ dir, 1, dir == XawsdRight);
+ break;
+ case XawselectAll:
+ pos = ctx->text.insertPos;
+ /*FALLTHROUGH*/
+ case XawselectPosition:
+ default:
+ break;
+ }
+
+ if (dir == XawsdRight)
+ ModifySelection(ctx, ctx->text.s.left, pos);
+ else
+ ModifySelection(ctx, pos, ctx->text.s.right);
+
+ ctx->text.insertPos = pos;
+}
+
+/*
+ * Function:
+ * _XawTextClearAndCenterDisplay
+ *
+ * Parameters:
+ * ctx - text widget
+ *
+ * Description:
+ * Redraws the display with the cursor in insert point
+ * centered vertically.
+ */
+void
+_XawTextClearAndCenterDisplay(TextWidget ctx)
+{
+ int left_margin = ctx->text.left_margin;
+ Bool visible = IsPositionVisible(ctx, ctx->text.insertPos);
+
+ _XawTextShowPosition(ctx);
+
+ if (XtIsRealized((Widget)ctx) && visible &&
+ left_margin == ctx->text.left_margin) {
+ int insert_line = LineForPosition(ctx, ctx->text.insertPos);
+ int scroll_by = insert_line - (ctx->text.lt.lines >> 1);
+ Boolean clear_to_eol = ctx->text.clear_to_eol;
+
+ XawTextScroll(ctx, scroll_by, 0);
+ SinkClearToBG(ctx->text.sink, 0, 0, XtWidth(ctx), XtHeight(ctx));
+ ClearWindow(ctx);
+ clear_to_eol = ctx->text.clear_to_eol;
+ ctx->text.clear_to_eol = False;
+ FlushUpdate(ctx);
+ ctx->text.clear_to_eol = clear_to_eol;
+ }
+}
+
+/*
+ * Internal redisplay entire window
+ * Legal to call only if widget is realized
+ */
+static void
+DisplayTextWindow(Widget w)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ _XawTextBuildLineTable(ctx, ctx->text.lt.top, False);
+ ClearWindow(ctx);
+}
+
+static void
+TextSinkResize(Widget w)
+{
+ if (w && XtClass(w)->core_class.resize)
+ XtClass(w)->core_class.resize(w);
+}
+
+/* ARGSUSED */
+void
+_XawTextCheckResize(TextWidget ctx)
+{
+ return;
+}
+
+/*
+ * Converts (params, num_params) to a list of atoms & caches the
+ * list in the TextWidget instance.
+ */
+Atom *
+_XawTextSelectionList(TextWidget ctx, String *list, Cardinal nelems)
+{
+ Atom *sel = ctx->text.s.selections;
+ Display *dpy = XtDisplay((Widget)ctx);
+ int n;
+
+ if (nelems > (Cardinal)ctx->text.s.array_size) {
+ sel = (Atom *)XtRealloc((char *)sel, sizeof(Atom) * nelems);
+ ctx->text.s.array_size = nelems;
+ ctx->text.s.selections = sel;
+ }
+ for (n = nelems; --n >= 0; sel++, list++)
+ *sel = XInternAtom(dpy, *list, False);
+ ctx->text.s.atom_count = nelems;
+
+ return (ctx->text.s.selections);
+}
+
+/*
+ * Function:
+ * SetSelection
+ *
+ * Parameters:
+ * ctx - text widget
+ * defaultSel - default selection
+ * l - left and right ends of the selection
+ * r - ""
+ * list - the selection list (as strings).
+ * nelems - ""
+ *
+ * Description:
+ * Sets the current selection.
+ *
+ * Note:
+ * if (ctx->text.s.left >= ctx->text.s.right) then the selection is unset
+ */
+void
+_XawTextSetSelection(TextWidget ctx, XawTextPosition l, XawTextPosition r,
+ String *list, Cardinal nelems)
+{
+ if (nelems == 1 && !strcmp (list[0], "none"))
+ return;
+ if (nelems == 0) {
+ String defaultSel = "PRIMARY";
+ list = &defaultSel;
+ nelems = 1;
+ }
+ _SetSelection(ctx, l, r, _XawTextSelectionList(ctx, list, nelems), nelems);
+}
+
+/*
+ * Function:
+ * ModifySelection
+ *
+ * Parameters:
+ * ctx - text widget
+ * left - left and right ends of the selection
+ * right - ""
+ *
+ * Description:
+ * Modifies the current selection.
+ *
+ * Note:
+ * if (ctx->text.s.left >= ctx->text.s.right) then the selection is unset
+ */
+static void
+ModifySelection(TextWidget ctx, XawTextPosition left, XawTextPosition right)
+{
+ if (left == right)
+ ctx->text.insertPos = left;
+ _SetSelection(ctx, left, right, NULL, 0);
+}
+
+/*
+ * This routine is used to perform various selection functions. The goal is
+ * to be able to specify all the more popular forms of draw-through and
+ * multi-click selection user interfaces from the outside.
+ */
+void
+_XawTextAlterSelection(TextWidget ctx, XawTextSelectionMode mode,
+ XawTextSelectionAction action, String *params,
+ Cardinal *num_params)
+{
+ XawTextPosition position;
+ Boolean flag;
+
+ /*
+ * This flag is used by TextPop.c:DoReplace() to determine if the selection
+ * is okay to use, or if it has been modified.
+ */
+ if (ctx->text.search != NULL)
+ ctx->text.search->selection_changed = True;
+
+ position = PositionForXY(ctx, (int) ctx->text.ev_x, (int) ctx->text.ev_y);
+
+ flag = (action != XawactionStart);
+ if (mode == XawsmTextSelect)
+ DoSelection(ctx, position, ctx->text.time, flag);
+ else /* mode == XawsmTextExtend */
+ ExtendSelection (ctx, position, flag);
+
+ if (action == XawactionEnd)
+ _XawTextSetSelection(ctx, ctx->text.s.left, ctx->text.s.right,
+ params, *num_params);
+}
+
+/*
+ * Function:
+ * UpdateTextInRectangle
+ *
+ * Parameters:
+ * ctx - the text widget
+ * rect - rectangle
+ *
+ * Description:
+ * Updates the text in the given rectangle
+ */
+static void
+UpdateTextInRectangle(TextWidget ctx, XRectangle *rect)
+{
+ XawTextLineTable *lt;
+ int line, y1, y2, x2;
+
+ y1 = rect->y;
+ y2 = y1 + rect->height;
+ x2 = rect->x + rect->width;
+
+ for (line = 0, lt = &ctx->text.lt; line < lt->lines; line++)
+ if (lt->info[line + 1].y > y1)
+ break;
+ for (; line <= lt->lines; line++) {
+ if (lt->info[line].y > y2)
+ break;
+ UpdateTextInLine(ctx, line, rect->x, x2);
+ }
+}
+
+/*
+ * This routine processes all "expose region" XEvents. In general, its job
+ * is to the best job at minimal re-paint of the text, displayed in the
+ * window, that it can.
+ */
+/* ARGSUSED */
+static void
+XawTextExpose(Widget w, XEvent *event, Region region)
+{
+ TextWidget ctx = (TextWidget)w;
+ Boolean clear_to_eol;
+ XRectangle expose;
+
+ if (event->type == Expose) {
+ expose.x = event->xexpose.x;
+ expose.y = event->xexpose.y;
+ expose.width = event->xexpose.width;
+ expose.height = event->xexpose.height;
+ }
+ else if (event->type == GraphicsExpose) {
+ expose.x = event->xgraphicsexpose.x;
+ expose.y = event->xgraphicsexpose.y;
+ expose.width = event->xgraphicsexpose.width;
+ expose.height = event->xgraphicsexpose.height;
+ }
+ else
+ return;
+
+ _XawTextPrepareToUpdate(ctx);
+
+ if (Superclass->core_class.expose)
+ (*Superclass->core_class.expose)(w, event, region);
+
+ clear_to_eol = ctx->text.clear_to_eol;
+ ctx->text.clear_to_eol = False;
+
+ UpdateTextInRectangle(ctx, &expose);
+ XawTextSinkGetCursorBounds(ctx->text.sink, &expose);
+ UpdateTextInRectangle(ctx, &expose);
+ SinkClearToBG(ctx->text.sink, expose.x, expose.y,
+ expose.width, expose.height);
+ _XawTextExecuteUpdate(ctx);
+ ctx->text.clear_to_eol = clear_to_eol;
+}
+
+/*
+ * This routine does all setup required to syncronize batched screen updates
+ */
+void
+_XawTextPrepareToUpdate(TextWidget ctx)
+{
+ if (ctx->text.old_insert < 0) {
+ InsertCursor((Widget)ctx, XawisOff);
+ ctx->text.showposition = False;
+ ctx->text.old_insert = ctx->text.insertPos;
+ ctx->text.clear_to_eol = False;
+#ifndef OLDXAW
+ ctx->text.source_changed = SRC_CHANGE_NONE;
+#endif
+ }
+}
+
+/*
+ * This is a private utility routine used by _XawTextExecuteUpdate. It
+ * processes all the outstanding update requests and merges update
+ * ranges where possible.
+ */
+static void
+FlushUpdate(TextWidget ctx)
+{
+ XmuSegment *seg;
+ void (*display_text)(Widget, XawTextPosition, XawTextPosition);
+
+ if (XtIsRealized((Widget)ctx)) {
+ ctx->text.s.right = XawMin(ctx->text.s.right, ctx->text.lastPos);
+ ctx->text.s.left = XawMin(ctx->text.s.left, ctx->text.s.right);
+
+#ifndef OLDXAW
+ if (XawTextSinkBeginPaint(ctx->text.sink) == False)
+#endif
+ display_text = OldDisplayText;
+#ifndef OLDXAW
+ else
+ display_text = DisplayText;
+#endif
+ for (seg = ctx->text.update->segment; seg; seg = seg->next)
+ (*display_text)((Widget)ctx,
+ (XawTextPosition)seg->x1,
+ (XawTextPosition)seg->x2);
+#ifndef OLDXAW
+ if (display_text != OldDisplayText) {
+ XawTextSinkDoPaint(ctx->text.sink);
+ XawTextSinkEndPaint(ctx->text.sink);
+ }
+#endif
+ }
+ (void)XmuScanlineXor(ctx->text.update, ctx->text.update);
+}
+
+static int
+CountLines(TextWidget ctx, XawTextPosition left, XawTextPosition right)
+{
+ if (ctx->text.wrap == XawtextWrapNever || left >= right)
+ return (1);
+ else {
+ XawTextPosition tmp;
+ int dim, lines = 0, wwidth = GetMaxTextWidth(ctx);
+
+ while (left < right) {
+ tmp = left;
+ XawTextSinkFindPosition(ctx->text.sink, left,
+ ctx->text.left_margin,
+ wwidth, ctx->text.wrap == XawtextWrapWord,
+ &left, &dim, &dim);
+ ++lines;
+ if (tmp == left)
+ ++left;
+ }
+
+ return (lines);
+ }
+ /*NOTREACHED*/
+}
+
+static int
+GetMaxTextWidth(TextWidget ctx)
+{
+ XRectangle cursor;
+ int width;
+
+ XawTextSinkGetCursorBounds(ctx->text.sink, &cursor);
+ width = (int)XtWidth(ctx) - RHMargins(ctx) - cursor.width;
+
+ return (XawMax(0, width));
+}
+
+/*
+ * Function:
+ * _XawTextShowPosition
+ *
+ * Parameters:
+ * ctx - the text widget to show the position
+ *
+ * Description:
+ * Makes sure the text cursor visible, scrolling the text window
+ * if required.
+ */
+void
+_XawTextShowPosition(TextWidget ctx)
+{
+ /*
+ * Variable scroll is used to avoid scanning large files to calculate
+ * line offsets
+ */
+ int hpixels, vlines;
+ XawTextPosition first, last, top, tmp;
+ Bool visible, scroll;
+
+ if (!XtIsRealized((Widget)ctx))
+ return;
+
+ /*
+ * Checks if a horizontal scroll is required
+ */
+ if (ctx->text.wrap == XawtextWrapNever) {
+ int x, vwidth, distance, dim;
+ XRectangle rect;
+
+ vwidth = (int)XtWidth(ctx) - RHMargins(ctx);
+ last = SrcScan(ctx->text.source, ctx->text.insertPos,
+ XawstEOL, XawsdLeft, 1, False);
+ XawTextSinkFindDistance(ctx->text.sink, last,
+ ctx->text.left_margin,
+ ctx->text.insertPos,
+ &distance, &first, &dim);
+ XawTextSinkGetCursorBounds(ctx->text.sink, &rect);
+ x = ctx->text.left_margin - ctx->text.r_margin.left;
+
+ if (x + distance + rect.width > vwidth)
+ hpixels = x + distance + rect.width - vwidth + (vwidth >> 2);
+ else if (x + distance < 0)
+ hpixels = x + distance - (vwidth >> 2);
+ else
+ hpixels = 0;
+ }
+ else
+ hpixels = 0;
+
+ visible = IsPositionVisible(ctx, ctx->text.insertPos);
+
+ /*
+ * If the cursor is already visible
+ */
+ if (!hpixels && visible)
+ return;
+
+ scroll = ctx->core.background_pixmap == XtUnspecifiedPixmap && !hpixels;
+ vlines = 0;
+ first = ctx->text.lt.top;
+
+ /*
+ * Needs to scroll the text window
+ */
+ if (visible)
+ top = ctx->text.lt.top;
+ else {
+ top = SrcScan(ctx->text.source, ctx->text.insertPos,
+ XawstEOL, XawsdLeft, 1, False);
+
+ /*
+ * Finds the nearest left position from ctx->text.insertPos
+ */
+ if (ctx->text.wrap != XawtextWrapNever) {
+ int dim, vwidth = GetMaxTextWidth(ctx);
+
+ last = top;
+ /*CONSTCOND*/
+ while (1) {
+ tmp = last;
+ XawTextSinkFindPosition(ctx->text.sink, last,
+ ctx->text.left_margin, vwidth,
+ ctx->text.wrap == XawtextWrapWord,
+ &last, &dim, &dim);
+ if (last == tmp)
+ ++last;
+ if (last <= ctx->text.insertPos)
+ top = last;
+ else
+ break;
+ }
+ }
+ }
+
+ if (scroll) {
+ if (ctx->text.insertPos < first) { /* Scroll Down */
+ while (first > top) {
+ last = first;
+ first = SrcScan(ctx->text.source, first,
+ XawstEOL, XawsdLeft, 2, False);
+ vlines -= CountLines(ctx, first, last);
+ if (-vlines >= ctx->text.lt.lines) {
+ scroll = False;
+ break;
+ }
+ }
+ }
+ else if (!visible) { /* Scroll Up */
+ while (first < top) {
+ last = first;
+ first = SrcScan(ctx->text.source, first,
+ XawstEOL, XawsdRight, 1, True);
+ vlines += CountLines(ctx, last, first);
+ if (vlines > ctx->text.lt.lines) {
+ scroll = False;
+ break;
+ }
+ }
+ }
+ else
+ scroll = False;
+ }
+
+ /*
+ * If a portion of the text that will be scrolled is visible
+ */
+ if (scroll)
+ XawTextScroll(ctx, vlines ? vlines - (ctx->text.lt.lines >> 1) : 0, 0);
+ /*
+ * Else redraw the entire text window
+ */
+ else {
+ ctx->text.left_margin -= hpixels;
+ if (ctx->text.left_margin > ctx->text.r_margin.left)
+ ctx->text.left_margin = ctx->text.margin.left =
+ ctx->text.r_margin.left;
+
+ if (!visible) {
+ vlines = ctx->text.lt.lines >> 1;
+ if (vlines)
+ top = SrcScan(ctx->text.source, ctx->text.insertPos,
+ XawstEOL, XawsdLeft, vlines + 1, False);
+
+ if (ctx->text.wrap != XawtextWrapNever) {
+ int dim;
+ int n_lines = CountLines(ctx, top, ctx->text.insertPos);
+ int vwidth = GetMaxTextWidth(ctx);
+
+ while (n_lines-- > vlines) {
+ tmp = top;
+ XawTextSinkFindPosition(ctx->text.sink, top,
+ ctx->text.left_margin,
+ vwidth,
+ ctx->text.wrap == XawtextWrapWord,
+ &top, &dim, &dim);
+ if (tmp == top)
+ ++top;
+ }
+ }
+ _XawTextBuildLineTable(ctx, top, True);
+ }
+ else
+ ClearWindow(ctx);
+ }
+ ctx->text.clear_to_eol = True;
+}
+
+#ifndef OLDXAW
+static int
+ResolveLineNumber(TextWidget ctx)
+{
+ int line_number = ctx->text.lt.base_line;
+ XawTextPosition position = ctx->text.lt.top;
+
+ if (ctx->text.lt.base_line < 1)
+ return (ctx->text.line_number);
+
+ if (ctx->text.wrap == XawtextWrapNever
+ && IsPositionVisible(ctx, ctx->text.insertPos))
+ line_number += LineForPosition(ctx, ctx->text.insertPos);
+ else if (position < ctx->text.insertPos) {
+ while (position < ctx->text.insertPos) {
+ position = SrcScan(ctx->text.source, position,
+ XawstEOL, XawsdRight, 1, True);
+ if (position <= ctx->text.insertPos) {
+ ++line_number;
+ if (position == ctx->text.lastPos) {
+ line_number -= !_XawTextSourceNewLineAtEOF(ctx->text.source);
+ break;
+ }
+ }
+ }
+ }
+ else if (position > ctx->text.insertPos) {
+ while (position > ctx->text.insertPos) {
+ position = SrcScan(ctx->text.source, position,
+ XawstEOL, XawsdLeft, 1, False);
+ if (--position >= ctx->text.insertPos)
+ --line_number;
+ }
+ }
+
+ return (line_number);
+}
+#endif
+
+/*
+ * This routine causes all batched screen updates to be performed
+ */
+void
+_XawTextExecuteUpdate(TextWidget ctx)
+{
+ if (ctx->text.update_disabled || ctx->text.old_insert < 0)
+ return;
+
+ if(ctx->text.old_insert != ctx->text.insertPos || ctx->text.showposition)
+ _XawTextShowPosition(ctx);
+
+ FlushUpdate(ctx);
+ InsertCursor((Widget)ctx, XawisOn);
+ ctx->text.old_insert = -1;
+#ifndef OLDXAW
+ _XawTextSetLineAndColumnNumber(ctx, False);
+#endif
+}
+
+static void
+XawTextDestroy(Widget w)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ DestroyHScrollBar(ctx);
+ DestroyVScrollBar(ctx);
+
+ XtFree((char *)ctx->text.s.selections);
+ XtFree((char *)ctx->text.lt.info);
+ XtFree((char *)ctx->text.search);
+ XmuDestroyScanline(ctx->text.update);
+ XtReleaseGC((Widget)ctx, ctx->text.gc);
+}
+
+/*
+ * by the time we are managed (and get this far) we had better
+ * have both a source and a sink
+ */
+static void
+XawTextResize(Widget w)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ PositionVScrollBar(ctx);
+ PositionHScrollBar(ctx);
+ TextSinkResize(ctx->text.sink);
+
+ ctx->text.showposition = True;
+ _XawTextBuildLineTable(ctx, ctx->text.lt.top, True);
+}
+
+/*
+ * This routine allow the application program to Set attributes.
+ */
+/*ARGSUSED*/
+static Boolean
+XawTextSetValues(Widget current, Widget request, Widget cnew,
+ ArgList args, Cardinal *num_args)
+{
+ TextWidget oldtw = (TextWidget)current;
+ TextWidget newtw = (TextWidget)cnew;
+ Boolean redisplay = False;
+ Boolean display_caret = newtw->text.display_caret;
+#ifndef OLDXAW
+ Boolean show_lc = False;
+#endif
+
+ newtw->text.display_caret = oldtw->text.display_caret;
+ _XawTextPrepareToUpdate(newtw);
+ newtw->text.display_caret = display_caret;
+
+ if (oldtw->text.r_margin.left != newtw->text.r_margin.left) {
+ newtw->text.left_margin = newtw->text.margin.left =
+ newtw->text.r_margin.left;
+ if (newtw->text.vbar != NULL) {
+ newtw->text.left_margin += XtWidth(newtw->text.vbar) +
+ XtBorderWidth(newtw->text.vbar);
+ }
+ redisplay = True;
+ }
+
+ if (oldtw->text.scroll_vert != newtw->text.scroll_vert) {
+ if (newtw->text.scroll_vert == XawtextScrollAlways)
+ CreateVScrollBar(newtw);
+ else
+ DestroyVScrollBar(newtw);
+
+ redisplay = True;
+ }
+
+ if (oldtw->text.r_margin.bottom != newtw->text.r_margin.bottom) {
+ newtw->text.margin.bottom = newtw->text.r_margin.bottom;
+ if (newtw->text.hbar != NULL)
+ newtw->text.margin.bottom += newtw->text.hbar->core.height +
+ newtw->text.hbar->core.border_width;
+ redisplay = True;
+ }
+
+ if (oldtw->text.scroll_horiz != newtw->text.scroll_horiz) {
+ if (newtw->text.scroll_horiz == XawtextScrollAlways)
+ CreateHScrollBar(newtw);
+ else
+ DestroyHScrollBar(newtw);
+
+ redisplay = True;
+ }
+
+ if (oldtw->text.source != newtw->text.source) {
+#ifndef OLDXAW
+ show_lc = True;
+ _XawSourceRemoveText(oldtw->text.source, cnew,
+ oldtw->text.source &&
+ XtParent(oldtw->text.source) == cnew);
+ _XawSourceAddText(newtw->text.source, cnew);
+#endif
+ _XawTextSetSource((Widget)newtw, newtw->text.source, newtw->text.lt.top,
+ newtw->text.insertPos);
+ }
+
+ newtw->text.redisplay_needed = False;
+ XtSetValues((Widget)newtw->text.source, args, *num_args);
+ XtSetValues((Widget)newtw->text.sink, args, *num_args);
+
+ if (oldtw->text.wrap != newtw->text.wrap
+ || oldtw->text.lt.top != newtw->text.lt.top
+ || oldtw->text.insertPos != newtw->text.insertPos
+ || oldtw->text.r_margin.right != newtw->text.r_margin.right
+ || oldtw->text.r_margin.top != newtw->text.r_margin.top
+ || oldtw->text.sink != newtw->text.sink
+ || newtw->text.redisplay_needed) {
+ if (oldtw->text.wrap != newtw->text.wrap) {
+ newtw->text.left_margin = newtw->text.margin.left =
+ newtw->text.r_margin.left;
+ if (oldtw->text.lt.top == newtw->text.lt.top)
+ newtw->text.lt.top = SrcScan(newtw->text.source, 0, XawstEOL,
+ XawsdLeft, 1, False);
+ }
+ newtw->text.showposition = True;
+#ifndef OLDXAW
+ show_lc = True;
+ newtw->text.source_changed = SRC_CHANGE_OVERLAP;
+#endif
+ _XawTextBuildLineTable(newtw, newtw->text.lt.top, True);
+ redisplay = True;
+ }
+
+#ifndef OLDXAW
+ if (newtw->text.left_column < 0)
+ newtw->text.left_column = 0;
+ if (newtw->text.right_column < 0)
+ newtw->text.right_column = 0;
+#endif
+
+ _XawTextExecuteUpdate(newtw);
+
+#ifndef OLDXAW
+ if (show_lc)
+ _XawTextSetLineAndColumnNumber(newtw, True);
+#endif
+
+ if (redisplay)
+ _XawTextSetScrollBars(newtw);
+
+ return (redisplay);
+}
+
+/* invoked by the Simple widget's SetValues */
+static Bool
+XawTextChangeSensitive(Widget w)
+{
+ Arg args[1];
+ TextWidget tw = (TextWidget)w;
+
+ (*(&simpleClassRec)->simple_class.change_sensitive)(w);
+
+ XtSetArg(args[0], XtNancestorSensitive,
+ (tw->core.ancestor_sensitive && tw->core.sensitive));
+ if (tw->text.vbar)
+ XtSetValues(tw->text.vbar, args, ONE);
+ if (tw->text.hbar)
+ XtSetValues(tw->text.hbar, args, ONE);
+ return (False);
+}
+
+/*
+ * Function:
+ * XawTextGetValuesHook
+ *
+ * Parameters:
+ * w - Text Widget
+ * args - argument list
+ * num_args - number of args
+ *
+ * Description:
+ * This is a get values hook routine that gets the
+ * values in the text source and sink.
+ */
+static void
+XawTextGetValuesHook(Widget w, ArgList args, Cardinal *num_args)
+{
+ XtGetValues(((TextWidget)w)->text.source, args, *num_args);
+ XtGetValues(((TextWidget)w)->text.sink, args, *num_args);
+}
+
+/*
+ * Function:
+ * FindGoodPosition
+ *
+ * Parameters:
+ * pos - any position
+ *
+ * Description:
+ * Returns a valid position given any postition.
+ *
+ * Returns:
+ * A position between (0 and lastPos)
+ */
+static XawTextPosition
+FindGoodPosition(TextWidget ctx, XawTextPosition pos)
+{
+ if (pos < 0)
+ return (0);
+ return (((pos > ctx->text.lastPos) ? ctx->text.lastPos : pos));
+}
+
+/* Li wrote this so the IM can find a given text position's screen position */
+void
+_XawTextPosToXY(Widget w, XawTextPosition pos, Position *x, Position *y)
+{
+ int line, ix, iy;
+
+ LineAndXYForPosition((TextWidget)w, pos, &line, &ix, &iy);
+ *x = ix;
+ *y = iy;
+}
+
+/*******************************************************************
+The following routines provide procedural interfaces to Text window state
+setting and getting. They need to be redone so than the args code can use
+them. I suggest we create a complete set that takes the context as an
+argument and then have the public version lookup the context and call the
+internal one. The major value of this set is that they have actual application
+clients and therefore the functionality provided is required for any future
+version of Text.
+********************************************************************/
+void
+XawTextDisplay(Widget w)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ if (!XtIsRealized(w))
+ return;
+
+ _XawTextPrepareToUpdate(ctx);
+ ctx->text.clear_to_eol = True;
+ DisplayTextWindow(w);
+ _XawTextExecuteUpdate(ctx);
+}
+
+void
+XawTextSetSelectionArray(Widget w, XawTextSelectType *sarray)
+{
+ ((TextWidget)w)->text.sarray = sarray;
+}
+
+void
+XawTextGetSelectionPos(Widget w, XawTextPosition *left, XawTextPosition *right)
+{
+ *left = ((TextWidget)w)->text.s.left;
+ *right = ((TextWidget)w)->text.s.right;
+}
+
+void
+_XawTextSetSource(Widget w, Widget source,
+ XawTextPosition top, XawTextPosition startPos)
+{
+ TextWidget ctx = (TextWidget)w;
+#ifndef OLDXAW
+ Bool resolve = False;
+#endif
+
+#ifndef OLDXAW
+ if (source != ctx->text.source)
+ _XawSourceRemoveText(ctx->text.source, w, ctx->text.source &&
+ XtParent(ctx->text.source) == w);
+ _XawSourceAddText(source, w);
+
+ if (source != ctx->text.source || ctx->text.insertPos != startPos)
+ resolve = True;
+
+ ctx->text.source_changed = SRC_CHANGE_OVERLAP;
+#endif
+ ctx->text.source = source;
+ ctx->text.s.left = ctx->text.s.right = 0;
+ ctx->text.lastPos = GETLASTPOS;
+ top = FindGoodPosition(ctx, top);
+ startPos = FindGoodPosition(ctx, startPos);
+ ctx->text.insertPos = ctx->text.old_insert = startPos;
+ _XawTextPrepareToUpdate(ctx);
+
+ _XawTextBuildLineTable(ctx, top, True);
+
+ _XawTextExecuteUpdate(ctx);
+#ifndef OLDXAW
+ if (resolve)
+ _XawTextSetLineAndColumnNumber(ctx, True);
+#endif
+}
+
+void
+XawTextSetSource(Widget w, Widget source, XawTextPosition top)
+{
+ _XawTextSetSource(w, source, top, top);
+}
+
+/*
+ * This public routine deletes the text from startPos to endPos in a source and
+ * then inserts, at startPos, the text that was passed. As a side effect it
+ * "invalidates" that portion of the displayed text (if any), so that things
+ * will be repainted properly.
+ */
+int
+XawTextReplace(Widget w, XawTextPosition startPos, XawTextPosition endPos,
+ XawTextBlock *text)
+{
+ TextWidget ctx = (TextWidget)w;
+ int result;
+#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]);
+#else
+ _XawTextPrepareToUpdate(ctx);
+#endif
+
+ endPos = FindGoodPosition(ctx, endPos);
+ startPos = FindGoodPosition(ctx, startPos);
+ result = _XawTextReplace(ctx, startPos, endPos, text);
+
+#ifndef OLDXAW
+ for (i = 0; i < src->textSrc.num_text; i++)
+ _XawTextExecuteUpdate((TextWidget)src->textSrc.text[i]);
+#else
+ _XawTextExecuteUpdate(ctx);
+#endif
+
+ return (result);
+}
+
+XawTextPosition
+XawTextTopPosition(Widget w)
+{
+ return (((TextWidget)w)->text.lt.top);
+}
+
+XawTextPosition
+XawTextLastPosition(Widget w)
+{
+ return (((TextWidget)w)->text.lastPos);
+}
+
+void
+XawTextSetInsertionPoint(Widget w, XawTextPosition position)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ _XawTextPrepareToUpdate(ctx);
+ ctx->text.insertPos = FindGoodPosition(ctx, position);
+ ctx->text.showposition = True;
+ ctx->text.from_left = -1;
+
+ _XawTextExecuteUpdate(ctx);
+#ifndef OLDXAW
+ _XawTextSetLineAndColumnNumber(ctx, False);
+#endif
+}
+
+XawTextPosition
+XawTextGetInsertionPoint(Widget w)
+{
+ return (((TextWidget)w)->text.insertPos);
+}
+
+/*
+ * Note: Must walk the selection list in opposite order from TextLoseSelection
+ */
+void
+XawTextUnsetSelection(Widget w)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ while (ctx->text.s.atom_count != 0) {
+ Atom sel = ctx->text.s.selections[ctx->text.s.atom_count - 1];
+
+ if (sel != (Atom) 0) {
+ /*
+ * As selections are lost the atom_count will decrement
+ */
+ if (GetCutBufferNumber(sel) == NOT_A_CUT_BUFFER)
+ XtDisownSelection(w, sel, ctx->text.time);
+ TextLoseSelection(w, &sel); /* In case this is a cut buffer, or
+ XtDisownSelection failed to call us */
+ }
+ }
+}
+
+void
+XawTextSetSelection(Widget w, XawTextPosition left, XawTextPosition right)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ _XawTextPrepareToUpdate(ctx);
+ _XawTextSetSelection(ctx, FindGoodPosition(ctx, left),
+ FindGoodPosition(ctx, right), NULL, 0);
+ _XawTextExecuteUpdate(ctx);
+}
+
+void
+XawTextInvalidate(Widget w, XawTextPosition from, XawTextPosition to)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ from = FindGoodPosition(ctx, from);
+ to = FindGoodPosition(ctx, to);
+ ctx->text.lastPos = GETLASTPOS;
+ _XawTextPrepareToUpdate(ctx);
+ _XawTextNeedsUpdating(ctx, from, to);
+ _XawTextExecuteUpdate(ctx);
+}
+
+/*ARGSUSED*/
+void
+XawTextDisableRedisplay(Widget w)
+{
+ ((TextWidget)w)->text.update_disabled = True;
+ _XawTextPrepareToUpdate((TextWidget)w);
+}
+
+void
+XawTextEnableRedisplay(Widget w)
+{
+ TextWidget ctx = (TextWidget)w;
+ XawTextPosition lastPos;
+
+ if (!ctx->text.update_disabled)
+ return;
+
+ ctx->text.update_disabled = False;
+ lastPos = ctx->text.lastPos = GETLASTPOS;
+ ctx->text.lt.top = FindGoodPosition(ctx, ctx->text.lt.top);
+ ctx->text.insertPos = FindGoodPosition(ctx, ctx->text.insertPos);
+
+ if (ctx->text.s.left > lastPos || ctx->text.s.right > lastPos)
+ ctx->text.s.left = ctx->text.s.right = 0;
+
+ _XawTextExecuteUpdate(ctx);
+}
+
+Widget
+XawTextGetSource(Widget w)
+{
+ return (((TextWidget)w)->text.source);
+}
+
+Widget
+XawTextGetSink(Widget w)
+{
+ return (((TextWidget)w)->text.sink);
+}
+
+void
+XawTextDisplayCaret(Widget w,
+#if NeedWidePrototypes
+ int display_caret
+#else
+ Boolean display_caret
+#endif
+)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ if (XtIsRealized(w)) {
+ _XawTextPrepareToUpdate(ctx);
+ ctx->text.display_caret = display_caret;
+ _XawTextExecuteUpdate(ctx);
+ }
+ else
+ ctx->text.display_caret = display_caret;
+}
+
+/*
+ * Function:
+ * XawTextSearch
+ *
+ * Parameters:
+ * w - text widget
+ * dir - direction to search
+ * text - text block containing info about the string to search for
+ *
+ * Description:
+ * Searches for the given text block.
+ *
+ * Returns:
+ * The position of the text found, or XawTextSearchError on an error
+ */
+XawTextPosition
+XawTextSearch(Widget w,
+#if NeedWidePrototypes
+ int dir,
+#else
+ XawTextScanDirection dir,
+#endif
+ XawTextBlock *text)
+{
+ TextWidget ctx = (TextWidget)w;
+
+ return (SrcSearch(ctx->text.source, ctx->text.insertPos, dir, text));
+}
+
+TextClassRec textClassRec = {
+ /* core */
+ {
+ (WidgetClass)&simpleClassRec, /* superclass */
+ "Text", /* class_name */
+ sizeof(TextRec), /* widget_size */
+ XawTextClassInitialize, /* class_initialize */
+ NULL, /* class_part_init */
+ False, /* class_inited */
+ XawTextInitialize, /* initialize */
+ NULL, /* initialize_hook */
+ XawTextRealize, /* realize */
+ _XawTextActionsTable, /* actions */
+ 0, /* num_actions */
+ resources, /* resources */
+ XtNumber(resources), /* num_resource */
+ NULLQUARK, /* xrm_class */
+ True, /* compress_motion */
+ XtExposeGraphicsExpose | /* compress_exposure */
+ XtExposeNoExpose,
+ True, /* compress_enterleave */
+ False, /* visible_interest */
+ XawTextDestroy, /* destroy */
+ XawTextResize, /* resize */
+ XawTextExpose, /* expose */
+ XawTextSetValues, /* set_values */
+ NULL, /* set_values_hook */
+ XtInheritSetValuesAlmost, /* set_values_almost */
+ XawTextGetValuesHook, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* version */
+ NULL, /* callback_private */
+ _XawDefaultTextTranslations, /* tm_table */
+ XtInheritQueryGeometry, /* query_geometry */
+ XtInheritDisplayAccelerator, /* display_accelerator */
+ NULL, /* extension */
+ },
+ /* simple */
+ {
+ XawTextChangeSensitive, /* change_sensitive */
+ },
+ /* text */
+ {
+ NULL, /* extension */
+ }
+};
+
+WidgetClass textWidgetClass = (WidgetClass)&textClassRec;
|