home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 5
/
FREESOFT.BIN
/
wink2
/
src
/
buff.c
< prev
next >
Wrap
Text File
|
1992-08-19
|
14KB
|
691 lines
/*
buffer I/O
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define ERR (-1)
#define PTR(p) (unsigned int)(p)
#define unlink remove
#define MAX_BUF (16384-24)
#define HEAD_SIZ (sizeof(BUF_PTR)-MAX_BUF)
#define SEEK_POS(n) ((long)(n)*sizeof(BUF_PTR))
#define WRITE_ERR 1
#define READ_ERR 2
typedef struct _BP {
struct _BP *next;
int alno;
int left;
int right;
int len;
int lfc;
char buf[MAX_BUF];
} BUF_PTR;
typedef struct _EP {
struct _EP *next;
int actno;
int actpos;
long pos;
long line;
} EDT_PTR;
extern void wrtstr();
extern int Input();
extern char *Tmp_device_name;
EDT_PTR *edt_top=NULL;
static EDT_PTR *undo_edt=NULL;
static long undo_sz=0L;
static FILE *tfp=NULL;
static int free_no=ERR;
static BUF_PTR *top_ptr=NULL;
static char TMPFILE[80];
unsigned long int Freemem()
{
int mx;
unsigned long int sz,fm;
char *dmy[128];
for ( sz = 0x10000,fm = mx = 0 ; mx < 128 ; mx++ ) {
while ( (dmy[mx] = malloc(sz)) == NULL ) {
if ( (sz /= 2) < 0x1000 )
break;
}
if ( dmy[mx] == NULL )
break;
fm += sz;
}
while ( mx > 0 )
free(dmy[--mx]);
return fm;
}
int Bfp_init()
{
int i;
BUF_PTR *bp;
char *p;
unsigned long int l;
l = Freemem() / 2;
i = l / sizeof(BUF_PTR);
if ( (bp = (BUF_PTR *)malloc(sizeof(BUF_PTR)*i)) == NULL )
return ERR;
top_ptr = bp;
for ( i-- ; i > 0 ; i-- ) {
bp->next = bp + 1;
bp->alno = ERR;
bp++;
}
bp->next = NULL;
bp->alno = ERR;
if ( (p = Tmp_device_name) != NULL ||
(p = getenv("TMP")) != NULL )
sprintf(TMPFILE,"%s\\",p);
else
TMPFILE[0] = '\0';
strcat(TMPFILE,"WINK.TMP");
New_link();
undo_edt = edt_top;
New_link();
return FALSE;
}
void Bfp_end()
{
if ( tfp != NULL ) {
fclose(tfp);
unlink(TMPFILE);
}
}
static void retry(no)
int no;
{
static char *msg[]={
"Save Temp Seek Error ",
"Save Temp Write Header Error",
"Save Temp Write Buffer Error",
"Load Temp Seek Error ",
"Load Temp Read Header Error ",
"Save Temp Read Buffer Error ",
"New Temp File Can't open ",
"New Temp Write Error ",
"Temp File Can't open "
};
int i;
FILE *fp;
char tmp[80];
char buf[512];
RETRY:
do {
wrtstr(msg[no],30,1,0x12);
tmp[0] = '\0';
while ( (short int)Input(tmp,"テンポラリドライブ名 ") != FALSE );
if ( strcmp(tmp,"EXIT") == 0 )
exit(10);
strcat(tmp,"\\WINK.TMP");
wrtstr(" ",30,1,0x1F);
no = 6;
} while ( (fp = fopen(tmp,"w+b")) == NULL );
if ( tfp != NULL ) {
fseek(tfp,0L,SEEK_SET);
while ( (i = fread(buf,1,512,tfp)) > 0 )
fwrite(buf,1,i,fp);
}
if ( ferror(fp) ) {
fclose(fp);
unlink(tmp);
no = 7;
goto RETRY;
}
if ( tfp != NULL ) {
fclose(tfp);
unlink(TMPFILE);
}
tfp = fp;
strcpy(TMPFILE,tmp);
}
static void save_buf(bp)
register BUF_PTR *bp;
{
if ( tfp == NULL && (tfp = fopen(TMPFILE,"w+b")) == NULL ) {
retry(8);
goto RETRY;
}
RETRY:
if ( fseek(tfp,SEEK_POS(bp->alno),SEEK_SET) ) {
retry(0);
goto RETRY;
}
if ( fwrite((char *)bp,HEAD_SIZ,1,tfp) < 1 ) {
retry(1);
goto RETRY;
}
if ( bp->len > 0 && fwrite(bp->buf,1,bp->len,tfp) < bp->len ) {
retry(2);
goto RETRY;
}
}
static void load_buf(no,bp)
int no;
register BUF_PTR *bp;
{
BUF_PTR *tp;
if ( tfp == NULL && (tfp = fopen(TMPFILE,"w+b")) == NULL ) {
retry(8);
goto RETRY;
}
RETRY:
if ( fseek(tfp,SEEK_POS(no),SEEK_SET) ) {
retry(3);
goto RETRY;
}
tp = bp->next;
if ( fread((char *)bp,HEAD_SIZ,1,tfp) < 1 ) {
bp->next = tp;
retry(4);
goto RETRY;
}
bp->next = tp;
if ( bp->len > 0 && fread(bp->buf,1,bp->len,tfp) < bp->len ) {
retry(5);
goto RETRY;
}
}
static BUF_PTR *get_buf(no)
int no;
{
BUF_PTR *tp;
register BUF_PTR *bp;
bp = top_ptr;
while ( bp->alno != no ) {
if ( bp->next == NULL ) {
if ( bp->alno != ERR )
save_buf(bp);
if ( no != ERR )
load_buf(no,bp);
break;
}
tp = bp;
bp = bp->next;
}
if ( bp != top_ptr ) {
tp->next = bp->next;
bp->next = top_ptr;
top_ptr = bp;
}
return bp;
}
static int xalloc()
{
static int alno=0;
register BUF_PTR *bp;
if ( free_no != ERR ) {
bp = get_buf(free_no);
free_no = bp->left;
} else {
bp = get_buf(ERR);
bp->alno = alno++;
}
bp->left = bp->right = ERR;
bp->len = 0;
bp->lfc = ERR;
return bp->alno;
}
static void xfree(no)
int no;
{
register BUF_PTR *bp;
bp = get_buf(no);
bp->left = free_no;
free_no = no;
bp->len = 0;
}
static int link_buf(no)
int no;
{
int new;
BUF_PTR *tp;
BUF_PTR *bp;
new = xalloc();
tp = get_buf(no); /* 1 */
bp = get_buf(new); /* 2 */
bp->left = no;
bp->right = tp->right;
tp->right = new;
if ( bp->right != ERR ) {
tp = get_buf(bp->right); /* 3 */
tp->left = new;
}
return new;
}
static void del_buf(no)
int no;
{
BUF_PTR *tp;
BUF_PTR *bp;
bp = get_buf(no);
if ( bp->left != ERR ) {
tp = get_buf(bp->left);
tp->right = bp->right;
}
if ( bp->right != ERR ) {
tp = get_buf(bp->right);
tp->left = bp->left;
}
xfree(no);
}
static int line_count(bp)
register BUF_PTR *bp;
{
int i,n;
register char *p;
if ( bp->lfc == ERR ) {
p = bp->buf;
n = 0;
for ( i = bp->len ; i > 0 ; i-- ) {
if ( *(p++) == '\n' )
n++;
}
bp->lfc = n;
}
return bp->lfc;
}
static char *chk_ptr(ep,pos)
register EDT_PTR *ep;
long pos;
{
BUF_PTR *bp;
bp = get_buf(ep->actno);
while ( (ep->pos + bp->len) < pos ) {
if ( bp->right == ERR )
return &(bp->buf[bp->len]);
ep->actno = bp->right;
ep->pos += bp->len;
ep->line += line_count(bp);
bp = get_buf(ep->actno);
}
while ( ep->pos > pos ) {
if ( bp->left == ERR )
return bp->buf;
ep->actno = bp->left;
bp = get_buf(ep->actno);
ep->pos -= bp->len;
ep->line -= line_count(bp);
}
return &(bp->buf[(int)(pos - ep->pos)]);
}
static long get_line(ep,line)
register EDT_PTR *ep;
int *line;
{
int t;
int n,i;
char *p;
BUF_PTR *bp;
bp = get_buf(ep->actno);
while ( (ep->line + line_count(bp)) < *line ) {
if ( bp->right == ERR ) {
*line = ep->line + line_count(bp);
break;
}
ep->actno = bp->right;
ep->pos += bp->len;
ep->line += line_count(bp);
bp = get_buf(ep->actno);
}
while ( ep->line >= *line ) {
if ( bp->left == ERR ) {
*line = ep->line;
break;
}
ep->actno = bp->left;
bp = get_buf(ep->actno);
ep->pos -= bp->len;
ep->line -= line_count(bp);
}
p = bp->buf;
t = n = *line - ep->line;
i = 0;
while ( n > 0 && i < bp->len ) {
if ( *(p++) == '\n' )
n--;
i++;
}
*line -= n;
return (ep->pos + (long)i);
}
char *Cnv_ptr(pos)
long pos;
{
register EDT_PTR *ep;
register BUF_PTR *bp;
ep = edt_top;
bp = get_buf(ep->actno);
while ( (ep->pos + bp->len) <= pos ) {
if ( bp->right == ERR )
return &(bp->buf[bp->len]);
ep->actno = bp->right;
ep->pos += bp->len;
ep->line += line_count(bp);
bp = get_buf(ep->actno);
}
while ( ep->pos > pos ) {
if ( bp->left == ERR )
return bp->buf;
ep->actno = bp->left;
bp = get_buf(ep->actno);
ep->pos -= bp->len;
ep->line -= line_count(bp);
}
return &(bp->buf[(int)(pos - ep->pos)]);
}
static int ins_str(ep,pos,str,n)
EDT_PTR *ep;
long pos;
char *str;
int n;
{
int tn,i,len;
BUF_PTR *tp;
BUF_PTR *bp;
char *p;
static char tmp[MAX_BUF];
p = chk_ptr(ep,pos);
bp = get_buf(ep->actno);
if ( (tn = &bp->buf[bp->len] - p) > 0 ) {
memcpy(tmp,p,tn);
bp->len -= tn;
}
len = n + tn;
for ( ; len > 0 ; ) {
if ( bp->len >= MAX_BUF ) {
bp = get_buf(link_buf(bp->alno));
p = bp->buf;
}
if ( n == 0 ) {
n = tn;
str = tmp;
}
i = PTR(&(bp->buf[MAX_BUF])) - PTR(p);
if ( i > n ) i = n;
memcpy(p,str,i);
p += i;
str += i;
n -= i;
len -= i;
bp->len += i;
bp->lfc = ERR;
}
if ( bp->right != ERR ) {
tp = get_buf(bp->right);
if ( (bp->len + tp->len) < MAX_BUF ) {
memcpy(&bp->buf[bp->len],tp->buf,tp->len);
bp->len += tp->len;
bp->lfc = ERR;
del_buf(bp->right);
}
}
return FALSE;
}
static int del_str(ep,pos,len)
EDT_PTR *ep;
long pos;
int len;
{
int i,n;
BUF_PTR *tp;
BUF_PTR *bp;
char *p;
p = chk_ptr(ep,pos);
bp = get_buf(ep->actno);
for ( ; len > 0 ; ) {
n = &bp->buf[bp->len] - p;
if ( n <= len ) {
bp->len -= n;
len -= n;
} else {
memcpy(p,p+len,n-(int)len);
bp->len -= len;
len = 0;
}
bp->lfc = ERR;
if ( bp->len == 0 && bp->right != ERR ) {
if ( (i = bp->alno) == ep->actno )
ep->actno = bp->right;
bp = get_buf(bp->right);
del_buf(i);
} else if ( len > 0 && bp->right != ERR ) {
bp = get_buf(bp->right);
} else
break;
p = bp->buf;
}
if ( bp->right != ERR ) {
tp = get_buf(bp->right);
if ( (bp->len + tp->len) < MAX_BUF ) {
memcpy(&bp->buf[bp->len],tp->buf,tp->len);
bp->len += tp->len;
bp->lfc = ERR;
del_buf(bp->right);
}
}
return FALSE;
}
static int cut_str(ep,pos,str,n)
EDT_PTR *ep;
long pos;
char *str;
int n;
{
int i,len;
BUF_PTR *bp;
char *p;
p = chk_ptr(ep,pos);
bp = get_buf(ep->actno);
for ( len = 0 ; n > 0 ; ) {
i = &bp->buf[bp->len] - p;
if ( i > n ) i = n;
memcpy(str,p,i);
str += i;
n -= i;
len += i;
if ( n > 0 ) {
if ( bp->right == ERR )
break;
bp = get_buf(bp->right);
p = bp->buf;
}
}
return len;
}
long Line_ptr(n)
int *n;
{
return get_line(edt_top,n);
}
void Ins_buf(ptr,sz,str)
long ptr;
int sz;
char *str;
{
ins_str(edt_top,ptr,str,sz);
}
void Del_buf(ptr,sz)
long ptr;
long sz;
{
int n;
while ( sz > 0 ) {
n = (sz > 16384 ? 16384:sz);
del_str(edt_top,ptr,n);
sz -= n;
}
}
void Cut_buf(str,sz,ptr)
char *str;
int sz;
long ptr;
{
cut_str(edt_top,ptr,str,sz);
}
int New_link()
{
EDT_PTR *ep;
if ( (ep = (EDT_PTR *)malloc(sizeof(EDT_PTR))) == NULL )
return ERR;
ep->next = edt_top;
edt_top = ep;
ep->actno = xalloc();
ep->pos = 0L;
ep->line = 0;
return FALSE;
}
void Kill_link(ep)
EDT_PTR *ep;
{
int no;
BUF_PTR *bp;
no = ep->actno;
for ( ; ; ) {
bp = get_buf(no);
if ( bp->left == ERR )
break;
no = bp->left;
}
while ( no != ERR ) {
bp = get_buf(no);
no = bp->right;
xfree(bp->alno);
}
free(ep);
}
long Nxt_line(pos)
long pos;
{
int i;
char *p;
register EDT_PTR *ep;
register BUF_PTR *bp;
extern long btm_ptr;
p = Cnv_ptr(pos);
ep = edt_top;
bp = get_buf(ep->actno);
do {
while ( p >= &(bp->buf[bp->len]) ) {
if ( bp->right == ERR ) {
p = &(bp->buf[bp->len]);
goto ENDOF;
}
i = PTR(p) - PTR(&(bp->buf[bp->len]));
ep->actno = bp->right;
ep->pos += bp->len;
ep->line += line_count(bp);
bp = get_buf(ep->actno);
p = &(bp->buf[i]);
}
} while ( *(p++) != '\n' );
ENDOF:
pos = (ep->pos + (long)(PTR(p) - PTR(bp->buf)));
return (pos > btm_ptr ? btm_ptr : pos);
}
void Undo_put(ptr,sz)
long ptr,sz;
{
int n;
char tmp[256];
while ( undo_sz > 0 ) {
n = (undo_sz > 16384 ? 16384:undo_sz);
del_str(undo_edt,0L,n);
undo_sz -= n;
}
while ( sz > 0 ) {
n = (sz > 256 ? 256:sz);
cut_str(edt_top,ptr,tmp,n);
ins_str(undo_edt,undo_sz,tmp,n);
sz -= n;
ptr += n;
undo_sz += n;
}
}
long Undo_get(ptr)
long ptr;
{
int n;
long sz,pos;
char tmp[256];
sz = undo_sz;
pos = 0L;
while ( sz > 0 ) {
n = (sz > 256 ? 256:sz);
cut_str(undo_edt,pos,tmp,n);
ins_str(edt_top,ptr,tmp,n);
sz -= n;
pos += n;
ptr += n;
}
return undo_sz;
}
int Undo_cpy(buf,sz,pos)
char *buf;
int sz;
long pos;
{
return cut_str(undo_edt,pos,buf,sz);
}