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 >
Wrap
C/C++ Source or Header
|
1994-04-19
|
13KB
|
550 lines
/* io.c -- Loading & saving files, etc...
Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
This file is part of Jade.
Jade is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Jade is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jade; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "jade.h"
#include "jade_protos.h"
#include <string.h>
#if defined( HAVE_UNIX )
# include <unistd.h>
#elif defined( HAVE_AMIGA )
/* my Amiga compiler has chdir() etc in <stdio.h> */
#endif
_PR bool readtx(TX *, FILE *, long, long *);
_PR bool writeline(u_char *, long, FILE *, TX *, long);
_PR bool fileexists2(u_char *, u_char *);
_PR bool fileexists3(u_char *, u_char *, u_char *);
_PR VALUE signalfileerror(VALUE cdr);
_PR void io_init(void);
/* bytes to copy instead of tabs */
_PR const u_char Spaces[];
_PR const u_char Tabs[];
const u_char Spaces[] = " "
" "
" ";
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";
/*
* read a file into a tx structure, the line list should have been
* killed.
* I'm going to have to speed this up somehow.
* hopefully now loads lines of any length (upto max of 32768)
*
* codePos is an array of 3 LONGs to hold the position of the code
* section to execute, it is filled in as follows,
* codePos[0] start column
* [1] start line
* [2] end line
* It should initially hold -1s to check for no code section.
*/
#define SIZESTEP 50 /* size at which line list grows by */
#define BUFFSTART 128
bool
readtx(TX *tx, FILE *fh, long diskTab, long *codePos)
{
bool rc = FALSE;
long bufflen = BUFFSTART;
u_char *buff = mystralloc(bufflen);
if(buff)
{
long c, i = 0;
long linenum = 0, allocedlines = 0;
u_char *newstr;
LINE *line;
#ifdef HAVE_AMIGA
settitle("loading...");
#endif
while((c = fgetc(fh)) != EOF)
{
if(i >= bufflen)
{
u_char *newbuff;
newbuff = mystralloc(bufflen * 2);
if(!newbuff)
goto abortmem;
memcpy(newbuff, buff, i);
mystrfree(buff);
buff = newbuff;
bufflen *= 2;
}
if(c == '\n')
{
if(linenum >= allocedlines)
{
if(!resizelinelist(tx, SIZESTEP, linenum))
goto abortmem;
allocedlines += SIZESTEP;
}
if(!(newstr = mystralloc(i + 1)))
goto abortmem;
memcpy(newstr, buff, i);
newstr[i] = 0;
line = tx->tx_Lines + linenum;
line->ln_Strlen = i + 1;
line->ln_Line = newstr;
i = 0;
/*
* check for code section
*/
if(codePos[1] < 0)
{
u_char *s = strstr(newstr, "::jade" "-code::");
if(s)
{
codePos[0] = s - newstr;
codePos[1] = linenum;
}
}
else if(codePos[2] < 0)
{
if(strstr(newstr, "::end::"))
codePos[2] = linenum;
}
linenum++;
}
else if(c == '\t')
{
int numspaces = diskTab - (i % diskTab);
if(i + numspaces >= bufflen)
{
u_char *newbuff = mystralloc(bufflen * 2);
if(!newbuff)
goto abortmem;
memcpy(newbuff, buff, i);
mystrfree(buff);
buff = newbuff;
bufflen *= 2;
}
strncpy(buff + i, Spaces, numspaces);
i += numspaces;
}
else
buff[i++] = c;
}
if(!resizelinelist(tx, linenum - allocedlines + 1, linenum))
goto abortmem;
if(!(newstr = mystralloc(i + 1)))
goto abortmem;
memcpy(newstr, buff, i);
newstr[i] = 0;
line = tx->tx_Lines + linenum;
line->ln_Strlen = i + 1;
line->ln_Line = newstr;
if((codePos[1] >= 0) && (codePos[2] < 0))
codePos[2] = linenum;
tx->tx_Changes++;
rc = TRUE;
#ifdef HAVE_AMIGA
settitle("OK");
#endif
/* This block only gets executed if we aborted while
* reading the file.
*/
if(0)
{
abortmem:
settitle(NoMemMsg);
#if 0
abort:
#endif
clearlinelist(tx);
}
mystrfree(buff);
}
else
settitle(NoMemMsg);
tx->tx_Flags |= TXFF_REFRESH_ALL;
return(rc);
}
_PR VALUE cmd_read_buffer(VALUE file, VALUE tx);
DEFUN("read-buffer", cmd_read_buffer, subr_read_buffer, (VALUE file, VALUE tx), V_Subr2, DOC_read_buffer) /*
::doc:read_buffer::
(read-buffer FILE [BUFFER])
Overwrites the text in BUFFER with that from the file FILE.
FILE is either a string naming the file to be opened or a Lisp file object
(from `open') to be used.
::end:: */
{
long codepos[3];
VALUE res = sym_nil;
FILE *fh;
bool closefh;
if(FILEP(file) && VFILE(file)->lf_Name)
{
fh = VFILE(file)->lf_File;
closefh = FALSE;
}
else
{
DECLARE1(file, STRINGP);
if(!(fh = fopen(VSTR(file), "r")))
return(cmd_signal(sym_file_error, list_2(geterrstring(), file)));
closefh = TRUE;
}
if(!BUFFERP(tx))
tx = CurrVW->vw_Tx;
killlinelist(VTX(tx));
codepos[1] = codepos[2] = -1;
if(readtx(VTX(tx), fh, VTX(tx)->tx_DiskTab, codepos))
res = tx;
else
clearlinelist(VTX(tx)); /* hope for some mem left */
if(closefh)
fclose(fh);
resetallviews(VTX(tx));
resetslptxtitles(VTX(tx));
if(codepos[2] > 0)
execfilecode(VTX(tx), codepos);
return(res);
}
_PR VALUE cmd_write_buffer(VALUE file, VALUE tx);
DEFUN("write-buffer", cmd_write_buffer, subr_write_buffer, (VALUE file, VALUE tx), V_Subr2, DOC_write_buffer) /*
::doc:write_buffer::
(write-buffer [FILE-NAME] [BUFFER])
Saves the contents of BUFFER to file FILE-NAME.
::end:: */
{
if(!BUFFERP(tx))
tx = CurrVW->vw_Tx;
if(!STRINGP(file))
file = VTX(tx)->tx_FileName;
if(file)
{
FILE *fh = fopen(VSTR(file), "w");
if(fh)
{
long i;
LINE *line = VTX(tx)->tx_Lines;
for(i = 0; i < VTX(tx)->tx_NumLines; i++, line++)
{
if(!writeline(line->ln_Line, line->ln_Strlen - 1, fh, VTX(tx), 0))
goto error;
if(i != VTX(tx)->tx_NumLines - 1)
fputc('\n', fh);
}
fclose(fh);
}
else
error:
return(cmd_signal(sym_file_error, list_2(geterrstring(), file)));
return(file);
}
return(cmd_signal(sym_bad_arg, list_2(file, newnumber(1))));
}
_PR VALUE cmd_write_buffer_area(VALUE vstart, VALUE vend, VALUE file, VALUE tx);
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) /*
::doc:write_buffer_area::
(write-buffer-area START-POS END-POS [FILE-NAME] [BUFFER])
Writes the text between START-POS and END-POS in BUFFER to file
FILE-NAME.
::end:: */
{
POS start, end;
DECLARE1(vstart, POSP);
DECLARE2(vend, POSP);
if(!BUFFERP(tx))
tx = CurrVW->vw_Tx;
if(!STRINGP(file))
file = VTX(tx)->tx_FileName;
start = VPOS(vstart);
end = VPOS(vend);
if(!checksect(tx, &start, &end))
return(cmd_signal(sym_invalid_area, list_3(tx, vstart, vend)));
if(file)
{
FILE *fh = fopen(VSTR(file), "w");
if(fh)
{
LINE *line = VTX(tx)->tx_Lines + start.pos_Line;
while(start.pos_Line <= end.pos_Line)
{
if(!writeline(line->ln_Line,
(start.pos_Line == end.pos_Line)
? end.pos_Col : line->ln_Strlen - 1,
fh, tx, start.pos_Col))
goto error;
if(start.pos_Line != end.pos_Line)
fputc('\n', fh);
start.pos_Line++;
start.pos_Col = 0;
line++;
}
fclose(fh);
}
else
error:
return(cmd_signal(sym_file_error, list_2(geterrstring(), file)));
return(file);
}
return(cmd_signal(sym_bad_arg, list_2(file, newnumber(1))));
}
_PR VALUE cmd_cd(VALUE dir);
DEFUN("cd", cmd_cd, subr_cd, (VALUE dir), V_Subr1, DOC_cd) /*
::doc:cd::
(cd [DIRECTORY])
If DIRECTORY is given set the editor's current directory to it, else
return the name of the current directory.
::end:: */
{
VALUE res = sym_nil;
if(STRINGP(dir))
{
if(chdir(VSTR(dir)))
settitlefmt("can't chdir to %s", VSTR(dir));
el