17a84e134Smrg/*
27a84e134Smrg
37a84e134SmrgCopyright 1989, 1994, 1998  The Open Group
47a84e134Smrg
57a84e134SmrgPermission to use, copy, modify, distribute, and sell this software and its
67a84e134Smrgdocumentation for any purpose is hereby granted without fee, provided that
77a84e134Smrgthe above copyright notice appear in all copies and that both that
87a84e134Smrgcopyright notice and this permission notice appear in supporting
97a84e134Smrgdocumentation.
107a84e134Smrg
117a84e134SmrgThe above copyright notice and this permission notice shall be included in
127a84e134Smrgall copies or substantial portions of the Software.
137a84e134Smrg
147a84e134SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
157a84e134SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
167a84e134SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
177a84e134SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
187a84e134SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
197a84e134SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
207a84e134Smrg
217a84e134SmrgExcept as contained in this notice, the name of The Open Group shall not be
227a84e134Smrgused in advertising or otherwise to promote the sale, use or other dealings
237a84e134Smrgin this Software without prior written authorization from The Open Group.
247a84e134Smrg
257a84e134Smrg*/
267a84e134Smrg
277a84e134Smrg/*
287a84e134Smrg * Author:  Chris Peterson, MIT X Consortium.
297a84e134Smrg * Much code taken from X11R3 String and Disk Sources.
307a84e134Smrg */
317a84e134Smrg
327a84e134Smrg#ifdef HAVE_CONFIG_H
337a84e134Smrg#include <config.h>
347a84e134Smrg#endif
357a84e134Smrg#include <stdio.h>
367a84e134Smrg#include <ctype.h>
377a84e134Smrg#include <X11/IntrinsicP.h>
387a84e134Smrg#include <X11/StringDefs.h>
397a84e134Smrg#include <X11/Xfuncs.h>
407a84e134Smrg#include <X11/Xutil.h>
417a84e134Smrg#include <X11/Xmu/Atoms.h>
427a84e134Smrg#include <X11/Xmu/CharSet.h>
437a84e134Smrg#include <X11/Xaw/TextSrcP.h>
447a84e134Smrg#include <X11/Xaw/XawInit.h>
457a84e134Smrg#include "XawI18n.h"
467a84e134Smrg#include "Private.h"
477a84e134Smrg
487a84e134Smrg#ifndef OLDXAW
497a84e134Smrg#define UNDO_DEPTH	16384
507a84e134Smrg
517a84e134Smrg#define ANCHORS_DIST	4096	/* default distance between anchors */
527a84e134Smrg
537a84e134Smrg/*
547a84e134Smrg * Types
557a84e134Smrg */
567a84e134Smrgtypedef struct {
577a84e134Smrg    XawTextPosition position;
587a84e134Smrg    char *buffer;
597a84e134Smrg    unsigned length;
607a84e134Smrg    unsigned refcount;
617a84e134Smrg    unsigned long format;
627a84e134Smrg} XawTextUndoBuffer;
637a84e134Smrg
647a84e134Smrgtypedef struct _XawTextUndoList XawTextUndoList;
657a84e134Smrgstruct _XawTextUndoList {
667a84e134Smrg    XawTextUndoBuffer *left, *right;
677a84e134Smrg    XawTextUndoList *undo, *redo;
687a84e134Smrg};
697a84e134Smrg
707a84e134Smrgstruct _XawTextUndo {
717a84e134Smrg    XawTextUndoBuffer **undo;
727a84e134Smrg    unsigned num_undo;
737a84e134Smrg    XawTextUndoList *list, *pointer, *end_mark, *head;
747a84e134Smrg    unsigned num_list;
757a84e134Smrg    XawTextScanDirection dir;
767a84e134Smrg    XawTextUndoBuffer *l_save, *r_save;
777a84e134Smrg    XawTextUndoList *u_save;
787a84e134Smrg    XawTextUndoBuffer *l_no_change, *r_no_change;
797a84e134Smrg    int merge;
807a84e134Smrg    int erase;		/* there are two types of erases */
817a84e134Smrg};
827a84e134Smrg#endif	/* OLDXAW */
837a84e134Smrg
847a84e134Smrg/*
857a84e134Smrg * Class Methods
867a84e134Smrg */
877a84e134Smrgstatic Boolean ConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*,
887a84e134Smrg				unsigned long*, int*);
897a84e134Smrgstatic XawTextPosition Read(Widget, XawTextPosition, XawTextBlock*, int);
907a84e134Smrgstatic int  Replace(Widget, XawTextPosition, XawTextPosition, XawTextBlock*);
917a84e134Smrgstatic  XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType,
927a84e134Smrg			      XawTextScanDirection, int, Bool);
937a84e134Smrgstatic XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection,
947a84e134Smrg			      XawTextBlock*);
957a84e134Smrgstatic void SetSelection(Widget, XawTextPosition, XawTextPosition, Atom);
967a84e134Smrgstatic void XawTextSrcClassInitialize(void);
977a84e134Smrgstatic void XawTextSrcClassPartInitialize(WidgetClass);
987a84e134Smrgstatic void XawTextSrcInitialize(Widget, Widget, ArgList, Cardinal*);
997a84e134Smrgstatic void XawTextSrcDestroy(Widget);
1007a84e134Smrgstatic Boolean XawTextSrcSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
1017a84e134Smrg/*
1027a84e134Smrg * Prototypes
1037a84e134Smrg */
1047a84e134Smrgstatic void CvtStringToEditMode(XrmValuePtr, Cardinal*,
1057a84e134Smrg				 XrmValuePtr, XrmValuePtr);
1067a84e134Smrgstatic Boolean CvtEditModeToString(Display*, XrmValuePtr, Cardinal*,
1077a84e134Smrg				   XrmValuePtr, XrmValuePtr, XtPointer*);
1087a84e134Smrg#ifndef OLDXAW
1097a84e134Smrgstatic void FreeUndoBuffer(XawTextUndo*);
1107a84e134Smrgstatic void UndoGC(XawTextUndo*);
1117a84e134Smrgstatic void TellSourceChanged(TextSrcObject, XawTextPosition, XawTextPosition,
1127a84e134Smrg			      XawTextBlock*, int);
1137a84e134SmrgBool _XawTextSrcUndo(TextSrcObject, XawTextPosition*);
1147a84e134SmrgBool _XawTextSrcToggleUndo(TextSrcObject);
1157a84e134SmrgXawTextAnchor *_XawTextSourceFindAnchor(Widget, XawTextPosition);
1167a84e134Smrg
1177a84e134Smrg/*
1187a84e134Smrg * External
1197a84e134Smrg */
1207a84e134Smrgvoid _XawSourceAddText(Widget, Widget);
1217a84e134Smrgvoid _XawSourceRemoveText(Widget, Widget, Bool);
1227a84e134SmrgBool _XawTextSourceNewLineAtEOF(Widget);
1237a84e134Smrgvoid _XawSourceSetUndoErase(TextSrcObject, int);
1247a84e134Smrgvoid _XawSourceSetUndoMerge(TextSrcObject, Bool);
1257a84e134Smrg#endif /* OLDXAW */
1267a84e134Smrg
1277a84e134Smrg/*
1287a84e134Smrg * Defined in Text.c
1297a84e134Smrg */
1307a84e134Smrgchar *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition);
1317a84e134Smrgvoid _XawTextSourceChanged(Widget, XawTextPosition, XawTextPosition,
1327a84e134Smrg			   XawTextBlock*, int);
1337a84e134Smrg
1347a84e134Smrg/*
1357a84e134Smrg * Initialization
1367a84e134Smrg */
1377a84e134Smrg#define offset(field) XtOffsetOf(TextSrcRec, textSrc.field)
1387a84e134Smrgstatic XtResource resources[] = {
1397a84e134Smrg  {
1407a84e134Smrg    XtNeditType,
1417a84e134Smrg    XtCEditType,
1427a84e134Smrg    XtREditMode,
1437a84e134Smrg    sizeof(XawTextEditType),
1447a84e134Smrg    offset(edit_mode),
1457a84e134Smrg    XtRString,
1465ec34c4cSmrg    (XtPointer)"read"
1477a84e134Smrg  },
1487a84e134Smrg#ifndef OLDXAW
1497a84e134Smrg  {
1507a84e134Smrg    XtNcallback,
1517a84e134Smrg    XtCCallback,
1527a84e134Smrg    XtRCallback,
1537a84e134Smrg    sizeof(XtPointer),
1547a84e134Smrg    offset(callback),
1557a84e134Smrg    XtRCallback,
1567a84e134Smrg    NULL
1577a84e134Smrg  },
1587a84e134Smrg  {
1597a84e134Smrg    XtNsourceChanged,
1607a84e134Smrg    XtCChanged,
1617a84e134Smrg    XtRBoolean,
1627a84e134Smrg    sizeof(Boolean),
1637a84e134Smrg    offset(changed),
1647a84e134Smrg    XtRImmediate,
1657a84e134Smrg    (XtPointer)False
1667a84e134Smrg  },
1677a84e134Smrg  {
1687a84e134Smrg    XtNenableUndo,
1697a84e134Smrg    XtCUndo,
1707a84e134Smrg    XtRBoolean,
1717a84e134Smrg    sizeof(Boolean),
1727a84e134Smrg    offset(enable_undo),
1737a84e134Smrg    XtRImmediate,
1747a84e134Smrg    (XtPointer)False
1757a84e134Smrg  },
1767a84e134Smrg  {
1777a84e134Smrg    XtNpropertyCallback,
1787a84e134Smrg    XtCCallback,
1797a84e134Smrg    XtRCallback,
1807a84e134Smrg    sizeof(XtPointer),
1817a84e134Smrg    offset(property_callback),
1827a84e134Smrg    XtRCallback,
1837a84e134Smrg    NULL
1847a84e134Smrg  },
1857a84e134Smrg#endif /* OLDXAW */
1867a84e134Smrg};
1877a84e134Smrg#undef offset
1887a84e134Smrg
1897a84e134Smrg#define Superclass	(&objectClassRec)
1907a84e134SmrgTextSrcClassRec textSrcClassRec = {
1917a84e134Smrg  /* object */
1927a84e134Smrg  {
1937a84e134Smrg    (WidgetClass)Superclass,		/* superclass */
1947a84e134Smrg    "TextSrc",				/* class_name */
1957a84e134Smrg    sizeof(TextSrcRec),			/* widget_size */
1967a84e134Smrg    XawTextSrcClassInitialize,		/* class_initialize */
1977a84e134Smrg    XawTextSrcClassPartInitialize,	/* class_part_initialize */
1987a84e134Smrg    False,				/* class_inited */
1997a84e134Smrg    XawTextSrcInitialize,		/* initialize */
2007a84e134Smrg    NULL,				/* initialize_hook */
2017a84e134Smrg    NULL,				/* realize */
2027a84e134Smrg    NULL,				/* actions */
2037a84e134Smrg    0,					/* num_actions */
2047a84e134Smrg    resources,				/* resources */
2057a84e134Smrg    XtNumber(resources),		/* num_resources */
2067a84e134Smrg    NULLQUARK,				/* xrm_class */
2077a84e134Smrg    False,				/* compress_motion */
2087a84e134Smrg    False,				/* compress_exposure */
2097a84e134Smrg    False,				/* compress_enterleave */
2107a84e134Smrg    False,				/* visible_interest */
2117a84e134Smrg    XawTextSrcDestroy,			/* destroy */
2127a84e134Smrg    NULL,				/* resize */
2137a84e134Smrg    NULL,				/* expose */
2147a84e134Smrg    XawTextSrcSetValues,		/* set_values */
2157a84e134Smrg    NULL,				/* set_values_hook */
2167a84e134Smrg    NULL,				/* set_values_almost */
2177a84e134Smrg    NULL,				/* get_values_hook */
2187a84e134Smrg    NULL,				/* accept_focus */
2197a84e134Smrg    XtVersion,				/* version */
2207a84e134Smrg    NULL,				/* callback_private */
2217a84e134Smrg    NULL,				/* tm_table */
2227a84e134Smrg    NULL,				/* query_geometry */
2237a84e134Smrg    NULL,				/* display_accelerator */
2247a84e134Smrg    NULL,				/* extension */
2257a84e134Smrg  },
2267a84e134Smrg  /* text_src */
2277a84e134Smrg  {
2287a84e134Smrg    Read,				/* Read */
2297a84e134Smrg    Replace,				/* Replace */
2307a84e134Smrg    Scan,				/* Scan */
2317a84e134Smrg    Search,				/* Search */
2327a84e134Smrg    SetSelection,			/* SetSelection */
2337a84e134Smrg    ConvertSelection,			/* ConvertSelection */
234efbcb2bfSmrg#ifndef OLDXAW
235efbcb2bfSmrg    NULL,				/* extension */
236efbcb2bfSmrg#endif
2377a84e134Smrg  },
2387a84e134Smrg};
2397a84e134Smrg
2407a84e134SmrgWidgetClass textSrcObjectClass = (WidgetClass)&textSrcClassRec;
2417a84e134Smrg
2427a84e134Smrgstatic XrmQuark QRead, QAppend, QEdit;
2437a84e134Smrg#ifndef OLDXAW
244efbcb2bfSmrgstatic char *SrcNL = (char*)"\n";
2457a84e134Smrgstatic wchar_t SrcWNL[2];
2467a84e134Smrg#endif
2477a84e134Smrg
2487a84e134Smrg/*
2497a84e134Smrg * Implementation
2507a84e134Smrg */
251421c997bSmrgstatic void
2527a84e134SmrgXawTextSrcClassInitialize(void)
2537a84e134Smrg{
2547a84e134Smrg    XawInitializeWidgetSet();
2557a84e134Smrg
2567a84e134Smrg#ifndef OLDXAW
2577a84e134Smrg    SrcWNL[0] = _Xaw_atowc(XawLF);
2587a84e134Smrg    SrcWNL[1] = 0;
2597a84e134Smrg#endif
2607a84e134Smrg    QRead   = XrmPermStringToQuark(XtEtextRead);
2617a84e134Smrg    QAppend = XrmPermStringToQuark(XtEtextAppend);
2627a84e134Smrg    QEdit   = XrmPermStringToQuark(XtEtextEdit);
2637a84e134Smrg    XtAddConverter(XtRString, XtREditMode,   CvtStringToEditMode,   NULL, 0);
2647a84e134Smrg    XtSetTypeConverter(XtREditMode, XtRString, CvtEditModeToString, NULL, 0,
2657a84e134Smrg		       XtCacheNone, NULL);
2667a84e134Smrg}
2677a84e134Smrg
2687a84e134Smrgstatic void
2697a84e134SmrgXawTextSrcClassPartInitialize(WidgetClass wc)
2707a84e134Smrg{
2717a84e134Smrg    TextSrcObjectClass t_src, superC;
2727a84e134Smrg
2737a84e134Smrg    t_src = (TextSrcObjectClass)wc;
2747a84e134Smrg    superC = (TextSrcObjectClass)t_src->object_class.superclass;
2757a84e134Smrg
2767a84e134Smrg    /*
2777a84e134Smrg     * We don't need to check for null super since we'll get to TextSrc
2787a84e134Smrg     * eventually
2797a84e134Smrg     */
280421c997bSmrg    if (t_src->textSrc_class.Read == XtInheritRead)
2817a84e134Smrg	t_src->textSrc_class.Read = superC->textSrc_class.Read;
2827a84e134Smrg
283421c997bSmrg    if (t_src->textSrc_class.Replace == XtInheritReplace)
2847a84e134Smrg	t_src->textSrc_class.Replace = superC->textSrc_class.Replace;
2857a84e134Smrg
286421c997bSmrg    if (t_src->textSrc_class.Scan == XtInheritScan)
2877a84e134Smrg	t_src->textSrc_class.Scan = superC->textSrc_class.Scan;
2887a84e134Smrg
289421c997bSmrg    if (t_src->textSrc_class.Search == XtInheritSearch)
2907a84e134Smrg	t_src->textSrc_class.Search = superC->textSrc_class.Search;
2917a84e134Smrg
292421c997bSmrg    if (t_src->textSrc_class.SetSelection == XtInheritSetSelection)
2937a84e134Smrg	t_src->textSrc_class.SetSelection = superC->textSrc_class.SetSelection;
2947a84e134Smrg
295421c997bSmrg    if (t_src->textSrc_class.ConvertSelection == XtInheritConvertSelection)
2967a84e134Smrg	t_src->textSrc_class.ConvertSelection =
2977a84e134Smrg	    superC->textSrc_class.ConvertSelection;
2987a84e134Smrg}
2997a84e134Smrg
3007a84e134Smrg/*ARGSUSED*/
3017a84e134Smrgstatic void
3025ec34c4cSmrgXawTextSrcInitialize(Widget request _X_UNUSED, Widget cnew _X_UNUSED,
3035ec34c4cSmrg		     ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
3047a84e134Smrg{
3057a84e134Smrg#ifndef OLDXAW
3067a84e134Smrg    TextSrcObject src = (TextSrcObject)cnew;
3077a84e134Smrg
3087a84e134Smrg    if (src->textSrc.enable_undo) {
3097a84e134Smrg	src->textSrc.undo = (XawTextUndo*)XtCalloc(1, sizeof(XawTextUndo));
3107a84e134Smrg	src->textSrc.undo->dir = XawsdLeft;
3117a84e134Smrg    }
3127a84e134Smrg    else
3137a84e134Smrg	src->textSrc.undo = NULL;
3147a84e134Smrg    src->textSrc.undo_state = False;
3157a84e134Smrg    if (XtIsSubclass(XtParent(cnew), textWidgetClass)) {
3167a84e134Smrg	src->textSrc.text = (WidgetList)XtMalloc(sizeof(Widget*));
3177a84e134Smrg	src->textSrc.text[0] = XtParent(cnew);
3187a84e134Smrg	src->textSrc.num_text = 1;
3197a84e134Smrg    }
3207a84e134Smrg    else {
3217a84e134Smrg	src->textSrc.text = NULL;
3227a84e134Smrg	src->textSrc.num_text = 0;
3237a84e134Smrg    }
3247a84e134Smrg
3257a84e134Smrg    src->textSrc.anchors = NULL;
3267a84e134Smrg    src->textSrc.num_anchors = 0;
3277a84e134Smrg    (void)XawTextSourceAddAnchor(cnew, 0);
3287a84e134Smrg#endif /* OLDXAW */
3297a84e134Smrg}
3307a84e134Smrg
3317a84e134Smrgstatic void
3325ec34c4cSmrgXawTextSrcDestroy(Widget w _X_UNUSED)
3337a84e134Smrg{
3347a84e134Smrg#ifndef OLDXAW
3357a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
3367a84e134Smrg
3377a84e134Smrg    if (src->textSrc.enable_undo) {
3387a84e134Smrg	FreeUndoBuffer(src->textSrc.undo);
3397a84e134Smrg	XtFree((char*)src->textSrc.undo);
3407a84e134Smrg    }
3417a84e134Smrg    XtFree((char*)src->textSrc.text);
3427a84e134Smrg
3437a84e134Smrg    if (src->textSrc.num_anchors) {
3447a84e134Smrg	XawTextEntity *entity, *enext;
3457a84e134Smrg	int i;
3467a84e134Smrg
3477a84e134Smrg	for (i = 0; i < src->textSrc.num_anchors; i++) {
3487a84e134Smrg	    entity = src->textSrc.anchors[i]->entities;
3497a84e134Smrg	    while (entity) {
3507a84e134Smrg		enext = entity->next;
3517a84e134Smrg		XtFree((XtPointer)entity);
3527a84e134Smrg		entity = enext;
3537a84e134Smrg	    }
3547a84e134Smrg	    XtFree((XtPointer)src->textSrc.anchors[i]);
3557a84e134Smrg	}
3567a84e134Smrg	XtFree((XtPointer)src->textSrc.anchors);
3577a84e134Smrg    }
3587a84e134Smrg#endif /* OLDXAW */
3597a84e134Smrg}
3607a84e134Smrg
3617a84e134Smrg/*ARGSUSED*/
3627a84e134Smrgstatic Boolean
3635ec34c4cSmrgXawTextSrcSetValues(Widget current _X_UNUSED, Widget request _X_UNUSED, Widget cnew _X_UNUSED,
3645ec34c4cSmrg		    ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
3657a84e134Smrg{
3667a84e134Smrg#ifndef OLDXAW
3677a84e134Smrg    TextSrcObject oldtw = (TextSrcObject)current;
3687a84e134Smrg    TextSrcObject newtw = (TextSrcObject)cnew;
3697a84e134Smrg
3707a84e134Smrg    if (oldtw->textSrc.enable_undo != newtw->textSrc.enable_undo) {
3717a84e134Smrg	if (newtw->textSrc.enable_undo) {
3727a84e134Smrg	    newtw->textSrc.undo = (XawTextUndo*)
3737a84e134Smrg		XtCalloc(1, sizeof(XawTextUndo));
3747a84e134Smrg	    newtw->textSrc.undo->dir = XawsdLeft;
3757a84e134Smrg	}
3767a84e134Smrg	else {
3777a84e134Smrg	    FreeUndoBuffer(newtw->textSrc.undo);
3787a84e134Smrg	    XtFree((char*)newtw->textSrc.undo);
3797a84e134Smrg	    newtw->textSrc.undo = NULL;
3807a84e134Smrg	}
3817a84e134Smrg    }
3827a84e134Smrg    if (oldtw->textSrc.changed != newtw->textSrc.changed) {
3837a84e134Smrg	if (newtw->textSrc.enable_undo) {
3847a84e134Smrg	    if (newtw->textSrc.undo->list) {
3857a84e134Smrg		newtw->textSrc.undo->l_no_change =
3867a84e134Smrg		    newtw->textSrc.undo->list->left;
3877a84e134Smrg		newtw->textSrc.undo->r_no_change =
3887a84e134Smrg		    newtw->textSrc.undo->list->right;
3897a84e134Smrg	    }
3907a84e134Smrg	    else
3917a84e134Smrg		newtw->textSrc.undo->l_no_change =
3927a84e134Smrg		    newtw->textSrc.undo->r_no_change = NULL;
3937a84e134Smrg	}
3947a84e134Smrg    }
3957a84e134Smrg#endif /* OLDXAW */
3967a84e134Smrg    return (False);
3977a84e134Smrg}
3987a84e134Smrg
3997a84e134Smrg/*
4007a84e134Smrg * Function:
4017a84e134Smrg *	Read
4027a84e134Smrg *
4037a84e134Smrg * Parameters:
4047a84e134Smrg *	w      - TextSrc Object
4055b16253fSmrg *	pos    - position of the text to retrieve
4067a84e134Smrg *	text   - text block that will contain returned text
4077a84e134Smrg *	length - maximum number of characters to read
4087a84e134Smrg *
4097a84e134Smrg * Description:
4107a84e134Smrg *	This function reads the source.
4117a84e134Smrg *
4127a84e134Smrg * Returns:
4137a84e134Smrg *	The character position following the retrieved text.
4147a84e134Smrg */
4157a84e134Smrg/*ARGSUSED*/
4167a84e134Smrgstatic XawTextPosition
4175ec34c4cSmrgRead(Widget w _X_UNUSED, XawTextPosition pos _X_UNUSED, XawTextBlock *text _X_UNUSED, int length _X_UNUSED)
4187a84e134Smrg{
4197a84e134Smrg    return ((XawTextPosition)0);
4207a84e134Smrg}
4217a84e134Smrg
4227a84e134Smrg/*
4237a84e134Smrg * Function:
4247a84e134Smrg *	Replace
4257a84e134Smrg *
4267a84e134Smrg * Parameters:
4277a84e134Smrg *	src	 - Text Source Object
4287a84e134Smrg *	startPos - ends of text that will be removed
4297a84e134Smrg *	endPos	 - ""
4307a84e134Smrg *	text	 - new text to be inserted into buffer at startPos
4317a84e134Smrg *
4327a84e134Smrg * Description:
4337a84e134Smrg *	Replaces a block of text with new text.
4347a84e134Smrg */
4357a84e134Smrg/*ARGSUSED*/
436421c997bSmrgstatic int
4375ec34c4cSmrgReplace(Widget w _X_UNUSED, XawTextPosition startPos _X_UNUSED, XawTextPosition endPos _X_UNUSED,
4385ec34c4cSmrg	XawTextBlock *text _X_UNUSED)
4397a84e134Smrg{
4407a84e134Smrg    return (XawEditError);
4417a84e134Smrg}
4427a84e134Smrg
4437a84e134Smrg/*
4447a84e134Smrg * Function:
4457a84e134Smrg *	Scan
4467a84e134Smrg *
4477a84e134Smrg * Parameters:
4487a84e134Smrg *	w	 - TextSrc Object
4497a84e134Smrg *	position - position to start scanning
4507a84e134Smrg *	type	 - type of thing to scan for
4517a84e134Smrg *	dir	 - direction to scan
4525b16253fSmrg *	count	 - which occurrence 0f this thing to search for
4535b16253fSmrg *	include  - whether or not to include the character found in
4547a84e134Smrg *		   the position that is returned
4557a84e134Smrg *
4567a84e134Smrg * Description:
4577a84e134Smrg *	Scans the text source for the number and type of item specified.
4587a84e134Smrg */
4597a84e134Smrg/*ARGSUSED*/
460421c997bSmrgstatic XawTextPosition
4615ec34c4cSmrgScan(Widget w _X_UNUSED, XawTextPosition position _X_UNUSED, XawTextScanType type _X_UNUSED,
4625ec34c4cSmrg     XawTextScanDirection dir _X_UNUSED, int count _X_UNUSED, Bool include _X_UNUSED)
4637a84e134Smrg{
4647a84e134Smrg    return ((XawTextPosition)0);
4657a84e134Smrg}
4667a84e134Smrg
4677a84e134Smrg/*
4687a84e134Smrg * Function:
4697a84e134Smrg *	Search
4707a84e134Smrg *
4717a84e134Smrg * Parameters:
4727a84e134Smrg *	w	 - TextSource Object
4737a84e134Smrg *	position - position to start searching
4747a84e134Smrg *	dir	 - direction to search
4757a84e134Smrg *	text	 - the text block to search for
4767a84e134Smrg *
4777a84e134Smrg * Description:
4785b16253fSmrg *	Searches the text source for the text block passed
4797a84e134Smrg */
4807a84e134Smrg/*ARGSUSED*/
4817a84e134Smrgstatic XawTextPosition
4825ec34c4cSmrgSearch(Widget w _X_UNUSED, XawTextPosition position _X_UNUSED, XawTextScanDirection dir _X_UNUSED,
4835ec34c4cSmrg       XawTextBlock *text _X_UNUSED)
4847a84e134Smrg{
4857a84e134Smrg    return (XawTextSearchError);
4867a84e134Smrg}
4877a84e134Smrg
4887a84e134Smrg/*ARGSUSED*/
4897a84e134Smrgstatic Boolean
4905ec34c4cSmrgConvertSelection(Widget w _X_UNUSED, Atom *selection _X_UNUSED, Atom *target _X_UNUSED, Atom *type _X_UNUSED,
4915ec34c4cSmrg		 XtPointer *value _X_UNUSED, unsigned long *length _X_UNUSED, int *format _X_UNUSED)
4927a84e134Smrg{
4937a84e134Smrg    return (False);
4947a84e134Smrg}
4957a84e134Smrg
4967a84e134Smrg/*ARGSUSED*/
4977a84e134Smrgstatic void
4985ec34c4cSmrgSetSelection(Widget w _X_UNUSED, XawTextPosition left _X_UNUSED, XawTextPosition right _X_UNUSED,
4995ec34c4cSmrg	     Atom selection _X_UNUSED)
5007a84e134Smrg{
5017a84e134Smrg}
5027a84e134Smrg
5037a84e134Smrg/*ARGSUSED*/
504421c997bSmrgstatic void
5055ec34c4cSmrgCvtStringToEditMode(XrmValuePtr args _X_UNUSED, Cardinal *num_args _X_UNUSED,
5067a84e134Smrg		    XrmValuePtr fromVal, XrmValuePtr toVal)
5077a84e134Smrg{
5087a84e134Smrg    static XawTextEditType editType;
5097a84e134Smrg    XrmQuark	q;
5107a84e134Smrg    char name[7];
511421c997bSmrg
5127a84e134Smrg    XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name));
5137a84e134Smrg    q = XrmStringToQuark(name);
5147a84e134Smrg
5157a84e134Smrg    if (q == QRead)
5167a84e134Smrg	editType = XawtextRead;
5177a84e134Smrg    else if (q == QAppend)
5187a84e134Smrg	editType = XawtextAppend;
5197a84e134Smrg    else if (q == QEdit)
5207a84e134Smrg	editType = XawtextEdit;
5217a84e134Smrg    else {
5227a84e134Smrg	toVal->size = 0;
5237a84e134Smrg	toVal->addr = NULL;
5247a84e134Smrg	XtStringConversionWarning((char *)fromVal->addr, XtREditMode);
5257a84e134Smrg    }
5267a84e134Smrg    toVal->size = sizeof(XawTextEditType);
5277a84e134Smrg    toVal->addr = (XPointer)&editType;
5287a84e134Smrg}
5297a84e134Smrg
5307a84e134Smrg/*ARGSUSED*/
5317a84e134Smrgstatic Boolean
5325ec34c4cSmrgCvtEditModeToString(Display *dpy, XrmValuePtr args _X_UNUSED, Cardinal *num_args _X_UNUSED,
5337a84e134Smrg		    XrmValuePtr fromVal, XrmValuePtr toVal,
5345ec34c4cSmrg		    XtPointer *data _X_UNUSED)
5357a84e134Smrg{
5367a84e134Smrg    static String buffer;
5377a84e134Smrg    Cardinal size;
5387a84e134Smrg
5397a84e134Smrg    switch (*(XawTextEditType *)fromVal->addr) {
5407a84e134Smrg	case XawtextRead:
5417a84e134Smrg	    buffer = XtEtextRead;
5427a84e134Smrg	    break;
543994689c1Smrg	case XawtextAppend:
5447a84e134Smrg	    buffer = XtEtextAppend;
5457a84e134Smrg	    break;
5467a84e134Smrg	case XawtextEdit:
5477a84e134Smrg	    buffer = XtEtextEdit;
5487a84e134Smrg	    break;
5497a84e134Smrg	default:
5507a84e134Smrg	    XawTypeToStringWarning(dpy, XtREditMode);
5517a84e134Smrg	    toVal->addr = NULL;
5527a84e134Smrg	    toVal->size = 0;
5537a84e134Smrg	    return (False);
5547a84e134Smrg    }
5557a84e134Smrg
5565ec34c4cSmrg    size = (Cardinal)(strlen(buffer) + 1);
5577a84e134Smrg    if (toVal->addr != NULL) {
5587a84e134Smrg	if (toVal->size < size) {
5597a84e134Smrg	    toVal->size = size;
5607a84e134Smrg	    return (False);
5617a84e134Smrg	}
5627a84e134Smrg	strcpy((char *)toVal->addr, buffer);
5637a84e134Smrg    }
5647a84e134Smrg    else
5657a84e134Smrg	toVal->addr = (XPointer)buffer;
5667a84e134Smrg    toVal->size = sizeof(String);
5677a84e134Smrg
5687a84e134Smrg    return (True);
5697a84e134Smrg}
5707a84e134Smrg
5717a84e134Smrg#ifndef OLDXAW
5727a84e134SmrgBool
5737a84e134Smrg_XawTextSourceNewLineAtEOF(Widget w)
5747a84e134Smrg{
5757a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
5767a84e134Smrg    XawTextBlock text;
5777a84e134Smrg
5787a84e134Smrg    text.firstPos = 0;
5795ec34c4cSmrg    if ((text.format = (unsigned long)src->textSrc.text_format) == XawFmt8Bit)
5807a84e134Smrg	text.ptr = SrcNL;
5817a84e134Smrg    else
5827a84e134Smrg	text.ptr = (char*)SrcWNL;
5837a84e134Smrg    text.length = 1;
5847a84e134Smrg
5857a84e134Smrg    return (XawTextSourceSearch(w, XawTextSourceScan(w, 0, XawstAll,
5867a84e134Smrg						     XawsdRight, 1, True) - 1,
5877a84e134Smrg				XawsdRight, &text) != XawTextSearchError);
5887a84e134Smrg}
5897a84e134Smrg
5907a84e134Smrgvoid
5917a84e134Smrg_XawSourceAddText(Widget source, Widget text)
5927a84e134Smrg{
5937a84e134Smrg    TextSrcObject src = (TextSrcObject)source;
5947a84e134Smrg    Bool found = False;
5957a84e134Smrg    Cardinal i;
5967a84e134Smrg
5977a84e134Smrg    for (i = 0; i < src->textSrc.num_text; i++)
5987a84e134Smrg	if (src->textSrc.text[i] == text) {
5997a84e134Smrg	    found = True;
6007a84e134Smrg	    break;
6017a84e134Smrg	}
6027a84e134Smrg
6037a84e134Smrg    if (!found) {
6047a84e134Smrg	src->textSrc.text = (WidgetList)
6057a84e134Smrg	    XtRealloc((char*)src->textSrc.text,
6065ec34c4cSmrg		      (Cardinal)(sizeof(Widget) * (src->textSrc.num_text + 1)));
6077a84e134Smrg	src->textSrc.text[src->textSrc.num_text++] = text;
6087a84e134Smrg    }
6097a84e134Smrg}
6107a84e134Smrg
6117a84e134Smrgvoid
6127a84e134Smrg_XawSourceRemoveText(Widget source, Widget text, Bool destroy)
6137a84e134Smrg{
6147a84e134Smrg    TextSrcObject src = (TextSrcObject)source;
6157a84e134Smrg    Bool found = False;
6167a84e134Smrg    Cardinal i;
6177a84e134Smrg
6187a84e134Smrg    if (src == NULL)
6197a84e134Smrg	return;
6207a84e134Smrg
6217a84e134Smrg    for (i = 0; i < src->textSrc.num_text; i++)
6227a84e134Smrg	if (src->textSrc.text[i] == text) {
6237a84e134Smrg	    found = True;
6247a84e134Smrg	    break;
6257a84e134Smrg	}
6267a84e134Smrg
6277a84e134Smrg    if (found) {
6287a84e134Smrg	if (--src->textSrc.num_text == 0) {
6297a84e134Smrg	    if (destroy) {
6307a84e134Smrg		XtDestroyWidget(source);
6317a84e134Smrg		return;
6327a84e134Smrg	    }
6337a84e134Smrg	    else {
6347a84e134Smrg		XtFree((char*)src->textSrc.text);
6357a84e134Smrg		src->textSrc.text = NULL;	/* for realloc "magic" */
6367a84e134Smrg	    }
6377a84e134Smrg	}
6387a84e134Smrg	else if (i < src->textSrc.num_text)
6397a84e134Smrg	    memmove(&src->textSrc.text[i], &src->textSrc.text[i + 1],
6407a84e134Smrg		    sizeof(Widget) * (src->textSrc.num_text - i));
6417a84e134Smrg    }
6427a84e134Smrg}
6437a84e134Smrg#endif /* OLDXAW */
6447a84e134Smrg
6457a84e134Smrg/*
6467a84e134Smrg * Function:
6477a84e134Smrg *	XawTextSourceRead
6487a84e134Smrg *
6497a84e134Smrg * Parameters:
6507a84e134Smrg *	w      - TextSrc Object
6517a84e134Smrg *	pos    - position of the text to retrieve
6527a84e134Smrg *	text   - text block that will contain returned text (return)
6537a84e134Smrg *	length - maximum number of characters to read
6547a84e134Smrg *
6557a84e134Smrg * Description:
6567a84e134Smrg *	This function reads the source.
6577a84e134Smrg *
6587a84e134Smrg * Returns:
6597a84e134Smrg *	The number of characters read into the buffer
6607a84e134Smrg */
6617a84e134SmrgXawTextPosition
6627a84e134SmrgXawTextSourceRead(Widget w, XawTextPosition pos, XawTextBlock *text,
6637a84e134Smrg		  int length)
6647a84e134Smrg{
6657a84e134Smrg  TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
6667a84e134Smrg
6677a84e134Smrg  return ((*cclass->textSrc_class.Read)(w, pos, text, length));
6687a84e134Smrg}
6697a84e134Smrg
6707a84e134Smrg#ifndef OLDXAW
6717a84e134Smrgstatic void
6727a84e134SmrgTellSourceChanged(TextSrcObject src, XawTextPosition left,
6737a84e134Smrg		  XawTextPosition right, XawTextBlock *block, int lines)
6747a84e134Smrg{
6757a84e134Smrg    Cardinal i;
6767a84e134Smrg
6777a84e134Smrg    for (i = 0; i < src->textSrc.num_text; i++)
6787a84e134Smrg	_XawTextSourceChanged(src->textSrc.text[i], left, right, block, lines);
6797a84e134Smrg}
6807a84e134Smrg
6817a84e134Smrg/*
6827a84e134Smrg * This function is required because there is no way to diferentiate
6837a84e134Smrg * if the first erase was generated by a backward-kill-char and the
6847a84e134Smrg * second by a forward-kill-char (or vice-versa) from XawTextSourceReplace.
6857a84e134Smrg * It is only possible to diferentiate after the second character is
6867a84e134Smrg * killed, but then, it is too late.
6877a84e134Smrg */
6887a84e134Smrgvoid
6897a84e134Smrg_XawSourceSetUndoErase(TextSrcObject src, int value)
6907a84e134Smrg{
6917a84e134Smrg    if (src && src->textSrc.enable_undo)
6927a84e134Smrg	src->textSrc.undo->erase = value;
6937a84e134Smrg}
6947a84e134Smrg
6957a84e134Smrg/*
6965b16253fSmrg * To differentiate insert-char's separated by cursor movements.
6977a84e134Smrg */
6987a84e134Smrgvoid
6997a84e134Smrg_XawSourceSetUndoMerge(TextSrcObject src, Bool state)
7007a84e134Smrg{
7017a84e134Smrg    if (src && src->textSrc.enable_undo)
7027a84e134Smrg	src->textSrc.undo->merge += state ? 1 : -1;
7037a84e134Smrg}
7047a84e134Smrg#endif /* OLDXAW */
7057a84e134Smrg
7067a84e134Smrg/*
7077a84e134Smrg * Public Functions
7087a84e134Smrg */
7097a84e134Smrg/*
7107a84e134Smrg * Function:
7117a84e134Smrg *	XawTextSourceReplace
7127a84e134Smrg *
7137a84e134Smrg * Parameters:
7147a84e134Smrg *	src	 - Text Source Object
7157a84e134Smrg *	startPos - ends of text that will be removed
7167a84e134Smrg *	endPos	 - ""
7177a84e134Smrg *	text	 - new text to be inserted into buffer at startPos
7187a84e134Smrg *
7197a84e134Smrg * Description:
7207a84e134Smrg *	Replaces a block of text with new text.
7217a84e134Smrg *
7227a84e134Smrg * Returns:
7237a84e134Smrg *	XawEditError or XawEditDone.
7247a84e134Smrg */
7257a84e134Smrg/*ARGSUSED*/
7267a84e134Smrgint
7277a84e134SmrgXawTextSourceReplace(Widget w, XawTextPosition left,
7287a84e134Smrg		      XawTextPosition right, XawTextBlock *block)
7297a84e134Smrg{
7307a84e134Smrg    TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
7317a84e134Smrg#ifndef OLDXAW
7327a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
7337a84e134Smrg    XawTextUndoBuffer *l_state, *r_state;
7347a84e134Smrg    XawTextUndoList *undo;
7357a84e134Smrg    Bool enable_undo;
7367a84e134Smrg    XawTextPosition start, end;
7377a84e134Smrg    int i, error, lines = 0;
738efbcb2bfSmrg    Cardinal j;
7397a84e134Smrg
7407a84e134Smrg    if (src->textSrc.edit_mode == XawtextRead)
7417a84e134Smrg	return (XawEditError);
7427a84e134Smrg
7437a84e134Smrg    enable_undo = src->textSrc.enable_undo && src->textSrc.undo_state == False;
7447a84e134Smrg    if (enable_undo) {
7457a84e134Smrg	unsigned size, total;
7467a84e134Smrg
7477a84e134Smrg	if (src->textSrc.undo->l_save) {
7487a84e134Smrg	    l_state = src->textSrc.undo->l_save;
7497a84e134Smrg	    src->textSrc.undo->l_save = NULL;
7507a84e134Smrg	}
7517a84e134Smrg	else
7527a84e134Smrg	    l_state = XtNew(XawTextUndoBuffer);
7537a84e134Smrg	l_state->refcount = 1;
7547a84e134Smrg	l_state->position = left;
7557a84e134Smrg	if (left < right) {
7567a84e134Smrg	    Widget ctx = NULL;
7577a84e134Smrg
758efbcb2bfSmrg	    for (j = 0; j < src->textSrc.num_text; j++)
759efbcb2bfSmrg		if (XtIsSubclass(src->textSrc.text[j], textWidgetClass)) {
760efbcb2bfSmrg		    ctx = src->textSrc.text[j];
7617a84e134Smrg		    break;
7627a84e134Smrg		}
7637a84e134Smrg	    l_state->buffer = _XawTextGetText((TextWidget)ctx, left, right);
7645ec34c4cSmrg	    l_state->length = (unsigned)(right - left);
7657a84e134Smrg	}
7667a84e134Smrg	else {
7677a84e134Smrg	    l_state->length = 0;
7687a84e134Smrg	    l_state->buffer = NULL;
7697a84e134Smrg	}
7705ec34c4cSmrg	l_state->format = (unsigned long)src->textSrc.text_format;
7717a84e134Smrg	if (l_state->length == 1) {
7727a84e134Smrg	    if (l_state->format == XawFmtWide &&
7737a84e134Smrg		*(wchar_t*)l_state->buffer == *SrcWNL) {
7747a84e134Smrg		XtFree(l_state->buffer);
7757a84e134Smrg		l_state->buffer = (char*)SrcWNL;
7767a84e134Smrg	    }
7777a84e134Smrg	    else if (*l_state->buffer == '\n') {
7787a84e134Smrg		XtFree(l_state->buffer);
7797a84e134Smrg		l_state->buffer = SrcNL;
7807a84e134Smrg	    }
7817a84e134Smrg	}
7827a84e134Smrg
7837a84e134Smrg	if (src->textSrc.undo->r_save) {
7847a84e134Smrg	    r_state = src->textSrc.undo->r_save;
7857a84e134Smrg	    src->textSrc.undo->r_save = NULL;
7867a84e134Smrg	}
7877a84e134Smrg	else
7887a84e134Smrg	    r_state = XtNew(XawTextUndoBuffer);
7897a84e134Smrg	r_state->refcount = 1;
7907a84e134Smrg	r_state->position = left;
7917a84e134Smrg	r_state->format = block->format;
7927a84e134Smrg	size = block->format == XawFmtWide ? sizeof(wchar_t) : sizeof(char);
7935ec34c4cSmrg	total = (size * (unsigned)block->length);
7945ec34c4cSmrg	r_state->length = (unsigned)block->length;
7957a84e134Smrg	r_state->buffer = NULL;
7967a84e134Smrg	if (total == size) {
7977a84e134Smrg	    if (r_state->format == XawFmtWide &&
7987a84e134Smrg		*(wchar_t*)block->ptr == *SrcWNL)
7997a84e134Smrg		r_state->buffer = (char*)SrcWNL;
8007a84e134Smrg	    else if (*block->ptr == '\n')
8017a84e134Smrg		r_state->buffer = SrcNL;
8027a84e134Smrg	}
8037a84e134Smrg	if (total && !r_state->buffer) {
8047a84e134Smrg	    r_state->buffer = XtMalloc(total);
8057a84e134Smrg	    memcpy(r_state->buffer, block->ptr, total);
8067a84e134Smrg	}
8077a84e134Smrg
8087a84e134Smrg	if (src->textSrc.undo->u_save) {
8097a84e134Smrg	    undo = src->textSrc.undo->u_save;
8107a84e134Smrg	    src->textSrc.undo->u_save = NULL;
8117a84e134Smrg	}
8127a84e134Smrg	else
8137a84e134Smrg	    undo = XtNew(XawTextUndoList);
8147a84e134Smrg	undo->left = l_state;
8157a84e134Smrg	undo->right = r_state;
8167a84e134Smrg	undo->undo = src->textSrc.undo->list;
8177a84e134Smrg	undo->redo = NULL;
8187a84e134Smrg    }
8197a84e134Smrg    else {
8207a84e134Smrg	undo = NULL;
8217a84e134Smrg	l_state = r_state = NULL;
8227a84e134Smrg    }
8237a84e134Smrg
8247a84e134Smrg#define	LARGE_VALUE	262144	/* 256 K */
8257a84e134Smrg    /* optimization, to avoid long delays recalculating the line number
8267a84e134Smrg     * when editing huge files
8277a84e134Smrg     */
8287a84e134Smrg    if (left > LARGE_VALUE) {
8297a84e134Smrg	start = XawTextSourceScan(w, left, XawstEOL, XawsdLeft, 2, False);
830efbcb2bfSmrg	for (j = 0; j < src->textSrc.num_text; j++) {
831efbcb2bfSmrg	    TextWidget tw = (TextWidget)src->textSrc.text[j];
8327a84e134Smrg
8337a84e134Smrg	    if (left <= tw->text.lt.top &&
8347a84e134Smrg		left + block->length - (right - left) > tw->text.lt.top)
8357a84e134Smrg		_XawTextBuildLineTable(tw, start, False);
8367a84e134Smrg	}
8377a84e134Smrg    }
8387a84e134Smrg#undef LARGE_VALUE
8397a84e134Smrg
8407a84e134Smrg    start = left;
8417a84e134Smrg    end = right;
8427a84e134Smrg    while (start < end) {
8437a84e134Smrg	start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True);
8447a84e134Smrg	if (start <= end) {
8457a84e134Smrg	    --lines;
8467a84e134Smrg	    if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) {
8477a84e134Smrg		lines += !_XawTextSourceNewLineAtEOF(w);
8487a84e134Smrg		break;
8497a84e134Smrg	    }
8507a84e134Smrg	}
8517a84e134Smrg    }
8527a84e134Smrg#else
8537a84e134Smrg    int error;
8547a84e134Smrg#endif /* OLDXAW */
8557a84e134Smrg
8567a84e134Smrg    error = (*cclass->textSrc_class.Replace)(w, left, right, block);
8577a84e134Smrg
8587a84e134Smrg#ifndef OLDXAW
8597a84e134Smrg    if (error != XawEditDone) {
8607a84e134Smrg	if (enable_undo) {
8617a84e134Smrg	    if (l_state->buffer) {
8627a84e134Smrg		if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL)
8637a84e134Smrg		    XtFree(l_state->buffer);
8647a84e134Smrg		l_state->buffer = NULL;
8657a84e134Smrg	    }
8667a84e134Smrg	     src->textSrc.undo->l_save = l_state;
8677a84e134Smrg	     if (r_state->buffer) {
8687a84e134Smrg		if (r_state->buffer != SrcNL && r_state->buffer != (char*)SrcWNL)
8697a84e134Smrg		    XtFree(r_state->buffer);
8707a84e134Smrg		r_state->buffer = NULL;
8717a84e134Smrg	    }
8727a84e134Smrg	    src->textSrc.undo->r_save = r_state;
8737a84e134Smrg
8747a84e134Smrg	    src->textSrc.undo->u_save = undo;
8757a84e134Smrg	}
8767a84e134Smrg    }
8777a84e134Smrg    else if (enable_undo) {
8787a84e134Smrg	XawTextUndoList *list = src->textSrc.undo->list;
8797a84e134Smrg	XawTextUndoBuffer *unl, *lnl;
8807a84e134Smrg	int erase = undo->right->length == 0 && undo->left->length == 1 && list
8817a84e134Smrg		    && list->right->length == 0;
8827a84e134Smrg
8837a84e134Smrg	if (erase) {
8847a84e134Smrg	    erase = list->left->position - 1 == undo->left->position ? -1 :
8857a84e134Smrg		    list->left->position == undo->left->position ? 1 : 0;
8867a84e134Smrg	    if (src->textSrc.undo->erase && erase != src->textSrc.undo->erase)
8877a84e134Smrg		erase = 0;
8887a84e134Smrg	    else
8897a84e134Smrg		src->textSrc.undo->erase = erase;
8907a84e134Smrg	}
8917a84e134Smrg
8927a84e134Smrg	if (erase) {
8937a84e134Smrg	    unl = l_state;
8947a84e134Smrg	    lnl = list->left;
8957a84e134Smrg	}
8967a84e134Smrg	else {
8977a84e134Smrg	    unl = r_state;
8987a84e134Smrg	    lnl = list ? list->right : NULL;
8997a84e134Smrg	}
9007a84e134Smrg
9017a84e134Smrg	/* Try to merge the undo buffers */
9027a84e134Smrg	if (src->textSrc.undo->merge > 0 && ((erase ||
9037a84e134Smrg	     (list && ((list->left->length == 0 && undo->left->length == 0) ||
9047a84e134Smrg		       (list->left->length == list->right->length &&
9057a84e134Smrg			undo->left->length == 1)) &&
9067a84e134Smrg	      undo->right->length == 1 &&
9077a84e134Smrg	      list->right->position + list->right->length
9087a84e134Smrg	      == undo->right->position))
9097a84e134Smrg	    && src->textSrc.undo->pointer == list
9107a84e134Smrg	    && unl->format == list->right->format
9117a84e134Smrg	    && ((unl->format == XawFmt8Bit && unl->buffer[0] != XawLF) ||
9127a84e134Smrg		(unl->format == XawFmtWide &&
9137a84e134Smrg		 *(wchar_t*)(unl->buffer) != _Xaw_atowc(XawLF)))
9147a84e134Smrg	    && ((lnl->format == XawFmt8Bit && lnl->buffer[0] != XawLF) ||
9157a84e134Smrg		(lnl->format == XawFmtWide &&
9167a84e134Smrg		 *(wchar_t*)(lnl->buffer) != _Xaw_atowc(XawLF))))) {
9177a84e134Smrg	    unsigned size = lnl->format == XawFmtWide ?
9187a84e134Smrg		sizeof(wchar_t) : sizeof(char);
9197a84e134Smrg
9207a84e134Smrg	    if (!erase) {
9217a84e134Smrg		list->right->buffer = XtRealloc(list->right->buffer,
9227a84e134Smrg						(list->right->length + 1) * size);
9237a84e134Smrg		memcpy(list->right->buffer + list->right->length * size,
9247a84e134Smrg		       undo->right->buffer, size);
9257a84e134Smrg		++list->right->length;
9267a84e134Smrg		XtFree(r_state->buffer);
9277a84e134Smrg	    }
9287a84e134Smrg	    else if (erase < 0) {
9297a84e134Smrg		--list->left->position;
9307a84e134Smrg		--list->right->position;
9317a84e134Smrg	    }
9327a84e134Smrg
9337a84e134Smrg	    src->textSrc.undo->l_save = l_state;
9347a84e134Smrg	    src->textSrc.undo->r_save = r_state;
9357a84e134Smrg	    src->textSrc.undo->u_save = undo;
9367a84e134Smrg
9377a84e134Smrg	    if (list->left->length) {
9387a84e134Smrg		list->left->buffer = XtRealloc(list->left->buffer,
9397a84e134Smrg					       (list->left->length + 1) * size);
9407a84e134Smrg		if (erase >= 0)
9417a84e134Smrg		    memcpy(list->left->buffer + list->left->length * size,
9427a84e134Smrg			   undo->left->buffer, size);
9437a84e134Smrg		else {
9447a84e134Smrg		    /* use memmove, since strings overlap */
9457a84e134Smrg		    memmove(list->left->buffer + size, list->left->buffer,
9467a84e134Smrg			    list->left->length * size);
9477a84e134Smrg		    memcpy(list->left->buffer, undo->left->buffer, size);
9487a84e134Smrg		}
9497a84e134Smrg		++list->left->length;
9507a84e134Smrg		if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL)
9517a84e134Smrg		    XtFree(l_state->buffer);
9527a84e134Smrg	    }
9537a84e134Smrg
9547a84e134Smrg	    if (src->textSrc.undo->num_list >= UNDO_DEPTH)
9557a84e134Smrg		UndoGC(src->textSrc.undo);
9567a84e134Smrg	}
9577a84e134Smrg	else {
9587a84e134Smrg	    src->textSrc.undo->undo = (XawTextUndoBuffer**)
9597a84e134Smrg		XtRealloc((char*)src->textSrc.undo->undo,
9605ec34c4cSmrg			  (Cardinal)((2 + src->textSrc.undo->num_undo)
9615ec34c4cSmrg				     * sizeof(XawTextUndoBuffer)));
9627a84e134Smrg	    src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = l_state;
9637a84e134Smrg	    src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = r_state;
9647a84e134Smrg
9657a84e134Smrg	    if (src->textSrc.undo->list)
9667a84e134Smrg		src->textSrc.undo->list->redo = undo;
9677a84e134Smrg	    else
9687a84e134Smrg		src->textSrc.undo->head = undo;
9697a84e134Smrg
9707a84e134Smrg	    src->textSrc.undo->merge = l_state->length <= 1 &&
9717a84e134Smrg				       r_state->length <= 1;
9727a84e134Smrg
9737a84e134Smrg	    src->textSrc.undo->list = src->textSrc.undo->pointer =
9747a84e134Smrg		src->textSrc.undo->end_mark = undo;
9757a84e134Smrg
9767a84e134Smrg	    if (++src->textSrc.undo->num_list >= UNDO_DEPTH)
9777a84e134Smrg		UndoGC(src->textSrc.undo);
9787a84e134Smrg	}
9797a84e134Smrg	src->textSrc.undo->dir = XawsdLeft;
9807a84e134Smrg	if (!src->textSrc.changed) {
9817a84e134Smrg	    src->textSrc.undo->l_no_change = src->textSrc.undo->list->right;
9827a84e134Smrg	    src->textSrc.undo->r_no_change = src->textSrc.undo->list->left;
9837a84e134Smrg	    src->textSrc.changed = True;
9847a84e134Smrg	}
9857a84e134Smrg    }
9867a84e134Smrg    else if (!src->textSrc.enable_undo)
9877a84e134Smrg	src->textSrc.changed = True;
9887a84e134Smrg
9897a84e134Smrg    if (error == XawEditDone) {
9907a84e134Smrg	XawTextAnchor *anchor;
9917a84e134Smrg
9927a84e134Smrg	/* find anchor and index */
9937a84e134Smrg	/* XXX index (i) could be returned by XawTextSourceFindAnchor
9947a84e134Smrg	 * or similar function, to speed up */
9957a84e134Smrg	if ((anchor = XawTextSourceFindAnchor(w, left))) {
9967a84e134Smrg	    XawTextEntity *eprev, *entity, *enext;
9977a84e134Smrg	    XawTextPosition offset = 0, diff = block->length - (right - left);
9987a84e134Smrg
9997a84e134Smrg	    for (i = 0; i < src->textSrc.num_anchors; i++)
10007a84e134Smrg		if (src->textSrc.anchors[i] == anchor)
10017a84e134Smrg		    break;
10027a84e134Smrg	    if (anchor->cache && anchor->position + anchor->cache->offset +
10037a84e134Smrg		anchor->cache->length <= left)
10047a84e134Smrg		eprev = entity = anchor->cache;
10057a84e134Smrg	    else
10067a84e134Smrg		eprev = entity = anchor->entities;
10077a84e134Smrg	    while (entity) {
10087a84e134Smrg		offset = anchor->position + entity->offset;
10097a84e134Smrg
10107a84e134Smrg		if (offset > left)
10117a84e134Smrg		    break;
10127a84e134Smrg		if (offset + entity->length > left)
10137a84e134Smrg		    break;
10147a84e134Smrg
10157a84e134Smrg		eprev = entity;
10167a84e134Smrg		entity = entity->next;
10177a84e134Smrg	    }
10187a84e134Smrg
10197a84e134Smrg	    /* try to do the right thing here (and most likely correct), but
10207a84e134Smrg	     * other code needs to check what was done */
10217a84e134Smrg
10227a84e134Smrg	    /* adjust entity length */
10237a84e134Smrg	    if (entity && offset <= left) {
10247a84e134Smrg		if (offset + entity->length < right)
10255ec34c4cSmrg		    entity->length = (Cardinal)(left - offset + block->length);
10267a84e134Smrg		else
10275ec34c4cSmrg		    entity->length = (Cardinal)(entity->length + diff);
10287a84e134Smrg
10297a84e134Smrg		if (entity->length == 0) {
10307a84e134Smrg		    enext = entity->next;
10317a84e134Smrg		    eprev->next = enext;
10327a84e134Smrg		    anchor->cache = NULL;
10337a84e134Smrg		    XtFree((XtPointer)entity);
10347a84e134Smrg		    if (entity == anchor->entities) {
10357a84e134Smrg			if ((anchor->entities = enext) == NULL) {
10367a84e134Smrg			    eprev = NULL;
10377a84e134Smrg			    anchor = XawTextSourceRemoveAnchor(w, anchor);
10387a84e134Smrg			    entity = anchor ? anchor->entities : NULL;
10397a84e134Smrg			}
10407a84e134Smrg			else
10417a84e134Smrg			    eprev = entity = enext;
10427a84e134Smrg		    }
10437a84e134Smrg		    else
10447a84e134Smrg			entity = enext;
10457a84e134Smrg		}
10467a84e134Smrg		else {
10477a84e134Smrg		    eprev = entity;
10487a84e134Smrg		    entity = entity->next;
10497a84e134Smrg		}
10507a84e134Smrg	    }
10517a84e134Smrg
10527a84e134Smrg	    while (anchor) {
10537a84e134Smrg		while (entity) {
10547a84e134Smrg		    offset = anchor->position + entity->offset + entity->length;
10557a84e134Smrg
10567a84e134Smrg		    if (offset > right) {
1057efbcb2bfSmrg			entity->length = (Cardinal) (XawMin(entity->length, offset - right));
10587a84e134Smrg			goto exit_anchor_loop;
10597a84e134Smrg		    }
10607a84e134Smrg
10617a84e134Smrg		    enext = entity->next;
10627a84e134Smrg		    if (eprev)
10637a84e134Smrg			eprev->next = enext;
10647a84e134Smrg		    XtFree((XtPointer)entity);
10657a84e134Smrg		    anchor->cache = NULL;
10667a84e134Smrg		    if (entity == anchor->entities) {
10677a84e134Smrg			eprev = NULL;
10687a84e134Smrg			if ((anchor->entities = enext) == NULL) {
10697a84e134Smrg			    if (i == 0)
10707a84e134Smrg				++i;
10717a84e134Smrg			    else if (i < --src->textSrc.num_anchors) {
10727a84e134Smrg				memmove(&src->textSrc.anchors[i],
10737a84e134Smrg					&src->textSrc.anchors[i + 1],
10745ec34c4cSmrg					(size_t)(src->textSrc.num_anchors - i) *
10757a84e134Smrg					sizeof(XawTextAnchor*));
10767a84e134Smrg				XtFree((XtPointer)anchor);
10777a84e134Smrg			    }
10787a84e134Smrg			    if (i >= src->textSrc.num_anchors) {
10797a84e134Smrg				anchor = NULL;
10807a84e134Smrg				entity = NULL;
10817a84e134Smrg				break;
10827a84e134Smrg			    }
10837a84e134Smrg			    anchor = src->textSrc.anchors[i];
10847a84e134Smrg			    entity = anchor->entities;
10857a84e134Smrg			    continue;
10867a84e134Smrg			}
10877a84e134Smrg		    }
10887a84e134Smrg		    entity = enext;
10897a84e134Smrg		}
10907a84e134Smrg		if (i + 1 < src->textSrc.num_anchors) {
10917a84e134Smrg		    anchor = src->textSrc.anchors[++i];
10927a84e134Smrg		    entity = anchor->entities;
10937a84e134Smrg		    eprev = NULL;
10947a84e134Smrg		}
1095ab902922Smrg		else {
1096ab902922Smrg		    anchor = NULL;
10977a84e134Smrg		    break;
1098ab902922Smrg		}
10997a84e134Smrg		eprev = NULL;
11007a84e134Smrg	    }
11017a84e134Smrg
11027a84e134Smrgexit_anchor_loop:
11037a84e134Smrg	    if (anchor) {
11047a84e134Smrg		XawTextAnchor *aprev;
11057a84e134Smrg
11067a84e134Smrg		if (anchor->position >= XawMax(right, left + block->length))
11077a84e134Smrg		    anchor->position += diff;
11087a84e134Smrg		else if (anchor->position > left &&
11097a84e134Smrg			 (aprev = XawTextSourcePrevAnchor(w, anchor))) {
11107a84e134Smrg		    XawTextPosition tmp = anchor->position - aprev->position;
11117a84e134Smrg
11127a84e134Smrg		    if (diff) {
11137a84e134Smrg			while (entity) {
11147a84e134Smrg			    entity->offset += diff;
11157a84e134Smrg			    entity = entity->next;
11167a84e134Smrg			}
11177a84e134Smrg		    }
11187a84e134Smrg		    entity = anchor->entities;
11197a84e134Smrg		    while (entity) {
11207a84e134Smrg			entity->offset += tmp;
11217a84e134Smrg			entity = entity->next;
11227a84e134Smrg		    }
11237a84e134Smrg		    if ((entity = aprev->entities) == NULL)
11247a84e134Smrg			aprev->entities = anchor->entities;
11257a84e134Smrg		    else {
11267a84e134Smrg			while (entity->next)
11277a84e134Smrg			    entity = entity->next;
11287a84e134Smrg			entity->next = anchor->entities;
11297a84e134Smrg		    }
11307a84e134Smrg		    anchor->entities = NULL;
11317a84e134Smrg		    (void)XawTextSourceRemoveAnchor(w, anchor);
11327a84e134Smrg		    --i;
11337a84e134Smrg		}
11347a84e134Smrg		else if (diff) {
11357a84e134Smrg		    while (entity) {
11367a84e134Smrg			entity->offset += diff;
11377a84e134Smrg			entity = entity->next;
11387a84e134Smrg		    }
11397a84e134Smrg		}
11407a84e134Smrg	    }
11417a84e134Smrg
11427a84e134Smrg	    if (diff) {
1143ab902922Smrg		/*   The first anchor is never removed, and should
1144ab902922Smrg		 * have position 0.
1145ab902922Smrg		 *   i should be -1 if attempted to removed the first
1146ab902922Smrg		 * anchor, what can be caused when removing a chunk
1147ab902922Smrg		 * of text of the first entity.
1148ab902922Smrg		 * */
1149ab902922Smrg		if (++i == 0) {
1150ab902922Smrg		    anchor = src->textSrc.anchors[0];
1151ab902922Smrg		    eprev = entity = anchor->entities;
1152ab902922Smrg		    while (entity) {
1153ab902922Smrg			enext = entity->next;
1154ab902922Smrg			if (entity->offset + entity->length <= -diff)
1155ab902922Smrg			    XtFree((XtPointer)entity);
1156ab902922Smrg			else
1157ab902922Smrg			    break;
1158ab902922Smrg			entity = enext;
1159ab902922Smrg		    }
1160ab902922Smrg		    if (eprev != entity) {
1161ab902922Smrg			anchor->cache = NULL;
1162ab902922Smrg			if ((anchor->entities = entity) != NULL) {
1163ab902922Smrg			    if ((entity->offset += diff) < 0) {
11645ec34c4cSmrg				entity->length = (Cardinal)(entity->length + entity->offset);
1165ab902922Smrg				entity->offset = 0;
1166ab902922Smrg			    }
1167ab902922Smrg			}
1168ab902922Smrg		    }
1169ab902922Smrg		    ++i;
1170ab902922Smrg		}
1171ab902922Smrg		for (; i < src->textSrc.num_anchors; i++)
11727a84e134Smrg		    src->textSrc.anchors[i]->position += diff;
11737a84e134Smrg	    }
11747a84e134Smrg	}
11757a84e134Smrg
11767a84e134Smrg	start = left;
11777a84e134Smrg	end = start + block->length;
11787a84e134Smrg	while (start < end) {
11797a84e134Smrg	    start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True);
11807a84e134Smrg	    if (start <= end) {
11817a84e134Smrg		++lines;
11827a84e134Smrg		if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) {
11837a84e134Smrg		    lines -= !_XawTextSourceNewLineAtEOF(w);
11847a84e134Smrg		    break;
11857a84e134Smrg		}
11867a84e134Smrg	    }
11877a84e134Smrg	}
11887a84e134Smrg
1189efbcb2bfSmrg	{
1190efbcb2bfSmrg	    XawTextPropertyInfo info = {
1191efbcb2bfSmrg		.left = left,
1192efbcb2bfSmrg		.right = right,
1193efbcb2bfSmrg		.block = block
1194efbcb2bfSmrg	    };
1195efbcb2bfSmrg
1196efbcb2bfSmrg	    XtCallCallbacks(w, XtNpropertyCallback, &info);
1197efbcb2bfSmrg	}
11987a84e134Smrg
11997a84e134Smrg	TellSourceChanged(src, left, right, block, lines);
12007a84e134Smrg	/* Call callbacks, we have changed the buffer */
12017a84e134Smrg	XtCallCallbacks(w, XtNcallback,
12027a84e134Smrg			(XtPointer)((long)src->textSrc.changed));
12037a84e134Smrg    }
12047a84e134Smrg
12057a84e134Smrg#endif /* OLDXAW */
12067a84e134Smrg    return (error);
12077a84e134Smrg}
12087a84e134Smrg
12097a84e134Smrg#ifndef OLDXAW
12107a84e134SmrgBool
12117a84e134Smrg_XawTextSrcUndo(TextSrcObject src, XawTextPosition *insert_pos)
12127a84e134Smrg{
12137a84e134Smrg    static wchar_t wnull = 0;
12147a84e134Smrg    XawTextBlock block;
12157a84e134Smrg    XawTextUndoList *list, *nlist;
12167a84e134Smrg    XawTextUndoBuffer *l_state, *r_state;
12177a84e134Smrg    Boolean changed = src->textSrc.changed;
12187a84e134Smrg
12197a84e134Smrg    if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo)
12207a84e134Smrg	return (False);
12217a84e134Smrg
12227a84e134Smrg    list = src->textSrc.undo->pointer;
12237a84e134Smrg
12247a84e134Smrg    if (src->textSrc.undo->dir == XawsdLeft) {
12257a84e134Smrg	l_state = list->right;
12267a84e134Smrg	r_state = list->left;
12277a84e134Smrg    }
12287a84e134Smrg    else {
12297a84e134Smrg	l_state = list->left;
12307a84e134Smrg	r_state = list->right;
12317a84e134Smrg    }
12327a84e134Smrg
12337a84e134Smrg    if (src->textSrc.undo->l_no_change == l_state
12347a84e134Smrg	&& src->textSrc.undo->r_no_change == r_state)
12357a84e134Smrg	src->textSrc.changed = False;
12367a84e134Smrg    else
12377a84e134Smrg	src->textSrc.changed = True;
12387a84e134Smrg
12397a84e134Smrg    block.firstPos = 0;
12405ec34c4cSmrg    block.length = (int)r_state->length;
12417a84e134Smrg    block.ptr = r_state->buffer ? r_state->buffer : (char*)&wnull;
12427a84e134Smrg    block.format = r_state->format;
12437a84e134Smrg
12447a84e134Smrg    src->textSrc.undo_state = True;
12457a84e134Smrg    if (XawTextSourceReplace((Widget)src, l_state->position, l_state->position
12467a84e134Smrg			     + l_state->length, &block) != XawEditDone) {
12477a84e134Smrg	src->textSrc.undo_state = False;
12487a84e134Smrg	src->textSrc.changed = changed;
12497a84e134Smrg	return (False);
12507a84e134Smrg    }
12517a84e134Smrg    src->textSrc.undo_state = False;
12527a84e134Smrg
12537a84e134Smrg    ++l_state->refcount;
12547a84e134Smrg    ++r_state->refcount;
12557a84e134Smrg    nlist = XtNew(XawTextUndoList);
12567a84e134Smrg    nlist->left = l_state;
12577a84e134Smrg    nlist->right = r_state;
12587a84e134Smrg    nlist->undo = src->textSrc.undo->list;
12597a84e134Smrg    nlist->redo = NULL;
12607a84e134Smrg
12617a84e134Smrg    if (list == src->textSrc.undo->list)
12627a84e134Smrg	src->textSrc.undo->end_mark = nlist;
12637a84e134Smrg
12647a84e134Smrg    if (src->textSrc.undo->dir == XawsdLeft) {
12657a84e134Smrg	if (list->undo == NULL)
12667a84e134Smrg	    src->textSrc.undo->dir = XawsdRight;
12677a84e134Smrg	else
12687a84e134Smrg	    list = list->undo;
12697a84e134Smrg    }
12707a84e134Smrg    else {
12717a84e134Smrg	if (list->redo == NULL || list->redo == src->textSrc.undo->end_mark)
12727a84e134Smrg	    src->textSrc.undo->dir = XawsdLeft;
12737a84e134Smrg	else
12747a84e134Smrg	    list = list->redo;
12757a84e134Smrg    }
12767a84e134Smrg    *insert_pos = r_state->position + r_state->length;
12777a84e134Smrg    src->textSrc.undo->pointer = list;
12787a84e134Smrg    src->textSrc.undo->list->redo = nlist;
12797a84e134Smrg    src->textSrc.undo->list = nlist;
12807a84e134Smrg    src->textSrc.undo->merge = src->textSrc.undo->erase = 0;
12817a84e134Smrg
12827a84e134Smrg    if (++src->textSrc.undo->num_list >= UNDO_DEPTH)
12837a84e134Smrg	UndoGC(src->textSrc.undo);
12847a84e134Smrg
12857a84e134Smrg    return (True);
12867a84e134Smrg}
12877a84e134Smrg
12887a84e134SmrgBool
12897a84e134Smrg_XawTextSrcToggleUndo(TextSrcObject src)
12907a84e134Smrg{
12917a84e134Smrg    if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo)
12927a84e134Smrg	return (False);
12937a84e134Smrg
12947a84e134Smrg    if (src->textSrc.undo->pointer != src->textSrc.undo->list) {
12957a84e134Smrg	if (src->textSrc.undo->dir == XawsdLeft) {
12967a84e134Smrg	    if (src->textSrc.undo->pointer->redo
12977a84e134Smrg		&& (src->textSrc.undo->pointer->redo
12987a84e134Smrg		    != src->textSrc.undo->end_mark)) {
12997a84e134Smrg		src->textSrc.undo->pointer = src->textSrc.undo->pointer->redo;
13007a84e134Smrg		src->textSrc.undo->dir = XawsdRight;
13017a84e134Smrg	    }
13027a84e134Smrg	}
13037a84e134Smrg	else {
13047a84e134Smrg	    if (src->textSrc.undo->pointer->undo
13057a84e134Smrg		&& (src->textSrc.undo->pointer != src->textSrc.undo->head)) {
13067a84e134Smrg		src->textSrc.undo->pointer = src->textSrc.undo->pointer->undo;
13077a84e134Smrg		src->textSrc.undo->dir = XawsdLeft;
13087a84e134Smrg	    }
13097a84e134Smrg	}
13107a84e134Smrg    }
13117a84e134Smrg
13127a84e134Smrg    return (True);
13137a84e134Smrg}
13147a84e134Smrg
13157a84e134Smrgstatic void
13167a84e134SmrgFreeUndoBuffer(XawTextUndo *undo)
13177a84e134Smrg{
13187a84e134Smrg    unsigned i;
13197a84e134Smrg    XawTextUndoList *head, *del;
13207a84e134Smrg
13217a84e134Smrg    for (i = 0; i < undo->num_undo; i++) {
13227a84e134Smrg	if (undo->undo[i]->buffer && undo->undo[i]->buffer != SrcNL &&
13237a84e134Smrg	    undo->undo[i]->buffer != (char*)SrcWNL)
13247a84e134Smrg	    XtFree(undo->undo[i]->buffer);
13257a84e134Smrg	XtFree((char*)undo->undo[i]);
13267a84e134Smrg    }
13277a84e134Smrg    XtFree((char*)undo->undo);
13287a84e134Smrg    head = undo->head;
13297a84e134Smrg
13307a84e134Smrg    del = head;
13317a84e134Smrg    while (head) {
13327a84e134Smrg	head = head->redo;
13337a84e134Smrg	XtFree((char*)del);
13347a84e134Smrg	del = head;
13357a84e134Smrg    }
13367a84e134Smrg
13377a84e134Smrg    if (undo->l_save) {
13387a84e134Smrg	XtFree((char*)undo->l_save);
13397a84e134Smrg	undo->l_save = NULL;
13407a84e134Smrg    }
13417a84e134Smrg    if (undo->r_save) {
13427a84e134Smrg	XtFree((char*)undo->r_save);
13437a84e134Smrg	undo->r_save = NULL;
13447a84e134Smrg    }
13457a84e134Smrg    if (undo->u_save) {
13467a84e134Smrg	XtFree((char*)undo->u_save);
13477a84e134Smrg	undo->u_save = NULL;
13487a84e134Smrg    }
13497a84e134Smrg
13507a84e134Smrg    undo->list = undo->pointer = undo->head = undo->end_mark = NULL;
13517a84e134Smrg    undo->l_no_change = undo->r_no_change = NULL;
13527a84e134Smrg    undo->undo = NULL;
13537a84e134Smrg    undo->dir = XawsdLeft;
13545ec34c4cSmrg    undo->num_undo = undo->num_list = (unsigned)(undo->erase = undo->merge = 0);
13557a84e134Smrg}
13567a84e134Smrg
13577a84e134Smrgstatic void
13587a84e134SmrgUndoGC(XawTextUndo *undo)
13597a84e134Smrg{
13607a84e134Smrg    XawTextUndoList *head = undo->head, *redo = head->redo;
13617a84e134Smrg
13627a84e134Smrg    if (head == undo->pointer || head == undo->end_mark
13637a84e134Smrg	|| undo->l_no_change == NULL
13647a84e134Smrg	|| head->left == undo->l_no_change || head->right == undo->l_no_change)
13657a84e134Smrg      return;
13667a84e134Smrg
13677a84e134Smrg    undo->head = redo;
13687a84e134Smrg    redo->undo = NULL;
13697a84e134Smrg
13707a84e134Smrg    --head->left->refcount;
13717a84e134Smrg    if (--head->right->refcount == 0) {
1372efbcb2bfSmrg	unsigned i;
1373efbcb2bfSmrg
13747a84e134Smrg	for (i = 0; i < undo->num_undo; i+= 2)
13757a84e134Smrg	    if (head->left == undo->undo[i] || head->left == undo->undo[i+1]) {
13767a84e134Smrg		if (head->left == undo->undo[i+1]) {
13777a84e134Smrg		    XawTextUndoBuffer *tmp = redo->left;
13787a84e134Smrg
13797a84e134Smrg		    redo->left = redo->right;
13807a84e134Smrg		    redo->right = tmp;
13817a84e134Smrg		}
13827a84e134Smrg		if (head->left->buffer && head->left->buffer != SrcNL &&
13837a84e134Smrg		    head->left->buffer != (char*)SrcWNL)
13847a84e134Smrg		    XtFree(head->left->buffer);
13857a84e134Smrg		XtFree((char*)head->left);
13867a84e134Smrg		if (head->right->buffer && head->right->buffer != SrcNL &&
13877a84e134Smrg		    head->right->buffer != (char*)SrcWNL)
13887a84e134Smrg		    XtFree(head->right->buffer);
13897a84e134Smrg		XtFree((char*)head->right);
13907a84e134Smrg
13917a84e134Smrg		undo->num_undo -= 2;
13927a84e134Smrg		memmove(&undo->undo[i], &undo->undo[i + 2],
13937a84e134Smrg			(undo->num_undo - i) * sizeof(XawTextUndoBuffer*));
13947a84e134Smrg		break;
13957a84e134Smrg	    }
13967a84e134Smrg    }
13977a84e134Smrg    XtFree((char*)head);
13987a84e134Smrg    --undo->num_list;
13997a84e134Smrg}
14007a84e134Smrg#endif /* OLDXAW */
14017a84e134Smrg
14027a84e134Smrg/*
14037a84e134Smrg * Function:
14047a84e134Smrg *	XawTextSourceScan
14057a84e134Smrg *
14067a84e134Smrg * Parameters:
14077a84e134Smrg *	w	 - TextSrc Object
14087a84e134Smrg *	position - position to start scanning
14097a84e134Smrg *	type	 - type of thing to scan for
14107a84e134Smrg *	dir	 - direction to scan
14115b16253fSmrg *	count	 - which occurrence if this thing to search for
14127a84e134Smrg *	include  - whether or not to include the character found in
1413421c997bSmrg *		   the position that is returned.
14147a84e134Smrg *
14157a84e134Smrg * Description:
14167a84e134Smrg *	Scans the text source for the number and type of item specified.
14177a84e134Smrg *
14187a84e134Smrg * Returns:
14197a84e134Smrg *	The position of the text
14207a84e134Smrg */
14217a84e134SmrgXawTextPosition
14227a84e134SmrgXawTextSourceScan(Widget w, XawTextPosition position,
14237a84e134Smrg#if NeedWidePrototypes
14247a84e134Smrg		  int type, int dir, int count, int include
14257a84e134Smrg#else
14267a84e134Smrg		  XawTextScanType type, XawTextScanDirection dir,
14277a84e134Smrg		  int count, Boolean include
14287a84e134Smrg#endif
14297a84e134Smrg)
14307a84e134Smrg{
14317a84e134Smrg    TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
14327a84e134Smrg
14337a84e134Smrg    return ((*cclass->textSrc_class.Scan)
14347a84e134Smrg	    (w, position, type, dir, count, include));
14357a84e134Smrg}
14367a84e134Smrg
14377a84e134Smrg/*
14387a84e134Smrg * Function:
14397a84e134Smrg *	XawTextSourceSearch
14407a84e134Smrg *
14417a84e134Smrg * Parameters:
14427a84e134Smrg *	w	 - TextSource Object
14437a84e134Smrg *	position - position to start scanning
14447a84e134Smrg *	dir	 - direction to scan
14457a84e134Smrg *	text	 - the text block to search for.
14467a84e134Smrg *
14477a84e134Smrg * Returns:
14487a84e134Smrg *	The position of the text we are searching for or XawTextSearchError.
14497a84e134Smrg *
14507a84e134Smrg * Description:
14515b16253fSmrg *	Searches the text source for the text block passed
14527a84e134Smrg */
1453421c997bSmrgXawTextPosition
14547a84e134SmrgXawTextSourceSearch(Widget w, XawTextPosition position,
14557a84e134Smrg#if NeedWidePrototypes
14567a84e134Smrg		    int dir,
14577a84e134Smrg#else
14587a84e134Smrg		    XawTextScanDirection dir,
14597a84e134Smrg#endif
14607a84e134Smrg		    XawTextBlock *text)
14617a84e134Smrg{
14627a84e134Smrg    TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
14637a84e134Smrg
14647a84e134Smrg    return ((*cclass->textSrc_class.Search)(w, position, dir, text));
14657a84e134Smrg}
14667a84e134Smrg
14677a84e134Smrg/*
14687a84e134Smrg * Function:
14697a84e134Smrg *	XawTextSourceConvertSelection
14707a84e134Smrg *
14717a84e134Smrg * Parameters:
14727a84e134Smrg *	w	  - TextSrc object
14737a84e134Smrg *	selection - current selection atom
14747a84e134Smrg *	target	  - current target atom
14755b16253fSmrg *	type	  - type to convert the selection to
14767a84e134Smrg *	value	  - return value that has been converted
14777a84e134Smrg *	length	  - ""
14787a84e134Smrg *	format	  - format of the returned value
14797a84e134Smrg *
14807a84e134Smrg * Returns:
14817a84e134Smrg *	True if the selection has been converted
14827a84e134Smrg */
14837a84e134SmrgBoolean
1484421c997bSmrgXawTextSourceConvertSelection(Widget w, Atom *selection, Atom *target,
14857a84e134Smrg			      Atom *type, XtPointer *value,
14867a84e134Smrg			      unsigned long *length, int *format)
14877a84e134Smrg{
14887a84e134Smrg    TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
14897a84e134Smrg
14907a84e134Smrg    return((*cclass->textSrc_class.ConvertSelection)
14917a84e134Smrg	   (w, selection, target, type, value, length, format));
14927a84e134Smrg}
14937a84e134Smrg
14947a84e134Smrg/*
14957a84e134Smrg * Function:
14967a84e134Smrg *	XawTextSourceSetSelection
14977a84e134Smrg *
14987a84e134Smrg * Parameters:
14997a84e134Smrg *	w	  - TextSrc object
15007a84e134Smrg *	left	  - bounds of the selection
15015b16253fSmrg *	right	  - ""
15027a84e134Smrg *	selection - selection atom
15037a84e134Smrg *
15047a84e134Smrg * Description:
15057a84e134Smrg *	Allows special setting of the selection.
15067a84e134Smrg */
15077a84e134Smrgvoid
1508421c997bSmrgXawTextSourceSetSelection(Widget w, XawTextPosition left,
15097a84e134Smrg			  XawTextPosition right, Atom selection)
15107a84e134Smrg{
15117a84e134Smrg    TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
15127a84e134Smrg
15137a84e134Smrg    (*cclass->textSrc_class.SetSelection)(w, left, right, selection);
15147a84e134Smrg}
15157a84e134Smrg
15167a84e134Smrg/*
15177a84e134Smrg * External Functions for Multi Text
15187a84e134Smrg */
15197a84e134Smrg/*
1520421c997bSmrg * TextFormat():
15217a84e134Smrg *	returns the format of text: FMT8BIT or FMTWIDE
15227a84e134Smrg */
15237a84e134SmrgXrmQuark
15247a84e134Smrg_XawTextFormat(TextWidget tw)
15257a84e134Smrg{
15267a84e134Smrg    return (((TextSrcObject)(tw->text.source))->textSrc.text_format);
15277a84e134Smrg}
15287a84e134Smrg
15297a84e134Smrg/* _XawTextWCToMB():
15307a84e134Smrg *	Convert the wchar string to external encoding
15317a84e134Smrg *	The caller is responsible for freeing both the source and ret string
15327a84e134Smrg *
15337a84e134Smrg *	wstr	   - source wchar string
15345b16253fSmrg *	len_in_out - length of string.
15357a84e134Smrg *		     As In, length of source wchar string, measured in wchar
15367a84e134Smrg *		     As Out, length of returned string
15377a84e134Smrg */
15387a84e134Smrgchar *
15397a84e134Smrg_XawTextWCToMB(Display *d, wchar_t *wstr, int *len_in_out)
15407a84e134Smrg{
15417a84e134Smrg    XTextProperty textprop;
15427a84e134Smrg
15437a84e134Smrg    if (XwcTextListToTextProperty(d, (wchar_t**)&wstr, 1,
15447a84e134Smrg				XTextStyle, &textprop) < Success) {
15457a84e134Smrg	XtWarningMsg("convertError", "textSource", "XawError",
15467a84e134Smrg		     "Non-character code(s) in buffer.", NULL, NULL);
15477a84e134Smrg	*len_in_out = 0;
15487a84e134Smrg	return (NULL);
15497a84e134Smrg    }
15505ec34c4cSmrg    *len_in_out = (int)textprop.nitems;
15517a84e134Smrg
15527a84e134Smrg    return ((char *)textprop.value);
15537a84e134Smrg}
15547a84e134Smrg
15557a84e134Smrg/* _XawTextMBToWC():
15567a84e134Smrg *	Convert the string to internal processing codeset WC.
15577a84e134Smrg *   The caller is responsible for freeing both the source and ret string.
1558421c997bSmrg *
15597a84e134Smrg *	str	   - source string
15605b16253fSmrg *	len_in_out - length of string
15617a84e134Smrg *		     As In, it is length of source string
15627a84e134Smrg *		     As Out, it is length of returned string, measured in wchar
15637a84e134Smrg */
15647a84e134Smrgwchar_t *
15657a84e134Smrg_XawTextMBToWC(Display *d, char *str, int *len_in_out)
15667a84e134Smrg{
15677a84e134Smrg    XTextProperty textprop;
15687a84e134Smrg    char *buf;
15697a84e134Smrg    wchar_t **wlist, *wstr;
15707a84e134Smrg    int count;
15717a84e134Smrg
15727a84e134Smrg    if (*len_in_out == 0)
15737a84e134Smrg	return (NULL);
15747a84e134Smrg
15755ec34c4cSmrg    buf = XtMalloc((Cardinal)(*len_in_out + 1));
15767a84e134Smrg
15775ec34c4cSmrg    strncpy(buf, str, (size_t)*len_in_out);
15787a84e134Smrg    *(buf + *len_in_out) = '\0';
15797a84e134Smrg    if (XmbTextListToTextProperty(d, &buf, 1, XTextStyle, &textprop) != Success) {
15807a84e134Smrg	XtWarningMsg("convertError", "textSource", "XawError",
15817a84e134Smrg		     "No Memory, or Locale not supported.", NULL, NULL);
15827a84e134Smrg	XtFree(buf);
15837a84e134Smrg	*len_in_out = 0;
15847a84e134Smrg	return (NULL);
15857a84e134Smrg    }
15867a84e134Smrg
15877a84e134Smrg    XtFree(buf);
15887a84e134Smrg    if (XwcTextPropertyToTextList(d, &textprop,
15897a84e134Smrg				  (wchar_t***)&wlist, &count) != Success) {
15907a84e134Smrg	XtWarningMsg("convertError", "multiSourceCreate", "XawError",
15917a84e134Smrg		     "Non-character code(s) in source.", NULL, NULL);
15927a84e134Smrg	*len_in_out = 0;
15937a84e134Smrg	return (NULL);
15947a84e134Smrg    }
15957a84e134Smrg    wstr = wlist[0];
15965ec34c4cSmrg    *len_in_out = (int)wcslen(wstr);
15977a84e134Smrg    XtFree((XtPointer)wlist);
15987a84e134Smrg
15997a84e134Smrg    return (wstr);
16007a84e134Smrg}
16017a84e134Smrg
16027a84e134Smrg#ifndef OLDXAW
16037a84e134Smrgstatic int
16047a84e134Smrgqcmp_anchors(_Xconst void *left, _Xconst void *right)
16057a84e134Smrg{
16065ec34c4cSmrg    return (int)((*(XawTextAnchor**)left)->position -
16075ec34c4cSmrg		 (*(XawTextAnchor**)right)->position);
16087a84e134Smrg}
16097a84e134Smrg
16107a84e134SmrgXawTextAnchor *
16117a84e134SmrgXawTextSourceAddAnchor(Widget w, XawTextPosition position)
16127a84e134Smrg{
16137a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
16147a84e134Smrg    XawTextAnchor *anchor, *panchor;
16157a84e134Smrg
16167a84e134Smrg    if ((panchor = XawTextSourceFindAnchor(w, position)) != NULL) {
16177a84e134Smrg	XawTextEntity *pentity, *entity;
16187a84e134Smrg
16197a84e134Smrg	if (position - panchor->position < ANCHORS_DIST)
16207a84e134Smrg	    return (panchor);
16217a84e134Smrg
16227a84e134Smrg	if (panchor->cache && panchor->position + panchor->cache->offset +
16237a84e134Smrg	    panchor->cache->length < position)
16247a84e134Smrg	    pentity = entity = panchor->cache;
16257a84e134Smrg	else
16267a84e134Smrg	    pentity = entity = panchor->entities;
16277a84e134Smrg
16287a84e134Smrg	while (entity && panchor->position + entity->offset +
16297a84e134Smrg	       entity->length < position) {
16307a84e134Smrg	    pentity = entity;
16317a84e134Smrg	    entity = entity->next;
16327a84e134Smrg	}
16337a84e134Smrg	if (entity) {
16347a84e134Smrg	    XawTextPosition diff;
16357a84e134Smrg
16367a84e134Smrg	    if (panchor->position + entity->offset < position)
16377a84e134Smrg		position = panchor->position + entity->offset;
16387a84e134Smrg
16397a84e134Smrg	    if (position == panchor->position)
16407a84e134Smrg		return (panchor);
16417a84e134Smrg
16427a84e134Smrg	    anchor = XtNew(XawTextAnchor);
16437a84e134Smrg	    diff = position - panchor->position;
16447a84e134Smrg
16457a84e134Smrg	    panchor->cache = NULL;
16467a84e134Smrg	    anchor->entities = entity;
16477a84e134Smrg	    if (pentity != entity)
16487a84e134Smrg		pentity->next = NULL;
16497a84e134Smrg	    else
16507a84e134Smrg		panchor->entities = NULL;
16517a84e134Smrg	    while (entity) {
16527a84e134Smrg		entity->offset -= diff;
16537a84e134Smrg		entity = entity->next;
16547a84e134Smrg	    }
16557a84e134Smrg	}
16567a84e134Smrg	else {
16577a84e134Smrg	    anchor = XtNew(XawTextAnchor);
16587a84e134Smrg	    anchor->entities = NULL;
16597a84e134Smrg	}
16607a84e134Smrg    }
16617a84e134Smrg    else {
16627a84e134Smrg	anchor = XtNew(XawTextAnchor);
16637a84e134Smrg	anchor->entities = NULL;
16647a84e134Smrg    }
16657a84e134Smrg
16667a84e134Smrg    anchor->position = position;
16677a84e134Smrg    anchor->cache = NULL;
16687a84e134Smrg
16697a84e134Smrg    src->textSrc.anchors = (XawTextAnchor**)
16705ec34c4cSmrg	XtRealloc((XtPointer)src->textSrc.anchors,
16715ec34c4cSmrg		  (Cardinal)(sizeof(XawTextAnchor*) *
16725ec34c4cSmrg			     (size_t)(src->textSrc.num_anchors + 1)));
16737a84e134Smrg    src->textSrc.anchors[src->textSrc.num_anchors++] = anchor;
16745ec34c4cSmrg    qsort((void*)src->textSrc.anchors,
16755ec34c4cSmrg	  (size_t)src->textSrc.num_anchors,
16767a84e134Smrg	  sizeof(XawTextAnchor*), qcmp_anchors);
16777a84e134Smrg
16787a84e134Smrg    return (anchor);
16797a84e134Smrg}
16807a84e134Smrg
16817a84e134SmrgXawTextAnchor *
16827a84e134SmrgXawTextSourceFindAnchor(Widget w, XawTextPosition position)
16837a84e134Smrg{
16847a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
1685efbcb2bfSmrg    int left, right, nmemb = src->textSrc.num_anchors;
1686efbcb2bfSmrg    XawTextAnchor **anchors = src->textSrc.anchors;
16877a84e134Smrg
16887a84e134Smrg    left = 0;
16897a84e134Smrg    right = nmemb - 1;
16907a84e134Smrg    while (left <= right) {
1691efbcb2bfSmrg	int i = (left + right) >> 1;
1692efbcb2bfSmrg	XawTextAnchor *anchor = anchors[i];
1693efbcb2bfSmrg
16947a84e134Smrg	if (anchor->position == position)
16957a84e134Smrg	    return (anchor);
16967a84e134Smrg	else if (position < anchor->position)
16977a84e134Smrg	    right = i - 1;
16987a84e134Smrg	else
16997a84e134Smrg	    left = i + 1;
17007a84e134Smrg    }
17017a84e134Smrg
17027a84e134Smrg    if (nmemb)
17037a84e134Smrg	return (right < 0 ? anchors[0] : anchors[right]);
17047a84e134Smrg
17057a84e134Smrg    return (NULL);
17067a84e134Smrg}
17077a84e134Smrg
17087a84e134SmrgBool
17097a84e134SmrgXawTextSourceAnchorAndEntity(Widget w, XawTextPosition position,
17107a84e134Smrg			     XawTextAnchor **anchor_return,
17117a84e134Smrg			     XawTextEntity **entity_return)
17127a84e134Smrg{
17137a84e134Smrg    XawTextAnchor *anchor = XawTextSourceFindAnchor(w, position);
17147a84e134Smrg    XawTextEntity *pentity, *entity;
17157a84e134Smrg    Bool next_anchor = True, retval = False;
17167a84e134Smrg
17177a84e134Smrg    if (anchor->cache && anchor->position + anchor->cache->offset +
17187a84e134Smrg	anchor->cache->length <= position)
17197a84e134Smrg	pentity = entity = anchor->cache;
17207a84e134Smrg    else
17217a84e134Smrg	pentity = entity = anchor->entities;
17227a84e134Smrg    while (entity) {
1723efbcb2bfSmrg	XawTextPosition offset = anchor->position + entity->offset;
17247a84e134Smrg
17257a84e134Smrg	if (offset > position) {
17267a84e134Smrg	    retval = next_anchor = False;
17277a84e134Smrg	    break;
17287a84e134Smrg	}
17297a84e134Smrg	if (offset + entity->length > position) {
17307a84e134Smrg	    retval = True;
17317a84e134Smrg	    next_anchor = False;
17327a84e134Smrg	    break;
17337a84e134Smrg	}
17347a84e134Smrg	pentity = entity;
17357a84e134Smrg	entity = entity->next;
17367a84e134Smrg    }
17377a84e134Smrg
17387a84e134Smrg    if (next_anchor) {
17397a84e134Smrg	*anchor_return = anchor = XawTextSourceNextAnchor(w, anchor);
17407a84e134Smrg	*entity_return = anchor ? anchor->entities : NULL;
17417a84e134Smrg    }
17427a84e134Smrg    else {
17437a84e134Smrg	*anchor_return = anchor;
17447a84e134Smrg	*entity_return = retval ? entity : pentity;
17457a84e134Smrg    }
17467a84e134Smrg
17477a84e134Smrg    if (*anchor_return)
17487a84e134Smrg	(*anchor_return)->cache = *entity_return;
17497a84e134Smrg
17507a84e134Smrg    return (retval);
17517a84e134Smrg}
17527a84e134Smrg
17537a84e134SmrgXawTextAnchor *
17547a84e134SmrgXawTextSourceNextAnchor(Widget w, XawTextAnchor *anchor)
17557a84e134Smrg{
17567a84e134Smrg    int i;
17577a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
17587a84e134Smrg
17597a84e134Smrg    for (i = 0; i < src->textSrc.num_anchors - 1; i++)
17607a84e134Smrg	if (src->textSrc.anchors[i] == anchor)
17617a84e134Smrg	    return (src->textSrc.anchors[i + 1]);
17627a84e134Smrg
17637a84e134Smrg    return (NULL);
17647a84e134Smrg}
17657a84e134Smrg
17667a84e134SmrgXawTextAnchor *
17677a84e134SmrgXawTextSourcePrevAnchor(Widget w, XawTextAnchor *anchor)
17687a84e134Smrg{
17697a84e134Smrg    int i;
17707a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
17717a84e134Smrg
17727a84e134Smrg    for (i = src->textSrc.num_anchors - 1; i > 0; i--)
17737a84e134Smrg	if (src->textSrc.anchors[i] == anchor)
17747a84e134Smrg	    return (src->textSrc.anchors[i - 1]);
17757a84e134Smrg
17767a84e134Smrg    return (NULL);
17777a84e134Smrg}
17787a84e134Smrg
17797a84e134SmrgXawTextAnchor *
17807a84e134SmrgXawTextSourceRemoveAnchor(Widget w, XawTextAnchor *anchor)
17817a84e134Smrg{
17827a84e134Smrg    int i;
17837a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
17847a84e134Smrg
17857a84e134Smrg    for (i = 0; i < src->textSrc.num_anchors; i++)
17867a84e134Smrg	if (src->textSrc.anchors[i] == anchor)
17877a84e134Smrg	    break;
17887a84e134Smrg
17897a84e134Smrg    if (i == 0)
17907a84e134Smrg	return (src->textSrc.num_anchors > 1 ? src->textSrc.anchors[1] : NULL);
17917a84e134Smrg
17927a84e134Smrg    if (i < src->textSrc.num_anchors) {
17937a84e134Smrg	XtFree((XtPointer)anchor);
17947a84e134Smrg	if (i < --src->textSrc.num_anchors) {
17957a84e134Smrg	    memmove(&src->textSrc.anchors[i],
17967a84e134Smrg		    &src->textSrc.anchors[i + 1],
17975ec34c4cSmrg		    (size_t)(src->textSrc.num_anchors - i) *
17987a84e134Smrg		    sizeof(XawTextAnchor*));
17997a84e134Smrg
18007a84e134Smrg	    return (src->textSrc.anchors[i]);
18017a84e134Smrg	}
18027a84e134Smrg    }
18037a84e134Smrg
18047a84e134Smrg    return (NULL);
18057a84e134Smrg}
18067a84e134Smrg
18077a84e134SmrgXawTextEntity *
18087a84e134SmrgXawTextSourceAddEntity(Widget w, int type, int flags, XtPointer data,
18097a84e134Smrg		       XawTextPosition position, Cardinal length,
18107a84e134Smrg		       XrmQuark property)
18117a84e134Smrg{
18127a84e134Smrg    XawTextAnchor *next, *anchor = _XawTextSourceFindAnchor(w, position);
18137a84e134Smrg    XawTextEntity *entity, *eprev;
18147a84e134Smrg
18157a84e134Smrg    /* There is no support for zero length entities for now */
18167a84e134Smrg    if (length == 0)
18177a84e134Smrg	return (NULL);
18187a84e134Smrg
18197a84e134Smrg    if (anchor->cache && anchor->position + anchor->cache->offset +
18207a84e134Smrg	anchor->cache->length <= position)
18217a84e134Smrg	eprev = entity = anchor->cache;
18227a84e134Smrg    else
18237a84e134Smrg	eprev = entity = anchor->entities;
18247a84e134Smrg
18257a84e134Smrg    while (entity && anchor->position + entity->offset + entity->length <=
18267a84e134Smrg	   position) {
18277a84e134Smrg	eprev = entity;
18287a84e134Smrg	entity = entity->next;
18297a84e134Smrg    }
18307a84e134Smrg    if (entity && anchor->position + entity->offset < position + length) {
18317a84e134Smrg	fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n");
18327a84e134Smrg	return (NULL);
18337a84e134Smrg    }
18347a84e134Smrg
18357a84e134Smrg    next = XawTextSourceFindAnchor(w, position + length);
18367a84e134Smrg    if (next && next != anchor) {
18377a84e134Smrg	if ((entity = next->entities) != NULL) {
18387a84e134Smrg	    if (next->position + entity->offset < position + length) {
18397a84e134Smrg		fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n");
18407a84e134Smrg		return (NULL);
18417a84e134Smrg	    }
18427a84e134Smrg	}
18437a84e134Smrg	if (position + length > next->position) {
18447a84e134Smrg	    XawTextPosition diff = position + length - next->position;
18457a84e134Smrg
18467a84e134Smrg	    next->position += diff;
18477a84e134Smrg	    entity = next->entities;
18487a84e134Smrg	    while (entity) {
18497a84e134Smrg		entity->offset -= diff;
18507a84e134Smrg		entity = entity->next;
18517a84e134Smrg	    }
18527a84e134Smrg	    entity = anchor->entities;
18537a84e134Smrg	    while (entity && entity->offset < 0)
18547a84e134Smrg		entity = entity->next;
18557a84e134Smrg	    if (entity && entity->offset < 0) {
18567a84e134Smrg		if (eprev)
18577a84e134Smrg		    eprev->next = next->entities;
18587a84e134Smrg		else
18597a84e134Smrg		    anchor->entities = next->entities;
18607a84e134Smrg		if ((next->entities = entity->next) == NULL)
18617a84e134Smrg		    (void)XawTextSourceRemoveAnchor(w, next);
18627a84e134Smrg		entity->next = NULL;
18637a84e134Smrg
18647a84e134Smrg		return (XawTextSourceAddEntity(w, type, flags, data, position,
18657a84e134Smrg					       length, property));
18667a84e134Smrg	    }
18677a84e134Smrg	}
18687a84e134Smrg    }
18697a84e134Smrg
18707a84e134Smrg    /* Automatically join sequential entities if possible */
18717a84e134Smrg    if (eprev &&
18727a84e134Smrg	anchor->position + eprev->offset + eprev->length == position &&
18737a84e134Smrg	eprev->property == property && eprev->type == type &&
18747a84e134Smrg	eprev->flags == flags && eprev->data == data) {
18757a84e134Smrg	eprev->length += length;
18767a84e134Smrg	return (eprev);
18777a84e134Smrg    }
18787a84e134Smrg
18797a84e134Smrg    entity = XtNew(XawTextEntity);
18805ec34c4cSmrg    entity->type = (short)type;
18815ec34c4cSmrg    entity->flags = (short)flags;
18827a84e134Smrg    entity->data = data;
18837a84e134Smrg    entity->offset = position - anchor->position;
18847a84e134Smrg    entity->length = length;
18857a84e134Smrg    entity->property = property;
18867a84e134Smrg
18877a84e134Smrg    if (eprev == NULL) {
18887a84e134Smrg	anchor->entities = entity;
18897a84e134Smrg	entity->next = NULL;
18907a84e134Smrg	anchor->cache = NULL;
18917a84e134Smrg    }
18927a84e134Smrg    else if (eprev->offset > entity->offset) {
18937a84e134Smrg	anchor->cache = NULL;
18947a84e134Smrg	anchor->entities = entity;
18957a84e134Smrg	entity->next = eprev;
18967a84e134Smrg    }
18977a84e134Smrg    else {
18987a84e134Smrg	anchor->cache = eprev;
18997a84e134Smrg	entity->next = eprev->next;
19007a84e134Smrg	eprev->next = entity;
19017a84e134Smrg    }
19027a84e134Smrg
19037a84e134Smrg    return (entity);
19047a84e134Smrg}
19057a84e134Smrg
19067a84e134Smrgvoid
19077a84e134SmrgXawTextSourceClearEntities(Widget w, XawTextPosition left, XawTextPosition right)
19087a84e134Smrg{
19097a84e134Smrg    XawTextAnchor *anchor = XawTextSourceFindAnchor(w, left);
19107a84e134Smrg    XawTextEntity *entity, *eprev, *enext;
19117a84e134Smrg    XawTextPosition offset;
19127a84e134Smrg
19137a84e134Smrg    while (anchor && anchor->entities == NULL)
19147a84e134Smrg	anchor = XawTextSourceRemoveAnchor(w, anchor);
19157a84e134Smrg
19167a84e134Smrg    if (anchor == NULL || left >= right)
19177a84e134Smrg	return;
19187a84e134Smrg
19197a84e134Smrg    if (anchor->cache && anchor->position + anchor->cache->offset +
19207a84e134Smrg	anchor->cache->length < left)
19217a84e134Smrg	eprev = entity = anchor->cache;
19227a84e134Smrg    else
19237a84e134Smrg	eprev = entity = anchor->entities;
19247a84e134Smrg
19257a84e134Smrg    /* find first entity before left position */
19267a84e134Smrg    while (anchor->position + entity->offset + entity->length < left) {
19277a84e134Smrg	eprev = entity;
19287a84e134Smrg	if ((entity = entity->next) == NULL) {
19297a84e134Smrg	    if ((anchor = XawTextSourceNextAnchor(w, anchor)) == NULL)
19307a84e134Smrg		return;
19317a84e134Smrg	    if ((eprev = entity = anchor->entities) == NULL) {
19327a84e134Smrg		fprintf(stderr, "Bad anchor found!\n");
19337a84e134Smrg		return;
19347a84e134Smrg	    }
19357a84e134Smrg	}
19367a84e134Smrg    }
19377a84e134Smrg
19387a84e134Smrg    offset = anchor->position + entity->offset;
19397a84e134Smrg    if (offset <= left) {
1940efbcb2bfSmrg	int length = (int) (XawMin(entity->length, left - offset));
19417a84e134Smrg
19427a84e134Smrg	if (length <= 0) {
19437a84e134Smrg	    enext = entity->next;
19447a84e134Smrg	    eprev->next = enext;
19457a84e134Smrg	    XtFree((XtPointer)entity);
19467a84e134Smrg	    anchor->cache = NULL;
19477a84e134Smrg	    if (entity == anchor->entities) {
19487a84e134Smrg		eprev = NULL;
19497a84e134Smrg		if ((anchor->entities = enext) == NULL) {
19507a84e134Smrg		    if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL)
19517a84e134Smrg			return;
19527a84e134Smrg		    entity = anchor->entities;
19537a84e134Smrg		}
19547a84e134Smrg		else
19557a84e134Smrg		    entity = enext;
19567a84e134Smrg	    }
19577a84e134Smrg	    else
19587a84e134Smrg		entity = enext;
19597a84e134Smrg	}
19607a84e134Smrg	else {
19615ec34c4cSmrg	    entity->length = (Cardinal)length;
19627a84e134Smrg	    eprev = entity;
19637a84e134Smrg	    entity = entity->next;
19647a84e134Smrg	}
19657a84e134Smrg    }
19667a84e134Smrg
19677a84e134Smrg    /* clean everything until right position is reached */
19687a84e134Smrg    while (anchor) {
19697a84e134Smrg	while (entity) {
19707a84e134Smrg	    offset = anchor->position + entity->offset + entity->length;
19717a84e134Smrg
19727a84e134Smrg	    if (offset > right) {
19737a84e134Smrg		anchor->cache = NULL;
19747a84e134Smrg		entity->offset = XawMax(entity->offset, right - anchor->position);
1975efbcb2bfSmrg		entity->length = (Cardinal) (XawMin(entity->length, offset - right));
19767a84e134Smrg		return;
19777a84e134Smrg	    }
19787a84e134Smrg
19797a84e134Smrg	    enext = entity->next;
19807a84e134Smrg	    if (eprev)
19817a84e134Smrg		eprev->next = enext;
19827a84e134Smrg	    XtFree((XtPointer)entity);
19837a84e134Smrg	    if (entity == anchor->entities) {
19847a84e134Smrg		eprev = anchor->cache = NULL;
19857a84e134Smrg		if ((anchor->entities = enext) == NULL) {
19867a84e134Smrg		    if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL)
19877a84e134Smrg			return;
19887a84e134Smrg		    entity = anchor->entities;
19897a84e134Smrg		    continue;
19907a84e134Smrg		}
19917a84e134Smrg	    }
19927a84e134Smrg	    entity = enext;
19937a84e134Smrg	}
19947a84e134Smrg	if (anchor)
19957a84e134Smrg	    anchor->cache = NULL;
19967a84e134Smrg	if ((anchor = XawTextSourceNextAnchor(w, anchor)) != NULL)
19977a84e134Smrg	    entity = anchor->entities;
19987a84e134Smrg	eprev = NULL;
19997a84e134Smrg    }
20007a84e134Smrg}
20017a84e134Smrg
20027a84e134Smrg/* checks the anchors up to position, and create an appropriate anchor
20037a84e134Smrg * at position, if required.
20047a84e134Smrg */
20057a84e134SmrgXawTextAnchor *
20067a84e134Smrg_XawTextSourceFindAnchor(Widget w, XawTextPosition position)
20077a84e134Smrg{
20087a84e134Smrg    XawTextAnchor *anchor;
20097a84e134Smrg
20107a84e134Smrg    anchor = XawTextSourceFindAnchor(w, position);
20117a84e134Smrg
20127a84e134Smrg    position -= position % ANCHORS_DIST;
20137a84e134Smrg
20147a84e134Smrg    if (position - anchor->position >= ANCHORS_DIST)
20157a84e134Smrg	return (XawTextSourceAddAnchor(w, position));
20167a84e134Smrg
20177a84e134Smrg    return (anchor);
20187a84e134Smrg}
20197a84e134Smrg#endif
2020