diff options
Diffstat (limited to 'libXaw/src/AsciiSrc.c')
-rw-r--r-- | libXaw/src/AsciiSrc.c | 3776 |
1 files changed, 1888 insertions, 1888 deletions
diff --git a/libXaw/src/AsciiSrc.c b/libXaw/src/AsciiSrc.c index 245a65464..2a07e6220 100644 --- a/libXaw/src/AsciiSrc.c +++ b/libXaw/src/AsciiSrc.c @@ -1,1888 +1,1888 @@ -/* - -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. - -*/ - -/* - * AsciiSrc.c - AsciiSrc object. (For use with the text widget). - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <errno.h> -#include <X11/IntrinsicP.h> -#include <X11/StringDefs.h> -#include <X11/Xos.h> -#include <X11/Xfuncs.h> -#include <X11/Xmu/CharSet.h> -#include <X11/Xmu/Misc.h> -#include <X11/Xaw/XawInit.h> -#include <X11/Xaw/AsciiSrcP.h> -#include <X11/Xaw/MultiSrcP.h> -#ifndef OLDXAW -#include <X11/Xaw/TextSinkP.h> -#include <X11/Xaw/AsciiSinkP.h> -#endif -#include "Private.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#if (defined(ASCII_STRING) || defined(ASCII_DISK)) -#include <X11/Xaw/AsciiText.h> /* for Widget Classes */ -#endif - -#ifdef X_NOT_POSIX -#define Off_t long -#define Size_t unsigned int -#else -#define Off_t off_t -#define Size_t size_t -#endif - -#define MAGIC_VALUE ((XawTextPosition)-1) -#define streq(a, b) (strcmp((a), (b)) == 0) - -/* - * Class Methods - */ -static void XawAsciiSrcClassInitialize(void); -static void XawAsciiSrcDestroy(Widget); -static void XawAsciiSrcGetValuesHook(Widget, ArgList, Cardinal*); -static void XawAsciiSrcInitialize(Widget, Widget, ArgList, Cardinal*); -static Boolean XawAsciiSrcSetValues(Widget, Widget, Widget, - ArgList, Cardinal*); -static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock*, int); -static int ReplaceText(Widget, XawTextPosition, XawTextPosition, - XawTextBlock*); -static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType, - XawTextScanDirection, int, Bool); -static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection, - XawTextBlock*); - -/* - * Prototypes - */ -static Piece *AllocNewPiece(AsciiSrcObject, Piece*); -static void BreakPiece(AsciiSrcObject, Piece*); -static Boolean CvtAsciiTypeToString(Display*, XrmValuePtr, Cardinal*, - XrmValuePtr, XrmValuePtr, XtPointer*); -static void CvtStringToAsciiType(XrmValuePtr, Cardinal*, - XrmValuePtr, XrmValuePtr); -static Piece *FindPiece(AsciiSrcObject, XawTextPosition, XawTextPosition*); -static void FreeAllPieces(AsciiSrcObject); -static FILE *InitStringOrFile(AsciiSrcObject, Bool); -static void LoadPieces(AsciiSrcObject, FILE*, char*); -static void RemoveOldStringOrFile(AsciiSrcObject, Bool); -static void RemovePiece(AsciiSrcObject, Piece*); -static String StorePiecesInString(AsciiSrcObject); -static Bool WriteToFile(String, String, unsigned); -static Bool WritePiecesToFile(AsciiSrcObject, String); -static void GetDefaultPieceSize(Widget, int, XrmValue*); - -/* - * More Prototypes - */ -#ifdef ASCII_DISK -Widget XawAsciiDiskSourceCreate(Widget, ArgList, Cardinal); -#endif -#ifdef ASCII_STRING -Widget XawStringSourceCreate(Widget, ArgList, Cardinal); -void XawTextSetLastPos(Widget, XawTextPosition); -#endif - -/* - * Initialization - */ -#define offset(field) XtOffsetOf(AsciiSrcRec, ascii_src.field) -static XtResource resources[] = { - { - XtNstring, - XtCString, - XtRString, - sizeof(char*), - offset(string), - XtRString, - NULL - }, - { - XtNtype, - XtCType, - XtRAsciiType, - sizeof(XawAsciiType), - offset(type), - XtRImmediate, - (XtPointer)XawAsciiString - }, - { - XtNdataCompression, - XtCDataCompression, - XtRBoolean, - sizeof(Boolean), - offset(data_compression), - XtRImmediate, - (XtPointer)True - }, - { - XtNpieceSize, - XtCPieceSize, - XtRInt, - sizeof(XawTextPosition), - offset(piece_size), - XtRCallProc, - (XtPointer)GetDefaultPieceSize - }, -#ifdef OLDXAW - { - XtNcallback, - XtCCallback, - XtRCallback, - sizeof(XtPointer), - offset(callback), - XtRCallback, - (XtPointer)NULL - }, -#endif - { - XtNuseStringInPlace, - XtCUseStringInPlace, - XtRBoolean, - sizeof(Boolean), - offset(use_string_in_place), - XtRImmediate, - (XtPointer)False - }, - { - XtNlength, - XtCLength, - XtRInt, - sizeof(int), - offset(ascii_length), - XtRImmediate, - (XtPointer)MAGIC_VALUE - }, -#ifdef ASCII_DISK - { - XtNfile, - XtCFile, - XtRString, - sizeof(String), - offset(filename), - XtRString, - NULL - }, -#endif /* ASCII_DISK */ -}; -#undef offset - - -#define Superclass (&textSrcClassRec) -AsciiSrcClassRec asciiSrcClassRec = { - /* object */ - { - (WidgetClass)Superclass, /* superclass */ - "AsciiSrc", /* class_name */ - sizeof(AsciiSrcRec), /* widget_size */ - XawAsciiSrcClassInitialize, /* class_initialize */ - NULL, /* class_part_initialize */ - False, /* class_inited */ - XawAsciiSrcInitialize, /* 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 */ - XawAsciiSrcDestroy, /* destroy */ - NULL, /* resize */ - NULL, /* expose */ - XawAsciiSrcSetValues, /* set_values */ - NULL, /* set_values_hook */ - NULL, /* set_values_almost */ - XawAsciiSrcGetValuesHook, /* get_values_hook */ - NULL, /* accept_focus */ - XtVersion, /* version */ - NULL, /* callback_private */ - NULL, /* tm_table */ - NULL, /* query_geometry */ - NULL, /* display_accelerator */ - NULL, /* extension */ - }, - /* text_src */ - { - ReadText, /* Read */ - ReplaceText, /* Replace */ - Scan, /* Scan */ - Search, /* Search */ - XtInheritSetSelection, /* SetSelection */ - XtInheritConvertSelection, /* ConvertSelection */ - }, - /* ascii_src */ - { - NULL, /* extension */ - }, -}; - -WidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec; - -static XrmQuark Qstring, Qfile; - -/* - * Implementation - */ -/* - * Function: - * XawAsciiSrcClassInitialize() - * - * Description: - * Initializes the asciiSrcObjectClass and install the converters for - * AsciiType <-> String. - */ -static void -XawAsciiSrcClassInitialize(void) -{ - XawInitializeWidgetSet(); - Qstring = XrmPermStringToQuark(XtEstring); - Qfile = XrmPermStringToQuark(XtEfile); - XtAddConverter(XtRString, XtRAsciiType, CvtStringToAsciiType, NULL, 0); - XtSetTypeConverter(XtRAsciiType, XtRString, CvtAsciiTypeToString, - NULL, 0, XtCacheNone, NULL); -} - -/* - * Function: - * XawAsciiSrcInitialize - * - * Parameters: - * request - widget requested by the argument list - * cnew - new widget with both resource and non resource values - * args - (unused) - * num_args - (unused) - * - * Description: - * Initializes the ascii src object. - */ -/*ARGSUSED*/ -static void -XawAsciiSrcInitialize(Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - AsciiSrcObject src = (AsciiSrcObject)cnew; - FILE *file; - - /* - * Set correct flags (override resources) depending upon widget class - */ - src->text_src.text_format = XawFmt8Bit; - -#ifdef ASCII_DISK - if (XtIsSubclass(XtParent(cnew), asciiDiskWidgetClass)) { - src->ascii_src.type = XawAsciiFile; - src->ascii_src.string = src->ascii_src.filename; - } -#endif - -#ifdef ASCII_STRING - if (XtIsSubclass(XtParent(cnew), asciiStringWidgetClass)) { - src->ascii_src.use_string_in_place = True; - src->ascii_src.type = XawAsciiString; - } -#endif - -#ifdef OLDXAW - src->ascii_src.changes = False; -#else - src->text_src.changed = False; -#endif - src->ascii_src.allocated_string = False; - - if (src->ascii_src.use_string_in_place && src->ascii_src.string == NULL) - src->ascii_src.use_string_in_place = False; - - file = InitStringOrFile(src, src->ascii_src.type == XawAsciiFile); - LoadPieces(src, file, NULL); - - if (file != NULL) - fclose(file); -} - -/* - * Function: - * ReadText - * - * Parameters: - * w - AsciiSource widget - * 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. - */ -static XawTextPosition -ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length) -{ - AsciiSrcObject src = (AsciiSrcObject)w; - XawTextPosition count, start; - Piece *piece; -#ifndef OLDXAW - XawTextAnchor *anchor; - XawTextEntity *entity; - XawTextPosition offset, end = pos + length; - Bool state; - - end = XawMin(end, src->ascii_src.length); - while ((state = XawTextSourceAnchorAndEntity(w, pos, &anchor, &entity)) && - (entity->flags & XAW_TENTF_HIDE)) - pos = anchor->position + entity->offset + entity->length; - if (state == False || - !(entity->flags & XAW_TENTF_REPLACE)) { - while (entity) { - offset = anchor->position + entity->offset; - if (offset >= end) - break; - if (offset > pos && - (entity->flags & (XAW_TENTF_HIDE | XAW_TENTF_REPLACE))) { - end = XawMin(end, offset); - break; - } - if ((entity = entity->next) == NULL && - (anchor = XawTextSourceNextAnchor(w, anchor)) != NULL) - entity = anchor->entities; - } - } - else if (state && (entity->flags & XAW_TENTF_REPLACE) && pos < end) { - XawTextBlock *block = (XawTextBlock*)entity->data; - - offset = anchor->position + entity->offset; - end = XawMin(end, offset + block->length); - if ((length = end - pos) < 0) - length = 0; - text->length = length; - text->format = XawFmt8Bit; - if (length == 0) { - text->firstPos = end = offset + entity->length; - text->ptr = ""; - } - else { - text->firstPos = pos; - text->ptr = block->ptr + (pos - offset); - if (pos + length < offset + block->length) - end = pos + length; /* there is data left to be read */ - else - end = offset + entity->length; - } - - return (end); - } - - if ((length = end - pos) < 0) - length = 0; -#endif - - piece = FindPiece(src, pos, &start); - text->firstPos = pos; - text->ptr = piece->text + (pos - start); - count = piece->used - (pos - start); - text->length = Max(0, (length > count) ? count : length); - text->format = XawFmt8Bit; - - return (pos + text->length); -} - -/* - * Function: - * ReplaceText - * - * Parameters: - * w - AsciiSource object - * startPos - ends of text that will be replaced - * endPos - "" - * text - new text to be inserted into buffer at startPos - * - * Description: - * Replaces a block of text with new text. - * - * Returns: - * XawEditDone on success, XawEditError otherwise - */ -/*ARGSUSED*/ -static int -ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos, - XawTextBlock *text) -{ - AsciiSrcObject src = (AsciiSrcObject)w; - Piece *start_piece, *end_piece, *temp_piece; - XawTextPosition start_first, end_first; - int length, firstPos; - - /* - * Editing a read only source is not allowed - */ - if (src->text_src.edit_mode == XawtextRead) - return (XawEditError); - - start_piece = FindPiece(src, startPos, &start_first); - end_piece = FindPiece(src, endPos, &end_first); - -#ifndef OLDXAW - /* - * This is a big hack, but I can't think about a clever way to know - * if the character being moved forward has a negative lbearing. - * - */ - if (start_piece->used) { - int i; - - for (i = 0; i < src->text_src.num_text; i++) { - int line; - TextWidget ctx = (TextWidget)src->text_src.text[i]; - - for (line = 0; line < ctx->text.lt.lines; line++) - if (startPos < ctx->text.lt.info[line + 1].position) - break; - if (i < ctx->text.lt.lines && - startPos > ctx->text.lt.info[i].position) { - AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink; - XawTextAnchor *anchor; - XawTextEntity *entity; - XawTextProperty *property; - XFontStruct *font; - - if (XawTextSourceAnchorAndEntity(w, startPos, &anchor, &entity) && - (property = XawTextSinkGetProperty(ctx->text.sink, - entity->property)) != NULL && - (property->mask & XAW_TPROP_FONT)) - font = property->font; - else - font = sink->ascii_sink.font; - - if (font->min_bounds.lbearing < 0) { - int lbearing = font->min_bounds.lbearing; - unsigned char c = *(unsigned char*) - (start_piece->text + (startPos - start_first)); - - if (c == '\t' || c == '\n') - c = ' '; - else if ((c & 0177) < XawSP || c == 0177) { - if (sink->ascii_sink.display_nonprinting) - c = c > 0177 ? '\\' : c + '^'; - else - c = ' '; - } - if (font->per_char && - (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2)) - lbearing = font->per_char[c - font->min_char_or_byte2].lbearing; - if (lbearing < 0) - _XawTextNeedsUpdating(ctx, startPos - 1, startPos); - } - } - } - } - - -#endif - - /* - * Remove Old Stuff - */ - if (start_piece != end_piece) { - temp_piece = start_piece->next; - - /* - * If empty and not the only piece then remove it. - */ - if (((start_piece->used = startPos - start_first) == 0) - && !(start_piece->next == NULL && start_piece->prev == NULL)) - RemovePiece(src, start_piece); - - while (temp_piece != end_piece) { - temp_piece = temp_piece->next; - RemovePiece(src, temp_piece->prev); - } - - end_piece->used -= endPos - end_first; - if (end_piece->used != 0) - memmove(end_piece->text, end_piece->text + endPos - end_first, - (unsigned)end_piece->used); - } - else { /* We are fully in one piece */ - if ((start_piece->used -= endPos - startPos) == 0) { - if (!(start_piece->next == NULL && start_piece->prev == NULL)) - RemovePiece(src, start_piece); - } - else { - memmove(start_piece->text + (startPos - start_first), - start_piece->text + (endPos - start_first), - (unsigned)(start_piece->used - (startPos - start_first))); - if (src->ascii_src.use_string_in_place - && src->ascii_src.length - (endPos - startPos) - < src->ascii_src.piece_size - 1) - start_piece->text[src->ascii_src.length - (endPos - startPos)] = - '\0'; - } - } - - src->ascii_src.length += -(endPos - startPos) + text->length; - - if ( text->length != 0) { - /* - * Put in the New Stuff - */ - start_piece = FindPiece(src, startPos, &start_first); - - length = text->length; - firstPos = text->firstPos; - - while (length > 0) { - char *ptr; - int fill; - - if (src->ascii_src.use_string_in_place) { - if (start_piece->used == src->ascii_src.piece_size - 1) { - /* - * If we are in ascii string emulation mode. Then the - * string is not allowed to grow - */ - start_piece->used = src->ascii_src.length = - src->ascii_src.piece_size - 1; - start_piece->text[src->ascii_src.length] = '\0'; - return (XawEditError); - } - } - - if (start_piece->used == src->ascii_src.piece_size) { - BreakPiece(src, start_piece); - start_piece = FindPiece(src, startPos, &start_first); - } - - fill = Min((int)(src->ascii_src.piece_size - start_piece->used), - length); - - ptr = start_piece->text + (startPos - start_first); - memmove(ptr + fill, ptr, - (unsigned)(start_piece->used - (startPos - start_first))); - memcpy(ptr, text->ptr + firstPos, (unsigned)fill); - - startPos += fill; - firstPos += fill; - start_piece->used += fill; - length -= fill; - } - } - - if (src->ascii_src.use_string_in_place) - start_piece->text[start_piece->used] = '\0'; - -#ifdef OLDXAW - src->ascii_src.changes = True; - XtCallCallbacks(w, XtNcallback, NULL); -#endif - - return (XawEditDone); -} - -/* - * Function: - * Scan - * - * Parameters: - * w - AsciiSource 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 item found - * - * Note: - * While there are only 'n' characters in the file there are n+1 - * possible cursor positions (one before the first character and - * one after the last character - */ -static XawTextPosition -Scan(Widget w, register XawTextPosition position, XawTextScanType type, - XawTextScanDirection dir, int count, Bool include) -{ - AsciiSrcObject src = (AsciiSrcObject)w; - Piece *piece; - XawTextPosition first, first_eol_position = 0; - register char *ptr, *lim; - register int cnt = count; - register unsigned char c; - - if (dir == XawsdLeft) { - if (position <= 0) - return (0); - --position; - } - else if (position >= src->ascii_src.length) - return (src->ascii_src.length); - - piece = FindPiece(src, position, &first); - if (piece->used == 0) - return (0); - - ptr = (position - first) + piece->text; - - if (dir == XawsdRight) { - lim = piece->text + piece->used; - switch (type) { - case XawstEOL: - case XawstParagraph: - case XawstWhiteSpace: - case XawstAlphaNumeric: - for (; cnt > 0; cnt--) { - Bool non_space = False, first_eol = True; - - /*CONSTCOND*/ - while (True) { - if (ptr >= lim) { - piece = piece->next; - if (piece == NULL) /* End of text */ - return (src->ascii_src.length); - ptr = piece->text; - lim = piece->text + piece->used; - } - - c = *ptr++; - ++position; - - if (type == XawstEOL) { - if (c == '\n') - break; - } - else if (type == XawstAlphaNumeric) { - if (!isalnum(c)) { - if (non_space) - break; - } - else - non_space = True; - } - else if (type == XawstWhiteSpace) { - if (isspace(c)) { - if (non_space) - break; - } - else - non_space = True; - } - else { /* XawstParagraph */ - if (first_eol) { - if (c == '\n') { - first_eol_position = position; - first_eol = False; - } - } - else if (c == '\n') - break; - else if (!isspace(c)) - first_eol = True; - } - } - } - break; - case XawstPositions: - position += count; - return (position < src->ascii_src.length ? - position : src->ascii_src.length); - case XawstAll: - return (src->ascii_src.length); - default: - break; - } - if (!include) { - if (type == XawstParagraph) - position = first_eol_position; - if (count) - --position; - } - } - else { - lim = piece->text; - switch (type) { - case XawstEOL: - case XawstParagraph: - case XawstWhiteSpace: - case XawstAlphaNumeric: - for (; cnt > 0; cnt--) { - Bool non_space = False, first_eol = True; - - /*CONSTCOND*/ - while (True) { - if (ptr < lim) { - piece = piece->prev; - if (piece == NULL) /* Begining of text */ - return (0); - ptr = piece->text + piece->used - 1; - lim = piece->text; - } - - c = *ptr--; - --position; - - if (type == XawstEOL) { - if (c == '\n') - break; - } - else if (type == XawstAlphaNumeric) { - if (!isalnum(c)) { - if (non_space) - break; - } - else - non_space = True; - } - else if (type == XawstWhiteSpace) { - if (isspace(c)) { - if (non_space) - break; - } - else - non_space = True; - } - else { /* XawstParagraph */ - if (first_eol) { - if (c == '\n') { - first_eol_position = position; - first_eol = False; - } - } - else if (c == '\n') - break; - else if (!isspace(c)) - first_eol = True; - } - } - } - break; - case XawstPositions: - position -= count - 1; - return (position > 0 ? position : 0); - case XawstAll: - return (0); - default: - break; - } - if (!include) { - if (type == XawstParagraph) - position = first_eol_position; - if (count) - ++position; - } - position++; - } - - return (position); -} - -/* - * Function: - * Search - * - * Parameters: - * w - AsciiSource object - * position - the position to start scanning - * dir - direction to scan - * text - text block to search for - * - * Description: - * Searchs the text source for the text block passed. - * - * Returns: - * The position of the item found - */ -static XawTextPosition -Search(Widget w, register XawTextPosition position, XawTextScanDirection dir, - XawTextBlock *text) -{ - AsciiSrcObject src = (AsciiSrcObject)w; - register int count = 0; - register char *ptr, c; - char *str; - Piece *piece; - char *buf; - XawTextPosition first; - int cnt, case_sensitive; - - if (dir == XawsdLeft) { - if (position == 0) - return (XawTextSearchError); - position--; - } - - buf = XtMalloc((unsigned)sizeof(unsigned char) * text->length); - memcpy(buf, text->ptr, (unsigned)text->length); - piece = FindPiece(src, position, &first); - ptr = (position - first) + piece->text; - case_sensitive = text->firstPos; - - if (dir == XawsdRight) { - str = buf; - c = *str; - /*CONSTCOND*/ - while (1) { - if (*ptr++ == c - || (case_sensitive && isalpha(c) && isalpha(ptr[-1]) - && toupper(c) == toupper(ptr[-1]))) { - if (++count == text->length) - break; - c = *++str; - } - else if (count) { - ptr -= count; - str -= count; - position -= count; - count = 0; - c = *str; - - if (ptr < piece->text) { - do { - cnt = piece->text - ptr; - piece = piece->prev; - if (piece == NULL) { - XtFree(buf); - return (XawTextSearchError); - } - ptr = piece->text + piece->used - cnt; - } while (ptr < piece->text); - } - } - position++; - if (ptr >= (piece->text + piece->used)) { - do { - cnt = ptr - (piece->text + piece->used); - piece = piece->next; - if (piece == NULL) { - XtFree(buf); - return (XawTextSearchError); - } - ptr = piece->text + cnt; - } while (ptr >= (piece->text + piece->used)); - } - } - - position -= text->length - 1; - } - else { - str = buf + text->length - 1; - c = *str; - /*CONSTCOND*/ - while (1) { - if (*ptr-- == c - || (case_sensitive && isalpha(c) && isalpha(ptr[1]) - && toupper(c) == toupper(ptr[1]))) { - if (++count == text->length) - break; - c = *--str; - } - else if (count) { - ptr += count; - str += count; - position += count; - count = 0; - c = *str; - - if (ptr >= (piece->text + piece->used)) { - do { - cnt = ptr - (piece->text + piece->used); - piece = piece->next; - if (piece == NULL) { - XtFree(buf); - return (XawTextSearchError); - } - ptr = piece->text + cnt; - } while (ptr >= (piece->text + piece->used)); - } - } - position--; - if (ptr < piece->text) { - do { - cnt = piece->text - ptr; - piece = piece->prev; - if (piece == NULL) { - XtFree(buf); - return (XawTextSearchError); - } - ptr = piece->text + piece->used - cnt; - } while (ptr < piece->text); - } - } - } - - XtFree(buf); - - return (position); -} - -/* - * Function: - * XawAsciiSrcSetValues - * - * Parameters: - * current - current state of the widget - * request - what was requested - * cnew - what the widget will become - * args - representation of changed resources - * num_args - number of resources that have changed - * - * Description: - * Sets the values for the AsciiSource. - * - * Returns: - * True if redisplay is needed - */ -static Boolean -XawAsciiSrcSetValues(Widget current, Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - AsciiSrcObject src = (AsciiSrcObject)cnew; - AsciiSrcObject old_src = (AsciiSrcObject)current; - Bool total_reset = False, string_set = False; - FILE *file; - unsigned int i; - - if (old_src->ascii_src.use_string_in_place - != src->ascii_src.use_string_in_place) { - XtAppWarning(XtWidgetToApplicationContext(cnew), - "AsciiSrc: The XtNuseStringInPlace resource may " - "not be changed."); - src->ascii_src.use_string_in_place = - old_src->ascii_src.use_string_in_place; - } - - for (i = 0; i < *num_args ; i++) - if (streq(args[i].name, XtNstring)) { - string_set = True; - break; - } - - if (string_set || (old_src->ascii_src.type != src->ascii_src.type)) { - RemoveOldStringOrFile(old_src, string_set); /* remove old info */ - file = InitStringOrFile(src, string_set); /* Init new info */ - LoadPieces(src, file, NULL); /* load new info into internal buffers */ - if (file != NULL) - fclose(file); -#ifndef OLDXAW - for (i = 0; i < src->text_src.num_text; i++) - /* Tell text widget what happened */ - XawTextSetSource(src->text_src.text[i], cnew, 0); -#else - XawTextSetSource(XtParent(cnew), cnew, 0); -#endif - total_reset = True; - } - - if (old_src->ascii_src.ascii_length != src->ascii_src.ascii_length) - src->ascii_src.piece_size = src->ascii_src.ascii_length + 1; - - if (!total_reset && - old_src->ascii_src.piece_size != src->ascii_src.piece_size) { - String string = StorePiecesInString(old_src); - - FreeAllPieces(old_src); - LoadPieces(src, NULL, string); - XtFree(string); - } - - return (False); -} - -/* - * Function: - * XawAsciiSrcGetValuesHook - * - * Parameters: - * w - AsciiSource Widget - * args - argument list - * num_args - number of args - * - * Description: - * This is a get values hook routine that sets the - * values specific to the ascii source. - */ -static void -XawAsciiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args) -{ - AsciiSrcObject src = (AsciiSrcObject)w; - unsigned int i; - - if (src->ascii_src.type == XawAsciiString) { - for (i = 0; i < *num_args ; i++) - if (streq(args[i].name, XtNstring)) { - if (src->ascii_src.use_string_in_place) - *((char **)args[i].value) = src->ascii_src.first_piece->text; - else if (XawAsciiSave(w)) /* If save sucessful */ - *((char **)args[i].value) = src->ascii_src.string; - break; - } - } - } - -/* - * Function: - * XawAsciiSrcDestroy - * - * Parameters: - * src - Ascii source object to free - * - * Description: - * Destroys an ascii source (frees all data) - */ -static void -XawAsciiSrcDestroy(Widget w) -{ - RemoveOldStringOrFile((AsciiSrcObject) w, True); -} - -/* - * Public routines - */ -/* - * Function: - * XawAsciiSourceFreeString - * - * Parameters: - * w - AsciiSrc widget - * - * Description: - * Frees the string returned by a get values call - * on the string when the source is of type string. - */ -void -XawAsciiSourceFreeString(Widget w) -{ - AsciiSrcObject src = (AsciiSrcObject)w; - - /* If the src is really a multi, call the multi routine */ - if (XtIsSubclass(w, multiSrcObjectClass)) { - _XawMultiSourceFreeString(w); - return; - } - else if (!XtIsSubclass(w, asciiSrcObjectClass)) { - XtErrorMsg("bad argument", "asciiSource", "XawError", - "XawAsciiSourceFreeString's parameter must be " - "an asciiSrc or multiSrc.", - NULL, NULL); - } - - if (src->ascii_src.allocated_string && src->ascii_src.type != XawAsciiFile) { - src->ascii_src.allocated_string = False; - XtFree(src->ascii_src.string); - src->ascii_src.string = NULL; - } -} - -/* - * Function: - * XawAsciiSave - * - * Parameters: - * w - asciiSrc Widget - * - * Description: - * Saves all the pieces into a file or string as required. - * - * Returns: - * True if the save was successful - */ -Bool -XawAsciiSave(Widget w) -{ - AsciiSrcObject src = (AsciiSrcObject)w; - - /* If the src is really a multi, call the multi save */ - if (XtIsSubclass(w, multiSrcObjectClass )) - return (_XawMultiSave(w)); - - else if (!XtIsSubclass(w, asciiSrcObjectClass)) - XtErrorMsg("bad argument", "asciiSource", "XawError", - "XawAsciiSave's parameter must be an asciiSrc or multiSrc.", - NULL, NULL); - - /* - * If using the string in place then there is no need to play games - * to get the internal info into a readable string. - */ - if (src->ascii_src.use_string_in_place) - return (True); - - if (src->ascii_src.type == XawAsciiFile) { -#ifdef OLDXAW - if (!src->ascii_src.changes) -#else - if (!src->text_src.changed) /* No changes to save */ -#endif - return (True); - - if (WritePiecesToFile(src, src->ascii_src.string) == False) - return (False); - } - else { - if (src->ascii_src.allocated_string == True) - XtFree(src->ascii_src.string); - else - src->ascii_src.allocated_string = True; - - src->ascii_src.string = StorePiecesInString(src); - } -#ifdef OLDXAW - src->ascii_src.changes = False; -#else - src->text_src.changed = False; -#endif - - return (True); -} - -/* - * Function: - * XawAsciiSaveAsFile - * - * Arguments: - * w - AsciiSrc widget - * name - name of the file to save this file into - * - * Description: - * Save the current buffer as a file. - * - * Returns: - * True if the save was sucessful - */ -Bool -XawAsciiSaveAsFile(Widget w, _Xconst char *name) -{ - AsciiSrcObject src = (AsciiSrcObject)w; - Bool ret; - - /* If the src is really a multi, call the multi save */ - - if (XtIsSubclass( w, multiSrcObjectClass)) - return (_XawMultiSaveAsFile(w, name)); - - else if (!XtIsSubclass(w, asciiSrcObjectClass)) - XtErrorMsg("bad argument", "asciiSource", "XawError", - "XawAsciiSaveAsFile's 1st parameter must be an " - "asciiSrc or multiSrc.", - NULL, NULL); - - if (src->ascii_src.type == XawAsciiFile) - ret = WritePiecesToFile(src, (String)name); - else { - String string = StorePiecesInString(src); - - ret = WriteToFile(string, (String)name, src->ascii_src.length); - XtFree(string); - } - - return (ret); -} - -/* - * Function: - * XawAsciiSourceChanged - * - * Parameters: - * w - ascii source widget - * - * Description: - * Returns true if the source has changed since last saved. - * - * Returns: - * A Boolean (see description). - */ -Bool -XawAsciiSourceChanged(Widget w) -{ -#ifdef OLDXAW - if (XtIsSubclass(w, multiSrcObjectClass)) - return (((MultiSrcObject)w)->multi_src.changes); - - if (XtIsSubclass(w, asciiSrcObjectClass)) - return (((AsciiSrcObject)w)->ascii_src.changes); -#else - if (XtIsSubclass(w, textSrcObjectClass)) - return (((TextSrcObject)w)->textSrc.changed); -#endif - XtErrorMsg("bad argument", "asciiSource", "XawError", - "XawAsciiSourceChanged parameter must be an " - "asciiSrc or multiSrc.", - NULL, NULL); - - return (True); -} - -/* - * Private Functions - */ -static void -RemoveOldStringOrFile(AsciiSrcObject src, Bool checkString) -{ - FreeAllPieces(src); - - if (checkString && src->ascii_src.allocated_string) { - XtFree(src->ascii_src.string); - src->ascii_src.allocated_string = False; - src->ascii_src.string = NULL; - } -} - -/* - * Function: - * WriteToFile - * - * Parameters: - * string - string to write - * name - the name of the file - * - * Description: - * Write the string specified to the begining of the file specified. - * - * Returns: - * returns True if sucessful, False otherwise - */ -static Bool -WriteToFile(String string, String name, unsigned length) -{ - int fd; - - if ((fd = creat(name, 0666)) == -1) - return (False); - - if (write(fd, string, length) == -1) { - close(fd); - return (False); - } - - if (close(fd) == -1) - return (False); - - return (True); -} - -/* - * Function: - * WritePiecesToFile - * - * Parameters: - * src - ascii source object - * name - name of the file - * - * Description: - * Almost identical to WriteToFile, but only works for ascii src objects - * of type XawAsciiFile. This function avoids allocating temporary memory, - * what can be useful when editing very large files. - * - * Returns: - * returns True if sucessful, False otherwise - */ -static Bool -WritePiecesToFile(AsciiSrcObject src, String name) -{ - Piece *piece; - int fd; - - if (src->ascii_src.data_compression) { - Piece *tmp; - - piece = src->ascii_src.first_piece; - while (piece) { - int bytes = src->ascii_src.piece_size - piece->used; - - if (bytes > 0 && (tmp = piece->next) != NULL) { - bytes = XawMin(bytes, tmp->used); - memcpy(piece->text + piece->used, tmp->text, bytes); - memmove(tmp->text, tmp->text + bytes, tmp->used - bytes); - piece->used += bytes; - if ((tmp->used -= bytes) == 0) { - RemovePiece(src, tmp); - continue; - } - } - piece = piece->next; - } - } - - if ((fd = creat(name, 0666)) == -1) - return (False); - - for (piece = src->ascii_src.first_piece; piece; piece = piece->next) - if (write(fd, piece->text, piece->used) == -1) { - close(fd); - return (False); - } - - if (close(fd) == -1) - return (False); - - return (True); -} - -/* - * Function: - * StorePiecesInString - * - * Parameters: - * data - ascii pointer data - * - * Description: - * Store the pieces in memory into a standard ascii string. - */ -static String -StorePiecesInString(AsciiSrcObject src) -{ - String string; - XawTextPosition first; - Piece *piece; - - string = XtMalloc((unsigned)(src->ascii_src.length + 1)); - - for (first = 0, piece = src->ascii_src.first_piece ; piece != NULL; - first += piece->used, piece = piece->next) - memcpy(string + first, piece->text, (unsigned)piece->used); - - string[src->ascii_src.length] = '\0'; - - /* - * This will refill all pieces to capacity - */ - if (src->ascii_src.data_compression) { - FreeAllPieces(src); - LoadPieces(src, NULL, string); - } - - return (string); -} - -/* - * Function: - * InitStringOrFile - * - * Parameters: - * src - AsciiSource - * - * Description: - * Initializes the string or file. - */ -static FILE * -InitStringOrFile(AsciiSrcObject src, Bool newString) -{ - mode_t open_mode = 0; - const char *fdopen_mode = NULL; - int fd; - FILE *file; - - if (src->ascii_src.type == XawAsciiString) { - if (src->ascii_src.string == NULL) - src->ascii_src.length = 0; - - else if (!src->ascii_src.use_string_in_place) { - src->ascii_src.string = XtNewString(src->ascii_src.string); - src->ascii_src.allocated_string = True; - src->ascii_src.length = strlen(src->ascii_src.string); - } - - if (src->ascii_src.use_string_in_place) { - if (src->ascii_src.string != NULL) - src->ascii_src.length = strlen(src->ascii_src.string); - /* In case the length resource is incorrectly set */ - if (src->ascii_src.length > src->ascii_src.ascii_length) - src->ascii_src.ascii_length = src->ascii_src.length; - - if (src->ascii_src.ascii_length == MAGIC_VALUE) - src->ascii_src.piece_size = src->ascii_src.length; - else - src->ascii_src.piece_size = src->ascii_src.ascii_length + 1; - } - - return (NULL); - } - - /* - * type is XawAsciiFile - */ - src->ascii_src.is_tempfile = False; - - switch (src->text_src.edit_mode) { - case XawtextRead: - if (src->ascii_src.string == NULL) - XtErrorMsg("NoFile", "asciiSourceCreate", "XawError", - "Creating a read only disk widget and no file specified.", - NULL, NULL); - open_mode = O_RDONLY; - fdopen_mode = "r"; - break; - case XawtextAppend: - case XawtextEdit: - if (src->ascii_src.string == NULL) { - src->ascii_src.string = "*ascii-src*"; - src->ascii_src.is_tempfile = True; - } - else { -/* O_NOFOLLOW is a FreeBSD & Linux extension */ -#ifdef O_NOFOLLOW - open_mode = O_RDWR | O_NOFOLLOW; -#else - open_mode = O_RDWR; /* unsafe; subject to race conditions */ -#endif /* O_NOFOLLOW */ - fdopen_mode = "r+"; - } - break; - default: - XtErrorMsg("badMode", "asciiSourceCreate", "XawError", - "Bad editMode for ascii source; must be Read, " - "Append or Edit.", - NULL, NULL); - } - - /* If is_tempfile, allocate a private copy of the text - * Unlikely to be changed, just to set allocated_string */ - if (newString || src->ascii_src.is_tempfile) { - src->ascii_src.string = XtNewString(src->ascii_src.string); - src->ascii_src.allocated_string = True; - } - - if (!src->ascii_src.is_tempfile) { - if ((fd = open(src->ascii_src.string, open_mode, 0666)) != -1) { - if ((file = fdopen(fd, fdopen_mode))) { - (void)fseek(file, 0, SEEK_END); - src->ascii_src.length = (XawTextPosition)ftell(file); - return (file); - } - } - { - String params[2]; - Cardinal num_params = 2; - - params[0] = src->ascii_src.string; - params[1] = strerror(errno); - XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), - "openError", "asciiSourceCreate", "XawWarning", - "Cannot open file %s; %s", params, &num_params); - } - } - src->ascii_src.length = 0; - return (NULL); -} - -static void -LoadPieces(AsciiSrcObject src, FILE *file, char *string) -{ - char *ptr; - Piece *piece = NULL; - XawTextPosition left; - - if (string == NULL) { - if (src->ascii_src.type == XawAsciiFile) { - if (src->ascii_src.length != 0) { - int len; - - left = 0; - fseek(file, 0, 0); - while (left < src->ascii_src.length) { - ptr = XtMalloc((unsigned)src->ascii_src.piece_size); - if ((len = fread(ptr, (Size_t)sizeof(unsigned char), - (Size_t)src->ascii_src.piece_size, file)) < 0) - XtErrorMsg("readError", "asciiSourceCreate", "XawError", - "fread returned error.", NULL, NULL); - piece = AllocNewPiece(src, piece); - piece->text = ptr; - piece->used = XawMin(len, src->ascii_src.piece_size); - left += piece->used; - } - } - else { - piece = AllocNewPiece(src, NULL); - piece->text = XtMalloc((unsigned)src->ascii_src.piece_size); - piece->used = 0; - } - return; - } - else - string = src->ascii_src.string; - } - - if (src->ascii_src.use_string_in_place) { - piece = AllocNewPiece(src, piece); - piece->used = XawMin(src->ascii_src.length, src->ascii_src.piece_size); - piece->text = src->ascii_src.string; - return; - } - - ptr = string; - left = src->ascii_src.length; - do { - piece = AllocNewPiece(src, piece); - - piece->text = XtMalloc((unsigned)src->ascii_src.piece_size); - piece->used = XawMin(left, src->ascii_src.piece_size); - if (piece->used != 0) - memcpy(piece->text, ptr, (unsigned)piece->used); - - left -= piece->used; - ptr += piece->used; - } while (left > 0); -} - -/* - * Function: - * AllocNewPiece - * - * Parameters: - * src - AsciiSrc Widget - * prev - piece just before this one, or NULL - * - * Description: - * Allocates a new piece of memory. - * - * Returns: - * The allocated piece - */ -static Piece * -AllocNewPiece(AsciiSrcObject src, Piece *prev) -{ - Piece *piece = XtNew(Piece); - - if (prev == NULL) { - src->ascii_src.first_piece = piece; - piece->next = NULL; - } - else { - if (prev->next != NULL) - (prev->next)->prev = piece; - piece->next = prev->next; - prev->next = piece; - } - - piece->prev = prev; - - return (piece); -} - -/* - * Function: - * FreeAllPieces - * - * Parameters: - * src - AsciiSrc Widget - * - * Description: - * Frees all the pieces. - */ -static void -FreeAllPieces(AsciiSrcObject src) -{ - Piece *next, * first = src->ascii_src.first_piece; - -#ifdef DEBUG - if (first->prev != NULL) - printf("Xaw AsciiSrc Object: possible memory leak in FreeAllPieces().\n"); -#endif - - for (; first != NULL ; first = next) { - next = first->next; - RemovePiece(src, first); - } -} - -/* - * Function: - * RemovePiece - * - * Parameters: - * piece - piece to remove - * - * Description: - * Removes a piece from the list. - */ -static void -RemovePiece(AsciiSrcObject src, Piece *piece) -{ - if (piece->prev == NULL) - src->ascii_src.first_piece = piece->next; - else - piece->prev->next = piece->next; - - if (piece->next != NULL) - piece->next->prev = piece->prev; - - if (!src->ascii_src.use_string_in_place) - XtFree(piece->text); - - XtFree((char *)piece); -} - -/* - * Function: - * FindPiece - * - * Parameters: - * src - AsciiSrc Widget - * position - position that we are searching for - * first - position of the first character in this piece (return) - * - * Description: - * Finds the piece containing the position indicated. - * - * Returns: - * the piece that contains this position - */ -static Piece * -FindPiece(AsciiSrcObject src, XawTextPosition position, XawTextPosition *first) -{ - Piece *old_piece, *piece; - XawTextPosition temp; - - for (old_piece = NULL, piece = src->ascii_src.first_piece, temp = 0; - piece; old_piece = piece, piece = piece->next) - if ((temp += piece->used) > position) { - *first = temp - piece->used; - return (piece); - } - - *first = temp - (old_piece ? old_piece->used : 0); - - return (old_piece); /* if we run off the end the return the last piece */ -} - -/* - * Function: - * BreakPiece - * - * Parameters: - * src - AsciiSrc Widget - * piece - piece to break - * - * Description: - * Breaks a full piece into two new pieces. - */ -#define HALF_PIECE (src->ascii_src.piece_size >> 1) -static void -BreakPiece(AsciiSrcObject src, Piece *piece) -{ - Piece *cnew = AllocNewPiece(src, piece); - - cnew->text = XtMalloc((unsigned)src->ascii_src.piece_size); - memcpy(cnew->text, piece->text + HALF_PIECE, - (unsigned)(src->ascii_src.piece_size - HALF_PIECE)); - piece->used = HALF_PIECE; - cnew->used = src->ascii_src.piece_size - HALF_PIECE; -} - -/*ARGSUSED*/ -static void -CvtStringToAsciiType(XrmValuePtr args, Cardinal *num_args, - XrmValuePtr fromVal, XrmValuePtr toVal) -{ - static XawAsciiType type; - XrmQuark q; - char name[7]; - - XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name)); - q = XrmStringToQuark(name); - - if (q == Qstring) - type = XawAsciiString; - else if (q == Qfile) - type = XawAsciiFile; - else { - toVal->size = 0; - toVal->addr = NULL; - XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType); - } - - toVal->size = sizeof(XawAsciiType); - toVal->addr = (XPointer)&type; -} - -/*ARGSUSED*/ -static Boolean -CvtAsciiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args, - XrmValuePtr fromVal, XrmValuePtr toVal, - XtPointer *data) -{ - static String buffer; - Cardinal size; - - switch (*(XawAsciiType *)fromVal->addr) { - case XawAsciiFile: - buffer = XtEfile; - break; - case XawAsciiString: - buffer = XtEstring; - break; - default: - XawTypeToStringWarning(dpy, XtRAsciiType); - toVal->addr = NULL; - toVal->size = 0; - return (False); - } - - size = strlen(buffer) + 1; - if (toVal->addr != NULL) { - if (toVal->size < size) { - toVal->size = size; - return (False); - } - strcpy((char *)toVal->addr, buffer); - } - else - toVal->addr = (XPointer)buffer; - toVal->size = sizeof(String); - - return (True); -} - -/*ARGSUSED*/ -static void -GetDefaultPieceSize(Widget w, int offset, XrmValue *value) -{ - static XPointer pagesize; - - if (pagesize == NULL) { - pagesize = (XPointer)((long)_XawGetPageSize()); - if (pagesize < (XPointer)BUFSIZ) - pagesize = (XPointer)BUFSIZ; - } - - value->addr = (XPointer)&pagesize; -} - -#if (defined(ASCII_STRING) || defined(ASCII_DISK)) -# include <X11/Xaw/Cardinals.h> -#endif - -#ifdef ASCII_STRING -/* - * Compatability functions. - */ -/* - * Function: - * AsciiStringSourceCreate - * - * Parameters: - * parent - widget that will own this source - * args - the argument list - * num_args - "" - * - * Description: - * Creates a string source. - * - * Returns: - * A pointer to the new text source. - */ -Widget -XawStringSourceCreate(Widget parent, ArgList args, Cardinal num_args) -{ - XawTextSource src; - ArgList ascii_args; - Arg temp[2]; - - XtSetArg(temp[0], XtNtype, XawAsciiString); - XtSetArg(temp[1], XtNuseStringInPlace, True); - ascii_args = XtMergeArgLists(temp, TWO, args, num_args); - - src = XtCreateWidget("genericAsciiString", asciiSrcObjectClass, parent, - ascii_args, num_args + TWO); - XtFree((char *)ascii_args); - - return (src); -} - -/* - * This is hacked up to try to emulate old functionality, it - * may not work, as I have not old code to test it on. - * - * Chris D. Peterson 8/31/89. - */ -void -XawTextSetLastPos(Widget w, XawTextPosition lastPos) -{ - AsciiSrcObject src = (AsciiSrcObject)XawTextGetSource(w); - - src->ascii_src.piece_size = lastPos; -} -#endif /* ASCII_STRING */ - -#ifdef ASCII_DISK -/* - * Function: - * AsciiDiskSourceCreate - * - * Parameters: - * parent - widget that will own this source - * args - argument list - * num_args - "" - * - * Description: - * Creates a disk source. - * - * Returns: - * A pointer to the new text source - */ -Widget -XawDiskSourceCreate(Widget parent, ArgList args, Cardinal num_args) -{ - XawTextSource src; - ArgList ascii_args; - Arg temp[1]; - int i; - - XtSetArg(temp[0], XtNtype, XawAsciiFile); - ascii_args = XtMergeArgLists(temp, ONE, args, num_args); - num_args++; - - for (i = 0; i < num_args; i++) - if (streq(ascii_args[i].name, XtNfile) - || streq(ascii_args[i].name, XtCFile)) - ascii_args[i].name = XtNstring; - - src = XtCreateWidget("genericAsciiDisk", asciiSrcObjectClass, parent, - ascii_args, num_args); - XtFree((char *)ascii_args); - - return (src); -} -#endif /* ASCII_DISK */ +/*
+
+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.
+
+*/
+
+/*
+ * AsciiSrc.c - AsciiSrc object. (For use with the text widget).
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xmu/CharSet.h>
+#include <X11/Xmu/Misc.h>
+#include <X11/Xaw/XawInit.h>
+#include <X11/Xaw/AsciiSrcP.h>
+#include <X11/Xaw/MultiSrcP.h>
+#ifndef OLDXAW
+#include <X11/Xaw/TextSinkP.h>
+#include <X11/Xaw/AsciiSinkP.h>
+#endif
+#include "Private.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#if (defined(ASCII_STRING) || defined(ASCII_DISK))
+#include <X11/Xaw/AsciiText.h> /* for Widget Classes */
+#endif
+
+#ifdef X_NOT_POSIX
+#define Off_t long
+#define Size_t unsigned int
+#else
+#define Off_t off_t
+#define Size_t size_t
+#endif
+
+#define MAGIC_VALUE ((XawTextPosition)-1)
+#define streq(a, b) (strcmp((a), (b)) == 0)
+
+/*
+ * Class Methods
+ */
+static void XawAsciiSrcClassInitialize(void);
+static void XawAsciiSrcDestroy(Widget);
+static void XawAsciiSrcGetValuesHook(Widget, ArgList, Cardinal*);
+static void XawAsciiSrcInitialize(Widget, Widget, ArgList, Cardinal*);
+static Boolean XawAsciiSrcSetValues(Widget, Widget, Widget,
+ ArgList, Cardinal*);
+static XawTextPosition ReadText(Widget, XawTextPosition, XawTextBlock*, int);
+static int ReplaceText(Widget, XawTextPosition, XawTextPosition,
+ XawTextBlock*);
+static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType,
+ XawTextScanDirection, int, Bool);
+static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection,
+ XawTextBlock*);
+
+/*
+ * Prototypes
+ */
+static Piece *AllocNewPiece(AsciiSrcObject, Piece*);
+static void BreakPiece(AsciiSrcObject, Piece*);
+static Boolean CvtAsciiTypeToString(Display*, XrmValuePtr, Cardinal*,
+ XrmValuePtr, XrmValuePtr, XtPointer*);
+static void CvtStringToAsciiType(XrmValuePtr, Cardinal*,
+ XrmValuePtr, XrmValuePtr);
+static Piece *FindPiece(AsciiSrcObject, XawTextPosition, XawTextPosition*);
+static void FreeAllPieces(AsciiSrcObject);
+static FILE *InitStringOrFile(AsciiSrcObject, Bool);
+static void LoadPieces(AsciiSrcObject, FILE*, char*);
+static void RemoveOldStringOrFile(AsciiSrcObject, Bool);
+static void RemovePiece(AsciiSrcObject, Piece*);
+static String StorePiecesInString(AsciiSrcObject);
+static Bool WriteToFile(String, String, unsigned);
+static Bool WritePiecesToFile(AsciiSrcObject, String);
+static void GetDefaultPieceSize(Widget, int, XrmValue*);
+
+/*
+ * More Prototypes
+ */
+#ifdef ASCII_DISK
+Widget XawAsciiDiskSourceCreate(Widget, ArgList, Cardinal);
+#endif
+#ifdef ASCII_STRING
+Widget XawStringSourceCreate(Widget, ArgList, Cardinal);
+void XawTextSetLastPos(Widget, XawTextPosition);
+#endif
+
+/*
+ * Initialization
+ */
+#define offset(field) XtOffsetOf(AsciiSrcRec, ascii_src.field)
+static XtResource resources[] = {
+ {
+ XtNstring,
+ XtCString,
+ XtRString,
+ sizeof(char*),
+ offset(string),
+ XtRString,
+ NULL
+ },
+ {
+ XtNtype,
+ XtCType,
+ XtRAsciiType,
+ sizeof(XawAsciiType),
+ offset(type),
+ XtRImmediate,
+ (XtPointer)XawAsciiString
+ },
+ {
+ XtNdataCompression,
+ XtCDataCompression,
+ XtRBoolean,
+ sizeof(Boolean),
+ offset(data_compression),
+ XtRImmediate,
+ (XtPointer)True
+ },
+ {
+ XtNpieceSize,
+ XtCPieceSize,
+ XtRInt,
+ sizeof(XawTextPosition),
+ offset(piece_size),
+ XtRCallProc,
+ (XtPointer)GetDefaultPieceSize
+ },
+#ifdef OLDXAW
+ {
+ XtNcallback,
+ XtCCallback,
+ XtRCallback,
+ sizeof(XtPointer),
+ offset(callback),
+ XtRCallback,
+ (XtPointer)NULL
+ },
+#endif
+ {
+ XtNuseStringInPlace,
+ XtCUseStringInPlace,
+ XtRBoolean,
+ sizeof(Boolean),
+ offset(use_string_in_place),
+ XtRImmediate,
+ (XtPointer)False
+ },
+ {
+ XtNlength,
+ XtCLength,
+ XtRInt,
+ sizeof(int),
+ offset(ascii_length),
+ XtRImmediate,
+ (XtPointer)MAGIC_VALUE
+ },
+#ifdef ASCII_DISK
+ {
+ XtNfile,
+ XtCFile,
+ XtRString,
+ sizeof(String),
+ offset(filename),
+ XtRString,
+ NULL
+ },
+#endif /* ASCII_DISK */
+};
+#undef offset
+
+
+#define Superclass (&textSrcClassRec)
+AsciiSrcClassRec asciiSrcClassRec = {
+ /* object */
+ {
+ (WidgetClass)Superclass, /* superclass */
+ "AsciiSrc", /* class_name */
+ sizeof(AsciiSrcRec), /* widget_size */
+ XawAsciiSrcClassInitialize, /* class_initialize */
+ NULL, /* class_part_initialize */
+ False, /* class_inited */
+ XawAsciiSrcInitialize, /* 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 */
+ XawAsciiSrcDestroy, /* destroy */
+ NULL, /* resize */
+ NULL, /* expose */
+ XawAsciiSrcSetValues, /* set_values */
+ NULL, /* set_values_hook */
+ NULL, /* set_values_almost */
+ XawAsciiSrcGetValuesHook, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* version */
+ NULL, /* callback_private */
+ NULL, /* tm_table */
+ NULL, /* query_geometry */
+ NULL, /* display_accelerator */
+ NULL, /* extension */
+ },
+ /* text_src */
+ {
+ ReadText, /* Read */
+ ReplaceText, /* Replace */
+ Scan, /* Scan */
+ Search, /* Search */
+ XtInheritSetSelection, /* SetSelection */
+ XtInheritConvertSelection, /* ConvertSelection */
+ },
+ /* ascii_src */
+ {
+ NULL, /* extension */
+ },
+};
+
+WidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec;
+
+static XrmQuark Qstring, Qfile;
+
+/*
+ * Implementation
+ */
+/*
+ * Function:
+ * XawAsciiSrcClassInitialize()
+ *
+ * Description:
+ * Initializes the asciiSrcObjectClass and install the converters for
+ * AsciiType <-> String.
+ */
+static void
+XawAsciiSrcClassInitialize(void)
+{
+ XawInitializeWidgetSet();
+ Qstring = XrmPermStringToQuark(XtEstring);
+ Qfile = XrmPermStringToQuark(XtEfile);
+ XtAddConverter(XtRString, XtRAsciiType, CvtStringToAsciiType, NULL, 0);
+ XtSetTypeConverter(XtRAsciiType, XtRString, CvtAsciiTypeToString,
+ NULL, 0, XtCacheNone, NULL);
+}
+
+/*
+ * Function:
+ * XawAsciiSrcInitialize
+ *
+ * Parameters:
+ * request - widget requested by the argument list
+ * cnew - new widget with both resource and non resource values
+ * args - (unused)
+ * num_args - (unused)
+ *
+ * Description:
+ * Initializes the ascii src object.
+ */
+/*ARGSUSED*/
+static void
+XawAsciiSrcInitialize(Widget request, Widget cnew,
+ ArgList args, Cardinal *num_args)
+{
+ AsciiSrcObject src = (AsciiSrcObject)cnew;
+ FILE *file;
+
+ /*
+ * Set correct flags (override resources) depending upon widget class
+ */
+ src->text_src.text_format = XawFmt8Bit;
+
+#ifdef ASCII_DISK
+ if (XtIsSubclass(XtParent(cnew), asciiDiskWidgetClass)) {
+ src->ascii_src.type = XawAsciiFile;
+ src->ascii_src.string = src->ascii_src.filename;
+ }
+#endif
+
+#ifdef ASCII_STRING
+ if (XtIsSubclass(XtParent(cnew), asciiStringWidgetClass)) {
+ src->ascii_src.use_string_in_place = True;
+ src->ascii_src.type = XawAsciiString;
+ }
+#endif
+
+#ifdef OLDXAW
+ src->ascii_src.changes = False;
+#else
+ src->text_src.changed = False;
+#endif
+ src->ascii_src.allocated_string = False;
+
+ if (src->ascii_src.use_string_in_place && src->ascii_src.string == NULL)
+ src->ascii_src.use_string_in_place = False;
+
+ file = InitStringOrFile(src, src->ascii_src.type == XawAsciiFile);
+ LoadPieces(src, file, NULL);
+
+ if (file != NULL)
+ fclose(file);
+}
+
+/*
+ * Function:
+ * ReadText
+ *
+ * Parameters:
+ * w - AsciiSource widget
+ * 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.
+ */
+static XawTextPosition
+ReadText(Widget w, XawTextPosition pos, XawTextBlock *text, int length)
+{
+ AsciiSrcObject src = (AsciiSrcObject)w;
+ XawTextPosition count, start;
+ Piece *piece;
+#ifndef OLDXAW
+ XawTextAnchor *anchor;
+ XawTextEntity *entity;
+ XawTextPosition offset, end = pos + length;
+ Bool state;
+
+ end = XawMin(end, src->ascii_src.length);
+ while ((state = XawTextSourceAnchorAndEntity(w, pos, &anchor, &entity)) &&
+ (entity->flags & XAW_TENTF_HIDE))
+ pos = anchor->position + entity->offset + entity->length;
+ if (state == False ||
+ !(entity->flags & XAW_TENTF_REPLACE)) {
+ while (entity) {
+ offset = anchor->position + entity->offset;
+ if (offset >= end)
+ break;
+ if (offset > pos &&
+ (entity->flags & (XAW_TENTF_HIDE | XAW_TENTF_REPLACE))) {
+ end = XawMin(end, offset);
+ break;
+ }
+ if ((entity = entity->next) == NULL &&
+ (anchor = XawTextSourceNextAnchor(w, anchor)) != NULL)
+ entity = anchor->entities;
+ }
+ }
+ else if (state && (entity->flags & XAW_TENTF_REPLACE) && pos < end) {
+ XawTextBlock *block = (XawTextBlock*)entity->data;
+
+ offset = anchor->position + entity->offset;
+ end = XawMin(end, offset + block->length);
+ if ((length = end - pos) < 0)
+ length = 0;
+ text->length = length;
+ text->format = XawFmt8Bit;
+ if (length == 0) {
+ text->firstPos = end = offset + entity->length;
+ text->ptr = "";
+ }
+ else {
+ text->firstPos = pos;
+ text->ptr = block->ptr + (pos - offset);
+ if (pos + length < offset + block->length)
+ end = pos + length; /* there is data left to be read */
+ else
+ end = offset + entity->length;
+ }
+
+ return (end);
+ }
+
+ if ((length = end - pos) < 0)
+ length = 0;
+#endif
+
+ piece = FindPiece(src, pos, &start);
+ text->firstPos = pos;
+ text->ptr = piece->text + (pos - start);
+ count = piece->used - (pos - start);
+ text->length = Max(0, (length > count) ? count : length);
+ text->format = XawFmt8Bit;
+
+ return (pos + text->length);
+}
+
+/*
+ * Function:
+ * ReplaceText
+ *
+ * Parameters:
+ * w - AsciiSource object
+ * startPos - ends of text that will be replaced
+ * endPos - ""
+ * text - new text to be inserted into buffer at startPos
+ *
+ * Description:
+ * Replaces a block of text with new text.
+ *
+ * Returns:
+ * XawEditDone on success, XawEditError otherwise
+ */
+/*ARGSUSED*/
+static int
+ReplaceText(Widget w, XawTextPosition startPos, XawTextPosition endPos,
+ XawTextBlock *text)
+{
+ AsciiSrcObject src = (AsciiSrcObject)w;
+ Piece *start_piece, *end_piece, *temp_piece;
+ XawTextPosition start_first, end_first;
+ int length, firstPos;
+
+ /*
+ * Editing a read only source is not allowed
+ */
+ if (src->text_src.edit_mode == XawtextRead)
+ return (XawEditError);
+
+ start_piece = FindPiece(src, startPos, &start_first);
+ end_piece = FindPiece(src, endPos, &end_first);
+
+#ifndef OLDXAW
+ /*
+ * This is a big hack, but I can't think about a clever way to know
+ * if the character being moved forward has a negative lbearing.
+ *
+ */
+ if (start_piece->used) {
+ int i;
+
+ for (i = 0; i < src->text_src.num_text; i++) {
+ int line;
+ TextWidget ctx = (TextWidget)src->text_src.text[i];
+
+ for (line = 0; line < ctx->text.lt.lines; line++)
+ if (startPos < ctx->text.lt.info[line + 1].position)
+ break;
+ if (i < ctx->text.lt.lines &&
+ startPos > ctx->text.lt.info[i].position) {
+ AsciiSinkObject sink = (AsciiSinkObject)ctx->text.sink;
+ XawTextAnchor *anchor;
+ XawTextEntity *entity;
+ XawTextProperty *property;
+ XFontStruct *font;
+
+ if (XawTextSourceAnchorAndEntity(w, startPos, &anchor, &entity) &&
+ (property = XawTextSinkGetProperty(ctx->text.sink,
+ entity->property)) != NULL &&
+ (property->mask & XAW_TPROP_FONT))
+ font = property->font;
+ else
+ font = sink->ascii_sink.font;
+
+ if (font->min_bounds.lbearing < 0) {
+ int lbearing = font->min_bounds.lbearing;
+ unsigned char c = *(unsigned char*)
+ (start_piece->text + (startPos - start_first));
+
+ if (c == '\t' || c == '\n')
+ c = ' ';
+ else if ((c & 0177) < XawSP || c == 0177) {
+ if (sink->ascii_sink.display_nonprinting)
+ c = c > 0177 ? '\\' : c + '^';
+ else
+ c = ' ';
+ }
+ if (font->per_char &&
+ (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
+ lbearing = font->per_char[c - font->min_char_or_byte2].lbearing;
+ if (lbearing < 0)
+ _XawTextNeedsUpdating(ctx, startPos - 1, startPos);
+ }
+ }
+ }
+ }
+
+
+#endif
+
+ /*
+ * Remove Old Stuff
+ */
+ if (start_piece != end_piece) {
+ temp_piece = start_piece->next;
+
+ /*
+ * If empty and not the only piece then remove it.
+ */
+ if (((start_piece->used = startPos - start_first) == 0)
+ && !(start_piece->next == NULL && start_piece->prev == NULL))
+ RemovePiece(src, start_piece);
+
+ while (temp_piece != end_piece) {
+ temp_piece = temp_piece->next;
+ RemovePiece(src, temp_piece->prev);
+ }
+
+ end_piece->used -= endPos - end_first;
+ if (end_piece->used != 0)
+ memmove(end_piece->text, end_piece->text + endPos - end_first,
+ (unsigned)end_piece->used);
+ }
+ else { /* We are fully in one piece */
+ if ((start_piece->used -= endPos - startPos) == 0) {
+ if (!(start_piece->next == NULL && start_piece->prev == NULL))
+ RemovePiece(src, start_piece);
+ }
+ else {
+ memmove(start_piece->text + (startPos - start_first),
+ start_piece->text + (endPos - start_first),
+ (unsigned)(start_piece->used - (startPos - start_first)));
+ if (src->ascii_src.use_string_in_place
+ && src->ascii_src.length - (endPos - startPos)
+ < src->ascii_src.piece_size - 1)
+ start_piece->text[src->ascii_src.length - (endPos - startPos)] =
+ '\0';
+ }
+ }
+
+ src->ascii_src.length += -(endPos - startPos) + text->length;
+
+ if ( text->length != 0) {
+ /*
+ * Put in the New Stuff
+ */
+ start_piece = FindPiece(src, startPos, &start_first);
+
+ length = text->length;
+ firstPos = text->firstPos;
+
+ while (length > 0) {
+ char *ptr;
+ int fill;
+
+ if (src->ascii_src.use_string_in_place) {
+ if (start_piece->used == src->ascii_src.piece_size - 1) {
+ /*
+ * If we are in ascii string emulation mode. Then the
+ * string is not allowed to grow
+ */
+ start_piece->used = src->ascii_src.length =
+ src->ascii_src.piece_size - 1;
+ start_piece->text[src->ascii_src.length] = '\0';
+ return (XawEditError);
+ }
+ }
+
+ if (start_piece->used == src->ascii_src.piece_size) {
+ BreakPiece(src, start_piece);
+ start_piece = FindPiece(src, startPos, &start_first);
+ }
+
+ fill = Min((int)(src->ascii_src.piece_size - start_piece->used),
+ length);
+
+ ptr = start_piece->text + (startPos - start_first);
+ memmove(ptr + fill, ptr,
+ (unsigned)(start_piece->used - (startPos - start_first)));
+ memcpy(ptr, text->ptr + firstPos, (unsigned)fill);
+
+ startPos += fill;
+ firstPos += fill;
+ start_piece->used += fill;
+ length -= fill;
+ }
+ }
+
+ if (src->ascii_src.use_string_in_place)
+ start_piece->text[start_piece->used] = '\0';
+
+#ifdef OLDXAW
+ src->ascii_src.changes = True;
+ XtCallCallbacks(w, XtNcallback, NULL);
+#endif
+
+ return (XawEditDone);
+}
+
+/*
+ * Function:
+ * Scan
+ *
+ * Parameters:
+ * w - AsciiSource 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 item found
+ *
+ * Note:
+ * While there are only 'n' characters in the file there are n+1
+ * possible cursor positions (one before the first character and
+ * one after the last character
+ */
+static XawTextPosition
+Scan(Widget w, register XawTextPosition position, XawTextScanType type,
+ XawTextScanDirection dir, int count, Bool include)
+{
+ AsciiSrcObject src = (AsciiSrcObject)w;
+ Piece *piece;
+ XawTextPosition first, first_eol_position = 0;
+ register char *ptr, *lim;
+ register int cnt = count;
+ register unsigned char c;
+
+ if (dir == XawsdLeft) {
+ if (position <= 0)
+ return (0);
+ --position;
+ }
+ else if (position >= src->ascii_src.length)
+ return (src->ascii_src.length);
+
+ piece = FindPiece(src, position, &first);
+ if (piece->used == 0)
+ return (0);
+
+ ptr = (position - first) + piece->text;
+
+ if (dir == XawsdRight) {
+ lim = piece->text + piece->used;
+ switch (type) {
+ case XawstEOL:
+ case XawstParagraph:
+ case XawstWhiteSpace:
+ case XawstAlphaNumeric:
+ for (; cnt > 0; cnt--) {
+ Bool non_space = False, first_eol = True;
+
+ /*CONSTCOND*/
+ while (True) {
+ if (ptr >= lim) {
+ piece = piece->next;
+ if (piece == NULL) /* End of text */
+ return (src->ascii_src.length);
+ ptr = piece->text;
+ lim = piece->text + piece->used;
+ }
+
+ c = *ptr++;
+ ++position;
+
+ if (type == XawstEOL) {
+ if (c == '\n')
+ break;
+ }
+ else if (type == XawstAlphaNumeric) {
+ if (!isalnum(c)) {
+ if (non_space)
+ break;
+ }
+ else
+ non_space = True;
+ }
+ else if (type == XawstWhiteSpace) {
+ if (isspace(c)) {
+ if (non_space)
+ break;
+ }
+ else
+ non_space = True;
+ }
+ else { /* XawstParagraph */
+ if (first_eol) {
+ if (c == '\n') {
+ first_eol_position = position;
+ first_eol = False;
+ }
+ }
+ else if (c == '\n')
+ break;
+ else if (!isspace(c))
+ first_eol = True;
+ }
+ }
+ }
+ break;
+ case XawstPositions:
+ position += count;
+ return (position < src->ascii_src.length ?
+ position : src->ascii_src.length);
+ case XawstAll:
+ return (src->ascii_src.length);
+ default:
+ break;
+ }
+ if (!include) {
+ if (type == XawstParagraph)
+ position = first_eol_position;
+ if (count)
+ --position;
+ }
+ }
+ else {
+ lim = piece->text;
+ switch (type) {
+ case XawstEOL:
+ case XawstParagraph:
+ case XawstWhiteSpace:
+ case XawstAlphaNumeric:
+ for (; cnt > 0; cnt--) {
+ Bool non_space = False, first_eol = True;
+
+ /*CONSTCOND*/
+ while (True) {
+ if (ptr < lim) {
+ piece = piece->prev;
+ if (piece == NULL) /* Begining of text */
+ return (0);
+ ptr = piece->text + piece->used - 1;
+ lim = piece->text;
+ }
+
+ c = *ptr--;
+ --position;
+
+ if (type == XawstEOL) {
+ if (c == '\n')
+ break;
+ }
+ else if (type == XawstAlphaNumeric) {
+ if (!isalnum(c)) {
+ if (non_space)
+ break;
+ }
+ else
+ non_space = True;
+ }
+ else if (type == XawstWhiteSpace) {
+ if (isspace(c)) {
+ if (non_space)
+ break;
+ }
+ else
+ non_space = True;
+ }
+ else { /* XawstParagraph */
+ if (first_eol) {
+ if (c == '\n') {
+ first_eol_position = position;
+ first_eol = False;
+ }
+ }
+ else if (c == '\n')
+ break;
+ else if (!isspace(c))
+ first_eol = True;
+ }
+ }
+ }
+ break;
+ case XawstPositions:
+ position -= count - 1;
+ return (position > 0 ? position : 0);
+ case XawstAll:
+ return (0);
+ default:
+ break;
+ }
+ if (!include) {
+ if (type == XawstParagraph)
+ position = first_eol_position;
+ if (count)
+ ++position;
+ }
+ position++;
+ }
+
+ return (position);
+}
+
+/*
+ * Function:
+ * Search
+ *
+ * Parameters:
+ * w - AsciiSource object
+ * position - the position to start scanning
+ * dir - direction to scan
+ * text - text block to search for
+ *
+ * Description:
+ * Searchs the text source for the text block passed.
+ *
+ * Returns:
+ * The position of the item found
+ */
+static XawTextPosition
+Search(Widget w, register XawTextPosition position, XawTextScanDirection dir,
+ XawTextBlock *text)
+{
+ AsciiSrcObject src = (AsciiSrcObject)w;
+ register int count = 0;
+ register char *ptr, c;
+ char *str;
+ Piece *piece;
+ char *buf;
+ XawTextPosition first;
+ int cnt, case_sensitive;
+
+ if (dir == XawsdLeft) {
+ if (position == 0)
+ return (XawTextSearchError);
+ position--;
+ }
+
+ buf = XtMalloc((unsigned)sizeof(unsigned char) * text->length);
+ memcpy(buf, text->ptr, (unsigned)text->length);
+ piece = FindPiece(src, position, &first);
+ ptr = (position - first) + piece->text;
+ case_sensitive = text->firstPos;
+
+ if (dir == XawsdRight) {
+ str = buf;
+ c = *str;
+ /*CONSTCOND*/
+ while (1) {
+ if (*ptr++ == c
+ || (case_sensitive && isalpha(c) && isalpha(ptr[-1])
+ && toupper(c) == toupper(ptr[-1]))) {
+ if (++count == text->length)
+ break;
+ c = *++str;
+ }
+ else if (count) {
+ ptr -= count;
+ str -= count;
+ position -= count;
+ count = 0;
+ c = *str;
+
+ if (ptr < piece->text) {
+ do {
+ cnt = piece->text - ptr;
+ piece = piece->prev;
+ if (piece == NULL) {
+ XtFree(buf);
+ return (XawTextSearchError);
+ }
+ ptr = piece->text + piece->used - cnt;
+ } while (ptr < piece->text);
+ }
+ }
+ position++;
+ if (ptr >= (piece->text + piece->used)) {
+ do {
+ cnt = ptr - (piece->text + piece->used);
+ piece = piece->next;
+ if (piece == NULL) {
+ XtFree(buf);
+ return (XawTextSearchError);
+ }
+ ptr = piece->text + cnt;
+ } while (ptr >= (piece->text + piece->used));
+ }
+ }
+
+ position -= text->length - 1;
+ }
+ else {
+ str = buf + text->length - 1;
+ c = *str;
+ /*CONSTCOND*/
+ while (1) {
+ if (*ptr-- == c
+ || (case_sensitive && isalpha(c) && isalpha(ptr[1])
+ && toupper(c) == toupper(ptr[1]))) {
+ if (++count == text->length)
+ break;
+ c = *--str;
+ }
+ else if (count) {
+ ptr += count;
+ str += count;
+ position += count;
+ count = 0;
+ c = *str;
+
+ if (ptr >= (piece->text + piece->used)) {
+ do {
+ cnt = ptr - (piece->text + piece->used);
+ piece = piece->next;
+ if (piece == NULL) {
+ XtFree(buf);
+ return (XawTextSearchError);
+ }
+ ptr = piece->text + cnt;
+ } while (ptr >= (piece->text + piece->used));
+ }
+ }
+ position--;
+ if (ptr < piece->text) {
+ do {
+ cnt = piece->text - ptr;
+ piece = piece->prev;
+ if (piece == NULL) {
+ XtFree(buf);
+ return (XawTextSearchError);
+ }
+ ptr = piece->text + piece->used - cnt;
+ } while (ptr < piece->text);
+ }
+ }
+ }
+
+ XtFree(buf);
+
+ return (position);
+}
+
+/*
+ * Function:
+ * XawAsciiSrcSetValues
+ *
+ * Parameters:
+ * current - current state of the widget
+ * request - what was requested
+ * cnew - what the widget will become
+ * args - representation of changed resources
+ * num_args - number of resources that have changed
+ *
+ * Description:
+ * Sets the values for the AsciiSource.
+ *
+ * Returns:
+ * True if redisplay is needed
+ */
+static Boolean
+XawAsciiSrcSetValues(Widget current, Widget request, Widget cnew,
+ ArgList args, Cardinal *num_args)
+{
+ AsciiSrcObject src = (AsciiSrcObject)cnew;
+ AsciiSrcObject old_src = (AsciiSrcObject)current;
+ Bool total_reset = False, string_set = False;
+ FILE *file;
+ unsigned int i;
+
+ if (old_src->ascii_src.use_string_in_place
+ != src->ascii_src.use_string_in_place) {
+ XtAppWarning(XtWidgetToApplicationContext(cnew),
+ "AsciiSrc: The XtNuseStringInPlace resource may "
+ "not be changed.");
+ src->ascii_src.use_string_in_place =
+ old_src->ascii_src.use_string_in_place;
+ }
+
+ for (i = 0; i < *num_args ; i++)
+ if (streq(args[i].name, XtNstring)) {
+ string_set = True;
+ break;
+ }
+
+ if (string_set || (old_src->ascii_src.type != src->ascii_src.type)) {
+ RemoveOldStringOrFile(old_src, string_set); /* remove old info */
+ file = InitStringOrFile(src, string_set); /* Init new info */
+ LoadPieces(src, file, NULL); /* load new info into internal buffers */
+ if (file != NULL)
+ fclose(file);
+#ifndef OLDXAW
+ for (i = 0; i < src->text_src.num_text; i++)
+ /* Tell text widget what happened */
+ XawTextSetSource(src->text_src.text[i], cnew, 0);
+#else
+ XawTextSetSource(XtParent(cnew), cnew, 0);
+#endif
+ total_reset = True;
+ }
+
+ if (old_src->ascii_src.ascii_length != src->ascii_src.ascii_length)
+ src->ascii_src.piece_size = src->ascii_src.ascii_length + 1;
+
+ if (!total_reset &&
+ old_src->ascii_src.piece_size != src->ascii_src.piece_size) {
+ String string = StorePiecesInString(old_src);
+
+ FreeAllPieces(old_src);
+ LoadPieces(src, NULL, string);
+ XtFree(string);
+ }
+
+ return (False);
+}
+
+/*
+ * Function:
+ * XawAsciiSrcGetValuesHook
+ *
+ * Parameters:
+ * w - AsciiSource Widget
+ * args - argument list
+ * num_args - number of args
+ *
+ * Description:
+ * This is a get values hook routine that sets the
+ * values specific to the ascii source.
+ */
+static void
+XawAsciiSrcGetValuesHook(Widget w, ArgList args, Cardinal *num_args)
+{
+ AsciiSrcObject src = (AsciiSrcObject)w;
+ unsigned int i;
+
+ if (src->ascii_src.type == XawAsciiString) {
+ for (i = 0; i < *num_args ; i++)
+ if (streq(args[i].name, XtNstring)) {
+ if (src->ascii_src.use_string_in_place)
+ *((char **)args[i].value) = src->ascii_src.first_piece->text;
+ else if (XawAsciiSave(w)) /* If save sucessful */
+ *((char **)args[i].value) = src->ascii_src.string;
+ break;
+ }
+ }
+ }
+
+/*
+ * Function:
+ * XawAsciiSrcDestroy
+ *
+ * Parameters:
+ * src - Ascii source object to free
+ *
+ * Description:
+ * Destroys an ascii source (frees all data)
+ */
+static void
+XawAsciiSrcDestroy(Widget w)
+{
+ RemoveOldStringOrFile((AsciiSrcObject) w, True);
+}
+
+/*
+ * Public routines
+ */
+/*
+ * Function:
+ * XawAsciiSourceFreeString
+ *
+ * Parameters:
+ * w - AsciiSrc widget
+ *
+ * Description:
+ * Frees the string returned by a get values call
+ * on the string when the source is of type string.
+ */
+void
+XawAsciiSourceFreeString(Widget w)
+{
+ AsciiSrcObject src = (AsciiSrcObject)w;
+
+ /* If the src is really a multi, call the multi routine */
+ if (XtIsSubclass(w, multiSrcObjectClass)) {
+ _XawMultiSourceFreeString(w);
+ return;
+ }
+ else if (!XtIsSubclass(w, asciiSrcObjectClass)) {
+ XtErrorMsg("bad argument", "asciiSource", "XawError",
+ "XawAsciiSourceFreeString's parameter must be "
+ "an asciiSrc or multiSrc.",
+ NULL, NULL);
+ }
+
+ if (src->ascii_src.allocated_string && src->ascii_src.type != XawAsciiFile) {
+ src->ascii_src.allocated_string = False;
+ XtFree(src->ascii_src.string);
+ src->ascii_src.string = NULL;
+ }
+}
+
+/*
+ * Function:
+ * XawAsciiSave
+ *
+ * Parameters:
+ * w - asciiSrc Widget
+ *
+ * Description:
+ * Saves all the pieces into a file or string as required.
+ *
+ * Returns:
+ * True if the save was successful
+ */
+Bool
+XawAsciiSave(Widget w)
+{
+ AsciiSrcObject src = (AsciiSrcObject)w;
+
+ /* If the src is really a multi, call the multi save */
+ if (XtIsSubclass(w, multiSrcObjectClass ))
+ return (_XawMultiSave(w));
+
+ else if (!XtIsSubclass(w, asciiSrcObjectClass))
+ XtErrorMsg("bad argument", "asciiSource", "XawError",
+ "XawAsciiSave's parameter must be an asciiSrc or multiSrc.",
+ NULL, NULL);
+
+ /*
+ * If using the string in place then there is no need to play games
+ * to get the internal info into a readable string.
+ */
+ if (src->ascii_src.use_string_in_place)
+ return (True);
+
+ if (src->ascii_src.type == XawAsciiFile) {
+#ifdef OLDXAW
+ if (!src->ascii_src.changes)
+#else
+ if (!src->text_src.changed) /* No changes to save */
+#endif
+ return (True);
+
+ if (WritePiecesToFile(src, src->ascii_src.string) == False)
+ return (False);
+ }
+ else {
+ if (src->ascii_src.allocated_string == True)
+ XtFree(src->ascii_src.string);
+ else
+ src->ascii_src.allocated_string = True;
+
+ src->ascii_src.string = StorePiecesInString(src);
+ }
+#ifdef OLDXAW
+ src->ascii_src.changes = False;
+#else
+ src->text_src.changed = False;
+#endif
+
+ return (True);
+}
+
+/*
+ * Function:
+ * XawAsciiSaveAsFile
+ *
+ * Arguments:
+ * w - AsciiSrc widget
+ * name - name of the file to save this file into
+ *
+ * Description:
+ * Save the current buffer as a file.
+ *
+ * Returns:
+ * True if the save was sucessful
+ */
+Bool
+XawAsciiSaveAsFile(Widget w, _Xconst char *name)
+{
+ AsciiSrcObject src = (AsciiSrcObject)w;
+ Bool ret;
+
+ /* If the src is really a multi, call the multi save */
+
+ if (XtIsSubclass( w, multiSrcObjectClass))
+ return (_XawMultiSaveAsFile(w, name));
+
+ else if (!XtIsSubclass(w, asciiSrcObjectClass))
+ XtErrorMsg("bad argument", "asciiSource", "XawError",
+ "XawAsciiSaveAsFile's 1st parameter must be an "
+ "asciiSrc or multiSrc.",
+ NULL, NULL);
+
+ if (src->ascii_src.type == XawAsciiFile)
+ ret = WritePiecesToFile(src, (String)name);
+ else {
+ String string = StorePiecesInString(src);
+
+ ret = WriteToFile(string, (String)name, src->ascii_src.length);
+ XtFree(string);
+ }
+
+ return (ret);
+}
+
+/*
+ * Function:
+ * XawAsciiSourceChanged
+ *
+ * Parameters:
+ * w - ascii source widget
+ *
+ * Description:
+ * Returns true if the source has changed since last saved.
+ *
+ * Returns:
+ * A Boolean (see description).
+ */
+Bool
+XawAsciiSourceChanged(Widget w)
+{
+#ifdef OLDXAW
+ if (XtIsSubclass(w, multiSrcObjectClass))
+ return (((MultiSrcObject)w)->multi_src.changes);
+
+ if (XtIsSubclass(w, asciiSrcObjectClass))
+ return (((AsciiSrcObject)w)->ascii_src.changes);
+#else
+ if (XtIsSubclass(w, textSrcObjectClass))
+ return (((TextSrcObject)w)->textSrc.changed);
+#endif
+ XtErrorMsg("bad argument", "asciiSource", "XawError",
+ "XawAsciiSourceChanged parameter must be an "
+ "asciiSrc or multiSrc.",
+ NULL, NULL);
+
+ return (True);
+}
+
+/*
+ * Private Functions
+ */
+static void
+RemoveOldStringOrFile(AsciiSrcObject src, Bool checkString)
+{
+ FreeAllPieces(src);
+
+ if (checkString && src->ascii_src.allocated_string) {
+ XtFree(src->ascii_src.string);
+ src->ascii_src.allocated_string = False;
+ src->ascii_src.string = NULL;
+ }
+}
+
+/*
+ * Function:
+ * WriteToFile
+ *
+ * Parameters:
+ * string - string to write
+ * name - the name of the file
+ *
+ * Description:
+ * Write the string specified to the begining of the file specified.
+ *
+ * Returns:
+ * returns True if sucessful, False otherwise
+ */
+static Bool
+WriteToFile(String string, String name, unsigned length)
+{
+ int fd;
+
+ if ((fd = creat(name, 0666)) == -1)
+ return (False);
+
+ if (write(fd, string, length) == -1) {
+ close(fd);
+ return (False);
+ }
+
+ if (close(fd) == -1)
+ return (False);
+
+ return (True);
+}
+
+/*
+ * Function:
+ * WritePiecesToFile
+ *
+ * Parameters:
+ * src - ascii source object
+ * name - name of the file
+ *
+ * Description:
+ * Almost identical to WriteToFile, but only works for ascii src objects
+ * of type XawAsciiFile. This function avoids allocating temporary memory,
+ * what can be useful when editing very large files.
+ *
+ * Returns:
+ * returns True if sucessful, False otherwise
+ */
+static Bool
+WritePiecesToFile(AsciiSrcObject src, String name)
+{
+ Piece *piece;
+ int fd;
+
+ if (src->ascii_src.data_compression) {
+ Piece *tmp;
+
+ piece = src->ascii_src.first_piece;
+ while (piece) {
+ int bytes = src->ascii_src.piece_size - piece->used;
+
+ if (bytes > 0 && (tmp = piece->next) != NULL) {
+ bytes = XawMin(bytes, tmp->used);
+ memcpy(piece->text + piece->used, tmp->text, bytes);
+ memmove(tmp->text, tmp->text + bytes, tmp->used - bytes);
+ piece->used += bytes;
+ if ((tmp->used -= bytes) == 0) {
+ RemovePiece(src, tmp);
+ continue;
+ }
+ }
+ piece = piece->next;
+ }
+ }
+
+ if ((fd = creat(name, 0666)) == -1)
+ return (False);
+
+ for (piece = src->ascii_src.first_piece; piece; piece = piece->next)
+ if (write(fd, piece->text, piece->used) == -1) {
+ close(fd);
+ return (False);
+ }
+
+ if (close(fd) == -1)
+ return (False);
+
+ return (True);
+}
+
+/*
+ * Function:
+ * StorePiecesInString
+ *
+ * Parameters:
+ * data - ascii pointer data
+ *
+ * Description:
+ * Store the pieces in memory into a standard ascii string.
+ */
+static String
+StorePiecesInString(AsciiSrcObject src)
+{
+ String string;
+ XawTextPosition first;
+ Piece *piece;
+
+ string = XtMalloc((unsigned)(src->ascii_src.length + 1));
+
+ for (first = 0, piece = src->ascii_src.first_piece ; piece != NULL;
+ first += piece->used, piece = piece->next)
+ memcpy(string + first, piece->text, (unsigned)piece->used);
+
+ string[src->ascii_src.length] = '\0';
+
+ /*
+ * This will refill all pieces to capacity
+ */
+ if (src->ascii_src.data_compression) {
+ FreeAllPieces(src);
+ LoadPieces(src, NULL, string);
+ }
+
+ return (string);
+}
+
+/*
+ * Function:
+ * InitStringOrFile
+ *
+ * Parameters:
+ * src - AsciiSource
+ *
+ * Description:
+ * Initializes the string or file.
+ */
+static FILE *
+InitStringOrFile(AsciiSrcObject src, Bool newString)
+{
+ mode_t open_mode = 0;
+ const char *fdopen_mode = NULL;
+ int fd;
+ FILE *file;
+
+ if (src->ascii_src.type == XawAsciiString) {
+ if (src->ascii_src.string == NULL)
+ src->ascii_src.length = 0;
+
+ else if (!src->ascii_src.use_string_in_place) {
+ src->ascii_src.string = XtNewString(src->ascii_src.string);
+ src->ascii_src.allocated_string = True;
+ src->ascii_src.length = strlen(src->ascii_src.string);
+ }
+
+ if (src->ascii_src.use_string_in_place) {
+ if (src->ascii_src.string != NULL)
+ src->ascii_src.length = strlen(src->ascii_src.string);
+ /* In case the length resource is incorrectly set */
+ if (src->ascii_src.length > src->ascii_src.ascii_length)
+ src->ascii_src.ascii_length = src->ascii_src.length;
+
+ if (src->ascii_src.ascii_length == MAGIC_VALUE)
+ src->ascii_src.piece_size = src->ascii_src.length;
+ else
+ src->ascii_src.piece_size = src->ascii_src.ascii_length + 1;
+ }
+
+ return (NULL);
+ }
+
+ /*
+ * type is XawAsciiFile
+ */
+ src->ascii_src.is_tempfile = False;
+
+ switch (src->text_src.edit_mode) {
+ case XawtextRead:
+ if (src->ascii_src.string == NULL)
+ XtErrorMsg("NoFile", "asciiSourceCreate", "XawError",
+ "Creating a read only disk widget and no file specified.",
+ NULL, NULL);
+ open_mode = O_RDONLY;
+ fdopen_mode = "r";
+ break;
+ case XawtextAppend:
+ case XawtextEdit:
+ if (src->ascii_src.string == NULL) {
+ src->ascii_src.string = "*ascii-src*";
+ src->ascii_src.is_tempfile = True;
+ }
+ else {
+/* O_NOFOLLOW is a FreeBSD & Linux extension */
+#ifdef O_NOFOLLOW
+ open_mode = O_RDWR | O_NOFOLLOW;
+#else
+ open_mode = O_RDWR; /* unsafe; subject to race conditions */
+#endif /* O_NOFOLLOW */
+ fdopen_mode = "r+";
+ }
+ break;
+ default:
+ XtErrorMsg("badMode", "asciiSourceCreate", "XawError",
+ "Bad editMode for ascii source; must be Read, "
+ "Append or Edit.",
+ NULL, NULL);
+ }
+
+ /* If is_tempfile, allocate a private copy of the text
+ * Unlikely to be changed, just to set allocated_string */
+ if (newString || src->ascii_src.is_tempfile) {
+ src->ascii_src.string = XtNewString(src->ascii_src.string);
+ src->ascii_src.allocated_string = True;
+ }
+
+ if (!src->ascii_src.is_tempfile) {
+ if ((fd = open(src->ascii_src.string, open_mode, 0666)) != -1) {
+ if ((file = fdopen(fd, fdopen_mode))) {
+ (void)fseek(file, 0, SEEK_END);
+ src->ascii_src.length = (XawTextPosition)ftell(file);
+ return (file);
+ }
+ }
+ {
+ String params[2];
+ Cardinal num_params = 2;
+
+ params[0] = src->ascii_src.string;
+ params[1] = strerror(errno);
+ XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
+ "openError", "asciiSourceCreate", "XawWarning",
+ "Cannot open file %s; %s", params, &num_params);
+ }
+ }
+ src->ascii_src.length = 0;
+ return (NULL);
+}
+
+static void
+LoadPieces(AsciiSrcObject src, FILE *file, char *string)
+{
+ char *ptr;
+ Piece *piece = NULL;
+ XawTextPosition left;
+
+ if (string == NULL) {
+ if (src->ascii_src.type == XawAsciiFile) {
+ if (src->ascii_src.length != 0) {
+ int len;
+
+ left = 0;
+ fseek(file, 0, 0);
+ while (left < src->ascii_src.length) {
+ ptr = XtMalloc((unsigned)src->ascii_src.piece_size);
+ if ((len = fread(ptr, (Size_t)sizeof(unsigned char),
+ (Size_t)src->ascii_src.piece_size, file)) < 0)
+ XtErrorMsg("readError", "asciiSourceCreate", "XawError",
+ "fread returned error.", NULL, NULL);
+ piece = AllocNewPiece(src, piece);
+ piece->text = ptr;
+ piece->used = XawMin(len, src->ascii_src.piece_size);
+ left += piece->used;
+ }
+ }
+ else {
+ piece = AllocNewPiece(src, NULL);
+ piece->text = XtMalloc((unsigned)src->ascii_src.piece_size);
+ piece->used = 0;
+ }
+ return;
+ }
+ else
+ string = src->ascii_src.string;
+ }
+
+ if (src->ascii_src.use_string_in_place) {
+ piece = AllocNewPiece(src, piece);
+ piece->used = XawMin(src->ascii_src.length, src->ascii_src.piece_size);
+ piece->text = src->ascii_src.string;
+ return;
+ }
+
+ ptr = string;
+ left = src->ascii_src.length;
+ do {
+ piece = AllocNewPiece(src, piece);
+
+ piece->text = XtMalloc((unsigned)src->ascii_src.piece_size);
+ piece->used = XawMin(left, src->ascii_src.piece_size);
+ if (piece->used != 0)
+ memcpy(piece->text, ptr, (unsigned)piece->used);
+
+ left -= piece->used;
+ ptr += piece->used;
+ } while (left > 0);
+}
+
+/*
+ * Function:
+ * AllocNewPiece
+ *
+ * Parameters:
+ * src - AsciiSrc Widget
+ * prev - piece just before this one, or NULL
+ *
+ * Description:
+ * Allocates a new piece of memory.
+ *
+ * Returns:
+ * The allocated piece
+ */
+static Piece *
+AllocNewPiece(AsciiSrcObject src, Piece *prev)
+{
+ Piece *piece = XtNew(Piece);
+
+ if (prev == NULL) {
+ src->ascii_src.first_piece = piece;
+ piece->next = NULL;
+ }
+ else {
+ if (prev->next != NULL)
+ (prev->next)->prev = piece;
+ piece->next = prev->next;
+ prev->next = piece;
+ }
+
+ piece->prev = prev;
+
+ return (piece);
+}
+
+/*
+ * Function:
+ * FreeAllPieces
+ *
+ * Parameters:
+ * src - AsciiSrc Widget
+ *
+ * Description:
+ * Frees all the pieces.
+ */
+static void
+FreeAllPieces(AsciiSrcObject src)
+{
+ Piece *next, * first = src->ascii_src.first_piece;
+
+#ifdef DEBUG
+ if (first->prev != NULL)
+ printf("Xaw AsciiSrc Object: possible memory leak in FreeAllPieces().\n");
+#endif
+
+ for (; first != NULL ; first = next) {
+ next = first->next;
+ RemovePiece(src, first);
+ }
+}
+
+/*
+ * Function:
+ * RemovePiece
+ *
+ * Parameters:
+ * piece - piece to remove
+ *
+ * Description:
+ * Removes a piece from the list.
+ */
+static void
+RemovePiece(AsciiSrcObject src, Piece *piece)
+{
+ if (piece->prev == NULL)
+ src->ascii_src.first_piece = piece->next;
+ else
+ piece->prev->next = piece->next;
+
+ if (piece->next != NULL)
+ piece->next->prev = piece->prev;
+
+ if (!src->ascii_src.use_string_in_place)
+ XtFree(piece->text);
+
+ XtFree((char *)piece);
+}
+
+/*
+ * Function:
+ * FindPiece
+ *
+ * Parameters:
+ * src - AsciiSrc Widget
+ * position - position that we are searching for
+ * first - position of the first character in this piece (return)
+ *
+ * Description:
+ * Finds the piece containing the position indicated.
+ *
+ * Returns:
+ * the piece that contains this position
+ */
+static Piece *
+FindPiece(AsciiSrcObject src, XawTextPosition position, XawTextPosition *first)
+{
+ Piece *old_piece, *piece;
+ XawTextPosition temp;
+
+ for (old_piece = NULL, piece = src->ascii_src.first_piece, temp = 0;
+ piece; old_piece = piece, piece = piece->next)
+ if ((temp += piece->used) > position) {
+ *first = temp - piece->used;
+ return (piece);
+ }
+
+ *first = temp - (old_piece ? old_piece->used : 0);
+
+ return (old_piece); /* if we run off the end the return the last piece */
+}
+
+/*
+ * Function:
+ * BreakPiece
+ *
+ * Parameters:
+ * src - AsciiSrc Widget
+ * piece - piece to break
+ *
+ * Description:
+ * Breaks a full piece into two new pieces.
+ */
+#define HALF_PIECE (src->ascii_src.piece_size >> 1)
+static void
+BreakPiece(AsciiSrcObject src, Piece *piece)
+{
+ Piece *cnew = AllocNewPiece(src, piece);
+
+ cnew->text = XtMalloc((unsigned)src->ascii_src.piece_size);
+ memcpy(cnew->text, piece->text + HALF_PIECE,
+ (unsigned)(src->ascii_src.piece_size - HALF_PIECE));
+ piece->used = HALF_PIECE;
+ cnew->used = src->ascii_src.piece_size - HALF_PIECE;
+}
+
+/*ARGSUSED*/
+static void
+CvtStringToAsciiType(XrmValuePtr args, Cardinal *num_args,
+ XrmValuePtr fromVal, XrmValuePtr toVal)
+{
+ static XawAsciiType type;
+ XrmQuark q;
+ char name[7];
+
+ XmuNCopyISOLatin1Lowered(name, (char *)fromVal->addr, sizeof(name));
+ q = XrmStringToQuark(name);
+
+ if (q == Qstring)
+ type = XawAsciiString;
+ else if (q == Qfile)
+ type = XawAsciiFile;
+ else {
+ toVal->size = 0;
+ toVal->addr = NULL;
+ XtStringConversionWarning((char *)fromVal->addr, XtRAsciiType);
+ }
+
+ toVal->size = sizeof(XawAsciiType);
+ toVal->addr = (XPointer)&type;
+}
+
+/*ARGSUSED*/
+static Boolean
+CvtAsciiTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args,
+ XrmValuePtr fromVal, XrmValuePtr toVal,
+ XtPointer *data)
+{
+ static String buffer;
+ Cardinal size;
+
+ switch (*(XawAsciiType *)fromVal->addr) {
+ case XawAsciiFile:
+ buffer = XtEfile;
+ break;
+ case XawAsciiString:
+ buffer = XtEstring;
+ break;
+ default:
+ XawTypeToStringWarning(dpy, XtRAsciiType);
+ toVal->addr = NULL;
+ toVal->size = 0;
+ return (False);
+ }
+
+ size = strlen(buffer) + 1;
+ if (toVal->addr != NULL) {
+ if (toVal->size < size) {
+ toVal->size = size;
+ return (False);
+ }
+ strcpy((char *)toVal->addr, buffer);
+ }
+ else
+ toVal->addr = (XPointer)buffer;
+ toVal->size = sizeof(String);
+
+ return (True);
+}
+
+/*ARGSUSED*/
+static void
+GetDefaultPieceSize(Widget w, int offset, XrmValue *value)
+{
+ static XPointer pagesize;
+
+ if (pagesize == NULL) {
+ pagesize = (XPointer)((long)_XawGetPageSize());
+ if (pagesize < (XPointer)BUFSIZ)
+ pagesize = (XPointer)BUFSIZ;
+ }
+
+ value->addr = (XPointer)&pagesize;
+}
+
+#if (defined(ASCII_STRING) || defined(ASCII_DISK))
+# include <X11/Xaw/Cardinals.h>
+#endif
+
+#ifdef ASCII_STRING
+/*
+ * Compatability functions.
+ */
+/*
+ * Function:
+ * AsciiStringSourceCreate
+ *
+ * Parameters:
+ * parent - widget that will own this source
+ * args - the argument list
+ * num_args - ""
+ *
+ * Description:
+ * Creates a string source.
+ *
+ * Returns:
+ * A pointer to the new text source.
+ */
+Widget
+XawStringSourceCreate(Widget parent, ArgList args, Cardinal num_args)
+{
+ XawTextSource src;
+ ArgList ascii_args;
+ Arg temp[2];
+
+ XtSetArg(temp[0], XtNtype, XawAsciiString);
+ XtSetArg(temp[1], XtNuseStringInPlace, True);
+ ascii_args = XtMergeArgLists(temp, TWO, args, num_args);
+
+ src = XtCreateWidget("genericAsciiString", asciiSrcObjectClass, parent,
+ ascii_args, num_args + TWO);
+ XtFree((char *)ascii_args);
+
+ return (src);
+}
+
+/*
+ * This is hacked up to try to emulate old functionality, it
+ * may not work, as I have not old code to test it on.
+ *
+ * Chris D. Peterson 8/31/89.
+ */
+void
+XawTextSetLastPos(Widget w, XawTextPosition lastPos)
+{
+ AsciiSrcObject src = (AsciiSrcObject)XawTextGetSource(w);
+
+ src->ascii_src.piece_size = lastPos;
+}
+#endif /* ASCII_STRING */
+
+#ifdef ASCII_DISK
+/*
+ * Function:
+ * AsciiDiskSourceCreate
+ *
+ * Parameters:
+ * parent - widget that will own this source
+ * args - argument list
+ * num_args - ""
+ *
+ * Description:
+ * Creates a disk source.
+ *
+ * Returns:
+ * A pointer to the new text source
+ */
+Widget
+XawDiskSourceCreate(Widget parent, ArgList args, Cardinal num_args)
+{
+ XawTextSource src;
+ ArgList ascii_args;
+ Arg temp[1];
+ int i;
+
+ XtSetArg(temp[0], XtNtype, XawAsciiFile);
+ ascii_args = XtMergeArgLists(temp, ONE, args, num_args);
+ num_args++;
+
+ for (i = 0; i < num_args; i++)
+ if (streq(ascii_args[i].name, XtNfile)
+ || streq(ascii_args[i].name, XtCFile))
+ ascii_args[i].name = XtNstring;
+
+ src = XtCreateWidget("genericAsciiDisk", asciiSrcObjectClass, parent,
+ ascii_args, num_args);
+ XtFree((char *)ascii_args);
+
+ return (src);
+}
+#endif /* ASCII_DISK */
|