MultiSrc.c

Go to the documentation of this file.
00001 /* $XConsortium: MultiSrc.c,v 1.8 95/01/24 22:29:08 kaleb Exp $ */
00002 
00003 /*
00004  * Copyright 1991 by OMRON Corporation
00005  *
00006  * Permission to use, copy, modify, distribute, and sell this software and its
00007  * documentation for any purpose is hereby granted without fee, provided that
00008  * the above copyright notice appear in all copies and that both that
00009  * copyright notice and this permission notice appear in supporting
00010  * documentation, and that the name OMRON not be used in
00011  * advertising or publicity pertaining to distribution of the software without
00012  * specific, written prior permission.  OMRON makes no representations
00013  * about the suitability of this software for any purpose.  It is provided
00014  * "as is" without express or implied warranty.
00015  *
00016  * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
00017  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
00018  * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
00019  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
00020  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
00021  * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00022  * PERFORMANCE OF THIS SOFTWARE.
00023  *
00024  *      Authors: Chris Peterson MIT X Consortium
00025  *               Li Yuhong      OMRON Corporation
00026  *               Frank Sheeran  OMRON Corporation
00027  *
00028  * Much code taken from X11R3 String and Disk Sources.
00029  */
00030 
00031 /*
00032 
00033 Copyright (c) 1991, 1994  X Consortium
00034 
00035 Permission is hereby granted, free of charge, to any person obtaining a copy
00036 of this software and associated documentation files (the "Software"), to deal
00037 in the Software without restriction, including without limitation the rights
00038 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00039 copies of the Software, and to permit persons to whom the Software is
00040 furnished to do so, subject to the following conditions:
00041 
00042 The above copyright notice and this permission notice shall be included in
00043 all copies or substantial portions of the Software.
00044 
00045 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00046 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00047 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00048 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00049 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00050 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00051 
00052 Except as contained in this notice, the name of the X Consortium shall not be
00053 used in advertising or otherwise to promote the sale, use or other dealings
00054 in this Software without prior written authorization from the X Consortium.
00055 
00056 */
00057 
00058 /*
00059  * MultiSrc.c - MultiSrc object. (For use with the text widget).
00060  *
00061  */
00062 
00063 #include <X11/IntrinsicP.h>
00064 #include <X11/StringDefs.h>
00065 #include <X11/Xfuncs.h>
00066 #include <X11/Xaw3d/XawInit.h>
00067 #include <X11/Xaw3d/MultiSrcP.h>
00068 #include <X11/Xaw3d/XawImP.h>
00069 #include <X11/Xmu/Misc.h>
00070 #include <X11/Xmu/CharSet.h>
00071 #include "XawI18n.h"
00072 #include <X11/Xos.h>
00073 #include <stdio.h>
00074 #include <ctype.h>
00075 #include <errno.h>
00076 
00077 /****************************************************************
00078  *
00079  * Full class record constant
00080  *
00081  ****************************************************************/
00082 
00083 /* Private Data */
00084 
00085 static int magic_value = MAGIC_VALUE;
00086 
00087 #define offset(field) XtOffsetOf(MultiSrcRec, multi_src.field)
00088 
00089 static XtResource resources[] = {
00090     {XtNstring, XtCString, XtRString, sizeof (XtPointer),
00091        offset(string), XtRPointer, NULL},
00092     {XtNtype, XtCType, XtRMultiType, sizeof (XawAsciiType),
00093        offset(type), XtRImmediate, (XtPointer)XawAsciiString},
00094     /* not used. */
00095     {XtNdataCompression, XtCDataCompression, XtRBoolean, sizeof (Boolean),
00096        offset(data_compression), XtRImmediate, (XtPointer) FALSE},
00097     {XtNpieceSize, XtCPieceSize, XtRInt, sizeof (XawTextPosition),
00098        offset(piece_size), XtRImmediate, (XtPointer) BUFSIZ},
00099     {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), 
00100        offset(callback), XtRCallback, (XtPointer)NULL},
00101     {XtNuseStringInPlace, XtCUseStringInPlace, XtRBoolean, sizeof (Boolean),
00102        offset(use_string_in_place), XtRImmediate, (XtPointer) FALSE},
00103     {XtNlength, XtCLength, XtRInt, sizeof (int),
00104        offset(multi_length), XtRInt, (XtPointer) &magic_value},
00105 
00106 };
00107 #undef offset
00108 
00109 static XawTextPosition Scan(), Search(), ReadText();
00110 static int ReplaceText();
00111 static MultiPiece * FindPiece(), * AllocNewPiece();
00112 static FILE * InitStringOrFile();
00113 static void FreeAllPieces(), RemovePiece(), BreakPiece(), LoadPieces();
00114 static void RemoveOldStringOrFile(),  CvtStringToMultiType();
00115 static void ClassInitialize(), Initialize(), Destroy(), GetValuesHook();
00116 static String StorePiecesInString();
00117 static Boolean SetValues(), WriteToFile();
00118 
00119 #define MyWStrncpy( t,s,wcnt ) (void) memmove( (t), (s), (wcnt)*sizeof(wchar_t))
00120 
00121 #ifndef MyWStrncpy
00122 static void (MyWStrncpy)();
00123 #endif
00124 
00125 extern char *tmpnam();
00126 #ifdef X_NOT_STDC_ENV
00127 extern int errno; 
00128 #endif
00129 
00130 #ifdef X_NOT_POSIX
00131 #define Off_t long
00132 #define Size_t unsigned int
00133 #else
00134 #define Off_t off_t
00135 #define Size_t size_t
00136 #endif
00137 
00138 extern wchar_t* _XawTextMBToWC();
00139 extern char *_XawTextWCToMB();
00140 
00141 #define superclass              (&textSrcClassRec)
00142 MultiSrcClassRec multiSrcClassRec = {
00143   { /* object_class fields */   
00144     /* superclass               */      (WidgetClass) superclass,
00145     /* class_name               */      "MultiSrc",
00146     /* widget_size              */      sizeof(MultiSrcRec),
00147     /* class_initialize         */      ClassInitialize,
00148     /* class_part_initialize    */      NULL,
00149     /* class_inited             */      FALSE,
00150     /* initialize               */      Initialize,
00151     /* initialize_hook          */      NULL,
00152     /* pad                      */      NULL,
00153     /* pad                      */      NULL,
00154     /* pad                      */      0,
00155     /* resources                */      resources,
00156     /* num_resources            */      XtNumber(resources),
00157     /* xrm_class                */      NULLQUARK,
00158     /* pad                      */      FALSE,
00159     /* pad                      */      FALSE,
00160     /* pad                      */      FALSE,
00161     /* pad                      */      FALSE,
00162     /* destroy                  */      Destroy,
00163     /* pad                      */      NULL,
00164     /* pad                      */      NULL,
00165     /* set_values               */      SetValues,
00166     /* set_values_hook          */      NULL,
00167     /* pad                      */      NULL,
00168     /* get_values_hook          */      GetValuesHook,
00169     /* pad                      */      NULL,
00170     /* version                  */      XtVersion,
00171     /* callback_private         */      NULL,
00172     /* pad                      */      NULL,
00173     /* pad                      */      NULL,
00174     /* pad                      */      NULL,
00175     /* extension                */      NULL
00176   },
00177   { /* textSrc_class fields */
00178     /* Read                     */      ReadText,
00179     /* Replace                  */      ReplaceText,
00180     /* Scan                     */      Scan,
00181     /* Search                   */      Search,
00182     /* SetSelection             */      XtInheritSetSelection,
00183     /* ConvertSelection         */      XtInheritConvertSelection
00184   },
00185   { /* multiSrc_class fields */
00186     /* Keep the compiler happy */       '\0'
00187   }
00188 };
00189 
00190 WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec;
00191 
00192 /************************************************************
00193  *
00194  * Semi-Public Interfaces.
00195  *
00196  ************************************************************/
00197 
00198 /*      Function Name: ClassInitialize
00199  *      Description: Class Initialize routine, called only once.
00200  *      Arguments: none.
00201  *      Returns: none.
00202  */
00203 
00204 static void
00205 ClassInitialize()
00206 {
00207   XawInitializeWidgetSet();
00208   XtAddConverter( XtRString, XtRMultiType, CvtStringToMultiType,
00209                  NULL, (Cardinal) 0);
00210 }
00211 
00212 /*      Function Name: Initialize
00213  *      Description: Initializes the simple menu widget
00214  *      Arguments: request - the widget requested by the argument list.
00215  *                 new     - the new widget with both resource and non
00216  *                           resource values.
00217  *      Returns: none.
00218  */
00219 
00220 /* ARGSUSED */
00221 static void
00222 Initialize(request, new, args, num_args)
00223     Widget request, new;
00224     ArgList args;
00225     Cardinal* num_args;
00226 {
00227   MultiSrcObject src = (MultiSrcObject) new;
00228   FILE * file;
00229 
00230 /*
00231  * Set correct flags (override resources) depending upon widget class.
00232  */
00233 
00234   src->multi_src.changes = FALSE;
00235   src->multi_src.allocated_string = FALSE;
00236 
00237   file = InitStringOrFile(src, src->multi_src.type == XawAsciiFile);
00238   LoadPieces(src, file, NULL);
00239 
00240   if (file != NULL) fclose(file);
00241   src->text_src.text_format = XawFmtWide;
00242 
00243 }
00244 
00245 /*      Function Name: ReadText
00246  *      Description: This function reads the source.
00247  *      Arguments: w - the MultiSource widget.
00248  *                 pos - position of the text to retreive.
00249  * RETURNED        text - text block that will contain returned text.
00250  *                length - maximum number of characters to read.
00251  *      Returns: The number of characters read into the buffer.
00252  */
00253 
00254 static XawTextPosition
00255 ReadText(w, pos, text, length)
00256     Widget w;
00257     XawTextPosition pos;
00258     XawTextBlock* text; 
00259     int length;         
00260 {
00261   MultiSrcObject src = (MultiSrcObject) w;
00262   XawTextPosition count, start;
00263   MultiPiece * piece = FindPiece(src, pos, &start);
00264     
00265   text->format = XawFmtWide;
00266   text->firstPos = pos;
00267   text->ptr = (char *)(piece->text + (pos - start));
00268   count = piece->used - (pos - start);
00269   text->length = (length > count) ? count : length;
00270   return(pos + text->length);
00271 }
00272 
00273 /*      Function Name: ReplaceText.
00274  *      Description: Replaces a block of text with new text.
00275  *      Arguments: w - the MultiSource widget.
00276  *                 startPos, endPos - ends of text that will be removed.
00277  *                 text - new text to be inserted into buffer at startPos.
00278  *      Returns: XawEditError or XawEditDone.
00279  */
00280 
00281 /*ARGSUSED*/
00282 static int 
00283 ReplaceText( w, startPos, endPos, u_text_p)
00284     Widget w;
00285     XawTextPosition startPos, endPos;
00286     XawTextBlock* u_text_p;
00287 {
00288   MultiSrcObject src = (MultiSrcObject) w;
00289   MultiPiece *start_piece, *end_piece, *temp_piece;
00290   XawTextPosition start_first, end_first;
00291   int length, firstPos;
00292   wchar_t *wptr;
00293   Boolean local_artificial_block = False;
00294   XawTextBlock text;
00295 
00296   /* STEP 1: The user handed me a text block called `u_text' that may be 
00297    * in either FMTWIDE or FMT8BIT (ie MB.)  Later code needs the block 
00298    * `text' to hold FMTWIDE.  So, this copies `u_text' to `text', and if 
00299    * `u_text' was MB, I knock it up to WIDE. */
00300 
00301   if ( u_text_p->length == 0 )  /* if so, the block contents never ref'd. */
00302       text.length = 0;
00303 
00304   else if ( u_text_p->format == XawFmtWide) {
00305       local_artificial_block = False;           /* ie, don't have to free it ourselves*/
00306       text.firstPos = u_text_p->firstPos;
00307       text.length =   u_text_p->length;
00308       text.ptr =      u_text_p->ptr;
00309       /* text.format is unneeded */
00310 
00311   } else {
00312       /* WARNING! u_text->firstPos and length are in units of CHAR, not CHARACTERS! */
00313 
00314       local_artificial_block = True;    /* ie, have to free it ourselves */
00315       text.firstPos = 0;
00316       text.length = u_text_p->length; /* _XawTextMBToWC converts this to wchar len. */
00317 
00318       text.ptr = (char*)_XawTextMBToWC( XtDisplay(XtParent(w)),
00319                          &(u_text_p->ptr[u_text_p->firstPos]), &(text.length) );
00320 
00321       /* I assert the following assignment is not needed - since Step 4
00322       depends on length, it has no need of a terminating NULL.  I think
00323       the ASCII-version has the same needless NULL. */
00324       /*((wchar_t*)text.ptr)[ text.length ] = NULL;*/
00325   }
00326 
00327 
00328   /* STEP 2: some initialization... */
00329 
00330   if (src->text_src.edit_mode == XawtextRead) 
00331     return(XawEditError);
00332 
00333   start_piece = FindPiece(src, startPos, &start_first);
00334   end_piece = FindPiece(src, endPos, &end_first);
00335 
00336 
00337   /* STEP 3: remove the empty pieces... */
00338 
00339   if (start_piece != end_piece) {
00340     temp_piece = start_piece->next;
00341 
00342   /* If empty and not the only piece then remove it. */
00343 
00344     if ( ((start_piece->used = startPos - start_first) == 0) &&
00345          !((start_piece->next == NULL) && (start_piece->prev == NULL)) )
00346       RemovePiece(src, start_piece);
00347 
00348     while (temp_piece != end_piece) {
00349       temp_piece = temp_piece->next;
00350       RemovePiece(src, temp_piece->prev);
00351     }
00352     end_piece->used -= endPos - end_first;
00353     if (end_piece->used != 0)
00354       MyWStrncpy(end_piece->text, (end_piece->text + endPos - end_first),
00355                 (int) end_piece->used);
00356   }
00357   else {                        /* We are fully in one piece. */
00358     if ( (start_piece->used -= endPos - startPos) == 0) {
00359       if ( !((start_piece->next == NULL) && (start_piece->prev == NULL)) )
00360         RemovePiece(src, start_piece);
00361     }
00362     else {
00363       MyWStrncpy(start_piece->text + (startPos - start_first),
00364                 start_piece->text + (endPos - start_first),
00365                 (int) (start_piece->used - (startPos - start_first)) );
00366       if ( src->multi_src.use_string_in_place && 
00367            ((src->multi_src.length - (endPos - startPos)) < 
00368             (src->multi_src.piece_size - 1)) ) 
00369         start_piece->text[src->multi_src.length - (endPos - startPos)] = (wchar_t)0;
00370     }
00371   }
00372 
00373   src->multi_src.length += text.length -(endPos - startPos);
00374   /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/
00375 
00376 
00377 
00378   /* STEP 4: insert the new stuff */
00379 
00380   if ( text.length != 0) {
00381 
00382     start_piece = FindPiece(src, startPos, &start_first);
00383     
00384     length = text.length;
00385     firstPos = text.firstPos;
00386     
00387     while (length > 0) {
00388       wchar_t* ptr;
00389       int fill;
00390       
00391       if (src->multi_src.use_string_in_place) {
00392         if (start_piece->used == (src->multi_src.piece_size - 1)) {
00393           /*
00394            * The string is used in place, then the string
00395            * is not allowed to grow.
00396            */
00397           start_piece->used = src->multi_src.length =
00398                                                  src->multi_src.piece_size - 1;
00399           /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/
00400 
00401 
00402           start_piece->text[src->multi_src.length] = (wchar_t)0;
00403           return(XawEditError);
00404         }
00405       }
00406 
00407 
00408       if (start_piece->used == src->multi_src.piece_size) {
00409         BreakPiece(src, start_piece);
00410         start_piece = FindPiece(src, startPos, &start_first);
00411       }
00412 
00413       fill = Min((int)(src->multi_src.piece_size - start_piece->used), length);
00414       
00415       ptr = start_piece->text + (startPos - start_first);
00416       MyWStrncpy(ptr + fill, ptr, 
00417                 (int) start_piece->used - (startPos - start_first));
00418       wptr =(wchar_t *)text.ptr;
00419       (void)wcsncpy(ptr, wptr + firstPos, fill);
00420       
00421       startPos += fill;
00422       firstPos += fill;
00423       start_piece->used += fill;
00424       length -= fill;
00425     }
00426   }
00427 
00428   if ( local_artificial_block == True )
00429 
00430       /* In other words, text is not the u_text that the user handed me but
00431       one I made myself.  I only care, because I need to free the string. */
00432 
00433       XFree( text.ptr );
00434 
00435   if (src->multi_src.use_string_in_place)
00436     start_piece->text[start_piece->used] = (wchar_t)0;
00437 
00438   src->multi_src.changes = TRUE;
00439 
00440   XtCallCallbacks(w, XtNcallback, NULL);
00441 
00442   return(XawEditDone);
00443 }
00444 
00445 /*      Function Name: Scan
00446  *      Description: Scans the text source for the number and type
00447  *                   of item specified.
00448  *      Arguments: w - the MultiSource widget.
00449  *                 position - the position to start scanning.
00450  *                 type - type of thing to scan for.
00451  *                 dir - direction to scan.
00452  *                 count - which occurance if this thing to search for.
00453  *                 include - whether or not to include the character found in
00454  *                           the position that is returned. 
00455  *      Returns: the position of the item found.
00456  *
00457  * Note: While there are only 'n' characters in the file there are n+1 
00458  *       possible cursor positions (one before the first character and
00459  *       one after the last character.
00460  */
00461 
00462 static 
00463 XawTextPosition 
00464 Scan( w, position, type, dir, count, include )
00465     Widget w;
00466     XawTextPosition position;
00467     XawTextScanType type;
00468     XawTextScanDirection dir;
00469     int count;
00470     Boolean include;
00471 {
00472   MultiSrcObject src = (MultiSrcObject) w;
00473   int inc;
00474   MultiPiece * piece;
00475   XawTextPosition first, first_eol_position = 0;
00476   wchar_t * ptr;
00477 
00478   if (type == XawstAll) {       /* Optimize this common case. */
00479     if (dir == XawsdRight)
00480       return(src->multi_src.length);
00481     return(0);                  /* else. */
00482   }
00483 
00484 
00485   /* STEP 1: basic sanity checks */
00486 
00487   if (position > src->multi_src.length)
00488     position = src->multi_src.length;
00489 
00490 
00491   if ( dir == XawsdRight ) {
00492     if (position == src->multi_src.length)
00493       return(src->multi_src.length);
00494     inc = 1;
00495   }
00496   else {
00497     if (position == 0)
00498       return(0);
00499     inc = -1;
00500     position--;
00501   }
00502 
00503   piece = FindPiece(src, position, &first);
00504 
00505   if ( piece->used == 0 ) return(0); /* i.e., buffer is empty. */
00506 
00507   ptr = (position - first) + piece->text;
00508 
00509   switch (type) {
00510   case XawstEOL: 
00511   case XawstParagraph: 
00512   case XawstWhiteSpace: 
00513     for ( ; count > 0 ; count-- ) {
00514       Boolean non_space = FALSE, first_eol = TRUE;
00515       /* CONSTCOND */
00516       while (TRUE) {
00517         wchar_t c = *ptr;
00518 
00519         ptr += inc;
00520         position += inc;
00521         
00522         if (type == XawstWhiteSpace) {
00523           if (iswspace(c)) {
00524             if (non_space) 
00525               break;
00526           }
00527           else
00528             non_space = TRUE;
00529         }
00530         else if (type == XawstEOL) {
00531           if (c == _Xaw_atowc(XawLF)) break;
00532         }
00533         else { /* XawstParagraph */
00534           if (first_eol) {
00535             if (c == _Xaw_atowc(XawLF)) {
00536               first_eol_position = position;
00537               first_eol = FALSE;
00538             }
00539           }
00540           else
00541             if ( c == _Xaw_atowc(XawLF))
00542               break;
00543             else if ( !iswspace(c) )
00544               first_eol = TRUE;
00545         }
00546               
00547 
00548         if ( ptr < piece->text ) {
00549           piece = piece->prev;
00550           if (piece == NULL)    /* Begining of text. */
00551             return(0);
00552           ptr = piece->text + piece->used - 1;
00553         }
00554         else if ( ptr >= (piece->text + piece->used) ) {
00555           piece = piece->next;
00556           if (piece == NULL)    /* End of text. */
00557             return(src->multi_src.length);
00558           ptr = piece->text;
00559         }
00560       }
00561     }
00562     if (!include) {
00563       if ( type == XawstParagraph)
00564         position = first_eol_position;
00565       position -= inc;
00566     }
00567     break;
00568   case XawstPositions: 
00569     position += count * inc;
00570     break;
00571   case XawstAll:                /* handled in special code above */
00572   default:
00573     break;
00574   }
00575 
00576   if ( dir == XawsdLeft )
00577     position++;
00578 
00579   if (position >= src->multi_src.length)
00580     return(src->multi_src.length);
00581   if (position < 0)
00582     return(0);
00583 
00584   return(position);
00585 }
00586 
00587 /*      Function Name: Search
00588  *      Description: Searchs the text source for the text block passed
00589  *      Arguments: w - the MultiSource Widget.
00590  *                 position - the position to start scanning.
00591  *                 dir - direction to scan.
00592  *                 text - the text block to search for.
00593  *      Returns: the position of the item found.
00594  */
00595 
00596 static XawTextPosition 
00597 Search(w, position, dir, text )
00598     Widget w;
00599     XawTextPosition position;
00600     XawTextScanDirection dir;
00601     XawTextBlock* text;
00602 {
00603   MultiSrcObject src = (MultiSrcObject) w;
00604   int inc, count = 0;
00605   wchar_t * ptr;
00606   wchar_t* wtarget;
00607   int wtarget_len;
00608   Display * d = XtDisplay(XtParent(w));
00609   MultiPiece * piece;
00610   wchar_t* buf;
00611   XawTextPosition first;
00612 
00613 
00614   /* STEP 1: First, a brief sanity check. */
00615 
00616   if ( dir == XawsdRight )
00617     inc = 1;
00618   else {
00619     inc = -1;
00620     if (position == 0)
00621       return(XawTextSearchError);       /* scanning left from 0??? */
00622     position--;
00623   }
00624 
00625 
00626   /* STEP 2: Ensure I have a local wide string.. */
00627 
00628   /* Since this widget stores 32bit chars, I check here to see if
00629   I'm being passed a string claiming to be 8bit chars (ie, MB text.)
00630   If that is the case, naturally I convert to 32bit format. */
00631 
00632   /*if the block was FMT8BIT, length will convert to REAL wchar count below */
00633   wtarget_len = text->length;
00634 
00635   if ( text->format == XawFmtWide )
00636       wtarget = &( ((wchar_t*)text->ptr) [text->firstPos] );
00637   else
00638   {
00639       /* The following converts wtarget_len from byte len to wchar count */
00640       wtarget = _XawTextMBToWC( d, &text->ptr[ text->firstPos ], &wtarget_len );
00641   }
00642 
00643   /* OK, I can now assert that wtarget holds wide characters, wtarget_len
00644   holds an accurate count of those characters, and that firstPos has been
00645   effectively factored out of the following computations. */
00646 
00647 
00648   /* STEP 3: SEARCH! */
00649 
00650   buf = (wchar_t *)XtMalloc((unsigned)sizeof(wchar_t) * wtarget_len );
00651   (void)wcsncpy(buf, wtarget, wtarget_len );
00652   piece = FindPiece(src, position, &first);
00653   ptr = (position - first) + piece->text;
00654 
00655   /* CONSTCOND */
00656   while (TRUE) {
00657     if (*ptr == ((dir == XawsdRight) ? *(buf + count) 
00658                                      : *(buf + wtarget_len - count - 1)) ) {
00659       if (count == (text->length - 1))
00660         break;
00661       else
00662         count++;
00663     }
00664     else {
00665       if (count != 0) {
00666         position -=inc * count;
00667         ptr -= inc * count;
00668       }
00669       count = 0;
00670     }
00671 
00672     ptr += inc;
00673     position += inc;
00674     
00675     while ( ptr < piece->text ) {
00676       piece = piece->prev;
00677       if (piece == NULL) {      /* Begining of text. */
00678         XtFree((char *)buf);
00679         return(XawTextSearchError);
00680       }
00681       ptr = piece->text + piece->used - 1;
00682     }
00683    
00684     while ( ptr >= (piece->text + piece->used) ) {
00685       piece = piece->next;
00686       if (piece == NULL) {      /* End of text. */
00687         XtFree((char *)buf);
00688         return(XawTextSearchError);
00689       }
00690       ptr = piece->text;
00691     }
00692   }
00693 
00694   XtFree( (char *) buf );
00695   if (dir == XawsdLeft)
00696     return( position );
00697   return( position - ( wtarget_len - 1 ) );
00698 }
00699 
00700 /*      Function Name: SetValues
00701  *      Description: Sets the values for the MultiSource.
00702  *      Arguments: current - current state of the widget.
00703  *                 request - what was requested.
00704  *                 new - what the widget will become.
00705  *      Returns: True if redisplay is needed.
00706  */
00707 
00708 /* ARGSUSED */
00709 static Boolean
00710 SetValues(current, request, new, args, num_args)
00711     Widget current, request, new;
00712     ArgList args;
00713     Cardinal* num_args;
00714 {
00715   MultiSrcObject src =      (MultiSrcObject) new;
00716   MultiSrcObject old_src = (MultiSrcObject) current;
00717   XtAppContext app_con = XtWidgetToApplicationContext(new);
00718   Boolean total_reset = FALSE, string_set = FALSE;
00719   FILE * file;
00720   int i;
00721 
00722   if ( old_src->multi_src.use_string_in_place != 
00723        src->multi_src.use_string_in_place ) {
00724       XtAppWarning( app_con,
00725            "MultiSrc: The XtNuseStringInPlace resources may not be changed.");
00726        src->multi_src.use_string_in_place = 
00727            old_src->multi_src.use_string_in_place;
00728   }
00729 
00730   for (i = 0; i < *num_args ; i++ ) 
00731       if (streq(args[i].name, XtNstring)) {
00732           string_set = TRUE;
00733           break;
00734       }
00735   
00736   if ( string_set || (old_src->multi_src.type != src->multi_src.type) ) {
00737     RemoveOldStringOrFile(old_src, string_set);
00738     file = InitStringOrFile(src, string_set);
00739 
00740     /* Load pieces does this logic for us, but it shouldn't.  Its messy.*/
00741     /*if (old_src->multi_src.type == XawAsciiString)
00742         LoadPieces(src, NULL, src->multi_src.string);
00743     else*/
00744         LoadPieces(src, file, NULL);
00745     if (file != NULL) fclose(file);
00746     XawTextSetSource( XtParent(new), new, 0);   /* Tell text widget
00747                                                    what happened. */
00748     total_reset = TRUE;
00749   }
00750 
00751   if ( old_src->multi_src.multi_length != src->multi_src.multi_length ) 
00752       src->multi_src.piece_size = src->multi_src.multi_length;
00753 
00754   if ( !total_reset && (old_src->multi_src.piece_size
00755                                         != src->multi_src.piece_size) ) {
00756       String mb_string = StorePiecesInString( old_src );
00757 
00758       if ( mb_string != 0 ) {
00759           FreeAllPieces( old_src );
00760           LoadPieces( src, NULL, mb_string );
00761           XtFree( mb_string );
00762       } else {
00763           /* If the buffer holds bad chars, don't touch it... */
00764           XtAppWarningMsg( app_con,
00765                 "convertError", "multiSource", "XawError",
00766                  XtName( XtParent( (Widget) old_src ) ), NULL, NULL );
00767           XtAppWarningMsg( app_con,
00768                 "convertError", "multiSource", "XawError",
00769                  "Non-character code(s) in buffer.", NULL, NULL );
00770       }
00771   }
00772 
00773   return(FALSE);
00774 }
00775 
00776 /*      Function Name: GetValuesHook
00777  *      Description: This is a get values hook routine that sets the
00778  *                   values specific to the multi source.
00779  *      Arguments: w - the MultiSource Widget.
00780  *                 args - the argument list.
00781  *                 num_args - the number of args.
00782  *      Returns: none.
00783  */
00784 
00785 static void
00786 GetValuesHook(w, args, num_args)
00787     Widget w;
00788     ArgList args;
00789     Cardinal* num_args;
00790 {
00791   MultiSrcObject src = (MultiSrcObject) w;
00792   int i;
00793 
00794   if (src->multi_src.type == XawAsciiString) {
00795     for (i = 0; i < *num_args ; i++ ) 
00796       if (streq(args[i].name, XtNstring)) {
00797           if (src->multi_src.use_string_in_place) {
00798               *((char **) args[i].value) = (char *)
00799                                         src->multi_src.first_piece->text;
00800           }
00801           else {
00802               if (_XawMultiSave(w))     /* If save sucessful. */
00803                   *((char **) args[i].value) = src->multi_src.string;
00804           }
00805         break;
00806       }
00807   }
00808 }    
00809 
00810 /*      Function Name: Destroy
00811  *      Description: Destroys an multi source (frees all data)
00812  *      Arguments: src - the Multi source Widget to free.
00813  *      Returns: none.
00814  */
00815 
00816 static void 
00817 Destroy (w)
00818     Widget w;
00819 {
00820     RemoveOldStringOrFile((MultiSrcObject) w, True);
00821 }
00822 
00823 /************************************************************
00824  *
00825  * Public routines 
00826  *
00827  ************************************************************/
00828 
00829 /*      Function Name: XawMultiSourceFreeString
00830  *      Description: Frees the string returned by a get values call
00831  *                   on the string when the source is of type string.
00832  *      Arguments: w - the MultiSrc widget.
00833  *      Returns: none.
00834  *
00835  * The public interface is XawAsciiSourceFreeString!
00836  */
00837 
00838 void
00839 #if NeedFunctionPrototypes
00840 _XawMultiSourceFreeString(
00841     Widget w)
00842 #else
00843 _XawMultiSourceFreeString(w)
00844     Widget w;
00845 #endif
00846 {
00847   MultiSrcObject src = (MultiSrcObject) w;
00848 
00849 /*if (src->multi_src.allocated_string&& src->multi_src.type != XawAsciiFile) {*/
00850   /* ASSERT: src->multi_src.allocated_string -> we MUST free .string! */
00851   if ( src->multi_src.allocated_string ) {
00852     XtFree(src->multi_src.string);
00853     src->multi_src.allocated_string = FALSE;
00854     src->multi_src.string = NULL;
00855   }
00856 }
00857 
00858 /*      Function Name: _XawMultiSave
00859  *      Description: Saves all the pieces into a file or string as required.
00860  *      Arguments: w - the multiSrc Widget.
00861  *      Returns: TRUE if the save was successful.
00862  *
00863  * The public interface is XawAsciiSave(w)!
00864  */
00865 
00866 Boolean
00867 #if NeedFunctionPrototypes
00868 _XawMultiSave(
00869     Widget w)
00870 #else
00871 _XawMultiSave(w)
00872     Widget w;
00873 #endif
00874 {
00875   MultiSrcObject src = (MultiSrcObject) w;
00876   XtAppContext app_con = XtWidgetToApplicationContext(w);
00877   char * mb_string;
00878 
00879 /*
00880  * If using the string in place then there is no need to play games
00881  * to get the internal info into a readable string.
00882  */
00883 
00884   if (src->multi_src.use_string_in_place) 
00885     return(TRUE);
00886 
00887   if (src->multi_src.type == XawAsciiFile) {
00888 
00889       if (!src->multi_src.changes)              /* No changes to save. */
00890           return(TRUE);
00891 
00892       mb_string = StorePiecesInString( src );
00893 
00894       if ( mb_string != 0 ) {
00895           if ( WriteToFile( mb_string, src->multi_src.string ) == FALSE ) {
00896               XtFree( mb_string );
00897               return( FALSE );
00898           }
00899           XtFree( mb_string );
00900           src->multi_src.changes = FALSE;
00901           return( TRUE );
00902       } else {
00903           /* If the buffer holds bad chars, don't touch it... */
00904           XtAppWarningMsg( app_con,
00905                 "convertError", "multiSource", "XawError",
00906                 "Due to illegal characters, file not saved.", NULL, NULL);
00907           return( FALSE );
00908       }
00909   }
00910   else {
00911 
00912   /* THIS FUNCTIONALITY IS UNDOCUMENTED, probably UNNEEDED?  The manual
00913   says this routine's only function is to save files to disk.  -Sheeran */
00914 
00915       mb_string = StorePiecesInString( src );
00916 
00917       if ( mb_string == 0 ) {
00918           /* If the buffer holds bad chars, don't touch it... */
00919           XtAppWarningMsg( app_con,
00920                 "convertError", "multiSource", "XawError",
00921                  XtName( XtParent( (Widget) src ) ), NULL, NULL);
00922           return( FALSE );
00923       }
00924 
00925       /* assert: mb_string holds good characters so the buffer is fine */
00926       if (src->multi_src.allocated_string == TRUE) 
00927           XtFree(src->multi_src.string);
00928       else
00929           src->multi_src.allocated_string = TRUE;
00930     
00931       src->multi_src.string = mb_string;
00932   }
00933   src->multi_src.changes = FALSE;
00934   return(TRUE);
00935 }
00936 
00937 /*      Function Name: XawMultiSaveAsFile
00938  *      Description: Save the current buffer as a file.
00939  *      Arguments: w - the MultiSrc widget.
00940  *                 name - name of the file to save this file into.
00941  *      Returns: True if the save was sucessful.
00942  *
00943  * The public interface is XawAsciiSaveAsFile!
00944  */
00945 
00946 Boolean
00947 #if NeedFunctionPrototypes
00948 _XawMultiSaveAsFile(
00949     Widget w, 
00950     _Xconst char* name)
00951 #else
00952 _XawMultiSaveAsFile(w, name)
00953     Widget w;
00954     String name;
00955 #endif
00956 {
00957   MultiSrcObject src = (MultiSrcObject) w;
00958   String mb_string;
00959   Boolean ret;
00960 
00961   mb_string = StorePiecesInString( src ); 
00962 
00963   if ( mb_string != 0 ) {
00964       ret = WriteToFile( mb_string, name );
00965       XtFree( mb_string );
00966       return( ret );
00967   }
00968 
00969   /* otherwise there was a conversion error.  So print widget name too. */
00970   XtAppWarningMsg( XtWidgetToApplicationContext(w),
00971                 "convertError", "multiSource", "XawError",
00972                 XtName( XtParent( (Widget) src ) ), NULL, NULL);
00973   return( False );
00974 }
00975 
00976 /************************************************************
00977  *
00978  * Private Functions.
00979  *
00980  ************************************************************/
00981 
00982 static void
00983 RemoveOldStringOrFile(src, checkString) 
00984     MultiSrcObject src;
00985     Boolean checkString;
00986 {
00987   FreeAllPieces(src);
00988 
00989   if (checkString && src->multi_src.allocated_string) {
00990     XtFree(src->multi_src.string);
00991     src->multi_src.allocated_string = False;
00992     src->multi_src.string = NULL;
00993   }
00994 }
00995 
00996 /*      Function Name: WriteToFile
00997  *      Description: Write the string specified to the begining of the file
00998  *                   specified.
00999  *      Arguments: string - string to write.
01000  *                 name - the name of the file
01001  *      Returns: returns TRUE if sucessful, FALSE otherwise.
01002  */
01003 
01004 static Boolean
01005 WriteToFile(string, name)
01006     String string, name;
01007 {
01008   int fd;
01009   
01010   if ( ((fd = creat(name, 0666)) == -1 ) ||
01011        (write(fd, string, sizeof(unsigned char) * strlen(string)) == -1) )
01012     return(FALSE);
01013 
01014   if ( close(fd) == -1 ) 
01015     return(FALSE);
01016 
01017   return(TRUE);
01018 }
01019 
01020 
01021 /*      Function Name: StorePiecesInString
01022  *      Description:   store the pieces in memory into a char string.
01023  *      Arguments:     src - the multiSrc to gather data from
01024  *      Returns:       char *mb_string.     Caller must free.
01025  *                  or 0: conversion error. Caller must panic!
01026  */
01027 
01028 static String
01029 StorePiecesInString(src)
01030     MultiSrcObject src;
01031 {
01032   wchar_t* wc_string;
01033   char *mb_string;
01034   int char_count = src->multi_src.length;
01035   XawTextPosition first;
01036   MultiPiece * piece;
01037 
01038   /* I believe the char_count + 1 and the NULL termination are unneeded! FS*/
01039 
01040   wc_string = (wchar_t*) XtMalloc((unsigned)(char_count + 1) * sizeof(wchar_t));
01041 
01042   for (first = 0, piece = src->multi_src.first_piece ; piece != NULL;
01043                                 first += piece->used, piece = piece->next)
01044       (void) wcsncpy( wc_string + first, piece->text, piece->used );
01045 
01046   wc_string[ char_count ] = (wchar_t)0; /* NULL terminate this sucker. */
01047 
01048 
01049   /* This will refill all pieces to capacity. */
01050 
01051   if ( src->multi_src.data_compression ) {
01052     FreeAllPieces( src );
01053     LoadPieces( src, NULL, (char *)wc_string );
01054   }
01055 
01056   /* Lastly, convert it to a MB format and send it back. */
01057 
01058   mb_string = _XawTextWCToMB( XtDisplayOfObject( (Widget)src ),
01059                                                 wc_string, &char_count );
01060 
01061   /* NOTE THAT mb_string MAY BE ZERO IF THE CONVERSION FAILED. */
01062   XtFree( (char*) wc_string );
01063   return( mb_string );
01064 }
01065 
01066 
01067 /*      Function Name: InitStringOrFile.
01068  *      Description: Initializes the string or file.
01069  *      Arguments: src - the MultiSource.
01070  *      Returns: none - May exit though.
01071  */
01072 
01073 static FILE *
01074 InitStringOrFile(src, newString)
01075     MultiSrcObject src;
01076     Boolean newString;
01077 {
01078     char * open_mode = NULL;
01079     FILE * file;
01080     char fileName[TMPSIZ];
01081     Display *d = XtDisplayOfObject((Widget)src);
01082 
01083     if (src->multi_src.type == XawAsciiString) {
01084 
01085         if (src->multi_src.string == NULL)
01086             src->multi_src.length = 0;
01087 
01088         else if (! src->multi_src.use_string_in_place) {
01089             int length;
01090             String temp = XtNewString(src->multi_src.string);
01091             if ( src->multi_src.allocated_string )
01092                 XtFree( src->multi_src.string );
01093             src->multi_src.allocated_string = True;
01094             src->multi_src.string = temp;
01095 
01096             length = strlen(src->multi_src.string);
01097 
01098             /* Wasteful, throwing away the WC string, but need side effect! */
01099             (void) _XawTextMBToWC(d, src->multi_src.string, &length);
01100             src->multi_src.length = (XawTextPosition) length;
01101         } else {
01102             src->multi_src.length = strlen(src->multi_src.string);
01103             /* In case the length resource is incorrectly set */
01104             if (src->multi_src.length > src->multi_src.multi_length)
01105                 src->multi_src.multi_length = src->multi_src.length;
01106 
01107             if (src->multi_src.multi_length == MAGIC_VALUE) 
01108                 src->multi_src.piece_size = src->multi_src.length;
01109             else
01110                 src->multi_src.piece_size = src->multi_src.multi_length + 1;
01111         }
01112                 
01113        /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/
01114         return(NULL);
01115     }
01116 
01117 /*
01118  * type is XawAsciiFile.
01119  */
01120     
01121     src->multi_src.is_tempfile = FALSE;
01122 
01123     switch (src->text_src.edit_mode) {
01124     case XawtextRead:
01125         if (src->multi_src.string == NULL)
01126             XtErrorMsg("NoFile", "multiSourceCreate", "XawError",
01127                      "Creating a read only disk widget and no file specified.",
01128                        NULL, 0);
01129         open_mode = "r";
01130         break;
01131     case XawtextAppend:
01132     case XawtextEdit:
01133         if (src->multi_src.string == NULL) {
01134 
01135             if ( src->multi_src.allocated_string )
01136                 XtFree( src->multi_src.string );
01137             src->multi_src.allocated_string = False;
01138             src->multi_src.string = fileName;
01139 
01140             (void) tmpnam(src->multi_src.string);
01141             src->multi_src.is_tempfile = TRUE;
01142             open_mode = "w";
01143         } else
01144             open_mode = "r+";
01145         break;
01146     default:
01147         XtErrorMsg("badMode", "multiSourceCreate", "XawError",
01148                 "Bad editMode for multi source; must be Read, Append or Edit.",
01149                    NULL, NULL);
01150     }
01151 
01152     /* Allocate new memory for the temp filename, because it is held in
01153      * a stack memory buffer.  We must verify that all routines that set
01154      * .string first check .allocated_string and free it - plumbing Sheeran.
01155      */
01156     if (newString || src->multi_src.is_tempfile) {
01157         if ( src->multi_src.allocated_string )
01158             src->multi_src.string = XtNewString(src->multi_src.string);
01159         src->multi_src.allocated_string = TRUE;
01160     }
01161     
01162     if (!src->multi_src.is_tempfile) {
01163         if ((file = fopen(src->multi_src.string, open_mode)) != 0) {
01164             (void) fseek(file, (Off_t)0, 2);
01165             src->multi_src.length = ftell (file);
01166             return file;
01167         } else {
01168             String params[2];
01169             Cardinal num_params = 2;
01170             
01171             params[0] = src->multi_src.string;
01172             params[1] = strerror(errno);
01173             XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
01174                             "openError", "multiSourceCreate", "XawWarning",
01175                             "Cannot open file %s; %s", params, &num_params);
01176         }
01177     } 
01178     src->multi_src.length = 0;
01179     return((FILE *)NULL);
01180 #undef StrLen
01181 }
01182 
01183 /* LoadPieces:  This routine takes either the MB contents of open file `file' or the
01184 MB contents of string or the MB contents of src->multi_src.string and places
01185 them in Pieces in WC format.
01186  
01187 CAUTION: You must have src->multi_src.length set to file length bytes 
01188 when src->multi_src.type == XawAsciiFile.  src->multi_src.length must be
01189 the length of the parameter string if string is non-NULL.               */
01190 
01191 static void
01192 LoadPieces(src, file, string)
01193     MultiSrcObject src;
01194     FILE* file;
01195     char* string;
01196 {
01197   Display *d = XtDisplayOfObject((Widget)src);
01198   wchar_t* local_str, *ptr;
01199   MultiPiece* piece = NULL;
01200   XawTextPosition left;
01201   int bytes = sizeof(wchar_t);
01202   char* temp_mb_holder = NULL;
01203 
01204   /* 
01205    * This is tricky - the _XawTextMBtoWC converter uses its 3rd arg 
01206    * in as MB length, out as WC length.  We want local_length to be 
01207    * WC count. 
01208    */
01209   int local_length = src->multi_src.length;
01210 
01211   if (string != NULL) {
01212     /* 
01213      * ASSERT: IF our caller passed a non-null string, THEN 
01214      * src->multi_src.length is currently string's * byte count, 
01215      * AND string is in a MB format.
01216      */
01217     local_str = _XawTextMBToWC(d, (char *)string, &local_length);
01218     src->multi_src.length = (XawTextPosition) local_length;
01219   } else if (src->multi_src.type != XawAsciiFile) {
01220     /* 
01221      * here, we are not changing the contents, just reloading, 
01222      * so don't change len...
01223      */
01224     local_length = src->multi_src.string ? 
01225                    strlen( src->multi_src.string ) : 0;
01226     local_str = _XawTextMBToWC( d, (char*)src->multi_src.string, &local_length );
01227   } else {
01228     if (src->multi_src.length != 0) {
01229       temp_mb_holder = 
01230         XtMalloc((unsigned)(src->multi_src.length + 1) * sizeof(unsigned char));
01231       fseek(file, (Off_t)0, 0);
01232       src->multi_src.length = fread (temp_mb_holder, 
01233                                      (Size_t)sizeof(unsigned char), 
01234                                      (Size_t)src->multi_src.length, file);
01235       if (src->multi_src.length <= 0) 
01236         XtAppErrorMsg( XtWidgetToApplicationContext ((Widget) src),
01237                        "readError", "multiSource", "XawError",
01238                        "fread returned error.", NULL, NULL);
01239       local_length = src->multi_src.length;
01240       local_str = _XawTextMBToWC(d, temp_mb_holder, &local_length);
01241       src->multi_src.length = local_length;
01242 
01243       if ( local_str == 0 ) {
01244         String params[2];
01245         Cardinal num_params;
01246         static char err_text[] = 
01247                 "<<< FILE CONTENTS NOT REPRESENTABLE IN THIS LOCALE >>>";
01248 
01249         params[0] = XtName(XtParent((Widget)src));
01250         params[1] = src->multi_src.string;
01251         num_params = 2;
01252 
01253         XtAppWarningMsg( XtWidgetToApplicationContext((Widget)src),
01254                          "readLocaleError", "multiSource", "XawError",
01255     "%s: The file `%s' contains characters not representable in this locale.",
01256                          params, &num_params);
01257         src->multi_src.length = sizeof err_text;
01258         local_length = src->multi_src.length;
01259         local_str = _XawTextMBToWC(d, err_text, &local_length);
01260         src->multi_src.length = local_length;
01261       }
01262     } else { /*ASSERT that since following while loop looks at local_length
01263         this isn't needed.  Sheeran, Omron KK, 1993/07/15
01264         temp_mb_holder[src->multi_src.length] = '\0';*/
01265         local_str = (wchar_t*)temp_mb_holder;
01266     }
01267   }
01268 
01269   if (src->multi_src.use_string_in_place) {
01270       piece = AllocNewPiece(src, piece);
01271       piece->used = Min(src->multi_src.length, src->multi_src.piece_size);
01272       piece->text = (wchar_t*)src->multi_src.string;
01273       return;
01274   }
01275 
01276   ptr = local_str;
01277   left = local_length;
01278 
01279   do {
01280       piece = AllocNewPiece(src, piece);
01281 
01282       piece->text = (wchar_t*)XtMalloc(src->multi_src.piece_size * bytes);
01283       piece->used = Min(left, src->multi_src.piece_size);
01284       if (piece->used != 0)
01285           (void) wcsncpy(piece->text, ptr, piece->used);
01286 
01287       left -= piece->used;
01288       ptr += piece->used;
01289   } while (left > 0);
01290 
01291   if ( temp_mb_holder )
01292       XtFree( (char*) temp_mb_holder );
01293 }
01294 
01295 
01296 /*      Function Name: AllocNewPiece
01297  *      Description: Allocates a new piece of memory.
01298  *      Arguments: src - The MultiSrc Widget.
01299  *                 prev - the piece just before this one, or NULL.
01300  *      Returns: the allocated piece.
01301  */
01302 
01303 static MultiPiece *
01304 AllocNewPiece(src, prev)
01305     MultiSrcObject src;
01306     MultiPiece * prev;
01307 {
01308   MultiPiece * piece = XtNew(MultiPiece);
01309 
01310   if (prev == NULL) {
01311     src->multi_src.first_piece = piece;
01312     piece->next = NULL;
01313   }
01314   else {
01315     if (prev->next != NULL)
01316       (prev->next)->prev = piece;
01317     piece->next = prev->next;
01318     prev->next = piece;
01319   }
01320   
01321   piece->prev = prev;
01322 
01323   return(piece);
01324 }
01325 
01326 /*      Function Name: FreeAllPieces
01327  *      Description: Frees all the pieces
01328  *      Arguments: src - The MultiSrc Widget.
01329  *      Returns: none.
01330  */
01331 
01332 static void 
01333 FreeAllPieces(src)
01334     MultiSrcObject src;
01335 {
01336   MultiPiece * next, * first = src->multi_src.first_piece;
01337 
01338   if (first->prev != NULL)
01339     printf("Xaw MultiSrc Object: possible memory leak in FreeAllPieces().\n");
01340 
01341   for ( ; first != NULL ; first = next ) {
01342     next = first->next;
01343     RemovePiece(src, first);
01344   }
01345 }
01346   
01347 /*      Function Name: RemovePiece
01348  *      Description: Removes a piece from the list.
01349  *      Arguments: 
01350  *                 piece - the piece to remove.
01351  *      Returns: none.
01352  */
01353 
01354 static void
01355 RemovePiece(src, piece)
01356     MultiSrcObject src;
01357     MultiPiece* piece;
01358 {
01359   if (piece->prev == NULL)
01360     src->multi_src.first_piece = piece->next;
01361   else
01362     (piece->prev)->next = piece->next;
01363 
01364   if (piece->next != NULL)
01365     (piece->next)->prev = piece->prev;
01366 
01367   if (!src->multi_src.use_string_in_place)
01368     XtFree((char *)piece->text);
01369 
01370   XtFree((char *)piece);
01371 }
01372 
01373 /*      Function Name: FindPiece
01374  *      Description: Finds the piece containing the position indicated.
01375  *      Arguments: src - The MultiSrc Widget.
01376  *                 position - the position that we are searching for.
01377  * RETURNED        first - the position of the first character in this piece.
01378  *      Returns: piece - the piece that contains this position.
01379  */
01380 
01381 static MultiPiece *
01382 FindPiece(src, position, first)
01383     MultiSrcObject src;
01384     XawTextPosition position, *first;
01385 {
01386   MultiPiece * old_piece = NULL, * piece = src->multi_src.first_piece;
01387   XawTextPosition temp;
01388 
01389   for ( temp = 0 ; piece != NULL ; temp += piece->used, piece = piece->next ) {
01390     *first = temp;
01391     old_piece = piece;
01392 
01393     if ((temp + piece->used) > position) 
01394       return(piece);
01395   }
01396   return(old_piece);      /* if we run off the end the return the last piece */
01397 }
01398     
01399 /*      Function Name: BreakPiece
01400  *      Description: Breaks a full piece into two new pieces.
01401  *      Arguments: src - The MultiSrc Widget.
01402  *                 piece - the piece to break.
01403  *      Returns: none.
01404  */
01405 
01406 #define HALF_PIECE (src->multi_src.piece_size/2)
01407 
01408 static void
01409 BreakPiece(src, piece)
01410     MultiSrcObject src;
01411     MultiPiece* piece;
01412 {
01413   MultiPiece * new = AllocNewPiece(src, piece);
01414   
01415   new->text = (wchar_t*)XtMalloc(src->multi_src.piece_size * sizeof(wchar_t));
01416   (void) wcsncpy(new->text, piece->text + HALF_PIECE,
01417           src->multi_src.piece_size - HALF_PIECE);
01418   piece->used = HALF_PIECE;
01419   new->used = src->multi_src.piece_size - HALF_PIECE; 
01420 }
01421 
01422 /* Convert string "XawAsciiString" and "XawAsciiFile" to quarks. */
01423 
01424 /* ARGSUSED */
01425 static void
01426 CvtStringToMultiType(args, num_args, fromVal, toVal)
01427     XrmValuePtr args;           /* unused */
01428     Cardinal*   num_args;       /* unused */
01429     XrmValuePtr fromVal;
01430     XrmValuePtr toVal;
01431 {
01432   static XawAsciiType type;
01433   static XrmQuark  XtQEstring = NULLQUARK;
01434   static XrmQuark  XtQEfile;
01435   XrmQuark q;
01436   char lowerName[40];
01437 
01438   if (XtQEstring == NULLQUARK) {
01439     XtQEstring = XrmPermStringToQuark(XtEstring);
01440     XtQEfile   = XrmPermStringToQuark(XtEfile);
01441   }
01442 
01443   if (strlen ((char*) fromVal->addr) < sizeof lowerName) {
01444     XmuCopyISOLatin1Lowered(lowerName, (char *) fromVal->addr);
01445     q = XrmStringToQuark(lowerName);
01446 
01447     if (q == XtQEstring)     type = XawAsciiString;
01448     else if (q == XtQEfile)  type = XawAsciiFile;
01449     else {
01450       toVal->size = 0;
01451       toVal->addr = NULL;
01452       return;
01453     }
01454     toVal->size = sizeof type;
01455     toVal->addr = (XPointer) &type;
01456     return;
01457   }
01458   toVal->size = 0;
01459   toVal->addr = NULL;
01460 }

Generated on Sun Mar 4 15:03:55 2007 for Scilab [trunk] by  doxygen 1.5.1