749N/A/* $XConsortium: MultiSrc.c,v 1.6 94/04/17 20:12:25 kaleb Exp $ */
749N/A
749N/A/*
749N/A * Copyright 1991 by OMRON Corporation
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 OMRON not be used in
749N/A * advertising or publicity pertaining to distribution of the software without
749N/A * specific, written prior permission. OMRON makes no representations
749N/A * about the suitability of this software for any purpose. It is provided
749N/A * "as is" without express or implied warranty.
749N/A *
749N/A * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
749N/A * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
749N/A * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
749N/A * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
749N/A * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
749N/A * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
749N/A * PERFORMANCE OF THIS SOFTWARE.
749N/A *
749N/A * Authors: Chris Peterson MIT X Consortium
749N/A * Li Yuhong OMRON Corporation
749N/A * Frank Sheeran OMRON Corporation
749N/A *
749N/A * Much code taken from X11R3 String and Disk Sources.
749N/A */
749N/A
749N/A/*
749N/A
749N/ACopyright (c) 1991, 1994 X Consortium
749N/A
749N/APermission is hereby granted, free of charge, to any person obtaining a copy
749N/Aof this software and associated documentation files (the "Software"), to deal
749N/Ain the Software without restriction, including without limitation the rights
749N/Ato use, copy, modify, merge, publish, distribute, sublicense, and/or sell
749N/Acopies of the Software, and to permit persons to whom the Software is
749N/Afurnished to do so, subject to the following conditions:
749N/A
749N/AThe above copyright notice and this permission notice shall be included in
749N/Aall copies or substantial portions of the Software.
749N/A
749N/ATHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
749N/AIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
749N/AFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
749N/AX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
749N/AAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
749N/ACONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
749N/A
749N/AExcept as contained in this notice, the name of the X Consortium shall not be
749N/Aused in advertising or otherwise to promote the sale, use or other dealings
749N/Ain this Software without prior written authorization from the X Consortium.
749N/A
749N/A*/
749N/A
749N/A/*
749N/A * MultiSrc.c - MultiSrc object. (For use with the text widget).
749N/A *
749N/A */
749N/A
749N/A#include <X11/IntrinsicP.h>
749N/A#include <X11/StringDefs.h>
749N/A#include <X11/Xfuncs.h>
749N/A#include <X11/Xaw/XawInit.h>
749N/A#include "MultiSrcP.h"
749N/A#include <X11/Xaw/XawImP.h>
749N/A#include <X11/Xmu/Misc.h>
749N/A#include <X11/Xmu/CharSet.h>
749N/A#include "XawI18n.h"
749N/A#include <X11/Xos.h>
749N/A#include <stdio.h>
749N/A#include <ctype.h>
749N/A#include <errno.h>
749N/A
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) XtOffsetOf(MultiSrcRec, multi_src.field)
749N/A
749N/Astatic XtResource resources[] = {
749N/A {XtNstring, XtCString, XtRString, sizeof (XtPointer),
749N/A offset(string), XtRPointer, NULL},
749N/A {XtNtype, XtCType, XtRMultiType, sizeof (XawAsciiType),
749N/A offset(type), XtRImmediate, (XtPointer)XawAsciiString},
749N/A /* not used. */
749N/A {XtNdataCompression, XtCDataCompression, XtRBoolean, sizeof (Boolean),
749N/A offset(data_compression), XtRImmediate, (XtPointer) FALSE},
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(multi_length), XtRInt, (XtPointer) &magic_value},
749N/A
749N/A};
749N/A#undef offset
749N/A
749N/Astatic XawTextPosition Scan(), Search(), ReadText();
749N/Astatic int ReplaceText();
749N/Astatic MultiPiece * FindPiece(), * AllocNewPiece();
749N/Astatic FILE * InitStringOrFile();
749N/Astatic void FreeAllPieces(), RemovePiece(), BreakPiece(), LoadPieces();
749N/Astatic void RemoveOldStringOrFile(), CvtStringToMultiType();
749N/Astatic void ClassInitialize(), Initialize(), Destroy(), GetValuesHook();
749N/Astatic String StorePiecesInString();
749N/Astatic Boolean SetValues(), WriteToFile();
749N/A
749N/A#define MyWStrncpy( t,s,wcnt ) (void) memmove( (t), (s), (wcnt)*sizeof(wchar_t))
749N/A
749N/A#ifndef MyWStrncpy
749N/Astatic void (MyWStrncpy)();
749N/A#endif
749N/A
749N/Aextern char *tmpnam();
749N/A#ifdef X_NOT_STDC_ENV
749N/Aextern int errno;
749N/A#endif
749N/A
749N/A#ifdef X_NOT_POSIX
749N/A#define Off_t long
749N/A#define Size_t unsigned int
749N/A#else
749N/A#define Off_t off_t
749N/A#define Size_t size_t
749N/A#endif
749N/A
749N/Aextern wchar_t* _XawTextMBToWC();
749N/Aextern char *_XawTextWCToMB();
749N/A
749N/A#define superclass (&textSrcClassRec)
749N/AMultiSrcClassRec multiSrcClassRec = {
749N/A { /* object_class fields */
749N/A /* superclass */ (WidgetClass) superclass,
749N/A /* class_name */ "MultiSrc",
749N/A /* widget_size */ sizeof(MultiSrcRec),
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 /* pad */ NULL,
749N/A /* pad */ NULL,
749N/A /* pad */ 0,
749N/A /* resources */ resources,
749N/A /* num_resources */ XtNumber(resources),
749N/A /* xrm_class */ NULLQUARK,
749N/A /* pad */ FALSE,
749N/A /* pad */ FALSE,
749N/A /* pad */ FALSE,
749N/A /* pad */ FALSE,
749N/A /* destroy */ Destroy,
749N/A /* pad */ NULL,
749N/A /* pad */ NULL,
749N/A /* set_values */ SetValues,
749N/A /* set_values_hook */ NULL,
749N/A /* pad */ NULL,
749N/A /* get_values_hook */ GetValuesHook,
749N/A /* pad */ NULL,
749N/A /* version */ XtVersion,
749N/A /* callback_private */ NULL,
749N/A /* pad */ NULL,
749N/A /* pad */ NULL,
749N/A /* pad */ NULL,
749N/A /* extension */ NULL
749N/A },
749N/A { /* textSrc_class fields */
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 { /* multiSrc_class fields */
749N/A /* Keep the compiler happy */ '\0'
749N/A }
749N/A};
749N/A
749N/AWidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec;
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, XtRMultiType, CvtStringToMultiType,
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, args, num_args)
749N/A Widget request, new;
749N/A ArgList args;
749N/A Cardinal* num_args;
749N/A{
749N/A MultiSrcObject src = (MultiSrcObject) 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 src->multi_src.changes = FALSE;
749N/A src->multi_src.allocated_string = FALSE;
749N/A
749N/A file = InitStringOrFile(src, src->multi_src.type == XawAsciiFile);
749N/A LoadPieces(src, file, NULL);
749N/A
749N/A if (file != NULL) fclose(file);
749N/A src->text_src.text_format = XawFmtWide;
749N/A
749N/A}
749N/A
749N/A/* Function Name: ReadText
749N/A * Description: This function reads the source.
749N/A * Arguments: w - the MultiSource 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/A Widget w;
749N/A XawTextPosition pos;
749N/A XawTextBlock* text;
749N/A int length;
749N/A{
749N/A MultiSrcObject src = (MultiSrcObject) w;
749N/A XawTextPosition count, start;
749N/A MultiPiece * piece = FindPiece(src, pos, &start);
749N/A
749N/A text->format = XawFmtWide;
749N/A text->firstPos = pos;
749N/A text->ptr = (char *)(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 MultiSource 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, u_text_p)
749N/A Widget w;
749N/A XawTextPosition startPos, endPos;
749N/A XawTextBlock* u_text_p;
749N/A{
749N/A MultiSrcObject src = (MultiSrcObject) w;
749N/A MultiPiece *start_piece, *end_piece, *temp_piece;
749N/A XawTextPosition start_first, end_first;
749N/A int length, firstPos;
749N/A wchar_t *wptr;
749N/A Boolean local_artificial_block = False;
749N/A XawTextBlock text;
749N/A
749N/A /* STEP 1: The user handed me a text block called `u_text' that may be
749N/A * in either FMTWIDE or FMT8BIT (ie MB.) Later code needs the block
749N/A * `text' to hold FMTWIDE. So, this copies `u_text' to `text', and if
749N/A * `u_text' was MB, I knock it up to WIDE. */
749N/A
749N/A if ( u_text_p->length == 0 ) /* if so, the block contents never ref'd. */
749N/A text.length = 0;
749N/A
749N/A else if ( u_text_p->format == XawFmtWide) {
749N/A local_artificial_block = False; /* ie, don't have to free it ourselves*/
749N/A text.firstPos = u_text_p->firstPos;
749N/A text.length = u_text_p->length;
749N/A text.ptr = u_text_p->ptr;
749N/A /* text.format is unneeded */
749N/A
749N/A } else {
749N/A /* WARNING! u_text->firstPos and length are in units of CHAR, not CHARACTERS! */
749N/A
749N/A local_artificial_block = True; /* ie, have to free it ourselves */
749N/A text.firstPos = 0;
749N/A text.length = u_text_p->length; /* _XawTextMBToWC converts this to wchar len. */
749N/A
749N/A text.ptr = (char*)_XawTextMBToWC( XtDisplay(XtParent(w)),
749N/A &(u_text_p->ptr[u_text_p->firstPos]), &(text.length) );
749N/A
749N/A /* I assert the following assignment is not needed - since Step 4
749N/A depends on length, it has no need of a terminating NULL. I think
749N/A the ASCII-version has the same needless NULL. */
749N/A /*((wchar_t*)text.ptr)[ text.length ] = NULL;*/
749N/A }
749N/A
749N/A
749N/A /* STEP 2: some initialization... */
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
749N/A /* STEP 3: remove the empty pieces... */
749N/A
749N/A if (start_piece != end_piece) {
749N/A temp_piece = start_piece->next;
749N/A
749N/A /* If empty and not the only piece then remove it. */
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 MyWStrncpy(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 MyWStrncpy(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->multi_src.use_string_in_place &&
749N/A ((src->multi_src.length - (endPos - startPos)) <
749N/A (src->multi_src.piece_size - 1)) )
749N/A start_piece->text[src->multi_src.length - (endPos - startPos)] = (wchar_t)0;
749N/A }
749N/A }
749N/A
749N/A src->multi_src.length += text.length -(endPos - startPos);
749N/A /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/
749N/A
749N/A
749N/A
749N/A /* STEP 4: insert the new stuff */
749N/A
749N/A if ( text.length != 0) {
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 wchar_t* ptr;
749N/A int fill;
749N/A
749N/A if (src->multi_src.use_string_in_place) {
749N/A if (start_piece->used == (src->multi_src.piece_size - 1)) {
749N/A /*
749N/A * The string is used in place, then the string
749N/A * is not allowed to grow.
749N/A */
749N/A start_piece->used = src->multi_src.length =
749N/A src->multi_src.piece_size - 1;
749N/A /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/
749N/A
749N/A
749N/A start_piece->text[src->multi_src.length] = (wchar_t)0;
749N/A return(XawEditError);
749N/A }
749N/A }
749N/A
749N/A
749N/A if (start_piece->used == src->multi_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->multi_src.piece_size - start_piece->used), length);
749N/A
749N/A ptr = start_piece->text + (startPos - start_first);
749N/A MyWStrncpy(ptr + fill, ptr,
749N/A (int) start_piece->used - (startPos - start_first));
749N/A wptr =(wchar_t *)text.ptr;
749N/A (void)wcsncpy(ptr, wptr + 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 ( local_artificial_block == True )
749N/A
749N/A /* In other words, text is not the u_text that the user handed me but
749N/A one I made myself. I only care, because I need to free the string. */
749N/A
749N/A XFree( text.ptr );
749N/A
749N/A if (src->multi_src.use_string_in_place)
749N/A start_piece->text[start_piece->used] = (wchar_t)0;
749N/A
749N/A src->multi_src.changes = TRUE;
749N/A
749N/A XtCallCallbacks(w, XtNcallback, NULL);
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 MultiSource 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/A Widget w;
749N/A XawTextPosition position;
749N/A XawTextScanType type;
749N/A XawTextScanDirection dir;
749N/A int count;
749N/A Boolean include;
749N/A{
749N/A MultiSrcObject src = (MultiSrcObject) w;
749N/A int inc;
749N/A MultiPiece * piece;
749N/A XawTextPosition first, first_eol_position;
749N/A wchar_t * ptr;
749N/A
749N/A if (type == XawstAll) { /* Optimize this common case. */
749N/A if (dir == XawsdRight)
749N/A return(src->multi_src.length);
749N/A return(0); /* else. */
749N/A }
749N/A
749N/A
749N/A /* STEP 1: basic sanity checks */
749N/A
749N/A if (position > src->multi_src.length)
749N/A position = src->multi_src.length;
749N/A
749N/A
749N/A if ( dir == XawsdRight ) {
749N/A if (position == src->multi_src.length)
749N/A return(src->multi_src.length);
749N/A inc = 1;
749N/A }
749N/A else {
749N/A if (position == 0)
749N/A return(0);
749N/A inc = -1;
749N/A position--;
749N/A }
749N/A
749N/A piece = FindPiece(src, position, &first);
749N/A
749N/A if ( piece->used == 0 ) return(0); /* i.e., buffer is empty. */
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 /* CONSTCOND */
749N/A while (TRUE) {
749N/A wchar_t c = *ptr;
749N/A
749N/A ptr += inc;
749N/A position += inc;
749N/A
749N/A if (type == XawstWhiteSpace) {
749N/A if (iswspace(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 == _Xaw_atowc(XawLF)) break;
749N/A }
749N/A else { /* XawstParagraph */
749N/A if (first_eol) {
749N/A if (c == _Xaw_atowc(XawLF)) {
749N/A first_eol_position = position;
749N/A first_eol = FALSE;
749N/A }
749N/A }
749N/A else
749N/A if ( c == _Xaw_atowc(XawLF))
749N/A break;
749N/A else if ( !iswspace(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->multi_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->multi_src.length)
749N/A return(src->multi_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 MultiSource 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/A Widget w;
749N/A XawTextPosition position;
749N/A XawTextScanDirection dir;
749N/A XawTextBlock* text;
749N/A{
749N/A MultiSrcObject src = (MultiSrcObject) w;
749N/A int inc, count = 0;
749N/A wchar_t * ptr;
749N/A wchar_t* wtarget;
749N/A int wtarget_len;
749N/A Display * d = XtDisplay(XtParent(w));
749N/A MultiPiece * piece;
749N/A wchar_t* buf;
749N/A XawTextPosition first;
749N/A
749N/A
749N/A /* STEP 1: First, a brief sanity check. */
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
749N/A /* STEP 2: Ensure I have a local wide string.. */
749N/A
749N/A /* Since this widget stores 32bit chars, I check here to see if
749N/A I'm being passed a string claiming to be 8bit chars (ie, MB text.)
749N/A If that is the case, naturally I convert to 32bit format. */
749N/A
749N/A /*if the block was FMT8BIT, length will convert to REAL wchar count below */
749N/A wtarget_len = text->length;
749N/A
749N/A if ( text->format == XawFmtWide )
749N/A wtarget = &( ((wchar_t*)text->ptr) [text->firstPos] );
749N/A else
749N/A {
749N/A /* The following converts wtarget_len from byte len to wchar count */
749N/A wtarget = _XawTextMBToWC( d, &text->ptr[ text->firstPos ], &wtarget_len );
749N/A }
749N/A
749N/A /* OK, I can now assert that wtarget holds wide characters, wtarget_len
749N/A holds an accurate count of those characters, and that firstPos has been
749N/A effectively factored out of the following computations. */
749N/A
749N/A
749N/A /* STEP 3: SEARCH! */
749N/A
749N/A buf = (wchar_t *)XtMalloc((unsigned)sizeof(wchar_t) * wtarget_len );
749N/A (void)wcsncpy(buf, wtarget, wtarget_len );
749N/A piece = FindPiece(src, position, &first);
749N/A ptr = (position - first) + piece->text;
749N/A
749N/A /* CONSTCOND */
749N/A while (TRUE) {
749N/A if (*ptr == ((dir == XawsdRight) ? *(buf + count)
749N/A : *(buf + wtarget_len - 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((char *)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((char *)buf);
749N/A return(XawTextSearchError);
749N/A }
749N/A ptr = piece->text;
749N/A }
749N/A }
749N/A
749N/A XtFree( (char *) buf );
749N/A if (dir == XawsdLeft)
749N/A return( position );
749N/A return( position - ( wtarget_len - 1 ) );
749N/A}
749N/A
749N/A/* Function Name: SetValues
749N/A * Description: Sets the values for the MultiSource.
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, args, num_args)
749N/A Widget current, request, new;
749N/A ArgList args;
749N/A Cardinal* num_args;
749N/A{
749N/A MultiSrcObject src = (MultiSrcObject) new;
749N/A MultiSrcObject old_src = (MultiSrcObject) current;
749N/A XtAppContext app_con = XtWidgetToApplicationContext(new);
749N/A Boolean total_reset = FALSE, string_set = FALSE;
749N/A FILE * file;
749N/A int i;
749N/A
749N/A if ( old_src->multi_src.use_string_in_place !=
749N/A src->multi_src.use_string_in_place ) {
749N/A XtAppWarning( app_con,
749N/A "MultiSrc: The XtNuseStringInPlace resources may not be changed.");
749N/A src->multi_src.use_string_in_place =
749N/A old_src->multi_src.use_string_in_place;
749N/A }
749N/A
749N/A for (i = 0; i < *num_args ; i++ )
749N/A if (streq(args[i].name, XtNstring)) {
749N/A string_set = TRUE;
749N/A break;
749N/A }
749N/A
749N/A if ( string_set || (old_src->multi_src.type != src->multi_src.type) ) {
749N/A RemoveOldStringOrFile(old_src, string_set);
749N/A file = InitStringOrFile(src, string_set);
749N/A
749N/A /* Load pieces does this logic for us, but it shouldn't. Its messy.*/
749N/A /*if (old_src->multi_src.type == XawAsciiString)
749N/A LoadPieces(src, NULL, src->multi_src.string);
749N/A else*/
749N/A LoadPieces(src, file, NULL);
749N/A if (file != NULL) fclose(file);
749N/A XawTextSetSource( XtParent(new), new, 0); /* Tell text widget
749N/A what happened. */
749N/A total_reset = TRUE;
749N/A }
749N/A
749N/A if ( old_src->multi_src.multi_length != src->multi_src.multi_length )
749N/A src->multi_src.piece_size = src->multi_src.multi_length;
749N/A
749N/A if ( !total_reset && (old_src->multi_src.piece_size
749N/A != src->multi_src.piece_size) ) {
749N/A String mb_string = StorePiecesInString( old_src );
749N/A
749N/A if ( mb_string != 0 ) {
749N/A FreeAllPieces( old_src );
749N/A LoadPieces( src, NULL, mb_string );
749N/A XtFree( mb_string );
749N/A } else {
749N/A /* If the buffer holds bad chars, don't touch it... */
749N/A XtAppWarningMsg( app_con,
749N/A "convertError", "multiSource", "XawError",
749N/A XtName( XtParent( (Widget) old_src ) ), NULL, NULL );
749N/A XtAppWarningMsg( app_con,
749N/A "convertError", "multiSource", "XawError",
749N/A "Non-character code(s) in buffer.", NULL, NULL );
749N/A }
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 multi source.
749N/A * Arguments: w - the MultiSource 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/A Widget w;
749N/A ArgList args;
749N/A Cardinal* num_args;
749N/A{
749N/A MultiSrcObject src = (MultiSrcObject) w;
749N/A int i;
749N/A
749N/A if (src->multi_src.type == XawAsciiString) {
749N/A for (i = 0; i < *num_args ; i++ )
749N/A if (streq(args[i].name, XtNstring)) {
749N/A if (src->multi_src.use_string_in_place) {
749N/A *((char **) args[i].value) = (char *)
749N/A src->multi_src.first_piece->text;
749N/A }
749N/A else {
749N/A if (_XawMultiSave(w)) /* If save sucessful. */
749N/A *((char **) args[i].value) = src->multi_src.string;
749N/A }
749N/A break;
749N/A }
749N/A }
749N/A}
749N/A
749N/A/* Function Name: Destroy
749N/A * Description: Destroys an multi source (frees all data)
749N/A * Arguments: src - the Multi source Widget to free.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/ADestroy (w)
749N/A Widget w;
749N/A{
749N/A RemoveOldStringOrFile((MultiSrcObject) w, True);
749N/A}
749N/A
749N/A/************************************************************
749N/A *
749N/A * Public routines
749N/A *
749N/A ************************************************************/
749N/A
749N/A/* Function Name: XawMultiSourceFreeString
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 MultiSrc widget.
749N/A * Returns: none.
749N/A *
749N/A * The public interface is XawAsciiSourceFreeString!
749N/A */
749N/A
749N/Avoid
749N/A#if NeedFunctionPrototypes
749N/A_XawMultiSourceFreeString(
749N/A Widget w)
749N/A#else
749N/A_XawMultiSourceFreeString(w)
749N/A Widget w;
749N/A#endif
749N/A{
749N/A MultiSrcObject src = (MultiSrcObject) w;
749N/A
749N/A/*if (src->multi_src.allocated_string&& src->multi_src.type != XawAsciiFile) {*/
749N/A /* ASSERT: src->multi_src.allocated_string -> we MUST free .string! */
749N/A if ( src->multi_src.allocated_string ) {
749N/A XtFree(src->multi_src.string);
749N/A src->multi_src.allocated_string = FALSE;
749N/A src->multi_src.string = NULL;
749N/A }
749N/A}
749N/A
749N/A/* Function Name: _XawMultiSave
749N/A * Description: Saves all the pieces into a file or string as required.
749N/A * Arguments: w - the multiSrc Widget.
749N/A * Returns: TRUE if the save was successful.
749N/A *
749N/A * The public interface is XawAsciiSave(w)!
749N/A */
749N/A
749N/ABool
749N/A#if NeedFunctionPrototypes
749N/A_XawMultiSave(
749N/A Widget w)
749N/A#else
749N/A_XawMultiSave(w)
749N/A Widget w;
749N/A#endif
749N/A{
749N/A MultiSrcObject src = (MultiSrcObject) w;
749N/A XtAppContext app_con = XtWidgetToApplicationContext(w);
749N/A char * mb_string;
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->multi_src.use_string_in_place)
749N/A return(TRUE);
749N/A
749N/A if (src->multi_src.type == XawAsciiFile) {
749N/A
749N/A if (!src->multi_src.changes) /* No changes to save. */
749N/A return(TRUE);
749N/A
749N/A mb_string = StorePiecesInString( src );
749N/A
749N/A if ( mb_string != 0 ) {
749N/A if ( WriteToFile( mb_string, src->multi_src.string ) == FALSE ) {
749N/A XtFree( mb_string );
749N/A return( FALSE );
749N/A }
749N/A XtFree( mb_string );
749N/A src->multi_src.changes = FALSE;
749N/A return( TRUE );
749N/A } else {
749N/A /* If the buffer holds bad chars, don't touch it... */
749N/A XtAppWarningMsg( app_con,
749N/A "convertError", "multiSource", "XawError",
749N/A "Due to illegal characters, file not saved.", NULL, NULL);
749N/A return( FALSE );
749N/A }
749N/A }
749N/A else {
749N/A
749N/A /* THIS FUNCTIONALITY IS UNDOCUMENTED, probably UNNEEDED? The manual
749N/A says this routine's only function is to save files to disk. -Sheeran */
749N/A
749N/A mb_string = StorePiecesInString( src );
749N/A
749N/A if ( mb_string == 0 ) {
749N/A /* If the buffer holds bad chars, don't touch it... */
749N/A XtAppWarningMsg( app_con,
749N/A "convertError", "multiSource", "XawError",
749N/A XtName( XtParent( (Widget) src ) ), NULL, NULL);
749N/A return( FALSE );
749N/A }
749N/A
749N/A /* assert: mb_string holds good characters so the buffer is fine */
749N/A if (src->multi_src.allocated_string == TRUE)
749N/A XtFree(src->multi_src.string);
749N/A else
749N/A src->multi_src.allocated_string = TRUE;
749N/A
749N/A src->multi_src.string = mb_string;
749N/A }
749N/A src->multi_src.changes = FALSE;
749N/A return(TRUE);
749N/A}
749N/A
749N/A/* Function Name: XawMultiSaveAsFile
749N/A * Description: Save the current buffer as a file.
749N/A * Arguments: w - the MultiSrc 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 * The public interface is XawAsciiSaveAsFile!
749N/A */
749N/A
749N/ABool
749N/A#if NeedFunctionPrototypes
749N/A_XawMultiSaveAsFile(
749N/A Widget w,
749N/A _Xconst char* name)
749N/A#else
749N/A_XawMultiSaveAsFile(w, name)
749N/A Widget w;
749N/A String name;
749N/A#endif
749N/A{
749N/A MultiSrcObject src = (MultiSrcObject) w;
749N/A String mb_string;
749N/A Boolean ret;
749N/A
749N/A mb_string = StorePiecesInString( src );
749N/A
749N/A if ( mb_string != 0 ) {
749N/A ret = WriteToFile( mb_string, name );
749N/A XtFree( mb_string );
749N/A return( ret );
749N/A }
749N/A
749N/A /* otherwise there was a conversion error. So print widget name too. */
749N/A XtAppWarningMsg( XtWidgetToApplicationContext(w),
749N/A "convertError", "multiSource", "XawError",
749N/A XtName( XtParent( (Widget) src ) ), NULL, NULL);
749N/A return( False );
749N/A}
749N/A
749N/A/************************************************************
749N/A *
749N/A * Private Functions.
749N/A *
749N/A ************************************************************/
749N/A
749N/Astatic void
749N/ARemoveOldStringOrFile(src, checkString)
749N/A MultiSrcObject src;
749N/A Boolean checkString;
749N/A{
749N/A FreeAllPieces(src);
749N/A
749N/A if (checkString && src->multi_src.allocated_string) {
749N/A XtFree(src->multi_src.string);
749N/A src->multi_src.allocated_string = False;
749N/A src->multi_src.string = NULL;
749N/A }
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: string - string to write.
749N/A * name - the name of the file
749N/A * Returns: returns TRUE if sucessful, FALSE otherwise.
749N/A */
749N/A
749N/Astatic Boolean
749N/AWriteToFile(string, name)
749N/A String string, name;
749N/A{
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 return(FALSE);
749N/A
749N/A if ( close(fd) == -1 )
749N/A return(FALSE);
749N/A
749N/A return(TRUE);
749N/A}
749N/A
749N/A
749N/A/* Function Name: StorePiecesInString
749N/A * Description: store the pieces in memory into a char string.
749N/A * Arguments: src - the multiSrc to gather data from
749N/A * Returns: char *mb_string. Caller must free.
749N/A * or 0: conversion error. Caller must panic!
749N/A */
749N/A
749N/Astatic String
749N/AStorePiecesInString(src)
749N/A MultiSrcObject src;
749N/A{
749N/A wchar_t* wc_string;
749N/A char *mb_string;
749N/A int char_count = src->multi_src.length;
749N/A XawTextPosition first;
749N/A MultiPiece * piece;
749N/A
749N/A /* I believe the char_count + 1 and the NULL termination are unneeded! FS*/
749N/A
749N/A wc_string = (wchar_t*) XtMalloc((unsigned)(char_count + 1) * sizeof(wchar_t));
749N/A
749N/A for (first = 0, piece = src->multi_src.first_piece ; piece != NULL;
749N/A first += piece->used, piece = piece->next)
749N/A (void) wcsncpy( wc_string + first, piece->text, piece->used );
749N/A
749N/A wc_string[ char_count ] = (wchar_t)0; /* NULL terminate this sucker. */
749N/A
749N/A
749N/A /* This will refill all pieces to capacity. */
749N/A
749N/A if ( src->multi_src.data_compression ) {
749N/A FreeAllPieces( src );
749N/A LoadPieces( src, NULL, (char *)wc_string );
749N/A }
749N/A
749N/A /* Lastly, convert it to a MB format and send it back. */
749N/A
749N/A mb_string = _XawTextWCToMB( XtDisplayOfObject( (Widget)src ),
749N/A wc_string, &char_count );
749N/A
749N/A /* NOTE THAT mb_string MAY BE ZERO IF THE CONVERSION FAILED. */
749N/A XtFree( (char*) wc_string );
749N/A return( mb_string );
749N/A}
749N/A
749N/A
749N/A/* Function Name: InitStringOrFile.
749N/A * Description: Initializes the string or file.
749N/A * Arguments: src - the MultiSource.
749N/A * Returns: none - May exit though.
749N/A */
749N/A
749N/Astatic FILE *
749N/AInitStringOrFile(src, newString)
749N/A MultiSrcObject src;
749N/A Boolean newString;
749N/A{
749N/A char * open_mode;
749N/A FILE * file;
749N/A char fileName[TMPSIZ];
749N/A Display *d = XtDisplayOfObject((Widget)src);
749N/A
749N/A if (src->multi_src.type == XawAsciiString) {
749N/A
749N/A if (src->multi_src.string == NULL)
749N/A src->multi_src.length = 0;
749N/A
749N/A else if (! src->multi_src.use_string_in_place) {
749N/A int length;
749N/A String temp = XtNewString(src->multi_src.string);
749N/A if ( src->multi_src.allocated_string )
749N/A XtFree( src->multi_src.string );
749N/A src->multi_src.allocated_string = True;
749N/A src->multi_src.string = temp;
749N/A
749N/A length = strlen(src->multi_src.string);
749N/A
749N/A /* Wasteful, throwing away the WC string, but need side effect! */
749N/A (void) _XawTextMBToWC(d, src->multi_src.string, &length);
749N/A src->multi_src.length = (XawTextPosition) length;
749N/A } else {
749N/A src->multi_src.length = strlen(src->multi_src.string);
749N/A /* In case the length resource is incorrectly set */
749N/A if (src->multi_src.length > src->multi_src.multi_length)
749N/A src->multi_src.multi_length = src->multi_src.length;
749N/A
749N/A if (src->multi_src.multi_length == MAGIC_VALUE)
749N/A src->multi_src.piece_size = src->multi_src.length;
749N/A else
749N/A src->multi_src.piece_size = src->multi_src.multi_length + 1;
749N/A }
749N/A
749N/A /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/
749N/A return(NULL);
749N/A }
749N/A
749N/A/*
749N/A * type is XawAsciiFile.
749N/A */
749N/A
749N/A src->multi_src.is_tempfile = FALSE;
749N/A
749N/A switch (src->text_src.edit_mode) {
749N/A case XawtextRead:
749N/A if (src->multi_src.string == NULL)
749N/A XtErrorMsg("NoFile", "multiSourceCreate", "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->multi_src.string == NULL) {
749N/A
749N/A if ( src->multi_src.allocated_string )
749N/A XtFree( src->multi_src.string );
749N/A src->multi_src.allocated_string = False;
749N/A src->multi_src.string = fileName;
749N/A
749N/A (void) tmpnam(src->multi_src.string);
749N/A src->multi_src.is_tempfile = TRUE;
749N/A open_mode = "w";
749N/A } else
749N/A open_mode = "r+";
749N/A break;
749N/A default:
749N/A XtErrorMsg("badMode", "multiSourceCreate", "XawError",
749N/A "Bad editMode for multi source; must be Read, Append or Edit.",
749N/A NULL, NULL);
749N/A }
749N/A
749N/A /* Allocate new memory for the temp filename, because it is held in
749N/A * a stack memory buffer. We must verify that all routines that set
749N/A * .string first check .allocated_string and free it - plumbing Sheeran.
749N/A */
749N/A if (newString || src->multi_src.is_tempfile) {
749N/A if ( src->multi_src.allocated_string )
749N/A XtFree( src->multi_src.string );
749N/A src->multi_src.string = XtNewString(src->multi_src.string);
749N/A src->multi_src.allocated_string = TRUE;
749N/A }
749N/A
749N/A if (!src->multi_src.is_tempfile) {
749N/A if ((file = fopen(src->multi_src.string, open_mode)) != 0) {
749N/A (void) fseek(file, (Off_t)0, 2);
749N/A src->multi_src.length = ftell (file);
749N/A return file;
749N/A } else {
749N/A String params[2];
749N/A Cardinal num_params = 2;
749N/A
749N/A params[0] = src->multi_src.string;
749N/A params[1] = strerror(errno);
749N/A XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
749N/A "openError", "multiSourceCreate", "XawWarning",
749N/A "Cannot open file %s; %s", params, &num_params);
749N/A }
749N/A }
749N/A src->multi_src.length = 0;
749N/A return((FILE *)NULL);
749N/A#undef StrLen
749N/A}
749N/A
749N/A/* LoadPieces: This routine takes either the MB contents of open file `file' or the
749N/AMB contents of string or the MB contents of src->multi_src.string and places
749N/Athem in Pieces in WC format.
749N/A
749N/ACAUTION: You must have src->multi_src.length set to file length bytes
749N/Awhen src->multi_src.type == XawAsciiFile. src->multi_src.length must be
749N/Athe length of the parameter string if string is non-NULL. */
749N/A
749N/Astatic void
749N/ALoadPieces(src, file, string)
749N/A MultiSrcObject src;
749N/A FILE* file;
749N/A char* string;
749N/A{
749N/A Display *d = XtDisplayOfObject((Widget)src);
749N/A wchar_t* local_str, *ptr;
749N/A MultiPiece* piece = NULL;
749N/A XawTextPosition left;
749N/A int bytes = sizeof(wchar_t);
749N/A char* temp_mb_holder = NULL;
749N/A
749N/A /*
749N/A * This is tricky - the _XawTextMBtoWC converter uses its 3rd arg
749N/A * in as MB length, out as WC length. We want local_length to be
749N/A * WC count.
749N/A */
749N/A int local_length = src->multi_src.length;
749N/A
749N/A if (string != NULL) {
749N/A /*
749N/A * ASSERT: IF our caller passed a non-null string, THEN
749N/A * src->multi_src.length is currently string's * byte count,
749N/A * AND string is in a MB format.
749N/A */
749N/A local_str = _XawTextMBToWC(d, (char *)string, &local_length);
749N/A src->multi_src.length = (XawTextPosition) local_length;
749N/A } else if (src->multi_src.type != XawAsciiFile) {
749N/A /*
749N/A * here, we are not changing the contents, just reloading,
749N/A * so don't change len...
749N/A */
749N/A local_length = src->multi_src.string ?
749N/A strlen( src->multi_src.string ) : 0;
749N/A local_str = _XawTextMBToWC( d, (char*)src->multi_src.string, &local_length );
749N/A } else {
749N/A if (src->multi_src.length != 0) {
749N/A temp_mb_holder =
749N/A XtMalloc((unsigned)(src->multi_src.length + 1) * sizeof(unsigned char));
749N/A fseek(file, (Off_t)0, 0);
749N/A src->multi_src.length = fread (temp_mb_holder,
749N/A (Size_t)sizeof(unsigned char),
749N/A (Size_t)src->multi_src.length, file);
749N/A if (src->multi_src.length <= 0)
749N/A XtAppErrorMsg( XtWidgetToApplicationContext ((Widget) src),
749N/A "readError", "multiSource", "XawError",
749N/A "fread returned error.", NULL, NULL);
749N/A local_length = src->multi_src.length;
749N/A local_str = _XawTextMBToWC(d, temp_mb_holder, &local_length);
749N/A src->multi_src.length = local_length;
749N/A
749N/A if ( local_str == 0 ) {
749N/A String params[2];
749N/A Cardinal num_params;
749N/A static char err_text[] =
749N/A "<<< FILE CONTENTS NOT REPRESENTABLE IN THIS LOCALE >>>";
749N/A
749N/A params[0] = XtName(XtParent((Widget)src));
749N/A params[1] = src->multi_src.string;
749N/A num_params = 2;
749N/A
749N/A XtAppWarningMsg( XtWidgetToApplicationContext((Widget)src),
749N/A "readLocaleError", "multiSource", "XawError",
749N/A "%s: The file `%s' contains characters not representable in this locale.",
749N/A params, &num_params);
749N/A src->multi_src.length = sizeof err_text;
749N/A local_length = src->multi_src.length;
749N/A local_str = _XawTextMBToWC(d, err_text, &local_length);
749N/A src->multi_src.length = local_length;
749N/A }
749N/A } else { /*ASSERT that since following while loop looks at local_length
749N/A this isn't needed. Sheeran, Omron KK, 1993/07/15
749N/A temp_mb_holder[src->multi_src.length] = '\0';*/
749N/A local_str = (wchar_t*)temp_mb_holder;
749N/A }
749N/A }
749N/A
749N/A if (src->multi_src.use_string_in_place) {
749N/A piece = AllocNewPiece(src, piece);
749N/A piece->used = Min(src->multi_src.length, src->multi_src.piece_size);
749N/A piece->text = (wchar_t*)src->multi_src.string;
749N/A return;
749N/A }
749N/A
749N/A ptr = local_str;
749N/A left = local_length;
749N/A
749N/A do {
749N/A piece = AllocNewPiece(src, piece);
749N/A
749N/A piece->text = (wchar_t*)XtMalloc(src->multi_src.piece_size * bytes);
749N/A piece->used = Min(left, src->multi_src.piece_size);
749N/A if (piece->used != 0)
749N/A (void) wcsncpy(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 ( temp_mb_holder )
749N/A XtFree( (char*) temp_mb_holder );
749N/A}
749N/A
749N/A
749N/A/* Function Name: AllocNewPiece
749N/A * Description: Allocates a new piece of memory.
749N/A * Arguments: src - The MultiSrc Widget.
749N/A * prev - the piece just before this one, or NULL.
749N/A * Returns: the allocated piece.
749N/A */
749N/A
749N/Astatic MultiPiece *
749N/AAllocNewPiece(src, prev)
749N/A MultiSrcObject src;
749N/A MultiPiece * prev;
749N/A{
749N/A MultiPiece * piece = XtNew(MultiPiece);
749N/A
749N/A if (prev == NULL) {
749N/A src->multi_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 MultiSrc Widget.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/AFreeAllPieces(src)
749N/A MultiSrcObject src;
749N/A{
749N/A MultiPiece * next, * first = src->multi_src.first_piece;
749N/A
749N/A if (first->prev != NULL)
749N/A printf("Xaw MultiSrc Object: possible memory leak in FreeAllPieces().\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/A MultiSrcObject src;
749N/A MultiPiece* piece;
749N/A{
749N/A if (piece->prev == NULL)
749N/A src->multi_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->multi_src.use_string_in_place)
749N/A XtFree((char *)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 MultiSrc 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 MultiPiece *
749N/AFindPiece(src, position, first)
749N/A MultiSrcObject src;
749N/A XawTextPosition position, *first;
749N/A{
749N/A MultiPiece * old_piece, * piece = src->multi_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: BreakPiece
749N/A * Description: Breaks a full piece into two new pieces.
749N/A * Arguments: src - The MultiSrc Widget.
749N/A * piece - the piece to break.
749N/A * Returns: none.
749N/A */
749N/A
749N/A#define HALF_PIECE (src->multi_src.piece_size/2)
749N/A
749N/Astatic void
749N/ABreakPiece(src, piece)
749N/A MultiSrcObject src;
749N/A MultiPiece* piece;
749N/A{
749N/A MultiPiece * new = AllocNewPiece(src, piece);
749N/A
749N/A new->text = (wchar_t*)XtMalloc(src->multi_src.piece_size * sizeof(wchar_t));
749N/A (void) wcsncpy(new->text, piece->text + HALF_PIECE,
749N/A src->multi_src.piece_size - HALF_PIECE);
749N/A piece->used = HALF_PIECE;
749N/A new->used = src->multi_src.piece_size - HALF_PIECE;
749N/A}
749N/A
749N/A/* Convert string "XawAsciiString" and "XawAsciiFile" to quarks. */
749N/A
749N/A/* ARGSUSED */
749N/Astatic void
749N/ACvtStringToMultiType(args, num_args, fromVal, toVal)
749N/A XrmValuePtr args; /* unused */
749N/A Cardinal* num_args; /* unused */
749N/A XrmValuePtr fromVal;
749N/A XrmValuePtr toVal;
749N/A{
749N/A static XawAsciiType type;
749N/A static XrmQuark XtQEstring = NULLQUARK;
749N/A static XrmQuark XtQEfile;
749N/A XrmQuark q;
749N/A char lowerName[40];
749N/A
749N/A if (XtQEstring == NULLQUARK) {
749N/A XtQEstring = XrmPermStringToQuark(XtEstring);
749N/A XtQEfile = XrmPermStringToQuark(XtEfile);
749N/A }
749N/A
749N/A if (strlen ((char*) fromVal->addr) < sizeof lowerName) {
749N/A XmuCopyISOLatin1Lowered(lowerName, (char *) fromVal->addr);
749N/A q = XrmStringToQuark(lowerName);
749N/A
749N/A if (q == XtQEstring) type = XawAsciiString;
749N/A else if (q == XtQEfile) type = XawAsciiFile;
749N/A else {
749N/A toVal->size = 0;
749N/A toVal->addr = NULL;
749N/A return;
749N/A }
749N/A toVal->size = sizeof type;
749N/A toVal->addr = (XPointer) &type;
749N/A return;
749N/A }
749N/A toVal->size = 0;
749N/A toVal->addr = NULL;
749N/A}