Back

//main.ctp Copyright (C) 1989-2010 I.Pedley (CTPP) Tue 25-Apr-2000 at 20:05:01

//ChaOS source file editor

#pragma breakpoints on

#include {stdlib.htm}   //stdlib.html
#include {string.htm}   //string.html

#include {drive.htm}    //drive.html
#include {accdis.htm}   //accdis.html
#include {bios.htm}     //bios.html
#include {ctype.htm}    //ctype.html
#include {chaoskey.htm} //chaoskey.html

#include {os.htm}       //os.html
#include {e3.htm}       //e3.html
#include {box.htm}      //box.html

CH* dsavebox(BOX* b);
VD  drestorebox(BOX* b,CH* ptr);
VD  dbox1(BOX* b,UL no,CH* str,UI col);
VD  dobsbox1   (UL dispoff,BOX* b,UL no,CH* str,UI col);
VD  dobclearbox(UL dispoff,BOX* b,UL col);
VD  dclear(BOX* b,UL col);
SL  dcat(UL row,UL col,CH* format,...);
VD  dvblit(VD);
SL  catprint(CH* buf,CH* format,...);
SL  catdisp(UL row,UL col,CH* format,...);

SL  getkey(VD);
EX  UL* kbinptr;
EX  UL* kboutptr;
EX  UL  kbdstate;
VD  ipx_poll(VD);

SL  clidisplay(CH* format,...);
SL  clitype(CH* str);
VD  clidownline(VD);
EX  SL  clistartline;
EX  SL  cliendline;
EX  SL  clicur;

    E3   ectl;
    E3   E[MAXEFILES];
    UL      efiles;
    UL      ecur;

VD  handleeditchar(E3* e,UL key);
SL  saveE3     (E3* e,UL preserve);
VD  efcleanup(VD);
VD  cleanup(VD);
SL  savecontrolfile  (E3* ec);
SL  createcontrolfile(E3* e);
SL  insertblankline  (E3* e);
SL  deleteline       (E3* e);
SL  repeatline       (E3* e);
SL  retypeline       (E3* e);
SL  insertblock      (E3* e);
SL  clearundeletebuffer    (VD);
SL  makeundeletebuffer     (VD);
SL  destroyundeletebuffer  (VD);
SL  alreadyedited  (E3* e,CH* name);
SL  createnewE3   (E3* e,CH* name);


EX  LDRIVE* LDcur;
LSEQ*   dosloadSEQ(CH* name);

    CH  banner[]="|c2ED - ChaOS Source File Editor ";
    CH  blankline[256];

    UL  insert=1;

    CH  ctfname[]="e.control";


UC* loadfile(CH* fname,CHAOSFILE* cf,PATH* sp);
SL  loadfile(UL idx);
VD  buildpathstring(PATH* sp,CH* str);
VD  buildchaospathstring(LDRIVE* l,CHAOSFILE* cf,CH* str);
//UC* cfupload(CHAOSFILE* cf,PATH* sp,UL* fsiz);
//SL  splitpath(CH* str,PATH* sp);
SL  patch(E3* e,UL size);
SL  patch(LSEQ* L,UL size);
SL  createeditbuffer(E3* e);


    UL  erroronscreen;

SL  errordisplay(CH* str)
{
    UL n=strlen(str);
    if(n>79){n=79;}
    displayat(49,0,"%79sc1500",str);
    erroronscreen=1;
    return 0;
}
VD  displayE3name(E3* e);
SL  clearerrorline(E3* e)
{
    CH* str="\x0";
    erroronscreen++;
    if(erroronscreen>=2)
        {
         displayat(49,0,"%79s",str);
         erroronscreen=0;
         displayE3name(e);
        }
    erroronscreen=0;
    return 0;
}

SL  splitpath(CH* str,PATH* sp);
UC* uploadfile(CH* fname,PATH* sp);
SL  wildcardchar(CH* str);

SL  loadE3(CH* str,E3* e,UL flag)
{
    PATH  sp;
    CH* ptr;
    CH* buf=NULL;
    UL  fsiz;
    CH  fname[256];memset(fname,0,256);

    if(flag)
        {//str should be of the form  wx wy curx cury
//#pragma breakpoint
         while(isspace(*str)){str++;}
         ptr=strchr(str,' ');
         if(!ptr)
            {
             displayat(49,0,"|c1500Control file appears to be corrupt");
             //clidisplay("Corrupt control file");
             return 1;
            }
         strncpy(fname,str,ptr-str);
         fname[ptr-str]=0;
         e->wy=strtol(ptr,&ptr,10);
         e->wx=strtol(ptr,&ptr,10);
         e->cury=strtol(ptr,&ptr,10);
         e->curx=strtol(ptr,&ptr,10);
        }
    else
        {
         ptr=strchr(str,'.');
         if(!ptr)
            {//try htm file first if no file extension
             strcpy(fname,str);strcat(fname,".htm");
            }
         if(*fname){buf=(CH*)uploadfile(fname,&sp);}
         if(!buf){strcpy(fname,str);}
         e->wx=0;
         e->wy=0;
         e->curx=0;
         e->cury=0;
        }

    if(!buf){buf=(CH*)uploadfile(fname,&sp);}
    if(!buf)
       {
        //clidisplay("File %s not found",fname);return 1;
        return 1;
       }

    strcpy(e->name,fname);

    e->buf=buf;
//    memcpy(e->sp,&sp,512); //should be e->sp=sp, but A10 won't compile it yet
    e->sp=sp;   //yes it will

    if(patch(e,sp.len)){return 1;}
//    if(createeditbuffer(e)){return 1;}

    e->modified=0;
    return 0;
}
VD  destroy(E3* e)
{
    if(e->loaded)
        {
         free(e->buf);
        }
    memset(e,0,sizeof(E3));
}

EX  CH  incpath[64];

E3* loadincludefile(E3* e)
{
    CH* text=e->buf+e->cury*MEMLINELEN;
    CH  ifname[256];
    ifname[0]=0;

    CH* ptr=text;
    CH* ptr1;
    if(memcmp(ptr,"#include",8)){return NULL;}

    ptr=strchr(ptr+8,'{');
    if(!ptr){return NULL;}

    ptr1=strchr(ptr+1,'}');
    if(!ptr1){return NULL;}
    else{}
#pragma breakpoint
//    ENV* env=findenvironmentstring("include");
//    if(env){strcpy(ifname,env->equ);}

    strcpy(ifname,incpath);
    strncpy(ifname+strlen(ifname),ptr+1,ptr1-ptr-1);

//#pragma breakpoint

    E3* e1;

    UL n=alreadyedited(&ectl,ifname);
    if(n!=-1)
        {
         e1=E+n;
         if(e1->loaded){return e1;}
         ptr=ectl.buf+n*MEMLINELEN;
         if(!loadE3(ptr,e1,1))
             {
              efiles++;return e1;
             }
         return NULL;
        }

    e1=E+efiles;
    if(!loadE3(ifname,e1,0))
        {
#pragma breakpoint
         ectl.cury=0;
         insertblankline(&ectl);
         memcpy(ectl.buf,ifname,strlen(ifname));
         ecur=0;
         efiles++;return e1;
        }
    return NULL;
}

VD  cls(VD)
{
    UL  n;
    for(n=clistartline;nname,&e->wy,&e->wx,&e->cury,&e->curx,&e->lines);
//    UL  archno=e->cf.archive&~0x80000000;
    UL  archno=e->sp.archno;
    displayat(48,0,"|c2%25sc2 (%4lc2,%3lc2) %5lc2 lines %Dc2 %Tc2 v(%5lc2) %4lc2",e->name,&e->cury,&e->curx,&e->lines,&e->sp.date,&e->sp.time,&archno,&udidx);
//    if(e->argtoggle)
//        {
//         displayat(1,60,"%3l %3l %3lw%3lh",&e->argy,&e->argx,&e->argw,&e->argh);
//        }
//    else
//        {
//         displayat(1,60,"|c2                ");
//        }

    if(erroronscreen){return;}

//    displayat(49,0,"|c2                             ");
    SL n,x=0;

    n=e->braces;
    if(n>0)     {while(n--)displayat(49,x++,"|c2%{");}
    else if(n<0){while(n++)displayat(49,x++,"|c2%}");}
    x++;
    n=e->brackets;
    if(n>0)     {while(n--)displayat(49,x++,"|c2[");}
    else if(n<0){while(n++)displayat(49,x++,"|c2]");}
    x++;
    n=e->parentheses;
    if(n>0)     {while(n--)displayat(49,x++,"|c2(");}
    else if(n<0){while(n++)displayat(49,x++,"|c2)");}
    x++;
    n=e->quotes;
    if(n>0){while(n--)displayat(49,x++,"|c2\"");}

}
UL  linelength(CH* str,UL maxlen)
{
    SL n;
    for(n=maxlen-1;n>=0;n--)
        {
         if(str[n]!=0x20){return n+1;}
        }
    return 0;
}
//UL  lflinelength(CH* str,UL maxlen)
//{
//    SL n;
//    for(n=maxlen-1;n>=0;n--)
//        {
//         if(str[n]!=0x0a)
//            {
//             if(str[n]!=0x20){return n+1;}
//            }
//        }
//    return 0;
//}

SL  scan(E3* e,UL errorbreak)
{
    UL n,m,o;
    CH* text=e->buf;
    CH* ptr;
    e->braces=0;
    e->brackets=0;
    e->parentheses=0;
    e->quotes=0;
    UL incomment=0,incppcomment,inquote=0,inccs=0;

    for(n=0;nlines;n++)
        {
         o=linelength(text,MAXLINELEN);
         ptr=text;
         incppcomment=0;
         for(m=0;mbraces++;break;
                         case '}':
                            if(!e->braces)
                                {
                                 if(errorbreak)
                                    {
                                     errordisplay("Closing brace before opening brace");
                                     e->cury=n;
                                     e->curx=ptr-text;
                                     return 1;
                                    }
                                }
                            e->braces--;
                            break;
                         case '[':e->brackets++;break;
                         case ']':
                            if(!e->brackets)
                                {
                                 if(errorbreak)
                                    {
                                     errordisplay("Closing bracket before opening bracket");
                                     e->cury=n;
                                     e->curx=ptr-text;
                                     return 1;
                                    }
                                }
                            e->brackets--;
                            break;
                         case '(':
                            e->parentheses++;break;
                         case ')':
                            if(!e->parentheses)
                                {
                                 if(errorbreak)
                                    {
                                     errordisplay("Closing parenthesis before opening parenthesis");
                                     e->cury=n;
                                     e->curx=ptr-text;
                                     return 1;
                                    }
                                }
                            e->parentheses--;
                            break;
                         case '"':
                            inquote=1;
                            break;
                         case ''':
                            inccs=1;
                            if(*(ptr+1)==''')
                                {//if character immediately following start
                                 //of constant character string is apostrophe
                                 //skip it
                                 ptr++;m++;
                                }
                            break;
                        }
                    }
                }
             ptr++;
            }
         text+=MEMLINELEN;
        }
    e->quotes=inquote;
    return 0;
}

VD  highlight(UL row,UL col,UL colour,UL len);

VD  displayE3(E3* e,UL h,SL yoff)
{
    if(e->modified){scan(e,0);}
    displayE3name(e);

//do autoscroll to bring line into view
    if(e->cury>=e->wy+h)
        {
         while(e->cury>=e->wy+h)
            {
             e->wy+=AUTOSCROLL;
            }
        }
    else if(e->curywy)
        {
         while(e->curywy)
            {
             if(e->wy>AUTOSCROLL)
                 {e->wy-=AUTOSCROLL;}
             else{e->wy=0;}
            }
        }

//do autoscroll to bring column into view
    if(e->curx>=e->wx+80)
        {
         while(e->curx>=e->wx+80)
            {
             e->wx+=10;
            }
        }
    else if(e->curxwx)
        {
         while(e->curxwx)
            {
             if(e->wx>10)
                 {e->wx-=10;}
             else{e->wx=0;}
            }
        }

    AA->fgd=7;

    CH* text=e->buf+e->wy*MEMLINELEN;

    UL  n;
    SL  len;
    SL  tlen;
    UL  hw;
    for(n=0;nwy>=e->lines){break;}

         len=linelength(text,MAXLINELEN);
         tlen=len-e->wx;
         if(tlen>80)
            {
             (*AA->putstrn)(AA->usr,text+e->wx,n+yoff,0,80);
            }
         else if(tlen>0)
            {
             (*AA->putstrn)(AA->usr,text+e->wx,n+yoff,0,tlen);
             if(tlen<80)
                {
                 (*AA->putstrn)(AA->usr,blankline,n+yoff,tlen,80-tlen);
                }
            }
         else
            {
             (*AA->putstrn)(AA->usr,blankline,n+yoff,0,80);
            }
         if(e->argtoggle)
            {
             if(e->wy+n>=e->argy)
                {
                 //if(e->wy+nargy+e->argh)
                 if(e->wy+n<=e->argh)
                    {
                //     brk
                     hw=e->argw-e->argx+1;
                     if(hw>128){hw=128;}
//                     highlight(n+yoff,e->argx-e->wx,0x70,hw);
                     AA->bgd=7;
                     AA->fgd=0;
                     (*AA->putstrn)(AA->usr,text+e->argx,n+yoff,e->argx,hw);
                     AA->bgd=0;
                     AA->fgd=7;
                    }
                }
            }
         text+=MEMLINELEN;
        }
    while(nputstrn)(AA->usr,blankline,n+yoff,0,80);
         n++;
        }

    (*AA->setcurpos)(AA->usr,e->cury-e->wy+yoff,e->curx-e->wx);
    if(insert)                          //if insert on
        {(*AA->setcursiz)(AA->usr,0x0007);}            //set block cursor
    else{(*AA->setcursiz)(AA->usr,0x0607);}

}

VD  displaymacros(VD);
VD  displayentb  (VD);
VD  displaysources(VD);
VD  topascalstr(CH* str,CH* pstr);

    CH  findstring [64];
    CH  pfindstring[64];
    CH  repstring  [64];
    CH  prepstring [64];
    CH  findproto  [64];
    CH  pfindproto [64];
    CH  hlinktext    [64];
    CH  hlinktarget  [64];

SL  command(UL argc,CH** argv,UL istsr,UL dbg,UL mp);

SL  shellcompile(E3* e)
{
    CH* argv[3];
    argv[0]="cc";
    argv[1]=e->name;
    argv[2]=NULL;

    return command(2,&argv,0,0,0);
}
SL  shellhtml(E3* e)
{
    CH* argv[3];
    argv[0]="grtest";
    argv[1]=e->name;
    argv[2]=NULL;

    return command(2,&argv,0,0,0);
}

E3* reload(E3* e)
{
//brk
    if(e==&ectl){return e;}
    BOX bp      ={18, 8 ,26,62};
    CH* ptr=dsavebox(&bp);
    UL  ecur;
    dclear(&bp,0);
    dbox1(&bp,-1,"Reload:",0x20);
    E3 etmp;
    memset(&etmp,0,sizeof(E3));

    displayat(20, 9,"Revert to saved version of:");
    displayat(21, 9,"       [%32s]?",e->name);
L01:
    dvblit();
    switch(getkey()&0xffff)
        {
         case 'y':
         case 'Y':
         case (SHIFT|'y'):
            if(loadE3(e->name,&etmp,0))
                {
                 displayat(23,9,"|c1500Couldn't reload file - continuing with current");
                 dvblit();
                 getkey();return e;
                }
            etmp.wx=e->wx;
            etmp.wy=e->wy;
            etmp.curx=e->curx;
            etmp.cury=e->cury;
            destroy(e);
            *e=etmp;
            e->loaded=1;
            scan(e,0);
            break;
         case 'n':
         case 'N':
         case (SHIFT|'n'):
         case ESC:
            break;
         default:
            goto L01;
        }

    drestorebox(&bp,    ptr);
    return e;
}

VD  dorevsearch(E3* e,CH* str)
{
    CH* text=e->buf+e->cury*MEMLINELEN;
    CH* end=e->buf+e->lines*MEMLINELEN;
    UL wrap;
    UL hit=0;
    CH* ptr1;

    if(str)
        {
         strcpy(findstring,str);
         spacestonulls(findstring,32);
         topascalstr(findstring,pfindstring);
         ptr1=text+e->curx-1;

         while(text>=e->buf)
            {
             while(ptr1>=text)
                {
                 if(!memcmp(ptr1,findstring,*pfindstring))
                    {
                     e->curx=ptr1-text;
                     e->cury=(text-e->buf)/MEMLINELEN;
                     hit=1;e->argtoggle=0;return;
                    }
                 ptr1--;
                }
             text-=MEMLINELEN;
             while(!linelength(text,MAXLINELEN))
                {
                 if(text<=e->buf){break;}
                 text-=MEMLINELEN;
                }
             ptr1=text+linelength(text,MAXLINELEN)-1;
            }
         if(!hit)
            {
             errordisplay("Not found:");
             dvblit();
             getkey();
             return;
            }
        }
}
VD  dosearch(E3* e,CH* str)
{
    CH* text=e->buf+e->cury*MEMLINELEN;
    CH* end=e->buf+e->lines*MEMLINELEN;
    UL wrap;
    UL hit=0;
    CH* ptr1;

    if(str)
        {
         strcpy(findstring,str);
         spacestonulls(findstring,32);
         topascalstr(findstring,pfindstring);
         ptr1=text+e->curx+1;

         while(textcurx=ptr1-text;
                     e->cury=(text-e->buf)/MEMLINELEN;
                     hit=1;e->argtoggle=0;return;
                    }
                 ptr1++;
                }
             text+=MEMLINELEN;
             ptr1=text;
            }
         if(!hit)
            {
             errordisplay("Not found:");
             dvblit();
             getkey();
             return;
            }
        }
//brk
    BOX bp      ={18, 8 ,26,62};
    CH* ptr=dsavebox(&bp);
    dclear(&bp,0);
    dbox1(&bp,-1,"Find:",0x20);

L01:
    dvblit();
    wrap=0;
    if(!acceptat(20, 9,"Find string:[%32s]",findstring))
        {
         spacestonulls(findstring,32);
         topascalstr(findstring,pfindstring);
         ptr1=text+e->curx+1;
L02:
         while(textcurx=ptr1-text;
                     e->cury=(text-e->buf)/MEMLINELEN;
                     hit=1;goto L03;
                    }
                 ptr1++;
                }
             text+=MEMLINELEN;
             ptr1=text;
             if(wrap){if(text>=e->buf){break;}}
            }
         if(!wrap)
            {
             if(text>=end){wrap=1;text=e->buf;goto L02;}
            }
L03:
         if(!hit)
            {
             displayat(25, 9,"|c1500%s not found: press a key",findstring);
             dvblit();
             getkey();
             displayat(25, 9,"                                           ");
             goto L01;
            }
        }
    drestorebox(&bp,    ptr);
}
SL  optionkey(VD);
VD  dosearchandreplace(E3* e,CH* str,UL global)
{
    CH* text=e->buf+e->cury*MEMLINELEN;
    CH* end=e->buf+e->lines*MEMLINELEN;
    UL wrap=0;
    SL hit=0,aut=0,n,m,o;
    CH* ptr1;
    if(global)
         {
          text=e->buf;
          e->curx=e->cury=0;
          goto L01a;
         }
    else if(str)
        {
         strcpy(findstring,str);
         spacestonulls(findstring,32);
         topascalstr(findstring,pfindstring);
         ptr1=text+e->curx+1;

         while(textcurx=ptr1-text;
                     e->cury=(text-e->buf)/MEMLINELEN;
                     hit=1;e->argtoggle=0;return;
                    }
                 ptr1++;
                }
             text+=MEMLINELEN;
             ptr1=text;
            }
         if(!hit)
            {
             errordisplay("Not found:");
             dvblit();
             getkey();
             return;
            }
        }
//brk
    BOX bp      ={18, 8 ,26,62};
L00:CH* ptr=dsavebox(&bp);
    dclear(&bp,0);
    dbox1(&bp,-1,"Find:",0x20);
//    UL fsi=strtol(findstring,NULL,10);
//    findstring[0]=0;fsi++;
//    catprint(findstring,"%3l",&fsi);
//    repstring[0]=0;fsi-=115;
//    catprint(repstring,"F+%03l",&fsi);

L01:
    dvblit();
    wrap=0;
    if(!accept("|p2010 Replace:[%32s]|p2110   With:[%32s]",findstring,repstring))
        {
L01a:    trailingspacestonulls(findstring,32);
         topascalstr(findstring,pfindstring);
         trailingspacestonulls(repstring,32);
         topascalstr(repstring,prepstring);
         ptr1=text+e->curx;
L02:
         while(textcurx=ptr1-text;
                     e->cury=(text-e->buf)/MEMLINELEN;
                     hit=1;goto L03;
                    }
                 ptr1++;
                }
             text+=MEMLINELEN;
             ptr1=text;
             if(wrap){if(text>=e->buf){break;}}
            }
         if(!wrap)
            {
             if(text>=end){wrap=1;text=e->buf;goto L02;}
            }
L03:
         if(!hit)
            {
             if(aut)
                {
                 if(!global){drestorebox(&bp,ptr);}
                 return;
                }
             dcat(49, 0,"|c1500%s not found: press a key",findstring);
             dvblit();
//             getkey();
             if(!global){drestorebox(&bp,ptr);}
             clearerrorline(e);
             return;
            }
         else
            {
             if(!global){drestorebox(&bp,ptr);}
             displayE3(e,43,2);
             if(aut){goto L05;}
             errordisplay("Replace (Y)es/(N)o/(A)ll/ESC");
L04:         switch(optionkey())
                {
                 case 'y':case 'Y':case (SHIFT|'y'):
L05:                n=linelength(text,MAXLINELEN);
                    o=n-e->curx-*pfindstring;
                    if(o){memmove(text+e->curx+*prepstring,text+e->curx+*pfindstring,o);}
                    memcpy(text+e->curx,repstring,*prepstring);
                    o=*pfindstring-*prepstring;
                    //blanks over end of shortened line
                    if(o>0){memset(text+n-o,0x20,o);}
                    e->modified=1;
                 case 'n':case 'N':case (SHIFT|'n'):
                    e->curx+=*prepstring;
                    ptr1=text+e->curx;
                    if(!global){ptr=dsavebox(&bp);}
                    hit=0;goto L02;
                    break;
                 case ESC:
                    break;
                 case 'a':case 'A':case (SHIFT|'a'):
                    aut=1;
                    if(!global){ptr=dsavebox(&bp);}
                    hit=0;goto L02;
                 default:
                    goto L04;
                }
             return;
            }
        }
    if(!global){drestorebox(&bp,ptr);}
}

EX  UL  OSbase;
SYMBOL* findglobalsymbol    (CBJHEADER* c,CH* name);
SYMBOL* findnextglobalsymbol(SYMBOL* s,CH* name);
VD  displaytype(CBJHEADER* c,UL typidx,CH* buf,UL flag);
TYPDEF* getusertype(CBJHEADER* c,UL typidx);


VD  displayprototype(CBJHEADER* c,UL typidx,CH* buf,CH* name);


VD  dofindprototype(E3* e)
{
    BOX bp      ={18, 8 ,26,62};
    CH* ptr=dsavebox(&bp);
    CH* text=e->buf+e->cury*MEMLINELEN;
    CH* end=text+e->lines*MEMLINELEN;
    CH* ptr1;
    dclear(&bp,0);
    dbox1(&bp,-1,"Find:",0x20);

    UL wrap;
    UL hit=0;
    SYMBOL* s;
    CBJHEADER* os=(CBJHEADER*)OSbase;
    CH  buf[1024];
    TYPDEF* tn;

L01:
    dvblit();
    wrap=0;
    if(!acceptat(20, 9,"Find prototype:[%32s]",findproto))
        {
         spacestonulls(findproto,32);
         topascalstr(findproto,pfindproto);

         s=findglobalsymbol(os,pfindproto);
         if(s)
            {
             if(s->type&tFUNC)
                {
                 L02:
                 displayprototype(os,s->type,buf,s->name);
                 displayat(23, 9,"|c1500%s",buf);
                 displayat(25, 9,"|c1500Copy prototype (Yes/Next/ESC)?");
                 dvblit();
                 switch(getkey()&0xffff)
                    {
                     case 'y':
                        insertblankline(e);
                        text=e->buf+e->cury*MEMLINELEN;
                        strcpy(text,buf);
                        UL n=strlen(text);
                        text[n]=0x20;
                        break;
                     case 'n':
                        while(s)
                            {
                             s=findnextglobalsymbol(s,pfindproto);
                             if(s->type&tFUNC){goto L02;}
                            }
                        displayat(25, 9,"No more matches: press a key");
                        dvblit();
                        getkey();goto DONE;
                     case ESC:
                        break;
                    }
                }
             goto DONE;
            }
         else
            {
             displayat(25, 9,"|c1500%s not found: press a key",findproto);
            }
         dvblit();
         getkey();
        }
DONE:
    drestorebox(&bp,    ptr);
}
VD  revstrcpy(CH* str1,CH* str2)
{
    UL  len=strlen(str2);
    str2+=len-1;
    while(len--){*str1++=*str2--;}
    *str1=0;
}
VD  doinserthyperlink(E3* e)
{
    BOX bp      ={18, 8 ,26,62};
    CH* ptr=dsavebox(&bp);
    CH* text=e->buf+e->cury*MEMLINELEN;
    CH* end=text+e->lines*MEMLINELEN;
    CH* ptr1;
    dclear(&bp,0);
    dbox1(&bp,-1,"Insert Hyperlink:",0x20);

    UL wrap;
    UL hit=0;
    SYMBOL* s;
    CBJHEADER* os=(CBJHEADER*)OSbase;
    CH  buf[1024];
    TYPDEF* tn;

L01:
    dvblit();
    if(!accept("|p2009Link text:[%32s]|p2109Target:[%32s]",hlinktext,hlinktarget))
        {
         spacestonulls(hlinktext,32);
         spacestonulls(hlinktarget,32);
         text=e->buf+e->cury*MEMLINELEN+e->curx;
      revstrcpy(text,"//:ptth\x22=ferh \x22\x22=eltit a<");
         strcat(text,hlinktarget);
         strcat(text,"\x22>");
         strcat(text,hlinktext);
         strcat(text,"");
        }
DONE:
    drestorebox(&bp,    ptr);
}
VD  inserttext(E3* e,CH* text)
{
    UL n=strlen(text);
    CH* ptr=e->buf+e->cury*MEMLINELEN+e->curx;
    UL tomove=MAXLINELEN-e->curx-n;
    memmove(ptr+n,ptr,tomove);
    memcpy(ptr,text,n);
    e->curx+=n;
}
VD  inserttextline(E3* e,CH* text)
{
    insertblankline(e);
    CH* ptr=e->buf+e->cury*MEMLINELEN;
    UL n=strlen(text);
    memcpy(ptr,text,n);
}
VD  doinsertmainfunction(E3* e)
{
    inserttextline(e,"}");
    inserttextline(e,"    return 0;");
    insertblankline(e);
    inserttextline(e,"{");
    inserttextline(e,"SL  main(UL argc,CH* argv[])");
    e->curx=0;
    e->cury++;
    e->cury++;
    e->curx=4;
}
VD  catline(E3* e,CH* ptr)
{
    CH* text=e->buf+e->cury*MEMLINELEN;
    text+=linelength(text,MAXLINELEN);
    memcpy(text,ptr,strlen(ptr));
}
//functions which insert HTML tags into the source file:
//these are awkward as HTML browsers will locate any <...> pairs
//and try to interpret these as HTML tags. So a complete HTML tag
//never exists in the source code or data - it is built from smaller
//chunks at run-time
VD  doinserthtmlprologue(E3* e)
{
//ant function which inserts html tags
    inserttextline(e,"<");
    catline(e,"html><");
    catline(e,"head><");
    catline(e,"title><");
    catline(e,"/title><");
    catline(e,"/head><");
    catline(e,"body bgcolor=\"#99ccFF\"><");
    catline(e,"pre><");
    catline(e,"chaos ext=\"");
    CH* ptr=strchr(e->name,'.');
    if(ptr){catline(e,ptr);}
    catline(e,"\">");
}
VD  doinserthtmlepilogue(E3* e)
{
//ant function which inserts html tags
    inserttextline(e,"<");
    catline(e,"/chaos><");
    catline(e,"/pre><");
    catline(e,"/body><");
    catline(e,"/html>");
}
VD  dospecialfunction(E3* e)
{
    CH* line=e->buf+e->cury*MEMLINELEN;
    CH* ptr=line;
    CH* str;
    UL  n;
    CH  newline[512];
    memset(newline,0,512);
    DB  lat,lng;
    for(n=0;n<5;n++)
        {
         lat=strtod(ptr,&ptr);
         if(lat==-1){break;}
         if(*ptr=='-'){lat=-lat;str="S";}else{str="N";}
         catprint(newline,"{0,%05.2d%1s,",&lat,str);
         ptr++;
         lng=strtod(ptr,&ptr);
         if(lng<=0){      str="W";}else{str="E";}
         catprint(newline,"%06.2d%1s},",&lng,str);
        }
    nullstospaces(newline,MAXLINELEN);
    memcpy(line,newline,MAXLINELEN);
    e->cury++;
}
SL  makehighlightbox(E3* e)
{
    if(e->cury<=e->argy)        {e->argy=e->cury;}
    else                        {e->argh=e->cury;}
    if(e->curx<=e->argx)        {e->argx=e->curx;}
    else if(e->argw!=MAXLINELEN){e->argw=e->curx;}

    UL  w=e->argw-e->argx+1;
    UL  h=e->argh-e->argy+1;
    if(w>1){return 2;}
    if(h>1){return 2;}
    return 1;
}
VD  saveargbuffer  (E3* e);
VD  insertargbuffer(E3* e);
VD  deleteargbuffer(E3* e);
//VD  printargbuffer (E3* e);

    CH  linearg[128];
    CH* lineargptr=linearg;

VD  handleargchar(E3* e,UL key)
{

    switch(key)
        {
         case ENTER:
         case NUMENTER:
         case TAB:
         case (SHIFT|TAB):
            break;
         case NDEL:
            if(e->argtoggle==1)
                {
                 if(lineargptr>linearg){lineargptr--;}
                 *lineargptr=0;
                }
            else if(e->argtoggle==2)
                {
                 deleteargbuffer(e);
                }
            break;
         case NLCUR:
         case BACKSPACE:
            if(e->argtoggle==1)
                {
                 if(lineargptr>linearg){lineargptr--;}
                 *lineargptr=0;
                }
            break;
         default:
            e->argx=e->argw=e->curx;
            e->argy=e->argh=e->cury;
            *lineargptr++=key;
            *lineargptr=0;
            break;
        }
}

EX  CH  scratch[2048];

SL  viewE3(E3* e)
{
    UL  n,rows=46;
    SL  yoff=2;
    E3* e1;

    displayE3(e,rows,yoff);

    UL  key=1;
    UL  disp=0;
    LINE* ls;
    CH* ptr;
    CH* text;

    while(key)
        {
//         dvblit();
         key=getkey()&0xffff;
         disp=1;
         switch(key)
            {
//             case BACKSPACE:
             case (SHIFT|NLCUR):
                if(e->argtoggle)
                    {
                     if(e->curx)
                        {
                         e->curx--;
                         e->argx--;
                         e->argw--;
                         break;
                        }
                    }
                else if(e->wx>0)
                   {
                    e->wx--;
                    if(e->curx){e->curx--;}
                   }
        //        break;
             case NLCUR:
                if(e->curx)
                    {
                     if(e->argtoggle)
                        {
                         if(e->curx==e->argw){e->argw--;}
                        }
                     e->curx--;
                    }
                else if(e->cury)
                    {
                     text=e->buf+e->cury*MEMLINELEN;
                     text-=MEMLINELEN;
                     n=linelength(text,MAXLINELEN);
                     e->cury--;
                     e->curx=n;
                    }
                break;
             case (SHIFT|NRCUR):
                if(e->argtoggle)
                    {
                     if(e->curxcurx++;
                         e->argx++;
                         e->argw++;
                         break;
                        }
                    }
//                else
//                    {
//                     e->wx++;
//                     e->curx++;
//                    }
//                else if(e->curx-e->wx>70)
//                    {
//                     e->wx+=10;
//                    }
//                break;
             case NRCUR:
                if(e->curxcurx++;
                   }
                break;
             case (SHIFT|NUCUR):
                if(e->argtoggle)
                    {
                     if(e->cury)
                        {
                         e->argy--;
                         e->argh--;
                         e->cury--;
                         break;
                        }
                    }
             case NUCUR:
                if(e->cury)
                    {
                     if(e->argtoggle)
                        {
                         if(e->cury==e->argh){e->argh--;}
                        }
                     if(e->wy==e->cury)
                        {
                         if(e->wy>=AUTOSCROLL)
                            {
                             e->wy-=AUTOSCROLL;
                            }
                         else
                            {
                             e->wy=0;
                            }
                        }
                     e->cury--;
                    }
                break;
             case (SHIFT|NDCUR):
                if(e->argtoggle)
                    {
                     e->cury++;
                     e->argy++;
                     e->argh++;
                     break;
                    }
             case NDCUR:
                DOWNCURSOR:
//                if(e->curylines-1)
                if(e->argtoggle)
                    {
                     if(e->argx==e->argw)
                        {
                         e->argx=0;
                         e->argw=MAXLINELEN;
                        }
                    }
                if(e->curymaxlines)
                    {
                     if(e->wy+rows-1==e->cury)
                        {
                         e->wy+=AUTOSCROLL;
                        }
                     e->cury++;
                    }
                break;
//             case (SHIFT|NUCUR):
//                if(e->wy){e->wy--;}
//                break;
//             case (SHIFT|NDCUR):
//                e->wy++;
//                break;
             case NPGDN:
                if(e->lines)
                    {
                     if(e->wylines-1)
                         {
                          e->wy+=VSCROLLINC;
                          e->cury+=VSCROLLINC;
                         }
                    }
                break;
             case NPGUP:
                if(e->wy>=VSCROLLINC)  {e->wy  -=VSCROLLINC;}
                else                   {e->wy   =0;}
                if(e->cury>=VSCROLLINC){e->cury-=VSCROLLINC;}
                else                   {e->cury =0;}
                break;
             case NHOME:
                if(e->curx){e->curx=0;}
                else
                    {
                     e->cury=e->wy;
                    }
                break;
             case NEND:
                text=e->buf+e->cury*MEMLINELEN;
                e->curx=linelength(text,MAXLINELEN);
                break;
             case (CTRL|NHOME):
                e->wy=e->wx=e->cury=e->curx=0;
                break;
             case (CTRL|NEND):
                if(e->lines>VSCROLLINC)
                    {
                     e->wy=e->lines-VSCROLLINC;
                    }
                else
                    {
                     e->wy=0;
                    }
                e->wx=0;
                e->cury=e->lines-1;
                e->curx=0;
                break;
             case (CTRL|F1):
//                text=e->buf+e->cury*MEMLINELEN+e->curx;
//                memmove(text+2,text,MEMLINELEN-e->curx-2);
                text=e->buf+e->cury*MEMLINELEN;
                n=linelength(text,MAXLINELEN);
                memmove(text+2,text,n);
                *text++='/';
                *text='/';
                e->modified=1;
                goto DOWNCURSOR;
                break;
             case (SHIFT|F1):
                text=e->buf+e->cury*MEMLINELEN;
                ptr=strchr(text,'/');
                if(ptrmodified=1;
                break;
             case F3:
                insertblankline(e);
                break;
             case F4:
                deleteline(e);
                break;
             case F5:
                if(e->argtoggle)
                    {
                     saveargbuffer(e);
                     e->argtoggle=0;
                     insertargbuffer(e);
                    }
                else
                    {
                     repeatline(e);
                    }
                break;
             case F6:
                retypeline(e);
                break;
             case F7:
                insertblock(e);
                break;
             case (CTRL|F7):
                clearundeletebuffer();
                break;
//             case F9:
//                insertblankline(e);
//                nullstospaces(scratch,MAXLINELEN);
//                n=linelength(scratch,MAXLINELEN);
//                text=e->buf+e->cury*MEMLINELEN;
//                memcpy(text,scratch,n);
//                trailingspacestonulls(scratch,MAXLINELEN);
//                break;
             case (ALT|F9):
                dospecialfunction(e);e->modified=1;
                break;
//             case F11:
//                printargbuffer(e);
//                break;
             case (ALT|F3):
                e=reload(e);
                break;
             case F1:
                if(e->argtoggle)
                    {
                     e->curx=e->argx;
                     e->cury=e->argy;
                     lineargptr=linearg;
                     *lineargptr=0;
                     e->argtoggle=0;
                    }
                else
                    {
                     lineargptr=linearg;
                     *lineargptr=0;
                     e->argtoggle=1;
                    }
                e->argx=e->argw=e->curx;
                e->argy=e->argh=e->cury;
                break;
//             case (ALT|'m'):
//                displaymacros();
//                dvblit();
//                getkey();
//                break;
//             case (ALT|'n'):
//                displayentb();
//                dvblit();
//                getkey();
//                break;
//             case (ALT|'s'):
//                displaysources();
//                dvblit();
//                getkey();
//                break;
             case (CTRL|'s'):
                dosearch(e,NULL);
                break;
             case (CTRL|'r'):
                dosearchandreplace(e,NULL,0);
                break;
             case (CTRL|F2):
                e->argtoggle=0;
                if(*linearg){dosearch(e,linearg);}
                else if(*findstring){dosearch(e,findstring);}
                else {errordisplay("No search string");}
                break;
             case (CTRL|F3):
                e->argtoggle=0;
                if(*linearg){dorevsearch(e,linearg);}
                else if(*findstring){dorevsearch(e,findstring);}
                else {errordisplay("No search string");}
                break;
             case (CTRL|F4):
                doinserthtmlprologue(e);
                break;
             case (CTRL|F5):
                doinserthtmlepilogue(e);
                break;
             case (CTRL|F6):
                doinserthyperlink(e);
                break;
             case (CTRL|'f'):
                inserttext(e,"for(n=0;n<;n++)");e->curx-=4;
                e->curx--;
                break;
             case (CTRL|'p'):
                dofindprototype(e);
                break;
             case (CTRL|'m'):
                doinsertmainfunction(e);
                break;
             case (CTRL|'d'):
                inserttextline(e,"#define ");
                e->curx=8;
                break;
//             case (CTRL|'r'):
//                inserttext(e,"return;");
//                e->curx--;
//                break;
             case (CTRL|'i'):
                inserttextline(e,"#include {.htm}");
                e->curx=10;
                break;
             case (SHIFT|NUMENTER):
                if(e->argtoggle)
                    {
                     saveargbuffer(e);
                     e->argtoggle=0;
                    }
                else
                    {
                     insertargbuffer(e);
                    }
                break;
             case CTRL|'q':
                dosearchandreplace(e,NULL,1);
                break;
             case ESC:
             case F2:   //return to compile file//
             case F9:   //return to view as html//
             case F10:
             case F12:
             case F8:
                return key;
             case NINS:
                insert^=1;
                break;
             case TAB:
             case (SHIFT|TAB):
             case ENTER:
             case NUMENTER:
             case NDEL:
             case BACKSPACE:
                if(e->argtoggle){handleargchar(e,key);}
                else            {handleeditchar(e,key);}
                break;
//             case LCTRLKEY:
             case (CTRL|'`'):
                n=viewE3(&ectl);
                if(ectl.modified)
                    {
                     saveE3(&ectl,1);return F12;
                    }
                break;
             case LALTKEY:
                break;
             case (ALT|'i'):
                e1=loadincludefile(e);
                if(e1)
                    {
                     viewE3(e1);
                    }
                break;
             default:
                if(isprint(key))
                    {
                     if(!e->argtoggle)
                        {
                         handleeditchar(e,key);
                        }
                     else
                        {
                         handleargchar(e,key);
                        }
                    }
                break;

            }
         if(e->argtoggle)
            {
             e->argtoggle=makehighlightbox(e);
            }


         if(disp){displayE3(e,rows,yoff);}
         clearerrorline(e);
         erroronscreen++;
         if(strlen(linearg))
            {
             errordisplay(linearg);
             //erroronscreen--;
            }
//         text=e->buf+e->cury*MEMLINELEN;
//         n=linelength(text,MAXLINELEN);
//         (*AA->putstrn)(AA->usr,text,49,0,n);
//         (*AA->putstrn)(AA->usr,"<-",49,n,2);
        }
}

    UC* scrnsave;
    UL  ginsert;        //note global insert sense
EX  UL  kbdstate;

UC* vesasavescreen(VD);
VD  vesarestorescreen(UC* mem);

SL  savescreen(VD)
{
//allocate memory for undelete buffer, otherwise exit before altering screen
    if(makeundeletebuffer()){return 1;}
//preserve cli() screen, and insert sense
    scrnsave=vesasavescreen();
    if(!scrnsave)
        {
         clidisplay("Insufficient memory");return 1;
        }
    displayat(0,0,banner);
    displayat(1,0,"%80sc2",blankline);
    ginsert=kbdstate&INSERT;


    return 0;
}
SL  restorescreen(VD)
{
//restore cli() screen, and insert sense
    vesarestorescreen(scrnsave);
    if(ginsert){kbdstate|=INSERT;}
    else       {kbdstate&=~INSERT;}

    if(destroyundeletebuffer()){return 1;}

    return 0;
}
CH* textcur(E3* e)
{
    return e->buf+e->cury*MEMLINELEN;
}
//UC* loadfile(CH* fname,CHAOSFILE* cf,PATH* sp)
//{
//    if(splitpath(fname,sp))
//        {
//         clidisplay("Illegal file name %s",fname);return NULL;
//        }
//    UL fsiz;
//    return cfupload(cf,sp,&fsiz);
//}
SL  loadfile(UL idx)
{
    CH* ptr=ectl.buf+idx*MEMLINELEN;
    E3* e1;
    UL  n;
    if(*ptr)
        {
         n=alreadyedited(&ectl,ptr);
         if(n!=-1)
            {
             e1=E+n;
             if(e1->loaded){return n;}
             if(!loadE3(ptr,e1,1))
                {
                 efiles++;return n;
                }
             return ecur;
            }
        }
    return -1;
}
SL  choosefile(CH* name)
{
    CH* ptr;
    E3* e1;
    UL  n;
    if(name)
    {
    n=alreadyedited(&ectl,name);
    if(n!=-1)
        {
         e1=E+n;
         if(e1->loaded){return n;}
         ptr=ectl.buf+n*MEMLINELEN;
         if(!loadE3(ptr,e1,1))
             {
              efiles++;return n;
             }
         return ecur;
        }
    else
        {
        // brk
         e1=E+efiles;
         if(!loadE3(name,e1,0))
             {
              if(ectl.lines==MAXEFILES)
                   {ectl.cury=ectl.lines-1;errordisplay("e.con file full");}
              else {ectl.cury=ectl.lines;}
              //insertblankline(&ectl);
              ptr=textcur(&ectl);
              memset(ptr,0x20,MAXLINELEN);
              memcpy(ptr,name,strlen(name));
              if(ectl.linesectl.lines){contents=ectl.lines;}
    CH* text;
    BOXCUR bc={contents,ectl.lines,10,0,ecur};
    if(ecur>contents){bc.start=ecur-contents+1;}
    hilite(&b,ecur-bc.start,0x70);

L01:
    for(n=0;n=efiles){efiles=lastcur+1;}
    return lastcur;
}

#include {i86.htm}
EX  pdesc   IDTcopy;
EX  pdesc   GDTcopy;

SL  runcompiler(E3* ein);

SL main(UL argc,CH** argv)
{
    CH* ptr;
    UC* buf;
    LSEQ* L;
    LINE* li;
    LDRIVE* l=LDcur;
    PATH sp;
    CHAOSFILE cf;
    CH  fname[256];
    E3* e;
    UL  n,ret;
    CH* text;

//    strcpy(findstring,"114");
//    strcpy(repstring,"F+000");

    UL  createfileonentry=0;

    memset(blankline,0x20,255);
    if(argc>2)
        {
         clidisplay("Too many arguments, Usage:ED ");return 1;
        }
    else if(argc==2)
        {
//         if(l->filesystem!=CHAOS)
//            {
//             clidisplay("Current drive %s is not a ChaOS drive",l->tag);
//             return 1;
//            }
         e=E;
         if(loadE3(argv[1],e,0))
            {
//             clidisplay("File %s not found",argv[1]);
             clidisplay("File %s does not exist; create Y/N?",argv[1]);
             switch(optionkey())
                {
                 default:
                    return 1;
                 case 'y':
                    if(createnewE3(e,argv[1])){return 1;}
                    createfileonentry=1;
                    break;
                }
            }
         e->loaded=1;
         efiles++;
         if(loadE3(ctfname,&ectl,0))
            {
             if(createcontrolfile(&ectl))
                {
                 clidisplay("couldn't create control file");return 1;
                }
             else
                {
                 strcpy(ectl.buf,argv[1]);ectl.lines=1;
                }
            }
         else
            {
             ecur=alreadyedited(&ectl,argv[1]);
             if(ecur==-1)
                {
                 if(!insertblankline(&ectl))
                    {
                     strcpy(ectl.buf,argv[1]);
                    }
                 ecur=0;
                }
             else
                {
                 if(!createfileonentry)
                    {
                     destroy(e);
                     efiles--;
                     e->loaded=0;
                    }
                 if(savescreen()){return 1;}
                 goto LOADNEXT;
                }
            }
         if(savescreen()){return 1;}
         goto VIEWNEXT;
        }
    else
        {
//         if(l->filesystem!=CHAOS)
//            {
//             clidisplay("Current drive %s is not a ChaOS drive",l->tag);
//             return 1;
//            }
         if(loadE3(ctfname,&ectl,0))
            {
             clidisplay("No control file: use ED  to edit a file");
             return 1;
            }

         if(savescreen()){return 1;}

LOADNEXT:
         e=E+ecur;
         text=ectl.buf+ecur*MEMLINELEN;
         if(!e->loaded)
            {
             if(loadE3(text,e,1))
                {
//                 clidisplay("File  %s not found",text);
                 ptr=strchr(text,' ');
                 if(!ptr){brk strcpy(fname,text);}
                 else    {strncpy(fname,text,ptr-text);}
                 fname[ptr-text]=0;
                 displayat(49,0,"|c1500File %s does not exist; create Y/N/Quit?",fname);
                 switch(optionkey())
                    {
                     case 'y':
                        if(!createnewE3(e,fname)){break;}
                     default:
                        ecur++;
                        text=ectl.buf+ecur*MEMLINELEN;
                        if(*text==0x20){ecur=0;}
                        erroronscreen++;
                        clearerrorline(e);
                        goto LOADNEXT;
                     case ESC:
                     case 'q':
                        ectl.cury=ecur;
                        deleteline(&ectl);
                        ecur=0;
                        erroronscreen++;
                        restorescreen();
                        goto DONE;
                    }
                }
             e->loaded=1;
             efiles++;
            }
VIEWNEXT:
         //scan(e,0);
//         errordisplay("Press F10 to exit");
         ret=viewE3(e);

         switch(ret)
            {
             case F2:
                if(e->modified){saveE3(e,1);}
                if(scan(e,1))
                    {
                    }
                else if(e->braces)
                    {
                     errordisplay("Can't compile: unbalanced braces");
                    }
                else if(e->brackets)
                    {
                     errordisplay("Can't compile: unbalanced brackets");
                    }
                else if(e->parentheses)
                    {
                     errordisplay("Can't compile: unbalanced parentheses");
                    }
                else if(e->quotes)
                    {
                     errordisplay("Can't compile: unbalanced quotes");
                    }
                else
                    {
                     if(!shellcompile(e))
                        {
                         errordisplay("Compiled OK");
                        }
//                     if(!runcompiler(e))
//                        {
//                         errordisplay("Compiled OK");
//                        }
//                     getkey();
                    }
                goto VIEWNEXT;
                break;
             case F9:
                if(e->modified){saveE3(e,1);}
                shellhtml(e);
                goto VIEWNEXT;
                break;
             case F10:
             case F12:
                break;
             case ESC:
//                if(ecurargtoggle=0;}
                goto LOADNEXT;
                break;
             case F8:
                if(efiles>1)
                    {
                     if(!ecur){ecur=loadfile(1);}
                     else     {ecur=loadfile(0);}
                    }
                goto LOADNEXT;
                break;
            }
         restorescreen();
        }
DONE:
    if(ret!=F12)
        {
//         brk
         if(savecontrolfile(&ectl))
             {
              clidisplay("Error saving control file %s",ectl.name);
             }
        }

    e=E;
    for(n=0;nloaded)
            {
             if(e->modified)
                {
                 if(ret!=F12){saveE3(e,0);}
                }
             destroy(e);
            }
         e++;
        }

    ectl.loaded=1;//!otherwise destroy(ectl) doesn't free ectl.buf!
    destroy(&ectl);
//    cleanup();
    return 0;
}



SL  epatch(LSEQ* L,UL size)
{
    UL  ctr=0,n;
    UI  isrc;
    CH* ptr=L->buf;
    CH* end=L->buf+size;
    LINE* l;
    LINE* lp;

    while(ptr!=end)
        {
         isrc=*(UI*)ptr;
         if(isrc==ENDOFLINE){ctr++;ptr+=2;}
         else if(*ptr==0x0a){ctr++;ptr++;}
         else {ptr++;}
        }

    L->lines=ctr;
    L->line=(LINE*)calloc(sizeof(LINE),L->lines+EDITEXTRAS);
    if(L->line==NULL)
        {
         clidisplay("Insufficient memory");
         free(L->buf);free(L);return 1;
        }

    lp=NULL;
    l=L->line;
    ptr=L->buf;
    l->text=ptr;


    while(ptr!=end)
        {
         isrc=*(UI*)ptr;
         if(isrc==ENDOFLINE)
            {
             l->len=ptr-l->text;
             *(l->text+l->len)=0;
             l->prev=lp;
             if(lp!=NULL){lp->next=l;}
             lp=l;
             l++;
             ptr+=2;
             l->text=ptr;
            }
         else if(*ptr==0x0a)
            {
             l->len=ptr-l->text;
             *(l->text+l->len)=0;
             l->prev=lp;
             if(lp!=NULL){lp->next=l;}
             lp=l;
             l++;
             ptr++;
             l->text=ptr;
            }
         else {ptr++;}
        }

    return 0;
}
//SL  createeditbuffer(E3* e)
//{
//    LSEQ* L=e->L;
//    CH* ptr;
//    UL  buflen=MEMLINELEN*(L->lines+EDITEXTRAS);
//
//    CH* editbuf=(CH*)malloc(buflen);
//    if(!editbuf)
//        {
//         clidisplay("Insufficient memory");
//         free(L->line);
//         free(L->buf);free(L);return 1;
//        }
//    memset(editbuf,0x20,buflen);
//
//    LINE* l=L->line;
//    ptr=editbuf;
//    while(l)
//        {
//         memcpy(ptr,l->text,l->len);
//         l->text=ptr;
//         ptr+=MEMLINELEN;
//         l=l->next;
//        }
//    free(L->buf);
//    L->buf=editbuf;
//    e->maxlines=L->lines+EDITEXTRAS;
//    return 0;
//}


UC* dosuploadfile(CH* fname,UL* fsiz);

LSEQ*   dosloadSEQ(CH* name)
{
    CH  path[64];
    LSEQ* L=(LSEQ*)calloc(sizeof(LSEQ),1);
    if(L==NULL){clidisplay("Insufficient memory");return NULL;}

    UL fsiz;
    L->buf=(CH*)dosuploadfile(name,&fsiz);
    if(!L->buf)
        {
         clidisplay("Insufficient memory or zero file length");free(L);return NULL;
        }

    if(epatch(L,fsiz)){free(L);return NULL;}

    return L;
}

SL  patch(E3* e,UL size)
{
    UL  ctr=0,cctr=0,n;
    UI  isrc;
    CH* ptr=e->buf;
    CH* end=e->buf+size;
    CH* ptr1;
    CH* ptr2;
    CH* ptr3;

//get line count in ctr
//note that ctr does not count last lint if 0x0a is missing from end of file
    while(ptr!=end)
        {
         isrc=*(UI*)ptr;
         if(isrc==ENDOFLINE)     {ctr++;cctr=0;ptr+=2;}
         else if(*ptr==0x0a)     {ctr++;cctr=0;ptr++;}
         else if(*ptr==0x0d)     {ctr++;cctr=0;ptr++;}//PS files use single 0x0d
         else if(cctr==MAXLINELEN){ctr++;cctr=0;}
         else {ptr++;cctr++;}                         //as end of line marker
        }
    e->lines=ctr;

//allocate edit buffer filled with spaces
    UL  buflen=MEMLINELEN*(e->lines+EDITEXTRAS);
    CH* editbuf=(CH*)malloc(buflen);
    if(!editbuf){clidisplay("Insufficient memory");return 1;}
    memset(editbuf,0x20,buflen);

    ptr=e->buf;
    ptr1=editbuf;
    ptr2=editbuf;
    ptr3=editbuf+MAXLINELEN;
    UL  lctr=0,col;
    UL  max=MAXLINELEN;
    UL  olctr=0;

    while(ptr!=end)
        {
         isrc=*(UI*)ptr;
         if(isrc==ENDOFLINE)
            {
             ptr+=2;
             ptr1+=MEMLINELEN;
             ptr3+=MEMLINELEN;
             ptr2=ptr1;
             lctr++;olctr++;
            }
         else if(*ptr==0x0a)
            {
             ptr++;
             ptr1+=MEMLINELEN;
             ptr3+=MEMLINELEN;
             ptr2=ptr1;
             lctr++;olctr++;
            }
         else if(*ptr==0x0d)    //Postscript files use single 0x0d
            {                   //as end of line marker
             ptr++;
             ptr1+=MEMLINELEN;
             ptr3+=MEMLINELEN;
             ptr2=ptr1;
             lctr++;olctr++;
            }
         else if(ptr2==ptr3)
            {//line will exceed MAXLINELEN, so we break it here
             clidisplay("|c700file %s line %5l too long, adding line break",e->name,&olctr);
             ptr1+=MEMLINELEN;
             ptr3+=MEMLINELEN;
             ptr2=ptr1;
//             e->lines++;
             lctr++;
            }
         else if(*ptr==0x09)
            {//TAB to column modulo 8
             ptr++;
             col=ptr2-ptr1;
             col&=7;
             do
                {
                 *ptr2++=0x20;
                 col++;
                }
             while(col&7);
            }
         else{*ptr2++=*ptr++;}
        }

    if(e->buf){free(e->buf);}
    e->buf=editbuf;
    e->maxlines=e->lines+EDITEXTRAS;

    if(lctr!=e->lines)
        {
         clidisplay("file %s line counter error e->lines=%5l, lctr=%5l",&e->lines,&lctr);
        }

    return 0;
}