gno/bin/vi/fileio.c
gdr-ftp 784e3de7cd Initial checkin of aroff, binprint, center, less, ls, make, makemake,
passwd, ps, purge, shutdown, stty, upper, and vi.  These sources are
for the versions of the utils shipped with GNO v2.0.4.
1998-03-09 08:30:21 +00:00

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;
}