//edit.ctp Copyright (C) 1989-2000 I.Pedley (CTPP) Sun 30-Apr-2000 at 14:30:21
//editor sub-functions, including modified line buffer management
#pragma breakpoints on
#include {stdlib.htm}
#include {string.htm}
#include {drive.htm}
#include {accdis.htm}
#include {bios.htm}
#include {chaoskey.htm}
#include {os3.htm}
#include {e3.htm}
EX E3 ectl;
EX E3 E[MAXEFILES];
EX UL efiles;
EX UL ecur;
UL linelength (CH* str,UL maxlen);
UL lflinelength(CH* str,UL maxlen);
E3* ce;
EX UL insert;
#define UDGRAN 100
CH* udbuf;
UL udidx;
UL udlines;
SL deleteline (E3* e)
{
if(e->cury>=e->lines){return 0;}
SL tomove=e->lines-e->cury; //include one blank line from extras
CH* text=e->buf+e->cury*MEMLINELEN;
CH* ud;
CH* ud1;
if(tomove>0)
{
if(udidxlines--;
e->modified=1;
return 0;
}
SL insertblankline(E3* e)
{
CH* ebuf;
if(e->lines==e->maxlines)
{
ebuf=malloc((e->lines+EDITEXTRAS)*MEMLINELEN);
if(!ebuf)
{
displayat(49,40,"|c4Out of memory for edit buffers");
return 1;
}
memcpy(ebuf,e->buf,e->lines*MEMLINELEN);
free(e->buf);
e->buf=ebuf;
e->maxlines+=EDITEXTRAS;
displayat(49,40,"|c4Edit buffer increased to %4l lines",&e->maxlines);
}
SL tomove=e->lines-e->cury;
CH* text=e->buf+e->cury*MEMLINELEN;
while(tomove<0){e->lines++;tomove++;} //allow for cursor beyond end of file
if(tomove>0){memmove(text+MEMLINELEN,text,tomove*MEMLINELEN);}
memset (text,0x20,MEMLINELEN);
e->lines++;
e->modified=1;
return 0;
}
SL repeatline (E3* e)
{
if(insertblankline(e)){return 1;}
CH* text=e->buf+e->cury*MEMLINELEN;
memcpy(text,text+MEMLINELEN,MEMLINELEN);
e->modified=1;
return 0;
}
SL retypeline (E3* e)
{
CH* text;
CH* ud;
if(udidx)
{
if(insertblankline(e)){return 1;}
text=e->buf+e->cury*MEMLINELEN; //e->buf can change in insertblankline!
udidx--;
ud =udbuf+udidx*MEMLINELEN;
memcpy (text,ud,MEMLINELEN);
}
e->modified=1;
return 0;
}
SL insertblock(E3* e)
{
//copy undelete buffer to current file, then restore undelete buffer contents
UL n=udidx;
while(udidx)
{
if(retypeline(e)){return 1;}
}
udidx=n;
return 0;
}
SL clearundeletebuffer(VD)
{
udidx=0;
}
SL makeundeletebuffer (VD)
{
udlines=UDGRAN;
udbuf=malloc(udlines*MEMLINELEN);
if(!udbuf)
{
clidisplay("Insufficient memory");return 1;
}
udidx=0;
return 0;
}
CH* argbuf;
SL destroyundeletebuffer (VD)
{
if(argbuf){free(argbuf);}
free(udbuf);return 0;
}
UL arglines;
UL argwidth;
VD saveargbuffer (E3* e)
{
CH* text=e->buf+e->argy*MEMLINELEN+e->argx;
UL n;
UL w=argwidth=e->argw-e->argx+1;
UL h=arglines=e->argh-e->argy+1;
if(argbuf){free(argbuf);}
argbuf=(CH*)calloc(h,MEMLINELEN);
if(!argbuf){brk arglines=0;return;}
memset(argbuf,0x20,h*MEMLINELEN);
for(n=0;ncurx=e->argx;
e->cury=e->argy;
}
VD insertargbuffer(E3* e)
{
CH* text=e->buf+e->cury*MEMLINELEN+e->curx;
UL tomove=MEMLINELEN-e->curx-argwidth;
UL n;
CH* ptr;
if(argwidth>=MAXLINELEN)
{
ptr=argbuf+(arglines-1)*MEMLINELEN; //insert last line first
for(n=0;nbuf+e->cury*MEMLINELEN+e->curx;
memcpy(text,ptr,argwidth); //text buffer may change after
ptr-=MEMLINELEN; //after insertblankline() so
} //refresh CH* text each time
}
else
{
for(n=0;nmodified=1;
}
VD deleteargbuffer(E3* e)
{
saveargbuffer(e);
CH* text=e->buf+e->argy*MEMLINELEN;
CH* text1=text+e->argx;
SL n,m,o;
UL w=argwidth=e->argw-e->argx+1;
UL h=arglines=e->argh-e->argy+1;
if(argwidth>=MAXLINELEN)
{
m=e->lines-e->cury-h;
if(m>0)
{
memcpy(text,text+h*MEMLINELEN,m*MEMLINELEN);
}
e->lines-=h;
}
else
{
for(n=0;nargx;
if(o>0){memcpy(text1,text1+w,o);}
text+=MEMLINELEN;
text1+=MEMLINELEN;
}
}
//move cursor to top-left of arg block, and clear arg box
e->curx=e->argx;
e->cury=e->argy;
e->argtoggle=0;
e->modified=1;
}
//SL lpt_sendchar(UL lpt,UL c);
//SL lpt_sendstring(CH* str);
//VD hpsmallprint(VD);
//VD printargbuffer (E3* e)
//{
// SL n,m,o;
// CH* text=e->buf+e->argy*MEMLINELEN+e->argx;
// UL h=arglines=e->argh-e->argy+1;
// if(h<=1){return;}
// CH* ptr;
// lpt_sendstring("\x1b\x45"); //reset printer
// hpsmallprint();
//
// lpt_sendstring("\x1b&a6L"); //set left margin to 6
//
// for(n=0;n=0x20){lpt_sendchar(0,*ptr);}
// else {lpt_sendchar(0,0x20);}
// ptr++;
// }
// lpt_sendchar(0,0x0d);
// lpt_sendchar(0,0x0a);
// text+=MEMLINELEN;
// }
// lpt_sendchar(0,0x0c);
////move cursor to top-left of arg block, and clear arg box
// e->curx=e->argx;
// e->cury=e->argy;
// e->argtoggle=0;
// e->modified=1;
//}
UL linestart(CH* str,UL maxlen)
{
SL n;
for(n=0;nbuf+e->cury*MEMLINELEN;
switch(key)
{
case TAB:
e->curx+=4;
e->curx&=-4;
if(e->curx>=MAXLINELEN)
{
e->curx-=4;
}
break;
case (SHIFT|TAB):
if(e->curx)
{
if(!(e->curx&3)){e->curx-=4;}
else {e->curx&=-4;}
}
break;
case ENTER:
case NUMENTER:
//brk
if(insert)
{
//#pragma breakpoint
insertblankline(e);
text=e->buf+e->cury*MEMLINELEN; //as e->buf may have changed!
n=linelength(text+MEMLINELEN,MAXLINELEN);
if(e->curx)
{
// if(n>=e->curx)
if(n>e->curx)
{
// rem=n-e->curx;
// memcpy(text,text+MEMLINELEN,e->curx);
// text+=MEMLINELEN;
// memcpy(text,text+e->curx,MAXLINELEN-e->curx);
// memset(text+n-e->curx,0x20,MAXLINELEN-e->curx);
rem=n-e->curx;
memcpy(text,text+MEMLINELEN,e->curx);
text+=MEMLINELEN;
memcpy(text,text+e->curx,rem);
memset(text+n-e->curx,0x20,MAXLINELEN-rem);
}
else
{
memcpy(text,text+MEMLINELEN,e->curx);
text+=MEMLINELEN;
memset(text,0x20,MAXLINELEN);
}
}
e->modified=1;
e->curx=0;
}
else
{
n=linestart(text+MEMLINELEN,MAXLINELEN);
e->curx=n;
}
e->cury++;
break;
case BACKSPACE:
if(insert)
{
if(e->curx)
{
n=linelength(text,MAXLINELEN);
if(e->curx>n)
{
//do nothing, cursor is beyond end of text on this line
}
else
{
// brk
tomove=n+1-e->curx;
memmove(text+e->curx-1,text+e->curx,tomove);
}
e->curx--;
}
else if(e->cury)
{
// brk
tomove=linelength(text,MAXLINELEN);
text-=MEMLINELEN;
n=linelength(text,MAXLINELEN);
if(!tomove) //backspace at beginning of a blank line
{ //just deletes the line
deleteline(e);
}
else if(tomove+nlines-e->cury; //include one blank line from extras
// text=e->buf+e->cury*MEMLINELEN;
// memmove(text,text+MEMLINELEN,tomove*MEMLINELEN);
}
e->cury--;
e->curx=n;
}
}
else
{
if(e->curx){e->curx--;}
else if(e->cury)
{
text-=MEMLINELEN;
n=linelength(text,MAXLINELEN);
e->cury--;
e->curx=n;
}
}
break;
case NDEL:
if(e->argtoggle)
{
saveargbuffer(e);
ptr=e->buf+e->cury*MEMLINELEN+e->curx;//<--recalc text position
if(argwidth==MAXLINELEN+1) //as cursor is moved
{ //by saveargbuffer
//we are deleting whole lines
tomove=arglines;
if(e->cury>=e->lines){break;}
if(tomove>e->lines-e->cury){tomove=e->lines-e->cury;}
memmove(ptr,ptr+arglines*MEMLINELEN,tomove*MEMLINELEN);
if(e->lines>arglines){e->lines-=arglines;}
else {e->lines=0;}
memset (e->buf+e->lines*MEMLINELEN,0x20,tomove*MEMLINELEN);
}
else
{
tomove=MAXLINELEN-e->curx-argwidth+1;
ptr=e->buf+e->cury*MEMLINELEN+e->curx;//<--recalc text position
for(n=0;nargtoggle=0;
}
else if(e->curxcurx; //include terminating null
ptr=text+e->curx;
if(tomove)
{
memcpy(ptr,ptr+1,tomove);
}
}
e->modified=1;
break;
default: //i.e. isprint()-able character
if(insert)
{
tomove=MAXLINELEN-e->curx;
ptr=text+e->curx;
memmove(ptr+1,ptr,tomove);
*ptr=key;
e->curx++;
}
else
{
ptr=text+e->curx;
*ptr=key;
e->curx++;
}
if(e->cury>=e->lines)
{
e->lines=e->cury+1;
}
e->modified=1;
break;
}
}
UL dumptrailingemptylines(E3* e)
{
SL n,m;
// CH* text=e->buf+(e->maxlines-1)*MEMLINELEN;
CH* text=e->buf+(e->lines-1)*MEMLINELEN;
// for(n=e->maxlines-1;n>=0;n--)
for(n=e->lines-1;n>=0;n--)
{
m=linelength(text,MAXLINELEN);
if(m)
{
e->lines=n+1;return 0;
}
text-=MEMLINELEN;
}
e->lines=0;
return 0;
}
UL makeasciibuf(E3* e)
{
//add CR and LF control characters to editor file lines, condensing the
//buffer as we go ready to write out to disk
//note that the condensed text is still in e->buf, for this to work correctly
//MEMLINELEN must be >= MAXLINELEN+2
//lines which are of length MAXLINELEN are saved without trailing CR LF
dumptrailingemptylines(e);
CH* ptr1=e->buf;
CH* ptr =e->buf;
UL n,m;
UL buflen=linelength(ptr,MAXLINELEN);
ptr=ptr+buflen;
*ptr++=0x0d;
*ptr++=0x0a;
ptr1=e->buf+MEMLINELEN;
buflen+=2;
for(n=1;nlines;n++)
{
m=linelength(ptr1,MAXLINELEN);
memcpy(ptr,ptr1,m);
ptr=ptr+m;
if(m==MAXLINELEN)
{
buflen+=m;
}
else
{
*ptr++=0x0d;
*ptr++=0x0a;
buflen+=m+2;
}
ptr1+=MEMLINELEN;
}
return buflen;
}
//SL cfdownload(CHAOSFILE* cf,PATH* sp,VD* buf,UL len);
//SL splitpath(CH* str,PATH* sp);
SL downloadfile(CH* fname,PATH* sp,UL fsiz,VD* buf,UL archive);
SL saveE3(E3* e,UL preserve)
{
CH* sbuf=NULL;
if(preserve)
{
sbuf=malloc(e->lines*MEMLINELEN);
if(sbuf)
{
memcpy(sbuf,e->buf,e->lines*MEMLINELEN);
}
}
UL buflen=makeasciibuf(e);
UL ret=downloadfile(e->name,&e->sp,buflen,e->buf,0);
// UL ret=downloadfile(e->name,&e->sp,buflen,e->buf,1);
if(sbuf)
{
memcpy(e->buf,sbuf,e->lines*MEMLINELEN);
free(sbuf);
}
e->modified=0;
return ret;
}
SL makecontrolfileline(E3* e,CH* msg)
{
strcpy(msg,e->name);
strcat(msg," ");itoa(e->wy, msg+strlen(msg),10);
strcat(msg," ");itoa(e->wx, msg+strlen(msg),10);
strcat(msg," ");itoa(e->cury,msg+strlen(msg),10);
strcat(msg," ");itoa(e->curx,msg+strlen(msg),10);
strcat(msg,"\r\n");
return strlen(msg);
}
SL savecontrolfile(E3* ec)
{
UL n,m;
E3* e=E;
UL buflen=0;
CH msg[512];
CH* ptr;
UL cl=ec->lines;
if(cl>MAXEFILES){cl=MAXEFILES;}
CH* text=ec->buf;
for(n=0;nloaded)
{
buflen+=makecontrolfileline(e,msg);
}
else
{
buflen+=linelength(text,MAXLINELEN)+2;
}
text+=MEMLINELEN;
e++;
}
if(!buflen){return 0;} //nothing to do is no error
CH* buf=(CH*)calloc(buflen+1,1); //add 1 for terminal null byte!
if(!buf){return 1;}
ptr=buf;
text=ec->buf;
e=E+ecur;
if(e->loaded)
{
ptr+=makecontrolfileline(e,ptr);
}
e=E;
for(n=0;nloaded)
{
ptr+=makecontrolfileline(e,ptr);
}
else
{
m=linelength(text,MAXLINELEN);
memcpy(ptr,text,m);
strcat(ptr,"\r\n");
ptr+=m+2;
}
}
text+=MEMLINELEN;
e++;
}
UL ret=downloadfile(ec->name,&ec->sp,buflen,buf,0);
free(buf);
return ret;
}
EX CH* ctfname;
SL patch(E3* e,UL size);
SL createcontrolfile(E3* e)
{
if(patch(e,0)){return 1;}
strcpy(e->name,ctfname);
strcpy(e->sp.name,"e");
strcpy(e->sp.ext, "control");
return 0;
}
SL alreadyedited(E3* e,CH* name)
{
//run through control file matching name to control file lines
UL n;
CH* text=e->buf;
CH* ptr;
CH c;
for(n=0;nlines;n++)
{
// if(!strncmp(text,name,strlen(name))){return n;}
ptr=strchr(text,' ');
if(ptr)
{
c=*ptr;
*ptr=0;
if(!strcmp(text,name)){*ptr=c;return n;}
CH tmp[256];
strcpy(tmp,name);strcat(tmp,".htm");
if(!strcmp(text,tmp )){*ptr=c;return n;}
*ptr=c;
}
text+=MEMLINELEN;
}
return -1;
}
SL createnewE3 (E3* e,CH* name)
{
memset(e,0,sizeof(E3));
e->buf=malloc((e->lines+EDITEXTRAS)*MEMLINELEN);
if(!e->buf)
{
displayat(49,40,"|c4Out of memory for edit buffers");
return 1;
}
e->maxlines=EDITEXTRAS;
memset (e->buf,0x20,e->maxlines*MEMLINELEN);
strcpy(e->name,name);
return 0;
}
SL lfterminate(E3* e)
{
//add LF control character to the end of each editor file line,
//and insert line length as first character
//ready to pass buffer in to compiler(!)
CH* text=e->buf;
UL n,m;
for(n=0;nlines;n++)
{
m=linelength(text,MAXLINELEN);
memmove(text+1,text,m);
text[0]=m;
if(mlines*MEMLINELEN;
CH* buf=malloc(buflen);
if(!buf){return NULL;}
CH* ptr=buf+sizeof(E3);
E3* e=(E3*)buf;
// *e=*ein;
memcpy(e,ein,sizeof(E3));
e->buf=ptr;
memcpy(e->buf,ein->buf,e->lines*MEMLINELEN);
return e;
}