home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xaw / AsciiSrc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-25  |  34.9 KB  |  1,337 lines

  1. /* $XConsortium: AsciiSrc.c,v 1.55 91/07/25 18:09:27 rws Exp $ */
  2.  
  3. /*
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Chris Peterson, MIT X Consortium.
  24.  *
  25.  * Much code taken from X11R3 String and Disk Sources.
  26.  */
  27.  
  28. /*
  29.  * AsciiSrc.c - AsciiSrc object. (For use with the text widget).
  30.  *
  31.  */
  32.  
  33. #include <X11/IntrinsicP.h>
  34. #include <stdio.h>
  35. #include <ctype.h>
  36. #include <errno.h>
  37. #include <X11/StringDefs.h>
  38. #include <X11/Xos.h>
  39. #include <X11/Xfuncs.h>
  40. #include <X11/Xaw/XawInit.h>
  41. #include <X11/Xaw/AsciiSrcP.h>
  42. #include <X11/Xmu/Misc.h>
  43. #include <X11/Xmu/CharSet.h>
  44.  
  45. #if (defined(ASCII_STRING) || defined(ASCII_DISK))
  46. #  include <X11/Xaw/AsciiText.h> /* for Widget Classes. */
  47. #endif
  48.  
  49.  
  50. /****************************************************************
  51.  *
  52.  * Full class record constant
  53.  *
  54.  ****************************************************************/
  55.  
  56. /* Private Data */
  57.  
  58. static int magic_value = MAGIC_VALUE;
  59.  
  60. #define offset(field) XtOffsetOf(AsciiSrcRec, ascii_src.field)
  61.  
  62. static XtResource resources[] = {
  63.     {XtNstring, XtCString, XtRString, sizeof (char *),
  64.        offset(string), XtRString, NULL},
  65.     {XtNtype, XtCType, XtRAsciiType, sizeof (XawAsciiType),
  66.        offset(type), XtRImmediate, (XtPointer)XawAsciiString},
  67.     {XtNdataCompression, XtCDataCompression, XtRBoolean, sizeof (Boolean),
  68.        offset(data_compression), XtRImmediate, (XtPointer) TRUE},
  69.     {XtNpieceSize, XtCPieceSize, XtRInt, sizeof (XawTextPosition),
  70.        offset(piece_size), XtRImmediate, (XtPointer) BUFSIZ},
  71.     {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), 
  72.        offset(callback), XtRCallback, (XtPointer)NULL},
  73.     {XtNuseStringInPlace, XtCUseStringInPlace, XtRBoolean, sizeof (Boolean),
  74.        offset(use_string_in_place), XtRImmediate, (XtPointer) FALSE},
  75.     {XtNlength, XtCLength, XtRInt, sizeof (int),
  76.        offset(ascii_length), XtRInt, (XtPointer) &magic_value},
  77.  
  78. #ifdef ASCII_DISK
  79.     {XtNfile, XtCFile, XtRString, sizeof (String),
  80.        offset(filename), XtRString, NULL},
  81. #endif /* ASCII_DISK */
  82. };
  83. #undef offset
  84.  
  85. static XawTextPosition Scan(), Search(), ReadText();
  86. static int ReplaceText();
  87. static Piece * FindPiece(), * AllocNewPiece();
  88. static FILE * InitStringOrFile();
  89. static void FreeAllPieces(), RemovePiece(), BreakPiece(), LoadPieces();
  90. static void RemoveOldStringOrFile(),  CvtStringToAsciiType();
  91. static void ClassInitialize(), Initialize(), Destroy(), GetValuesHook();
  92. static String MyStrncpy(), StorePiecesInString();
  93. static Boolean SetValues(), WriteToFile();
  94. extern int errno, sys_nerr;
  95. extern char* sys_errlist[];
  96.  
  97. #define superclass        (&textSrcClassRec)
  98. AsciiSrcClassRec asciiSrcClassRec = {
  99.   {
  100. /* core_class fields */    
  101.     /* superclass          */    (WidgetClass) superclass,
  102.     /* class_name          */    "AsciiSrc",
  103.     /* widget_size          */    sizeof(AsciiSrcRec),
  104.     /* class_initialize       */    ClassInitialize,
  105.     /* class_part_initialize    */    NULL,
  106.     /* class_inited           */    FALSE,
  107.     /* initialize          */    Initialize,
  108.     /* initialize_hook        */    NULL,
  109.     /* realize              */    NULL,
  110.     /* actions              */    NULL,
  111.     /* num_actions          */    0,
  112.     /* resources          */    resources,
  113.     /* num_resources          */    XtNumber(resources),
  114.     /* xrm_class          */    NULLQUARK,
  115.     /* compress_motion          */    FALSE,
  116.     /* compress_exposure      */    FALSE,
  117.     /* compress_enterleave    */    FALSE,
  118.     /* visible_interest          */    FALSE,
  119.     /* destroy              */    Destroy,
  120.     /* resize              */    NULL,
  121.     /* expose              */    NULL,
  122.     /* set_values          */    SetValues,
  123.     /* set_values_hook        */    NULL,
  124.     /* set_values_almost    */    NULL,
  125.     /* get_values_hook        */    GetValuesHook,
  126.     /* accept_focus         */    NULL,
  127.     /* version            */    XtVersion,
  128.     /* callback_private       */    NULL,
  129.     /* tm_table               */    NULL,
  130.     /* query_geometry        */    NULL,
  131.     /* display_accelerator    */    NULL,
  132.     /* extension        */    NULL
  133.   },
  134. /* textSrc_class fields */
  135.   {
  136.     /* Read                     */      ReadText,
  137.     /* Replace                  */      ReplaceText,
  138.     /* Scan                     */      Scan,
  139.     /* Search                   */      Search,
  140.     /* SetSelection             */      XtInheritSetSelection,
  141.     /* ConvertSelection         */      XtInheritConvertSelection
  142.   },
  143. /* asciiSrc_class fields */
  144.   {
  145.     /* Keep the compiler happy */       NULL
  146.   }
  147. };
  148.  
  149. WidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec;
  150.  
  151. /************************************************************
  152.  *
  153.  * Semi-Public Interfaces.
  154.  *
  155.  ************************************************************/
  156.  
  157. /*      Function Name: ClassInitialize
  158.  *      Description: Class Initialize routine, called only once.
  159.  *      Arguments: none.
  160.  *      Returns: none.
  161.  */
  162.  
  163. static void
  164. ClassInitialize()
  165. {
  166.   XawInitializeWidgetSet();
  167.   XtAddConverter( XtRString, XtRAsciiType, CvtStringToAsciiType,
  168.          NULL, (Cardinal) 0);
  169. }
  170.  
  171. /*      Function Name: Initialize
  172.  *      Description: Initializes the simple menu widget
  173.  *      Arguments: request - the widget requested by the argument list.
  174.  *                 new     - the new widget with both resource and non
  175.  *                           resource values.
  176.  *      Returns: none.
  177.  */
  178.  
  179. /* ARGSUSED */
  180. static void
  181. Initialize(request, new)
  182. Widget request, new;
  183. {
  184.   AsciiSrcObject src = (AsciiSrcObject) new;
  185.   FILE * file;
  186.  
  187. /*
  188.  * Set correct flags (override resources) depending upon widget class.
  189.  */
  190.  
  191. #ifdef ASCII_DISK
  192.   if (XtIsSubclass(XtParent(new), asciiDiskWidgetClass)) {
  193.     src->ascii_src.type = XawAsciiFile;
  194.     src->ascii_src.string = src->ascii_src.filename;
  195.   }
  196. #endif
  197.  
  198. #ifdef ASCII_STRING
  199.   if (XtIsSubclass(XtParent(new), asciiStringWidgetClass)) {
  200.     src->ascii_src.use_string_in_place = TRUE;
  201.     src->ascii_src.type = XawAsciiString;
  202.   }
  203. #endif
  204.  
  205.   src->ascii_src.changes = FALSE;
  206.   src->ascii_src.allocated_string = FALSE;
  207.  
  208.   file = InitStringOrFile(src, src->ascii_src.type == XawAsciiFile);
  209.   LoadPieces(src, file, NULL);
  210.  
  211.   if (file != NULL) fclose(file);
  212. }
  213.  
  214. /*    Function Name: ReadText
  215.  *    Description: This function reads the source.
  216.  *    Arguments: w - the AsciiSource widget.
  217.  *                 pos - position of the text to retreive.
  218.  * RETURNED        text - text block that will contain returned text.
  219.  *                 length - maximum number of characters to read.
  220.  *    Returns: The number of characters read into the buffer.
  221.  */
  222.  
  223. static XawTextPosition
  224. ReadText(w, pos, text, length)
  225. Widget w;
  226. XawTextPosition pos;
  227. XawTextBlock *text;    
  228. int length;        
  229. {
  230.   AsciiSrcObject src = (AsciiSrcObject) w;
  231.   XawTextPosition count, start;
  232.   Piece * piece = FindPiece(src, pos, &start);
  233.     
  234.   text->firstPos = pos;
  235.   text->ptr = piece->text + (pos - start);
  236.   count = piece->used - (pos - start);
  237.   text->length = (length > count) ? count : length;
  238.   return(pos + text->length);
  239. }
  240.  
  241. /*    Function Name: ReplaceText.
  242.  *    Description: Replaces a block of text with new text.
  243.  *    Arguments: w - the AsciiSource widget.
  244.  *                 startPos, endPos - ends of text that will be removed.
  245.  *                 text - new text to be inserted into buffer at startPos.
  246.  *    Returns: XawEditError or XawEditDone.
  247.  */
  248.  
  249. /*ARGSUSED*/
  250. static int 
  251. ReplaceText (w, startPos, endPos, text)
  252. Widget w;
  253. XawTextPosition startPos, endPos;
  254. XawTextBlock *text;
  255. {
  256.   AsciiSrcObject src = (AsciiSrcObject) w;
  257.   Piece *start_piece, *end_piece, *temp_piece;
  258.   XawTextPosition start_first, end_first;
  259.   int length, firstPos;
  260.  
  261. /*
  262.  * Editing a read only source is not allowed.
  263.  */
  264.  
  265.   if (src->text_src.edit_mode == XawtextRead) 
  266.     return(XawEditError);
  267.  
  268.   start_piece = FindPiece(src, startPos, &start_first);
  269.   end_piece = FindPiece(src, endPos, &end_first);
  270.  
  271.   src->ascii_src.changes = TRUE; /* We have changed the buffer. */
  272.  
  273. /* 
  274.  * Remove Old Stuff. 
  275.  */
  276.  
  277.   if (start_piece != end_piece) {
  278.     temp_piece = start_piece->next;
  279.  
  280. /*
  281.  * If empty and not the only piece then remove it. 
  282.  */
  283.  
  284.     if ( ((start_piece->used = startPos - start_first) == 0) &&
  285.      !((start_piece->next == NULL) && (start_piece->prev == NULL)) )
  286.       RemovePiece(src, start_piece);
  287.  
  288.     while (temp_piece != end_piece) {
  289.       temp_piece = temp_piece->next;
  290.       RemovePiece(src, temp_piece->prev);
  291.     }
  292.     end_piece->used -= endPos - end_first;
  293.     if (end_piece->used != 0)
  294.       MyStrncpy(end_piece->text, (end_piece->text + endPos - end_first),
  295.         (int) end_piece->used);
  296.   }
  297.   else {            /* We are fully in one piece. */
  298.     if ( (start_piece->used -= endPos - startPos) == 0) {
  299.       if ( !((start_piece->next == NULL) && (start_piece->prev == NULL)) )
  300.     RemovePiece(src, start_piece);
  301.     }
  302.     else {
  303.       MyStrncpy(start_piece->text + (startPos - start_first),
  304.         start_piece->text + (endPos - start_first),
  305.         (int) (start_piece->used - (startPos - start_first)) );
  306.       if ( src->ascii_src.use_string_in_place && 
  307.        ((src->ascii_src.length - (endPos - startPos)) < 
  308.         (src->ascii_src.piece_size - 1)) ) 
  309.     start_piece->text[src->ascii_src.length - (endPos - startPos)] = '\0';
  310.     }
  311.   }
  312.  
  313.   src->ascii_src.length += -(endPos - startPos) + text->length;
  314.  
  315.   if ( text->length != 0) {
  316.  
  317.     /* 
  318.      * Put in the New Stuff.
  319.      */
  320.     
  321.     start_piece = FindPiece(src, startPos, &start_first);
  322.     
  323.     length = text->length;
  324.     firstPos = text->firstPos;
  325.     
  326.     while (length > 0) {
  327.       char * ptr;
  328.       int fill;
  329.       
  330.       if (src->ascii_src.use_string_in_place) {
  331.     if (start_piece->used == (src->ascii_src.piece_size - 1)) {
  332.       /*
  333.        * If we are in ascii string emulation mode. Then the
  334.        *  string is not allowed to grow.
  335.        */
  336.       start_piece->used = src->ascii_src.length = 
  337.                                              src->ascii_src.piece_size - 1;
  338.       start_piece->text[src->ascii_src.length] = '\0';
  339.       return(XawEditError);
  340.     }
  341.       }
  342.  
  343.  
  344.       if (start_piece->used == src->ascii_src.piece_size) {
  345.     BreakPiece(src, start_piece);
  346.     start_piece = FindPiece(src, startPos, &start_first);
  347.       }
  348.  
  349.       fill = Min((int)(src->ascii_src.piece_size - start_piece->used), length);
  350.       
  351.       ptr = start_piece->text + (startPos - start_first);
  352.       MyStrncpy(ptr + fill, ptr, 
  353.         (int) start_piece->used - (startPos - start_first));
  354.       strncpy(ptr, text->ptr + firstPos, fill);
  355.       
  356.       startPos += fill;
  357.       firstPos += fill;
  358.       start_piece->used += fill;
  359.       length -= fill;
  360.     }
  361.   }
  362.  
  363.   if (src->ascii_src.use_string_in_place)
  364.     start_piece->text[start_piece->used] = '\0';
  365.  
  366.   XtCallCallbacks(w, XtNcallback, NULL); /* Call callbacks, we have changed 
  367.                         the buffer. */
  368.  
  369.   return(XawEditDone);
  370. }
  371.  
  372. /*    Function Name: Scan
  373.  *    Description: Scans the text source for the number and type
  374.  *                   of item specified.
  375.  *    Arguments: w - the AsciiSource widget.
  376.  *                 position - the position to start scanning.
  377.  *                 type - type of thing to scan for.
  378.  *                 dir - direction to scan.
  379.  *                 count - which occurance if this thing to search for.
  380.  *                 include - whether or not to include the character found in
  381.  *                           the position that is returned. 
  382.  *    Returns: the position of the item found.
  383.  *
  384.  * Note: While there are only 'n' characters in the file there are n+1 
  385.  *       possible cursor positions (one before the first character and
  386.  *       one after the last character.
  387.  */
  388.  
  389. static 
  390. XawTextPosition 
  391. Scan (w, position, type, dir, count, include)
  392. Widget                w;
  393. XawTextPosition       position;
  394. XawTextScanType       type;
  395. XawTextScanDirection  dir;
  396. int               count;
  397. Boolean                  include;
  398. {
  399.   AsciiSrcObject src = (AsciiSrcObject) w;
  400.   register int inc;
  401.   Piece * piece;
  402.   XawTextPosition first, first_eol_position;
  403.   register char * ptr;
  404.  
  405.   if (type == XawstAll) {    /* Optomize this common case. */
  406.     if (dir == XawsdRight)
  407.       return(src->ascii_src.length);
  408.     return(0);            /* else. */
  409.   }
  410.  
  411.   if (position > src->ascii_src.length)
  412.     position = src->ascii_src.length;
  413.  
  414.   if ( dir == XawsdRight ) {
  415.     if (position == src->ascii_src.length)
  416. /*
  417.  * Scanning right from src->ascii_src.length???
  418.  */
  419.       return(src->ascii_src.length);
  420.     inc = 1;
  421.   }
  422.   else {
  423.     if (position == 0)
  424.       return(0);        /* Scanning left from 0??? */
  425.     inc = -1;
  426.     position--;
  427.   }
  428.  
  429.   piece = FindPiece(src, position, &first);
  430.  
  431. /*
  432.  * If the buffer is empty then return 0. 
  433.  */
  434.  
  435.   if ( piece->used == 0 ) return(0); 
  436.  
  437.   ptr = (position - first) + piece->text;
  438.  
  439.   switch (type) {
  440.   case XawstEOL: 
  441.   case XawstParagraph: 
  442.   case XawstWhiteSpace: 
  443.     for ( ; count > 0 ; count-- ) {
  444.       Boolean non_space = FALSE, first_eol = TRUE;
  445.       while (TRUE) {
  446.     register unsigned char c = *ptr;
  447.  
  448.     ptr += inc;
  449.     position += inc;
  450.     
  451.     if (type == XawstWhiteSpace) {
  452.       if (isspace(c)) {
  453.         if (non_space) 
  454.           break;
  455.       }
  456.       else
  457.         non_space = TRUE;
  458.     }
  459.     else if (type == XawstEOL) {
  460.       if (c == '\n') break;
  461.     }
  462.     else { /* XawstParagraph */
  463.       if (first_eol) {
  464.         if (c == '\n') {
  465.           first_eol_position = position;
  466.           first_eol = FALSE;
  467.         }
  468.       }
  469.       else
  470.         if ( c == '\n') 
  471.           break;
  472.         else if ( !isspace(c) )
  473.           first_eol = TRUE;
  474.     }
  475.           
  476.  
  477.     if ( ptr < piece->text ) {
  478.       piece = piece->prev;
  479.       if (piece == NULL)    /* Begining of text. */
  480.         return(0);
  481.       ptr = piece->text + piece->used - 1;
  482.     }
  483.     else if ( ptr >= (piece->text + piece->used) ) {
  484.       piece = piece->next;
  485.       if (piece == NULL)    /* End of text. */
  486.         return(src->ascii_src.length);
  487.       ptr = piece->text;
  488.     }
  489.       }
  490.     }
  491.     if (!include) {
  492.       if ( type == XawstParagraph)
  493.     position = first_eol_position;
  494.       position -= inc;
  495.     }
  496.     break;
  497.   case XawstPositions: 
  498.     position += count * inc;
  499.     break;
  500. /*  case XawstAll:        ---- handled in special code above */
  501.   }
  502.  
  503.   if ( dir == XawsdLeft )
  504.     position++;
  505.  
  506.   if (position >= src->ascii_src.length)
  507.     return(src->ascii_src.length);
  508.   if (position < 0)
  509.     return(0);
  510.  
  511.   return(position);
  512. }
  513.  
  514. /*    Function Name: Search
  515.  *    Description: Searchs the text source for the text block passed
  516.  *    Arguments: w - the AsciiSource Widget.
  517.  *                 position - the position to start scanning.
  518.  *                 dir - direction to scan.
  519.  *                 text - the text block to search for.
  520.  *    Returns: the position of the item found.
  521.  */
  522.  
  523. static XawTextPosition 
  524. Search(w, position, dir, text)
  525. Widget                w;
  526. XawTextPosition       position;
  527. XawTextScanDirection  dir;
  528. XawTextBlock *        text;
  529. {
  530.   AsciiSrcObject src = (AsciiSrcObject) w;
  531.   register int inc, count = 0;
  532.   register char * ptr;
  533.   Piece * piece;
  534.   char * buf;
  535.   XawTextPosition first;
  536.  
  537.   if ( dir == XawsdRight )
  538.     inc = 1;
  539.   else {
  540.     inc = -1;
  541.     if (position == 0)
  542.       return(XawTextSearchError);    /* scanning left from 0??? */
  543.     position--;
  544.   }
  545.  
  546.   buf = XtMalloc(sizeof(unsigned char) * text->length);
  547.   strncpy(buf, (text->ptr + text->firstPos), text->length);
  548.   piece = FindPiece(src, position, &first);
  549.   ptr = (position - first) + piece->text;
  550.  
  551.   while (TRUE) {
  552.     if (*ptr == ((dir == XawsdRight) ? *(buf + count) 
  553.                              : *(buf + text->length - count - 1)) ) {
  554.       if (count == (text->length - 1))
  555.     break;
  556.       else
  557.     count++;
  558.     }
  559.     else {
  560.       if (count != 0) {
  561.     position -=inc * count;
  562.     ptr -= inc * count;
  563.       }
  564.       count = 0;
  565.     }
  566.  
  567.     ptr += inc;
  568.     position += inc;
  569.     
  570.     while ( ptr < piece->text ) {
  571.       piece = piece->prev;
  572.       if (piece == NULL) {    /* Begining of text. */
  573.     XtFree(buf);
  574.     return(XawTextSearchError);
  575.       }
  576.       ptr = piece->text + piece->used - 1;
  577.     }
  578.    
  579.     while ( ptr >= (piece->text + piece->used) ) {
  580.       piece = piece->next;
  581.       if (piece == NULL) {    /* End of text. */
  582.     XtFree(buf);
  583.     return(XawTextSearchError);
  584.       }
  585.       ptr = piece->text;
  586.     }
  587.   }
  588.  
  589.   XtFree(buf);
  590.   if (dir == XawsdLeft)
  591.     return(position);
  592.   return(position - (text->length - 1));
  593. }
  594.  
  595. /*    Function Name: SetValues
  596.  *    Description: Sets the values for the AsciiSource.
  597.  *    Arguments: current - current state of the widget.
  598.  *                 request - what was requested.
  599.  *                 new - what the widget will become.
  600.  *    Returns: True if redisplay is needed.
  601.  */
  602.  
  603. /* ARGSUSED */
  604. static Boolean
  605. SetValues(current, request, new, args, num_args)
  606. Widget current, request, new;
  607. ArgList args;
  608. Cardinal * num_args;
  609. {
  610.   AsciiSrcObject src =      (AsciiSrcObject) new;
  611.   AsciiSrcObject old_src = (AsciiSrcObject) current;
  612.   Boolean total_reset = FALSE, string_set = FALSE;
  613.   FILE * file;
  614.   int i;
  615.  
  616.   if ( old_src->ascii_src.use_string_in_place != 
  617.        src->ascii_src.use_string_in_place ) {
  618.       XtAppWarning( XtWidgetToApplicationContext(new),
  619.        "AsciiSrc: The XtNuseStringInPlace resource may not be changed.");
  620.        src->ascii_src.use_string_in_place = 
  621.        old_src->ascii_src.use_string_in_place;
  622.   }
  623.  
  624.   for (i = 0; i < *num_args ; i++ ) 
  625.       if (streq(args[i].name, XtNstring)) {
  626.       string_set = TRUE;
  627.       break;
  628.       }
  629.   
  630.   if ( string_set || (old_src->ascii_src.type != src->ascii_src.type) ) {
  631.     RemoveOldStringOrFile(old_src, string_set); /* remove old info. */
  632.     file = InitStringOrFile(src, string_set);    /* Init new info. */
  633.     LoadPieces(src, file, NULL);    /* load new info into internal buffers. */
  634.     if (file != NULL) fclose(file);
  635.     XawTextSetSource( XtParent(new), new, 0);   /* Tell text widget
  636.                            what happened. */
  637.     total_reset = TRUE;
  638.   }
  639.  
  640.   if ( old_src->ascii_src.ascii_length != src->ascii_src.ascii_length ) 
  641.       src->ascii_src.piece_size = src->ascii_src.ascii_length;
  642.  
  643.   if ( !total_reset && 
  644.       (old_src->ascii_src.piece_size != src->ascii_src.piece_size) ) {
  645.       String string = StorePiecesInString(old_src);
  646.       FreeAllPieces(old_src);
  647.       LoadPieces(src, NULL, string);
  648.       XtFree(string);
  649.   }
  650.  
  651.   return(FALSE);
  652. }
  653.  
  654. /*    Function Name: GetValuesHook
  655.  *    Description: This is a get values hook routine that sets the
  656.  *                   values specific to the ascii source.
  657.  *    Arguments: w - the AsciiSource Widget.
  658.  *                 args - the argument list.
  659.  *                 num_args - the number of args.
  660.  *    Returns: none.
  661.  */
  662.  
  663. static void
  664. GetValuesHook(w, args, num_args)
  665. Widget w;
  666. ArgList args;
  667. Cardinal * num_args;
  668. {
  669.   AsciiSrcObject src = (AsciiSrcObject) w;
  670.   register int i;
  671.  
  672.   if (src->ascii_src.type == XawAsciiString) {
  673.     for (i = 0; i < *num_args ; i++ ) 
  674.       if (streq(args[i].name, XtNstring)) {
  675.       if (src->ascii_src.use_string_in_place) {
  676.           *((char **) args[i].value) = src->ascii_src.first_piece->text;
  677.       }
  678.       else {
  679.           if (XawAsciiSave(w))    /* If save sucessful. */
  680.           *((char **) args[i].value) = src->ascii_src.string;
  681.       }
  682.     break;
  683.       }
  684.   }
  685. }    
  686.  
  687. /*    Function Name: Destroy
  688.  *    Description: Destroys an ascii source (frees all data)
  689.  *    Arguments: src - the Ascii source Widget to free.
  690.  *    Returns: none.
  691.  */
  692.  
  693. static void 
  694. Destroy (w)
  695. Widget w;
  696. {
  697.   RemoveOldStringOrFile((AsciiSrcObject) w, True);
  698. }
  699.  
  700. /************************************************************
  701.  *
  702.  * Public routines 
  703.  *
  704.  ************************************************************/
  705.  
  706. /*    Function Name: XawAsciiSourceFreeString
  707.  *    Description: Frees the string returned by a get values call
  708.  *                   on the string when the source is of type string.
  709.  *    Arguments: w - the AsciiSrc widget.
  710.  *    Returns: none.
  711.  */
  712.  
  713. void
  714. #if NeedFunctionPrototypes
  715. XawAsciiSourceFreeString(Widget w)
  716. #else
  717. XawAsciiSourceFreeString(w)
  718. Widget w;
  719. #endif
  720. {
  721.   AsciiSrcObject src = (AsciiSrcObject) w;
  722.  
  723.   if (src->ascii_src.allocated_string && src->ascii_src.type != XawAsciiFile) {
  724.     src->ascii_src.allocated_string = FALSE;
  725.     XtFree(src->ascii_src.string);
  726.     src->ascii_src.string = NULL;
  727.   }
  728. }
  729.  
  730. /*    Function Name: XawAsciiSave
  731.  *    Description: Saves all the pieces into a file or string as required.
  732.  *    Arguments: w - the asciiSrc Widget.
  733.  *    Returns: TRUE if the save was successful.
  734.  */
  735.  
  736. Boolean
  737. #if NeedFunctionPrototypes
  738. XawAsciiSave(Widget w)
  739. #else
  740. XawAsciiSave(w)
  741. Widget w;
  742. #endif
  743. {
  744.   AsciiSrcObject src = (AsciiSrcObject) w;
  745.  
  746. /*
  747.  * If using the string in place then there is no need to play games
  748.  * to get the internal info into a readable string.
  749.  */
  750.  
  751.   if (src->ascii_src.use_string_in_place) 
  752.     return(TRUE);
  753.  
  754.   if (src->ascii_src.type == XawAsciiFile) {
  755.     char * string;
  756.  
  757.     if (!src->ascii_src.changes)         /* No changes to save. */
  758.       return(TRUE);
  759.  
  760.     string = StorePiecesInString(src);
  761.  
  762.     if (WriteToFile(string, src->ascii_src.string) == FALSE) {
  763.       XtFree(string);
  764.       return(FALSE);
  765.     }
  766.     XtFree(string);
  767.   }
  768.   else {            /* This is a string widget. */
  769.     if (src->ascii_src.allocated_string == TRUE) 
  770.       XtFree(src->ascii_src.string);
  771.     else
  772.       src->ascii_src.allocated_string = TRUE;
  773.     
  774.     src->ascii_src.string = StorePiecesInString(src);
  775.   }
  776.   src->ascii_src.changes = FALSE;
  777.   return(TRUE);
  778. }
  779.  
  780. /*    Function Name: XawAsciiSaveAsFile
  781.  *    Description: Save the current buffer as a file.
  782.  *    Arguments: w - the AsciiSrc widget.
  783.  *                 name - name of the file to save this file into.
  784.  *    Returns: True if the save was sucessful.
  785.  */
  786.  
  787. Boolean
  788. #if NeedFunctionPrototypes
  789. XawAsciiSaveAsFile(Widget w, _Xconst char* name)
  790. #else
  791. XawAsciiSaveAsFile(w, name)
  792. Widget w;
  793. String name;
  794. #endif
  795. {
  796.   AsciiSrcObject src = (AsciiSrcObject) w;
  797.   String string;
  798.   Boolean ret;
  799.  
  800.   string = StorePiecesInString(src); 
  801.  
  802.   ret = WriteToFile(string, name);
  803.   XtFree(string);
  804.   return(ret);
  805. }
  806.  
  807. /*    Function Name: XawAsciiSourceChanged
  808.  *    Description: Returns true if the source has changed since last saved.
  809.  *    Arguments: w - the ascii source widget.
  810.  *    Returns: a Boolean (see description).
  811.  */
  812.  
  813. Boolean 
  814. #if NeedFunctionPrototypes
  815. XawAsciiSourceChanged(Widget w)
  816. #else
  817. XawAsciiSourceChanged(w)
  818. Widget w;
  819. #endif
  820. {
  821.   return( ((AsciiSrcObject) w)->ascii_src.changes );
  822. }
  823.   
  824. /************************************************************
  825.  *
  826.  * Private Functions.
  827.  *
  828.  ************************************************************/
  829.  
  830. static void
  831. RemoveOldStringOrFile(src, checkString) 
  832. AsciiSrcObject src;
  833. Boolean checkString;
  834. {
  835.   FreeAllPieces(src);
  836.  
  837.   if (checkString && src->ascii_src.allocated_string) {
  838.     XtFree(src->ascii_src.string);
  839.     src->ascii_src.allocated_string = False;
  840.     src->ascii_src.string = NULL;
  841.   }
  842. }
  843.  
  844. /*    Function Name: WriteToFile
  845.  *    Description: Write the string specified to the begining of the file
  846.  *                   specified.
  847.  *    Arguments: string - string to write.
  848.  *                 name - the name of the file
  849.  *    Returns: returns TRUE if sucessful, FALSE otherwise.
  850.  */
  851.  
  852. static Boolean
  853. WriteToFile(string, name)
  854. String string, name;
  855. {
  856.   int fd;
  857.   
  858.   if ( ((fd = creat(name, 0666)) == -1 ) ||
  859.        (write(fd, string, sizeof(unsigned char) * strlen(string)) == -1) )
  860.     return(FALSE);
  861.  
  862.   if ( close(fd) == -1 ) 
  863.     return(FALSE);
  864.  
  865.   return(TRUE);
  866. }
  867.  
  868. /*    Function Name: StorePiecesInString
  869.  *    Description: store the pieces in memory into a standard ascii string.
  870.  *    Arguments: data - the ascii pointer data.
  871.  *    Returns: none.
  872.  */
  873.  
  874. static String
  875. StorePiecesInString(src)
  876. AsciiSrcObject src;
  877. {
  878.   String string;
  879.   XawTextPosition first;
  880.   Piece * piece;
  881.  
  882.   string = XtMalloc(sizeof(unsigned char) * src->ascii_src.length + 1);
  883.   
  884.   for (first = 0, piece = src->ascii_src.first_piece ; piece != NULL; 
  885.        first += piece->used, piece = piece->next) 
  886.     strncpy(string + first, piece->text, piece->used);
  887.  
  888.   string[src->ascii_src.length] = '\0';    /* NULL terminate this sucker. */
  889.  
  890. /*
  891.  * This will refill all pieces to capacity. 
  892.  */
  893.  
  894.   if (src->ascii_src.data_compression) {    
  895.     FreeAllPieces(src);
  896.     LoadPieces(src, NULL, string);
  897.   }
  898.  
  899.   return(string);
  900. }
  901.  
  902. /*    Function Name: InitStringOrFile.
  903.  *    Description: Initializes the string or file.
  904.  *    Arguments: src - the AsciiSource.
  905.  *    Returns: none - May exit though.
  906.  */
  907.  
  908. static FILE *
  909. InitStringOrFile(src, newString)
  910. AsciiSrcObject src;
  911. Boolean newString;
  912. {
  913.     char * open_mode;
  914.     FILE * file;
  915.     char fileName[TMPSIZ];
  916.  
  917.     if (src->ascii_src.type == XawAsciiString) {
  918.  
  919.     if (src->ascii_src.string == NULL)
  920.         src->ascii_src.length = 0;
  921.  
  922.     else if (! src->ascii_src.use_string_in_place) {
  923.         src->ascii_src.string = XtNewString(src->ascii_src.string);
  924.         src->ascii_src.allocated_string = True;
  925.         src->ascii_src.length = strlen(src->ascii_src.string);
  926.     }
  927.  
  928.     if (src->ascii_src.use_string_in_place) {
  929.         src->ascii_src.length = strlen(src->ascii_src.string);
  930.         /* In case the length resource is incorrectly set */
  931.         if (src->ascii_src.length > src->ascii_src.ascii_length)
  932.         src->ascii_src.ascii_length = src->ascii_src.length;
  933.  
  934.         if (src->ascii_src.ascii_length == MAGIC_VALUE) 
  935.         src->ascii_src.piece_size = src->ascii_src.length;
  936.         else
  937.         src->ascii_src.piece_size = src->ascii_src.ascii_length + 1;
  938.     }
  939.         
  940.     return(NULL);
  941.     }
  942.  
  943. /*
  944.  * type is XawAsciiFile.
  945.  */
  946.     
  947.     src->ascii_src.is_tempfile = FALSE;
  948.  
  949.     switch (src->text_src.edit_mode) {
  950.     case XawtextRead:
  951.     if (src->ascii_src.string == NULL)
  952.         XtErrorMsg("NoFile", "asciiSourceCreate", "XawError",
  953.              "Creating a read only disk widget and no file specified.",
  954.                NULL, 0);
  955.     open_mode = "r";
  956.     break;
  957.     case XawtextAppend:
  958.     case XawtextEdit:
  959.     if (src->ascii_src.string == NULL) {
  960.         src->ascii_src.string = fileName;
  961.         (void) tmpnam(src->ascii_src.string);
  962.         src->ascii_src.is_tempfile = TRUE;
  963.         open_mode = "w";
  964.     } else
  965.         open_mode = "r+";
  966.     break;
  967.     default:
  968.     XtErrorMsg("badMode", "asciiSourceCreate", "XawError",
  969.         "Bad editMode for ascii source; must be Read, Append or Edit.",
  970.            NULL, NULL);
  971.     }
  972.  
  973.     /* Allocate new memory for the temp filename, because it is held in
  974.      * a stack variable, not static memory.  This widget does not need
  975.      * to keep the private state field is_tempfile -- it is only accessed
  976.      * in this routine, and its former setting is unused.
  977.      */
  978.     if (newString || src->ascii_src.is_tempfile) {
  979.     src->ascii_src.string = XtNewString(src->ascii_src.string);
  980.     src->ascii_src.allocated_string = TRUE;
  981.     }
  982.     
  983.     if (!src->ascii_src.is_tempfile) {
  984.     if ((file = fopen(src->ascii_src.string, open_mode)) != 0) {
  985.         (void) fseek(file, 0L, 2);
  986.         src->ascii_src.length = ftell(file);
  987.         return file;
  988.     } else {
  989.         String params[2];
  990.         Cardinal num_params = 2;
  991.         char msg[11];
  992.         
  993.         params[0] = src->ascii_src.string;
  994.         if (errno <= sys_nerr)
  995.         params[1] = sys_errlist[errno];
  996.         else {
  997.         sprintf(msg, "errno=%.4d", errno);
  998.         params[1] = msg;
  999.         }
  1000.         XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src),
  1001.                 "openError", "asciiSourceCreate", "XawWarning",
  1002.                 "Cannot open file %s; %s", params, &num_params);
  1003.     }
  1004.     } 
  1005.     src->ascii_src.length = 0;
  1006.     return((FILE *)NULL);
  1007. }
  1008.  
  1009. static void
  1010. LoadPieces(src, file, string)
  1011. AsciiSrcObject src;
  1012. FILE * file;
  1013. char * string;
  1014. {
  1015.   char *local_str, *ptr;
  1016.   register Piece * piece = NULL;
  1017.   XawTextPosition left;
  1018.  
  1019.   if (string == NULL) {
  1020.     if (src->ascii_src.type == XawAsciiFile) {
  1021.       local_str = XtMalloc((src->ascii_src.length + 1) *sizeof(unsigned char));
  1022.       if (src->ascii_src.length != 0) {
  1023.     fseek(file, 0L, 0);
  1024.     if ( fread(local_str, sizeof(unsigned char),
  1025.            src->ascii_src.length, file) != src->ascii_src.length ) 
  1026.       XtErrorMsg("readError", "asciiSourceCreate", "XawError",
  1027.              "fread returned error.", NULL, NULL);
  1028.       }
  1029.       local_str[src->ascii_src.length] = '\0';
  1030.     }
  1031.     else
  1032.       local_str = src->ascii_src.string;
  1033.   }
  1034.   else
  1035.     local_str = string;
  1036.  
  1037. /*
  1038.  * If we are using teh string in place then set the other fields as follows:
  1039.  *
  1040.  * piece_size = length;
  1041.  * piece->used = src->ascii_src.length;
  1042.  */
  1043.   
  1044.   if (src->ascii_src.use_string_in_place) {
  1045.     piece = AllocNewPiece(src, piece);
  1046.     piece->used = Min(src->ascii_src.length, src->ascii_src.piece_size);
  1047.     piece->text = src->ascii_src.string;
  1048.     return;
  1049.   }
  1050.  
  1051.   ptr = local_str;
  1052.   left = src->ascii_src.length;
  1053.  
  1054.   do {
  1055.     piece = AllocNewPiece(src, piece);
  1056.  
  1057.     piece->text = XtMalloc(src->ascii_src.piece_size * sizeof(unsigned char));
  1058.     piece->used = Min(left, src->ascii_src.piece_size);
  1059.     if (piece->used != 0)
  1060.       strncpy(piece->text, ptr, piece->used);
  1061.  
  1062.     left -= piece->used;
  1063.     ptr += piece->used;
  1064.   } while (left > 0);
  1065.  
  1066.   if ( (src->ascii_src.type == XawAsciiFile) && (string == NULL) )
  1067.     XtFree(local_str);
  1068. }
  1069.  
  1070. /*    Function Name: AllocNewPiece
  1071.  *    Description: Allocates a new piece of memory.
  1072.  *    Arguments: src - The AsciiSrc Widget.
  1073.  *                 prev - the piece just before this one, or NULL.
  1074.  *    Returns: the allocated piece.
  1075.  */
  1076.  
  1077. static Piece *
  1078. AllocNewPiece(src, prev)
  1079. AsciiSrcObject src;
  1080. Piece * prev;
  1081. {
  1082.   Piece * piece = XtNew(Piece);
  1083.  
  1084.   if (prev == NULL) {
  1085.     src->ascii_src.first_piece = piece;
  1086.     piece->next = NULL;
  1087.   }
  1088.   else {
  1089.     if (prev->next != NULL)
  1090.       (prev->next)->prev = piece;
  1091.     piece->next = prev->next;
  1092.     prev->next = piece;
  1093.   }
  1094.   
  1095.   piece->prev = prev;
  1096.  
  1097.   return(piece);
  1098. }
  1099.  
  1100. /*    Function Name: FreeAllPieces
  1101.  *    Description: Frees all the pieces
  1102.  *    Arguments: src - The AsciiSrc Widget.
  1103.  *    Returns: none.
  1104.  */
  1105.  
  1106. static void 
  1107. FreeAllPieces(src)
  1108. AsciiSrcObject src;
  1109. {
  1110.   Piece * next, * first = src->ascii_src.first_piece;
  1111.  
  1112.   if (first->prev != NULL)
  1113.     printf("Programmer Botch in FreeAllPieces, there may be a memory leak.\n");
  1114.  
  1115.   for ( ; first != NULL ; first = next ) {
  1116.     next = first->next;
  1117.     RemovePiece(src, first);
  1118.   }
  1119. }
  1120.   
  1121. /*    Function Name: RemovePiece
  1122.  *    Description: Removes a piece from the list.
  1123.  *    Arguments: 
  1124.  *                 piece - the piece to remove.
  1125.  *    Returns: none.
  1126.  */
  1127.  
  1128. static void
  1129. RemovePiece(src, piece)
  1130. AsciiSrcObject src;
  1131. Piece * piece;
  1132. {
  1133.   if (piece->prev == NULL)
  1134.     src->ascii_src.first_piece = piece->next;
  1135.   else
  1136.     (piece->prev)->next = piece->next;
  1137.  
  1138.   if (piece->next != NULL)
  1139.     (piece->next)->prev = piece->prev;
  1140.  
  1141.   if (!src->ascii_src.use_string_in_place)
  1142.     XtFree(piece->text);
  1143.  
  1144.   XtFree((char *)piece);
  1145. }
  1146.  
  1147. /*    Function Name: FindPiece
  1148.  *    Description: Finds the piece containing the position indicated.
  1149.  *    Arguments: src - The AsciiSrc Widget.
  1150.  *                 position - the position that we are searching for.
  1151.  * RETURNED        first - the position of the first character in this piece.
  1152.  *    Returns: piece - the piece that contains this position.
  1153.  */
  1154.  
  1155. static Piece *
  1156. FindPiece(src, position, first)
  1157. AsciiSrcObject src;
  1158. XawTextPosition position, *first;
  1159. {
  1160.   Piece * old_piece, * piece = src->ascii_src.first_piece;
  1161.   XawTextPosition temp;
  1162.  
  1163.   for ( temp = 0 ; piece != NULL ; temp += piece->used, piece = piece->next ) {
  1164.     *first = temp;
  1165.     old_piece = piece;
  1166.  
  1167.     if ((temp + piece->used) > position) 
  1168.       return(piece);
  1169.   }
  1170.   return(old_piece);      /* if we run off the end the return the last piece */
  1171. }
  1172.     
  1173. /*    Function Name: MyStrncpy
  1174.  *    Description: Just like string copy, but slower and will always
  1175.  *                   work on overlapping strings.
  1176.  *    Arguments: (same as strncpy) - s1, s2 - strings to copy (2->1).
  1177.  *                  n - the number of chars to copy.
  1178.  *    Returns: s1.
  1179.  */
  1180.  
  1181. static String
  1182. MyStrncpy(s1, s2, n)
  1183. char * s1, * s2;
  1184. int n;
  1185. {
  1186.   char * temp = XtMalloc(sizeof(unsigned char) * n);
  1187.  
  1188.   strncpy(temp, s2, n);        /* Saber has a bug that causes it to generate*/
  1189.   strncpy(s1, temp, n);        /* a bogus warning message here (CDP 6/32/89)*/
  1190.   XtFree(temp);
  1191.   return(s1);
  1192. }
  1193.   
  1194. /*    Function Name: BreakPiece
  1195.  *    Description: Breaks a full piece into two new pieces.
  1196.  *    Arguments: src - The AsciiSrc Widget.
  1197.  *                 piece - the piece to break.
  1198.  *    Returns: none.
  1199.  */
  1200.  
  1201. #define HALF_PIECE (src->ascii_src.piece_size/2)
  1202.  
  1203. static void
  1204. BreakPiece(src, piece)
  1205. AsciiSrcObject src;
  1206. Piece * piece;
  1207. {
  1208.   Piece * new = AllocNewPiece(src, piece);
  1209.   
  1210.   new->text = XtMalloc(src->ascii_src.piece_size * sizeof(unsigned char));
  1211.   strncpy(new->text, piece->text + HALF_PIECE,
  1212.       src->ascii_src.piece_size - HALF_PIECE);
  1213.   piece->used = HALF_PIECE;
  1214.   new->used = src->ascii_src.piece_size - HALF_PIECE; 
  1215. }
  1216.  
  1217. /* ARGSUSED */
  1218. static void
  1219. CvtStringToAsciiType(args, num_args, fromVal, toVal)
  1220. XrmValuePtr *args;        /* unused */
  1221. Cardinal    *num_args;    /* unused */
  1222. XrmValuePtr    fromVal;
  1223. XrmValuePtr    toVal;
  1224. {
  1225.   static XawAsciiType type;
  1226.   static XrmQuark  XtQEstring = NULLQUARK;
  1227.   static XrmQuark  XtQEfile;
  1228.   XrmQuark q;
  1229.   char lowerName[BUFSIZ];
  1230.  
  1231.   if (XtQEstring == NULLQUARK) {
  1232.     XtQEstring = XrmPermStringToQuark(XtEstring);
  1233.     XtQEfile   = XrmPermStringToQuark(XtEfile);
  1234.   }
  1235.  
  1236.   XmuCopyISOLatin1Lowered(lowerName, (char *) fromVal->addr);
  1237.   q = XrmStringToQuark(lowerName);
  1238.  
  1239.   if (q == XtQEstring) type = XawAsciiString;
  1240.   if (q == XtQEfile)  type = XawAsciiFile;
  1241.  
  1242.   (*toVal).size = sizeof(XawAsciiType);
  1243.   (*toVal).addr = (XPointer) &type;
  1244.   return;
  1245. }
  1246.  
  1247. #if (defined(ASCII_STRING) || defined(ASCII_DISK))
  1248. #  include <X11/Xaw/Cardinals.h>
  1249. #endif
  1250.  
  1251. #ifdef ASCII_STRING
  1252. /************************************************************
  1253.  *
  1254.  * Compatability functions.
  1255.  *
  1256.  ************************************************************/
  1257.  
  1258. /*    Function Name: AsciiStringSourceCreate
  1259.  *    Description: Creates a string source.
  1260.  *    Arguments: parent - the widget that will own this source.
  1261.  *                 args, num_args - the argument list.
  1262.  *    Returns: a pointer to the new text source.
  1263.  */
  1264.  
  1265. Widget
  1266. XawStringSourceCreate(parent, args, num_args)
  1267. Widget parent;
  1268. ArgList args;
  1269. Cardinal num_args;
  1270. {
  1271.   XawTextSource src;
  1272.   ArgList ascii_args;
  1273.   Arg temp[2];
  1274.  
  1275.   XtSetArg(temp[0], XtNtype, XawAsciiString);
  1276.   XtSetArg(temp[1], XtNuseStringInPlace, TRUE);
  1277.   ascii_args = XtMergeArgLists(temp, TWO, args, num_args);
  1278.  
  1279.   src = XtCreateWidget("genericAsciiString", asciiSrcObjectClass, parent,
  1280.                ascii_args, num_args + TWO);
  1281.   XtFree((char *)ascii_args);
  1282.   return(src);
  1283. }
  1284.  
  1285. /*
  1286.  * This is hacked up to try to emulate old functionality, it
  1287.  * may not work, as I have not old code to test it on.
  1288.  *
  1289.  * Chris D. Peterson  8/31/89.
  1290.  */
  1291.  
  1292. void 
  1293. XawTextSetLastPos (w, lastPos)
  1294. Widget w;
  1295. XawTextPosition lastPos;
  1296. {
  1297.   AsciiSrcObject src = (AsciiSrcObject) XawTextGetSource(w);
  1298.  
  1299.   src->ascii_src.piece_size = lastPos;
  1300. }
  1301. #endif /* ASCII_STRING */
  1302.  
  1303. #ifdef ASCII_DISK
  1304. /*    Function Name: AsciiDiskSourceCreate
  1305.  *    Description: Creates a disk source.
  1306.  *    Arguments: parent - the widget that will own this source.
  1307.  *                 args, num_args - the argument list.
  1308.  *    Returns: a pointer to the new text source.
  1309.  */
  1310.  
  1311. Widget
  1312. XawDiskSourceCreate(parent, args, num_args)
  1313. Widget parent;
  1314. ArgList args;
  1315. Cardinal num_args;
  1316. {
  1317.   XawTextSource src;
  1318.   ArgList ascii_args;
  1319.   Arg temp[1];
  1320.   register int i;
  1321.  
  1322.   XtSetArg(temp[0], XtNtype, XawAsciiFile);
  1323.   ascii_args = XtMergeArgLists(temp, ONE, args, num_args);
  1324.   num_args++;
  1325.  
  1326.   for (i = 0; i < num_args; i++) 
  1327.     if (streq(ascii_args[i].name, XtNfile) || 
  1328.               streq(ascii_args[i].name, XtCFile)) 
  1329.       ascii_args[i].name = XtNstring;
  1330.  
  1331.   src = XtCreateWidget("genericAsciiDisk", asciiSrcObjectClass, parent,
  1332.                ascii_args, num_args);
  1333.   XtFree((char *)ascii_args);
  1334.   return(src);
  1335. }
  1336. #endif /* ASCII_DISK */
  1337.