home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 4 / FreshFish_May-June1994.bin / bbs / may94 / util / edit / jade.lha / Jade / src / io.c < prev    next >
C/C++ Source or Header  |  1994-04-19  |  13KB  |  550 lines

  1. /* io.c -- Loading & saving files, etc...
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4. This file is part of Jade.
  5.  
  6. Jade is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. Jade is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with Jade; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. #include <string.h>
  24.  
  25. #if defined( HAVE_UNIX )
  26. # include <unistd.h>
  27. #elif defined( HAVE_AMIGA )
  28.   /* my Amiga compiler has chdir() etc in <stdio.h> */
  29. #endif
  30.  
  31. _PR bool readtx(TX *, FILE *, long, long *);
  32. _PR bool writeline(u_char *, long, FILE *, TX *, long);
  33. _PR bool fileexists2(u_char *, u_char *);
  34. _PR bool fileexists3(u_char *, u_char *, u_char *);
  35. _PR VALUE signalfileerror(VALUE cdr);
  36. _PR void io_init(void);
  37.  
  38. /* bytes to copy instead of tabs */
  39. _PR   const u_char Spaces[];
  40. _PR   const u_char Tabs[];
  41. const u_char Spaces[] = "                                                "
  42.             "                                                "
  43.             "                                                ";
  44. const u_char Tabs[] =    "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
  45.  
  46. /*
  47.  * read a file into a tx structure, the line list should have been
  48.  * killed.
  49.  * I'm going to have to speed this up somehow.
  50.  * hopefully now loads lines of any length (upto max of 32768)
  51.  *
  52.  * codePos is an array of 3 LONGs to hold the position of the code
  53.  * section to execute, it is filled in as follows,
  54.  *  codePos[0]    start column
  55.  *       [1]    start line
  56.  *       [2]    end line
  57.  * It should initially hold -1s to check for no code section.
  58.  */
  59. #define SIZESTEP  50    /* size at which line list grows by */
  60. #define BUFFSTART 128
  61. bool
  62. readtx(TX *tx, FILE *fh, long diskTab, long *codePos)
  63. {
  64.     bool rc = FALSE;
  65.     long bufflen = BUFFSTART;
  66.     u_char *buff = mystralloc(bufflen);
  67.     if(buff)
  68.     {
  69.     long c, i = 0;
  70.     long linenum = 0, allocedlines = 0;
  71.     u_char *newstr;
  72.     LINE *line;
  73. #ifdef HAVE_AMIGA
  74.     settitle("loading...");
  75. #endif
  76.     while((c = fgetc(fh)) != EOF)
  77.     {
  78.         if(i >= bufflen)
  79.         {
  80.         u_char *newbuff;
  81.         newbuff = mystralloc(bufflen * 2);
  82.         if(!newbuff)
  83.             goto abortmem;
  84.         memcpy(newbuff, buff, i);
  85.         mystrfree(buff);
  86.         buff = newbuff;
  87.         bufflen *= 2;
  88.         }
  89.         if(c == '\n')
  90.         {
  91.         if(linenum >= allocedlines)
  92.         {
  93.             if(!resizelinelist(tx, SIZESTEP, linenum))
  94.             goto abortmem;
  95.             allocedlines += SIZESTEP;
  96.         }
  97.         if(!(newstr = mystralloc(i + 1)))
  98.             goto abortmem;
  99.         memcpy(newstr, buff, i);
  100.         newstr[i] = 0;
  101.         line = tx->tx_Lines + linenum;
  102.         line->ln_Strlen = i + 1;
  103.         line->ln_Line = newstr;
  104.         i = 0;
  105.         /*
  106.          * check for code section
  107.          */
  108.         if(codePos[1] < 0)
  109.         {
  110.             u_char *s = strstr(newstr, "::jade" "-code::");
  111.             if(s)
  112.             {
  113.             codePos[0] = s - newstr;
  114.             codePos[1] = linenum;
  115.             }
  116.         }
  117.         else if(codePos[2] < 0)
  118.         {
  119.             if(strstr(newstr, "::end::"))
  120.             codePos[2] = linenum;
  121.         }
  122.         linenum++;
  123.         }
  124.         else if(c == '\t')
  125.         {
  126.         int numspaces = diskTab - (i % diskTab);
  127.         if(i + numspaces >= bufflen)
  128.         {
  129.             u_char *newbuff = mystralloc(bufflen * 2);
  130.             if(!newbuff)
  131.             goto abortmem;
  132.             memcpy(newbuff, buff, i);
  133.             mystrfree(buff);
  134.             buff = newbuff;
  135.             bufflen *= 2;
  136.         }
  137.         strncpy(buff + i, Spaces, numspaces);
  138.         i += numspaces;
  139.         }
  140.         else
  141.         buff[i++] = c;
  142.     }
  143.     if(!resizelinelist(tx, linenum - allocedlines + 1, linenum))
  144.         goto abortmem;
  145.     if(!(newstr = mystralloc(i + 1)))
  146.         goto abortmem;
  147.     memcpy(newstr, buff, i);
  148.     newstr[i] = 0;
  149.     line = tx->tx_Lines + linenum;
  150.     line->ln_Strlen = i + 1;
  151.     line->ln_Line = newstr;
  152.     if((codePos[1] >= 0) && (codePos[2] < 0))
  153.         codePos[2] = linenum;
  154.     tx->tx_Changes++;
  155.     rc = TRUE;
  156. #ifdef HAVE_AMIGA
  157.     settitle("OK");
  158. #endif
  159.     /* This block only gets executed if we aborted while
  160.      * reading the file.
  161.      */
  162.     if(0)
  163.     {
  164. abortmem:
  165.         settitle(NoMemMsg);
  166. #if 0
  167. abort:
  168. #endif
  169.         clearlinelist(tx);
  170.     }
  171.     mystrfree(buff);
  172.     }
  173.     else
  174.     settitle(NoMemMsg);
  175.     tx->tx_Flags |= TXFF_REFRESH_ALL;
  176.     return(rc);
  177. }
  178.  
  179. _PR VALUE cmd_read_buffer(VALUE file, VALUE tx);
  180. DEFUN("read-buffer", cmd_read_buffer, subr_read_buffer, (VALUE file, VALUE tx), V_Subr2, DOC_read_buffer) /*
  181. ::doc:read_buffer::
  182. (read-buffer FILE [BUFFER])
  183. Overwrites the text in BUFFER with that from the file FILE.
  184. FILE is either a string naming the file to be opened or a Lisp file object
  185. (from `open') to be used.
  186. ::end:: */
  187. {
  188.     long codepos[3];
  189.     VALUE res = sym_nil;
  190.     FILE *fh;
  191.     bool closefh;
  192.     if(FILEP(file) && VFILE(file)->lf_Name)
  193.     {
  194.     fh = VFILE(file)->lf_File;
  195.     closefh = FALSE;
  196.     }
  197.     else
  198.     {
  199.     DECLARE1(file, STRINGP);
  200.     if(!(fh = fopen(VSTR(file), "r")))
  201.         return(cmd_signal(sym_file_error, list_2(geterrstring(), file)));
  202.     closefh = TRUE;
  203.     }
  204.     if(!BUFFERP(tx))
  205.     tx = CurrVW->vw_Tx;
  206.     killlinelist(VTX(tx));
  207.     codepos[1] = codepos[2] = -1;
  208.     if(readtx(VTX(tx), fh, VTX(tx)->tx_DiskTab, codepos))
  209.     res = tx;
  210.     else
  211.     clearlinelist(VTX(tx));     /* hope for some mem left */
  212.     if(closefh)
  213.     fclose(fh);
  214.     resetallviews(VTX(tx));
  215.     resetslptxtitles(VTX(tx));
  216.     if(codepos[2] > 0)
  217.     execfilecode(VTX(tx), codepos);
  218.     return(res);
  219. }
  220.  
  221. _PR VALUE cmd_write_buffer(VALUE file, VALUE tx);
  222. DEFUN("write-buffer", cmd_write_buffer, subr_write_buffer, (VALUE file, VALUE tx), V_Subr2, DOC_write_buffer) /*
  223. ::doc:write_buffer::
  224. (write-buffer [FILE-NAME] [BUFFER])
  225. Saves the contents of BUFFER to file FILE-NAME.
  226. ::end:: */
  227. {
  228.     if(!BUFFERP(tx))
  229.     tx = CurrVW->vw_Tx;
  230.     if(!STRINGP(file))
  231.     file = VTX(tx)->tx_FileName;
  232.     if(file)
  233.     {
  234.     FILE *fh = fopen(VSTR(file), "w");
  235.     if(fh)
  236.     {
  237.         long i;
  238.         LINE *line = VTX(tx)->tx_Lines;
  239.         for(i = 0; i < VTX(tx)->tx_NumLines; i++, line++)
  240.         {
  241.         if(!writeline(line->ln_Line, line->ln_Strlen - 1, fh, VTX(tx), 0))
  242.             goto error;
  243.         if(i != VTX(tx)->tx_NumLines - 1)
  244.             fputc('\n', fh);
  245.         }
  246.         fclose(fh);
  247.     }
  248.     else
  249. error:
  250.         return(cmd_signal(sym_file_error, list_2(geterrstring(), file)));
  251.     return(file);
  252.     }
  253.     return(cmd_signal(sym_bad_arg, list_2(file, newnumber(1))));
  254. }
  255.  
  256. _PR VALUE cmd_write_buffer_area(VALUE vstart, VALUE vend, VALUE file, VALUE tx);
  257. DEFUN("write-buffer-area", cmd_write_buffer_area, subr_write_buffer_area, (VALUE vstart, VALUE vend, VALUE file, VALUE tx), V_Subr4, DOC_write_buffer_area) /*
  258. ::doc:write_buffer_area::
  259. (write-buffer-area START-POS END-POS [FILE-NAME] [BUFFER])
  260. Writes the text between START-POS and END-POS in BUFFER to file
  261. FILE-NAME.
  262. ::end:: */
  263. {
  264.     POS start, end;
  265.     DECLARE1(vstart, POSP);
  266.     DECLARE2(vend, POSP);
  267.     if(!BUFFERP(tx))
  268.     tx = CurrVW->vw_Tx;
  269.     if(!STRINGP(file))
  270.     file = VTX(tx)->tx_FileName;
  271.     start = VPOS(vstart);
  272.     end = VPOS(vend);
  273.     if(!checksect(tx, &start, &end))
  274.     return(cmd_signal(sym_invalid_area, list_3(tx, vstart, vend)));
  275.     if(file)
  276.     {
  277.     FILE *fh = fopen(VSTR(file), "w");
  278.     if(fh)
  279.     {
  280.         LINE *line = VTX(tx)->tx_Lines + start.pos_Line;
  281.         while(start.pos_Line <= end.pos_Line)
  282.         {
  283.         if(!writeline(line->ln_Line,
  284.                   (start.pos_Line == end.pos_Line)
  285.                 ? end.pos_Col : line->ln_Strlen - 1,
  286.                   fh, tx, start.pos_Col))
  287.             goto error;
  288.         if(start.pos_Line != end.pos_Line)
  289.             fputc('\n', fh);
  290.         start.pos_Line++;
  291.         start.pos_Col = 0;
  292.         line++;
  293.         }
  294.         fclose(fh);
  295.     }
  296.     else
  297. error:
  298.         return(cmd_signal(sym_file_error, list_2(geterrstring(), file)));
  299.     return(file);
  300.     }
  301.     return(cmd_signal(sym_bad_arg, list_2(file, newnumber(1))));
  302. }
  303.  
  304. _PR VALUE cmd_cd(VALUE dir);
  305. DEFUN("cd", cmd_cd, subr_cd, (VALUE dir), V_Subr1, DOC_cd) /*
  306. ::doc:cd::
  307. (cd [DIRECTORY])
  308. If DIRECTORY is given set the editor's current directory to it, else
  309. return the name of the current directory.
  310. ::end:: */
  311. {
  312.     VALUE res = sym_nil;
  313.     if(STRINGP(dir))
  314.     {
  315.     if(chdir(VSTR(dir)))
  316.         settitlefmt("can't chdir to %s", VSTR(dir));
  317.     el