gno/bin/vi/fileio.c

382 lines
8.4 KiB
C

/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
*
* Code Contributions By : Jawaid Bayzar bazyar@cs.uiuc.edu
* Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!grwalter
*/
#include "stevie.h"
segment "s_io";
#ifdef GSOS
#include <gsos.h>
#include <signal.h>
#include <gno/gno.h>
#include <fcntl.h>
FileInfoRecGS finfo = {4, 0l, 0xC3, 0xB0, 0l};
#endif
void
filemess(char *s)
{
sprintf(IObuff, "\"%s\" %s", ((Filename == NULL) ? "" : Filename), s);
msg(IObuff);
}
void
renum(void)
{
LPtr *p;
unsigned long l = 0;
for (p = Filemem; p != NULL; p = nextline(p), l += LINEINC)
p->linep->num = l;
Fileend->linep->num = 0xffffffffL;
}
#ifdef MEGAMAX
overlay "fileio"
#endif
#ifdef GSOS
#define BUFSIZE1 4096
char *savebuf;
int outind;
int fd;
void flushout()
{
write(fd,savebuf,outind);
outind = 0;
}
#endif
/* made a bunch of these things unsigned for speed- 816 be dumb */
bool_t
readfile(char *fname, LPtr *fromp, bool_t nochangename)
/*char *fname;
LPtr *fromp;
bool_t nochangename; /* if TRUE, don't change the Filename */
{
FILE *f, *fopen();
LINE *curr;
char buf2[80];
int c,hitEOF = 0;
unsigned short IObuffsize = 0;
unsigned long nchars = 0;
unsigned int linecnt = 0;
bool_t wasempty = bufempty();
unsigned nonascii = 0; /* count garbage characters */
unsigned nulls = 0; /* count nulls */
bool_t incomplete = FALSE; /* was the last line incomplete? */
bool_t toolong = FALSE; /* a line was too long */
char *saveb1,*locIObuff;
unsigned inind,insize;
curr = fromp->linep;
locIObuff = IObuff;
if (!nochangename)
Filename = strsave(fname);
f = fopen(fname, "r");
if (f == NULL) {
s_refresh(NOT_VALID);
filemess("");
return TRUE;
}
#ifdef GSOS
{
GSString255Ptr fn;
fn = malloc(strlen(fname)+2);
fn->length = strlen(fname);
strncpy(fn->text,fname,fn->length);
finfo.pCount = 4;
finfo.pathname = fn;
GetFileInfoGS(&finfo);
free(fn);
}
#endif
S_NOT_VALID;
#ifdef GSOS
savebuf = malloc(BUFSIZE1+1);
saveb1 = savebuf;
insize = inind = 0;
#endif
do {
if (inind == insize) {
insize = read(fileno(f), savebuf, BUFSIZE1);
if (!insize) hitEOF = 1;
inind = 0;
}
/*c = getc(f);*/
c = saveb1[inind++];
if (c == '\r') c = NL;
if (hitEOF) {
if (IObuffsize == 0)/* normal loop termination */
break;
/*
* If we get EOF in the middle of a line, note the fact and
* complete the line ourselves.
*/
incomplete = TRUE;
c = NL;
}
if (c & 0x80) { /* much faster check for hi bit set */
c &= 0x7f; /* this is faster, jesus */
nonascii++;
}
/*
* If we reached the end of the line, OR we ran out of space for it,
* then process the complete line.
*/
if (c == NL || IObuffsize == (IOSIZE - 1)) {
LINE *lp;
if (c != NL)
toolong = TRUE;
locIObuff[IObuffsize++] = NUL;
lp = newline(IObuffsize);
if (lp == NULL) {
fprintf(stderr, "not enough memory - should never happen");
getout(1);
}
strcpy(lp->s, locIObuff);
curr->next->prev = lp; /* new line to next one */
lp->next = curr->next;
curr->next = lp; /* new line to prior one */
lp->prev = curr;
curr = lp; /* new line becomes current */
IObuffsize = 0;
linecnt++;
} else if (c == NUL) {
nulls++; /* count and ignore nulls */
} else {
locIObuff[IObuffsize++] = (char) c; /* normal character */
}
nchars++;
} while (!incomplete && !toolong);
free(savebuf);
fclose(f);
/*
* If the buffer was empty when we started, we have to go back and remove
* the "dummy" line at Filemem and patch up the ptrs.
*/
if (wasempty && linecnt != 0) {
LINE *dummy = Filemem->linep; /* dummy line ptr */
Filemem->linep = Filemem->linep->next;
Filemem->linep->prev = Filetop->linep;
Filetop->linep->next = Filemem->linep;
Curschar->linep = Filemem->linep;
Topchar->linep = Filemem->linep;
free(dummy->s); /* free string space */
free((char *) dummy); /* free LINE struct */
}
renum();
if (toolong) {
s_refresh(NOT_VALID);
sprintf(IObuff, "\"%s\" Line too long", fname);
msg(IObuff);
return FALSE;
}
s_refresh(NOT_VALID);
sprintf(IObuff, "\"%s\" %s%d line%s, %ld character%s",
fname,
incomplete ? "[Incomplete last line] " : "",
linecnt, (linecnt > 1) ? "s" : "",
nchars, (nchars > 1) ? "s" : "");
buf2[0] = NUL;
if (nonascii || nulls) {
if (nonascii) {
if (nulls)
sprintf(buf2, " (%d null, %d non-ASCII)",
nulls, nonascii);
else
sprintf(buf2, " (%d non-ASCII)", nonascii);
} else
sprintf(buf2, " (%d null)", nulls);
}
strcat(IObuff, buf2);
msg(IObuff);
return FALSE;
}
/*
* writeit - write to file 'fname' lines 'start' through 'end'
*
* If either 'start' or 'end' contain null line pointers, the default is to use
* the start or end of the file respectively.
*/
bool_t
writeit(char *fname, LPtr *start, LPtr *end)
{
FILE *f;
FILE *fopen();
FILE *fopenb(); /* open in binary mode, where needed */
char *s;
long nchars;
int lines;
LPtr *p;
#ifdef GSOS
int linesize,inind;
char *line_ptr,*saveb1;
#endif
sprintf(IObuff, "\"%s\"", fname);
msg(IObuff);
#ifdef GSOS
signal(SIGTSTP,SIG_IGN);
#endif
/*
* Form the backup file name - change foo.* to foo.bak - use IObuff to
* hold the backup file name
*/
strcpy(IObuff, fname);
for (s = IObuff; *s && *s != '.'; s++);
*s = NUL;
strcat(IObuff, ".bak");
/*
* Delete any existing backup and move the current version to the backup.
* For safety, we don't remove the backup until the write has finished
* successfully. And if the 'backup' option is set, leave it around.
*/
rename(fname, IObuff);
f = P(P_CR) ? fopen(fname, "w") : fopenb(fname, "w");
if (f == NULL) {
emsg("Can't open file for writing!");
return FALSE;
}
#ifdef GSOS
savebuf = malloc(BUFSIZE1+1); /* allocate our big memory-save buffer */
saveb1 = savebuf;
#endif
/*
* If we were given a bound, start there. Otherwise just start at the
* beginning of the file.
*/
if (start == NULL || start->linep == NULL)
p = Filemem;
else
p = start;
lines = 0;
nchars = 0;
#ifdef GSOS
outind = 0;
fd = fileno(f);
#endif
do {
#ifndef GSOS
fprintf(f, "%s\n", p->linep->s);
#else
line_ptr = p->linep->s;
asm {
stz inind
agin: ldy inind
lda [line_ptr],y
and #0xff
beq done
ldy outind
cpy #BUFSIZE1
bcc otaydude
pha
jsl flushout
pla
ldy #0
otaydude: sta [saveb1],y
iny
sty outind
inc inind
jmp agin
done: sty linesize
lda #13
ldy outind
sta [saveb1],y
iny
sty outind
lda linesize
clc
adc nchars
sta nchars
}
#endif
lines++;
#ifndef GSOS
nchars += strlen(p->linep->s) + 1;
#endif
/*
* If we were given an upper bound, and we just did that line, then
* bag it now.
*/
if (end != NULL && end->linep != NULL) {
if (end->linep == p->linep)
break;
}
} while ((p = nextline(p)) != NULL);
#ifdef GSOS
flushout();
free(savebuf);
#endif
fclose(f);
/*
* Remove the backup unless they want it left around
*/
if (!P(P_BK))
remove(IObuff);
sprintf(IObuff, "\"%s\" %d line%s, %ld character%s", fname,
lines, (lines > 1) ? "s" : "",
nchars, (nchars > 1) ? "s" : "");
msg(IObuff);
UNCHANGED;
#ifdef GSOS
{
GSString255Ptr fn;
extern void stopHandler(int,int);
fn = malloc(strlen(fname)+2);
fn->length = strlen(fname);
strncpy(fn->text,fname,fn->length);
finfo.pCount = 4;
finfo.pathname = fn;
SetFileInfoGS(&finfo);
free(fn);
}
signal(SIGTSTP, stopHandler); /* handle ^Z with a message */
#endif
return TRUE;
}