From dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 11:27:51 +0200 Subject: Synchronised line endinge with release branch --- libXaw/src/TextSrc.c | 4016 +++++++++++++++++++++++++------------------------- 1 file changed, 2008 insertions(+), 2008 deletions(-) (limited to 'libXaw/src/TextSrc.c') diff --git a/libXaw/src/TextSrc.c b/libXaw/src/TextSrc.c index bc055aaca..118361ea5 100644 --- a/libXaw/src/TextSrc.c +++ b/libXaw/src/TextSrc.c @@ -1,2008 +1,2008 @@ -/* - -Copyright 1989, 1994, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - -*/ - -/* - * Author: Chris Peterson, MIT X Consortium. - * Much code taken from X11R3 String and Disk Sources. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "XawI18n.h" -#include "Private.h" - -#ifndef OLDXAW -#define UNDO_DEPTH 16384 - -#define ANCHORS_DIST 4096 /* default distance between anchors */ - -/* - * Types - */ -typedef struct { - XawTextPosition position; - char *buffer; - unsigned length; - unsigned refcount; - unsigned long format; -} XawTextUndoBuffer; - -typedef struct _XawTextUndoList XawTextUndoList; -struct _XawTextUndoList { - XawTextUndoBuffer *left, *right; - XawTextUndoList *undo, *redo; -}; - -struct _XawTextUndo { - XawTextUndoBuffer **undo; - unsigned num_undo; - XawTextUndoList *list, *pointer, *end_mark, *head; - unsigned num_list; - XawTextScanDirection dir; - XawTextUndoBuffer *l_save, *r_save; - XawTextUndoList *u_save; - XawTextUndoBuffer *l_no_change, *r_no_change; - int merge; - int erase; /* there are two types of erases */ -}; -#endif /* OLDXAW */ - -/* - * Class Methods - */ -static Boolean ConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*, - unsigned long*, int*); -static XawTextPosition Read(Widget, XawTextPosition, XawTextBlock*, int); -static int Replace(Widget, XawTextPosition, XawTextPosition, XawTextBlock*); -static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType, - XawTextScanDirection, int, Bool); -static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection, - XawTextBlock*); -static void SetSelection(Widget, XawTextPosition, XawTextPosition, Atom); -static void XawTextSrcClassInitialize(void); -static void XawTextSrcClassPartInitialize(WidgetClass); -static void XawTextSrcInitialize(Widget, Widget, ArgList, Cardinal*); -static void XawTextSrcDestroy(Widget); -static Boolean XawTextSrcSetValues(Widget, Widget, Widget, ArgList, Cardinal*); -/* - * Prototypes - */ -static void CvtStringToEditMode(XrmValuePtr, Cardinal*, - XrmValuePtr, XrmValuePtr); -static Boolean CvtEditModeToString(Display*, XrmValuePtr, Cardinal*, - XrmValuePtr, XrmValuePtr, XtPointer*); -#ifndef OLDXAW -static void FreeUndoBuffer(XawTextUndo*); -static void UndoGC(XawTextUndo*); -static void TellSourceChanged(TextSrcObject, XawTextPosition, XawTextPosition, - XawTextBlock*, int); -Bool _XawTextSrcUndo(TextSrcObject, XawTextPosition*); -Bool _XawTextSrcToggleUndo(TextSrcObject); -XawTextAnchor *_XawTextSourceFindAnchor(Widget, XawTextPosition); - -/* - * External - */ -void _XawSourceAddText(Widget, Widget); -void _XawSourceRemoveText(Widget, Widget, Bool); -Bool _XawTextSourceNewLineAtEOF(Widget); -void _XawSourceSetUndoErase(TextSrcObject, int); -void _XawSourceSetUndoMerge(TextSrcObject, Bool); -#endif /* OLDXAW */ - -/* - * Defined in Text.c - */ -char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition); -void _XawTextSourceChanged(Widget, XawTextPosition, XawTextPosition, - XawTextBlock*, int); - -/* - * Initialization - */ -#define offset(field) XtOffsetOf(TextSrcRec, textSrc.field) -static XtResource resources[] = { - { - XtNeditType, - XtCEditType, - XtREditMode, - sizeof(XawTextEditType), - offset(edit_mode), - XtRString, - "read" - }, -#ifndef OLDXAW - { - XtNcallback, - XtCCallback, - XtRCallback, - sizeof(XtPointer), - offset(callback), - XtRCallback, - NULL - }, - { - XtNsourceChanged, - XtCChanged, - XtRBoolean, - sizeof(Boolean), - offset(changed), - XtRImmediate, - (XtPointer)False - }, - { - XtNenableUndo, - XtCUndo, - XtRBoolean, - sizeof(Boolean), - offset(enable_undo), - XtRImmediate, - (XtPointer)False - }, - { - XtNpropertyCallback, - XtCCallback, - XtRCallback, - sizeof(XtPointer), - offset(property_callback), - XtRCallback, - NULL - }, -#endif /* OLDXAW */ -}; -#undef offset - -#define Superclass (&objectClassRec) -TextSrcClassRec textSrcClassRec = { - /* object */ - { - (WidgetClass)Superclass, /* superclass */ - "TextSrc", /* class_name */ - sizeof(TextSrcRec), /* widget_size */ - XawTextSrcClassInitialize, /* class_initialize */ - XawTextSrcClassPartInitialize, /* class_part_initialize */ - False, /* class_inited */ - XawTextSrcInitialize, /* initialize */ - NULL, /* initialize_hook */ - NULL, /* realize */ - NULL, /* actions */ - 0, /* num_actions */ - resources, /* resources */ - XtNumber(resources), /* num_resources */ - NULLQUARK, /* xrm_class */ - False, /* compress_motion */ - False, /* compress_exposure */ - False, /* compress_enterleave */ - False, /* visible_interest */ - XawTextSrcDestroy, /* destroy */ - NULL, /* resize */ - NULL, /* expose */ - XawTextSrcSetValues, /* set_values */ - NULL, /* set_values_hook */ - NULL, /* set_values_almost */ - NULL, /* get_values_hook */ - NULL, /* accept_focus */ - XtVersion, /* version */ - NULL, /* callback_private */ - NULL, /* tm_table */ - NULL, /* query_geometry */ - NULL, /* display_accelerator */ - NULL, /* extension */ - }, - /* text_src */ - { - Read, /* Read */ - Replace, /* Replace */ - Scan, /* Scan */ - Search, /* Search */ - SetSelection, /* SetSelection */ - ConvertSelection, /* ConvertSelection */ - }, -}; - -WidgetClass textSrcObjectClass = (WidgetClass)&textSrcClassRec; - -static XrmQuark QRead, QAppend, QEdit; -#ifndef OLDXAW -static char *SrcNL = "\n"; -static wchar_t SrcWNL[2]; -#endif - -/* - * Implementation - */ -static void -XawTextSrcClassInitialize(void) -{ - XawInitializeWidgetSet(); - -#ifndef OLDXAW - SrcWNL[0] = _Xaw_atowc(XawLF); - SrcWNL[1] = 0; -#endif - QRead = XrmPermStringToQuark(XtEtextRead); - QAppend = XrmPermStringToQuark(XtEtextAppend); - QEdit = XrmPermStringToQuark(XtEtextEdit); - XtAddConverter(XtRString, XtREditMode, CvtStringToEditMode, NULL, 0); - XtSetTypeConverter(XtREditMode, XtRString, CvtEditModeToString, NULL, 0, - XtCacheNone, NULL); -} - -static void -XawTextSrcClassPartInitialize(WidgetClass wc) -{ - TextSrcObjectClass t_src, superC; - - t_src = (TextSrcObjectClass)wc; - superC = (TextSrcObjectClass)t_src->object_class.superclass; - - /* - * We don't need to check for null super since we'll get to TextSrc - * eventually - */ - if (t_src->textSrc_class.Read == XtInheritRead) - t_src->textSrc_class.Read = superC->textSrc_class.Read; - - if (t_src->textSrc_class.Replace == XtInheritReplace) - t_src->textSrc_class.Replace = superC->textSrc_class.Replace; - - if (t_src->textSrc_class.Scan == XtInheritScan) - t_src->textSrc_class.Scan = superC->textSrc_class.Scan; - - if (t_src->textSrc_class.Search == XtInheritSearch) - t_src->textSrc_class.Search = superC->textSrc_class.Search; - - if (t_src->textSrc_class.SetSelection == XtInheritSetSelection) - t_src->textSrc_class.SetSelection = superC->textSrc_class.SetSelection; - - if (t_src->textSrc_class.ConvertSelection == XtInheritConvertSelection) - t_src->textSrc_class.ConvertSelection = - superC->textSrc_class.ConvertSelection; -} - -/*ARGSUSED*/ -static void -XawTextSrcInitialize(Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ -#ifndef OLDXAW - TextSrcObject src = (TextSrcObject)cnew; - - if (src->textSrc.enable_undo) { - src->textSrc.undo = (XawTextUndo*)XtCalloc(1, sizeof(XawTextUndo)); - src->textSrc.undo->dir = XawsdLeft; - } - else - src->textSrc.undo = NULL; - src->textSrc.undo_state = False; - if (XtIsSubclass(XtParent(cnew), textWidgetClass)) { - src->textSrc.text = (WidgetList)XtMalloc(sizeof(Widget*)); - src->textSrc.text[0] = XtParent(cnew); - src->textSrc.num_text = 1; - } - else { - src->textSrc.text = NULL; - src->textSrc.num_text = 0; - } - - src->textSrc.anchors = NULL; - src->textSrc.num_anchors = 0; - (void)XawTextSourceAddAnchor(cnew, 0); -#endif /* OLDXAW */ -} - -static void -XawTextSrcDestroy(Widget w) -{ -#ifndef OLDXAW - TextSrcObject src = (TextSrcObject)w; - - if (src->textSrc.enable_undo) { - FreeUndoBuffer(src->textSrc.undo); - XtFree((char*)src->textSrc.undo); - } - XtFree((char*)src->textSrc.text); - - if (src->textSrc.num_anchors) { - XawTextEntity *entity, *enext; - int i; - - for (i = 0; i < src->textSrc.num_anchors; i++) { - entity = src->textSrc.anchors[i]->entities; - while (entity) { - enext = entity->next; - XtFree((XtPointer)entity); - entity = enext; - } - XtFree((XtPointer)src->textSrc.anchors[i]); - } - XtFree((XtPointer)src->textSrc.anchors); - } -#endif /* OLDXAW */ -} - -/*ARGSUSED*/ -static Boolean -XawTextSrcSetValues(Widget current, Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ -#ifndef OLDXAW - TextSrcObject oldtw = (TextSrcObject)current; - TextSrcObject newtw = (TextSrcObject)cnew; - - if (oldtw->textSrc.enable_undo != newtw->textSrc.enable_undo) { - if (newtw->textSrc.enable_undo) { - newtw->textSrc.undo = (XawTextUndo*) - XtCalloc(1, sizeof(XawTextUndo)); - newtw->textSrc.undo->dir = XawsdLeft; - } - else { - FreeUndoBuffer(newtw->textSrc.undo); - XtFree((char*)newtw->textSrc.undo); - newtw->textSrc.undo = NULL; - } - } - if (oldtw->textSrc.changed != newtw->textSrc.changed) { - if (newtw->textSrc.enable_undo) { - if (newtw->textSrc.undo->list) { - newtw->textSrc.undo->l_no_change = - newtw->textSrc.undo->list->left; - newtw->textSrc.undo->r_no_change = - newtw->textSrc.undo->list->right; - } - else - newtw->textSrc.undo->l_no_change = - newtw->textSrc.undo->r_no_change = NULL; - } - } -#endif /* OLDXAW */ - return (False); -} - -/* - * Function: - * Read - * - * Parameters: - * w - TextSrc Object - * pos - position of the text to retreive - * text - text block that will contain returned text - * length - maximum number of characters to read - * - * Description: - * This function reads the source. - * - * Returns: - * The character position following the retrieved text. - */ -/*ARGSUSED*/ -static XawTextPosition -Read(Widget w, XawTextPosition pos, XawTextBlock *text, int length) -{ - return ((XawTextPosition)0); -} - -/* - * Function: - * Replace - * - * Parameters: - * src - Text Source Object - * startPos - ends of text that will be removed - * endPos - "" - * text - new text to be inserted into buffer at startPos - * - * Description: - * Replaces a block of text with new text. - */ -/*ARGSUSED*/ -static int -Replace(Widget w, XawTextPosition startPos, XawTextPosition endPos, - XawTextBlock *text) -{ - return (XawEditError); -} - -/* - * Function: - * Scan - * - * Parameters: - * w - TextSrc Object - * position - position to start scanning - * type - type of thing to scan for - * dir - direction to scan - * count - which occurance if this thing to search for - * include - whether or not to include the character found in - * the position that is returned - * - * Description: - * Scans the text source for the number and type of item specified. - */ -/*ARGSUSED*/ -static XawTextPosition -Scan(Widget w, XawTextPosition position, XawTextScanType type, - XawTextScanDirection dir, int count, Bool include) -{ - return ((XawTextPosition)0); -} - -/* - * Function: - * Search - * - * Parameters: - * w - TextSource Object - * position - position to start searching - * dir - direction to search - * text - the text block to search for - * - * Description: - * Searchs the text source for the text block passed - */ -/*ARGSUSED*/ -static XawTextPosition -Search(Widget w, XawTextPosition position, XawTextScanDirection dir, - XawTextBlock *text) -{ - return (XawTextSearchError); -} - -/*ARGSUSED*/ -static Boolean -ConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type, - XtPointer *value, unsigned long *length, int *format) -{ - return (False); -} - -/*ARGSUSED*/ -static void -SetSelection(Widget w, XawTextPosition left, XawTextPosition right, - Atom selection) -{ -} - -/*ARGSUSED*/ -static void -CvtStringToEditMode(XrmValuePtr args, Cardinal *num_args, - XrmValuePtr fromVal, XrmValuePtr toVal) -{ - static XawTextEditType editType; - XrmQuark q; - char name[7]; - - XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); - q = XrmStringToQuark(name); - - if (q == QRead) - editType = XawtextRead; - else if (q == QAppend) - editType = XawtextAppend; - else if (q == QEdit) - editType = XawtextEdit; - else { - toVal->size = 0; - toVal->addr = NULL; - XtStringConversionWarning((char *)fromVal->addr, XtREditMode); - } - toVal->size = sizeof(XawTextEditType); - toVal->addr = (XPointer)&editType; -} - -/*ARGSUSED*/ -static Boolean -CvtEditModeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, - XrmValuePtr fromVal, XrmValuePtr toVal, - XtPointer *data) -{ - static String buffer; - Cardinal size; - - switch (*(XawTextEditType *)fromVal->addr) { - case XawtextRead: - buffer = XtEtextRead; - break; - case XawtextAppend: - buffer = XtEtextAppend; - break; - case XawtextEdit: - buffer = XtEtextEdit; - break; - default: - XawTypeToStringWarning(dpy, XtREditMode); - toVal->addr = NULL; - toVal->size = 0; - return (False); - } - - size = strlen(buffer) + 1; - if (toVal->addr != NULL) { - if (toVal->size < size) { - toVal->size = size; - return (False); - } - strcpy((char *)toVal->addr, buffer); - } - else - toVal->addr = (XPointer)buffer; - toVal->size = sizeof(String); - - return (True); -} - -#ifndef OLDXAW -Bool -_XawTextSourceNewLineAtEOF(Widget w) -{ - TextSrcObject src = (TextSrcObject)w; - XawTextBlock text; - - text.firstPos = 0; - if ((text.format = src->textSrc.text_format) == XawFmt8Bit) - text.ptr = SrcNL; - else - text.ptr = (char*)SrcWNL; - text.length = 1; - - return (XawTextSourceSearch(w, XawTextSourceScan(w, 0, XawstAll, - XawsdRight, 1, True) - 1, - XawsdRight, &text) != XawTextSearchError); -} - -void -_XawSourceAddText(Widget source, Widget text) -{ - TextSrcObject src = (TextSrcObject)source; - Bool found = False; - Cardinal i; - - for (i = 0; i < src->textSrc.num_text; i++) - if (src->textSrc.text[i] == text) { - found = True; - break; - } - - if (!found) { - src->textSrc.text = (WidgetList) - XtRealloc((char*)src->textSrc.text, - sizeof(Widget) * (src->textSrc.num_text + 1)); - src->textSrc.text[src->textSrc.num_text++] = text; - } -} - -void -_XawSourceRemoveText(Widget source, Widget text, Bool destroy) -{ - TextSrcObject src = (TextSrcObject)source; - Bool found = False; - Cardinal i; - - if (src == NULL) - return; - - for (i = 0; i < src->textSrc.num_text; i++) - if (src->textSrc.text[i] == text) { - found = True; - break; - } - - if (found) { - if (--src->textSrc.num_text == 0) { - if (destroy) { - XtDestroyWidget(source); - return; - } - else { - XtFree((char*)src->textSrc.text); - src->textSrc.text = NULL; /* for realloc "magic" */ - } - } - else if (i < src->textSrc.num_text) - memmove(&src->textSrc.text[i], &src->textSrc.text[i + 1], - sizeof(Widget) * (src->textSrc.num_text - i)); - } -} -#endif /* OLDXAW */ - -/* - * Function: - * XawTextSourceRead - * - * Parameters: - * w - TextSrc Object - * pos - position of the text to retrieve - * text - text block that will contain returned text (return) - * length - maximum number of characters to read - * - * Description: - * This function reads the source. - * - * Returns: - * The number of characters read into the buffer - */ -XawTextPosition -XawTextSourceRead(Widget w, XawTextPosition pos, XawTextBlock *text, - int length) -{ - TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; - - return ((*cclass->textSrc_class.Read)(w, pos, text, length)); -} - -#ifndef OLDXAW -static void -TellSourceChanged(TextSrcObject src, XawTextPosition left, - XawTextPosition right, XawTextBlock *block, int lines) -{ - Cardinal i; - - for (i = 0; i < src->textSrc.num_text; i++) - _XawTextSourceChanged(src->textSrc.text[i], left, right, block, lines); -} - -/* - * This function is required because there is no way to diferentiate - * if the first erase was generated by a backward-kill-char and the - * second by a forward-kill-char (or vice-versa) from XawTextSourceReplace. - * It is only possible to diferentiate after the second character is - * killed, but then, it is too late. - */ -void -_XawSourceSetUndoErase(TextSrcObject src, int value) -{ - if (src && src->textSrc.enable_undo) - src->textSrc.undo->erase = value; -} - -/* - * To diferentiate insert-char's separeted by cursor movements. - */ -void -_XawSourceSetUndoMerge(TextSrcObject src, Bool state) -{ - if (src && src->textSrc.enable_undo) - src->textSrc.undo->merge += state ? 1 : -1; -} -#endif /* OLDXAW */ - -/* - * Public Functions - */ -/* - * Function: - * XawTextSourceReplace - * - * Parameters: - * src - Text Source Object - * startPos - ends of text that will be removed - * endPos - "" - * text - new text to be inserted into buffer at startPos - * - * Description: - * Replaces a block of text with new text. - * - * Returns: - * XawEditError or XawEditDone. - */ -/*ARGSUSED*/ -int -XawTextSourceReplace(Widget w, XawTextPosition left, - XawTextPosition right, XawTextBlock *block) -{ - TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; -#ifndef OLDXAW - TextSrcObject src = (TextSrcObject)w; - XawTextUndoBuffer *l_state, *r_state; - XawTextUndoList *undo; - Bool enable_undo; - XawTextPosition start, end; - int i, error, lines = 0; - - if (src->textSrc.edit_mode == XawtextRead) - return (XawEditError); - - enable_undo = src->textSrc.enable_undo && src->textSrc.undo_state == False; - if (enable_undo) { - unsigned size, total; - - if (src->textSrc.undo->l_save) { - l_state = src->textSrc.undo->l_save; - src->textSrc.undo->l_save = NULL; - } - else - l_state = XtNew(XawTextUndoBuffer); - l_state->refcount = 1; - l_state->position = left; - if (left < right) { - Widget ctx = NULL; - - for (i = 0; i < src->textSrc.num_text; i++) - if (XtIsSubclass(src->textSrc.text[i], textWidgetClass)) { - ctx = src->textSrc.text[i]; - break; - } - l_state->buffer = _XawTextGetText((TextWidget)ctx, left, right); - l_state->length = right - left; - } - else { - l_state->length = 0; - l_state->buffer = NULL; - } - l_state->format = src->textSrc.text_format; - if (l_state->length == 1) { - if (l_state->format == XawFmtWide && - *(wchar_t*)l_state->buffer == *SrcWNL) { - XtFree(l_state->buffer); - l_state->buffer = (char*)SrcWNL; - } - else if (*l_state->buffer == '\n') { - XtFree(l_state->buffer); - l_state->buffer = SrcNL; - } - } - - if (src->textSrc.undo->r_save) { - r_state = src->textSrc.undo->r_save; - src->textSrc.undo->r_save = NULL; - } - else - r_state = XtNew(XawTextUndoBuffer); - r_state->refcount = 1; - r_state->position = left; - r_state->format = block->format; - size = block->format == XawFmtWide ? sizeof(wchar_t) : sizeof(char); - total = size * block->length; - r_state->length = block->length; - r_state->buffer = NULL; - if (total == size) { - if (r_state->format == XawFmtWide && - *(wchar_t*)block->ptr == *SrcWNL) - r_state->buffer = (char*)SrcWNL; - else if (*block->ptr == '\n') - r_state->buffer = SrcNL; - } - if (total && !r_state->buffer) { - r_state->buffer = XtMalloc(total); - memcpy(r_state->buffer, block->ptr, total); - } - - if (src->textSrc.undo->u_save) { - undo = src->textSrc.undo->u_save; - src->textSrc.undo->u_save = NULL; - } - else - undo = XtNew(XawTextUndoList); - undo->left = l_state; - undo->right = r_state; - undo->undo = src->textSrc.undo->list; - undo->redo = NULL; - } - else { - undo = NULL; - l_state = r_state = NULL; - } - -#define LARGE_VALUE 262144 /* 256 K */ - /* optimization, to avoid long delays recalculating the line number - * when editing huge files - */ - if (left > LARGE_VALUE) { - start = XawTextSourceScan(w, left, XawstEOL, XawsdLeft, 2, False); - for (i = 0; i < src->textSrc.num_text; i++) { - TextWidget tw = (TextWidget)src->textSrc.text[i]; - - if (left <= tw->text.lt.top && - left + block->length - (right - left) > tw->text.lt.top) - _XawTextBuildLineTable(tw, start, False); - } - } -#undef LARGE_VALUE - - start = left; - end = right; - while (start < end) { - start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True); - if (start <= end) { - --lines; - if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) { - lines += !_XawTextSourceNewLineAtEOF(w); - break; - } - } - } -#else - int error; -#endif /* OLDXAW */ - - error = (*cclass->textSrc_class.Replace)(w, left, right, block); - -#ifndef OLDXAW - if (error != XawEditDone) { - if (enable_undo) { - if (l_state->buffer) { - if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL) - XtFree(l_state->buffer); - l_state->buffer = NULL; - } - src->textSrc.undo->l_save = l_state; - if (r_state->buffer) { - if (r_state->buffer != SrcNL && r_state->buffer != (char*)SrcWNL) - XtFree(r_state->buffer); - r_state->buffer = NULL; - } - src->textSrc.undo->r_save = r_state; - - src->textSrc.undo->u_save = undo; - } - } - else if (enable_undo) { - XawTextUndoList *list = src->textSrc.undo->list; - XawTextUndoBuffer *unl, *lnl; - int erase = undo->right->length == 0 && undo->left->length == 1 && list - && list->right->length == 0; - - if (erase) { - erase = list->left->position - 1 == undo->left->position ? -1 : - list->left->position == undo->left->position ? 1 : 0; - if (src->textSrc.undo->erase && erase != src->textSrc.undo->erase) - erase = 0; - else - src->textSrc.undo->erase = erase; - } - - if (erase) { - unl = l_state; - lnl = list->left; - } - else { - unl = r_state; - lnl = list ? list->right : NULL; - } - - /* Try to merge the undo buffers */ - if (src->textSrc.undo->merge > 0 && ((erase || - (list && ((list->left->length == 0 && undo->left->length == 0) || - (list->left->length == list->right->length && - undo->left->length == 1)) && - undo->right->length == 1 && - list->right->position + list->right->length - == undo->right->position)) - && src->textSrc.undo->pointer == list - && unl->format == list->right->format - && ((unl->format == XawFmt8Bit && unl->buffer[0] != XawLF) || - (unl->format == XawFmtWide && - *(wchar_t*)(unl->buffer) != _Xaw_atowc(XawLF))) - && ((lnl->format == XawFmt8Bit && lnl->buffer[0] != XawLF) || - (lnl->format == XawFmtWide && - *(wchar_t*)(lnl->buffer) != _Xaw_atowc(XawLF))))) { - unsigned size = lnl->format == XawFmtWide ? - sizeof(wchar_t) : sizeof(char); - - if (!erase) { - list->right->buffer = XtRealloc(list->right->buffer, - (list->right->length + 1) * size); - memcpy(list->right->buffer + list->right->length * size, - undo->right->buffer, size); - ++list->right->length; - XtFree(r_state->buffer); - } - else if (erase < 0) { - --list->left->position; - --list->right->position; - } - - src->textSrc.undo->l_save = l_state; - src->textSrc.undo->r_save = r_state; - src->textSrc.undo->u_save = undo; - - if (list->left->length) { - list->left->buffer = XtRealloc(list->left->buffer, - (list->left->length + 1) * size); - if (erase >= 0) - memcpy(list->left->buffer + list->left->length * size, - undo->left->buffer, size); - else { - /* use memmove, since strings overlap */ - memmove(list->left->buffer + size, list->left->buffer, - list->left->length * size); - memcpy(list->left->buffer, undo->left->buffer, size); - } - ++list->left->length; - if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL) - XtFree(l_state->buffer); - } - - if (src->textSrc.undo->num_list >= UNDO_DEPTH) - UndoGC(src->textSrc.undo); - } - else { - src->textSrc.undo->undo = (XawTextUndoBuffer**) - XtRealloc((char*)src->textSrc.undo->undo, - (2 + src->textSrc.undo->num_undo) - * sizeof(XawTextUndoBuffer)); - src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = l_state; - src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = r_state; - - if (src->textSrc.undo->list) - src->textSrc.undo->list->redo = undo; - else - src->textSrc.undo->head = undo; - - src->textSrc.undo->merge = l_state->length <= 1 && - r_state->length <= 1; - - src->textSrc.undo->list = src->textSrc.undo->pointer = - src->textSrc.undo->end_mark = undo; - - if (++src->textSrc.undo->num_list >= UNDO_DEPTH) - UndoGC(src->textSrc.undo); - } - src->textSrc.undo->dir = XawsdLeft; - if (!src->textSrc.changed) { - src->textSrc.undo->l_no_change = src->textSrc.undo->list->right; - src->textSrc.undo->r_no_change = src->textSrc.undo->list->left; - src->textSrc.changed = True; - } - } - else if (!src->textSrc.enable_undo) - src->textSrc.changed = True; - - if (error == XawEditDone) { - XawTextPropertyInfo info; - XawTextAnchor *anchor; - - /* find anchor and index */ - /* XXX index (i) could be returned by XawTextSourceFindAnchor - * or similar function, to speed up */ - if ((anchor = XawTextSourceFindAnchor(w, left))) { - XawTextEntity *eprev, *entity, *enext; - XawTextPosition offset = 0, diff = block->length - (right - left); - - for (i = 0; i < src->textSrc.num_anchors; i++) - if (src->textSrc.anchors[i] == anchor) - break; - if (anchor->cache && anchor->position + anchor->cache->offset + - anchor->cache->length <= left) - eprev = entity = anchor->cache; - else - eprev = entity = anchor->entities; - while (entity) { - offset = anchor->position + entity->offset; - - if (offset > left) - break; - if (offset + entity->length > left) - break; - - eprev = entity; - entity = entity->next; - } - - /* try to do the right thing here (and most likely correct), but - * other code needs to check what was done */ - - /* adjust entity length */ - if (entity && offset <= left) { - if (offset + entity->length < right) - entity->length = left - offset + block->length; - else - entity->length += diff; - - if (entity->length == 0) { - enext = entity->next; - eprev->next = enext; - anchor->cache = NULL; - XtFree((XtPointer)entity); - if (entity == anchor->entities) { - if ((anchor->entities = enext) == NULL) { - eprev = NULL; - anchor = XawTextSourceRemoveAnchor(w, anchor); - entity = anchor ? anchor->entities : NULL; - } - else - eprev = entity = enext; - } - else - entity = enext; - } - else { - eprev = entity; - entity = entity->next; - } - } - - while (anchor) { - while (entity) { - offset = anchor->position + entity->offset + entity->length; - - if (offset > right) { - entity->length = XawMin(entity->length, offset - right); - goto exit_anchor_loop; - } - - enext = entity->next; - if (eprev) - eprev->next = enext; - XtFree((XtPointer)entity); - anchor->cache = NULL; - if (entity == anchor->entities) { - eprev = NULL; - if ((anchor->entities = enext) == NULL) { - if (i == 0) - ++i; - else if (i < --src->textSrc.num_anchors) { - memmove(&src->textSrc.anchors[i], - &src->textSrc.anchors[i + 1], - (src->textSrc.num_anchors - i) * - sizeof(XawTextAnchor*)); - XtFree((XtPointer)anchor); - } - if (i >= src->textSrc.num_anchors) { - anchor = NULL; - entity = NULL; - break; - } - anchor = src->textSrc.anchors[i]; - entity = anchor->entities; - continue; - } - } - entity = enext; - } - if (i + 1 < src->textSrc.num_anchors) { - anchor = src->textSrc.anchors[++i]; - entity = anchor->entities; - eprev = NULL; - } - else { - anchor = NULL; - break; - } - eprev = NULL; - } - -exit_anchor_loop: - if (anchor) { - XawTextAnchor *aprev; - - if (anchor->position >= XawMax(right, left + block->length)) - anchor->position += diff; - else if (anchor->position > left && - (aprev = XawTextSourcePrevAnchor(w, anchor))) { - XawTextPosition tmp = anchor->position - aprev->position; - - if (diff) { - while (entity) { - entity->offset += diff; - entity = entity->next; - } - } - entity = anchor->entities; - while (entity) { - entity->offset += tmp; - entity = entity->next; - } - if ((entity = aprev->entities) == NULL) - aprev->entities = anchor->entities; - else { - while (entity->next) - entity = entity->next; - entity->next = anchor->entities; - } - anchor->entities = NULL; - (void)XawTextSourceRemoveAnchor(w, anchor); - --i; - } - else if (diff) { - while (entity) { - entity->offset += diff; - entity = entity->next; - } - } - } - - if (diff) { - /* The first anchor is never removed, and should - * have position 0. - * i should be -1 if attempted to removed the first - * anchor, what can be caused when removing a chunk - * of text of the first entity. - * */ - if (++i == 0) { - anchor = src->textSrc.anchors[0]; - eprev = entity = anchor->entities; - while (entity) { - enext = entity->next; - if (entity->offset + entity->length <= -diff) - XtFree((XtPointer)entity); - else - break; - entity = enext; - } - if (eprev != entity) { - anchor->cache = NULL; - if ((anchor->entities = entity) != NULL) { - if ((entity->offset += diff) < 0) { - entity->length += entity->offset; - entity->offset = 0; - } - } - } - ++i; - } - for (; i < src->textSrc.num_anchors; i++) - src->textSrc.anchors[i]->position += diff; - } - } - - start = left; - end = start + block->length; - while (start < end) { - start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True); - if (start <= end) { - ++lines; - if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) { - lines -= !_XawTextSourceNewLineAtEOF(w); - break; - } - } - } - - info.left = left; - info.right = right; - info.block = block; - XtCallCallbacks(w, XtNpropertyCallback, &info); - - TellSourceChanged(src, left, right, block, lines); - /* Call callbacks, we have changed the buffer */ - XtCallCallbacks(w, XtNcallback, - (XtPointer)((long)src->textSrc.changed)); - } - -#endif /* OLDXAW */ - return (error); -} - -#ifndef OLDXAW -Bool -_XawTextSrcUndo(TextSrcObject src, XawTextPosition *insert_pos) -{ - static wchar_t wnull = 0; - XawTextBlock block; - XawTextUndoList *list, *nlist; - XawTextUndoBuffer *l_state, *r_state; - Boolean changed = src->textSrc.changed; - - if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo) - return (False); - - list = src->textSrc.undo->pointer; - - if (src->textSrc.undo->dir == XawsdLeft) { - l_state = list->right; - r_state = list->left; - } - else { - l_state = list->left; - r_state = list->right; - } - - if (src->textSrc.undo->l_no_change == l_state - && src->textSrc.undo->r_no_change == r_state) - src->textSrc.changed = False; - else - src->textSrc.changed = True; - - block.firstPos = 0; - block.length = r_state->length; - block.ptr = r_state->buffer ? r_state->buffer : (char*)&wnull; - block.format = r_state->format; - - src->textSrc.undo_state = True; - if (XawTextSourceReplace((Widget)src, l_state->position, l_state->position - + l_state->length, &block) != XawEditDone) { - src->textSrc.undo_state = False; - src->textSrc.changed = changed; - return (False); - } - src->textSrc.undo_state = False; - - ++l_state->refcount; - ++r_state->refcount; - nlist = XtNew(XawTextUndoList); - nlist->left = l_state; - nlist->right = r_state; - nlist->undo = src->textSrc.undo->list; - nlist->redo = NULL; - - if (list == src->textSrc.undo->list) - src->textSrc.undo->end_mark = nlist; - - if (src->textSrc.undo->dir == XawsdLeft) { - if (list->undo == NULL) - src->textSrc.undo->dir = XawsdRight; - else - list = list->undo; - } - else { - if (list->redo == NULL || list->redo == src->textSrc.undo->end_mark) - src->textSrc.undo->dir = XawsdLeft; - else - list = list->redo; - } - *insert_pos = r_state->position + r_state->length; - src->textSrc.undo->pointer = list; - src->textSrc.undo->list->redo = nlist; - src->textSrc.undo->list = nlist; - src->textSrc.undo->merge = src->textSrc.undo->erase = 0; - - if (++src->textSrc.undo->num_list >= UNDO_DEPTH) - UndoGC(src->textSrc.undo); - - return (True); -} - -Bool -_XawTextSrcToggleUndo(TextSrcObject src) -{ - if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo) - return (False); - - if (src->textSrc.undo->pointer != src->textSrc.undo->list) { - if (src->textSrc.undo->dir == XawsdLeft) { - if (src->textSrc.undo->pointer->redo - && (src->textSrc.undo->pointer->redo - != src->textSrc.undo->end_mark)) { - src->textSrc.undo->pointer = src->textSrc.undo->pointer->redo; - src->textSrc.undo->dir = XawsdRight; - } - } - else { - if (src->textSrc.undo->pointer->undo - && (src->textSrc.undo->pointer != src->textSrc.undo->head)) { - src->textSrc.undo->pointer = src->textSrc.undo->pointer->undo; - src->textSrc.undo->dir = XawsdLeft; - } - } - } - - return (True); -} - -static void -FreeUndoBuffer(XawTextUndo *undo) -{ - unsigned i; - XawTextUndoList *head, *del; - - for (i = 0; i < undo->num_undo; i++) { - if (undo->undo[i]->buffer && undo->undo[i]->buffer != SrcNL && - undo->undo[i]->buffer != (char*)SrcWNL) - XtFree(undo->undo[i]->buffer); - XtFree((char*)undo->undo[i]); - } - XtFree((char*)undo->undo); - head = undo->head; - - del = head; - while (head) { - head = head->redo; - XtFree((char*)del); - del = head; - } - - if (undo->l_save) { - XtFree((char*)undo->l_save); - undo->l_save = NULL; - } - if (undo->r_save) { - XtFree((char*)undo->r_save); - undo->r_save = NULL; - } - if (undo->u_save) { - XtFree((char*)undo->u_save); - undo->u_save = NULL; - } - - undo->list = undo->pointer = undo->head = undo->end_mark = NULL; - undo->l_no_change = undo->r_no_change = NULL; - undo->undo = NULL; - undo->dir = XawsdLeft; - undo->num_undo = undo->num_list = undo->erase = undo->merge = 0; -} - -static void -UndoGC(XawTextUndo *undo) -{ - unsigned i; - XawTextUndoList *head = undo->head, *redo = head->redo; - - if (head == undo->pointer || head == undo->end_mark - || undo->l_no_change == NULL - || head->left == undo->l_no_change || head->right == undo->l_no_change) - return; - - undo->head = redo; - redo->undo = NULL; - - --head->left->refcount; - if (--head->right->refcount == 0) { - for (i = 0; i < undo->num_undo; i+= 2) - if (head->left == undo->undo[i] || head->left == undo->undo[i+1]) { - if (head->left == undo->undo[i+1]) { - XawTextUndoBuffer *tmp = redo->left; - - redo->left = redo->right; - redo->right = tmp; - } - if (head->left->buffer && head->left->buffer != SrcNL && - head->left->buffer != (char*)SrcWNL) - XtFree(head->left->buffer); - XtFree((char*)head->left); - if (head->right->buffer && head->right->buffer != SrcNL && - head->right->buffer != (char*)SrcWNL) - XtFree(head->right->buffer); - XtFree((char*)head->right); - - undo->num_undo -= 2; - memmove(&undo->undo[i], &undo->undo[i + 2], - (undo->num_undo - i) * sizeof(XawTextUndoBuffer*)); - break; - } - } - XtFree((char*)head); - --undo->num_list; -} -#endif /* OLDXAW */ - -/* - * Function: - * XawTextSourceScan - * - * Parameters: - * w - TextSrc Object - * position - position to start scanning - * type - type of thing to scan for - * dir - direction to scan - * count - which occurance if this thing to search for - * include - whether or not to include the character found in - * the position that is returned. - * - * Description: - * Scans the text source for the number and type of item specified. - * - * Returns: - * The position of the text - */ -XawTextPosition -XawTextSourceScan(Widget w, XawTextPosition position, -#if NeedWidePrototypes - int type, int dir, int count, int include -#else - XawTextScanType type, XawTextScanDirection dir, - int count, Boolean include -#endif -) -{ - TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; - - return ((*cclass->textSrc_class.Scan) - (w, position, type, dir, count, include)); -} - -/* - * Function: - * XawTextSourceSearch - * - * Parameters: - * w - TextSource Object - * position - position to start scanning - * dir - direction to scan - * text - the text block to search for. - * - * Returns: - * The position of the text we are searching for or XawTextSearchError. - * - * Description: - * Searchs the text source for the text block passed - */ -XawTextPosition -XawTextSourceSearch(Widget w, XawTextPosition position, -#if NeedWidePrototypes - int dir, -#else - XawTextScanDirection dir, -#endif - XawTextBlock *text) -{ - TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; - - return ((*cclass->textSrc_class.Search)(w, position, dir, text)); -} - -/* - * Function: - * XawTextSourceConvertSelection - * - * Parameters: - * w - TextSrc object - * selection - current selection atom - * target - current target atom - * type - type to conver the selection to - * value - return value that has been converted - * length - "" - * format - format of the returned value - * - * Returns: - * True if the selection has been converted - */ -Boolean -XawTextSourceConvertSelection(Widget w, Atom *selection, Atom *target, - Atom *type, XtPointer *value, - unsigned long *length, int *format) -{ - TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; - - return((*cclass->textSrc_class.ConvertSelection) - (w, selection, target, type, value, length, format)); -} - -/* - * Function: - * XawTextSourceSetSelection - * - * Parameters: - * w - TextSrc object - * left - bounds of the selection - * rigth - "" - * selection - selection atom - * - * Description: - * Allows special setting of the selection. - */ -void -XawTextSourceSetSelection(Widget w, XawTextPosition left, - XawTextPosition right, Atom selection) -{ - TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; - - (*cclass->textSrc_class.SetSelection)(w, left, right, selection); -} - -/* - * External Functions for Multi Text - */ -/* - * TextFormat(): - * returns the format of text: FMT8BIT or FMTWIDE - */ -XrmQuark -_XawTextFormat(TextWidget tw) -{ - return (((TextSrcObject)(tw->text.source))->textSrc.text_format); -} - -/* _XawTextWCToMB(): - * Convert the wchar string to external encoding - * The caller is responsible for freeing both the source and ret string - * - * wstr - source wchar string - * len_in_out - lengh of string. - * As In, length of source wchar string, measured in wchar - * As Out, length of returned string - */ -char * -_XawTextWCToMB(Display *d, wchar_t *wstr, int *len_in_out) -{ - XTextProperty textprop; - - if (XwcTextListToTextProperty(d, (wchar_t**)&wstr, 1, - XTextStyle, &textprop) < Success) { - XtWarningMsg("convertError", "textSource", "XawError", - "Non-character code(s) in buffer.", NULL, NULL); - *len_in_out = 0; - return (NULL); - } - *len_in_out = textprop.nitems; - - return ((char *)textprop.value); -} - -/* _XawTextMBToWC(): - * Convert the string to internal processing codeset WC. - * The caller is responsible for freeing both the source and ret string. - * - * str - source string - * len_in_out - lengh of string - * As In, it is length of source string - * As Out, it is length of returned string, measured in wchar - */ -wchar_t * -_XawTextMBToWC(Display *d, char *str, int *len_in_out) -{ - XTextProperty textprop; - char *buf; - wchar_t **wlist, *wstr; - int count; - - if (*len_in_out == 0) - return (NULL); - - buf = XtMalloc(*len_in_out + 1); - - strncpy(buf, str, *len_in_out); - *(buf + *len_in_out) = '\0'; - if (XmbTextListToTextProperty(d, &buf, 1, XTextStyle, &textprop) != Success) { - XtWarningMsg("convertError", "textSource", "XawError", - "No Memory, or Locale not supported.", NULL, NULL); - XtFree(buf); - *len_in_out = 0; - return (NULL); - } - - XtFree(buf); - if (XwcTextPropertyToTextList(d, &textprop, - (wchar_t***)&wlist, &count) != Success) { - XtWarningMsg("convertError", "multiSourceCreate", "XawError", - "Non-character code(s) in source.", NULL, NULL); - *len_in_out = 0; - return (NULL); - } - wstr = wlist[0]; - *len_in_out = wcslen(wstr); - XtFree((XtPointer)wlist); - - return (wstr); -} - -#ifndef OLDXAW -static int -qcmp_anchors(_Xconst void *left, _Xconst void *right) -{ - return ((*(XawTextAnchor**)left)->position - - (*(XawTextAnchor**)right)->position); -} - -XawTextAnchor * -XawTextSourceAddAnchor(Widget w, XawTextPosition position) -{ - TextSrcObject src = (TextSrcObject)w; - XawTextAnchor *anchor, *panchor; - - if ((panchor = XawTextSourceFindAnchor(w, position)) != NULL) { - XawTextEntity *pentity, *entity; - - if (position - panchor->position < ANCHORS_DIST) - return (panchor); - - if (panchor->cache && panchor->position + panchor->cache->offset + - panchor->cache->length < position) - pentity = entity = panchor->cache; - else - pentity = entity = panchor->entities; - - while (entity && panchor->position + entity->offset + - entity->length < position) { - pentity = entity; - entity = entity->next; - } - if (entity) { - XawTextPosition diff; - - if (panchor->position + entity->offset < position) - position = panchor->position + entity->offset; - - if (position == panchor->position) - return (panchor); - - anchor = XtNew(XawTextAnchor); - diff = position - panchor->position; - - panchor->cache = NULL; - anchor->entities = entity; - if (pentity != entity) - pentity->next = NULL; - else - panchor->entities = NULL; - while (entity) { - entity->offset -= diff; - entity = entity->next; - } - } - else { - anchor = XtNew(XawTextAnchor); - anchor->entities = NULL; - } - } - else { - anchor = XtNew(XawTextAnchor); - anchor->entities = NULL; - } - - anchor->position = position; - anchor->cache = NULL; - - src->textSrc.anchors = (XawTextAnchor**) - XtRealloc((XtPointer)src->textSrc.anchors, sizeof(XawTextAnchor*) * - (src->textSrc.num_anchors + 1)); - src->textSrc.anchors[src->textSrc.num_anchors++] = anchor; - qsort((void*)src->textSrc.anchors, src->textSrc.num_anchors, - sizeof(XawTextAnchor*), qcmp_anchors); - - return (anchor); -} - -XawTextAnchor * -XawTextSourceFindAnchor(Widget w, XawTextPosition position) -{ - TextSrcObject src = (TextSrcObject)w; - int i = 0, left, right, nmemb = src->textSrc.num_anchors; - XawTextAnchor *anchor, **anchors = src->textSrc.anchors; - - left = 0; - right = nmemb - 1; - while (left <= right) { - anchor = anchors[i = (left + right) >> 1]; - if (anchor->position == position) - return (anchor); - else if (position < anchor->position) - right = i - 1; - else - left = i + 1; - } - - if (nmemb) - return (right < 0 ? anchors[0] : anchors[right]); - - return (NULL); -} - -Bool -XawTextSourceAnchorAndEntity(Widget w, XawTextPosition position, - XawTextAnchor **anchor_return, - XawTextEntity **entity_return) -{ - XawTextAnchor *anchor = XawTextSourceFindAnchor(w, position); - XawTextEntity *pentity, *entity; - XawTextPosition offset; - Bool next_anchor = True, retval = False; - - if (anchor->cache && anchor->position + anchor->cache->offset + - anchor->cache->length <= position) - pentity = entity = anchor->cache; - else - pentity = entity = anchor->entities; - while (entity) { - offset = anchor->position + entity->offset; - - if (offset > position) { - retval = next_anchor = False; - break; - } - if (offset + entity->length > position) { - retval = True; - next_anchor = False; - break; - } - pentity = entity; - entity = entity->next; - } - - if (next_anchor) { - *anchor_return = anchor = XawTextSourceNextAnchor(w, anchor); - *entity_return = anchor ? anchor->entities : NULL; - } - else { - *anchor_return = anchor; - *entity_return = retval ? entity : pentity; - } - - if (*anchor_return) - (*anchor_return)->cache = *entity_return; - - return (retval); -} - -XawTextAnchor * -XawTextSourceNextAnchor(Widget w, XawTextAnchor *anchor) -{ - int i; - TextSrcObject src = (TextSrcObject)w; - - for (i = 0; i < src->textSrc.num_anchors - 1; i++) - if (src->textSrc.anchors[i] == anchor) - return (src->textSrc.anchors[i + 1]); - - return (NULL); -} - -XawTextAnchor * -XawTextSourcePrevAnchor(Widget w, XawTextAnchor *anchor) -{ - int i; - TextSrcObject src = (TextSrcObject)w; - - for (i = src->textSrc.num_anchors - 1; i > 0; i--) - if (src->textSrc.anchors[i] == anchor) - return (src->textSrc.anchors[i - 1]); - - return (NULL); -} - -XawTextAnchor * -XawTextSourceRemoveAnchor(Widget w, XawTextAnchor *anchor) -{ - int i; - TextSrcObject src = (TextSrcObject)w; - - for (i = 0; i < src->textSrc.num_anchors; i++) - if (src->textSrc.anchors[i] == anchor) - break; - - if (i == 0) - return (src->textSrc.num_anchors > 1 ? src->textSrc.anchors[1] : NULL); - - if (i < src->textSrc.num_anchors) { - XtFree((XtPointer)anchor); - if (i < --src->textSrc.num_anchors) { - memmove(&src->textSrc.anchors[i], - &src->textSrc.anchors[i + 1], - (src->textSrc.num_anchors - i) * - sizeof(XawTextAnchor*)); - - return (src->textSrc.anchors[i]); - } - } - - return (NULL); -} - -XawTextEntity * -XawTextSourceAddEntity(Widget w, int type, int flags, XtPointer data, - XawTextPosition position, Cardinal length, - XrmQuark property) -{ - XawTextAnchor *next, *anchor = _XawTextSourceFindAnchor(w, position); - XawTextEntity *entity, *eprev; - - /* There is no support for zero length entities for now */ - if (length == 0) - return (NULL); - - if (anchor->cache && anchor->position + anchor->cache->offset + - anchor->cache->length <= position) - eprev = entity = anchor->cache; - else - eprev = entity = anchor->entities; - - while (entity && anchor->position + entity->offset + entity->length <= - position) { - eprev = entity; - entity = entity->next; - } - if (entity && anchor->position + entity->offset < position + length) { - fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n"); - return (NULL); - } - - next = XawTextSourceFindAnchor(w, position + length); - if (next && next != anchor) { - if ((entity = next->entities) != NULL) { - if (next->position + entity->offset < position + length) { - fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n"); - return (NULL); - } - } - if (position + length > next->position) { - XawTextPosition diff = position + length - next->position; - - next->position += diff; - entity = next->entities; - while (entity) { - entity->offset -= diff; - entity = entity->next; - } - entity = anchor->entities; - while (entity && entity->offset < 0) - entity = entity->next; - if (entity && entity->offset < 0) { - if (eprev) - eprev->next = next->entities; - else - anchor->entities = next->entities; - if ((next->entities = entity->next) == NULL) - (void)XawTextSourceRemoveAnchor(w, next); - entity->next = NULL; - - return (XawTextSourceAddEntity(w, type, flags, data, position, - length, property)); - } - } - } - - /* Automatically join sequential entities if possible */ - if (eprev && - anchor->position + eprev->offset + eprev->length == position && - eprev->property == property && eprev->type == type && - eprev->flags == flags && eprev->data == data) { - eprev->length += length; - return (eprev); - } - - entity = XtNew(XawTextEntity); - entity->type = type; - entity->flags = flags; - entity->data = data; - entity->offset = position - anchor->position; - entity->length = length; - entity->property = property; - - if (eprev == NULL) { - anchor->entities = entity; - entity->next = NULL; - anchor->cache = NULL; - } - else if (eprev->offset > entity->offset) { - anchor->cache = NULL; - anchor->entities = entity; - entity->next = eprev; - } - else { - anchor->cache = eprev; - entity->next = eprev->next; - eprev->next = entity; - } - - return (entity); -} - -void -XawTextSourceClearEntities(Widget w, XawTextPosition left, XawTextPosition right) -{ - XawTextAnchor *anchor = XawTextSourceFindAnchor(w, left); - XawTextEntity *entity, *eprev, *enext; - XawTextPosition offset; - int length; - - while (anchor && anchor->entities == NULL) - anchor = XawTextSourceRemoveAnchor(w, anchor); - - if (anchor == NULL || left >= right) - return; - - if (anchor->cache && anchor->position + anchor->cache->offset + - anchor->cache->length < left) - eprev = entity = anchor->cache; - else - eprev = entity = anchor->entities; - - /* find first entity before left position */ - while (anchor->position + entity->offset + entity->length < left) { - eprev = entity; - if ((entity = entity->next) == NULL) { - if ((anchor = XawTextSourceNextAnchor(w, anchor)) == NULL) - return; - if ((eprev = entity = anchor->entities) == NULL) { - fprintf(stderr, "Bad anchor found!\n"); - return; - } - } - } - - offset = anchor->position + entity->offset; - if (offset <= left) { - length = XawMin(entity->length, left - offset); - - if (length <= 0) { - enext = entity->next; - eprev->next = enext; - XtFree((XtPointer)entity); - anchor->cache = NULL; - if (entity == anchor->entities) { - eprev = NULL; - if ((anchor->entities = enext) == NULL) { - if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL) - return; - entity = anchor->entities; - } - else - entity = enext; - } - else - entity = enext; - } - else { - entity->length = length; - eprev = entity; - entity = entity->next; - } - } - - /* clean everything until right position is reached */ - while (anchor) { - while (entity) { - offset = anchor->position + entity->offset + entity->length; - - if (offset > right) { - anchor->cache = NULL; - entity->offset = XawMax(entity->offset, right - anchor->position); - entity->length = XawMin(entity->length, offset - right); - return; - } - - enext = entity->next; - if (eprev) - eprev->next = enext; - XtFree((XtPointer)entity); - if (entity == anchor->entities) { - eprev = anchor->cache = NULL; - if ((anchor->entities = enext) == NULL) { - if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL) - return; - entity = anchor->entities; - continue; - } - } - entity = enext; - } - if (anchor) - anchor->cache = NULL; - if ((anchor = XawTextSourceNextAnchor(w, anchor)) != NULL) - entity = anchor->entities; - eprev = NULL; - } -} - -/* checks the anchors up to position, and create an appropriate anchor - * at position, if required. - */ -XawTextAnchor * -_XawTextSourceFindAnchor(Widget w, XawTextPosition position) -{ - XawTextAnchor *anchor; - - anchor = XawTextSourceFindAnchor(w, position); - - position -= position % ANCHORS_DIST; - - if (position - anchor->position >= ANCHORS_DIST) - return (XawTextSourceAddAnchor(w, position)); - - return (anchor); -} -#endif +/* + +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Chris Peterson, MIT X Consortium. + * Much code taken from X11R3 String and Disk Sources. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "XawI18n.h" +#include "Private.h" + +#ifndef OLDXAW +#define UNDO_DEPTH 16384 + +#define ANCHORS_DIST 4096 /* default distance between anchors */ + +/* + * Types + */ +typedef struct { + XawTextPosition position; + char *buffer; + unsigned length; + unsigned refcount; + unsigned long format; +} XawTextUndoBuffer; + +typedef struct _XawTextUndoList XawTextUndoList; +struct _XawTextUndoList { + XawTextUndoBuffer *left, *right; + XawTextUndoList *undo, *redo; +}; + +struct _XawTextUndo { + XawTextUndoBuffer **undo; + unsigned num_undo; + XawTextUndoList *list, *pointer, *end_mark, *head; + unsigned num_list; + XawTextScanDirection dir; + XawTextUndoBuffer *l_save, *r_save; + XawTextUndoList *u_save; + XawTextUndoBuffer *l_no_change, *r_no_change; + int merge; + int erase; /* there are two types of erases */ +}; +#endif /* OLDXAW */ + +/* + * Class Methods + */ +static Boolean ConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*, + unsigned long*, int*); +static XawTextPosition Read(Widget, XawTextPosition, XawTextBlock*, int); +static int Replace(Widget, XawTextPosition, XawTextPosition, XawTextBlock*); +static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType, + XawTextScanDirection, int, Bool); +static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection, + XawTextBlock*); +static void SetSelection(Widget, XawTextPosition, XawTextPosition, Atom); +static void XawTextSrcClassInitialize(void); +static void XawTextSrcClassPartInitialize(WidgetClass); +static void XawTextSrcInitialize(Widget, Widget, ArgList, Cardinal*); +static void XawTextSrcDestroy(Widget); +static Boolean XawTextSrcSetValues(Widget, Widget, Widget, ArgList, Cardinal*); +/* + * Prototypes + */ +static void CvtStringToEditMode(XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr); +static Boolean CvtEditModeToString(Display*, XrmValuePtr, Cardinal*, + XrmValuePtr, XrmValuePtr, XtPointer*); +#ifndef OLDXAW +static void FreeUndoBuffer(XawTextUndo*); +static void UndoGC(XawTextUndo*); +static void TellSourceChanged(TextSrcObject, XawTextPosition, XawTextPosition, + XawTextBlock*, int); +Bool _XawTextSrcUndo(TextSrcObject, XawTextPosition*); +Bool _XawTextSrcToggleUndo(TextSrcObject); +XawTextAnchor *_XawTextSourceFindAnchor(Widget, XawTextPosition); + +/* + * External + */ +void _XawSourceAddText(Widget, Widget); +void _XawSourceRemoveText(Widget, Widget, Bool); +Bool _XawTextSourceNewLineAtEOF(Widget); +void _XawSourceSetUndoErase(TextSrcObject, int); +void _XawSourceSetUndoMerge(TextSrcObject, Bool); +#endif /* OLDXAW */ + +/* + * Defined in Text.c + */ +char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition); +void _XawTextSourceChanged(Widget, XawTextPosition, XawTextPosition, + XawTextBlock*, int); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(TextSrcRec, textSrc.field) +static XtResource resources[] = { + { + XtNeditType, + XtCEditType, + XtREditMode, + sizeof(XawTextEditType), + offset(edit_mode), + XtRString, + "read" + }, +#ifndef OLDXAW + { + XtNcallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(callback), + XtRCallback, + NULL + }, + { + XtNsourceChanged, + XtCChanged, + XtRBoolean, + sizeof(Boolean), + offset(changed), + XtRImmediate, + (XtPointer)False + }, + { + XtNenableUndo, + XtCUndo, + XtRBoolean, + sizeof(Boolean), + offset(enable_undo), + XtRImmediate, + (XtPointer)False + }, + { + XtNpropertyCallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + offset(property_callback), + XtRCallback, + NULL + }, +#endif /* OLDXAW */ +}; +#undef offset + +#define Superclass (&objectClassRec) +TextSrcClassRec textSrcClassRec = { + /* object */ + { + (WidgetClass)Superclass, /* superclass */ + "TextSrc", /* class_name */ + sizeof(TextSrcRec), /* widget_size */ + XawTextSrcClassInitialize, /* class_initialize */ + XawTextSrcClassPartInitialize, /* class_part_initialize */ + False, /* class_inited */ + XawTextSrcInitialize, /* initialize */ + NULL, /* initialize_hook */ + NULL, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + False, /* compress_motion */ + False, /* compress_exposure */ + False, /* compress_enterleave */ + False, /* visible_interest */ + XawTextSrcDestroy, /* destroy */ + NULL, /* resize */ + NULL, /* expose */ + XawTextSrcSetValues, /* set_values */ + NULL, /* set_values_hook */ + NULL, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + NULL, /* query_geometry */ + NULL, /* display_accelerator */ + NULL, /* extension */ + }, + /* text_src */ + { + Read, /* Read */ + Replace, /* Replace */ + Scan, /* Scan */ + Search, /* Search */ + SetSelection, /* SetSelection */ + ConvertSelection, /* ConvertSelection */ + }, +}; + +WidgetClass textSrcObjectClass = (WidgetClass)&textSrcClassRec; + +static XrmQuark QRead, QAppend, QEdit; +#ifndef OLDXAW +static char *SrcNL = "\n"; +static wchar_t SrcWNL[2]; +#endif + +/* + * Implementation + */ +static void +XawTextSrcClassInitialize(void) +{ + XawInitializeWidgetSet(); + +#ifndef OLDXAW + SrcWNL[0] = _Xaw_atowc(XawLF); + SrcWNL[1] = 0; +#endif + QRead = XrmPermStringToQuark(XtEtextRead); + QAppend = XrmPermStringToQuark(XtEtextAppend); + QEdit = XrmPermStringToQuark(XtEtextEdit); + XtAddConverter(XtRString, XtREditMode, CvtStringToEditMode, NULL, 0); + XtSetTypeConverter(XtREditMode, XtRString, CvtEditModeToString, NULL, 0, + XtCacheNone, NULL); +} + +static void +XawTextSrcClassPartInitialize(WidgetClass wc) +{ + TextSrcObjectClass t_src, superC; + + t_src = (TextSrcObjectClass)wc; + superC = (TextSrcObjectClass)t_src->object_class.superclass; + + /* + * We don't need to check for null super since we'll get to TextSrc + * eventually + */ + if (t_src->textSrc_class.Read == XtInheritRead) + t_src->textSrc_class.Read = superC->textSrc_class.Read; + + if (t_src->textSrc_class.Replace == XtInheritReplace) + t_src->textSrc_class.Replace = superC->textSrc_class.Replace; + + if (t_src->textSrc_class.Scan == XtInheritScan) + t_src->textSrc_class.Scan = superC->textSrc_class.Scan; + + if (t_src->textSrc_class.Search == XtInheritSearch) + t_src->textSrc_class.Search = superC->textSrc_class.Search; + + if (t_src->textSrc_class.SetSelection == XtInheritSetSelection) + t_src->textSrc_class.SetSelection = superC->textSrc_class.SetSelection; + + if (t_src->textSrc_class.ConvertSelection == XtInheritConvertSelection) + t_src->textSrc_class.ConvertSelection = + superC->textSrc_class.ConvertSelection; +} + +/*ARGSUSED*/ +static void +XawTextSrcInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ +#ifndef OLDXAW + TextSrcObject src = (TextSrcObject)cnew; + + if (src->textSrc.enable_undo) { + src->textSrc.undo = (XawTextUndo*)XtCalloc(1, sizeof(XawTextUndo)); + src->textSrc.undo->dir = XawsdLeft; + } + else + src->textSrc.undo = NULL; + src->textSrc.undo_state = False; + if (XtIsSubclass(XtParent(cnew), textWidgetClass)) { + src->textSrc.text = (WidgetList)XtMalloc(sizeof(Widget*)); + src->textSrc.text[0] = XtParent(cnew); + src->textSrc.num_text = 1; + } + else { + src->textSrc.text = NULL; + src->textSrc.num_text = 0; + } + + src->textSrc.anchors = NULL; + src->textSrc.num_anchors = 0; + (void)XawTextSourceAddAnchor(cnew, 0); +#endif /* OLDXAW */ +} + +static void +XawTextSrcDestroy(Widget w) +{ +#ifndef OLDXAW + TextSrcObject src = (TextSrcObject)w; + + if (src->textSrc.enable_undo) { + FreeUndoBuffer(src->textSrc.undo); + XtFree((char*)src->textSrc.undo); + } + XtFree((char*)src->textSrc.text); + + if (src->textSrc.num_anchors) { + XawTextEntity *entity, *enext; + int i; + + for (i = 0; i < src->textSrc.num_anchors; i++) { + entity = src->textSrc.anchors[i]->entities; + while (entity) { + enext = entity->next; + XtFree((XtPointer)entity); + entity = enext; + } + XtFree((XtPointer)src->textSrc.anchors[i]); + } + XtFree((XtPointer)src->textSrc.anchors); + } +#endif /* OLDXAW */ +} + +/*ARGSUSED*/ +static Boolean +XawTextSrcSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ +#ifndef OLDXAW + TextSrcObject oldtw = (TextSrcObject)current; + TextSrcObject newtw = (TextSrcObject)cnew; + + if (oldtw->textSrc.enable_undo != newtw->textSrc.enable_undo) { + if (newtw->textSrc.enable_undo) { + newtw->textSrc.undo = (XawTextUndo*) + XtCalloc(1, sizeof(XawTextUndo)); + newtw->textSrc.undo->dir = XawsdLeft; + } + else { + FreeUndoBuffer(newtw->textSrc.undo); + XtFree((char*)newtw->textSrc.undo); + newtw->textSrc.undo = NULL; + } + } + if (oldtw->textSrc.changed != newtw->textSrc.changed) { + if (newtw->textSrc.enable_undo) { + if (newtw->textSrc.undo->list) { + newtw->textSrc.undo->l_no_change = + newtw->textSrc.undo->list->left; + newtw->textSrc.undo->r_no_change = + newtw->textSrc.undo->list->right; + } + else + newtw->textSrc.undo->l_no_change = + newtw->textSrc.undo->r_no_change = NULL; + } + } +#endif /* OLDXAW */ + return (False); +} + +/* + * Function: + * Read + * + * Parameters: + * w - TextSrc Object + * pos - position of the text to retreive + * text - text block that will contain returned text + * length - maximum number of characters to read + * + * Description: + * This function reads the source. + * + * Returns: + * The character position following the retrieved text. + */ +/*ARGSUSED*/ +static XawTextPosition +Read(Widget w, XawTextPosition pos, XawTextBlock *text, int length) +{ + return ((XawTextPosition)0); +} + +/* + * Function: + * Replace + * + * Parameters: + * src - Text Source Object + * startPos - ends of text that will be removed + * endPos - "" + * text - new text to be inserted into buffer at startPos + * + * Description: + * Replaces a block of text with new text. + */ +/*ARGSUSED*/ +static int +Replace(Widget w, XawTextPosition startPos, XawTextPosition endPos, + XawTextBlock *text) +{ + return (XawEditError); +} + +/* + * Function: + * Scan + * + * Parameters: + * w - TextSrc Object + * position - position to start scanning + * type - type of thing to scan for + * dir - direction to scan + * count - which occurance if this thing to search for + * include - whether or not to include the character found in + * the position that is returned + * + * Description: + * Scans the text source for the number and type of item specified. + */ +/*ARGSUSED*/ +static XawTextPosition +Scan(Widget w, XawTextPosition position, XawTextScanType type, + XawTextScanDirection dir, int count, Bool include) +{ + return ((XawTextPosition)0); +} + +/* + * Function: + * Search + * + * Parameters: + * w - TextSource Object + * position - position to start searching + * dir - direction to search + * text - the text block to search for + * + * Description: + * Searchs the text source for the text block passed + */ +/*ARGSUSED*/ +static XawTextPosition +Search(Widget w, XawTextPosition position, XawTextScanDirection dir, + XawTextBlock *text) +{ + return (XawTextSearchError); +} + +/*ARGSUSED*/ +static Boolean +ConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type, + XtPointer *value, unsigned long *length, int *format) +{ + return (False); +} + +/*ARGSUSED*/ +static void +SetSelection(Widget w, XawTextPosition left, XawTextPosition right, + Atom selection) +{ +} + +/*ARGSUSED*/ +static void +CvtStringToEditMode(XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal) +{ + static XawTextEditType editType; + XrmQuark q; + char name[7]; + + XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); + q = XrmStringToQuark(name); + + if (q == QRead) + editType = XawtextRead; + else if (q == QAppend) + editType = XawtextAppend; + else if (q == QEdit) + editType = XawtextEdit; + else { + toVal->size = 0; + toVal->addr = NULL; + XtStringConversionWarning((char *)fromVal->addr, XtREditMode); + } + toVal->size = sizeof(XawTextEditType); + toVal->addr = (XPointer)&editType; +} + +/*ARGSUSED*/ +static Boolean +CvtEditModeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, + XrmValuePtr fromVal, XrmValuePtr toVal, + XtPointer *data) +{ + static String buffer; + Cardinal size; + + switch (*(XawTextEditType *)fromVal->addr) { + case XawtextRead: + buffer = XtEtextRead; + break; + case XawtextAppend: + buffer = XtEtextAppend; + break; + case XawtextEdit: + buffer = XtEtextEdit; + break; + default: + XawTypeToStringWarning(dpy, XtREditMode); + toVal->addr = NULL; + toVal->size = 0; + return (False); + } + + size = strlen(buffer) + 1; + if (toVal->addr != NULL) { + if (toVal->size < size) { + toVal->size = size; + return (False); + } + strcpy((char *)toVal->addr, buffer); + } + else + toVal->addr = (XPointer)buffer; + toVal->size = sizeof(String); + + return (True); +} + +#ifndef OLDXAW +Bool +_XawTextSourceNewLineAtEOF(Widget w) +{ + TextSrcObject src = (TextSrcObject)w; + XawTextBlock text; + + text.firstPos = 0; + if ((text.format = src->textSrc.text_format) == XawFmt8Bit) + text.ptr = SrcNL; + else + text.ptr = (char*)SrcWNL; + text.length = 1; + + return (XawTextSourceSearch(w, XawTextSourceScan(w, 0, XawstAll, + XawsdRight, 1, True) - 1, + XawsdRight, &text) != XawTextSearchError); +} + +void +_XawSourceAddText(Widget source, Widget text) +{ + TextSrcObject src = (TextSrcObject)source; + Bool found = False; + Cardinal i; + + for (i = 0; i < src->textSrc.num_text; i++) + if (src->textSrc.text[i] == text) { + found = True; + break; + } + + if (!found) { + src->textSrc.text = (WidgetList) + XtRealloc((char*)src->textSrc.text, + sizeof(Widget) * (src->textSrc.num_text + 1)); + src->textSrc.text[src->textSrc.num_text++] = text; + } +} + +void +_XawSourceRemoveText(Widget source, Widget text, Bool destroy) +{ + TextSrcObject src = (TextSrcObject)source; + Bool found = False; + Cardinal i; + + if (src == NULL) + return; + + for (i = 0; i < src->textSrc.num_text; i++) + if (src->textSrc.text[i] == text) { + found = True; + break; + } + + if (found) { + if (--src->textSrc.num_text == 0) { + if (destroy) { + XtDestroyWidget(source); + return; + } + else { + XtFree((char*)src->textSrc.text); + src->textSrc.text = NULL; /* for realloc "magic" */ + } + } + else if (i < src->textSrc.num_text) + memmove(&src->textSrc.text[i], &src->textSrc.text[i + 1], + sizeof(Widget) * (src->textSrc.num_text - i)); + } +} +#endif /* OLDXAW */ + +/* + * Function: + * XawTextSourceRead + * + * Parameters: + * w - TextSrc Object + * pos - position of the text to retrieve + * text - text block that will contain returned text (return) + * length - maximum number of characters to read + * + * Description: + * This function reads the source. + * + * Returns: + * The number of characters read into the buffer + */ +XawTextPosition +XawTextSourceRead(Widget w, XawTextPosition pos, XawTextBlock *text, + int length) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; + + return ((*cclass->textSrc_class.Read)(w, pos, text, length)); +} + +#ifndef OLDXAW +static void +TellSourceChanged(TextSrcObject src, XawTextPosition left, + XawTextPosition right, XawTextBlock *block, int lines) +{ + Cardinal i; + + for (i = 0; i < src->textSrc.num_text; i++) + _XawTextSourceChanged(src->textSrc.text[i], left, right, block, lines); +} + +/* + * This function is required because there is no way to diferentiate + * if the first erase was generated by a backward-kill-char and the + * second by a forward-kill-char (or vice-versa) from XawTextSourceReplace. + * It is only possible to diferentiate after the second character is + * killed, but then, it is too late. + */ +void +_XawSourceSetUndoErase(TextSrcObject src, int value) +{ + if (src && src->textSrc.enable_undo) + src->textSrc.undo->erase = value; +} + +/* + * To diferentiate insert-char's separeted by cursor movements. + */ +void +_XawSourceSetUndoMerge(TextSrcObject src, Bool state) +{ + if (src && src->textSrc.enable_undo) + src->textSrc.undo->merge += state ? 1 : -1; +} +#endif /* OLDXAW */ + +/* + * Public Functions + */ +/* + * Function: + * XawTextSourceReplace + * + * Parameters: + * src - Text Source Object + * startPos - ends of text that will be removed + * endPos - "" + * text - new text to be inserted into buffer at startPos + * + * Description: + * Replaces a block of text with new text. + * + * Returns: + * XawEditError or XawEditDone. + */ +/*ARGSUSED*/ +int +XawTextSourceReplace(Widget w, XawTextPosition left, + XawTextPosition right, XawTextBlock *block) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; +#ifndef OLDXAW + TextSrcObject src = (TextSrcObject)w; + XawTextUndoBuffer *l_state, *r_state; + XawTextUndoList *undo; + Bool enable_undo; + XawTextPosition start, end; + int i, error, lines = 0; + + if (src->textSrc.edit_mode == XawtextRead) + return (XawEditError); + + enable_undo = src->textSrc.enable_undo && src->textSrc.undo_state == False; + if (enable_undo) { + unsigned size, total; + + if (src->textSrc.undo->l_save) { + l_state = src->textSrc.undo->l_save; + src->textSrc.undo->l_save = NULL; + } + else + l_state = XtNew(XawTextUndoBuffer); + l_state->refcount = 1; + l_state->position = left; + if (left < right) { + Widget ctx = NULL; + + for (i = 0; i < src->textSrc.num_text; i++) + if (XtIsSubclass(src->textSrc.text[i], textWidgetClass)) { + ctx = src->textSrc.text[i]; + break; + } + l_state->buffer = _XawTextGetText((TextWidget)ctx, left, right); + l_state->length = right - left; + } + else { + l_state->length = 0; + l_state->buffer = NULL; + } + l_state->format = src->textSrc.text_format; + if (l_state->length == 1) { + if (l_state->format == XawFmtWide && + *(wchar_t*)l_state->buffer == *SrcWNL) { + XtFree(l_state->buffer); + l_state->buffer = (char*)SrcWNL; + } + else if (*l_state->buffer == '\n') { + XtFree(l_state->buffer); + l_state->buffer = SrcNL; + } + } + + if (src->textSrc.undo->r_save) { + r_state = src->textSrc.undo->r_save; + src->textSrc.undo->r_save = NULL; + } + else + r_state = XtNew(XawTextUndoBuffer); + r_state->refcount = 1; + r_state->position = left; + r_state->format = block->format; + size = block->format == XawFmtWide ? sizeof(wchar_t) : sizeof(char); + total = size * block->length; + r_state->length = block->length; + r_state->buffer = NULL; + if (total == size) { + if (r_state->format == XawFmtWide && + *(wchar_t*)block->ptr == *SrcWNL) + r_state->buffer = (char*)SrcWNL; + else if (*block->ptr == '\n') + r_state->buffer = SrcNL; + } + if (total && !r_state->buffer) { + r_state->buffer = XtMalloc(total); + memcpy(r_state->buffer, block->ptr, total); + } + + if (src->textSrc.undo->u_save) { + undo = src->textSrc.undo->u_save; + src->textSrc.undo->u_save = NULL; + } + else + undo = XtNew(XawTextUndoList); + undo->left = l_state; + undo->right = r_state; + undo->undo = src->textSrc.undo->list; + undo->redo = NULL; + } + else { + undo = NULL; + l_state = r_state = NULL; + } + +#define LARGE_VALUE 262144 /* 256 K */ + /* optimization, to avoid long delays recalculating the line number + * when editing huge files + */ + if (left > LARGE_VALUE) { + start = XawTextSourceScan(w, left, XawstEOL, XawsdLeft, 2, False); + for (i = 0; i < src->textSrc.num_text; i++) { + TextWidget tw = (TextWidget)src->textSrc.text[i]; + + if (left <= tw->text.lt.top && + left + block->length - (right - left) > tw->text.lt.top) + _XawTextBuildLineTable(tw, start, False); + } + } +#undef LARGE_VALUE + + start = left; + end = right; + while (start < end) { + start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True); + if (start <= end) { + --lines; + if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) { + lines += !_XawTextSourceNewLineAtEOF(w); + break; + } + } + } +#else + int error; +#endif /* OLDXAW */ + + error = (*cclass->textSrc_class.Replace)(w, left, right, block); + +#ifndef OLDXAW + if (error != XawEditDone) { + if (enable_undo) { + if (l_state->buffer) { + if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL) + XtFree(l_state->buffer); + l_state->buffer = NULL; + } + src->textSrc.undo->l_save = l_state; + if (r_state->buffer) { + if (r_state->buffer != SrcNL && r_state->buffer != (char*)SrcWNL) + XtFree(r_state->buffer); + r_state->buffer = NULL; + } + src->textSrc.undo->r_save = r_state; + + src->textSrc.undo->u_save = undo; + } + } + else if (enable_undo) { + XawTextUndoList *list = src->textSrc.undo->list; + XawTextUndoBuffer *unl, *lnl; + int erase = undo->right->length == 0 && undo->left->length == 1 && list + && list->right->length == 0; + + if (erase) { + erase = list->left->position - 1 == undo->left->position ? -1 : + list->left->position == undo->left->position ? 1 : 0; + if (src->textSrc.undo->erase && erase != src->textSrc.undo->erase) + erase = 0; + else + src->textSrc.undo->erase = erase; + } + + if (erase) { + unl = l_state; + lnl = list->left; + } + else { + unl = r_state; + lnl = list ? list->right : NULL; + } + + /* Try to merge the undo buffers */ + if (src->textSrc.undo->merge > 0 && ((erase || + (list && ((list->left->length == 0 && undo->left->length == 0) || + (list->left->length == list->right->length && + undo->left->length == 1)) && + undo->right->length == 1 && + list->right->position + list->right->length + == undo->right->position)) + && src->textSrc.undo->pointer == list + && unl->format == list->right->format + && ((unl->format == XawFmt8Bit && unl->buffer[0] != XawLF) || + (unl->format == XawFmtWide && + *(wchar_t*)(unl->buffer) != _Xaw_atowc(XawLF))) + && ((lnl->format == XawFmt8Bit && lnl->buffer[0] != XawLF) || + (lnl->format == XawFmtWide && + *(wchar_t*)(lnl->buffer) != _Xaw_atowc(XawLF))))) { + unsigned size = lnl->format == XawFmtWide ? + sizeof(wchar_t) : sizeof(char); + + if (!erase) { + list->right->buffer = XtRealloc(list->right->buffer, + (list->right->length + 1) * size); + memcpy(list->right->buffer + list->right->length * size, + undo->right->buffer, size); + ++list->right->length; + XtFree(r_state->buffer); + } + else if (erase < 0) { + --list->left->position; + --list->right->position; + } + + src->textSrc.undo->l_save = l_state; + src->textSrc.undo->r_save = r_state; + src->textSrc.undo->u_save = undo; + + if (list->left->length) { + list->left->buffer = XtRealloc(list->left->buffer, + (list->left->length + 1) * size); + if (erase >= 0) + memcpy(list->left->buffer + list->left->length * size, + undo->left->buffer, size); + else { + /* use memmove, since strings overlap */ + memmove(list->left->buffer + size, list->left->buffer, + list->left->length * size); + memcpy(list->left->buffer, undo->left->buffer, size); + } + ++list->left->length; + if (l_state->buffer != SrcNL && l_state->buffer != (char*)SrcWNL) + XtFree(l_state->buffer); + } + + if (src->textSrc.undo->num_list >= UNDO_DEPTH) + UndoGC(src->textSrc.undo); + } + else { + src->textSrc.undo->undo = (XawTextUndoBuffer**) + XtRealloc((char*)src->textSrc.undo->undo, + (2 + src->textSrc.undo->num_undo) + * sizeof(XawTextUndoBuffer)); + src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = l_state; + src->textSrc.undo->undo[src->textSrc.undo->num_undo++] = r_state; + + if (src->textSrc.undo->list) + src->textSrc.undo->list->redo = undo; + else + src->textSrc.undo->head = undo; + + src->textSrc.undo->merge = l_state->length <= 1 && + r_state->length <= 1; + + src->textSrc.undo->list = src->textSrc.undo->pointer = + src->textSrc.undo->end_mark = undo; + + if (++src->textSrc.undo->num_list >= UNDO_DEPTH) + UndoGC(src->textSrc.undo); + } + src->textSrc.undo->dir = XawsdLeft; + if (!src->textSrc.changed) { + src->textSrc.undo->l_no_change = src->textSrc.undo->list->right; + src->textSrc.undo->r_no_change = src->textSrc.undo->list->left; + src->textSrc.changed = True; + } + } + else if (!src->textSrc.enable_undo) + src->textSrc.changed = True; + + if (error == XawEditDone) { + XawTextPropertyInfo info; + XawTextAnchor *anchor; + + /* find anchor and index */ + /* XXX index (i) could be returned by XawTextSourceFindAnchor + * or similar function, to speed up */ + if ((anchor = XawTextSourceFindAnchor(w, left))) { + XawTextEntity *eprev, *entity, *enext; + XawTextPosition offset = 0, diff = block->length - (right - left); + + for (i = 0; i < src->textSrc.num_anchors; i++) + if (src->textSrc.anchors[i] == anchor) + break; + if (anchor->cache && anchor->position + anchor->cache->offset + + anchor->cache->length <= left) + eprev = entity = anchor->cache; + else + eprev = entity = anchor->entities; + while (entity) { + offset = anchor->position + entity->offset; + + if (offset > left) + break; + if (offset + entity->length > left) + break; + + eprev = entity; + entity = entity->next; + } + + /* try to do the right thing here (and most likely correct), but + * other code needs to check what was done */ + + /* adjust entity length */ + if (entity && offset <= left) { + if (offset + entity->length < right) + entity->length = left - offset + block->length; + else + entity->length += diff; + + if (entity->length == 0) { + enext = entity->next; + eprev->next = enext; + anchor->cache = NULL; + XtFree((XtPointer)entity); + if (entity == anchor->entities) { + if ((anchor->entities = enext) == NULL) { + eprev = NULL; + anchor = XawTextSourceRemoveAnchor(w, anchor); + entity = anchor ? anchor->entities : NULL; + } + else + eprev = entity = enext; + } + else + entity = enext; + } + else { + eprev = entity; + entity = entity->next; + } + } + + while (anchor) { + while (entity) { + offset = anchor->position + entity->offset + entity->length; + + if (offset > right) { + entity->length = XawMin(entity->length, offset - right); + goto exit_anchor_loop; + } + + enext = entity->next; + if (eprev) + eprev->next = enext; + XtFree((XtPointer)entity); + anchor->cache = NULL; + if (entity == anchor->entities) { + eprev = NULL; + if ((anchor->entities = enext) == NULL) { + if (i == 0) + ++i; + else if (i < --src->textSrc.num_anchors) { + memmove(&src->textSrc.anchors[i], + &src->textSrc.anchors[i + 1], + (src->textSrc.num_anchors - i) * + sizeof(XawTextAnchor*)); + XtFree((XtPointer)anchor); + } + if (i >= src->textSrc.num_anchors) { + anchor = NULL; + entity = NULL; + break; + } + anchor = src->textSrc.anchors[i]; + entity = anchor->entities; + continue; + } + } + entity = enext; + } + if (i + 1 < src->textSrc.num_anchors) { + anchor = src->textSrc.anchors[++i]; + entity = anchor->entities; + eprev = NULL; + } + else { + anchor = NULL; + break; + } + eprev = NULL; + } + +exit_anchor_loop: + if (anchor) { + XawTextAnchor *aprev; + + if (anchor->position >= XawMax(right, left + block->length)) + anchor->position += diff; + else if (anchor->position > left && + (aprev = XawTextSourcePrevAnchor(w, anchor))) { + XawTextPosition tmp = anchor->position - aprev->position; + + if (diff) { + while (entity) { + entity->offset += diff; + entity = entity->next; + } + } + entity = anchor->entities; + while (entity) { + entity->offset += tmp; + entity = entity->next; + } + if ((entity = aprev->entities) == NULL) + aprev->entities = anchor->entities; + else { + while (entity->next) + entity = entity->next; + entity->next = anchor->entities; + } + anchor->entities = NULL; + (void)XawTextSourceRemoveAnchor(w, anchor); + --i; + } + else if (diff) { + while (entity) { + entity->offset += diff; + entity = entity->next; + } + } + } + + if (diff) { + /* The first anchor is never removed, and should + * have position 0. + * i should be -1 if attempted to removed the first + * anchor, what can be caused when removing a chunk + * of text of the first entity. + * */ + if (++i == 0) { + anchor = src->textSrc.anchors[0]; + eprev = entity = anchor->entities; + while (entity) { + enext = entity->next; + if (entity->offset + entity->length <= -diff) + XtFree((XtPointer)entity); + else + break; + entity = enext; + } + if (eprev != entity) { + anchor->cache = NULL; + if ((anchor->entities = entity) != NULL) { + if ((entity->offset += diff) < 0) { + entity->length += entity->offset; + entity->offset = 0; + } + } + } + ++i; + } + for (; i < src->textSrc.num_anchors; i++) + src->textSrc.anchors[i]->position += diff; + } + } + + start = left; + end = start + block->length; + while (start < end) { + start = XawTextSourceScan(w, start, XawstEOL, XawsdRight, 1, True); + if (start <= end) { + ++lines; + if (start == XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True)) { + lines -= !_XawTextSourceNewLineAtEOF(w); + break; + } + } + } + + info.left = left; + info.right = right; + info.block = block; + XtCallCallbacks(w, XtNpropertyCallback, &info); + + TellSourceChanged(src, left, right, block, lines); + /* Call callbacks, we have changed the buffer */ + XtCallCallbacks(w, XtNcallback, + (XtPointer)((long)src->textSrc.changed)); + } + +#endif /* OLDXAW */ + return (error); +} + +#ifndef OLDXAW +Bool +_XawTextSrcUndo(TextSrcObject src, XawTextPosition *insert_pos) +{ + static wchar_t wnull = 0; + XawTextBlock block; + XawTextUndoList *list, *nlist; + XawTextUndoBuffer *l_state, *r_state; + Boolean changed = src->textSrc.changed; + + if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo) + return (False); + + list = src->textSrc.undo->pointer; + + if (src->textSrc.undo->dir == XawsdLeft) { + l_state = list->right; + r_state = list->left; + } + else { + l_state = list->left; + r_state = list->right; + } + + if (src->textSrc.undo->l_no_change == l_state + && src->textSrc.undo->r_no_change == r_state) + src->textSrc.changed = False; + else + src->textSrc.changed = True; + + block.firstPos = 0; + block.length = r_state->length; + block.ptr = r_state->buffer ? r_state->buffer : (char*)&wnull; + block.format = r_state->format; + + src->textSrc.undo_state = True; + if (XawTextSourceReplace((Widget)src, l_state->position, l_state->position + + l_state->length, &block) != XawEditDone) { + src->textSrc.undo_state = False; + src->textSrc.changed = changed; + return (False); + } + src->textSrc.undo_state = False; + + ++l_state->refcount; + ++r_state->refcount; + nlist = XtNew(XawTextUndoList); + nlist->left = l_state; + nlist->right = r_state; + nlist->undo = src->textSrc.undo->list; + nlist->redo = NULL; + + if (list == src->textSrc.undo->list) + src->textSrc.undo->end_mark = nlist; + + if (src->textSrc.undo->dir == XawsdLeft) { + if (list->undo == NULL) + src->textSrc.undo->dir = XawsdRight; + else + list = list->undo; + } + else { + if (list->redo == NULL || list->redo == src->textSrc.undo->end_mark) + src->textSrc.undo->dir = XawsdLeft; + else + list = list->redo; + } + *insert_pos = r_state->position + r_state->length; + src->textSrc.undo->pointer = list; + src->textSrc.undo->list->redo = nlist; + src->textSrc.undo->list = nlist; + src->textSrc.undo->merge = src->textSrc.undo->erase = 0; + + if (++src->textSrc.undo->num_list >= UNDO_DEPTH) + UndoGC(src->textSrc.undo); + + return (True); +} + +Bool +_XawTextSrcToggleUndo(TextSrcObject src) +{ + if (!src->textSrc.enable_undo || !src->textSrc.undo->num_undo) + return (False); + + if (src->textSrc.undo->pointer != src->textSrc.undo->list) { + if (src->textSrc.undo->dir == XawsdLeft) { + if (src->textSrc.undo->pointer->redo + && (src->textSrc.undo->pointer->redo + != src->textSrc.undo->end_mark)) { + src->textSrc.undo->pointer = src->textSrc.undo->pointer->redo; + src->textSrc.undo->dir = XawsdRight; + } + } + else { + if (src->textSrc.undo->pointer->undo + && (src->textSrc.undo->pointer != src->textSrc.undo->head)) { + src->textSrc.undo->pointer = src->textSrc.undo->pointer->undo; + src->textSrc.undo->dir = XawsdLeft; + } + } + } + + return (True); +} + +static void +FreeUndoBuffer(XawTextUndo *undo) +{ + unsigned i; + XawTextUndoList *head, *del; + + for (i = 0; i < undo->num_undo; i++) { + if (undo->undo[i]->buffer && undo->undo[i]->buffer != SrcNL && + undo->undo[i]->buffer != (char*)SrcWNL) + XtFree(undo->undo[i]->buffer); + XtFree((char*)undo->undo[i]); + } + XtFree((char*)undo->undo); + head = undo->head; + + del = head; + while (head) { + head = head->redo; + XtFree((char*)del); + del = head; + } + + if (undo->l_save) { + XtFree((char*)undo->l_save); + undo->l_save = NULL; + } + if (undo->r_save) { + XtFree((char*)undo->r_save); + undo->r_save = NULL; + } + if (undo->u_save) { + XtFree((char*)undo->u_save); + undo->u_save = NULL; + } + + undo->list = undo->pointer = undo->head = undo->end_mark = NULL; + undo->l_no_change = undo->r_no_change = NULL; + undo->undo = NULL; + undo->dir = XawsdLeft; + undo->num_undo = undo->num_list = undo->erase = undo->merge = 0; +} + +static void +UndoGC(XawTextUndo *undo) +{ + unsigned i; + XawTextUndoList *head = undo->head, *redo = head->redo; + + if (head == undo->pointer || head == undo->end_mark + || undo->l_no_change == NULL + || head->left == undo->l_no_change || head->right == undo->l_no_change) + return; + + undo->head = redo; + redo->undo = NULL; + + --head->left->refcount; + if (--head->right->refcount == 0) { + for (i = 0; i < undo->num_undo; i+= 2) + if (head->left == undo->undo[i] || head->left == undo->undo[i+1]) { + if (head->left == undo->undo[i+1]) { + XawTextUndoBuffer *tmp = redo->left; + + redo->left = redo->right; + redo->right = tmp; + } + if (head->left->buffer && head->left->buffer != SrcNL && + head->left->buffer != (char*)SrcWNL) + XtFree(head->left->buffer); + XtFree((char*)head->left); + if (head->right->buffer && head->right->buffer != SrcNL && + head->right->buffer != (char*)SrcWNL) + XtFree(head->right->buffer); + XtFree((char*)head->right); + + undo->num_undo -= 2; + memmove(&undo->undo[i], &undo->undo[i + 2], + (undo->num_undo - i) * sizeof(XawTextUndoBuffer*)); + break; + } + } + XtFree((char*)head); + --undo->num_list; +} +#endif /* OLDXAW */ + +/* + * Function: + * XawTextSourceScan + * + * Parameters: + * w - TextSrc Object + * position - position to start scanning + * type - type of thing to scan for + * dir - direction to scan + * count - which occurance if this thing to search for + * include - whether or not to include the character found in + * the position that is returned. + * + * Description: + * Scans the text source for the number and type of item specified. + * + * Returns: + * The position of the text + */ +XawTextPosition +XawTextSourceScan(Widget w, XawTextPosition position, +#if NeedWidePrototypes + int type, int dir, int count, int include +#else + XawTextScanType type, XawTextScanDirection dir, + int count, Boolean include +#endif +) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; + + return ((*cclass->textSrc_class.Scan) + (w, position, type, dir, count, include)); +} + +/* + * Function: + * XawTextSourceSearch + * + * Parameters: + * w - TextSource Object + * position - position to start scanning + * dir - direction to scan + * text - the text block to search for. + * + * Returns: + * The position of the text we are searching for or XawTextSearchError. + * + * Description: + * Searchs the text source for the text block passed + */ +XawTextPosition +XawTextSourceSearch(Widget w, XawTextPosition position, +#if NeedWidePrototypes + int dir, +#else + XawTextScanDirection dir, +#endif + XawTextBlock *text) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; + + return ((*cclass->textSrc_class.Search)(w, position, dir, text)); +} + +/* + * Function: + * XawTextSourceConvertSelection + * + * Parameters: + * w - TextSrc object + * selection - current selection atom + * target - current target atom + * type - type to conver the selection to + * value - return value that has been converted + * length - "" + * format - format of the returned value + * + * Returns: + * True if the selection has been converted + */ +Boolean +XawTextSourceConvertSelection(Widget w, Atom *selection, Atom *target, + Atom *type, XtPointer *value, + unsigned long *length, int *format) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; + + return((*cclass->textSrc_class.ConvertSelection) + (w, selection, target, type, value, length, format)); +} + +/* + * Function: + * XawTextSourceSetSelection + * + * Parameters: + * w - TextSrc object + * left - bounds of the selection + * rigth - "" + * selection - selection atom + * + * Description: + * Allows special setting of the selection. + */ +void +XawTextSourceSetSelection(Widget w, XawTextPosition left, + XawTextPosition right, Atom selection) +{ + TextSrcObjectClass cclass = (TextSrcObjectClass)w->core.widget_class; + + (*cclass->textSrc_class.SetSelection)(w, left, right, selection); +} + +/* + * External Functions for Multi Text + */ +/* + * TextFormat(): + * returns the format of text: FMT8BIT or FMTWIDE + */ +XrmQuark +_XawTextFormat(TextWidget tw) +{ + return (((TextSrcObject)(tw->text.source))->textSrc.text_format); +} + +/* _XawTextWCToMB(): + * Convert the wchar string to external encoding + * The caller is responsible for freeing both the source and ret string + * + * wstr - source wchar string + * len_in_out - lengh of string. + * As In, length of source wchar string, measured in wchar + * As Out, length of returned string + */ +char * +_XawTextWCToMB(Display *d, wchar_t *wstr, int *len_in_out) +{ + XTextProperty textprop; + + if (XwcTextListToTextProperty(d, (wchar_t**)&wstr, 1, + XTextStyle, &textprop) < Success) { + XtWarningMsg("convertError", "textSource", "XawError", + "Non-character code(s) in buffer.", NULL, NULL); + *len_in_out = 0; + return (NULL); + } + *len_in_out = textprop.nitems; + + return ((char *)textprop.value); +} + +/* _XawTextMBToWC(): + * Convert the string to internal processing codeset WC. + * The caller is responsible for freeing both the source and ret string. + * + * str - source string + * len_in_out - lengh of string + * As In, it is length of source string + * As Out, it is length of returned string, measured in wchar + */ +wchar_t * +_XawTextMBToWC(Display *d, char *str, int *len_in_out) +{ + XTextProperty textprop; + char *buf; + wchar_t **wlist, *wstr; + int count; + + if (*len_in_out == 0) + return (NULL); + + buf = XtMalloc(*len_in_out + 1); + + strncpy(buf, str, *len_in_out); + *(buf + *len_in_out) = '\0'; + if (XmbTextListToTextProperty(d, &buf, 1, XTextStyle, &textprop) != Success) { + XtWarningMsg("convertError", "textSource", "XawError", + "No Memory, or Locale not supported.", NULL, NULL); + XtFree(buf); + *len_in_out = 0; + return (NULL); + } + + XtFree(buf); + if (XwcTextPropertyToTextList(d, &textprop, + (wchar_t***)&wlist, &count) != Success) { + XtWarningMsg("convertError", "multiSourceCreate", "XawError", + "Non-character code(s) in source.", NULL, NULL); + *len_in_out = 0; + return (NULL); + } + wstr = wlist[0]; + *len_in_out = wcslen(wstr); + XtFree((XtPointer)wlist); + + return (wstr); +} + +#ifndef OLDXAW +static int +qcmp_anchors(_Xconst void *left, _Xconst void *right) +{ + return ((*(XawTextAnchor**)left)->position - + (*(XawTextAnchor**)right)->position); +} + +XawTextAnchor * +XawTextSourceAddAnchor(Widget w, XawTextPosition position) +{ + TextSrcObject src = (TextSrcObject)w; + XawTextAnchor *anchor, *panchor; + + if ((panchor = XawTextSourceFindAnchor(w, position)) != NULL) { + XawTextEntity *pentity, *entity; + + if (position - panchor->position < ANCHORS_DIST) + return (panchor); + + if (panchor->cache && panchor->position + panchor->cache->offset + + panchor->cache->length < position) + pentity = entity = panchor->cache; + else + pentity = entity = panchor->entities; + + while (entity && panchor->position + entity->offset + + entity->length < position) { + pentity = entity; + entity = entity->next; + } + if (entity) { + XawTextPosition diff; + + if (panchor->position + entity->offset < position) + position = panchor->position + entity->offset; + + if (position == panchor->position) + return (panchor); + + anchor = XtNew(XawTextAnchor); + diff = position - panchor->position; + + panchor->cache = NULL; + anchor->entities = entity; + if (pentity != entity) + pentity->next = NULL; + else + panchor->entities = NULL; + while (entity) { + entity->offset -= diff; + entity = entity->next; + } + } + else { + anchor = XtNew(XawTextAnchor); + anchor->entities = NULL; + } + } + else { + anchor = XtNew(XawTextAnchor); + anchor->entities = NULL; + } + + anchor->position = position; + anchor->cache = NULL; + + src->textSrc.anchors = (XawTextAnchor**) + XtRealloc((XtPointer)src->textSrc.anchors, sizeof(XawTextAnchor*) * + (src->textSrc.num_anchors + 1)); + src->textSrc.anchors[src->textSrc.num_anchors++] = anchor; + qsort((void*)src->textSrc.anchors, src->textSrc.num_anchors, + sizeof(XawTextAnchor*), qcmp_anchors); + + return (anchor); +} + +XawTextAnchor * +XawTextSourceFindAnchor(Widget w, XawTextPosition position) +{ + TextSrcObject src = (TextSrcObject)w; + int i = 0, left, right, nmemb = src->textSrc.num_anchors; + XawTextAnchor *anchor, **anchors = src->textSrc.anchors; + + left = 0; + right = nmemb - 1; + while (left <= right) { + anchor = anchors[i = (left + right) >> 1]; + if (anchor->position == position) + return (anchor); + else if (position < anchor->position) + right = i - 1; + else + left = i + 1; + } + + if (nmemb) + return (right < 0 ? anchors[0] : anchors[right]); + + return (NULL); +} + +Bool +XawTextSourceAnchorAndEntity(Widget w, XawTextPosition position, + XawTextAnchor **anchor_return, + XawTextEntity **entity_return) +{ + XawTextAnchor *anchor = XawTextSourceFindAnchor(w, position); + XawTextEntity *pentity, *entity; + XawTextPosition offset; + Bool next_anchor = True, retval = False; + + if (anchor->cache && anchor->position + anchor->cache->offset + + anchor->cache->length <= position) + pentity = entity = anchor->cache; + else + pentity = entity = anchor->entities; + while (entity) { + offset = anchor->position + entity->offset; + + if (offset > position) { + retval = next_anchor = False; + break; + } + if (offset + entity->length > position) { + retval = True; + next_anchor = False; + break; + } + pentity = entity; + entity = entity->next; + } + + if (next_anchor) { + *anchor_return = anchor = XawTextSourceNextAnchor(w, anchor); + *entity_return = anchor ? anchor->entities : NULL; + } + else { + *anchor_return = anchor; + *entity_return = retval ? entity : pentity; + } + + if (*anchor_return) + (*anchor_return)->cache = *entity_return; + + return (retval); +} + +XawTextAnchor * +XawTextSourceNextAnchor(Widget w, XawTextAnchor *anchor) +{ + int i; + TextSrcObject src = (TextSrcObject)w; + + for (i = 0; i < src->textSrc.num_anchors - 1; i++) + if (src->textSrc.anchors[i] == anchor) + return (src->textSrc.anchors[i + 1]); + + return (NULL); +} + +XawTextAnchor * +XawTextSourcePrevAnchor(Widget w, XawTextAnchor *anchor) +{ + int i; + TextSrcObject src = (TextSrcObject)w; + + for (i = src->textSrc.num_anchors - 1; i > 0; i--) + if (src->textSrc.anchors[i] == anchor) + return (src->textSrc.anchors[i - 1]); + + return (NULL); +} + +XawTextAnchor * +XawTextSourceRemoveAnchor(Widget w, XawTextAnchor *anchor) +{ + int i; + TextSrcObject src = (TextSrcObject)w; + + for (i = 0; i < src->textSrc.num_anchors; i++) + if (src->textSrc.anchors[i] == anchor) + break; + + if (i == 0) + return (src->textSrc.num_anchors > 1 ? src->textSrc.anchors[1] : NULL); + + if (i < src->textSrc.num_anchors) { + XtFree((XtPointer)anchor); + if (i < --src->textSrc.num_anchors) { + memmove(&src->textSrc.anchors[i], + &src->textSrc.anchors[i + 1], + (src->textSrc.num_anchors - i) * + sizeof(XawTextAnchor*)); + + return (src->textSrc.anchors[i]); + } + } + + return (NULL); +} + +XawTextEntity * +XawTextSourceAddEntity(Widget w, int type, int flags, XtPointer data, + XawTextPosition position, Cardinal length, + XrmQuark property) +{ + XawTextAnchor *next, *anchor = _XawTextSourceFindAnchor(w, position); + XawTextEntity *entity, *eprev; + + /* There is no support for zero length entities for now */ + if (length == 0) + return (NULL); + + if (anchor->cache && anchor->position + anchor->cache->offset + + anchor->cache->length <= position) + eprev = entity = anchor->cache; + else + eprev = entity = anchor->entities; + + while (entity && anchor->position + entity->offset + entity->length <= + position) { + eprev = entity; + entity = entity->next; + } + if (entity && anchor->position + entity->offset < position + length) { + fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n"); + return (NULL); + } + + next = XawTextSourceFindAnchor(w, position + length); + if (next && next != anchor) { + if ((entity = next->entities) != NULL) { + if (next->position + entity->offset < position + length) { + fprintf(stderr, "Cannot (yet) add more than one entity to same region.\n"); + return (NULL); + } + } + if (position + length > next->position) { + XawTextPosition diff = position + length - next->position; + + next->position += diff; + entity = next->entities; + while (entity) { + entity->offset -= diff; + entity = entity->next; + } + entity = anchor->entities; + while (entity && entity->offset < 0) + entity = entity->next; + if (entity && entity->offset < 0) { + if (eprev) + eprev->next = next->entities; + else + anchor->entities = next->entities; + if ((next->entities = entity->next) == NULL) + (void)XawTextSourceRemoveAnchor(w, next); + entity->next = NULL; + + return (XawTextSourceAddEntity(w, type, flags, data, position, + length, property)); + } + } + } + + /* Automatically join sequential entities if possible */ + if (eprev && + anchor->position + eprev->offset + eprev->length == position && + eprev->property == property && eprev->type == type && + eprev->flags == flags && eprev->data == data) { + eprev->length += length; + return (eprev); + } + + entity = XtNew(XawTextEntity); + entity->type = type; + entity->flags = flags; + entity->data = data; + entity->offset = position - anchor->position; + entity->length = length; + entity->property = property; + + if (eprev == NULL) { + anchor->entities = entity; + entity->next = NULL; + anchor->cache = NULL; + } + else if (eprev->offset > entity->offset) { + anchor->cache = NULL; + anchor->entities = entity; + entity->next = eprev; + } + else { + anchor->cache = eprev; + entity->next = eprev->next; + eprev->next = entity; + } + + return (entity); +} + +void +XawTextSourceClearEntities(Widget w, XawTextPosition left, XawTextPosition right) +{ + XawTextAnchor *anchor = XawTextSourceFindAnchor(w, left); + XawTextEntity *entity, *eprev, *enext; + XawTextPosition offset; + int length; + + while (anchor && anchor->entities == NULL) + anchor = XawTextSourceRemoveAnchor(w, anchor); + + if (anchor == NULL || left >= right) + return; + + if (anchor->cache && anchor->position + anchor->cache->offset + + anchor->cache->length < left) + eprev = entity = anchor->cache; + else + eprev = entity = anchor->entities; + + /* find first entity before left position */ + while (anchor->position + entity->offset + entity->length < left) { + eprev = entity; + if ((entity = entity->next) == NULL) { + if ((anchor = XawTextSourceNextAnchor(w, anchor)) == NULL) + return; + if ((eprev = entity = anchor->entities) == NULL) { + fprintf(stderr, "Bad anchor found!\n"); + return; + } + } + } + + offset = anchor->position + entity->offset; + if (offset <= left) { + length = XawMin(entity->length, left - offset); + + if (length <= 0) { + enext = entity->next; + eprev->next = enext; + XtFree((XtPointer)entity); + anchor->cache = NULL; + if (entity == anchor->entities) { + eprev = NULL; + if ((anchor->entities = enext) == NULL) { + if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL) + return; + entity = anchor->entities; + } + else + entity = enext; + } + else + entity = enext; + } + else { + entity->length = length; + eprev = entity; + entity = entity->next; + } + } + + /* clean everything until right position is reached */ + while (anchor) { + while (entity) { + offset = anchor->position + entity->offset + entity->length; + + if (offset > right) { + anchor->cache = NULL; + entity->offset = XawMax(entity->offset, right - anchor->position); + entity->length = XawMin(entity->length, offset - right); + return; + } + + enext = entity->next; + if (eprev) + eprev->next = enext; + XtFree((XtPointer)entity); + if (entity == anchor->entities) { + eprev = anchor->cache = NULL; + if ((anchor->entities = enext) == NULL) { + if ((anchor = XawTextSourceRemoveAnchor(w, anchor)) == NULL) + return; + entity = anchor->entities; + continue; + } + } + entity = enext; + } + if (anchor) + anchor->cache = NULL; + if ((anchor = XawTextSourceNextAnchor(w, anchor)) != NULL) + entity = anchor->entities; + eprev = NULL; + } +} + +/* checks the anchors up to position, and create an appropriate anchor + * at position, if required. + */ +XawTextAnchor * +_XawTextSourceFindAnchor(Widget w, XawTextPosition position) +{ + XawTextAnchor *anchor; + + anchor = XawTextSourceFindAnchor(w, position); + + position -= position % ANCHORS_DIST; + + if (position - anchor->position >= ANCHORS_DIST) + return (XawTextSourceAddAnchor(w, position)); + + return (anchor); +} +#endif -- cgit v1.2.3