TextSrc.c revision 994689c1
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,
1467a84e134Smrg    "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 */
2347a84e134Smrg  },
2357a84e134Smrg};
2367a84e134Smrg
2377a84e134SmrgWidgetClass textSrcObjectClass = (WidgetClass)&textSrcClassRec;
2387a84e134Smrg
2397a84e134Smrgstatic XrmQuark QRead, QAppend, QEdit;
2407a84e134Smrg#ifndef OLDXAW
2417a84e134Smrgstatic char *SrcNL = "\n";
2427a84e134Smrgstatic wchar_t SrcWNL[2];
2437a84e134Smrg#endif
2447a84e134Smrg
2457a84e134Smrg/*
2467a84e134Smrg * Implementation
2477a84e134Smrg */
2487a84e134Smrgstatic void
2497a84e134SmrgXawTextSrcClassInitialize(void)
2507a84e134Smrg{
2517a84e134Smrg    XawInitializeWidgetSet();
2527a84e134Smrg
2537a84e134Smrg#ifndef OLDXAW
2547a84e134Smrg    SrcWNL[0] = _Xaw_atowc(XawLF);
2557a84e134Smrg    SrcWNL[1] = 0;
2567a84e134Smrg#endif
2577a84e134Smrg    QRead   = XrmPermStringToQuark(XtEtextRead);
2587a84e134Smrg    QAppend = XrmPermStringToQuark(XtEtextAppend);
2597a84e134Smrg    QEdit   = XrmPermStringToQuark(XtEtextEdit);
2607a84e134Smrg    XtAddConverter(XtRString, XtREditMode,   CvtStringToEditMode,   NULL, 0);
2617a84e134Smrg    XtSetTypeConverter(XtREditMode, XtRString, CvtEditModeToString, NULL, 0,
2627a84e134Smrg		       XtCacheNone, NULL);
2637a84e134Smrg}
2647a84e134Smrg
2657a84e134Smrgstatic void
2667a84e134SmrgXawTextSrcClassPartInitialize(WidgetClass wc)
2677a84e134Smrg{
2687a84e134Smrg    TextSrcObjectClass t_src, superC;
2697a84e134Smrg
2707a84e134Smrg    t_src = (TextSrcObjectClass)wc;
2717a84e134Smrg    superC = (TextSrcObjectClass)t_src->object_class.superclass;
2727a84e134Smrg
2737a84e134Smrg    /*
2747a84e134Smrg     * We don't need to check for null super since we'll get to TextSrc
2757a84e134Smrg     * eventually
2767a84e134Smrg     */
2777a84e134Smrg    if (t_src->textSrc_class.Read == XtInheritRead)
2787a84e134Smrg	t_src->textSrc_class.Read = superC->textSrc_class.Read;
2797a84e134Smrg
2807a84e134Smrg    if (t_src->textSrc_class.Replace == XtInheritReplace)
2817a84e134Smrg	t_src->textSrc_class.Replace = superC->textSrc_class.Replace;
2827a84e134Smrg
2837a84e134Smrg    if (t_src->textSrc_class.Scan == XtInheritScan)
2847a84e134Smrg	t_src->textSrc_class.Scan = superC->textSrc_class.Scan;
2857a84e134Smrg
2867a84e134Smrg    if (t_src->textSrc_class.Search == XtInheritSearch)
2877a84e134Smrg	t_src->textSrc_class.Search = superC->textSrc_class.Search;
2887a84e134Smrg
2897a84e134Smrg    if (t_src->textSrc_class.SetSelection == XtInheritSetSelection)
2907a84e134Smrg	t_src->textSrc_class.SetSelection = superC->textSrc_class.SetSelection;
2917a84e134Smrg
2927a84e134Smrg    if (t_src->textSrc_class.ConvertSelection == XtInheritConvertSelection)
2937a84e134Smrg	t_src->textSrc_class.ConvertSelection =
2947a84e134Smrg	    superC->textSrc_class.ConvertSelection;
2957a84e134Smrg}
2967a84e134Smrg
2977a84e134Smrg/*ARGSUSED*/
2987a84e134Smrgstatic void
2997a84e134SmrgXawTextSrcInitialize(Widget request, Widget cnew,
3007a84e134Smrg		     ArgList args, Cardinal *num_args)
3017a84e134Smrg{
3027a84e134Smrg#ifndef OLDXAW
3037a84e134Smrg    TextSrcObject src = (TextSrcObject)cnew;
3047a84e134Smrg
3057a84e134Smrg    if (src->textSrc.enable_undo) {
3067a84e134Smrg	src->textSrc.undo = (XawTextUndo*)XtCalloc(1, sizeof(XawTextUndo));
3077a84e134Smrg	src->textSrc.undo->dir = XawsdLeft;
3087a84e134Smrg    }
3097a84e134Smrg    else
3107a84e134Smrg	src->textSrc.undo = NULL;
3117a84e134Smrg    src->textSrc.undo_state = False;
3127a84e134Smrg    if (XtIsSubclass(XtParent(cnew), textWidgetClass)) {
3137a84e134Smrg	src->textSrc.text = (WidgetList)XtMalloc(sizeof(Widget*));
3147a84e134Smrg	src->textSrc.text[0] = XtParent(cnew);
3157a84e134Smrg	src->textSrc.num_text = 1;
3167a84e134Smrg    }
3177a84e134Smrg    else {
3187a84e134Smrg	src->textSrc.text = NULL;
3197a84e134Smrg	src->textSrc.num_text = 0;
3207a84e134Smrg    }
3217a84e134Smrg
3227a84e134Smrg    src->textSrc.anchors = NULL;
3237a84e134Smrg    src->textSrc.num_anchors = 0;
3247a84e134Smrg    (void)XawTextSourceAddAnchor(cnew, 0);
3257a84e134Smrg#endif /* OLDXAW */
3267a84e134Smrg}
3277a84e134Smrg
3287a84e134Smrgstatic void
3297a84e134SmrgXawTextSrcDestroy(Widget w)
3307a84e134Smrg{
3317a84e134Smrg#ifndef OLDXAW
3327a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
3337a84e134Smrg
3347a84e134Smrg    if (src->textSrc.enable_undo) {
3357a84e134Smrg	FreeUndoBuffer(src->textSrc.undo);
3367a84e134Smrg	XtFree((char*)src->textSrc.undo);
3377a84e134Smrg    }
3387a84e134Smrg    XtFree((char*)src->textSrc.text);
3397a84e134Smrg
3407a84e134Smrg    if (src->textSrc.num_anchors) {
3417a84e134Smrg	XawTextEntity *entity, *enext;
3427a84e134Smrg	int i;
3437a84e134Smrg
3447a84e134Smrg	for (i = 0; i < src->textSrc.num_anchors; i++) {
3457a84e134Smrg	    entity = src->textSrc.anchors[i]->entities;
3467a84e134Smrg	    while (entity) {
3477a84e134Smrg		enext = entity->next;
3487a84e134Smrg		XtFree((XtPointer)entity);
3497a84e134Smrg		entity = enext;
3507a84e134Smrg	    }
3517a84e134Smrg	    XtFree((XtPointer)src->textSrc.anchors[i]);
3527a84e134Smrg	}
3537a84e134Smrg	XtFree((XtPointer)src->textSrc.anchors);
3547a84e134Smrg    }
3557a84e134Smrg#endif /* OLDXAW */
3567a84e134Smrg}
3577a84e134Smrg
3587a84e134Smrg/*ARGSUSED*/
3597a84e134Smrgstatic Boolean
3607a84e134SmrgXawTextSrcSetValues(Widget current, Widget request, Widget cnew,
3617a84e134Smrg		    ArgList args, Cardinal *num_args)
3627a84e134Smrg{
3637a84e134Smrg#ifndef OLDXAW
3647a84e134Smrg    TextSrcObject oldtw = (TextSrcObject)current;
3657a84e134Smrg    TextSrcObject newtw = (TextSrcObject)cnew;
3667a84e134Smrg
3677a84e134Smrg    if (oldtw->textSrc.enable_undo != newtw->textSrc.enable_undo) {
3687a84e134Smrg	if (newtw->textSrc.enable_undo) {
3697a84e134Smrg	    newtw->textSrc.undo = (XawTextUndo*)
3707a84e134Smrg		XtCalloc(1, sizeof(XawTextUndo));
3717a84e134Smrg	    newtw->textSrc.undo->dir = XawsdLeft;
3727a84e134Smrg	}
3737a84e134Smrg	else {
3747a84e134Smrg	    FreeUndoBuffer(newtw->textSrc.undo);
3757a84e134Smrg	    XtFree((char*)newtw->textSrc.undo);
3767a84e134Smrg	    newtw->textSrc.undo = NULL;
3777a84e134Smrg	}
3787a84e134Smrg    }
3797a84e134Smrg    if (oldtw->textSrc.changed != newtw->textSrc.changed) {
3807a84e134Smrg	if (newtw->textSrc.enable_undo) {
3817a84e134Smrg	    if (newtw->textSrc.undo->list) {
3827a84e134Smrg		newtw->textSrc.undo->l_no_change =
3837a84e134Smrg		    newtw->textSrc.undo->list->left;
3847a84e134Smrg		newtw->textSrc.undo->r_no_change =
3857a84e134Smrg		    newtw->textSrc.undo->list->right;
3867a84e134Smrg	    }
3877a84e134Smrg	    else
3887a84e134Smrg		newtw->textSrc.undo->l_no_change =
3897a84e134Smrg		    newtw->textSrc.undo->r_no_change = NULL;
3907a84e134Smrg	}
3917a84e134Smrg    }
3927a84e134Smrg#endif /* OLDXAW */
3937a84e134Smrg    return (False);
3947a84e134Smrg}
3957a84e134Smrg
3967a84e134Smrg/*
3977a84e134Smrg * Function:
3987a84e134Smrg *	Read
3997a84e134Smrg *
4007a84e134Smrg * Parameters:
4017a84e134Smrg *	w      - TextSrc Object
4027a84e134Smrg *	pos    - position of the text to retreive
4037a84e134Smrg *	text   - text block that will contain returned text
4047a84e134Smrg *	length - maximum number of characters to read
4057a84e134Smrg *
4067a84e134Smrg * Description:
4077a84e134Smrg *	This function reads the source.
4087a84e134Smrg *
4097a84e134Smrg * Returns:
4107a84e134Smrg *	The character position following the retrieved text.
4117a84e134Smrg */
4127a84e134Smrg/*ARGSUSED*/
4137a84e134Smrgstatic XawTextPosition
4147a84e134SmrgRead(Widget w, XawTextPosition pos, XawTextBlock *text, int length)
4157a84e134Smrg{
4167a84e134Smrg    return ((XawTextPosition)0);
4177a84e134Smrg}
4187a84e134Smrg
4197a84e134Smrg/*
4207a84e134Smrg * Function:
4217a84e134Smrg *	Replace
4227a84e134Smrg *
4237a84e134Smrg * Parameters:
4247a84e134Smrg *	src	 - Text Source Object
4257a84e134Smrg *	startPos - ends of text that will be removed
4267a84e134Smrg *	endPos	 - ""
4277a84e134Smrg *	text	 - new text to be inserted into buffer at startPos
4287a84e134Smrg *
4297a84e134Smrg * Description:
4307a84e134Smrg *	Replaces a block of text with new text.
4317a84e134Smrg */
4327a84e134Smrg/*ARGSUSED*/
4337a84e134Smrgstatic int
4347a84e134SmrgReplace(Widget w, XawTextPosition startPos, XawTextPosition endPos,
4357a84e134Smrg	XawTextBlock *text)
4367a84e134Smrg{
4377a84e134Smrg    return (XawEditError);
4387a84e134Smrg}
4397a84e134Smrg
4407a84e134Smrg/*
4417a84e134Smrg * Function:
4427a84e134Smrg *	Scan
4437a84e134Smrg *
4447a84e134Smrg * Parameters:
4457a84e134Smrg *	w	 - TextSrc Object
4467a84e134Smrg *	position - position to start scanning
4477a84e134Smrg *	type	 - type of thing to scan for
4487a84e134Smrg *	dir	 - direction to scan
4497a84e134Smrg *	count	 - which occurance if this thing to search for
4507a84e134Smrg *		 include - whether or not to include the character found in
4517a84e134Smrg *		   the position that is returned
4527a84e134Smrg *
4537a84e134Smrg * Description:
4547a84e134Smrg *	Scans the text source for the number and type of item specified.
4557a84e134Smrg */
4567a84e134Smrg/*ARGSUSED*/
4577a84e134Smrgstatic XawTextPosition
4587a84e134SmrgScan(Widget w, XawTextPosition position, XawTextScanType type,
4597a84e134Smrg     XawTextScanDirection dir, int count, Bool include)
4607a84e134Smrg{
4617a84e134Smrg    return ((XawTextPosition)0);
4627a84e134Smrg}
4637a84e134Smrg
4647a84e134Smrg/*
4657a84e134Smrg * Function:
4667a84e134Smrg *	Search
4677a84e134Smrg *
4687a84e134Smrg * Parameters:
4697a84e134Smrg *	w	 - TextSource Object
4707a84e134Smrg *	position - position to start searching
4717a84e134Smrg *	dir	 - direction to search
4727a84e134Smrg *	text	 - the text block to search for
4737a84e134Smrg *
4747a84e134Smrg * Description:
4757a84e134Smrg *	Searchs the text source for the text block passed
4767a84e134Smrg */
4777a84e134Smrg/*ARGSUSED*/
4787a84e134Smrgstatic XawTextPosition
4797a84e134SmrgSearch(Widget w, XawTextPosition position, XawTextScanDirection dir,
4807a84e134Smrg       XawTextBlock *text)
4817a84e134Smrg{
4827a84e134Smrg    return (XawTextSearchError);
4837a84e134Smrg}
4847a84e134Smrg
4857a84e134Smrg/*ARGSUSED*/
4867a84e134Smrgstatic Boolean
4877a84e134SmrgConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type,
4887a84e134Smrg		 XtPointer *value, unsigned long *length, int *format)
4897a84e134Smrg{
4907a84e134Smrg    return (False);
4917a84e134Smrg}
4927a84e134Smrg
4937a84e134Smrg/*ARGSUSED*/
4947a84e134Smrgstatic void
4957a84e134SmrgSetSelection(Widget w, XawTextPosition left, XawTextPosition right,
4967a84e134Smrg	     Atom selection)
4977a84e134Smrg{
4987a84e134Smrg}
4997a84e134Smrg
5007a84e134Smrg/*ARGSUSED*/
5017a84e134Smrgstatic void
5027a84e134SmrgCvtStringToEditMode(XrmValuePtr args, Cardinal *num_args,
5037a84e134Smrg		    XrmValuePtr fromVal, XrmValuePtr toVal)
5047a84e134Smrg{
5057a84e134Smrg    static XawTextEditType editType;
5067a84e134Smrg    XrmQuark	q;
5077a84e134Smrg    char name[7];
5087a84e134Smrg
5097a84e134Smrg    XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name));
5107a84e134Smrg    q = XrmStringToQuark(name);
5117a84e134Smrg
5127a84e134Smrg    if (q == QRead)
5137a84e134Smrg	editType = XawtextRead;
5147a84e134Smrg    else if (q == QAppend)
5157a84e134Smrg	editType = XawtextAppend;
5167a84e134Smrg    else if (q == QEdit)
5177a84e134Smrg	editType = XawtextEdit;
5187a84e134Smrg    else {
5197a84e134Smrg	toVal->size = 0;
5207a84e134Smrg	toVal->addr = NULL;
5217a84e134Smrg	XtStringConversionWarning((char *)fromVal->addr, XtREditMode);
5227a84e134Smrg    }
5237a84e134Smrg    toVal->size = sizeof(XawTextEditType);
5247a84e134Smrg    toVal->addr = (XPointer)&editType;
5257a84e134Smrg}
5267a84e134Smrg
5277a84e134Smrg/*ARGSUSED*/
5287a84e134Smrgstatic Boolean
5297a84e134SmrgCvtEditModeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args,
5307a84e134Smrg		    XrmValuePtr fromVal, XrmValuePtr toVal,
5317a84e134Smrg		    XtPointer *data)
5327a84e134Smrg{
5337a84e134Smrg    static String buffer;
5347a84e134Smrg    Cardinal size;
5357a84e134Smrg
5367a84e134Smrg    switch (*(XawTextEditType *)fromVal->addr) {
5377a84e134Smrg	case XawtextRead:
5387a84e134Smrg	    buffer = XtEtextRead;
5397a84e134Smrg	    break;
540994689c1Smrg	case XawtextAppend:
5417a84e134Smrg	    buffer = XtEtextAppend;
5427a84e134Smrg	    break;
5437a84e134Smrg	case XawtextEdit:
5447a84e134Smrg	    buffer = XtEtextEdit;
5457a84e134Smrg	    break;
5467a84e134Smrg	default:
5477a84e134Smrg	    XawTypeToStringWarning(dpy, XtREditMode);
5487a84e134Smrg	    toVal->addr = NULL;
5497a84e134Smrg	    toVal->size = 0;
5507a84e134Smrg	    return (False);
5517a84e134Smrg    }
5527a84e134Smrg
5537a84e134Smrg    size = strlen(buffer) + 1;
5547a84e134Smrg    if (toVal->addr != NULL) {
5557a84e134Smrg	if (toVal->size < size) {
5567a84e134Smrg	    toVal->size = size;
5577a84e134Smrg	    return (False);
5587a84e134Smrg	}
5597a84e134Smrg	strcpy((char *)toVal->addr, buffer);
5607a84e134Smrg    }
5617a84e134Smrg    else
5627a84e134Smrg	toVal->addr = (XPointer)buffer;
5637a84e134Smrg    toVal->size = sizeof(String);
5647a84e134Smrg
5657a84e134Smrg    return (True);
5667a84e134Smrg}
5677a84e134Smrg
5687a84e134Smrg#ifndef OLDXAW
5697a84e134SmrgBool
5707a84e134Smrg_XawTextSourceNewLineAtEOF(Widget w)
5717a84e134Smrg{
5727a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
5737a84e134Smrg    XawTextBlock text;
5747a84e134Smrg
5757a84e134Smrg    text.firstPos = 0;
5767a84e134Smrg    if ((text.format = src->textSrc.text_format) == XawFmt8Bit)
5777a84e134Smrg	text.ptr = SrcNL;
5787a84e134Smrg    else
5797a84e134Smrg	text.ptr = (char*)SrcWNL;
5807a84e134Smrg    text.length = 1;
5817a84e134Smrg
5827a84e134Smrg    return (XawTextSourceSearch(w, XawTextSourceScan(w, 0, XawstAll,
5837a84e134Smrg						     XawsdRight, 1, True) - 1,
5847a84e134Smrg				XawsdRight, &text) != XawTextSearchError);
5857a84e134Smrg}
5867a84e134Smrg
5877a84e134Smrgvoid
5887a84e134Smrg_XawSourceAddText(Widget source, Widget text)
5897a84e134Smrg{
5907a84e134Smrg    TextSrcObject src = (TextSrcObject)source;
5917a84e134Smrg    Bool found = False;
5927a84e134Smrg    Cardinal i;
5937a84e134Smrg
5947a84e134Smrg    for (i = 0; i < src->textSrc.num_text; i++)
5957a84e134Smrg	if (src->textSrc.text[i] == text) {
5967a84e134Smrg	    found = True;
5977a84e134Smrg	    break;
5987a84e134Smrg	}
5997a84e134Smrg
6007a84e134Smrg    if (!found) {
6017a84e134Smrg	src->textSrc.text = (WidgetList)
6027a84e134Smrg	    XtRealloc((char*)src->textSrc.text,
6037a84e134Smrg		      sizeof(Widget) * (src->textSrc.num_text + 1));
6047a84e134Smrg	src->textSrc.text[src->textSrc.num_text++] = text;
6057a84e134Smrg    }
6067a84e134Smrg}
6077a84e134Smrg
6087a84e134Smrgvoid
6097a84e134Smrg_XawSourceRemoveText(Widget source, Widget text, Bool destroy)
6107a84e134Smrg{
6117a84e134Smrg    TextSrcObject src = (TextSrcObject)source;
6127a84e134Smrg    Bool found = False;
6137a84e134Smrg    Cardinal i;
6147a84e134Smrg
6157a84e134Smrg    if (src == NULL)
6167a84e134Smrg	return;
6177a84e134Smrg
6187a84e134Smrg    for (i = 0; i < src->textSrc.num_text; i++)
6197a84e134Smrg	if (src->textSrc.text[i] == text) {
6207a84e134Smrg	    found = True;
6217a84e134Smrg	    break;
6227a84e134Smrg	}
6237a84e134Smrg
6247a84e134Smrg    if (found) {
6257a84e134Smrg	if (--src->textSrc.num_text == 0) {
6267a84e134Smrg	    if (destroy) {
6277a84e134Smrg		XtDestroyWidget(source);
6287a84e134Smrg		return;
6297a84e134Smrg	    }
6307a84e134Smrg	    else {
6317a84e134Smrg		XtFree((char*)src->textSrc.text);
6327a84e134Smrg		src->textSrc.text = NULL;	/* for realloc "magic" */
6337a84e134Smrg	    }
6347a84e134Smrg	}
6357a84e134Smrg	else if (i < src->textSrc.num_text)
6367a84e134Smrg	    memmove(&src->textSrc.text[i], &src->textSrc.text[i + 1],
6377a84e134Smrg		    sizeof(Widget) * (src->textSrc.num_text - i));
6387a84e134Smrg    }
6397a84e134Smrg}
6407a84e134Smrg#endif /* OLDXAW */
6417a84e134Smrg
6427a84e134Smrg/*
6437a84e134Smrg * Function:
6447a84e134Smrg *	XawTextSourceRead
6457a84e134Smrg *
6467a84e134Smrg * Parameters:
6477a84e134Smrg *	w      - TextSrc Object
6487a84e134Smrg *	pos    - position of the text to retrieve
6497a84e134Smrg *	text   - text block that will contain returned text (return)
6507a84e134Smrg *	length - maximum number of characters to read
6517a84e134Smrg *
6527a84e134Smrg * Description:
6537a84e134Smrg *	This function reads the source.
6547a84e134Smrg *
6557a84e134Smrg * Returns:
6567a84e134Smrg *	The number of characters read into the buffer
6577a84e134Smrg */
6587a84e134SmrgXawTextPosition
6597a84e134SmrgXawTextSourceRead(Widget w, XawTextPosition pos, XawTextBlock *text,
6607a84e134Smrg		  int length)
6617a84e134Smrg{
6627a84e134Smrg  TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
6637a84e134Smrg
6647a84e134Smrg  return ((*cclass->textSrc_class.Read)(w, pos, text, length));
6657a84e134Smrg}
6667a84e134Smrg
6677a84e134Smrg#ifndef OLDXAW
6687a84e134Smrgstatic void
6697a84e134SmrgTellSourceChanged(TextSrcObject src, XawTextPosition left,
6707a84e134Smrg		  XawTextPosition right, XawTextBlock *block, int lines)
6717a84e134Smrg{
6727a84e134Smrg    Cardinal i;
6737a84e134Smrg
6747a84e134Smrg    for (i = 0; i < src->textSrc.num_text; i++)
6757a84e134Smrg	_XawTextSourceChanged(src->textSrc.text[i], left, right, block, lines);
6767a84e134Smrg}
6777a84e134Smrg
6787a84e134Smrg/*
6797a84e134Smrg * This function is required because there is no way to diferentiate
6807a84e134Smrg * if the first erase was generated by a backward-kill-char and the
6817a84e134Smrg * second by a forward-kill-char (or vice-versa) from XawTextSourceReplace.
6827a84e134Smrg * It is only possible to diferentiate after the second character is
6837a84e134Smrg * killed, but then, it is too late.
6847a84e134Smrg */
6857a84e134Smrgvoid
6867a84e134Smrg_XawSourceSetUndoErase(TextSrcObject src, int value)
6877a84e134Smrg{
6887a84e134Smrg    if (src && src->textSrc.enable_undo)
6897a84e134Smrg	src->textSrc.undo->erase = value;
6907a84e134Smrg}
6917a84e134Smrg
6927a84e134Smrg/*
6937a84e134Smrg * To diferentiate insert-char's separeted by cursor movements.
6947a84e134Smrg */
6957a84e134Smrgvoid
6967a84e134Smrg_XawSourceSetUndoMerge(TextSrcObject src, Bool state)
6977a84e134Smrg{
6987a84e134Smrg    if (src && src->textSrc.enable_undo)
6997a84e134Smrg	src->textSrc.undo->merge += state ? 1 : -1;
7007a84e134Smrg}
7017a84e134Smrg#endif /* OLDXAW */
7027a84e134Smrg
7037a84e134Smrg/*
7047a84e134Smrg * Public Functions
7057a84e134Smrg */
7067a84e134Smrg/*
7077a84e134Smrg * Function:
7087a84e134Smrg *	XawTextSourceReplace
7097a84e134Smrg *
7107a84e134Smrg * Parameters:
7117a84e134Smrg *	src	 - Text Source Object
7127a84e134Smrg *	startPos - ends of text that will be removed
7137a84e134Smrg *	endPos	 - ""
7147a84e134Smrg *	text	 - new text to be inserted into buffer at startPos
7157a84e134Smrg *
7167a84e134Smrg * Description:
7177a84e134Smrg *	Replaces a block of text with new text.
7187a84e134Smrg *
7197a84e134Smrg * Returns:
7207a84e134Smrg *	XawEditError or XawEditDone.
7217a84e134Smrg */
7227a84e134Smrg/*ARGSUSED*/
7237a84e134Smrgint
7247a84e134SmrgXawTextSourceReplace(Widget w, XawTextPosition left,
7257a84e134Smrg		      XawTextPosition right, XawTextBlock *block)
7267a84e134Smrg{
7277a84e134Smrg    TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
7287a84e134Smrg#ifndef OLDXAW
7297a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
7307a84e134Smrg    XawTextUndoBuffer *l_state, *r_state;
7317a84e134Smrg    XawTextUndoList *undo;
7327a84e134Smrg    Bool enable_undo;
7337a84e134Smrg    XawTextPosition start, end;
7347a84e134Smrg    int i, error, lines = 0;
7357a84e134Smrg
7367a84e134Smrg    if (src->textSrc.edit_mode == XawtextRead)
7377a84e134Smrg	return (XawEditError);
7387a84e134Smrg
7397a84e134Smrg    enable_undo = src->textSrc.enable_undo && src->textSrc.undo_state == False;
7407a84e134Smrg    if (enable_undo) {
7417a84e134Smrg	unsigned size, total;
7427a84e134Smrg
7437a84e134Smrg	if (src->textSrc.undo->l_save) {
7447a84e134Smrg	    l_state = src->textSrc.undo->l_save;
7457a84e134Smrg	    src->textSrc.undo->l_save = NULL;
7467a84e134Smrg	}
7477a84e134Smrg	else
7487a84e134Smrg	    l_state = XtNew(XawTextUndoBuffer);
7497a84e134Smrg	l_state->refcount = 1;
7507a84e134Smrg	l_state->position = left;
7517a84e134Smrg	if (left < right) {
7527a84e134Smrg	    Widget ctx = NULL;
7537a84e134Smrg
7547a84e134Smrg	    for (i = 0; i < src->textSrc.num_text; i++)
7557a84e134Smrg		if (XtIsSubclass(src->textSrc.text[i], textWidgetClass)) {
7567a84e134Smrg		    ctx = src->textSrc.text[i];
7577a84e134Smrg		    break;
7587a84e134Smrg		}
7597a84e134Smrg	    l_state->buffer = _XawTextGetText((TextWidget)ctx, left, right);
7607a84e134Smrg	    l_state->length = right - left;
7617a84e134Smrg	}
7627a84e134Smrg	else {
7637a84e134Smrg	    l_state->length = 0;
7647a84e134Smrg	    l_state->buffer = NULL;
7657a84e134Smrg	}
7667a84e134Smrg	l_state->format = src->textSrc.text_format;
7677a84e134Smrg	if (l_state->length == 1) {
7687a84e134Smrg	    if (l_state->format == XawFmtWide &&
7697a84e134Smrg		*(wchar_t*)l_state->buffer == *SrcWNL) {
7707a84e134Smrg		XtFree(l_state->buffer);
7717a84e134Smrg		l_state->buffer = (char*)SrcWNL;
7727a84e134Smrg	    }
7737a84e134Smrg	    else if (*l_state->buffer == '\n') {
7747a84e134Smrg		XtFree(l_state->buffer);
7757a84e134Smrg		l_state->buffer = SrcNL;
7767a84e134Smrg	    }
7777a84e134Smrg	}
7787a84e134Smrg
7797a84e134Smrg	if (src->textSrc.undo->r_save) {
7807a84e134Smrg	    r_state = src->textSrc.undo->r_save;
7817a84e134Smrg	    src->textSrc.undo->r_save = NULL;
7827a84e134Smrg	}
7837a84e134Smrg	else
7847a84e134Smrg	    r_state = XtNew(XawTextUndoBuffer);
7857a84e134Smrg	r_state->refcount = 1;
7867a84e134Smrg	r_state->position = left;
7877a84e134Smrg	r_state->format = block->format;
7887a84e134Smrg	size = block->format == XawFmtWide ? sizeof(wchar_t) : sizeof(char);
7897a84e134Smrg	total = size * block->length;
7907a84e134Smrg	r_state->length = block->length;
7917a84e134Smrg	r_state->buffer = NULL;
7927a84e134Smrg	if (total == size) {
7937a84e134Smrg	    if (r_state->format == XawFmtWide &&
7947a84e134Smrg		*(wchar_t*)block->ptr == *SrcWNL)
7957a84e134Smrg		r_state->buffer = (char*)SrcWNL;
7967a84e134Smrg	    else if (*block->ptr == '\n')
7977a84e134Smrg		r_state->buffer = SrcNL;
7987a84e134Smrg	}
7997a84e134Smrg	if (total && !r_state->buffer) {
8007a84e134Smrg	    r_state->buffer = XtMalloc(total);
8017a84e134Smrg	    memcpy(r_state->buffer, block->ptr, total);
8027a84e134Smrg	}
8037a84e134Smrg
8047a84e134Smrg	if (src->textSrc.undo->u_save) {
8057a84e134Smrg	    undo = src->textSrc.undo->u_save;
8067a84e134Smrg	    src->textSrc.undo->u_save = NULL;
8077a84e134Smrg	}
8087a84e134Smrg	else
8097a84e134Smrg	    undo = XtNew(XawTextUndoList);
8107a84e134Smrg	undo->left = l_state;
8117a84e134Smrg	undo->right = r_state;
8127a84e134Smrg	undo->undo = src->textSrc.undo->list;
8137a84e134Smrg	undo->redo = NULL;
8147a84e134Smrg    }
8157a84e134Smrg    else {
8167a84e134Smrg	undo = NULL;
8177a84e134Smrg	l_state = r_state = NULL;
8187a84e134Smrg    }
8197a84e134Smrg
8207a84e134Smrg#define	LARGE_VALUE	262144	/* 256 K */
8217a84e134Smrg    /* optimization, to avoid long delays recalculating the line number
8227a84e134Smrg     * when editing huge files
8237a84e134Smrg     */
8247a84e134Smrg    if (left > LARGE_VALUE) {
8257a84e134Smrg	start = XawTextSourceScan(w, left, XawstEOL, XawsdLeft, 2, False);
8267a84e134Smrg	for (i = 0; i < src->textSrc.num_text; i++) {
8277a84e134Smrg	    TextWidget tw = (TextWidget)src->textSrc.text[i];
8287a84e134Smrg
8297a84e134Smrg	    if (left <= tw->text.lt.top &&
8307a84e134Smrg		left + block->length - (right - left) > tw->text.lt.top)
8317a84e134Smrg		_XawTextBuildLineTable(tw, start, False);
8327a84e134Smrg	}
8337a84e134Smrg    }
8347a84e134Smrg#undef LARGE_VALUE
8357a84e134Smrg
8367a84e134Smrg    start = left;
8377a84e134Smrg    end = right;
8387a84e134Smrg    while (start < end) {
8397a84e134Smrg	start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True);
8407a84e134Smrg	if (start <= end) {
8417a84e134Smrg	    --lines;
8427a84e134Smrg	    if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) {
8437a84e134Smrg		lines += !_XawTextSourceNewLineAtEOF(w);
8447a84e134Smrg		break;
8457a84e134Smrg	    }
8467a84e134Smrg	}
8477a84e134Smrg    }
8487a84e134Smrg#else
8497a84e134Smrg    int error;
8507a84e134Smrg#endif /* OLDXAW */
8517a84e134Smrg
8527a84e134Smrg    error = (*cclass->textSrc_class.Replace)(w, left, right, block);
8537a84e134Smrg
8547a84e134Smrg#ifndef OLDXAW
8557a84e134Smrg    if (error != XawEditDone) {
8567a84e134Smrg	if (enable_undo) {
8577a84e134Smrg	    if (l_state->buffer) {
8587a84e134Smrg		if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL)
8597a84e134Smrg		    XtFree(l_state->buffer);
8607a84e134Smrg		l_state->buffer = NULL;
8617a84e134Smrg	    }
8627a84e134Smrg	     src->textSrc.undo->l_save = l_state;
8637a84e134Smrg	     if (r_state->buffer) {
8647a84e134Smrg		if (r_state->buffer != SrcNL && r_state->buffer != (char*)SrcWNL)
8657a84e134Smrg		    XtFree(r_state->buffer);
8667a84e134Smrg		r_state->buffer = NULL;
8677a84e134Smrg	    }
8687a84e134Smrg	    src->textSrc.undo->r_save = r_state;
8697a84e134Smrg
8707a84e134Smrg	    src->textSrc.undo->u_save = undo;
8717a84e134Smrg	}
8727a84e134Smrg    }
8737a84e134Smrg    else if (enable_undo) {
8747a84e134Smrg	XawTextUndoList *list = src->textSrc.undo->list;
8757a84e134Smrg	XawTextUndoBuffer *unl, *lnl;
8767a84e134Smrg	int erase = undo->right->length == 0 && undo->left->length == 1 && list
8777a84e134Smrg		    && list->right->length == 0;
8787a84e134Smrg
8797a84e134Smrg	if (erase) {
8807a84e134Smrg	    erase = list->left->position - 1 == undo->left->position ? -1 :
8817a84e134Smrg		    list->left->position == undo->left->position ? 1 : 0;
8827a84e134Smrg	    if (src->textSrc.undo->erase && erase != src->textSrc.undo->erase)
8837a84e134Smrg		erase = 0;
8847a84e134Smrg	    else
8857a84e134Smrg		src->textSrc.undo->erase = erase;
8867a84e134Smrg	}
8877a84e134Smrg
8887a84e134Smrg	if (erase) {
8897a84e134Smrg	    unl = l_state;
8907a84e134Smrg	    lnl = list->left;
8917a84e134Smrg	}
8927a84e134Smrg	else {
8937a84e134Smrg	    unl = r_state;
8947a84e134Smrg	    lnl = list ? list->right : NULL;
8957a84e134Smrg	}
8967a84e134Smrg
8977a84e134Smrg	/* Try to merge the undo buffers */
8987a84e134Smrg	if (src->textSrc.undo->merge > 0 && ((erase ||
8997a84e134Smrg	     (list && ((list->left->length == 0 && undo->left->length == 0) ||
9007a84e134Smrg		       (list->left->length == list->right->length &&
9017a84e134Smrg			undo->left->length == 1)) &&
9027a84e134Smrg	      undo->right->length == 1 &&
9037a84e134Smrg	      list->right->position + list->right->length
9047a84e134Smrg	      == undo->right->position))
9057a84e134Smrg	    && src->textSrc.undo->pointer == list
9067a84e134Smrg	    && unl->format == list->right->format
9077a84e134Smrg	    && ((unl->format == XawFmt8Bit && unl->buffer[0] != XawLF) ||
9087a84e134Smrg		(unl->format == XawFmtWide &&
9097a84e134Smrg		 *(wchar_t*)(unl->buffer) != _Xaw_atowc(XawLF)))
9107a84e134Smrg	    && ((lnl->format == XawFmt8Bit && lnl->buffer[0] != XawLF) ||
9117a84e134Smrg		(lnl->format == XawFmtWide &&
9127a84e134Smrg		 *(wchar_t*)(lnl->buffer) != _Xaw_atowc(XawLF))))) {
9137a84e134Smrg	    unsigned size = lnl->format == XawFmtWide ?
9147a84e134Smrg		sizeof(wchar_t) : sizeof(char);
9157a84e134Smrg
9167a84e134Smrg	    if (!erase) {
9177a84e134Smrg		list->right->buffer = XtRealloc(list->right->buffer,
9187a84e134Smrg						(list->right->length + 1) * size);
9197a84e134Smrg		memcpy(list->right->buffer + list->right->length * size,
9207a84e134Smrg		       undo->right->buffer, size);
9217a84e134Smrg		++list->right->length;
9227a84e134Smrg		XtFree(r_state->buffer);
9237a84e134Smrg	    }
9247a84e134Smrg	    else if (erase < 0) {
9257a84e134Smrg		--list->left->position;
9267a84e134Smrg		--list->right->position;
9277a84e134Smrg	    }
9287a84e134Smrg
9297a84e134Smrg	    src->textSrc.undo->l_save = l_state;
9307a84e134Smrg	    src->textSrc.undo->r_save = r_state;
9317a84e134Smrg	    src->textSrc.undo->u_save = undo;
9327a84e134Smrg
9337a84e134Smrg	    if (list->left->length) {
9347a84e134Smrg		list->left->buffer = XtRealloc(list->left->buffer,
9357a84e134Smrg					       (list->left->length + 1) * size);
9367a84e134Smrg		if (erase >= 0)
9377a84e134Smrg		    memcpy(list->left->buffer + list->left->length * size,
9387a84e134Smrg			   undo->left->buffer, size);
9397a84e134Smrg		else {
9407a84e134Smrg		    /* use memmove, since strings overlap */
9417a84e134Smrg		    memmove(list->left->buffer + size, list->left->buffer,
9427a84e134Smrg			    list->left->length * size);
9437a84e134Smrg		    memcpy(list->left->buffer, undo->left->buffer, size);
9447a84e134Smrg		}
9457a84e134Smrg		++list->left->length;
9467a84e134Smrg		if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL)
9477a84e134Smrg		    XtFree(l_state->buffer);
9487a84e134Smrg	    }
9497a84e134Smrg
9507a84e134Smrg	    if (src->textSrc.undo->num_list >= UNDO_DEPTH)
9517a84e134Smrg		UndoGC(src->textSrc.undo);
9527a84e134Smrg	}
9537a84e134Smrg	else {
9547a84e134Smrg	    src->textSrc.undo->undo = (XawTextUndoBuffer**)
9557a84e134Smrg		XtRealloc((char*)src->textSrc.undo->undo,
9567a84e134Smrg			  (2 + src->textSrc.undo->num_undo)
9577a84e134Smrg			  * sizeof(XawTextUndoBuffer));
9587a84e134Smrg	    src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = l_state;
9597a84e134Smrg	    src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = r_state;
9607a84e134Smrg
9617a84e134Smrg	    if (src->textSrc.undo->list)
9627a84e134Smrg		src->textSrc.undo->list->redo = undo;
9637a84e134Smrg	    else
9647a84e134Smrg		src->textSrc.undo->head = undo;
9657a84e134Smrg
9667a84e134Smrg	    src->textSrc.undo->merge = l_state->length <= 1 &&
9677a84e134Smrg				       r_state->length <= 1;
9687a84e134Smrg
9697a84e134Smrg	    src->textSrc.undo->list = src->textSrc.undo->pointer =
9707a84e134Smrg		src->textSrc.undo->end_mark = undo;
9717a84e134Smrg
9727a84e134Smrg	    if (++src->textSrc.undo->num_list >= UNDO_DEPTH)
9737a84e134Smrg		UndoGC(src->textSrc.undo);
9747a84e134Smrg	}
9757a84e134Smrg	src->textSrc.undo->dir = XawsdLeft;
9767a84e134Smrg	if (!src->textSrc.changed) {
9777a84e134Smrg	    src->textSrc.undo->l_no_change = src->textSrc.undo->list->right;
9787a84e134Smrg	    src->textSrc.undo->r_no_change = src->textSrc.undo->list->left;
9797a84e134Smrg	    src->textSrc.changed = True;
9807a84e134Smrg	}
9817a84e134Smrg    }
9827a84e134Smrg    else if (!src->textSrc.enable_undo)
9837a84e134Smrg	src->textSrc.changed = True;
9847a84e134Smrg
9857a84e134Smrg    if (error == XawEditDone) {
9867a84e134Smrg	XawTextPropertyInfo info;
9877a84e134Smrg	XawTextAnchor *anchor;
9887a84e134Smrg
9897a84e134Smrg	/* find anchor and index */
9907a84e134Smrg	/* XXX index (i) could be returned by XawTextSourceFindAnchor
9917a84e134Smrg	 * or similar function, to speed up */
9927a84e134Smrg	if ((anchor = XawTextSourceFindAnchor(w, left))) {
9937a84e134Smrg	    XawTextEntity *eprev, *entity, *enext;
9947a84e134Smrg	    XawTextPosition offset = 0, diff = block->length - (right - left);
9957a84e134Smrg
9967a84e134Smrg	    for (i = 0; i < src->textSrc.num_anchors; i++)
9977a84e134Smrg		if (src->textSrc.anchors[i] == anchor)
9987a84e134Smrg		    break;
9997a84e134Smrg	    if (anchor->cache && anchor->position + anchor->cache->offset +
10007a84e134Smrg		anchor->cache->length <= left)
10017a84e134Smrg		eprev = entity = anchor->cache;
10027a84e134Smrg	    else
10037a84e134Smrg		eprev = entity = anchor->entities;
10047a84e134Smrg	    while (entity) {
10057a84e134Smrg		offset = anchor->position + entity->offset;
10067a84e134Smrg
10077a84e134Smrg		if (offset > left)
10087a84e134Smrg		    break;
10097a84e134Smrg		if (offset + entity->length > left)
10107a84e134Smrg		    break;
10117a84e134Smrg
10127a84e134Smrg		eprev = entity;
10137a84e134Smrg		entity = entity->next;
10147a84e134Smrg	    }
10157a84e134Smrg
10167a84e134Smrg	    /* try to do the right thing here (and most likely correct), but
10177a84e134Smrg	     * other code needs to check what was done */
10187a84e134Smrg
10197a84e134Smrg	    /* adjust entity length */
10207a84e134Smrg	    if (entity && offset <= left) {
10217a84e134Smrg		if (offset + entity->length < right)
10227a84e134Smrg		    entity->length = left - offset + block->length;
10237a84e134Smrg		else
10247a84e134Smrg		    entity->length += diff;
10257a84e134Smrg
10267a84e134Smrg		if (entity->length == 0) {
10277a84e134Smrg		    enext = entity->next;
10287a84e134Smrg		    eprev->next = enext;
10297a84e134Smrg		    anchor->cache = NULL;
10307a84e134Smrg		    XtFree((XtPointer)entity);
10317a84e134Smrg		    if (entity == anchor->entities) {
10327a84e134Smrg			if ((anchor->entities = enext) == NULL) {
10337a84e134Smrg			    eprev = NULL;
10347a84e134Smrg			    anchor = XawTextSourceRemoveAnchor(w, anchor);
10357a84e134Smrg			    entity = anchor ? anchor->entities : NULL;
10367a84e134Smrg			}
10377a84e134Smrg			else
10387a84e134Smrg			    eprev = entity = enext;
10397a84e134Smrg		    }
10407a84e134Smrg		    else
10417a84e134Smrg			entity = enext;
10427a84e134Smrg		}
10437a84e134Smrg		else {
10447a84e134Smrg		    eprev = entity;
10457a84e134Smrg		    entity = entity->next;
10467a84e134Smrg		}
10477a84e134Smrg	    }
10487a84e134Smrg
10497a84e134Smrg	    while (anchor) {
10507a84e134Smrg		while (entity) {
10517a84e134Smrg		    offset = anchor->position + entity->offset + entity->length;
10527a84e134Smrg
10537a84e134Smrg		    if (offset > right) {
10547a84e134Smrg			entity->length = XawMin(entity->length, offset - right);
10557a84e134Smrg			goto exit_anchor_loop;
10567a84e134Smrg		    }
10577a84e134Smrg
10587a84e134Smrg		    enext = entity->next;
10597a84e134Smrg		    if (eprev)
10607a84e134Smrg			eprev->next = enext;
10617a84e134Smrg		    XtFree((XtPointer)entity);
10627a84e134Smrg		    anchor->cache = NULL;
10637a84e134Smrg		    if (entity == anchor->entities) {
10647a84e134Smrg			eprev = NULL;
10657a84e134Smrg			if ((anchor->entities = enext) == NULL) {
10667a84e134Smrg			    if (i == 0)
10677a84e134Smrg				++i;
10687a84e134Smrg			    else if (i < --src->textSrc.num_anchors) {
10697a84e134Smrg				memmove(&src->textSrc.anchors[i],
10707a84e134Smrg					&src->textSrc.anchors[i + 1],
10717a84e134Smrg					(src->textSrc.num_anchors - i) *
10727a84e134Smrg					sizeof(XawTextAnchor*));
10737a84e134Smrg				XtFree((XtPointer)anchor);
10747a84e134Smrg			    }
10757a84e134Smrg			    if (i >= src->textSrc.num_anchors) {
10767a84e134Smrg				anchor = NULL;
10777a84e134Smrg				entity = NULL;
10787a84e134Smrg				break;
10797a84e134Smrg			    }
10807a84e134Smrg			    anchor = src->textSrc.anchors[i];
10817a84e134Smrg			    entity = anchor->entities;
10827a84e134Smrg			    continue;
10837a84e134Smrg			}
10847a84e134Smrg		    }
10857a84e134Smrg		    entity = enext;
10867a84e134Smrg		}
10877a84e134Smrg		if (i + 1 < src->textSrc.num_anchors) {
10887a84e134Smrg		    anchor = src->textSrc.anchors[++i];
10897a84e134Smrg		    entity = anchor->entities;
10907a84e134Smrg		    eprev = NULL;
10917a84e134Smrg		}
1092ab902922Smrg		else {
1093ab902922Smrg		    anchor = NULL;
10947a84e134Smrg		    break;
1095ab902922Smrg		}
10967a84e134Smrg		eprev = NULL;
10977a84e134Smrg	    }
10987a84e134Smrg
10997a84e134Smrgexit_anchor_loop:
11007a84e134Smrg	    if (anchor) {
11017a84e134Smrg		XawTextAnchor *aprev;
11027a84e134Smrg
11037a84e134Smrg		if (anchor->position >= XawMax(right, left + block->length))
11047a84e134Smrg		    anchor->position += diff;
11057a84e134Smrg		else if (anchor->position > left &&
11067a84e134Smrg			 (aprev = XawTextSourcePrevAnchor(w, anchor))) {
11077a84e134Smrg		    XawTextPosition tmp = anchor->position - aprev->position;
11087a84e134Smrg
11097a84e134Smrg		    if (diff) {
11107a84e134Smrg			while (entity) {
11117a84e134Smrg			    entity->offset += diff;
11127a84e134Smrg			    entity = entity->next;
11137a84e134Smrg			}
11147a84e134Smrg		    }
11157a84e134Smrg		    entity = anchor->entities;
11167a84e134Smrg		    while (entity) {
11177a84e134Smrg			entity->offset += tmp;
11187a84e134Smrg			entity = entity->next;
11197a84e134Smrg		    }
11207a84e134Smrg		    if ((entity = aprev->entities) == NULL)
11217a84e134Smrg			aprev->entities = anchor->entities;
11227a84e134Smrg		    else {
11237a84e134Smrg			while (entity->next)
11247a84e134Smrg			    entity = entity->next;
11257a84e134Smrg			entity->next = anchor->entities;
11267a84e134Smrg		    }
11277a84e134Smrg		    anchor->entities = NULL;
11287a84e134Smrg		    (void)XawTextSourceRemoveAnchor(w, anchor);
11297a84e134Smrg		    --i;
11307a84e134Smrg		}
11317a84e134Smrg		else if (diff) {
11327a84e134Smrg		    while (entity) {
11337a84e134Smrg			entity->offset += diff;
11347a84e134Smrg			entity = entity->next;
11357a84e134Smrg		    }
11367a84e134Smrg		}
11377a84e134Smrg	    }
11387a84e134Smrg
11397a84e134Smrg	    if (diff) {
1140ab902922Smrg		/*   The first anchor is never removed, and should
1141ab902922Smrg		 * have position 0.
1142ab902922Smrg		 *   i should be -1 if attempted to removed the first
1143ab902922Smrg		 * anchor, what can be caused when removing a chunk
1144ab902922Smrg		 * of text of the first entity.
1145ab902922Smrg		 * */
1146ab902922Smrg		if (++i == 0) {
1147ab902922Smrg		    anchor = src->textSrc.anchors[0];
1148ab902922Smrg		    eprev = entity = anchor->entities;
1149ab902922Smrg		    while (entity) {
1150ab902922Smrg			enext = entity->next;
1151ab902922Smrg			if (entity->offset + entity->length <= -diff)
1152ab902922Smrg			    XtFree((XtPointer)entity);
1153ab902922Smrg			else
1154ab902922Smrg			    break;
1155ab902922Smrg			entity = enext;
1156ab902922Smrg		    }
1157ab902922Smrg		    if (eprev != entity) {
1158ab902922Smrg			anchor->cache = NULL;
1159ab902922Smrg			if ((anchor->entities = entity) != NULL) {
1160ab902922Smrg			    if ((entity->offset += diff) < 0) {
1161ab902922Smrg				entity->length += entity->offset;
1162ab902922Smrg				entity->offset = 0;
1163ab902922Smrg			    }
1164ab902922Smrg			}
1165ab902922Smrg		    }
1166ab902922Smrg		    ++i;
1167ab902922Smrg		}
1168ab902922Smrg		for (; i < src->textSrc.num_anchors; i++)
11697a84e134Smrg		    src->textSrc.anchors[i]->position += diff;
11707a84e134Smrg	    }
11717a84e134Smrg	}
11727a84e134Smrg
11737a84e134Smrg	start = left;
11747a84e134Smrg	end = start + block->length;
11757a84e134Smrg	while (start < end) {
11767a84e134Smrg	    start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True);
11777a84e134Smrg	    if (start <= end) {
11787a84e134Smrg		++lines;
11797a84e134Smrg		if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) {
11807a84e134Smrg		    lines -= !_XawTextSourceNewLineAtEOF(w);
11817a84e134Smrg		    break;
11827a84e134Smrg		}
11837a84e134Smrg	    }
11847a84e134Smrg	}
11857a84e134Smrg
11867a84e134Smrg	info.left = left;
11877a84e134Smrg	info.right = right;
11887a84e134Smrg	info.block = block;
11897a84e134Smrg	XtCallCallbacks(w, XtNpropertyCallback, &info);
11907a84e134Smrg
11917a84e134Smrg	TellSourceChanged(src, left, right, block, lines);
11927a84e134Smrg	/* Call callbacks, we have changed the buffer */
11937a84e134Smrg	XtCallCallbacks(w, XtNcallback,
11947a84e134Smrg			(XtPointer)((long)src->textSrc.changed));
11957a84e134Smrg    }
11967a84e134Smrg
11977a84e134Smrg#endif /* OLDXAW */
11987a84e134Smrg    return (error);
11997a84e134Smrg}
12007a84e134Smrg
12017a84e134Smrg#ifndef OLDXAW
12027a84e134SmrgBool
12037a84e134Smrg_XawTextSrcUndo(TextSrcObject src, XawTextPosition *insert_pos)
12047a84e134Smrg{
12057a84e134Smrg    static wchar_t wnull = 0;
12067a84e134Smrg    XawTextBlock block;
12077a84e134Smrg    XawTextUndoList *list, *nlist;
12087a84e134Smrg    XawTextUndoBuffer *l_state, *r_state;
12097a84e134Smrg    Boolean changed = src->textSrc.changed;
12107a84e134Smrg
12117a84e134Smrg    if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo)
12127a84e134Smrg	return (False);
12137a84e134Smrg
12147a84e134Smrg    list = src->textSrc.undo->pointer;
12157a84e134Smrg
12167a84e134Smrg    if (src->textSrc.undo->dir == XawsdLeft) {
12177a84e134Smrg	l_state = list->right;
12187a84e134Smrg	r_state = list->left;
12197a84e134Smrg    }
12207a84e134Smrg    else {
12217a84e134Smrg	l_state = list->left;
12227a84e134Smrg	r_state = list->right;
12237a84e134Smrg    }
12247a84e134Smrg
12257a84e134Smrg    if (src->textSrc.undo->l_no_change == l_state
12267a84e134Smrg	&& src->textSrc.undo->r_no_change == r_state)
12277a84e134Smrg	src->textSrc.changed = False;
12287a84e134Smrg    else
12297a84e134Smrg	src->textSrc.changed = True;
12307a84e134Smrg
12317a84e134Smrg    block.firstPos = 0;
12327a84e134Smrg    block.length = r_state->length;
12337a84e134Smrg    block.ptr = r_state->buffer ? r_state->buffer : (char*)&wnull;
12347a84e134Smrg    block.format = r_state->format;
12357a84e134Smrg
12367a84e134Smrg    src->textSrc.undo_state = True;
12377a84e134Smrg    if (XawTextSourceReplace((Widget)src, l_state->position, l_state->position
12387a84e134Smrg			     + l_state->length, &block) != XawEditDone) {
12397a84e134Smrg	src->textSrc.undo_state = False;
12407a84e134Smrg	src->textSrc.changed = changed;
12417a84e134Smrg	return (False);
12427a84e134Smrg    }
12437a84e134Smrg    src->textSrc.undo_state = False;
12447a84e134Smrg
12457a84e134Smrg    ++l_state->refcount;
12467a84e134Smrg    ++r_state->refcount;
12477a84e134Smrg    nlist = XtNew(XawTextUndoList);
12487a84e134Smrg    nlist->left = l_state;
12497a84e134Smrg    nlist->right = r_state;
12507a84e134Smrg    nlist->undo = src->textSrc.undo->list;
12517a84e134Smrg    nlist->redo = NULL;
12527a84e134Smrg
12537a84e134Smrg    if (list == src->textSrc.undo->list)
12547a84e134Smrg	src->textSrc.undo->end_mark = nlist;
12557a84e134Smrg
12567a84e134Smrg    if (src->textSrc.undo->dir == XawsdLeft) {
12577a84e134Smrg	if (list->undo == NULL)
12587a84e134Smrg	    src->textSrc.undo->dir = XawsdRight;
12597a84e134Smrg	else
12607a84e134Smrg	    list = list->undo;
12617a84e134Smrg    }
12627a84e134Smrg    else {
12637a84e134Smrg	if (list->redo == NULL || list->redo == src->textSrc.undo->end_mark)
12647a84e134Smrg	    src->textSrc.undo->dir = XawsdLeft;
12657a84e134Smrg	else
12667a84e134Smrg	    list = list->redo;
12677a84e134Smrg    }
12687a84e134Smrg    *insert_pos = r_state->position + r_state->length;
12697a84e134Smrg    src->textSrc.undo->pointer = list;
12707a84e134Smrg    src->textSrc.undo->list->redo = nlist;
12717a84e134Smrg    src->textSrc.undo->list = nlist;
12727a84e134Smrg    src->textSrc.undo->merge = src->textSrc.undo->erase = 0;
12737a84e134Smrg
12747a84e134Smrg    if (++src->textSrc.undo->num_list >= UNDO_DEPTH)
12757a84e134Smrg	UndoGC(src->textSrc.undo);
12767a84e134Smrg
12777a84e134Smrg    return (True);
12787a84e134Smrg}
12797a84e134Smrg
12807a84e134SmrgBool
12817a84e134Smrg_XawTextSrcToggleUndo(TextSrcObject src)
12827a84e134Smrg{
12837a84e134Smrg    if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo)
12847a84e134Smrg	return (False);
12857a84e134Smrg
12867a84e134Smrg    if (src->textSrc.undo->pointer != src->textSrc.undo->list) {
12877a84e134Smrg	if (src->textSrc.undo->dir == XawsdLeft) {
12887a84e134Smrg	    if (src->textSrc.undo->pointer->redo
12897a84e134Smrg		&& (src->textSrc.undo->pointer->redo
12907a84e134Smrg		    != src->textSrc.undo->end_mark)) {
12917a84e134Smrg		src->textSrc.undo->pointer = src->textSrc.undo->pointer->redo;
12927a84e134Smrg		src->textSrc.undo->dir = XawsdRight;
12937a84e134Smrg	    }
12947a84e134Smrg	}
12957a84e134Smrg	else {
12967a84e134Smrg	    if (src->textSrc.undo->pointer->undo
12977a84e134Smrg		&& (src->textSrc.undo->pointer != src->textSrc.undo->head)) {
12987a84e134Smrg		src->textSrc.undo->pointer = src->textSrc.undo->pointer->undo;
12997a84e134Smrg		src->textSrc.undo->dir = XawsdLeft;
13007a84e134Smrg	    }
13017a84e134Smrg	}
13027a84e134Smrg    }
13037a84e134Smrg
13047a84e134Smrg    return (True);
13057a84e134Smrg}
13067a84e134Smrg
13077a84e134Smrgstatic void
13087a84e134SmrgFreeUndoBuffer(XawTextUndo *undo)
13097a84e134Smrg{
13107a84e134Smrg    unsigned i;
13117a84e134Smrg    XawTextUndoList *head, *del;
13127a84e134Smrg
13137a84e134Smrg    for (i = 0; i < undo->num_undo; i++) {
13147a84e134Smrg	if (undo->undo[i]->buffer && undo->undo[i]->buffer != SrcNL &&
13157a84e134Smrg	    undo->undo[i]->buffer != (char*)SrcWNL)
13167a84e134Smrg	    XtFree(undo->undo[i]->buffer);
13177a84e134Smrg	XtFree((char*)undo->undo[i]);
13187a84e134Smrg    }
13197a84e134Smrg    XtFree((char*)undo->undo);
13207a84e134Smrg    head = undo->head;
13217a84e134Smrg
13227a84e134Smrg    del = head;
13237a84e134Smrg    while (head) {
13247a84e134Smrg	head = head->redo;
13257a84e134Smrg	XtFree((char*)del);
13267a84e134Smrg	del = head;
13277a84e134Smrg    }
13287a84e134Smrg
13297a84e134Smrg    if (undo->l_save) {
13307a84e134Smrg	XtFree((char*)undo->l_save);
13317a84e134Smrg	undo->l_save = NULL;
13327a84e134Smrg    }
13337a84e134Smrg    if (undo->r_save) {
13347a84e134Smrg	XtFree((char*)undo->r_save);
13357a84e134Smrg	undo->r_save = NULL;
13367a84e134Smrg    }
13377a84e134Smrg    if (undo->u_save) {
13387a84e134Smrg	XtFree((char*)undo->u_save);
13397a84e134Smrg	undo->u_save = NULL;
13407a84e134Smrg    }
13417a84e134Smrg
13427a84e134Smrg    undo->list = undo->pointer = undo->head = undo->end_mark = NULL;
13437a84e134Smrg    undo->l_no_change = undo->r_no_change = NULL;
13447a84e134Smrg    undo->undo = NULL;
13457a84e134Smrg    undo->dir = XawsdLeft;
13467a84e134Smrg    undo->num_undo = undo->num_list = undo->erase = undo->merge = 0;
13477a84e134Smrg}
13487a84e134Smrg
13497a84e134Smrgstatic void
13507a84e134SmrgUndoGC(XawTextUndo *undo)
13517a84e134Smrg{
13527a84e134Smrg    unsigned i;
13537a84e134Smrg    XawTextUndoList *head = undo->head, *redo = head->redo;
13547a84e134Smrg
13557a84e134Smrg    if (head == undo->pointer || head == undo->end_mark
13567a84e134Smrg	|| undo->l_no_change == NULL
13577a84e134Smrg	|| head->left == undo->l_no_change || head->right == undo->l_no_change)
13587a84e134Smrg      return;
13597a84e134Smrg
13607a84e134Smrg    undo->head = redo;
13617a84e134Smrg    redo->undo = NULL;
13627a84e134Smrg
13637a84e134Smrg    --head->left->refcount;
13647a84e134Smrg    if (--head->right->refcount == 0) {
13657a84e134Smrg	for (i = 0; i < undo->num_undo; i+= 2)
13667a84e134Smrg	    if (head->left == undo->undo[i] || head->left == undo->undo[i+1]) {
13677a84e134Smrg		if (head->left == undo->undo[i+1]) {
13687a84e134Smrg		    XawTextUndoBuffer *tmp = redo->left;
13697a84e134Smrg
13707a84e134Smrg		    redo->left = redo->right;
13717a84e134Smrg		    redo->right = tmp;
13727a84e134Smrg		}
13737a84e134Smrg		if (head->left->buffer && head->left->buffer != SrcNL &&
13747a84e134Smrg		    head->left->buffer != (char*)SrcWNL)
13757a84e134Smrg		    XtFree(head->left->buffer);
13767a84e134Smrg		XtFree((char*)head->left);
13777a84e134Smrg		if (head->right->buffer && head->right->buffer != SrcNL &&
13787a84e134Smrg		    head->right->buffer != (char*)SrcWNL)
13797a84e134Smrg		    XtFree(head->right->buffer);
13807a84e134Smrg		XtFree((char*)head->right);
13817a84e134Smrg
13827a84e134Smrg		undo->num_undo -= 2;
13837a84e134Smrg		memmove(&undo->undo[i], &undo->undo[i + 2],
13847a84e134Smrg			(undo->num_undo - i) * sizeof(XawTextUndoBuffer*));
13857a84e134Smrg		break;
13867a84e134Smrg	    }
13877a84e134Smrg    }
13887a84e134Smrg    XtFree((char*)head);
13897a84e134Smrg    --undo->num_list;
13907a84e134Smrg}
13917a84e134Smrg#endif /* OLDXAW */
13927a84e134Smrg
13937a84e134Smrg/*
13947a84e134Smrg * Function:
13957a84e134Smrg *	XawTextSourceScan
13967a84e134Smrg *
13977a84e134Smrg * Parameters:
13987a84e134Smrg *	w	 - TextSrc Object
13997a84e134Smrg *	position - position to start scanning
14007a84e134Smrg *	type	 - type of thing to scan for
14017a84e134Smrg *	dir	 - direction to scan
14027a84e134Smrg *	count	 - which occurance if this thing to search for
14037a84e134Smrg *	include  - whether or not to include the character found in
14047a84e134Smrg *		   the position that is returned.
14057a84e134Smrg *
14067a84e134Smrg * Description:
14077a84e134Smrg *	Scans the text source for the number and type of item specified.
14087a84e134Smrg *
14097a84e134Smrg * Returns:
14107a84e134Smrg *	The position of the text
14117a84e134Smrg */
14127a84e134SmrgXawTextPosition
14137a84e134SmrgXawTextSourceScan(Widget w, XawTextPosition position,
14147a84e134Smrg#if NeedWidePrototypes
14157a84e134Smrg		  int type, int dir, int count, int include
14167a84e134Smrg#else
14177a84e134Smrg		  XawTextScanType type, XawTextScanDirection dir,
14187a84e134Smrg		  int count, Boolean include
14197a84e134Smrg#endif
14207a84e134Smrg)
14217a84e134Smrg{
14227a84e134Smrg    TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
14237a84e134Smrg
14247a84e134Smrg    return ((*cclass->textSrc_class.Scan)
14257a84e134Smrg	    (w, position, type, dir, count, include));
14267a84e134Smrg}
14277a84e134Smrg
14287a84e134Smrg/*
14297a84e134Smrg * Function:
14307a84e134Smrg *	XawTextSourceSearch
14317a84e134Smrg *
14327a84e134Smrg * Parameters:
14337a84e134Smrg *	w	 - TextSource Object
14347a84e134Smrg *	position - position to start scanning
14357a84e134Smrg *	dir	 - direction to scan
14367a84e134Smrg *	text	 - the text block to search for.
14377a84e134Smrg *
14387a84e134Smrg * Returns:
14397a84e134Smrg *	The position of the text we are searching for or XawTextSearchError.
14407a84e134Smrg *
14417a84e134Smrg * Description:
14427a84e134Smrg *	Searchs the text source for the text block passed
14437a84e134Smrg */
14447a84e134SmrgXawTextPosition
14457a84e134SmrgXawTextSourceSearch(Widget w, XawTextPosition position,
14467a84e134Smrg#if NeedWidePrototypes
14477a84e134Smrg		    int dir,
14487a84e134Smrg#else
14497a84e134Smrg		    XawTextScanDirection dir,
14507a84e134Smrg#endif
14517a84e134Smrg		    XawTextBlock *text)
14527a84e134Smrg{
14537a84e134Smrg    TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
14547a84e134Smrg
14557a84e134Smrg    return ((*cclass->textSrc_class.Search)(w, position, dir, text));
14567a84e134Smrg}
14577a84e134Smrg
14587a84e134Smrg/*
14597a84e134Smrg * Function:
14607a84e134Smrg *	XawTextSourceConvertSelection
14617a84e134Smrg *
14627a84e134Smrg * Parameters:
14637a84e134Smrg *	w	  - TextSrc object
14647a84e134Smrg *	selection - current selection atom
14657a84e134Smrg *	target	  - current target atom
14667a84e134Smrg *	type	  - type to conver the selection to
14677a84e134Smrg *	value	  - return value that has been converted
14687a84e134Smrg *	length	  - ""
14697a84e134Smrg *	format	  - format of the returned value
14707a84e134Smrg *
14717a84e134Smrg * Returns:
14727a84e134Smrg *	True if the selection has been converted
14737a84e134Smrg */
14747a84e134SmrgBoolean
14757a84e134SmrgXawTextSourceConvertSelection(Widget w, Atom *selection, Atom *target,
14767a84e134Smrg			      Atom *type, XtPointer *value,
14777a84e134Smrg			      unsigned long *length, int *format)
14787a84e134Smrg{
14797a84e134Smrg    TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
14807a84e134Smrg
14817a84e134Smrg    return((*cclass->textSrc_class.ConvertSelection)
14827a84e134Smrg	   (w, selection, target, type, value, length, format));
14837a84e134Smrg}
14847a84e134Smrg
14857a84e134Smrg/*
14867a84e134Smrg * Function:
14877a84e134Smrg *	XawTextSourceSetSelection
14887a84e134Smrg *
14897a84e134Smrg * Parameters:
14907a84e134Smrg *	w	  - TextSrc object
14917a84e134Smrg *	left	  - bounds of the selection
14927a84e134Smrg *	rigth	  - ""
14937a84e134Smrg *	selection - selection atom
14947a84e134Smrg *
14957a84e134Smrg * Description:
14967a84e134Smrg *	Allows special setting of the selection.
14977a84e134Smrg */
14987a84e134Smrgvoid
14997a84e134SmrgXawTextSourceSetSelection(Widget w, XawTextPosition left,
15007a84e134Smrg			  XawTextPosition right, Atom selection)
15017a84e134Smrg{
15027a84e134Smrg    TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class;
15037a84e134Smrg
15047a84e134Smrg    (*cclass->textSrc_class.SetSelection)(w, left, right, selection);
15057a84e134Smrg}
15067a84e134Smrg
15077a84e134Smrg/*
15087a84e134Smrg * External Functions for Multi Text
15097a84e134Smrg */
15107a84e134Smrg/*
15117a84e134Smrg * TextFormat():
15127a84e134Smrg *	returns the format of text: FMT8BIT or FMTWIDE
15137a84e134Smrg */
15147a84e134SmrgXrmQuark
15157a84e134Smrg_XawTextFormat(TextWidget tw)
15167a84e134Smrg{
15177a84e134Smrg    return (((TextSrcObject)(tw->text.source))->textSrc.text_format);
15187a84e134Smrg}
15197a84e134Smrg
15207a84e134Smrg/* _XawTextWCToMB():
15217a84e134Smrg *	Convert the wchar string to external encoding
15227a84e134Smrg *	The caller is responsible for freeing both the source and ret string
15237a84e134Smrg *
15247a84e134Smrg *	wstr	   - source wchar string
15257a84e134Smrg * len_in_out - lengh of string.
15267a84e134Smrg *		     As In, length of source wchar string, measured in wchar
15277a84e134Smrg *		     As Out, length of returned string
15287a84e134Smrg */
15297a84e134Smrgchar *
15307a84e134Smrg_XawTextWCToMB(Display *d, wchar_t *wstr, int *len_in_out)
15317a84e134Smrg{
15327a84e134Smrg    XTextProperty textprop;
15337a84e134Smrg
15347a84e134Smrg    if (XwcTextListToTextProperty(d, (wchar_t**)&wstr, 1,
15357a84e134Smrg				XTextStyle, &textprop) < Success) {
15367a84e134Smrg	XtWarningMsg("convertError", "textSource", "XawError",
15377a84e134Smrg		     "Non-character code(s) in buffer.", NULL, NULL);
15387a84e134Smrg	*len_in_out = 0;
15397a84e134Smrg	return (NULL);
15407a84e134Smrg    }
15417a84e134Smrg    *len_in_out = textprop.nitems;
15427a84e134Smrg
15437a84e134Smrg    return ((char *)textprop.value);
15447a84e134Smrg}
15457a84e134Smrg
15467a84e134Smrg/* _XawTextMBToWC():
15477a84e134Smrg *	Convert the string to internal processing codeset WC.
15487a84e134Smrg *   The caller is responsible for freeing both the source and ret string.
15497a84e134Smrg *
15507a84e134Smrg *	str	   - source string
15517a84e134Smrg *	len_in_out - lengh of string
15527a84e134Smrg *		     As In, it is length of source string
15537a84e134Smrg *		     As Out, it is length of returned string, measured in wchar
15547a84e134Smrg */
15557a84e134Smrgwchar_t *
15567a84e134Smrg_XawTextMBToWC(Display *d, char *str, int *len_in_out)
15577a84e134Smrg{
15587a84e134Smrg    XTextProperty textprop;
15597a84e134Smrg    char *buf;
15607a84e134Smrg    wchar_t **wlist, *wstr;
15617a84e134Smrg    int count;
15627a84e134Smrg
15637a84e134Smrg    if (*len_in_out == 0)
15647a84e134Smrg	return (NULL);
15657a84e134Smrg
15667a84e134Smrg    buf = XtMalloc(*len_in_out + 1);
15677a84e134Smrg
15687a84e134Smrg    strncpy(buf, str, *len_in_out);
15697a84e134Smrg    *(buf + *len_in_out) = '\0';
15707a84e134Smrg    if (XmbTextListToTextProperty(d, &buf, 1, XTextStyle, &textprop) != Success) {
15717a84e134Smrg	XtWarningMsg("convertError", "textSource", "XawError",
15727a84e134Smrg		     "No Memory, or Locale not supported.", NULL, NULL);
15737a84e134Smrg	XtFree(buf);
15747a84e134Smrg	*len_in_out = 0;
15757a84e134Smrg	return (NULL);
15767a84e134Smrg    }
15777a84e134Smrg
15787a84e134Smrg    XtFree(buf);
15797a84e134Smrg    if (XwcTextPropertyToTextList(d, &textprop,
15807a84e134Smrg				  (wchar_t***)&wlist, &count) != Success) {
15817a84e134Smrg	XtWarningMsg("convertError", "multiSourceCreate", "XawError",
15827a84e134Smrg		     "Non-character code(s) in source.", NULL, NULL);
15837a84e134Smrg	*len_in_out = 0;
15847a84e134Smrg	return (NULL);
15857a84e134Smrg    }
15867a84e134Smrg    wstr = wlist[0];
15877a84e134Smrg    *len_in_out = wcslen(wstr);
15887a84e134Smrg    XtFree((XtPointer)wlist);
15897a84e134Smrg
15907a84e134Smrg    return (wstr);
15917a84e134Smrg}
15927a84e134Smrg
15937a84e134Smrg#ifndef OLDXAW
15947a84e134Smrgstatic int
15957a84e134Smrgqcmp_anchors(_Xconst void *left, _Xconst void *right)
15967a84e134Smrg{
15977a84e134Smrg    return ((*(XawTextAnchor**)left)->position -
15987a84e134Smrg	    (*(XawTextAnchor**)right)->position);
15997a84e134Smrg}
16007a84e134Smrg
16017a84e134SmrgXawTextAnchor *
16027a84e134SmrgXawTextSourceAddAnchor(Widget w, XawTextPosition position)
16037a84e134Smrg{
16047a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
16057a84e134Smrg    XawTextAnchor *anchor, *panchor;
16067a84e134Smrg
16077a84e134Smrg    if ((panchor = XawTextSourceFindAnchor(w, position)) != NULL) {
16087a84e134Smrg	XawTextEntity *pentity, *entity;
16097a84e134Smrg
16107a84e134Smrg	if (position - panchor->position < ANCHORS_DIST)
16117a84e134Smrg	    return (panchor);
16127a84e134Smrg
16137a84e134Smrg	if (panchor->cache && panchor->position + panchor->cache->offset +
16147a84e134Smrg	    panchor->cache->length < position)
16157a84e134Smrg	    pentity = entity = panchor->cache;
16167a84e134Smrg	else
16177a84e134Smrg	    pentity = entity = panchor->entities;
16187a84e134Smrg
16197a84e134Smrg	while (entity && panchor->position + entity->offset +
16207a84e134Smrg	       entity->length < position) {
16217a84e134Smrg	    pentity = entity;
16227a84e134Smrg	    entity = entity->next;
16237a84e134Smrg	}
16247a84e134Smrg	if (entity) {
16257a84e134Smrg	    XawTextPosition diff;
16267a84e134Smrg
16277a84e134Smrg	    if (panchor->position + entity->offset < position)
16287a84e134Smrg		position = panchor->position + entity->offset;
16297a84e134Smrg
16307a84e134Smrg	    if (position == panchor->position)
16317a84e134Smrg		return (panchor);
16327a84e134Smrg
16337a84e134Smrg	    anchor = XtNew(XawTextAnchor);
16347a84e134Smrg	    diff = position - panchor->position;
16357a84e134Smrg
16367a84e134Smrg	    panchor->cache = NULL;
16377a84e134Smrg	    anchor->entities = entity;
16387a84e134Smrg	    if (pentity != entity)
16397a84e134Smrg		pentity->next = NULL;
16407a84e134Smrg	    else
16417a84e134Smrg		panchor->entities = NULL;
16427a84e134Smrg	    while (entity) {
16437a84e134Smrg		entity->offset -= diff;
16447a84e134Smrg		entity = entity->next;
16457a84e134Smrg	    }
16467a84e134Smrg	}
16477a84e134Smrg	else {
16487a84e134Smrg	    anchor = XtNew(XawTextAnchor);
16497a84e134Smrg	    anchor->entities = NULL;
16507a84e134Smrg	}
16517a84e134Smrg    }
16527a84e134Smrg    else {
16537a84e134Smrg	anchor = XtNew(XawTextAnchor);
16547a84e134Smrg	anchor->entities = NULL;
16557a84e134Smrg    }
16567a84e134Smrg
16577a84e134Smrg    anchor->position = position;
16587a84e134Smrg    anchor->cache = NULL;
16597a84e134Smrg
16607a84e134Smrg    src->textSrc.anchors = (XawTextAnchor**)
16617a84e134Smrg	XtRealloc((XtPointer)src->textSrc.anchors, sizeof(XawTextAnchor*) *
16627a84e134Smrg		  (src->textSrc.num_anchors + 1));
16637a84e134Smrg    src->textSrc.anchors[src->textSrc.num_anchors++] = anchor;
16647a84e134Smrg    qsort((void*)src->textSrc.anchors, src->textSrc.num_anchors,
16657a84e134Smrg	  sizeof(XawTextAnchor*), qcmp_anchors);
16667a84e134Smrg
16677a84e134Smrg    return (anchor);
16687a84e134Smrg}
16697a84e134Smrg
16707a84e134SmrgXawTextAnchor *
16717a84e134SmrgXawTextSourceFindAnchor(Widget w, XawTextPosition position)
16727a84e134Smrg{
16737a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
16747a84e134Smrg    int i = 0, left, right, nmemb = src->textSrc.num_anchors;
16757a84e134Smrg    XawTextAnchor *anchor, **anchors = src->textSrc.anchors;
16767a84e134Smrg
16777a84e134Smrg    left = 0;
16787a84e134Smrg    right = nmemb - 1;
16797a84e134Smrg    while (left <= right) {
16807a84e134Smrg	anchor = anchors[i = (left + right) >> 1];
16817a84e134Smrg	if (anchor->position == position)
16827a84e134Smrg	    return (anchor);
16837a84e134Smrg	else if (position < anchor->position)
16847a84e134Smrg	    right = i - 1;
16857a84e134Smrg	else
16867a84e134Smrg	    left = i + 1;
16877a84e134Smrg    }
16887a84e134Smrg
16897a84e134Smrg    if (nmemb)
16907a84e134Smrg	return (right < 0 ? anchors[0] : anchors[right]);
16917a84e134Smrg
16927a84e134Smrg    return (NULL);
16937a84e134Smrg}
16947a84e134Smrg
16957a84e134SmrgBool
16967a84e134SmrgXawTextSourceAnchorAndEntity(Widget w, XawTextPosition position,
16977a84e134Smrg			     XawTextAnchor **anchor_return,
16987a84e134Smrg			     XawTextEntity **entity_return)
16997a84e134Smrg{
17007a84e134Smrg    XawTextAnchor *anchor = XawTextSourceFindAnchor(w, position);
17017a84e134Smrg    XawTextEntity *pentity, *entity;
17027a84e134Smrg    XawTextPosition offset;
17037a84e134Smrg    Bool next_anchor = True, retval = False;
17047a84e134Smrg
17057a84e134Smrg    if (anchor->cache && anchor->position + anchor->cache->offset +
17067a84e134Smrg	anchor->cache->length <= position)
17077a84e134Smrg	pentity = entity = anchor->cache;
17087a84e134Smrg    else
17097a84e134Smrg	pentity = entity = anchor->entities;
17107a84e134Smrg    while (entity) {
17117a84e134Smrg	offset = anchor->position + entity->offset;
17127a84e134Smrg
17137a84e134Smrg	if (offset > position) {
17147a84e134Smrg	    retval = next_anchor = False;
17157a84e134Smrg	    break;
17167a84e134Smrg	}
17177a84e134Smrg	if (offset + entity->length > position) {
17187a84e134Smrg	    retval = True;
17197a84e134Smrg	    next_anchor = False;
17207a84e134Smrg	    break;
17217a84e134Smrg	}
17227a84e134Smrg	pentity = entity;
17237a84e134Smrg	entity = entity->next;
17247a84e134Smrg    }
17257a84e134Smrg
17267a84e134Smrg    if (next_anchor) {
17277a84e134Smrg	*anchor_return = anchor = XawTextSourceNextAnchor(w, anchor);
17287a84e134Smrg	*entity_return = anchor ? anchor->entities : NULL;
17297a84e134Smrg    }
17307a84e134Smrg    else {
17317a84e134Smrg	*anchor_return = anchor;
17327a84e134Smrg	*entity_return = retval ? entity : pentity;
17337a84e134Smrg    }
17347a84e134Smrg
17357a84e134Smrg    if (*anchor_return)
17367a84e134Smrg	(*anchor_return)->cache = *entity_return;
17377a84e134Smrg
17387a84e134Smrg    return (retval);
17397a84e134Smrg}
17407a84e134Smrg
17417a84e134SmrgXawTextAnchor *
17427a84e134SmrgXawTextSourceNextAnchor(Widget w, XawTextAnchor *anchor)
17437a84e134Smrg{
17447a84e134Smrg    int i;
17457a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
17467a84e134Smrg
17477a84e134Smrg    for (i = 0; i < src->textSrc.num_anchors - 1; i++)
17487a84e134Smrg	if (src->textSrc.anchors[i] == anchor)
17497a84e134Smrg	    return (src->textSrc.anchors[i + 1]);
17507a84e134Smrg
17517a84e134Smrg    return (NULL);
17527a84e134Smrg}
17537a84e134Smrg
17547a84e134SmrgXawTextAnchor *
17557a84e134SmrgXawTextSourcePrevAnchor(Widget w, XawTextAnchor *anchor)
17567a84e134Smrg{
17577a84e134Smrg    int i;
17587a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
17597a84e134Smrg
17607a84e134Smrg    for (i = src->textSrc.num_anchors - 1; i > 0; i--)
17617a84e134Smrg	if (src->textSrc.anchors[i] == anchor)
17627a84e134Smrg	    return (src->textSrc.anchors[i - 1]);
17637a84e134Smrg
17647a84e134Smrg    return (NULL);
17657a84e134Smrg}
17667a84e134Smrg
17677a84e134SmrgXawTextAnchor *
17687a84e134SmrgXawTextSourceRemoveAnchor(Widget w, XawTextAnchor *anchor)
17697a84e134Smrg{
17707a84e134Smrg    int i;
17717a84e134Smrg    TextSrcObject src = (TextSrcObject)w;
17727a84e134Smrg
17737a84e134Smrg    for (i = 0; i < src->textSrc.num_anchors; i++)
17747a84e134Smrg	if (src->textSrc.anchors[i] == anchor)
17757a84e134Smrg	    break;
17767a84e134Smrg
17777a84e134Smrg    if (i == 0)
17787a84e134Smrg	return (src->textSrc.num_anchors > 1 ? src->textSrc.anchors[1] : NULL);
17797a84e134Smrg
17807a84e134Smrg    if (i < src->textSrc.num_anchors) {
17817a84e134Smrg	XtFree((XtPointer)anchor);
17827a84e134Smrg	if (i < --src->textSrc.num_anchors) {
17837a84e134Smrg	    memmove(&src->textSrc.anchors[i],
17847a84e134Smrg		    &src->textSrc.anchors[i + 1],
17857a84e134Smrg		    (src->textSrc.num_anchors - i) *
17867a84e134Smrg		    sizeof(XawTextAnchor*));
17877a84e134Smrg
17887a84e134Smrg	    return (src->textSrc.anchors[i]);
17897a84e134Smrg	}
17907a84e134Smrg    }
17917a84e134Smrg
17927a84e134Smrg    return (NULL);
17937a84e134Smrg}
17947a84e134Smrg
17957a84e134SmrgXawTextEntity *
17967a84e134SmrgXawTextSourceAddEntity(Widget w, int type, int flags, XtPointer data,
17977a84e134Smrg		       XawTextPosition position, Cardinal length,
17987a84e134Smrg		       XrmQuark property)
17997a84e134Smrg{
18007a84e134Smrg    XawTextAnchor *next, *anchor = _XawTextSourceFindAnchor(w, position);
18017a84e134Smrg    XawTextEntity *entity, *eprev;
18027a84e134Smrg
18037a84e134Smrg    /* There is no support for zero length entities for now */
18047a84e134Smrg    if (length == 0)
18057a84e134Smrg	return (NULL);
18067a84e134Smrg
18077a84e134Smrg    if (anchor->cache && anchor->position + anchor->cache->offset +
18087a84e134Smrg	anchor->cache->length <= position)
18097a84e134Smrg	eprev = entity = anchor->cache;
18107a84e134Smrg    else
18117a84e134Smrg	eprev = entity = anchor->entities;
18127a84e134Smrg
18137a84e134Smrg    while (entity && anchor->position + entity->offset + entity->length <=
18147a84e134Smrg	   position) {
18157a84e134Smrg	eprev = entity;
18167a84e134Smrg	entity = entity->next;
18177a84e134Smrg    }
18187a84e134Smrg    if (entity && anchor->position + entity->offset < position + length) {
18197a84e134Smrg	fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n");
18207a84e134Smrg	return (NULL);
18217a84e134Smrg    }
18227a84e134Smrg
18237a84e134Smrg    next = XawTextSourceFindAnchor(w, position + length);
18247a84e134Smrg    if (next && next != anchor) {
18257a84e134Smrg	if ((entity = next->entities) != NULL) {
18267a84e134Smrg	    if (next->position + entity->offset < position + length) {
18277a84e134Smrg		fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n");
18287a84e134Smrg		return (NULL);
18297a84e134Smrg	    }
18307a84e134Smrg	}
18317a84e134Smrg	if (position + length > next->position) {
18327a84e134Smrg	    XawTextPosition diff = position + length - next->position;
18337a84e134Smrg
18347a84e134Smrg	    next->position += diff;
18357a84e134Smrg	    entity = next->entities;
18367a84e134Smrg	    while (entity) {
18377a84e134Smrg		entity->offset -= diff;
18387a84e134Smrg		entity = entity->next;
18397a84e134Smrg	    }
18407a84e134Smrg	    entity = anchor->entities;
18417a84e134Smrg	    while (entity && entity->offset < 0)
18427a84e134Smrg		entity = entity->next;
18437a84e134Smrg	    if (entity && entity->offset < 0) {
18447a84e134Smrg		if (eprev)
18457a84e134Smrg		    eprev->next = next->entities;
18467a84e134Smrg		else
18477a84e134Smrg		    anchor->entities = next->entities;
18487a84e134Smrg		if ((next->entities = entity->next) == NULL)
18497a84e134Smrg		    (void)XawTextSourceRemoveAnchor(w, next);
18507a84e134Smrg		entity->next = NULL;
18517a84e134Smrg
18527a84e134Smrg		return (XawTextSourceAddEntity(w, type, flags, data, position,
18537a84e134Smrg					       length, property));
18547a84e134Smrg	    }
18557a84e134Smrg	}
18567a84e134Smrg    }
18577a84e134Smrg
18587a84e134Smrg    /* Automatically join sequential entities if possible */
18597a84e134Smrg    if (eprev &&
18607a84e134Smrg	anchor->position + eprev->offset + eprev->length == position &&
18617a84e134Smrg	eprev->property == property && eprev->type == type &&
18627a84e134Smrg	eprev->flags == flags && eprev->data == data) {
18637a84e134Smrg	eprev->length += length;
18647a84e134Smrg	return (eprev);
18657a84e134Smrg    }
18667a84e134Smrg
18677a84e134Smrg    entity = XtNew(XawTextEntity);
18687a84e134Smrg    entity->type = type;
18697a84e134Smrg    entity->flags = flags;
18707a84e134Smrg    entity->data = data;
18717a84e134Smrg    entity->offset = position - anchor->position;
18727a84e134Smrg    entity->length = length;
18737a84e134Smrg    entity->property = property;
18747a84e134Smrg
18757a84e134Smrg    if (eprev == NULL) {
18767a84e134Smrg	anchor->entities = entity;
18777a84e134Smrg	entity->next = NULL;
18787a84e134Smrg	anchor->cache = NULL;
18797a84e134Smrg    }
18807a84e134Smrg    else if (eprev->offset > entity->offset) {
18817a84e134Smrg	anchor->cache = NULL;
18827a84e134Smrg	anchor->entities = entity;
18837a84e134Smrg	entity->next = eprev;
18847a84e134Smrg    }
18857a84e134Smrg    else {
18867a84e134Smrg	anchor->cache = eprev;
18877a84e134Smrg	entity->next = eprev->next;
18887a84e134Smrg	eprev->next = entity;
18897a84e134Smrg    }
18907a84e134Smrg
18917a84e134Smrg    return (entity);
18927a84e134Smrg}
18937a84e134Smrg
18947a84e134Smrgvoid
18957a84e134SmrgXawTextSourceClearEntities(Widget w, XawTextPosition left, XawTextPosition right)
18967a84e134Smrg{
18977a84e134Smrg    XawTextAnchor *anchor = XawTextSourceFindAnchor(w, left);
18987a84e134Smrg    XawTextEntity *entity, *eprev, *enext;
18997a84e134Smrg    XawTextPosition offset;
19007a84e134Smrg    int length;
19017a84e134Smrg
19027a84e134Smrg    while (anchor && anchor->entities == NULL)
19037a84e134Smrg	anchor = XawTextSourceRemoveAnchor(w, anchor);
19047a84e134Smrg
19057a84e134Smrg    if (anchor == NULL || left >= right)
19067a84e134Smrg	return;
19077a84e134Smrg
19087a84e134Smrg    if (anchor->cache && anchor->position + anchor->cache->offset +
19097a84e134Smrg	anchor->cache->length < left)
19107a84e134Smrg	eprev = entity = anchor->cache;
19117a84e134Smrg    else
19127a84e134Smrg	eprev = entity = anchor->entities;
19137a84e134Smrg
19147a84e134Smrg    /* find first entity before left position */
19157a84e134Smrg    while (anchor->position + entity->offset + entity->length < left) {
19167a84e134Smrg	eprev = entity;
19177a84e134Smrg	if ((entity = entity->next) == NULL) {
19187a84e134Smrg	    if ((anchor = XawTextSourceNextAnchor(w, anchor)) == NULL)
19197a84e134Smrg		return;
19207a84e134Smrg	    if ((eprev = entity = anchor->entities) == NULL) {
19217a84e134Smrg		fprintf(stderr, "Bad anchor found!\n");
19227a84e134Smrg		return;
19237a84e134Smrg	    }
19247a84e134Smrg	}
19257a84e134Smrg    }
19267a84e134Smrg
19277a84e134Smrg    offset = anchor->position + entity->offset;
19287a84e134Smrg    if (offset <= left) {
19297a84e134Smrg	length = XawMin(entity->length, left - offset);
19307a84e134Smrg
19317a84e134Smrg	if (length <= 0) {
19327a84e134Smrg	    enext = entity->next;
19337a84e134Smrg	    eprev->next = enext;
19347a84e134Smrg	    XtFree((XtPointer)entity);
19357a84e134Smrg	    anchor->cache = NULL;
19367a84e134Smrg	    if (entity == anchor->entities) {
19377a84e134Smrg		eprev = NULL;
19387a84e134Smrg		if ((anchor->entities = enext) == NULL) {
19397a84e134Smrg		    if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL)
19407a84e134Smrg			return;
19417a84e134Smrg		    entity = anchor->entities;
19427a84e134Smrg		}
19437a84e134Smrg		else
19447a84e134Smrg		    entity = enext;
19457a84e134Smrg	    }
19467a84e134Smrg	    else
19477a84e134Smrg		entity = enext;
19487a84e134Smrg	}
19497a84e134Smrg	else {
19507a84e134Smrg	    entity->length = length;
19517a84e134Smrg	    eprev = entity;
19527a84e134Smrg	    entity = entity->next;
19537a84e134Smrg	}
19547a84e134Smrg    }
19557a84e134Smrg
19567a84e134Smrg    /* clean everything until right position is reached */
19577a84e134Smrg    while (anchor) {
19587a84e134Smrg	while (entity) {
19597a84e134Smrg	    offset = anchor->position + entity->offset + entity->length;
19607a84e134Smrg
19617a84e134Smrg	    if (offset > right) {
19627a84e134Smrg		anchor->cache = NULL;
19637a84e134Smrg		entity->offset = XawMax(entity->offset, right - anchor->position);
19647a84e134Smrg		entity->length = XawMin(entity->length, offset - right);
19657a84e134Smrg		return;
19667a84e134Smrg	    }
19677a84e134Smrg
19687a84e134Smrg	    enext = entity->next;
19697a84e134Smrg	    if (eprev)
19707a84e134Smrg		eprev->next = enext;
19717a84e134Smrg	    XtFree((XtPointer)entity);
19727a84e134Smrg	    if (entity == anchor->entities) {
19737a84e134Smrg		eprev = anchor->cache = NULL;
19747a84e134Smrg		if ((anchor->entities = enext) == NULL) {
19757a84e134Smrg		    if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL)
19767a84e134Smrg			return;
19777a84e134Smrg		    entity = anchor->entities;
19787a84e134Smrg		    continue;
19797a84e134Smrg		}
19807a84e134Smrg	    }
19817a84e134Smrg	    entity = enext;
19827a84e134Smrg	}
19837a84e134Smrg	if (anchor)
19847a84e134Smrg	    anchor->cache = NULL;
19857a84e134Smrg	if ((anchor = XawTextSourceNextAnchor(w, anchor)) != NULL)
19867a84e134Smrg	    entity = anchor->entities;
19877a84e134Smrg	eprev = NULL;
19887a84e134Smrg    }
19897a84e134Smrg}
19907a84e134Smrg
19917a84e134Smrg/* checks the anchors up to position, and create an appropriate anchor
19927a84e134Smrg * at position, if required.
19937a84e134Smrg */
19947a84e134SmrgXawTextAnchor *
19957a84e134Smrg_XawTextSourceFindAnchor(Widget w, XawTextPosition position)
19967a84e134Smrg{
19977a84e134Smrg    XawTextAnchor *anchor;
19987a84e134Smrg
19997a84e134Smrg    anchor = XawTextSourceFindAnchor(w, position);
20007a84e134Smrg
20017a84e134Smrg    position -= position % ANCHORS_DIST;
20027a84e134Smrg
20037a84e134Smrg    if (position - anchor->position >= ANCHORS_DIST)
20047a84e134Smrg	return (XawTextSourceAddAnchor(w, position));
20057a84e134Smrg
20067a84e134Smrg    return (anchor);
20077a84e134Smrg}
20087a84e134Smrg#endif
2009