749N/A#if ( !defined(lint) && !defined(SABER) )
749N/Astatic char Xrcsid[] = "$XConsortium: AsciiSrc.c,v 1.28 90/01/10 14:25:21 kit Exp $";
749N/A#endif
749N/A
749N/A/*
749N/A * Copyright 1989 Massachusetts Institute of Technology
749N/A *
749N/A * Permission to use, copy, modify, distribute, and sell this software and its
749N/A * documentation for any purpose is hereby granted without fee, provided that
749N/A * the above copyright notice appear in all copies and that both that
749N/A * copyright notice and this permission notice appear in supporting
749N/A * documentation, and that the name of M.I.T. not be used in advertising or
749N/A * publicity pertaining to distribution of the software without specific,
749N/A * written prior permission. M.I.T. makes no representations about the
749N/A * suitability of this software for any purpose. It is provided "as is"
749N/A * without express or implied warranty.
749N/A *
749N/A * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
749N/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
749N/A * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
749N/A * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
749N/A * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
749N/A * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
749N/A *
749N/A * Author: Chris Peterson, MIT X Consortium.
749N/A *
749N/A * Much code taken from X11R3 String and Disk Sources.
749N/A */
749N/A
749N/A/*
749N/A * AsciiSrc.c - AsciiSrc object. (For use with the text widget).
749N/A *
749N/A */
749N/A
749N/A#include <stdio.h>
749N/A#include <ctype.h>
1233N/A#include <fcntl.h>
1233N/A#include <unistd.h>
749N/A#include <X11/IntrinsicP.h>
749N/A#include <X11/StringDefs.h>
749N/A
749N/A#include <./Xaw3_1XawInit.h>
749N/A#include <./Xaw3_1AsciiSrcP.h>
749N/A#include <X11/Xmu/Misc.h>
749N/A#include <X11/Xmu/CharSet.h>
749N/A
749N/A#ifdef ASCII_STRING
749N/A#include <./Xaw3_1AsciiText.h> /* for Widget Classes. */
749N/A#endif
749N/A#ifdef ASCII_DISK)
749N/A#include <./Xaw3_1AsciiText.h> /* for Widget Classes. */
749N/A#endif
749N/A/****************************************************************
749N/A *
749N/A * Full class record constant
749N/A *
749N/A ****************************************************************/
749N/A
749N/A/* Private Data */
749N/A
749N/Astatic int magic_value = MAGIC_VALUE;
749N/A
749N/A#define offset(field) XtOffset(AsciiSrcObject, ascii_src.field)
749N/A
749N/Astatic XtResource resources[] = {
749N/A {XtNstring, XtCString, XtRString, sizeof (char *),
749N/A offset(string), XtRString, NULL},
749N/A {XtNtype, XtCType, XtRAsciiType, sizeof (XawAsciiType),
749N/A offset(type), XtRImmediate, (XtPointer)XawAsciiString},
749N/A {XtNdataCompression, XtCDataCompression, XtRBoolean, sizeof (Boolean),
749N/A offset(data_compression), XtRImmediate, (XtPointer) TRUE},
749N/A {XtNpieceSize, XtCPieceSize, XtRInt, sizeof (XawTextPosition),
749N/A offset(piece_size), XtRImmediate, (XtPointer) BUFSIZ},
749N/A {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
749N/A offset(callback), XtRCallback, (XtPointer)NULL},
749N/A {XtNuseStringInPlace, XtCUseStringInPlace, XtRBoolean, sizeof (Boolean),
749N/A offset(use_string_in_place), XtRImmediate, (XtPointer) FALSE},
749N/A {XtNlength, XtCLength, XtRInt, sizeof (int),
749N/A offset(ascii_length), XtRInt, (XtPointer) &magic_value},
749N/A
749N/A#ifdef ASCII_DISK
749N/A {XtNfile, XtCFile, XtRString, sizeof (String),
749N/A offset(filename), XtRString, NULL},
749N/A#endif /* ASCII_DISK */
749N/A};
749N/A
749N/Astatic XawTextPosition Scan(), Search(), ReadText();
749N/Astatic int ReplaceText();
749N/Astatic Piece * FindPiece(), * AllocNewPiece();
749N/Astatic FILE * InitStringOrFile();
749N/Astatic void FreeAllPieces(), RemovePiece(), BreakPiece(), LoadPieces();
749N/Astatic void RemoveOldStringOrFile(), CvtStringToAsciiType();
749N/Astatic void ClassInitialize(), Initialize(), Destroy(), GetValuesHook();
749N/Astatic String MyStrncpy(), StorePiecesInString();
749N/Astatic Boolean SetValues(), WriteToFile();
749N/Aextern char *tmpnam();
749N/A#ifndef SYSV
749N/Avoid bcopy();
749N/A#endif
749N/Aextern int errno, sys_nerr;
749N/Aextern char* sys_errlist[];
749N/A
749N/A#define superclass (&textSrcClassRec)
749N/AAsciiSrcClassRec asciiSrcClassRec = {
749N/A {
749N/A/* core_class fields */
749N/A /* superclass */ (WidgetClass) superclass,
749N/A /* class_name */ "AsciiSrc",
749N/A /* widget_size */ sizeof(AsciiSrcRec),
749N/A /* class_initialize */ ClassInitialize,
749N/A /* class_part_initialize */ NULL,
749N/A /* class_inited */ FALSE,
749N/A /* initialize */ Initialize,
749N/A /* initialize_hook */ NULL,
749N/A /* realize */ NULL,
749N/A /* actions */ NULL,
749N/A /* num_actions */ 0,
749N/A /* resources */ resources,
749N/A /* num_resources */ XtNumber(resources),
749N/A /* xrm_class */ NULLQUARK,
749N/A /* compress_motion */ FALSE,
749N/A /* compress_exposure */ FALSE,
749N/A /* compress_enterleave */ FALSE,
749N/A /* visible_interest */ FALSE,
749N/A /* destroy */ Destroy,
749N/A /* resize */ NULL,
749N/A /* expose */ NULL,
749N/A /* set_values */ SetValues,
749N/A /* set_values_hook */ NULL,
749N/A /* set_values_almost */ NULL,
749N/A /* get_values_hook */ GetValuesHook,
749N/A /* accept_focus */ NULL,
749N/A /* version */ XtVersion,
749N/A /* callback_private */ NULL,
749N/A /* tm_table */ NULL,
749N/A /* query_geometry */ NULL,
749N/A /* display_accelerator */ NULL,
749N/A /* extension */ NULL
749N/A },
749N/A/* textSrc_class fields */
749N/A {
749N/A /* Read */ ReadText,
749N/A /* Replace */ ReplaceText,
749N/A /* Scan */ Scan,
749N/A /* Search */ Search,
749N/A /* SetSelection */ XtInheritSetSelection,
749N/A /* ConvertSelection */ XtInheritConvertSelection
749N/A },
749N/A/* asciiSrc_class fields */
749N/A {
749N/A /* Keep the compiler happy */ NULL
749N/A }
749N/A};
749N/A
749N/AWidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec;
749N/A
749N/A/************************************************************
749N/A *
749N/A * Semi-Public Interfaces.
749N/A *
749N/A ************************************************************/
749N/A
749N/A/* Function Name: ClassInitialize
749N/A * Description: Class Initialize routine, called only once.
749N/A * Arguments: none.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/AClassInitialize()
749N/A{
749N/A XawInitializeWidgetSet();
749N/A XtAddConverter( XtRString, XtRAsciiType, CvtStringToAsciiType,
749N/A NULL, (Cardinal) 0);
749N/A}
749N/A
749N/A/* Function Name: Initialize
749N/A * Description: Initializes the simple menu widget
749N/A * Arguments: request - the widget requested by the argument list.
749N/A * new - the new widget with both resource and non
749N/A * resource values.
749N/A * Returns: none.
749N/A */
749N/A
749N/A/* ARGSUSED */
749N/Astatic void
749N/AInitialize(request, new)
749N/AWidget request, new;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) new;
749N/A FILE * file;
749N/A
749N/A/*
749N/A * Set correct flags (override resources) depending upon widget class.
749N/A */
749N/A
749N/A#ifdef ASCII_DISK
749N/A if (XtIsSubclass(XtParent(new), asciiDiskWidgetClass)) {
749N/A src->ascii_src.type = XawAsciiFile;
749N/A src->ascii_src.string = src->ascii_src.filename;
749N/A }
749N/A#endif
749N/A
749N/A#ifdef ASCII_STRING
749N/A if (XtIsSubclass(XtParent(new), asciiStringWidgetClass)) {
749N/A src->ascii_src.use_string_in_place = TRUE;
749N/A src->ascii_src.type = XawAsciiString;
749N/A }
749N/A#endif
749N/A
749N/A src->ascii_src.changes = FALSE;
749N/A src->ascii_src.allocated_string = FALSE;
749N/A
749N/A file = InitStringOrFile(src);
749N/A LoadPieces(src, file, NULL);
749N/A
749N/A if (file != NULL) fclose(file);
749N/A
749N/A if ( src->ascii_src.type == XawAsciiString )
749N/A src->ascii_src.string = NULL;
749N/A}
749N/A
749N/A/* Function Name: ReadText
749N/A * Description: This function reads the source.
749N/A * Arguments: w - the AsciiSource widget.
749N/A * pos - position of the text to retreive.
749N/A * RETURNED text - text block that will contain returned text.
749N/A * length - maximum number of characters to read.
749N/A * Returns: The number of characters read into the buffer.
749N/A */
749N/A
749N/Astatic XawTextPosition
749N/AReadText(w, pos, text, length)
749N/AWidget w;
749N/AXawTextPosition pos;
749N/AXawTextBlock *text;
749N/Aint length;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) w;
749N/A XawTextPosition count, start;
749N/A Piece * piece = FindPiece(src, pos, &start);
749N/A
749N/A text->firstPos = pos;
749N/A text->ptr = piece->text + (pos - start);
749N/A count = piece->used - (pos - start);
749N/A text->length = (length > count) ? count : length;
749N/A return(pos + text->length);
749N/A}
749N/A
749N/A/* Function Name: ReplaceText.
749N/A * Description: Replaces a block of text with new text.
749N/A * Arguments: w - the AsciiSource widget.
749N/A * startPos, endPos - ends of text that will be removed.
749N/A * text - new text to be inserted into buffer at startPos.
749N/A * Returns: XawEditError or XawEditDone.
749N/A */
749N/A
749N/A/*ARGSUSED*/
749N/Astatic int
749N/AReplaceText (w, startPos, endPos, text)
749N/AWidget w;
749N/AXawTextPosition startPos, endPos;
749N/AXawTextBlock *text;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) w;
749N/A Piece *start_piece, *end_piece, *temp_piece;
749N/A XawTextPosition start_first, end_first;
749N/A int length, firstPos;
749N/A
749N/A/*
749N/A * Editing a read only source is not allowed.
749N/A */
749N/A
749N/A if (src->text_src.edit_mode == XawtextRead)
749N/A return(XawEditError);
749N/A
749N/A start_piece = FindPiece(src, startPos, &start_first);
749N/A end_piece = FindPiece(src, endPos, &end_first);
749N/A
749N/A src->ascii_src.changes = TRUE; /* We have changed the buffer. */
749N/A
749N/A XtCallCallbacks(w, XtNcallback, NULL);
749N/A
749N/A/*
749N/A * Remove Old Stuff.
749N/A */
749N/A
749N/A if (start_piece != end_piece) {
749N/A temp_piece = start_piece->next;
749N/A
749N/A/*
749N/A * If empty and not the only piece then remove it.
749N/A */
749N/A
749N/A if ( ((start_piece->used = startPos - start_first) == 0) &&
749N/A !((start_piece->next == NULL) && (start_piece->prev == NULL)) )
749N/A RemovePiece(src, start_piece);
749N/A
749N/A while (temp_piece != end_piece) {
749N/A temp_piece = temp_piece->next;
749N/A RemovePiece(src, temp_piece->prev);
749N/A }
749N/A end_piece->used -= endPos - end_first;
749N/A if (end_piece->used != 0)
749N/A MyStrncpy(end_piece->text, (end_piece->text + endPos - end_first),
749N/A (int) end_piece->used);
749N/A }
749N/A else { /* We are fully in one piece. */
749N/A if ( (start_piece->used -= endPos - startPos) == 0) {
749N/A if ( !((start_piece->next == NULL) && (start_piece->prev == NULL)) )
749N/A RemovePiece(src, start_piece);
749N/A }
749N/A else {
749N/A MyStrncpy(start_piece->text + (startPos - start_first),
749N/A start_piece->text + (endPos - start_first),
749N/A (int) (start_piece->used - (startPos - start_first)) );
749N/A if ( src->ascii_src.use_string_in_place &&
749N/A ((src->ascii_src.length - (endPos - startPos)) <
749N/A (src->ascii_src.piece_size - 1)) )
749N/A start_piece->text[src->ascii_src.length - (endPos - startPos)] = '\0';
749N/A }
749N/A }
749N/A
749N/A src->ascii_src.length += -(endPos - startPos) + text->length;
749N/A
749N/A if ( text->length != 0) {
749N/A
749N/A /*
749N/A * Put in the New Stuff.
749N/A */
749N/A
749N/A start_piece = FindPiece(src, startPos, &start_first);
749N/A
749N/A length = text->length;
749N/A firstPos = text->firstPos;
749N/A
749N/A while (length > 0) {
749N/A char * ptr;
749N/A int fill;
749N/A
749N/A if (src->ascii_src.use_string_in_place) {
749N/A if (start_piece->used == (src->ascii_src.piece_size - 1)) {
749N/A /*
749N/A * If we are in ascii string emulation mode. Then the
749N/A * string is not allowed to grow.
749N/A */
749N/A start_piece->used = src->ascii_src.length =
749N/A src->ascii_src.piece_size - 1;
749N/A start_piece->text[src->ascii_src.length] = '\0';
749N/A return(XawEditError);
749N/A }
749N/A }
749N/A
749N/A
749N/A if (start_piece->used == src->ascii_src.piece_size) {
749N/A BreakPiece(src, start_piece);
749N/A start_piece = FindPiece(src, startPos, &start_first);
749N/A }
749N/A
749N/A fill = Min((int)(src->ascii_src.piece_size - start_piece->used), length);
749N/A
749N/A ptr = start_piece->text + (startPos - start_first);
749N/A MyStrncpy(ptr + fill, ptr,
749N/A (int) start_piece->used - (startPos - start_first));
749N/A strncpy(ptr, text->ptr + firstPos, fill);
749N/A
749N/A startPos += fill;
749N/A firstPos += fill;
749N/A start_piece->used += fill;
749N/A length -= fill;
749N/A }
749N/A }
749N/A
749N/A if (src->ascii_src.use_string_in_place)
749N/A start_piece->text[start_piece->used] = '\0';
749N/A
749N/A return(XawEditDone);
749N/A}
749N/A
749N/A/* Function Name: Scan
749N/A * Description: Scans the text source for the number and type
749N/A * of item specified.
749N/A * Arguments: w - the AsciiSource widget.
749N/A * position - the position to start scanning.
749N/A * type - type of thing to scan for.
749N/A * dir - direction to scan.
749N/A * count - which occurance if this thing to search for.
749N/A * include - whether or not to include the character found in
749N/A * the position that is returned.
749N/A * Returns: the position of the item found.
749N/A *
749N/A * Note: While there are only 'n' characters in the file there are n+1
749N/A * possible cursor positions (one before the first character and
749N/A * one after the last character.
749N/A */
749N/A
749N/Astatic
749N/AXawTextPosition
749N/AScan (w, position, type, dir, count, include)
749N/AWidget w;
749N/AXawTextPosition position;
749N/AXawTextScanType type;
749N/AXawTextScanDirection dir;
749N/Aint count;
749N/ABoolean include;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) w;
749N/A register int inc;
749N/A Piece * piece;
749N/A XawTextPosition first, first_eol_position;
749N/A register char * ptr;
749N/A
749N/A if (type == XawstAll) { /* Optomize this common case. */
749N/A if (dir == XawsdRight)
749N/A return(src->ascii_src.length);
749N/A return(0); /* else. */
749N/A }
749N/A
749N/A if (position > src->ascii_src.length)
749N/A position = src->ascii_src.length;
749N/A
749N/A if ( dir == XawsdRight ) {
749N/A if (position == src->ascii_src.length)
749N/A/*
749N/A * Scanning right from src->ascii_src.length???
749N/A */
749N/A return(src->ascii_src.length);
749N/A inc = 1;
749N/A }
749N/A else {
749N/A if (position == 0)
749N/A return(0); /* Scanning left from 0??? */
749N/A inc = -1;
749N/A position--;
749N/A }
749N/A
749N/A piece = FindPiece(src, position, &first);
749N/A
749N/A/*
749N/A * If the buffer is empty then return 0.
749N/A */
749N/A
749N/A if ( piece->used == 0 ) return(0);
749N/A
749N/A ptr = (position - first) + piece->text;
749N/A
749N/A switch (type) {
749N/A case XawstEOL:
749N/A case XawstParagraph:
749N/A case XawstWhiteSpace:
749N/A for ( ; count > 0 ; count-- ) {
749N/A Boolean non_space = FALSE, first_eol = TRUE;
749N/A while (TRUE) {
749N/A register unsigned char c = *ptr;
749N/A
749N/A ptr += inc;
749N/A position += inc;
749N/A
749N/A if (type == XawstWhiteSpace) {
749N/A if (isspace(c)) {
749N/A if (non_space)
749N/A break;
749N/A }
749N/A else
749N/A non_space = TRUE;
749N/A }
749N/A else if (type == XawstEOL) {
749N/A if (c == '\n') break;
749N/A }
749N/A else { /* XawstParagraph */
749N/A if (first_eol) {
749N/A if (c == '\n') {
749N/A first_eol_position = position;
749N/A first_eol = FALSE;
749N/A }
749N/A }
749N/A else
749N/A if ( c == '\n')
749N/A break;
749N/A else if ( !isspace(c) )
749N/A first_eol = TRUE;
749N/A }
749N/A
749N/A
749N/A if ( ptr < piece->text ) {
749N/A piece = piece->prev;
749N/A if (piece == NULL) /* Begining of text. */
749N/A return(0);
749N/A ptr = piece->text + piece->used - 1;
749N/A }
749N/A else if ( ptr >= (piece->text + piece->used) ) {
749N/A piece = piece->next;
749N/A if (piece == NULL) /* End of text. */
749N/A return(src->ascii_src.length);
749N/A ptr = piece->text;
749N/A }
749N/A }
749N/A }
749N/A if (!include) {
749N/A if ( type == XawstParagraph)
749N/A position = first_eol_position;
749N/A position -= inc;
749N/A }
749N/A break;
749N/A case XawstPositions:
749N/A position += count * inc;
749N/A break;
749N/A/* case XawstAll: ---- handled in special code above */
749N/A }
749N/A
749N/A if ( dir == XawsdLeft )
749N/A position++;
749N/A
749N/A if (position >= src->ascii_src.length)
749N/A return(src->ascii_src.length);
749N/A if (position < 0)
749N/A return(0);
749N/A
749N/A return(position);
749N/A}
749N/A
749N/A/* Function Name: Search
749N/A * Description: Searchs the text source for the text block passed
749N/A * Arguments: w - the AsciiSource Widget.
749N/A * position - the position to start scanning.
749N/A * dir - direction to scan.
749N/A * text - the text block to search for.
749N/A * Returns: the position of the item found.
749N/A */
749N/A
749N/Astatic XawTextPosition
749N/ASearch(w, position, dir, text)
749N/AWidget w;
749N/AXawTextPosition position;
749N/AXawTextScanDirection dir;
749N/AXawTextBlock * text;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) w;
749N/A register int inc, count = 0;
749N/A register char * ptr;
749N/A Piece * piece;
749N/A char * buf;
749N/A XawTextPosition first;
749N/A
749N/A if ( dir == XawsdRight )
749N/A inc = 1;
749N/A else {
749N/A inc = -1;
749N/A if (position == 0)
749N/A return(XawTextSearchError); /* scanning left from 0??? */
749N/A position--;
749N/A }
749N/A
749N/A buf = XtMalloc(sizeof(unsigned char) * text->length);
749N/A strncpy(buf, (text->ptr + text->firstPos), text->length);
749N/A piece = FindPiece(src, position, &first);
749N/A ptr = (position - first) + piece->text;
749N/A
749N/A while (TRUE) {
749N/A if (*ptr == ((dir == XawsdRight) ? *(buf + count)
749N/A : *(buf + text->length - count - 1)) ) {
749N/A if (count == (text->length - 1))
749N/A break;
749N/A else
749N/A count++;
749N/A }
749N/A else {
749N/A if (count != 0) {
749N/A position -=inc * count;
749N/A ptr -= inc * count;
749N/A }
749N/A count = 0;
749N/A }
749N/A
749N/A ptr += inc;
749N/A position += inc;
749N/A
749N/A while ( ptr < piece->text ) {
749N/A piece = piece->prev;
749N/A if (piece == NULL) { /* Begining of text. */
749N/A XtFree(buf);
749N/A return(XawTextSearchError);
749N/A }
749N/A ptr = piece->text + piece->used - 1;
749N/A }
749N/A
749N/A while ( ptr >= (piece->text + piece->used) ) {
749N/A piece = piece->next;
749N/A if (piece == NULL) { /* End of text. */
749N/A XtFree(buf);
749N/A return(XawTextSearchError);
749N/A }
749N/A ptr = piece->text;
749N/A }
749N/A }
749N/A
749N/A XtFree(buf);
749N/A if (dir == XawsdLeft)
749N/A return(position);
749N/A return(position - (text->length - 1));
749N/A}
749N/A
749N/A/* Function Name: SetValues
749N/A * Description: Sets the values for the AsciiSource.
749N/A * Arguments: current - current state of the widget.
749N/A * request - what was requested.
749N/A * new - what the widget will become.
749N/A * Returns: True if redisplay is needed.
749N/A */
749N/A
749N/A/* ARGSUSED */
749N/Astatic Boolean
749N/ASetValues(current, request, new)
749N/AWidget current, request, new;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) new;
749N/A AsciiSrcObject old_src = (AsciiSrcObject) current;
749N/A Boolean total_reset = FALSE;
749N/A FILE * file;
749N/A
749N/A if ( old_src->ascii_src.use_string_in_place !=
749N/A src->ascii_src.use_string_in_place ) {
749N/A XtAppWarning( XtWidgetToApplicationContext(new),
749N/A "AsciiSrc: The XtNuseStrinInPlace resources may not be changed.");
749N/A src->ascii_src.use_string_in_place =
749N/A old_src->ascii_src.use_string_in_place;
749N/A }
749N/A
749N/A if ( (old_src->ascii_src.string != src->ascii_src.string) ||
749N/A (old_src->ascii_src.type != src->ascii_src.type) ) {
749N/A if (old_src->ascii_src.string == src->ascii_src.string) {
749N/A /* Fool it into not freeing the string */
749N/A src->ascii_src.allocated_string = FALSE;
749N/A RemoveOldStringOrFile(old_src); /* remove old info. */
749N/A src->ascii_src.allocated_string = TRUE;
749N/A }
749N/A else {
749N/A RemoveOldStringOrFile(old_src); /* remove old info. */
749N/A src->ascii_src.allocated_string = FALSE;
749N/A }
749N/A
749N/A file = InitStringOrFile(src); /* Init new info. */
749N/A LoadPieces(src, file, NULL); /* load new info into internal buffers. */
749N/A if (file != NULL) fclose(file);
749N/A XawTextSetSource( XtParent(new), new, 0); /* Tell text widget
749N/A what happened. */
749N/A if ( src->ascii_src.type == XawAsciiString )
749N/A src->ascii_src.string = NULL;
749N/A
749N/A total_reset = TRUE;
749N/A }
749N/A
749N/A if ( old_src->ascii_src.ascii_length != src->ascii_src.ascii_length )
749N/A src->ascii_src.piece_size = src->ascii_src.ascii_length;
749N/A
749N/A if ( !total_reset &&
749N/A (old_src->ascii_src.piece_size != src->ascii_src.piece_size) ) {
749N/A String string = StorePiecesInString(old_src);
749N/A FreeAllPieces(old_src);
749N/A LoadPieces(src, NULL, string);
749N/A XtFree(string);
749N/A }
749N/A
749N/A return(FALSE);
749N/A}
749N/A
749N/A/* Function Name: GetValuesHook
749N/A * Description: This is a get values hook routine that sets the
749N/A * values specific to the ascii source.
749N/A * Arguments: w - the AsciiSource Widget.
749N/A * args - the argument list.
749N/A * num_args - the number of args.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/AGetValuesHook(w, args, num_args)
749N/AWidget w;
749N/AArgList args;
749N/ACardinal * num_args;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) w;
749N/A register int i;
749N/A
749N/A if (src->ascii_src.use_string_in_place)
749N/A return;
749N/A
749N/A if (src->ascii_src.type == XawAsciiString) {
749N/A for (i = 0; i < *num_args ; i++ )
749N/A if (streq(args[i].name, XtNstring)) {
749N/A if (XawAsciiSave(w)) /* If save sucessful. */
749N/A *((char **) args[i].value) = src->ascii_src.string;
749N/A break;
749N/A }
749N/A }
749N/A}
749N/A
749N/A/* Function Name: Destroy
749N/A * Description: Destroys an ascii source (frees all data)
749N/A * Arguments: src - the Ascii source Widget to free.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/ADestroy (w)
749N/AWidget w;
749N/A{
749N/A RemoveOldStringOrFile((AsciiSrcObject) w);
749N/A}
749N/A
749N/A/************************************************************
749N/A *
749N/A * Public routines
749N/A *
749N/A ************************************************************/
749N/A
749N/A/* Function Name: XawAsciiSourceFreeString
749N/A * Description: Frees the string returned by a get values call
749N/A * on the string when the source is of type string.
749N/A * Arguments: w - the AsciiSrc widget.
749N/A * Returns: none.
749N/A */
749N/A
749N/Avoid
749N/AXawAsciiSourceFreeString(w)
749N/AWidget w;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) w;
749N/A
749N/A if (src->ascii_src.allocated_string) {
749N/A src->ascii_src.allocated_string = FALSE;
749N/A XtFree(src->ascii_src.string);
749N/A }
749N/A}
749N/A
749N/A/* Function Name: XawAsciiSave
749N/A * Description: Saves all the pieces into a file or string as required.
749N/A * Arguments: w - the asciiSrc Widget.
749N/A * Returns: TRUE if the save was successful.
749N/A */
749N/A
749N/ABoolean
749N/AXawAsciiSave(w)
749N/AWidget w;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) w;
749N/A
749N/A/*
749N/A * If using the string in place then there is no need to play games
749N/A * to get the internal info into a readable string.
749N/A */
749N/A
749N/A if (src->ascii_src.use_string_in_place)
749N/A return(TRUE);
749N/A
749N/A if (src->ascii_src.type == XawAsciiFile) {
749N/A char * string;
749N/A
749N/A if (!src->ascii_src.changes) /* No changes to save. */
749N/A return(TRUE);
749N/A
749N/A string = StorePiecesInString(src);
749N/A
749N/A if (WriteToFile(src, string, src->ascii_src.string) == FALSE) {
749N/A XtFree(string);
749N/A return(FALSE);
749N/A }
749N/A XtFree(string);
749N/A }
749N/A else { /* This is a string widget. */
749N/A if (src->ascii_src.allocated_string == TRUE)
749N/A XtFree(src->ascii_src.string);
749N/A else
749N/A src->ascii_src.allocated_string = TRUE;
749N/A
749N/A src->ascii_src.string = StorePiecesInString(src);
749N/A }
749N/A src->ascii_src.changes = FALSE;
749N/A return(TRUE);
749N/A}
749N/A
749N/A/* Function Name: XawAsciiSaveAsFile
749N/A * Description: Save the current buffer as a file.
749N/A * Arguments: w - the AsciiSrc widget.
749N/A * name - name of the file to save this file into.
749N/A * Returns: True if the save was sucessful.
749N/A */
749N/A
749N/ABoolean
749N/AXawAsciiSaveAsFile(w, name)
749N/AWidget w;
749N/AString name;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) w;
749N/A String string;
749N/A Boolean ret;
749N/A
749N/A string = StorePiecesInString(src);
749N/A
749N/A ret = WriteToFile(src, string, name);
749N/A XtFree(string);
749N/A return(ret);
749N/A}
749N/A
749N/A/* Function Name: XawAsciiSourceChanged
749N/A * Description: Returns true if the source has changed since last saved.
749N/A * Arguments: w - the ascii source widget.
749N/A * Returns: a Boolean (see description).
749N/A */
749N/A
749N/ABoolean
749N/AXawAsciiSourceChanged(w)
749N/AWidget w;
749N/A{
749N/A return( ((AsciiSrcObject) w)->ascii_src.changes );
749N/A}
749N/A
749N/A/************************************************************
749N/A *
749N/A * Private Functions.
749N/A *
749N/A ************************************************************/
749N/A
749N/Astatic void
749N/ARemoveOldStringOrFile(src)
749N/AAsciiSrcObject src;
749N/A{
749N/A FreeAllPieces(src);
749N/A
749N/A if (src->ascii_src.allocated_string)
749N/A XtFree(src->ascii_src.string);
749N/A}
749N/A
749N/A/* Function Name: WriteToFile
749N/A * Description: Write the string specified to the begining of the file
749N/A * specified.
749N/A * Arguments: w - the widget. (for error messages only)
749N/A * string - string to write.
749N/A * name - the name of the file
749N/A * file - file to write it to.
749N/A * Returns: returns TRUE if sucessful, FALSE otherwise.
749N/A */
749N/A
749N/Astatic Boolean
749N/AWriteToFile(src, string, name)
749N/AAsciiSrcObject src;
749N/AString string, name;
749N/A{
749N/A unsigned char buf[BUFSIZ];
749N/A int fd;
749N/A
749N/A if ( ((fd = creat(name, 0666)) == -1 ) ||
749N/A (write(fd, string, sizeof(unsigned char) * strlen(string)) == -1) ) {
749N/A sprintf((char *)buf, "Error, while attempting to write to the file %s.", name);
749N/A XtAppWarning(XtWidgetToApplicationContext((Widget) src), (const char *)buf);
749N/A return(FALSE);
749N/A }
749N/A
749N/A if ( close(fd) == -1 ) {
749N/A sprintf((char *)buf, "Error, while attempting to close the file %s.", name);
749N/A XtAppWarning(XtWidgetToApplicationContext((Widget) src), (const char *)buf);
749N/A return(FALSE);
749N/A }
749N/A return(TRUE);
749N/A}
749N/A
749N/A/* Function Name: StorePiecesInString
749N/A * Description: store the pieces in memory into a standard ascii string.
749N/A * Arguments: data - the ascii pointer data.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic String
749N/AStorePiecesInString(src)
749N/AAsciiSrcObject src;
749N/A{
749N/A String string;
749N/A XawTextPosition first;
749N/A Piece * piece;
749N/A
749N/A string = XtMalloc(sizeof(unsigned char) * src->ascii_src.length + 1);
749N/A
749N/A for (first = 0, piece = src->ascii_src.first_piece ; piece != NULL;
749N/A first += piece->used, piece = piece->next)
749N/A strncpy(string + first, piece->text, piece->used);
749N/A
749N/A string[src->ascii_src.length] = '\0'; /* NULL terminate this sucker. */
749N/A
749N/A/*
749N/A * This will refill all pieces to capacity.
749N/A */
749N/A
749N/A if (src->ascii_src.data_compression) {
749N/A FreeAllPieces(src);
749N/A LoadPieces(src, NULL, string);
749N/A }
749N/A
749N/A return(string);
749N/A}
749N/A
749N/A/* Function Name: InitStringOrFile.
749N/A * Description: Initializes the string or file.
749N/A * Arguments: src - the AsciiSource.
749N/A * Returns: none - May exit though.
749N/A */
749N/A
749N/Astatic FILE *
749N/AInitStringOrFile(src)
749N/AAsciiSrcObject src;
749N/A{
749N/A char * open_mode;
749N/A FILE * file;
749N/A
749N/A if (src->ascii_src.type == XawAsciiString) {
749N/A if (src->ascii_src.string == NULL)
749N/A src->ascii_src.length = 0;
749N/A else
749N/A src->ascii_src.length = strlen(src->ascii_src.string);
749N/A
749N/A if (src->ascii_src.use_string_in_place) {
749N/A if (src->ascii_src.ascii_length == MAGIC_VALUE)
749N/A src->ascii_src.piece_size = src->ascii_src.length;
749N/A else
749N/A src->ascii_src.piece_size = src->ascii_src.ascii_length + 1;
749N/A }
749N/A
749N/A return(NULL);
749N/A }
749N/A
749N/A/*
749N/A * type is XawAsciiFile.
749N/A */
749N/A
749N/A src->ascii_src.is_tempfile = FALSE;
749N/A
749N/A switch (src->text_src.edit_mode) {
749N/A case XawtextRead:
749N/A if (src->ascii_src.string == NULL)
749N/A XtErrorMsg("NoFile", "asciiSourceCreate", "XawError",
749N/A "Creating a read only disk widget and no file specified.",
749N/A NULL, 0);
749N/A open_mode = "r";
749N/A break;
749N/A case XawtextAppend:
749N/A case XawtextEdit:
749N/A if (src->ascii_src.string == NULL) {
749N/A src->ascii_src.string = tmpnam (XtMalloc((unsigned)TMPSIZ));
749N/A src->ascii_src.is_tempfile = TRUE;
749N/A }
749N/A else {
749N/A if (!src->ascii_src.allocated_string) {
749N/A src->ascii_src.allocated_string = TRUE;
749N/A src->ascii_src.string = XtNewString(src->ascii_src.string);
749N/A }
749N/A open_mode = "r+";
749N/A }
749N/A
749N/A break;
749N/A default:
749N/A XtErrorMsg("badMode", "asciiSourceCreate", "XawError",
749N/A "Bad editMode for ascii source; must be Read, Append or Edit.",
749N/A NULL, NULL);
749N/A }
749N/A
749N/A if (!src->ascii_src.is_tempfile) {
749N/A if ((file = fopen(src->ascii_src.string, open_mode)) == 0) {
749N/A String params[2];
749N/A Cardinal num_params = 2;
749N/A
749N/A params[0] = src->ascii_src.string;
749N/A if (errno <= sys_nerr)
749N/A params[1] = sys_errlist[errno];
749N/A else {
749N/A char msg[11];
749N/A sprintf(msg, "errno=%.4d", errno);
749N/A params[1] = msg;
749N/A }
749N/A XtErrorMsg("openError", "asciiSourceCreate", "XawError",
749N/A "Cannot open source file %s; %s", params, &num_params);
749N/A }
749N/A (void) fseek(file, 0L, 2);
749N/A src->ascii_src.length = ftell (file);
749N/A }
749N/A else {
749N/A src->ascii_src.length = 0;
749N/A return(NULL);
749N/A }
749N/A
749N/A return(file);
749N/A}
749N/A
749N/Astatic void
749N/ALoadPieces(src, file, string)
749N/AAsciiSrcObject src;
749N/AFILE * file;
749N/Achar * string;
749N/A{
749N/A char *local_str, *ptr;
749N/A register Piece * piece = NULL;
749N/A XawTextPosition left;
749N/A
749N/A if (string == NULL) {
749N/A if (src->ascii_src.type == XawAsciiFile) {
749N/A local_str = XtMalloc((src->ascii_src.length + 1) *sizeof(unsigned char));
749N/A if (src->ascii_src.length != 0) {
749N/A fseek(file, 0L, 0);
749N/A if ( fread(local_str, sizeof(unsigned char),
749N/A src->ascii_src.length, file) != src->ascii_src.length )
749N/A XtErrorMsg("readError", "asciiSourceCreate", "XawError",
749N/A "fread returned error.", NULL, NULL);
749N/A }
749N/A local_str[src->ascii_src.length] = '\0';
749N/A }
749N/A else
749N/A local_str = src->ascii_src.string;
749N/A }
749N/A else
749N/A local_str = string;
749N/A
749N/A/*
749N/A * If we are using teh string in place then set the other fields as follows:
749N/A *
749N/A * piece_size = length;
749N/A * piece->used = src->ascii_src.length;
749N/A */
749N/A
749N/A if (src->ascii_src.use_string_in_place) {
749N/A piece = AllocNewPiece(src, piece);
749N/A piece->used = Min(src->ascii_src.length, src->ascii_src.piece_size);
749N/A piece->text = src->ascii_src.string;
749N/A return;
749N/A }
749N/A
749N/A ptr = local_str;
749N/A left = src->ascii_src.length;
749N/A
749N/A do {
749N/A piece = AllocNewPiece(src, piece);
749N/A
749N/A piece->text = XtMalloc(src->ascii_src.piece_size * sizeof(unsigned char));
749N/A piece->used = Min(left, src->ascii_src.piece_size);
749N/A if (piece->used != 0)
749N/A strncpy(piece->text, ptr, piece->used);
749N/A
749N/A left -= piece->used;
749N/A ptr += piece->used;
749N/A } while (left > 0);
749N/A
749N/A if ( (src->ascii_src.type == XawAsciiFile) && (string == NULL) )
749N/A XtFree(local_str);
749N/A}
749N/A
749N/A/* Function Name: AllocNewPiece
749N/A * Description: Allocates a new piece of memory.
749N/A * Arguments: src - The AsciiSrc Widget.
749N/A * prev - the piece just before this one, or NULL.
749N/A * Returns: the allocated piece.
749N/A */
749N/A
749N/Astatic Piece *
749N/AAllocNewPiece(src, prev)
749N/AAsciiSrcObject src;
749N/APiece * prev;
749N/A{
749N/A Piece * piece = XtNew(Piece);
749N/A
749N/A if (prev == NULL) {
749N/A src->ascii_src.first_piece = piece;
749N/A piece->next = NULL;
749N/A }
749N/A else {
749N/A if (prev->next != NULL)
749N/A (prev->next)->prev = piece;
749N/A piece->next = prev->next;
749N/A prev->next = piece;
749N/A }
749N/A
749N/A piece->prev = prev;
749N/A
749N/A return(piece);
749N/A}
749N/A
749N/A/* Function Name: FreeAllPieces
749N/A * Description: Frees all the pieces
749N/A * Arguments: src - The AsciiSrc Widget.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/AFreeAllPieces(src)
749N/AAsciiSrcObject src;
749N/A{
749N/A Piece * next, * first = src->ascii_src.first_piece;
749N/A
749N/A if (first->prev != NULL)
749N/A printf("Programmer Botch in FreeAllPieces, there may be a memory leak.\n");
749N/A
749N/A for ( ; first != NULL ; first = next ) {
749N/A next = first->next;
749N/A RemovePiece(src, first);
749N/A }
749N/A}
749N/A
749N/A/* Function Name: RemovePiece
749N/A * Description: Removes a piece from the list.
749N/A * Arguments:
749N/A * piece - the piece to remove.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/ARemovePiece(src, piece)
749N/AAsciiSrcObject src;
749N/APiece * piece;
749N/A{
749N/A if (piece->prev == NULL)
749N/A src->ascii_src.first_piece = piece->next;
749N/A else
749N/A (piece->prev)->next = piece->next;
749N/A
749N/A if (piece->next != NULL)
749N/A (piece->next)->prev = piece->prev;
749N/A
749N/A if (src->ascii_src.allocated_string)
749N/A XtFree(piece->text);
749N/A
749N/A XtFree((char *)piece);
749N/A}
749N/A
749N/A/* Function Name: FindPiece
749N/A * Description: Finds the piece containing the position indicated.
749N/A * Arguments: src - The AsciiSrc Widget.
749N/A * position - the position that we are searching for.
749N/A * RETURNED first - the position of the first character in this piece.
749N/A * Returns: piece - the piece that contains this position.
749N/A */
749N/A
749N/Astatic Piece *
749N/AFindPiece(src, position, first)
749N/AAsciiSrcObject src;
749N/AXawTextPosition position, *first;
749N/A{
749N/A Piece * old_piece, * piece = src->ascii_src.first_piece;
749N/A XawTextPosition temp;
749N/A
749N/A for ( temp = 0 ; piece != NULL ; temp += piece->used, piece = piece->next ) {
749N/A *first = temp;
749N/A old_piece = piece;
749N/A
749N/A if ((temp + piece->used) > position)
749N/A return(piece);
749N/A }
749N/A return(old_piece); /* if we run off the end the return the last piece */
749N/A}
749N/A
749N/A/* Function Name: MyStrncpy
749N/A * Description: Just like string copy, but slower and will always
749N/A * work on overlapping strings.
749N/A * Arguments: (same as strncpy) - s1, s2 - strings to copy (2->1).
749N/A * n - the number of chars to copy.
749N/A * Returns: s1.
749N/A */
749N/A
749N/Astatic String
749N/AMyStrncpy(s1, s2, n)
749N/Achar * s1, * s2;
749N/Aint n;
749N/A{
749N/A char * temp = XtMalloc(sizeof(unsigned char) * n);
749N/A
749N/A strncpy(temp, s2, n); /* Saber has a bug that causes it to generate*/
749N/A strncpy(s1, temp, n); /* a bogus warning message here (CDP 6/32/89)*/
749N/A XtFree(temp);
749N/A return(s1);
749N/A}
749N/A
749N/A/* Function Name: BreakPiece
749N/A * Description: Breaks a full piece into two new pieces.
749N/A * Arguments: src - The AsciiSrc Widget.
749N/A * piece - the piece to break.
749N/A * Returns: none.
749N/A */
749N/A
749N/A#define HALF_PIECE (src->ascii_src.piece_size/2)
749N/A
749N/Astatic void
749N/ABreakPiece(src, piece)
749N/AAsciiSrcObject src;
749N/APiece * piece;
749N/A{
749N/A Piece * new = AllocNewPiece(src, piece);
749N/A
749N/A new->text = XtMalloc(src->ascii_src.piece_size * sizeof(unsigned char));
749N/A strncpy(new->text, piece->text + HALF_PIECE,
749N/A src->ascii_src.piece_size - HALF_PIECE);
749N/A piece->used = HALF_PIECE;
749N/A new->used = src->ascii_src.piece_size - HALF_PIECE;
749N/A}
749N/A
749N/A/* ARGSUSED */
749N/Astatic void
749N/ACvtStringToAsciiType(args, num_args, fromVal, toVal)
749N/AXrmValuePtr *args; /* unused */
749N/ACardinal *num_args; /* unused */
749N/AXrmValuePtr fromVal;
749N/AXrmValuePtr toVal;
749N/A{
749N/A static XawAsciiType type;
749N/A static XrmQuark XtQEstring;
749N/A static XrmQuark XtQEfile;
749N/A static int haveQuarks = FALSE;
749N/A XrmQuark q;
749N/A char lowerName[BUFSIZ];
749N/A
749N/A if (!haveQuarks) {
749N/A XtQEstring = XrmStringToQuark(XtEstring);
749N/A XtQEfile = XrmStringToQuark(XtEfile);
749N/A haveQuarks = TRUE;
749N/A }
749N/A
749N/A XmuCopyISOLatin1Lowered(lowerName, (char *) fromVal->addr);
749N/A q = XrmStringToQuark(lowerName);
749N/A
749N/A if (q == XtQEstring) type = XawAsciiString;
749N/A if (q == XtQEfile) type = XawAsciiFile;
749N/A
749N/A (*toVal).size = sizeof(XawAsciiType);
749N/A (*toVal).addr = (caddr_t) &type;
749N/A return;
749N/A}
749N/A
749N/A#if (defined(ASCII_STRING) || defined(ASCII_DISK))
749N/A# include <./Xaw3_1Cardinals.h>
749N/A#endif
749N/A
749N/A#ifdef ASCII_STRING
749N/A/************************************************************
749N/A *
749N/A * Compatability functions.
749N/A *
749N/A ************************************************************/
749N/A
749N/A/* Function Name: AsciiStringSourceCreate
749N/A * Description: Creates a string source.
749N/A * Arguments: parent - the widget that will own this source.
749N/A * args, num_args - the argument list.
749N/A * Returns: a pointer to the new text source.
749N/A */
749N/A
749N/AWidget
749N/AXawStringSourceCreate(parent, args, num_args)
749N/AWidget parent;
749N/AArgList args;
749N/ACardinal num_args;
749N/A{
749N/A XawTextSource src;
749N/A ArgList ascii_args;
749N/A Arg temp[2];
749N/A
749N/A XtSetArg(temp[0], XtNtype, XawAsciiString);
749N/A XtSetArg(temp[1], XtNuseStringInPlace, TRUE);
749N/A ascii_args = XtMergeArgLists(temp, TWO, args, num_args);
749N/A
749N/A src = XtCreateWidget("genericAsciiString", asciiSrcObjectClass, parent,
749N/A ascii_args, num_args + TWO);
749N/A XtFree((char *)ascii_args);
749N/A return(src);
749N/A}
749N/A
749N/A/*
749N/A * This is hacked up to try to emulate old functionality, it
749N/A * may not work, as I have not old code to test it on.
749N/A *
749N/A * Chris D. Peterson 8/31/89.
749N/A */
749N/A
749N/Avoid
749N/AXawTextSetLastPos (w, lastPos)
749N/AWidget w;
749N/AXawTextPosition lastPos;
749N/A{
749N/A AsciiSrcObject src = (AsciiSrcObject) XawTextGetSource(w);
749N/A
749N/A src->ascii_src.piece_size = lastPos;
749N/A}
749N/A#endif /* ASCII_STRING */
749N/A
749N/A#ifdef ASCII_DISK
749N/A/* Function Name: AsciiDiskSourceCreate
749N/A * Description: Creates a disk source.
749N/A * Arguments: parent - the widget that will own this source.
749N/A * args, num_args - the argument list.
749N/A * Returns: a pointer to the new text source.
749N/A */
749N/A
749N/AWidget
749N/AXawDiskSourceCreate(parent, args, num_args)
749N/AWidget parent;
749N/AArgList args;
749N/ACardinal num_args;
749N/A{
749N/A XawTextSource src;
749N/A ArgList ascii_args;
749N/A Arg temp[1];
749N/A register int i;
749N/A
749N/A XtSetArg(temp[0], XtNtype, XawAsciiFile);
749N/A
749N/A for (i = 0; i < num_args; i++)
749N/A if (streq(args[i].name, XtNfile) || streq(args[i].name, XtCFile))
749N/A args[i].name = XtNstring;
749N/A
749N/A ascii_args = XtMergeArgLists(temp, ONE, args, num_args);
749N/A src = XtCreateWidget("genericAsciiDisk", asciiSrcObjectClass, parent,
749N/A ascii_args, num_args + ONE);
749N/A XtFree((char *)ascii_args);
749N/A return(src);
749N/A}
749N/A#endif /* ASCII_DISK */