home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / the25.zip / thesrc251.zip / file.c < prev    next >
C/C++ Source or Header  |  1998-07-23  |  78KB  |  2,265 lines

  1. /***********************************************************************/
  2. /* FILE.C - File and view related functions.                           */
  3. /***********************************************************************/
  4. /*
  5.  * THE - The Hessling Editor. A text editor similar to VM/CMS xedit.
  6.  * Copyright (C) 1991-1997 Mark Hessling
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License as
  10.  * published by the Free Software Foundation; either version 2 of
  11.  * the License, or any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16.  * General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to:
  20.  *
  21.  *    The Free Software Foundation, Inc.
  22.  *    675 Mass Ave,
  23.  *    Cambridge, MA 02139 USA.
  24.  *
  25.  *
  26.  * If you make modifications to this software that you feel increases
  27.  * it usefulness for the rest of the community, please email the
  28.  * changes, enhancements, bug fixes as well as any and all ideas to me.
  29.  * This software is going to be maintained and enhanced as deemed
  30.  * necessary by the community.
  31.  *
  32.  * Mark Hessling                 Email:             M.Hessling@qut.edu.au
  33.  * PO Box 203                    Phone:                    +617 3802 0800
  34.  * Bellara                       http://www.gu.edu.au/gext/the/markh.html
  35.  * QLD 4507                      **** Maintainer PDCurses & REXX/SQL ****
  36.  * Australia                     ************* Author of THE ************
  37.  */
  38.  
  39. /*
  40. $Id: file.c 2.1 1995/06/24 16:29:57 MH Rel MH $
  41. */
  42.  
  43. #include <the.h>
  44. #include <proto.h>
  45.  
  46. #include <errno.h>
  47. #include <directry.h>
  48.  
  49. #if defined(DOS) || defined(OS2)
  50. #include <io.h>
  51. #endif
  52.  
  53. #if defined(HAVE_SYS_ACL_H) && !defined(HAVE_BROKEN_SYS_ACL_H)
  54. #include <sys/acl.h>
  55. #endif
  56. /****************** needs to be fixed *************/
  57. #ifdef GO32
  58. #define stricmp strcasecmp
  59. #endif
  60.  
  61. #ifdef HAVE_PROTO
  62. static short write_line(CHARTYPE *,LENGTHTYPE,FILE *);
  63. static short write_char(CHARTYPE,FILE *);
  64. #else
  65. static short write_line();
  66. static short write_char();
  67. #endif
  68.  
  69. LINE *dir_first_line=NULL;
  70. LINE *dir_last_line=NULL;
  71. LINETYPE dir_number_lines=0L;
  72.  
  73. /*#define TRACE*/
  74. /***********************************************************************/
  75. #ifdef HAVE_PROTO
  76. short get_file(CHARTYPE *filename)
  77. #else
  78. short get_file(filename)
  79. CHARTYPE *filename;
  80. #endif
  81. /***********************************************************************/
  82. {
  83. /*-------------------------- external data ----------------------------*/
  84.  extern struct stat stat_buf;
  85.  extern CHARTYPE TABI_ONx;
  86.  extern CHARTYPE *rexxoutname;
  87.  extern CHARTYPE *keyfilename;
  88.  extern CHARTYPE number_of_files;
  89. #if !defined(MULTIPLE_PSEUDO_FILES)
  90.  extern CHARTYPE dir_filename[10];
  91.  extern CHARTYPE dir_pathname[MAX_FILE_NAME+1];
  92. #endif
  93.  extern CHARTYPE dir_path[MAX_FILE_NAME+1];
  94.  extern CHARTYPE dir_files[MAX_FILE_NAME+1];
  95.  extern CHARTYPE sp_path[MAX_FILE_NAME+1];
  96.  extern CHARTYPE sp_fname[MAX_FILE_NAME+1];
  97. #if defined(MULTIPLE_PSEUDO_FILES)
  98.  extern CHARTYPE rexx_macro_name[MAX_FILE_NAME+1];
  99.  extern CHARTYPE rexx_macro_parameters[MAX_FILE_NAME+1];
  100. #endif
  101.  extern LINE *dir_first_line;
  102.  extern LINE *dir_last_line;
  103.  extern LINETYPE dir_number_lines;
  104.  extern LINE *rexxout_first_line;
  105.  extern LINE *rexxout_last_line;
  106.  extern LINETYPE rexxout_number_lines;
  107.  extern LINE *key_first_line;
  108.  extern LINE *key_last_line;
  109.  extern LINETYPE key_number_lines;
  110.  extern LENGTHTYPE display_length;
  111. /*--------------------------- local data ------------------------------*/
  112.  LINE *curr=NULL;
  113.  CHARTYPE work_filename[MAX_FILE_NAME+1] ;
  114.  VIEW_DETAILS *save_current_view=NULL,*found_file=NULL;
  115.  short rc=RC_OK;
  116.  FILE_DETAILS *save_current_file=NULL;
  117.  bool save_scope=FALSE;
  118.  bool save_stay=FALSE;
  119.  CHARTYPE pseudo_file=PSEUDO_REAL;
  120. /*--------------------------- processing ------------------------------*/
  121. #ifdef TRACE
  122.  trace_function("file.c:    get_file");
  123. #endif
  124. #if defined(MULTIPLE_PSEUDO_FILES)
  125. /*---------------------------------------------------------------------*/
  126. /* Determine if we are editing a PSEUDO file.  Set a temporary flag    */
  127. /* here for REXXOUT and KEY files; a DIR.DIR file is determined below. */
  128. /*---------------------------------------------------------------------*/
  129.  if (dir_number_lines != 0L)
  130.    {
  131.     pseudo_file = PSEUDO_DIR;
  132.     strcpy((DEFCHAR *)sp_path,(DEFCHAR *)dir_path);
  133.     strcpy((DEFCHAR *)sp_fname,(DEFCHAR *)dir_files);
  134.    }
  135.  else
  136.    {
  137.     if (rexxout_number_lines != 0L)
  138.       {
  139.        pseudo_file = PSEUDO_REXX;
  140.        strcpy((DEFCHAR *)sp_path,"Output from: ");
  141.        strcpy((DEFCHAR *)sp_fname,(DEFCHAR *)rexx_macro_name);
  142.        strcat((DEFCHAR *)sp_fname," ");
  143.        strcat((DEFCHAR *)sp_fname,(DEFCHAR *)rexx_macro_parameters);
  144.       }
  145.     else
  146.       {
  147.        if (key_number_lines != 0L)
  148.          {
  149.           pseudo_file = PSEUDO_KEY;
  150.           strcpy((DEFCHAR *)sp_path,"Key definitions:");
  151.           strcpy((DEFCHAR *)sp_fname,"");
  152.          }
  153.        else
  154.          {
  155. /*---------------------------------------------------------------------*/
  156. /* Split the filename supplied into directory and filename parts.      */
  157. /* This is done before allocating a new current_file number.           */
  158. /*---------------------------------------------------------------------*/
  159.           if ((rc = splitpath(filename)) != RC_OK)
  160.             {
  161.              display_error(10,filename,FALSE);
  162. #ifdef TRACE
  163.              trace_return();
  164. #endif
  165.              return(rc);
  166.             }
  167. /*---------------------------------------------------------------------*/
  168. /* If the filename portion of the splitpath is empty, then we are      */
  169. /* editing a directory. So create the new file with the appropriate OS */
  170. /* command and set the filename to DIR.DIR.                            */
  171. /*---------------------------------------------------------------------*/
  172.           if (strcmp((DEFCHAR *)sp_fname,"") == 0)
  173.             {
  174.              if ((rc = read_directory()) != RC_OK)
  175.                {
  176.                 display_error(10,sp_path,FALSE);
  177. #ifdef TRACE
  178.                 trace_return();
  179. #endif
  180.                 return(rc);
  181.                }
  182.              pseudo_file = PSEUDO_DIR;
  183.              strcpy((DEFCHAR *)sp_path,(DEFCHAR *)dir_path);
  184.              strcpy((DEFCHAR *)sp_fname,(DEFCHAR *)dir_files);
  185.             }
  186.          }
  187.       }
  188.    }
  189. #else
  190. /*---------------------------------------------------------------------*/
  191. /* Split the filename supplied into directory and filename parts.      */
  192. /* This is done before allocating a new current_file number.           */
  193. /*---------------------------------------------------------------------*/
  194.  if ((rc = splitpath(filename)) != RC_OK)
  195.    {
  196.     display_error(10,filename,FALSE);
  197. #ifdef TRACE
  198.     trace_return();
  199. #endif
  200.     return(rc);
  201.    }
  202. /*---------------------------------------------------------------------*/
  203. /* If the filename portion of the splitpath is empty, then we are      */
  204. /* editing a directory. So create the new file with the appropriate OS */
  205. /* command and set the filename to DIR.DIR.                            */
  206. /*---------------------------------------------------------------------*/
  207.  if (strcmp((DEFCHAR *)sp_fname,"") == 0)
  208.    {
  209.     if ((rc = read_directory()) != RC_OK)
  210.        {
  211.         display_error(10,sp_path,FALSE);
  212. #ifdef TRACE
  213.         trace_return();
  214. #endif
  215.         return(rc);
  216.        }
  217.     strcpy((DEFCHAR *)sp_path,(DEFCHAR *)dir_pathname);
  218.     strcpy((DEFCHAR *)sp_fname,(DEFCHAR *)dir_filename);
  219.    }
  220. /*---------------------------------------------------------------------*/
  221. /* Determine if we are editing a PSEUDO file.  Set a temporary flag    */
  222. /* here for REXXOUT and KEY files; a DIR.DIR file is determined below. */
  223. /*---------------------------------------------------------------------*/
  224.  if (strcmp((DEFCHAR *)dir_filename,(DEFCHAR *)sp_fname) == 0)
  225.     pseudo_file = PSEUDO_DIR;
  226.  else
  227.     if (strcmp((DEFCHAR *)rexxoutname,(DEFCHAR *)sp_fname) == 0)
  228.        pseudo_file = PSEUDO_REXX;
  229.     else
  230.        if (strcmp((DEFCHAR *)keyfilename,(DEFCHAR *)sp_fname) == 0)
  231.           pseudo_file = PSEUDO_KEY;
  232. #endif
  233. /*---------------------------------------------------------------------*/
  234. /* If this is the first file to be edited, don't check to see if the  */
  235. /* file is already in the ring. Obvious hey!                           */
  236. /*---------------------------------------------------------------------*/
  237.  if (CURRENT_VIEW == (VIEW_DETAILS *)NULL)     /* no files in ring yet */
  238.    {
  239.     if ((rc = defaults_for_first_file()) != RC_OK)
  240.       {
  241. #ifdef TRACE
  242.        trace_return();
  243. #endif
  244.        return(rc);
  245.       }
  246.    }
  247.  else
  248.    {
  249. /*---------------------------------------------------------------------*/
  250. /* Here we should check if we already have the file to be edited in   */
  251. /* the ring. If the file is there and it is DIR.DIR, QQUIT out of it   */
  252. /* otherwise set the current pointer to it and exit.                   */
  253. /* Same applies to REXX output file.                                   */
  254. /*---------------------------------------------------------------------*/
  255.     save_current_view = CURRENT_VIEW;
  256. #if !defined(MULTIPLE_PSEUDO_FILES)
  257.     if ((found_file = find_file(sp_path,sp_fname)) != (VIEW_DETAILS *)NULL)
  258.       {
  259.        CURRENT_VIEW = found_file;
  260.        if (CURRENT_FILE->pseudo_file == PSEUDO_DIR
  261.        ||  CURRENT_FILE->pseudo_file == PSEUDO_REXX
  262.        ||  CURRENT_FILE->pseudo_file == PSEUDO_KEY)
  263.          {
  264.           free_view_memory(FALSE,FALSE);
  265.           if (CURRENT_VIEW == (VIEW_DETAILS *)NULL)
  266.              rc = defaults_for_first_file();
  267.           else
  268.             {
  269.              save_current_file = CURRENT_FILE;
  270.              rc = defaults_for_other_files(NULL);
  271.             }
  272.           if (rc != RC_OK)
  273.             {
  274. #ifdef TRACE
  275.              trace_return();
  276. #endif
  277.              return(rc);
  278.             }
  279.          }
  280.        else
  281.          {
  282.           SCREEN_VIEW(current_screen) = CURRENT_VIEW;
  283.           CURRENT_VIEW->in_ring = TRUE;
  284. #ifdef TRACE
  285.           trace_return();
  286. #endif
  287.           return(RC_OK);
  288.          }
  289.       }
  290.     else
  291.       {
  292.        CURRENT_VIEW = save_current_view;
  293.        save_current_file = CURRENT_FILE;
  294.        if ((rc = defaults_for_other_files(NULL)) != RC_OK)
  295.          {
  296. #ifdef TRACE
  297.           trace_return();
  298. #endif
  299.           return(rc);
  300.          }
  301.       }
  302. #else
  303.     found_file = find_file(sp_path,sp_fname);
  304.     if (CURRENT_FILE->pseudo_file != PSEUDO_REAL
  305.     ||  found_file == (VIEW_DETAILS *)NULL)
  306.       {
  307.        CURRENT_VIEW = save_current_view;
  308.        save_current_file = CURRENT_FILE;
  309.        if ((rc = defaults_for_other_files(NULL)) != RC_OK)
  310.          {
  311. #ifdef TRACE
  312.           trace_return();
  313. #endif
  314.           return(rc);
  315.          }
  316.       }
  317.     else
  318.       {
  319.        CURRENT_VIEW = found_file;
  320.        CURRENT_VIEW->in_ring = TRUE;
  321.        SCREEN_VIEW(current_screen) = CURRENT_VIEW;
  322. #ifdef TRACE
  323.        trace_return();
  324. #endif
  325.        return(RC_OK);
  326.       }
  327. #endif
  328.     }
  329. /*---------------------------------------------------------------------*/
  330. /* Increment the number of files in storage here, so that if there are */
  331. /* any problems with reading the file, free_file_memory() function can */
  332. /* correctly decrement the number of files.                            */
  333. /*---------------------------------------------------------------------*/
  334.  number_of_files++;
  335. /*---------------------------------------------------------------------*/
  336. /* Allocate memory to file pointer.                                    */
  337. /*---------------------------------------------------------------------*/
  338.  if ((CURRENT_FILE = (FILE_DETAILS *)(*the_malloc)(sizeof(FILE_DETAILS))) == NULL)
  339.    {
  340.     free_view_memory(TRUE,TRUE);
  341.     display_error(30,(CHARTYPE *)"",FALSE);
  342. #ifdef TRACE
  343.     trace_return();
  344. #endif
  345.     return(RC_OUT_OF_MEMORY);
  346.    }
  347. /*---------------------------------------------------------------------*/
  348. /* Allocate space for file's colour attributes...                      */
  349. /*---------------------------------------------------------------------*/
  350.  if ((CURRENT_FILE->attr = (COLOUR_ATTR *)(*the_malloc)(ATTR_MAX*sizeof(COLOUR_ATTR))) == NULL)
  351.    {
  352.     display_error(30,(CHARTYPE *)"",FALSE);
  353. #ifdef TRACE
  354.     trace_return();
  355. #endif
  356.     return(RC_OUT_OF_MEMORY);
  357.    }
  358.  memset(CURRENT_FILE->attr,0,ATTR_MAX*sizeof(COLOUR_ATTR));
  359. /*---------------------------------------------------------------------*/
  360. /* Set up default file attributes.                                     */
  361. /*---------------------------------------------------------------------*/
  362.  default_file_attributes(save_current_file);
  363.  CURRENT_FILE->pseudo_file = pseudo_file;
  364. /*---------------------------------------------------------------------*/
  365. /* Copy the filename and path strings split up at the start of the     */
  366. /* function.                                                           */
  367. /*---------------------------------------------------------------------*/
  368.  if ((CURRENT_FILE->fname = (CHARTYPE *)(*the_malloc)(strlen((DEFCHAR *)sp_fname)+1)) == NULL)
  369.    {
  370.     free_view_memory(TRUE,TRUE);
  371.     display_error(30,(CHARTYPE *)"",FALSE);
  372. #ifdef TRACE
  373.     trace_return();
  374. #endif
  375.     return(RC_OUT_OF_MEMORY);
  376.    }
  377.  if ((CURRENT_FILE->fpath = (CHARTYPE *)(*the_malloc)(strlen((DEFCHAR *)sp_path)+1)) == NULL)
  378.    {
  379.     free_view_memory(TRUE,TRUE);
  380.     display_error(30,(CHARTYPE *)"",FALSE);
  381. #ifdef TRACE
  382.     trace_return();
  383. #endif
  384.     return(RC_OUT_OF_MEMORY);
  385.    }
  386.  if ((CURRENT_FILE->actualfname = (CHARTYPE *)(*the_malloc)(strlen((DEFCHAR *)filename)+1)) == NULL)
  387.    {
  388.     free_view_memory(TRUE,TRUE);
  389.     display_error(30,(CHARTYPE *)"",FALSE);
  390. #ifdef TRACE
  391.     trace_return();
  392. #endif
  393.     return(RC_OUT_OF_MEMORY);
  394.    }
  395.  strcpy((DEFCHAR *)CURRENT_FILE->fname,(DEFCHAR *)sp_fname);
  396.  strcpy((DEFCHAR *)CURRENT_FILE->fpath,(DEFCHAR *)sp_path);
  397.  strcpy((DEFCHAR *)CURRENT_FILE->actualfname,(DEFCHAR *)filename);
  398. /*---------------------------------------------------------------------*/
  399. /* If we have a "real" file, generate the filename to be used in       */
  400. /* AUTOSAVE.                                                           */
  401. /*---------------------------------------------------------------------*/
  402.  if (!CURRENT_FILE->pseudo_file)
  403.    {
  404.     if ((CURRENT_FILE->autosave_fname = 
  405.        (CHARTYPE *)(*the_malloc)(strlen((DEFCHAR *)sp_fname)+strlen((DEFCHAR *)sp_path)+7)) == NULL)
  406.       {
  407.        free_view_memory(TRUE,TRUE);
  408.        display_error(30,(CHARTYPE *)"",FALSE);
  409. #ifdef TRACE
  410.        trace_return();
  411. #endif
  412.        return(RC_OUT_OF_MEMORY);
  413.       }
  414.     new_filename(sp_path,sp_fname,CURRENT_FILE->autosave_fname,(CHARTYPE *)".aus");
  415.    }
  416. /*---------------------------------------------------------------------*/
  417. /* Save the path and filename in a working area.                       */
  418. /*---------------------------------------------------------------------*/
  419.  strcpy((DEFCHAR *)work_filename,(DEFCHAR *)sp_path);
  420.  strcat((DEFCHAR *)work_filename,(DEFCHAR *)sp_fname);
  421. /*---------------------------------------------------------------------*/
  422. /* For PSEUDO files, point the first and last line pointers to the     */
  423. /* already allocated LINE* linked list...                              */
  424. /*---------------------------------------------------------------------*/
  425.  if (CURRENT_FILE->pseudo_file) /* if DIR.DIR or REXXOUT.$$$ or KEY$$$.$$$ */
  426.    {
  427.     CURRENT_FILE->fmode = 0;
  428.     switch(CURRENT_FILE->pseudo_file)
  429.       {
  430.        case PSEUDO_DIR:
  431.             CURRENT_FILE->first_line = dir_first_line;
  432.             CURRENT_FILE->last_line = dir_last_line;
  433.             CURRENT_FILE->number_lines = dir_number_lines;
  434. #if defined(MULTIPLE_PSEUDO_FILES)
  435.             dir_number_lines = 0L;
  436. #endif
  437.             break;
  438.        case PSEUDO_REXX:
  439.             CURRENT_FILE->first_line = rexxout_first_line;
  440.             CURRENT_FILE->last_line = rexxout_last_line;
  441.             CURRENT_FILE->number_lines = rexxout_number_lines;
  442. #if defined(MULTIPLE_PSEUDO_FILES)
  443.             rexxout_number_lines = 0L;
  444. #endif
  445.             break;
  446.        case PSEUDO_KEY:
  447.             CURRENT_FILE->first_line = key_first_line;
  448.             CURRENT_FILE->last_line = key_last_line;
  449.             CURRENT_FILE->number_lines = key_number_lines;
  450. #if defined(MULTIPLE_PSEUDO_FILES)
  451.             key_number_lines = 0L;
  452. #endif
  453.             break;
  454.       }
  455. #ifdef TRACE
  456.     trace_return();
  457. #endif
  458.     return(RC_OK);
  459.    }
  460.  if (file_exists(work_filename))
  461.    {
  462.     if (file_writable(work_filename))
  463.        CURRENT_FILE->disposition = FILE_NORMAL;
  464.     else
  465.       {
  466.        if (file_readable(work_filename))
  467.          {
  468.           CURRENT_FILE->disposition = FILE_READONLY;
  469.           display_error(14,(CHARTYPE *)work_filename,FALSE);
  470.          }
  471.        else
  472.          {
  473.           display_error(8,work_filename,FALSE);
  474.           free_view_memory(TRUE,TRUE);
  475. #ifdef TRACE
  476.           trace_return();
  477. #endif
  478.           return(RC_ACCESS_DENIED);
  479.          }
  480.       }
  481.     stat((DEFCHAR *)work_filename,&stat_buf);
  482.     CURRENT_FILE->fmode = stat_buf.st_mode;
  483. #ifdef HAVE_CHOWN
  484.     CURRENT_FILE->uid = stat_buf.st_uid;
  485.     CURRENT_FILE->gid = stat_buf.st_gid;
  486. #endif
  487.     if ((CURRENT_FILE->fp = fopen((DEFCHAR *)work_filename,"rb")) == NULL)
  488.       {
  489. #ifdef TRACE
  490.        trace_return();
  491. #endif
  492.        return(RC_ACCESS_DENIED);
  493.       }
  494.    }
  495.  else
  496.    {
  497.     CURRENT_FILE->fmode = 0;
  498.     CURRENT_FILE->disposition = FILE_NEW;
  499.     display_error(20,(CHARTYPE *)work_filename,TRUE);
  500.    }
  501. /*---------------------------------------------------------------------*/
  502. /* first_line is set to "Top of File"                                  */
  503. /*---------------------------------------------------------------------*/
  504.  if ((CURRENT_FILE->first_line = add_line(CURRENT_FILE->first_line,NULL,TOP_OF_FILE,
  505.      strlen((DEFCHAR *)TOP_OF_FILE),0,FALSE)) == NULL)
  506.    {
  507.     if (CURRENT_FILE->disposition != FILE_NEW)
  508.        fclose(CURRENT_FILE->fp);
  509.     free_view_memory(TRUE,TRUE);
  510. #ifdef TRACE
  511.     trace_return();
  512. #endif
  513.     return(RC_OUT_OF_MEMORY);
  514.    }
  515.  
  516.  curr = CURRENT_FILE->first_line;
  517. /*---------------------------------------------------------------------*/
  518. /* Read in the existing file...                                        */
  519. /*---------------------------------------------------------------------*/
  520.  CURRENT_FILE->number_lines = 0L;
  521.  if (CURRENT_FILE->disposition != FILE_NEW)
  522.    {
  523.     if (!display_length)                 /* NOT reading fixed length records... */
  524.       {
  525.        if ((curr = read_file(CURRENT_FILE->fp,curr,work_filename,1L,0L,FALSE)) == NULL)
  526.          {
  527.           if (CURRENT_FILE->disposition != FILE_NEW)
  528.              fclose(CURRENT_FILE->fp);
  529.           free_view_memory(TRUE,TRUE);
  530. #ifdef TRACE
  531.           trace_return();
  532. #endif
  533.           return(RC_ACCESS_DENIED);
  534.          }
  535.       }
  536.     else
  537.       {
  538.        if ((curr = read_fixed_file(CURRENT_FILE->fp,curr,work_filename,1L,0L)) == NULL)
  539.          {
  540.           if (CURRENT_FILE->disposition != FILE_NEW)
  541.              fclose(CURRENT_FILE->fp);
  542.           free_view_memory(TRUE,TRUE);
  543. #ifdef TRACE
  544.           trace_return();
  545. #endif
  546.           return(RC_ACCESS_DENIED);
  547.          }
  548.       }
  549.    }
  550. /*---------------------------------------------------------------------*/
  551. /* Close the file...                                                   */
  552. /*---------------------------------------------------------------------*/
  553.  if (CURRENT_FILE->disposition != FILE_NEW)
  554.     fclose(CURRENT_FILE->fp);
  555. /*---------------------------------------------------------------------*/
  556. /* last line is set to "Bottom of File"                                */
  557. /*---------------------------------------------------------------------*/
  558.  if ((CURRENT_FILE->last_line = add_line(CURRENT_FILE->first_line,curr,BOTTOM_OF_FILE,
  559.      strlen((DEFCHAR *)BOTTOM_OF_FILE),0,FALSE)) == NULL)
  560.    {
  561.     free_view_memory(TRUE,TRUE);
  562. #ifdef TRACE
  563.     trace_return();
  564. #endif
  565.     return(RC_OUT_OF_MEMORY);
  566.    }
  567.  pre_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line,(LINE *)NULL);
  568. /*---------------------------------------------------------------------*/
  569. /* If TABSIN is ON, we need to run EXPAND ALL.                         */
  570. /* We need to save the current setting of scope so that it can be      */
  571. /* changed to ALL so that every line will be expanded.                 */
  572. /* Of course if TABSIN OFF was set we DON'T run EXPAND ALL :-)         */
  573. /*---------------------------------------------------------------------*/
  574.  if (TABI_ONx)
  575.    {
  576.     save_scope = CURRENT_VIEW->scope_all;
  577.     save_stay = CURRENT_VIEW->stay;
  578.     CURRENT_VIEW->stay = TRUE;
  579.     rc = execute_expand_compress((CHARTYPE *)"ALL",TRUE,FALSE,FALSE,FALSE);
  580.     if (rc == RC_TOF_EOF_REACHED)
  581.        rc = RC_OK;
  582.     CURRENT_VIEW->scope_all = save_scope;
  583.     CURRENT_VIEW->stay = save_stay;
  584.    }
  585.  
  586. #ifdef TRACE
  587.  trace_return();
  588. #endif
  589.  return(rc);
  590. }
  591. /***********************************************************************/
  592. #ifdef HAVE_PROTO
  593. LINE *read_file(FILE *fp,LINE *curr,CHARTYPE *filename,LINETYPE fromline,LINETYPE numlines,bool called_from_get_command)
  594. #else
  595. LINE *read_file(fp,curr,filename,fromline,numlines,called_from_get_command)
  596. FILE *fp;
  597. LINE *curr;
  598. CHARTYPE *filename;
  599. LINETYPE fromline,numlines;
  600. bool called_from_get_command;
  601. #endif
  602. /***********************************************************************/
  603. {
  604. #define CR '\r'
  605. #define LF '\n'
  606. #define DOSEOF 26
  607. /*-------------------------- external data ----------------------------*/
  608. #ifdef MSWIN
  609.  extern bool in_profile;
  610. #endif
  611.  extern CHARTYPE *trec;
  612. /*--------------------------- local data ------------------------------*/
  613.  register unsigned short i=0;
  614.  LENGTHTYPE maxlen=0;
  615.  short ch=0;
  616.  LINE *temp=NULL;
  617.  LENGTHTYPE len=0;
  618.  bool eof_reached=FALSE;
  619.  LENGTHTYPE chars_read=0;
  620.  LENGTHTYPE line_start=0;
  621.  LENGTHTYPE total_line_length=0;
  622.  int extra=0;
  623.  LENGTHTYPE read_start=0;
  624.  LINETYPE total_lines_read=0L,actual_lines_read=0L;
  625. /*--------------------------- processing ------------------------------*/
  626. #ifdef TRACE
  627.  trace_function("file.c:    read_file");
  628. #endif
  629.  temp = curr;
  630. #ifdef MSWIN
  631.  WinLock();
  632. #endif
  633.  
  634.  while(1)
  635.    {
  636.     line_start = 0;
  637.     chars_read = (LENGTHTYPE)fread(trec+read_start,sizeof(CHARTYPE),max_line_length+2,fp);
  638.     if (feof(fp))
  639.       {
  640.        eof_reached = TRUE;
  641.        for (;*(trec+read_start+chars_read-1)==DOSEOF;chars_read--)
  642.           ;
  643.       }
  644. /*---------------------------------------------------------------------*/
  645. /* For each character remaining from the previous read in an incomplete*/
  646. /* line and each character read from the last fread()...               */
  647. /*---------------------------------------------------------------------*/
  648.     for (i=read_start;i<chars_read+read_start;i++)
  649.       {
  650. /*---------------------------------------------------------------------*/
  651. /* If the character is a CR or LF we have a new line...                */
  652. /*---------------------------------------------------------------------*/
  653.        if (*(trec+i) != CR
  654.        &&  *(trec+i) != LF)
  655.           continue;
  656.          {
  657. /*---------------------------------------------------------------------*/
  658. /* If we have read all the lines in the file that has been requested,  */
  659. /* get out.                                                            */
  660. /*---------------------------------------------------------------------*/
  661.           if (actual_lines_read == numlines
  662.           &&  numlines != 0)
  663.             {
  664.              line_start = chars_read + read_start;
  665.              eof_reached = TRUE;
  666.              break;
  667.             }
  668.           extra = 0;
  669.           if (*(trec+i) == CR)
  670.             {
  671.              if (i == chars_read+read_start-1)
  672.                {
  673.                 *(trec+i+1) = fgetc(fp);
  674.                 if (feof(fp))
  675.                    eof_reached = TRUE;
  676.                 else
  677.                    chars_read++;
  678.                }
  679.              ch = *(trec+i+1);
  680.              if (ch == LF)
  681.                 extra = 1;
  682.             }
  683.           if (++total_lines_read >= fromline)
  684.             {
  685.              len = i - line_start;
  686.              total_line_length += len;
  687.              if (total_line_length > max_line_length)
  688.                {
  689.                 sprintf((DEFCHAR *)trec,"Line %ld exceeds max. width of %d",total_lines_read,max_line_length);
  690.                 display_error(29,trec,FALSE);
  691.                 if (!called_from_get_command)
  692.                    CURRENT_FILE->first_line = CURRENT_FILE->last_line = lll_free(CURRENT_FILE->first_line);
  693. #ifdef MSWIN
  694.                 WinUnLock();
  695. #endif
  696. #ifdef TRACE
  697.                 trace_return();
  698. #endif
  699.                 return(NULL);
  700.                }
  701.              if (total_line_length > maxlen)
  702.                 maxlen = total_line_length;
  703.              if ((temp = add_line(CURRENT_FILE->first_line,temp,trec+line_start,len,0,FALSE)) == NULL)
  704.                {
  705.                 if (!called_from_get_command)
  706.                    CURRENT_FILE->first_line = CURRENT_FILE->last_line = lll_free(CURRENT_FILE->first_line);
  707. #ifdef MSWIN
  708.                 WinUnLock();
  709. #endif
  710. #ifdef TRACE
  711.                 trace_return();
  712. #endif
  713.                 return(NULL);
  714.                }
  715.              actual_lines_read++;
  716.             }
  717.           line_start = i + 1 + extra;
  718.           i += extra;
  719.           total_line_length = 0;
  720.          }
  721.       }
  722.  
  723.     if (line_start != chars_read+read_start)        /* incomplete line */
  724.       {
  725.        if (line_start > chars_read+read_start)
  726.           read_start = 0;
  727.        else
  728.          {
  729.           len = chars_read+read_start - line_start;
  730.           if (eof_reached)
  731.             {
  732.              if (++total_lines_read >= fromline)
  733.                {
  734.                 total_line_length += len;
  735.                 if (total_line_length > max_line_length)
  736.                   {
  737.                    sprintf((DEFCHAR *)trec,"Line %ld exceeds max. width of %d",total_lines_read,max_line_length);
  738.                    display_error(29,trec,FALSE);
  739.                    if (!called_from_get_command)
  740.                       CURRENT_FILE->first_line = CURRENT_FILE->last_line = lll_free(CURRENT_FILE->first_line);
  741. #ifdef MSWIN
  742.                    WinUnLock();
  743. #endif
  744. #ifdef TRACE
  745.                    trace_return();
  746. #endif
  747.                    return(NULL);
  748.                   }
  749.                }
  750.              if ((temp = add_line(CURRENT_FILE->first_line,temp,trec+line_start,len,0,FALSE)) == NULL)
  751.                {
  752.                 if (!called_from_get_command)
  753.                    CURRENT_FILE->first_line = CURRENT_FILE->last_line = lll_free(CURRENT_FILE->first_line);
  754. #ifdef MSWIN
  755.                 WinUnLock();
  756. #endif
  757. #ifdef TRACE
  758.                 trace_return();
  759. #endif
  760.                 return(NULL);
  761.                }
  762.              actual_lines_read++;
  763.             }
  764.           else
  765.             {
  766.              for (i=0;i<len;i++)
  767.                 *(trec+i) = *(trec+i+line_start);
  768.              read_start = len;
  769.             }
  770.          }
  771.       }
  772.     else
  773.        read_start = 0;
  774.     if (eof_reached)
  775.        break;
  776.    }
  777.  
  778.  CURRENT_FILE->max_line_length = maxlen;
  779.  CURRENT_FILE->number_lines += actual_lines_read;
  780. #ifdef MSWIN
  781.  WinUnLock();
  782.  if (!in_profile)
  783.     show_statarea();
  784. #endif
  785. #ifdef TRACE
  786.  trace_return();
  787. #endif
  788.  return(temp);
  789. }
  790. /***********************************************************************/
  791. #ifdef HAVE_PROTO
  792. LINE *read_fixed_file(FILE *fp,LINE *curr,CHARTYPE *filename,LINETYPE fromline,LINETYPE numlines)
  793. #else
  794. LINE *read_fixed_file(fp,curr,filename,fromline,numlines)
  795. FILE *fp;
  796. LINE *curr;
  797. CHARTYPE *filename;
  798. LINETYPE fromline,numlines;
  799. #endif
  800. /***********************************************************************/
  801. {
  802. /*-------------------------- external data ----------------------------*/
  803. #ifdef MSWIN
  804.  extern bool in_profile;
  805. #endif
  806.  extern CHARTYPE *trec;
  807.  extern LENGTHTYPE display_length;
  808. /*--------------------------- local data ------------------------------*/
  809.  LINE *temp=NULL;
  810.  bool eof_reached=FALSE;
  811.  LENGTHTYPE chars_read=0;
  812.  LINETYPE total_lines_read=0L,actual_lines_read=0L;
  813. /*--------------------------- processing ------------------------------*/
  814. #ifdef TRACE
  815.  trace_function("file.c:    read_fixed_file");
  816. #endif
  817.  temp = curr;
  818. #ifdef MSWIN
  819.  WinLock();
  820. #endif
  821.  
  822.  while(1)
  823.    {
  824.     chars_read = (LENGTHTYPE)fread(trec,sizeof(CHARTYPE),display_length,fp);
  825.     if (feof(fp))
  826.       {
  827.        eof_reached = TRUE;
  828.       }
  829.     if (chars_read != 0)
  830.       {
  831. /*---------------------------------------------------------------------*/
  832. /* If we have read all the lines in the file that has been requested,  */
  833. /* get out.                                                            */
  834. /*---------------------------------------------------------------------*/
  835.        if (actual_lines_read == numlines
  836.        &&  numlines != 0)
  837.          {
  838.           eof_reached = TRUE;
  839.           break;
  840.          }
  841.        if (++total_lines_read >= fromline)
  842.          {
  843.           if ((temp = add_line(CURRENT_FILE->first_line,temp,trec,chars_read,0,FALSE)) == NULL)
  844.             {
  845.              CURRENT_FILE->first_line = CURRENT_FILE->last_line = lll_free(CURRENT_FILE->first_line);
  846. #ifdef MSWIN
  847.              WinUnLock();
  848. #endif
  849. #ifdef TRACE
  850.              trace_return();
  851. #endif
  852.              return(NULL);
  853.             }
  854.           actual_lines_read++;
  855.          }
  856.       }
  857.     if (eof_reached)
  858.        break;
  859.    }
  860.  CURRENT_FILE->max_line_length = display_length;
  861.  CURRENT_FILE->number_lines += actual_lines_read;
  862. #ifdef MSWIN
  863.  WinUnLock();
  864.  if (!in_profile)
  865.     show_statarea();
  866. #endif
  867. #ifdef TRACE
  868.  trace_return();
  869. #endif
  870.  return(temp);
  871. }
  872. /***********************************************************************/
  873. #ifdef HAVE_PROTO
  874. short save_file(FILE_DETAILS *cf,CHARTYPE *new_fname,bool force,LINETYPE in_lines,
  875.                 LINETYPE start_line,LINETYPE *num_file_lines,bool append,LENGTHTYPE start_col, LENGTHTYPE end_col,bool ignore_scope,bool lines_based_on_scope)
  876. #else
  877. short save_file(cf,new_fname,force,in_lines,start_line,num_file_lines,append,start_col,end_col,ignore_scope,lines_based_on_scope)
  878. FILE_DETAILS *cf;
  879. CHARTYPE *new_fname;
  880. bool force,append;
  881. LINETYPE in_lines,start_line;
  882. LINETYPE *num_file_lines;
  883. LENGTHTYPE start_col,end_col;
  884. bool ignore_scope;
  885. bool lines_based_on_scope;
  886. #endif
  887. /***********************************************************************/
  888. {
  889. /*------------------------- external data -----------------------------*/
  890.  extern CHARTYPE sp_fname[MAX_FILE_NAME+1];
  891.  extern CHARTYPE sp_path[MAX_FILE_NAME+1];
  892. /*--------------------------- local data ------------------------------*/
  893.  CHARTYPE *bak_filename=NULL;
  894.  CHARTYPE *write_fname=NULL;
  895.  LINETYPE i=0L;
  896.  LINETYPE abs_num_lines=(in_lines < 0L ? -in_lines : in_lines);
  897.  LINETYPE num_actual_lines=0L;
  898.  LINETYPE my_num_file_lines=0L;
  899.  short direction=(in_lines < 0L ? DIRECTION_BACKWARD : DIRECTION_FORWARD);
  900.  LINE *curr=NULL;
  901.  FILE *fp=NULL;
  902.  LENGTHTYPE col=0,newcol=0;
  903.  long off=0L;
  904.  CHARTYPE c=0;
  905.  short rc=RC_OK;
  906.  bool same_file=TRUE;
  907.  short anerror=0;
  908.  bool save_scope_all=CURRENT_VIEW->scope_all;
  909.  CHARTYPE eol[2];
  910.  int eol_len=0;
  911. #if defined(HAVE_GETACL)
  912.  struct acl_entry file_acl[NACLENTRIES];
  913.  size_t acl_entries=0;
  914. #endif
  915. #if defined(HAVE_ACL_GET)
  916.  char *acl_ptr=NULL;
  917. #endif
  918. /*--------------------------- processing ------------------------------*/
  919. #ifdef TRACE
  920.  trace_function("file.c:    save_file");
  921. #endif
  922.  
  923. #ifdef MSWIN_NOT_REQUIRED
  924.  if (!Registered()
  925.  &&  cf->number_lines > 100L)
  926.    {
  927.     display_error(77,(CHARTYPE *)"",FALSE);
  928. #ifdef TRACE
  929.     trace_return();
  930. #endif
  931.     return(RC_INVALID_ENVIRON);
  932.    }
  933. #endif
  934. /*---------------------------------------------------------------------*/
  935. /* Do not attempt to autosave a pseudo file...                         */
  936. /*---------------------------------------------------------------------*/
  937.  if (cf->pseudo_file
  938.  &&  blank_field(new_fname))
  939.     return(RC_OK);
  940.  
  941.  switch(cf->eolout)
  942.    {
  943.     case EOLOUT_CRLF:
  944.          eol[0] = (CHARTYPE)'\r';
  945.          eol[1] = (CHARTYPE)'\n';
  946.          eol_len = 2;
  947.          break;
  948.     case EOLOUT_LF:
  949.          eol[0] = (CHARTYPE)'\n';
  950.          eol_len = 1;
  951.          break;
  952.     case EOLOUT_CR:
  953.          eol[0] = (CHARTYPE)'\r';
  954.          eol_len = 1;
  955.          break;
  956.     case EOLOUT_NONE:
  957.          eol[0] = '\0';
  958.          eol_len = 0;
  959.          break;
  960.    }
  961.  if ((write_fname = (CHARTYPE *)(*the_malloc)(MAX_FILE_NAME)) == NULL)
  962.    {
  963.     display_error(30,(CHARTYPE *)"",FALSE);
  964. #ifdef TRACE
  965.     trace_return();
  966. #endif
  967.     return(RC_OUT_OF_MEMORY);
  968.    }
  969. /*---------------------------------------------------------------------*/
  970. /* If a new filename is specified, use it as the old filename.         */
  971. /*---------------------------------------------------------------------*/
  972.  (void *)strrmdup(strtrans(new_fname,OSLASH,ISLASH),ISLASH);
  973.  if (strcmp((DEFCHAR *)new_fname,"") != 0)       /* new_fname supplied */
  974.    {
  975. /*---------------------------------------------------------------------*/
  976. /* Split the supplied new filename.                                    */
  977. /*---------------------------------------------------------------------*/
  978.     if ((rc = splitpath(new_fname)) != RC_OK)
  979.       {
  980.        display_error(10,new_fname,FALSE);
  981.        if (bak_filename != (CHARTYPE *)NULL)
  982.           (*the_free)(bak_filename);
  983.        if (write_fname != (CHARTYPE *)NULL)
  984.           (*the_free)(write_fname);
  985. #ifdef TRACE
  986.        trace_return();
  987. #endif
  988.        return(rc);
  989.       }
  990.     strcpy((DEFCHAR *)write_fname,(DEFCHAR *)sp_path);
  991.     strcat((DEFCHAR *)write_fname,(DEFCHAR *)sp_fname);
  992.     same_file = FALSE;
  993. /*---------------------------------------------------------------------*/
  994. /* Test to make sure that the write fname doesn't exist...             */
  995. /* ...unless we are forcing the write.                                 */
  996. /*---------------------------------------------------------------------*/
  997.     if ((!force) && file_exists(write_fname))
  998.       {
  999.        display_error(31,write_fname,FALSE);
  1000.        if (bak_filename != (CHARTYPE *)NULL)
  1001.           (*the_free)(bak_filename);
  1002.        if (write_fname != (CHARTYPE *)NULL)
  1003.           (*the_free)(write_fname);
  1004. #ifdef TRACE
  1005.        trace_return();
  1006. #endif
  1007.        return(RC_ACCESS_DENIED);
  1008.       }
  1009. /*---------------------------------------------------------------------*/
  1010. /* Test to make sure that we can write the file.                       */
  1011. /*---------------------------------------------------------------------*/
  1012.     if (!file_writable(write_fname))
  1013.       {
  1014.        display_error(8,write_fname,FALSE);
  1015.        if (bak_filename != (CHARTYPE *)NULL)
  1016.           (*the_free)(bak_filename);
  1017.        if (write_fname != (CHARTYPE *)NULL)
  1018.           (*the_free)(write_fname);
  1019. #ifdef TRACE
  1020.        trace_return();
  1021. #endif
  1022.        return(RC_ACCESS_DENIED);
  1023.       }
  1024.    }
  1025.  else
  1026.    {
  1027. /*---------------------------------------------------------------------*/
  1028. /* We are using the same file name for the new file.                   */
  1029. /* Create the name of the current file.                                */
  1030. /*---------------------------------------------------------------------*/
  1031.     strcpy((DEFCHAR *)write_fname,(DEFCHAR *)cf->fpath);
  1032.     strcat((DEFCHAR *)write_fname,(DEFCHAR *)cf->fname);
  1033. /*---------------------------------------------------------------------*/
  1034. /* If the file to be saved is a "pseudo" file, return with an error... */
  1035. /*---------------------------------------------------------------------*/
  1036.     if (cf->pseudo_file)
  1037.       {
  1038.        display_error(8,write_fname,FALSE);
  1039.        if (bak_filename != (CHARTYPE *)NULL)
  1040.           (*the_free)(bak_filename);
  1041.        if (write_fname != (CHARTYPE *)NULL)
  1042.           (*the_free)(write_fname);
  1043. #ifdef TRACE
  1044.        trace_return();
  1045. #endif
  1046.        return(RC_ACCESS_DENIED);
  1047.       }
  1048. /*---------------------------------------------------------------------*/
  1049. /* If the file exists, test to make sure we can write it and save a    */
  1050. /* backup copy.                                                        */
  1051. /*---------------------------------------------------------------------*/
  1052.     if (file_exists(write_fname))
  1053.       {
  1054. /*---------------------------------------------------------------------*/
  1055. /* Test to make sure that we can write the file.                       */
  1056. /*---------------------------------------------------------------------*/
  1057.        if (!file_writable(write_fname))
  1058.          {
  1059.           display_error(8,write_fname,FALSE);
  1060.           if (bak_filename != (CHARTYPE *)NULL)
  1061.              (*the_free)(bak_filename);
  1062.           if (write_fname != (CHARTYPE *)NULL)
  1063.              (*the_free)(write_fname);
  1064. #ifdef TRACE
  1065.           trace_return();
  1066. #endif
  1067.           return(RC_ACCESS_DENIED);
  1068.          }
  1069. /*---------------------------------------------------------------------*/
  1070. /* For HPUX, save the current ACL...                                   */
  1071. /*---------------------------------------------------------------------*/
  1072. #if defined(HAVE_GETACL)
  1073.        if (cf->disposition != FILE_NEW)
  1074.          {
  1075.           if ((acl_entries = getacl((DEFCHAR *)write_fname,NACLENTRIES,file_acl)) == (-1))
  1076.             {
  1077.              if (errno == EOPNOTSUPP
  1078.              ||  errno == ENOSYS)
  1079.                 acl_entries = 0;
  1080.              else
  1081.                {
  1082.                 display_error(8,write_fname,FALSE);
  1083.                 if (bak_filename != (CHARTYPE *)NULL)
  1084.                    (*the_free)(bak_filename);
  1085.                 if (write_fname != (CHARTYPE *)NULL)
  1086.                    (*the_free)(write_fname);
  1087. #ifdef TRACE
  1088.                 trace_return();
  1089. #endif
  1090.                 return(RC_ACCESS_DENIED);
  1091.                }
  1092.             }
  1093.          }
  1094. #endif
  1095. /*---------------------------------------------------------------------*/
  1096. /* For AIX,  save the current ACL...                                   */
  1097. /*---------------------------------------------------------------------*/
  1098. #if defined(HAVE_ACL_GET)
  1099.        if (cf->disposition != FILE_NEW)
  1100.           acl_ptr = (DEFCHAR *)acl_get((DEFCHAR *)write_fname);
  1101. #endif
  1102. /*---------------------------------------------------------------------*/
  1103. /* For OS/2, save the current EAs...                                   */
  1104. /*---------------------------------------------------------------------*/
  1105. #if defined(OS2) || (defined(__EMX__) && !defined(MSDOS))
  1106.        if (cf->disposition != FILE_NEW)
  1107.          {
  1108.           if (ReadEAs(write_fname))
  1109.             {
  1110.              display_error(8,write_fname,FALSE);
  1111.              if (bak_filename != (CHARTYPE *)NULL)
  1112.                 (*the_free)(bak_filename);
  1113.              if (write_fname != (CHARTYPE *)NULL)
  1114.                 (*the_free)(write_fname);
  1115. #ifdef TRACE
  1116.              trace_return();
  1117. #endif
  1118.              return(RC_ACCESS_DENIED);
  1119.             }
  1120.          }
  1121. #endif
  1122. /*---------------------------------------------------------------------*/
  1123. /* Rename the current file to filename.bak.                            */
  1124. /*---------------------------------------------------------------------*/
  1125.        if (cf->backup != BACKUP_OFF)
  1126.          {
  1127.           if ((bak_filename =
  1128.              (CHARTYPE *)(*the_malloc)(strlen((DEFCHAR *)cf->fpath)+strlen((DEFCHAR *)cf->fname)+5)) == NULL)
  1129.             {
  1130.              display_error(30,(CHARTYPE *)"",FALSE);
  1131.              if (bak_filename != (CHARTYPE *)NULL)
  1132.                 (*the_free)(bak_filename);
  1133.              if (write_fname != (CHARTYPE *)NULL)
  1134.                 (*the_free)(write_fname);
  1135. #ifdef TRACE
  1136.              trace_return();
  1137. #endif
  1138.              return(RC_OUT_OF_MEMORY);
  1139.             }
  1140.           new_filename(cf->fpath,cf->fname,bak_filename,(CHARTYPE *)".bak");
  1141.           if (cf->fp != NULL)
  1142.             {
  1143.              remove_file(bak_filename);
  1144.              if (rename((DEFCHAR *)write_fname,(DEFCHAR *)bak_filename) != 0)
  1145.                {
  1146.                 display_error(8,write_fname,FALSE);
  1147.                 if (bak_filename != (CHARTYPE *)NULL)
  1148.                    (*the_free)(bak_filename);
  1149.                 if (write_fname != (CHARTYPE *)NULL)
  1150.                    (*the_free)(write_fname);
  1151. #ifdef TRACE
  1152.                 trace_return();
  1153. #endif
  1154.                 return(RC_ACCESS_DENIED);
  1155.                }
  1156.             }
  1157.          }
  1158.       }
  1159.    }
  1160. /*---------------------------------------------------------------------*/
  1161. /* Open the file we are writing to...                                  */
  1162. /*---------------------------------------------------------------------*/
  1163.  if (append == TRUE)
  1164.     fp = fopen((DEFCHAR *)write_fname,"ab");
  1165.  else
  1166.     fp = fopen((DEFCHAR *)write_fname,"wb");
  1167.  if (fp == NULL)
  1168.    {
  1169.     display_error(8,(CHARTYPE *)"could not open for writing",FALSE);
  1170.     if (bak_filename != (CHARTYPE *)NULL)
  1171.        (*the_free)(bak_filename);
  1172.     if (write_fname != (CHARTYPE *)NULL)
  1173.        (*the_free)(write_fname);
  1174. #ifdef TRACE
  1175.     trace_return();
  1176. #endif
  1177.     return(RC_ACCESS_DENIED);
  1178.    }
  1179. /*---------------------------------------------------------------------*/
  1180. /* Determine where to start writing from in the linked list.           */
  1181. /*---------------------------------------------------------------------*/
  1182.  curr = lll_find(cf->first_line,cf->last_line,start_line,cf->number_lines);
  1183. /*---------------------------------------------------------------------*/
  1184. /* Save the setting of scope_all if we are ignoring scope. ie full file*/
  1185. /* is being written...                                                 */
  1186. /*---------------------------------------------------------------------*/
  1187.  if (ignore_scope)
  1188.     CURRENT_VIEW->scope_all = TRUE;
  1189. /*---------------------------------------------------------------------*/
  1190. /* Now write out the contents of the file array to the new filename.   */
  1191. /*---------------------------------------------------------------------*/
  1192.  rc = RC_OK;
  1193.  for (i=0L,num_actual_lines=0L;;i++)
  1194.    {
  1195.     if (lines_based_on_scope)
  1196.       {
  1197.        if (num_actual_lines == abs_num_lines)
  1198.           break;
  1199.       }
  1200.     else
  1201.       {
  1202.        if (abs_num_lines == i)
  1203.           break;
  1204.       }
  1205.     rc = processable_line(CURRENT_VIEW,start_line+(LINETYPE)(i*direction),curr);
  1206.     switch(rc)
  1207.       {
  1208.        case LINE_SHADOW:
  1209.             rc = 0;
  1210.             break;
  1211. /*       case LINE_TOF_EOF: MH12 */
  1212.        case LINE_TOF:
  1213.        case LINE_EOF:
  1214.             rc = 0;
  1215.             num_actual_lines++;
  1216.             break;
  1217.        default:
  1218.             rc = 0;
  1219.             if (cf->tabsout_on)
  1220.               {
  1221.                col = 0;
  1222.                off = (long)start_col;
  1223.                while (1)
  1224.                  {
  1225.                   newcol = col;
  1226.                   while ((c = next_char(curr,&off,end_col+1)) == ' ')
  1227.                     {
  1228.                      newcol++;
  1229.                      if ((newcol % cf->tabsout_num) == 0)
  1230.                        {
  1231.                         if ((rc = write_char((CHARTYPE)'\t',fp)) == RC_DISK_FULL)
  1232.                            break;
  1233.                         col = newcol;
  1234.                        }
  1235.                     }
  1236.                   for (;col<newcol;col++)
  1237.                       if ((rc = write_char((CHARTYPE)' ',fp)) == RC_DISK_FULL)
  1238.                          break;
  1239.                   if (off == (-1L))  /* end of line */
  1240.                      break;
  1241.                   if ((rc = write_char((CHARTYPE)c,fp)) == RC_DISK_FULL)
  1242.                      break;
  1243.                   col++;
  1244.                  }
  1245.                if (rc) break;
  1246.               }
  1247.             else
  1248.               {
  1249.                if (start_col < curr->length)
  1250.                  {
  1251.                   if ((rc = write_line(curr->line+start_col,min(curr->length-start_col,(end_col - start_col) + 1),fp)) == RC_DISK_FULL)
  1252.                      break;
  1253.                  }
  1254.               }
  1255.             if (rc) 
  1256.                break;
  1257.             if ((rc = write_line(eol,eol_len,fp)) == RC_DISK_FULL)
  1258.                break;
  1259.             num_actual_lines++;
  1260.             break;
  1261.       }
  1262. /*---------------------------------------------------------------------*/
  1263. /* Proceed to the next record, even if the current record not in scope.*/
  1264. /*---------------------------------------------------------------------*/
  1265.     if (rc) 
  1266.        break;
  1267.     if (direction == DIRECTION_BACKWARD)
  1268.        curr = curr->prev;
  1269.     else
  1270.        curr = curr->next;
  1271.     my_num_file_lines += (LINETYPE)direction;
  1272.     if (curr == NULL)
  1273.        break;
  1274.    }
  1275.  if (num_file_lines)
  1276.     *num_file_lines = my_num_file_lines;
  1277. /*---------------------------------------------------------------------*/
  1278. /* Restore the setting of scope_all if we changed it before...         */
  1279. /*---------------------------------------------------------------------*/
  1280.  if (ignore_scope)
  1281.     CURRENT_VIEW->scope_all = save_scope_all;
  1282.  
  1283.  anerror = errno;
  1284.  if (fflush(fp) == EOF)
  1285.    {
  1286.     rc = RC_DISK_FULL;
  1287. #if 0
  1288.     clearerr(fp);
  1289. #else
  1290.     rewind(fp);
  1291. #endif
  1292.    }
  1293.  if (fclose(fp) == EOF)
  1294.     rc = RC_DISK_FULL;
  1295.  if (rc)
  1296.     clearerr(fp);
  1297. /*---------------------------------------------------------------------*/
  1298. /* If an error occurred in writing the file (usuallly a result of a    */
  1299. /* disk full error), get the files back to the way they were before    */
  1300. /* this attempt to write them.                                         */
  1301. /*---------------------------------------------------------------------*/
  1302.  if (rc)
  1303.    {
  1304.     /* remove 'new' file (the one that couldn't be written) */
  1305.     remove_file(write_fname);
  1306.     if (same_file)
  1307.       {
  1308.        if (rename((DEFCHAR *)bak_filename,(DEFCHAR *)write_fname) != 0)
  1309.          {
  1310.           display_error(8,write_fname,FALSE);
  1311.           if (bak_filename != (CHARTYPE *)NULL)
  1312.              (*the_free)(bak_filename);
  1313.           if (write_fname != (CHARTYPE *)NULL)
  1314.              (*the_free)(write_fname);
  1315. #ifdef TRACE
  1316.           trace_return();
  1317. #endif
  1318.           return(RC_ACCESS_DENIED);
  1319.          }
  1320.       }
  1321.    }
  1322.  else
  1323.    {
  1324.     if (same_file)
  1325.       {
  1326.        if (cf->fmode != 0)
  1327.           chmod((DEFCHAR *)write_fname,cf->fmode);
  1328. #ifdef HAVE_CHOWN
  1329.        if (cf->disposition != FILE_NEW)
  1330.          {
  1331.           if (chown((DEFCHAR *)write_fname,cf->uid,cf->gid))
  1332.             {
  1333.              display_error(84,(CHARTYPE *)"ownerships",FALSE);
  1334.             }
  1335.          }
  1336. #endif
  1337. /*---------------------------------------------------------------------*/
  1338. /* For HPUX, write the current ACL...                                  */
  1339. /*---------------------------------------------------------------------*/
  1340. #if defined(HAVE_GETACL)
  1341.        if (acl_entries != 0)
  1342.          {
  1343.           if (setacl((DEFCHAR *)write_fname,acl_entries,file_acl))
  1344.             {
  1345.              display_error(84,(CHARTYPE *)"ACLs",FALSE);
  1346.             }
  1347.          }
  1348. #endif
  1349. /*---------------------------------------------------------------------*/
  1350. /* For AIX,  write the current ACL...                                  */
  1351. /*---------------------------------------------------------------------*/
  1352. #if defined(HAVE_ACL_GET)
  1353.        if (cf->disposition != FILE_NEW)
  1354.          {
  1355.           if (acl_put((DEFCHAR *)write_fname,acl_ptr,1))
  1356.              display_error(84,(CHARTYPE *)"ACLs",FALSE);
  1357.          }
  1358. #endif
  1359. /*---------------------------------------------------------------------*/
  1360. /* For OS/2, write the current EAs...                                  */
  1361. /*---------------------------------------------------------------------*/
  1362. #if defined(OS2) || (defined(__EMX__) && !defined(MSDOS))
  1363.        if (cf->disposition != FILE_NEW)
  1364.          {
  1365.           if (WriteEAs(write_fname))
  1366.             {
  1367.              display_error(84,(CHARTYPE *)"EAs",FALSE);
  1368.             }
  1369.          }
  1370. #endif
  1371.       }
  1372. /*---------------------------------------------------------------------*/
  1373. /* If a backup file is not to be kept, remove the backup file provided */
  1374. /* that there hasn't been a problem in writing the file.               */
  1375. /*---------------------------------------------------------------------*/
  1376.     if (cf->backup == BACKUP_TEMP)
  1377.        remove_file(bak_filename);
  1378. /*---------------------------------------------------------------------*/
  1379. /* If a new filename was not supplied, free up temporary memory.       */
  1380. /*---------------------------------------------------------------------*/
  1381.    }
  1382.  if (bak_filename != (CHARTYPE *)NULL)
  1383.     (*the_free)(bak_filename);
  1384.  if (write_fname != (CHARTYPE *)NULL)
  1385.     (*the_free)(write_fname);
  1386.  
  1387. #ifdef TRACE
  1388.  trace_return();
  1389. #endif
  1390.  return(rc);
  1391. }
  1392. /***********************************************************************/
  1393. #ifdef HAVE_PROTO
  1394. static short write_char(CHARTYPE chr,FILE *fp)
  1395. #else
  1396. static short write_char(chr,fp)
  1397. CHARTYPE chr;
  1398. FILE *fp;
  1399. #endif
  1400. /***********************************************************************/
  1401. {
  1402. /*--------------------------- local data ------------------------------*/
  1403. /*--------------------------- processing ------------------------------*/
  1404.  if (fputc(chr,fp) == chr
  1405.  && ferror(fp) == 0)
  1406.     return(RC_OK);
  1407.  clearerr(fp);
  1408.  display_error(57,(CHARTYPE *)"",FALSE);
  1409.  return(RC_DISK_FULL);
  1410. }
  1411. /***********************************************************************/
  1412. #ifdef HAVE_PROTO
  1413. static short write_line(CHARTYPE *line,LENGTHTYPE len,FILE *fp)
  1414. #else
  1415. static short write_line(line,len,fp)
  1416. CHARTYPE *line;
  1417. LENGTHTYPE len;
  1418. FILE *fp;
  1419. #endif
  1420. /***********************************************************************/
  1421. {
  1422. /*--------------------------- local data ------------------------------*/
  1423. /*--------------------------- processing ------------------------------*/
  1424.  if (fwrite(line,sizeof(CHARTYPE),len,fp) == len)
  1425.     return(RC_OK);
  1426.  display_error(57,(CHARTYPE *)"",FALSE);
  1427.  return(RC_DISK_FULL);
  1428. }
  1429. /***********************************************************************/
  1430. #ifdef HAVE_PROTO
  1431. void increment_alt(FILE_DETAILS *cf)
  1432. #else
  1433. void increment_alt(cf)
  1434. FILE_DETAILS *cf;
  1435. #endif
  1436. /***********************************************************************/
  1437. {
  1438. /*--------------------------- local data ------------------------------*/
  1439. /*--------------------------- processing ------------------------------*/
  1440. #ifdef TRACE
  1441.  trace_function("file.c:    increment_alt");
  1442. #endif
  1443.  cf->autosave_alt++;
  1444.  cf->save_alt++;
  1445. /*---------------------------------------------------------------------*/
  1446. /* We can now test for autosave_alt exceeding the defined limit and    */
  1447. /* carry out an autosave if necessary.                                 */
  1448. /*---------------------------------------------------------------------*/
  1449.  if (cf->autosave != 0
  1450.  &&  cf->autosave_alt >= cf->autosave
  1451.  &&  cf->autosave_fname)
  1452.    {
  1453.     if (save_file(cf,cf->autosave_fname,TRUE,cf->number_lines,1L,NULL,FALSE,0,max_line_length,TRUE,FALSE) == RC_OK)
  1454.        cf->autosave_alt = 0;
  1455.    }
  1456. #ifdef TRACE
  1457.  trace_return();
  1458. #endif
  1459.  return;
  1460. }
  1461. /***********************************************************************/
  1462. #ifdef HAVE_PROTO
  1463. CHARTYPE *new_filename(CHARTYPE *ofp,CHARTYPE *ofn,
  1464.                             CHARTYPE *nfn,CHARTYPE *ext)
  1465. #else
  1466. CHARTYPE *new_filename(ofp,ofn,nfn,ext)
  1467. CHARTYPE *ofp,*ofn,*nfn,*ext;
  1468. #endif
  1469. /***********************************************************************/
  1470. {
  1471. /*--------------------------- local data ------------------------------*/
  1472. #if defined(DOS) || defined(OS2)
  1473.  short rc=RC_OK;
  1474. #endif
  1475. /*--------------------------- processing ------------------------------*/
  1476. #ifdef TRACE
  1477.  trace_function("file.c:    new_filename");
  1478. #endif
  1479.  strcpy((DEFCHAR *)nfn,(DEFCHAR *)ofp);
  1480.  strcat((DEFCHAR *)nfn,(DEFCHAR *)ofn);
  1481.  
  1482. #ifdef DOS
  1483.  rc = strzeq(nfn,'.');
  1484.  if (rc != (-1))
  1485.     *(nfn+rc) = '\0';
  1486. #endif
  1487.  
  1488. #if defined(OS2) || (defined(__EMX__) && !defined(MSDOS))
  1489.  /*if (!LongFileNames(nfn))*/ /* old style */
  1490.  if (!IsPathAndFilenameValid(nfn))
  1491.    {
  1492.     rc = strzreveq(nfn,'.');
  1493.     if (rc != (-1))
  1494.        *(nfn+rc) = '\0';
  1495.    }
  1496. #endif
  1497.  
  1498.  strcat((DEFCHAR *)nfn,(DEFCHAR *)ext);
  1499. #ifdef TRACE
  1500.  trace_return();
  1501. #endif
  1502.  return(nfn);
  1503. }
  1504. /***********************************************************************/
  1505. #ifdef HAVE_PROTO
  1506. short remove_aus_file(FILE_DETAILS *cf)
  1507. #else
  1508. short remove_aus_file(cf)
  1509. FILE_DETAILS *cf;
  1510. #endif
  1511. /***********************************************************************/
  1512. {
  1513. /*--------------------------- local data ------------------------------*/
  1514.  CHARTYPE *aus_filename=NULL;
  1515. /*--------------------------- processing ------------------------------*/
  1516. #ifdef TRACE
  1517.  trace_function("file.c:    remove_aus_file");
  1518. #endif
  1519.  if ((aus_filename =
  1520.     (CHARTYPE *)(*the_malloc)(strlen((DEFCHAR *)cf->fpath)+strlen((DEFCHAR *)cf->fname)+5)) == NULL)
  1521.    {
  1522.     display_error(30,(CHARTYPE *)"",FALSE);
  1523. #ifdef TRACE
  1524.     trace_return();
  1525. #endif
  1526.     return(RC_OUT_OF_MEMORY);
  1527.    }
  1528.  new_filename(cf->fpath,cf->fname,aus_filename,(CHARTYPE *)".aus");
  1529.  remove_file(aus_filename);
  1530.  (*the_free)(aus_filename);
  1531. #ifdef TRACE
  1532.  trace_return();
  1533. #endif
  1534.  return(RC_OK);
  1535. }
  1536. /***********************************************************************/
  1537. #ifdef HAVE_PROTO
  1538. short free_view_memory(bool free_file_lines,bool display_the_screen)
  1539. #else
  1540. short free_view_memory(free_file_lines,display_the_screen)
  1541. bool free_file_lines;
  1542. bool display_the_screen;
  1543. #endif
  1544. /***********************************************************************/
  1545. {
  1546. /*-------------------------- external data ----------------------------*/
  1547.  extern bool curses_started;
  1548.  extern CHARTYPE number_of_views;
  1549.  extern CHARTYPE display_screens;
  1550.  extern CHARTYPE number_of_files;
  1551. /*--------------------------- local data ------------------------------*/
  1552.  VIEW_DETAILS *save_current_view=NULL;
  1553.  CHARTYPE save_current_screen=0;
  1554.  short rc=RC_OK;
  1555.  int y=0,x=0;
  1556.  int scenario=0;
  1557.  ROWTYPE save_cmd_line=0;
  1558.  CHARTYPE save_prefix=0;
  1559.  short save_gap=0;
  1560. /*--------------------------- processing ------------------------------*/
  1561. #ifdef TRACE
  1562.  trace_function("file.c:    free_view_memory");
  1563. #endif
  1564. /*---------------------------------------------------------------------*/
  1565. /* Before freeing up anything, determine which scenario is current...  */
  1566. /*---------------------------------------------------------------------*/
  1567.  if (display_screens > 1)
  1568.    {
  1569.     if (CURRENT_SCREEN.screen_view->file_for_view
  1570.         == OTHER_SCREEN.screen_view->file_for_view)
  1571.       {
  1572.        if (number_of_files > 1)
  1573.           scenario = 2;
  1574.        else
  1575.           scenario = 3;
  1576.       }
  1577.     else
  1578.        scenario = 4;
  1579.    }
  1580.  else
  1581.    {
  1582.     if (number_of_files > 1)
  1583.        scenario = 1;
  1584.     else
  1585.        scenario = 0;
  1586.    }
  1587. /*---------------------------------------------------------------------*/
  1588. /* Save details of the current view's prefix and cmd_line settings so  */
  1589. /* that if the new view has different settings we can adjust the size  */
  1590. /* and/or position of the new view's windows.                          */
  1591. /*---------------------------------------------------------------------*/
  1592.  save_prefix = CURRENT_VIEW->prefix;
  1593.  save_gap = CURRENT_VIEW->prefix_gap;
  1594.  save_cmd_line = CURRENT_VIEW->cmd_line;
  1595. /*---------------------------------------------------------------------*/
  1596. /* Free the view and the memory for the file if this is the last view  */
  1597. /* for that file...                                                    */
  1598. /*---------------------------------------------------------------------*/
  1599.  if (--CURRENT_FILE->file_views == 0)
  1600.     free_file_memory(free_file_lines);
  1601.  free_a_view();
  1602.  
  1603.  switch(scenario)
  1604.    {
  1605.     case 0:
  1606.          /*
  1607.           *----------------------------------------------------------
  1608.           * +---+---+
  1609.           * |   a   |
  1610.           * |       | --> exit
  1611.           * |qq     |
  1612.           * +---+---+
  1613.           * display_screens = 1 & number_of_files = 1 & same views
  1614.           * (scenario 0)
  1615.           *----------------------------------------------------------
  1616.           */
  1617.          break;
  1618.     case 1:
  1619.          /*
  1620.           *----------------------------------------------------------
  1621.           * +---+---+     +---+---+
  1622.           * |   a   |  b  |   b   |
  1623.           * |       | --> |       |
  1624.           * |qq     |     |       |
  1625.           * +---+---+     +---+---+
  1626.           * display_screens = 1 & number_of_files > 1 & same views
  1627.           * (scenario 1)
  1628.           *----------------------------------------------------------
  1629.           */
  1630.          if ((save_prefix&PREFIX_LOCATION_MASK) != (CURRENT_VIEW->prefix&PREFIX_LOCATION_MASK)
  1631.          ||  save_gap != CURRENT_VIEW->prefix_gap
  1632.          ||  save_cmd_line != CURRENT_VIEW->cmd_line)
  1633.            {
  1634.             set_screen_defaults();
  1635.             if (curses_started)
  1636.               {
  1637.                if (set_up_windows(current_screen) != RC_OK)
  1638.                  {
  1639. #ifdef TRACE
  1640.                   trace_return();
  1641. #endif
  1642.                   return(RC_OK);
  1643.                  }
  1644.               }
  1645.            }
  1646.          break;
  1647.     case 2:
  1648.          /*
  1649.           *----------------------------------------------------------
  1650.           * +---+---+     +---+---+       +---+---+     +---+---+
  1651.           * | a | a |  b  | b | b |   or  | a | a | b c | b | b |
  1652.           * |   |   | --> |   |   |       |   |   |     |   |   |
  1653.           * |   |qq |     |   |   |       |   |qq |     |   |   |
  1654.           * +---+---+     +---+---+       +---+---+     +---+---+
  1655.           * display_screens > 1 & number_of_files > 1 & same views
  1656.           * (scenario 2)
  1657.           *----------------------------------------------------------
  1658.           * At this point the view associated with the "current" screen
  1659.           * has been deleted. vd_current now points to the "next" view.
  1660.           * We need to point vd_current at the view in OTHER_SCREEN so
  1661.           * it can be deleted properly.
  1662.           *----------------------------------------------------------
  1663.           */
  1664.          CURRENT_VIEW = OTHER_VIEW;
  1665.          free_file_memory(free_file_lines);
  1666.          free_a_view();
  1667.          save_current_screen = current_screen;
  1668.          save_current_view = CURRENT_VIEW;
  1669.          current_screen = (current_screen==0)?1:0; /* make other screen current */
  1670.          if ((rc = defaults_for_other_files(PREVIOUS_VIEW)) != RC_OK)
  1671.            {
  1672. #ifdef TRACE
  1673.             trace_return();
  1674. #endif
  1675.             return(rc);
  1676.            }
  1677.          CURRENT_FILE = save_current_view->file_for_view;
  1678.          CURRENT_FILE->file_views++;
  1679.          CURRENT_SCREEN.screen_view = CURRENT_VIEW;
  1680.          CURRENT_VIEW = save_current_view;
  1681.          current_screen = save_current_screen;
  1682.          set_screen_defaults();
  1683.          if (curses_started)
  1684.            {
  1685.             if ((rc = set_up_windows(other_screen)) != RC_OK)
  1686.               {
  1687. #ifdef TRACE
  1688.                trace_return();
  1689. #endif
  1690.                return(rc);
  1691.               }
  1692.             if ((rc = set_up_windows(current_screen)) != RC_OK)
  1693.               {
  1694. #ifdef TRACE
  1695.                trace_return();
  1696. #endif
  1697.                return(rc);
  1698.               }
  1699.            }
  1700.          pre_process_line(OTHER_SCREEN.screen_view,OTHER_SCREEN.screen_view->focus_line,(LINE *)NULL);
  1701.          prepare_view(other_screen);
  1702.          if (display_the_screen)
  1703.             display_screen(other_screen);
  1704.          break;
  1705.     case 3:
  1706.          /*
  1707.           *----------------------------------------------------------
  1708.           * +---+---+
  1709.           * | a | a |
  1710.           * |   |   | --> exit
  1711.           * |   |qq |
  1712.           * +---+---+
  1713.           * display_screens > 1 & number_of_files = 1 & same views
  1714.           * (scenario 3)
  1715.           *----------------------------------------------------------
  1716.           */
  1717.          CURRENT_FILE->file_views--;
  1718.          free_file_memory(free_file_lines);
  1719.          free_a_view();
  1720.          break;
  1721.     case 4:
  1722.          /*
  1723.           *----------------------------------------------------------
  1724.           * +---+---+     +---+---+       +---+---+     +---+---+
  1725.           * | a | b |     | a | a |   or  | a | b |  c  | a | a |
  1726.           * |   |   | --> |   |   |       |   |   |     |   |   |
  1727.           * |   |qq |     |   |   |       |   |qq |     |   |   |
  1728.           * +---+---+     +---+---+       +---+---+     +---+---+
  1729.           * display_screens > 1 & number_of_files > 1 & diff views
  1730.           * (scenario 4)
  1731.           *----------------------------------------------------------
  1732.           */
  1733.          if ((rc = defaults_for_other_files(OTHER_VIEW)) != RC_OK)
  1734.            {
  1735. #ifdef TRACE
  1736.             trace_return();
  1737. #endif
  1738.             return(rc);
  1739.            }
  1740.          CURRENT_SCREEN.screen_view = CURRENT_VIEW;
  1741.          CURRENT_FILE = OTHER_SCREEN.screen_view->file_for_view;
  1742.          CURRENT_FILE->file_views++;
  1743.          set_screen_defaults();
  1744.          if ((rc = set_up_windows(current_screen)) != RC_OK)
  1745.            {
  1746. #ifdef TRACE
  1747.             trace_return();
  1748. #endif
  1749.             return(rc);
  1750.            }
  1751.          break;
  1752.     default:
  1753.          break;
  1754.    }
  1755. /*---------------------------------------------------------------------*/
  1756. /* If we still have at least one view, display the it.                 */
  1757. /*---------------------------------------------------------------------*/
  1758.  if (number_of_views > 0)
  1759.    {
  1760.     pre_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line,(LINE *)NULL);
  1761.     prepare_view(current_screen);
  1762.     if (display_the_screen)
  1763.        display_screen(current_screen);
  1764.     if (curses_started)
  1765.       {
  1766.        wmove(CURRENT_WINDOW_FILEAREA,CURRENT_VIEW->y[WINDOW_FILEAREA],CURRENT_VIEW->x[WINDOW_FILEAREA]);
  1767.        if (CURRENT_WINDOW_PREFIX != NULL)
  1768.           wmove(CURRENT_WINDOW_PREFIX,CURRENT_VIEW->y[WINDOW_PREFIX],CURRENT_VIEW->x[WINDOW_PREFIX]);
  1769.        getyx(CURRENT_WINDOW,y,x);
  1770.        wmove(CURRENT_WINDOW,y,x);
  1771.       }
  1772.    }
  1773. #ifdef TRACE
  1774.  trace_return();
  1775. #endif
  1776.  return(RC_OK);
  1777. }
  1778. /***********************************************************************/
  1779. #ifdef HAVE_PROTO
  1780. void free_a_view(void)
  1781. #else
  1782. void free_a_view()
  1783. #endif
  1784. /***********************************************************************/
  1785. {
  1786. /*-------------------------- external data ----------------------------*/
  1787.  extern CHARTYPE number_of_views;
  1788.  extern VIEW_DETAILS *vd_first;
  1789.  extern VIEW_DETAILS *vd_last;
  1790.  extern VIEW_DETAILS *vd_mark;
  1791. /*--------------------------- local data ------------------------------*/
  1792. /*--------------------------- processing ------------------------------*/
  1793. #ifdef TRACE
  1794.  trace_function("file.c:    free_a_view");
  1795. #endif
  1796. /*---------------------------------------------------------------------*/
  1797. /* If the marked block is within the current view, unset the variables.*/
  1798. /*---------------------------------------------------------------------*/
  1799.  if (MARK_VIEW == CURRENT_VIEW)
  1800.     MARK_VIEW = (VIEW_DETAILS *)NULL;
  1801.  if (CURRENT_VIEW->preserved_view_details)
  1802.    (*the_free)(CURRENT_VIEW->preserved_view_details);
  1803.  CURRENT_VIEW = vll_del(&vd_first,&vd_last,CURRENT_VIEW,DIRECTION_BACKWARD);
  1804.  CURRENT_SCREEN.screen_view = CURRENT_VIEW;
  1805.  
  1806.  number_of_views--;
  1807.  return;
  1808. }
  1809. /***********************************************************************/
  1810. #ifdef HAVE_PROTO
  1811. short free_file_memory(bool free_file_lines)
  1812. #else
  1813. short free_file_memory(free_file_lines)
  1814. bool free_file_lines;
  1815. #endif
  1816. /***********************************************************************/
  1817. {
  1818. /*-------------------------- external data ----------------------------*/
  1819.  extern LINE *rexxout_first_line;
  1820.  extern LINE *rexxout_last_line;
  1821.  extern LINE *key_first_line;
  1822.  extern LINE *key_last_line;
  1823.  extern CHARTYPE number_of_files;
  1824. /*--------------------------- local data ------------------------------*/
  1825. /*--------------------------- processing ------------------------------*/
  1826. #ifdef TRACE
  1827.  trace_function("file.c:    free_file_memory");
  1828. #endif
  1829. /*---------------------------------------------------------------------*/
  1830. /* If the file name is not NULL, free it...                            */
  1831. /*---------------------------------------------------------------------*/
  1832.  if (CURRENT_FILE->fname != NULL)
  1833.    {
  1834.     (*the_free)(CURRENT_FILE->fname);
  1835.     CURRENT_FILE->fname = (CHARTYPE *)NULL;
  1836.    }
  1837. /*---------------------------------------------------------------------*/
  1838. /* If the actual file name is not NULL, free it...                     */
  1839. /*---------------------------------------------------------------------*/
  1840.  if (CURRENT_FILE->actualfname != NULL)
  1841.    {
  1842.     (*the_free)(CURRENT_FILE->actualfname);
  1843.     CURRENT_FILE->actualfname = (CHARTYPE *)NULL;
  1844.    }
  1845. /*---------------------------------------------------------------------*/
  1846. /* If the file path is not NULL, free it...                            */
  1847. /*---------------------------------------------------------------------*/
  1848.  if (CURRENT_FILE->fpath != NULL)
  1849.    {
  1850.     (*the_free)(CURRENT_FILE->fpath);
  1851.     CURRENT_FILE->fpath = (CHARTYPE *)NULL;
  1852.    }
  1853. /*---------------------------------------------------------------------*/
  1854. /* If the autosave file name is not NULL, free it...                   */
  1855. /*---------------------------------------------------------------------*/
  1856.  if (CURRENT_FILE->autosave_fname != NULL)
  1857.    {
  1858.     (*the_free)(CURRENT_FILE->autosave_fname);
  1859.     CURRENT_FILE->autosave_fname = (CHARTYPE *)NULL;
  1860.    }
  1861. /*---------------------------------------------------------------------*/
  1862. /* If the file display attributes is not NULL, free it...              */
  1863. /*---------------------------------------------------------------------*/
  1864.  if (CURRENT_FILE->attr != NULL)
  1865.    {
  1866.     (*the_free)(CURRENT_FILE->attr);
  1867.     CURRENT_FILE->attr = (COLOUR_ATTR *)NULL;
  1868.    }
  1869. /*---------------------------------------------------------------------*/
  1870. /* Free the linked list of all lines in the file...                    */
  1871. /*---------------------------------------------------------------------*/
  1872.  if (free_file_lines)
  1873.    {
  1874.     CURRENT_FILE->first_line = CURRENT_FILE->last_line = lll_free(CURRENT_FILE->first_line);
  1875.     switch(CURRENT_FILE->pseudo_file)
  1876.       {
  1877.        case PSEUDO_DIR:
  1878.             dir_first_line = dir_last_line = NULL;
  1879.             break;
  1880.        case PSEUDO_REXX:
  1881.             rexxout_first_line = rexxout_last_line = NULL;
  1882.             break;
  1883.        case PSEUDO_KEY:
  1884.             key_first_line = key_last_line = NULL;
  1885.             break;
  1886.        default:
  1887.             break;
  1888.       }
  1889.    }
  1890. /*---------------------------------------------------------------------*/
  1891. /* Free the linked list of all pending prefix commands...              */
  1892. /*---------------------------------------------------------------------*/
  1893.  pll_free(CURRENT_FILE->first_ppc);
  1894. /*---------------------------------------------------------------------*/
  1895. /* Free the linked list of reserved lines...                           */
  1896. /*---------------------------------------------------------------------*/
  1897.  rll_free(CURRENT_FILE->first_reserved);
  1898. /*---------------------------------------------------------------------*/
  1899. /* Free the linked list of EDITV variables...                          */
  1900. /*---------------------------------------------------------------------*/
  1901.  lll_free(CURRENT_FILE->editv);
  1902. /*---------------------------------------------------------------------*/
  1903. /* Free the preserved file details (if any)                            */
  1904. /*---------------------------------------------------------------------*/
  1905.  if (CURRENT_FILE->preserved_file_details)
  1906.    {
  1907.     (*the_free)(CURRENT_FILE->preserved_file_details);
  1908.     CURRENT_FILE->preserved_file_details = NULL;
  1909.    }
  1910. /*---------------------------------------------------------------------*/
  1911. /* Free the FILE_DETAILS structure...                                  */
  1912. /*---------------------------------------------------------------------*/
  1913.  if (CURRENT_FILE != NULL)
  1914.    {
  1915.     (*the_free)(CURRENT_FILE);
  1916.     CURRENT_FILE = (FILE_DETAILS *)NULL;
  1917.    }
  1918.  number_of_files--;
  1919. #ifdef TRACE
  1920.  trace_return();
  1921. #endif
  1922.  return(RC_OK);
  1923. }
  1924. /***********************************************************************/
  1925. #ifdef HAVE_PROTO
  1926. short read_directory(void)
  1927. #else
  1928. short read_directory()
  1929. #endif
  1930. /***********************************************************************/
  1931. {
  1932. /*-------------------------- external data ----------------------------*/
  1933. #if !defined(MULTIPLE_PSEUDO_FILES)
  1934.  extern CHARTYPE dir_filename[10];
  1935.  extern CHARTYPE dir_pathname[MAX_FILE_NAME+1];
  1936. #endif
  1937.  extern CHARTYPE dir_path[MAX_FILE_NAME+1];
  1938.  extern CHARTYPE dir_files[MAX_FILE_NAME+1];
  1939.  extern CHARTYPE sp_path[MAX_FILE_NAME+1];
  1940.  extern CHARTYPE sp_fname[MAX_FILE_NAME+1];
  1941.  extern int DEFSORTx;
  1942. /*--------------------------- local data ------------------------------*/
  1943.  struct dirfile *dpfirst=NULL,*dplast=NULL,*dp;
  1944.  CHARTYPE str_attr[12];
  1945.  CHARTYPE str_date[12];
  1946.  CHARTYPE str_time[6];
  1947.  VIEW_DETAILS *found_view=NULL;
  1948.  short rc=RC_OK;
  1949.  LINE *curr=NULL;
  1950.  CHARTYPE dir_rec[MAX_FILE_NAME+50];
  1951. /*--------------------------- processing ------------------------------*/
  1952. #ifdef TRACE
  1953.  trace_function("file.c:    read_directory");
  1954. #endif
  1955. /*---------------------------------------------------------------------*/
  1956. /* Get all file info for the selected files into structure. If no file */
  1957. /* name specified, force it to '*'.                                    */
  1958. /*---------------------------------------------------------------------*/
  1959.  if (strcmp((DEFCHAR *)sp_fname,"") == 0)
  1960.     rc = getfiles(sp_path,(CHARTYPE *)"*",&dpfirst,&dplast);
  1961.  else
  1962.     rc = getfiles(sp_path,sp_fname,&dpfirst,&dplast);
  1963.  if (rc != RC_OK)
  1964.    {
  1965.     display_error(rc,sp_path,FALSE);
  1966. #ifdef TRACE
  1967.     trace_return();
  1968. #endif
  1969.     return(RC_FILE_NOT_FOUND);
  1970.    }
  1971.  if (dpfirst == dplast)
  1972.    {
  1973. #ifdef TRACE
  1974.     trace_return();
  1975. #endif
  1976.     return(RC_FILE_NOT_FOUND);
  1977.    }
  1978. /*---------------------------------------------------------------------*/
  1979. /* dir_path is set up here so that subsequent sos_edit commands can use*/
  1980. /* the directory path as a prefix to the edit files filename.          */
  1981. /*---------------------------------------------------------------------*/
  1982.  strcpy((DEFCHAR *)dir_path,(DEFCHAR *)sp_path);
  1983.  strcpy((DEFCHAR *)dir_files,(DEFCHAR *)sp_fname);
  1984. /*---------------------------------------------------------------------*/
  1985. /* sort the array of file structures.                                  */
  1986. /*---------------------------------------------------------------------*/
  1987.  switch(DEFSORTx)
  1988.    {
  1989.     case DIRSORT_DATE:
  1990.          qsort(dpfirst,dplast - dpfirst,sizeof(struct dirfile),date_comp);
  1991.          break;
  1992.     case DIRSORT_TIME:
  1993.          qsort(dpfirst,dplast - dpfirst,sizeof(struct dirfile),time_comp);
  1994.          break;
  1995.     case DIRSORT_NAME:
  1996.          qsort(dpfirst,dplast - dpfirst,sizeof(struct dirfile),name_comp);
  1997.          break;
  1998.     case DIRSORT_SIZE:
  1999.          qsort(dpfirst,dplast - dpfirst,sizeof(struct dirfile),size_comp);
  2000.          break;
  2001.     case DIRSORT_DIR:
  2002.          qsort(dpfirst,dplast - dpfirst,sizeof(struct dirfile),dir_comp);
  2003.          break;
  2004.     default:                              /* DIRSORT_NONE - no sorting */
  2005.          break;
  2006.    }
  2007. #if !defined(MULTIPLE_PSEUDO_FILES)
  2008. /*---------------------------------------------------------------------*/
  2009. /* Free up the existing linked list (if any)                           */
  2010. /*---------------------------------------------------------------------*/
  2011.  dir_first_line = dir_last_line = lll_free(dir_first_line);
  2012.  dir_number_lines = 0L;
  2013.  if ((found_view = find_file(dir_pathname,dir_filename)) != (VIEW_DETAILS *)NULL)
  2014.    {
  2015.     found_view->file_for_view->first_line = found_view->file_for_view->last_line = NULL;
  2016.     found_view->file_for_view->number_lines = 0L;
  2017.    }
  2018. #endif
  2019. /*---------------------------------------------------------------------*/
  2020. /* first_line is set to "Top of File"                                  */
  2021. /*---------------------------------------------------------------------*/
  2022.  if ((dir_first_line = add_line(dir_first_line,NULL,TOP_OF_FILE,
  2023.      strlen((DEFCHAR *)TOP_OF_FILE),0,FALSE)) == NULL)
  2024.    {
  2025. #ifdef TRACE
  2026.     trace_return();
  2027. #endif
  2028.     return(RC_OUT_OF_MEMORY);
  2029.    }
  2030. /*---------------------------------------------------------------------*/
  2031. /* last line is set to "Bottom of File"                                */
  2032. /*---------------------------------------------------------------------*/
  2033.  if ((dir_last_line = add_line(dir_first_line,dir_first_line,BOTTOM_OF_FILE,
  2034.      strlen((DEFCHAR *)BOTTOM_OF_FILE),0,FALSE)) == NULL)
  2035.    {
  2036. #ifdef TRACE
  2037.     trace_return();
  2038. #endif
  2039.     return(RC_OUT_OF_MEMORY);
  2040.    }
  2041.  curr = dir_first_line;
  2042. /*---------------------------------------------------------------------*/
  2043. /* write out the formatted contents of the file structures.            */
  2044. /*---------------------------------------------------------------------*/
  2045.  for (dp=dpfirst;dp<dplast;dp++,dir_number_lines++)
  2046.     {
  2047.      if (dp->lname != NULL)
  2048.         sprintf((DEFCHAR *)dir_rec,"%s%8ld %s %s %s -> %s",
  2049.                 file_attrs(dp->fattr,str_attr,dp->facl),
  2050.                 dp->fsize,
  2051.                 file_date(dp,str_date),
  2052.                 file_time(dp,str_time),
  2053.                 dp->fname,
  2054.                 dp->lname);
  2055.      else
  2056.         sprintf((DEFCHAR *)dir_rec,"%s%8ld %s %s %s",
  2057.                 file_attrs(dp->fattr,str_attr,dp->facl),
  2058.                 dp->fsize,
  2059.                 file_date(dp,str_date),
  2060.                 file_time(dp,str_time),
  2061.                 dp->fname);
  2062.      if ((curr = add_line(dir_first_line,curr,dir_rec,strlen((DEFCHAR *)dir_rec),0,FALSE)) == NULL)
  2063.        {
  2064. #ifdef TRACE
  2065.         trace_return();
  2066. #endif
  2067.         return(RC_OUT_OF_MEMORY);
  2068.        }
  2069. #if FILENAME_LENGTH
  2070.      /*
  2071.       * Set the filename length here for all files...
  2072.       */
  2073.      curr->filename_length = dp->fname_length;
  2074. #endif
  2075.      (*the_free)(dp->fname);
  2076.     }
  2077.  (*the_free)(dpfirst);
  2078.  
  2079. #ifdef TRACE
  2080.  trace_return();
  2081. #endif
  2082.  return(RC_OK);
  2083. }
  2084. /***********************************************************************/
  2085. #ifdef HAVE_PROTO
  2086. VIEW_DETAILS *find_file(CHARTYPE *fp,CHARTYPE *fn)
  2087. #else
  2088. VIEW_DETAILS *find_file(fp,fn)
  2089. CHARTYPE *fp,*fn;
  2090. #endif
  2091. /***********************************************************************/
  2092. {
  2093. /*-------------------------- external data ----------------------------*/
  2094.  extern VIEW_DETAILS *vd_first;
  2095. /*--------------------------- local data ------------------------------*/
  2096.  VIEW_DETAILS *save_current_view=NULL,*found_file=NULL;
  2097. /*--------------------------- processing ------------------------------*/
  2098. #ifdef TRACE
  2099.  trace_function("file.c:    find_file");
  2100. #endif
  2101.  save_current_view = CURRENT_VIEW;
  2102.  CURRENT_VIEW = vd_first;
  2103.  while(CURRENT_VIEW != (VIEW_DETAILS *)NULL)
  2104.    {
  2105. #ifdef UNIX
  2106.     if (strcmp((DEFCHAR *)CURRENT_FILE->fname,(DEFCHAR *)fn) == 0
  2107.     &&  strcmp((DEFCHAR *)CURRENT_FILE->fpath,(DEFCHAR *)fp) == 0)
  2108. #else
  2109.     if (stricmp(CURRENT_FILE->fname,fn) == 0
  2110.     &&  stricmp(CURRENT_FILE->fpath,fp) == 0)
  2111. #endif
  2112.       {
  2113. #ifdef TRACE
  2114.        trace_return();
  2115. #endif
  2116.        found_file = CURRENT_VIEW;
  2117.        CURRENT_VIEW = save_current_view;
  2118.        return(found_file);
  2119.       }
  2120.     CURRENT_VIEW = CURRENT_VIEW->next;
  2121.    }
  2122. #ifdef TRACE
  2123.  trace_return();
  2124. #endif
  2125.  CURRENT_VIEW = save_current_view;
  2126.  return((VIEW_DETAILS *)NULL);
  2127. }
  2128. /***********************************************************************/
  2129. #ifdef HAVE_PROTO
  2130. short execute_command_file(FILE *fp)
  2131. #else
  2132. short execute_command_file(fp)
  2133. FILE *fp;
  2134. #endif
  2135. /***********************************************************************/
  2136. {
  2137. /*-------------------------- external data ----------------------------*/
  2138.  extern CHARTYPE number_of_files;
  2139.  extern CHARTYPE *profile_command_line;
  2140. /*--------------------------- local data ------------------------------*/
  2141.  register short i=0;
  2142.  CHARTYPE ch=0;
  2143.  short rc=RC_OK;
  2144.  short line_number=0;
  2145. /*--------------------------- processing ------------------------------*/
  2146. #ifdef TRACE
  2147.  trace_function("file.c:    execute_command_file");
  2148. #endif
  2149.  
  2150.  memset(profile_command_line,' ',MAX_LENGTH_OF_LINE);
  2151.  i = 0;
  2152.  while(1)
  2153.   {
  2154.    ch = fgetc(fp);
  2155.    if (feof(fp))
  2156.       break;
  2157.    if (ch == '\n')
  2158.      {
  2159.       line_number++;
  2160.       profile_command_line[i] = '\0';
  2161.       rc = process_command_line(profile_command_line,line_number);
  2162.       if (rc == RC_SYSTEM_ERROR
  2163.       ||  rc == RC_NOREXX_ERROR)
  2164.          break;
  2165.       if (number_of_files == 0)
  2166.          break;
  2167.       i = 0;
  2168.       memset(profile_command_line,' ',MAX_LENGTH_OF_LINE);
  2169.       continue;
  2170.      }
  2171.    if (ch == '\r')
  2172.      {
  2173.       profile_command_line[i] = ch;
  2174.       i++;
  2175.       ch = fgetc(fp);
  2176.       if (feof(fp))
  2177.          break;
  2178.       if (ch == '\n')
  2179.         {
  2180.          --i;
  2181.          line_number++;
  2182.          profile_command_line[i] = '\0';
  2183.          rc = process_command_line(profile_command_line,line_number);
  2184.          if (rc == RC_SYSTEM_ERROR
  2185.          ||  rc == RC_NOREXX_ERROR)
  2186.             break;
  2187.          if (number_of_files == 0)
  2188.             break;
  2189.          i = 0;
  2190.          memset(profile_command_line,' ',MAX_LENGTH_OF_LINE);
  2191.          continue;
  2192.         }
  2193.      }
  2194.    profile_command_line[i] = ch;
  2195.    i++;
  2196.   }
  2197. #ifdef TRACE
  2198.  trace_return();
  2199. #endif
  2200.  return(rc);
  2201. }
  2202. /***********************************************************************/
  2203. #ifdef HAVE_PROTO
  2204. short process_command_line(CHARTYPE *profile_command_line,short line_number)
  2205. #else
  2206. short process_command_line(profile_command_line,line_number)
  2207. CHARTYPE *profile_command_line;
  2208. short line_number;
  2209. #endif
  2210. /***********************************************************************/
  2211. {
  2212. /*--------------------------- local data ------------------------------*/
  2213.  short rc=RC_OK;
  2214.  short len=0;
  2215.  bool strip=FALSE;
  2216. /*--------------------------- processing ------------------------------*/
  2217. #ifdef TRACE
  2218.  trace_function("file.c:    process_command_line");
  2219. #endif
  2220. /*---------------------------------------------------------------------*/
  2221. /* If the first line of the macro file does not contain the comment    */
  2222. /* 'NOREXX' abort further processing of the macro file.                */
  2223. /*---------------------------------------------------------------------*/
  2224.  if (memcmp(profile_command_line,"/*NOREXX*/",10) != 0
  2225.  && line_number == 1)
  2226.    {
  2227. #ifdef TRACE
  2228.     trace_return();
  2229. #endif
  2230.     return(RC_NOREXX_ERROR);
  2231.    }
  2232. /*---------------------------------------------------------------------*/
  2233. /* If the line is a comment, return with RC_OK.                        */
  2234. /*---------------------------------------------------------------------*/
  2235.  if (memcmp(profile_command_line,"/*",2) == 0)    /* is a comment line */
  2236.    {
  2237. #ifdef TRACE
  2238.     trace_return();
  2239. #endif
  2240.     return(RC_OK);
  2241.    }
  2242. /*---------------------------------------------------------------------*/
  2243. /* If the line begins and ends with a quote, single or double, strip   */
  2244. /* the quotes.                                                         */
  2245. /*---------------------------------------------------------------------*/
  2246.  len = strlen((DEFCHAR *)profile_command_line);
  2247.  if (*(profile_command_line) == '\''
  2248.  &&  *(profile_command_line+len-1) == '\'')
  2249.     strip = TRUE;
  2250.  if (*(profile_command_line) == '"'
  2251.  &&  *(profile_command_line+len-1) == '"')
  2252.     strip = TRUE;
  2253.  if (strip)
  2254.    {
  2255.     *(profile_command_line+len-1) = '\0';
  2256.     profile_command_line++;
  2257.    }
  2258.  rc = command_line(profile_command_line,COMMAND_ONLY_FALSE);
  2259.  
  2260. #ifdef TRACE
  2261.  trace_return();
  2262. #endif
  2263.  return(rc);
  2264. }
  2265.