/* ule - Copyright (c) 1998 - mark holgerson */

/* ule V2.1  */
/* ib - insert before */
/* r@ - trim trail blanks */
/* pl - print (long) 34 lines */
/* pn - print without line #'s */
/*      bug fix in trimu */

#include <stdio.h>
#include <string.h>

#define MAXLINES 1000000 /* set maxlines for editor    */
                         /* i set 1000000 for unix (what the heck ...)
                                     4000 for PC         */
#define MAXLENGTH  255   /* set maxlength of editorline*/
                         /* 255 should do it           */

char command;            /* user command (a-z,#, ...   */
char tabc;               /* tab char                   */
int  tabn,tabs[10];      /* # of tabs, tab stops       */
int  nlines,nhits;       /* lines 2 search,find, used by locate,find,etc */
char f[80],ver[80];      /* file name, ule version #   */
char u[MAXLENGTH];       /* user input command line    */
char w[MAXLENGTH];       /* work area                  */
char us1[MAXLENGTH];     /* returned from parcing command line */
char us2[MAXLENGTH];     /*  "                         */
char us3[MAXLENGTH];     /*  "                         */
char bsave[80],          /* memory of last break       */
     csave[80],          /*                change      */
     fsave[80],          /*                find        */
     hsave[80],          /*                hack        */
     lsave[80];          /*                locate      */
char *v;                 /* work holding area          */
char *b[MAXLINES];       /* buffer holding line pointers */
char **vb;               /* virtual buffer used by move and kopy(ditto) */
int  endsw;              /* end user switch            */
int  fmodsw;             /* file modified switch       */
int  n;                  /* current line pointer       */
int  e;                  /* end of file pointer        */
int  noln;               /* nodlinef#lonpprintr        */

main(argc,argv)
int argc;
char **argv;

{
        strcpy(ver,"V2.1 (06/22/2001)");
        printf("\n\n>>>> Holg's ule (Unix Line Editor) %s\n",ver);
        printf(    ">>>>        %d Lines Maximum!\n\n",MAXLINES);
        printf(">>>>>>>> help = ?; FULL HELP = http://www.holg.com/ule\n\n");
        endsw=0;
        fmodsw=0;
        tabc='\0';
        tabn=0;
        noln=0;
        strcpy(csave,"");
        strcpy(fsave,"");
        strcpy(hsave,"");
        strcpy(lsave,"");
        n=0;
        e=0;
        strcpy(u,"");
        valloc1(strlen(u));
        b[0]=v;
        strcpy(f,"NONAME");
        if (argc>1)
           {strcpy(f,argv[1]);
            processcommandline();
           }
        while (endsw==0)
           {
            printf("%4uE>",n);
            getcommand();
                 if (command=='a') acommand();
            else if (command=='b') bcommand();
            else if (command=='c') ccommand();
            else if (command=='d') dcommand();
            else if (command=='e') ecommand();
            else if (command=='f') fcommand();
            else if (command=='g') gcommand();
            else if (command=='h') hcommand();
            else if (command=='i') icommand();
            else if (command=='j') jcommand();
            else if (command=='k') kcommand();
            else if (command=='l') lcommand();
            else if (command=='m') mcommand();
            else if (command=='n') ncommand();
            else if (command=='o') ocommand();
            else if (command=='p') pcommand();
            else if (command=='q') qcommand();
            else if (command=='r') rcommand();
            else if (command=='s') scommand();
            else if (command=='t') tcommand();
            else if (command=='u') ucommand();
            else if (command=='v') vcommand();
            else if (command=='w') wcommand();
            else if (command=='x') xcommand();
            else if (command=='y') ycommand();
            else if (command=='z') zcommand();
            else if (command=='+') pmcommand();
            else if (command=='-') pmcommand();
            else if (command=='@') incommand();
            else if (command=='!') pscommand();
            else if (command=='?') hlcommand();
            else if ((command>='0') &&
                     (command<='9')) nncommand();
            else                   ercommand();
           }
}

int  processcommandline()
       {
        FILE *infile,*fopen();
        if ((infile=fopen(f,"r"))==NULL)
           {if ((infile=fopen(f,"w"))==NULL)
               {printf("\n??? FILE <%s>   UNABLE TO OPEN\n\n",f);
                strcpy(f,"NONAME");
                return;
               }
            else
               {fclose(infile);
                if ((infile=fopen(f,"w"))==NULL)
                   {printf("\n??? FILE <%s>   UNABLE TO OPEN\n\n",f);
                    strcpy(f,"NONAME");
                    return;
                   }
                else
                   {
                    printf(">>>>>>>>NEW FILE\n\n");
                   }
               }
           }
        n=0;
        e=0;
        while (fgets(u,MAXLENGTH,infile) != NULL)
           {
            n++;
            e++;
            if (u[strlen(u)-1]==10) u[strlen(u)-1]='\0';
            trimu();
            valloc1(strlen(u));
            strcpy(v,u);
            if (n<=MAXLINES) b[n]=v;
           }
        fclose(infile);
        printf(">>>>>>>>    FILE :%s\n",f);
        printf(">>>>>>>> # Lines :%6d\n\n",e);
        if (n > MAXLINES) {
           printf("\n??? CANT OPEN FILE <%s>   LINES:%d > MAXLINES:%d\n\n",f,n,MAXLINES);
           endsw=1;
           return;
        }
        n=0;
       }

int  getcommand()
       {
        gets(u);
        trimu();
        if (strlen(u)==0)
           {command='@';
            return;
           }
        command=u[0];
        if (!('0' <= command && command <= '9')) strcpy(u,&u[1]);
        if ('A'<=command && command<='Z')
           {command='a'+command-'A';}
       }

int  acommand()
       {
        char aname[80];
        int  i,j,k,fr,to;
        FILE *infile,*fopen();
        parseu();
        strcpy(aname,us1);
        if ((infile=fopen(aname,"r"))==NULL)
           {printf("\n??? FILE <%s>    UNABLE TO OPEN\n\n",aname);
            return;
           }
        j=0;
        while (fgets(u,MAXLENGTH,infile) != NULL)
           {j++;}
        close(infile);
        if (strcmp(us2,"")==0)
           {fr=1; to=j;}
        else
           {for (i=0; i<strlen(us2); i++)
                if ((us2[i]<'0') || ('9'<us2[i]))
                   {ercommand(); return;}
            for (i=0; i<strlen(us3); i++)
                if ((us3[i]<'0') || ('9'<us3[i]))
                   {ercommand(); return;}
            fr=xatoi(us2);
            to=xatoi(us3);
            if ((fr>to) || (fr==0))
               {ercommand(); return;}
            if (fr>j)
               {printf("\n??? FILE <%s> contains %d Lines\n\n",aname,j);
                return;}
            fr=imin(fr,j);
            to=imin(to,j);
           }
        k=to-fr+1;
        if (k+e > MAXLINES) {
printf("\n??? CANT ADD FILE <%s>   LINES:%d + ADDS:%d = %d > MAXLINES:%d\n\n",aname,e,k,k+e,MAXLINES);
           return;
        }
        for (i=e; i>n; i--)
            {b[i+k]=b[i];}
        if ((infile=fopen(aname,"r"))==NULL)
           {printf("\n??? FILE <%s>    UNABLE TO OPEN\n\n",aname);
            return;
           }
        j=0;
        while (fgets(u,MAXLENGTH,infile) != NULL)
           {j++;
            if ((fr<=j) && (j<=to))
               {
                if (u[strlen(u)-1]==10) u[strlen(u)-1]='\0';
                trimu();
                valloc1(strlen(u));
                strcpy(v,u);
                b[n+j-fr+1]=v;
               }
            }
        fclose(infile);
        fmodsw=1;
        e=e+k;
        plcommand(imax(n+1,n+k-21),n+k);
        printf("\n>>> FILE <%s>   %d Lines Added\n\n",aname,k);
       }

int  bcommand()
       {
        int i,j;
        char bs[80];
        if (n==0)
           {ercommand(); return;}
        if (u[0]=='?')
           {printf("%s\n",bsave);
            return;
           }
        i=0;
        while (u[i]==' ') i++;
        strcpy(u,&u[i]);
        if (strcmp(u,"")==0)
           {strcpy(u,bsave);}
        else
           {strcpy(bsave,u);}
        if ((u[0]=='\'') && (u[strlen(u)-1]=='\''))
           {strcpy(bs,&u[1]); bs[strlen(bs)-1]='\0';}
        else
        if ((u[0]=='"') && (u[strlen(u)-1]=='"'))
           {strcpy(bs,&u[1]); bs[strlen(bs)-1]='\0';}
        else
           strcpy(bs,u);
        if (strcmp(bs,"")==0)
           {ercommand(); return;}
        j=strpos(b[n],bs);
        if (j>=0)
           {fmodsw=1;
            strcpy(w,&b[n][j+strlen(bs)]);
            i=0; while(w[i]==' ') strcpy(w,&w[1]);
            b[n][j+strlen(bs)]='\0';
            strcpy(u,w);
            strcpy(w,"");
            i=0; while(b[n][i]==' ') {strcat(w," "); i++;}
            strcat(w,u);
            valloc1(strlen(w));
            strcpy(v,w);
            for (i=e; i>n; i--) b[i+1]=b[i];
            b[n+1]=v;
            e++;
            plcommand(n,n+1);
            }
        else
           printf("No Break\n");
       }

int  ccommand()
      {
       int i,j,k,  l,m,x,in,lcf,lct,lw,i1,i2,i3,cont,tb;
       char d,cf[80],ct[80],z[256],g,csavesave[80];
       strcpy(csavesave,csave);
       if (u[0]=='?')
          {printf("%s\n",csave);
           return;
          }
       if (u[0]=='a' || u[0]=='A' || u[0]==',')
          gethitslines();
       else
          {nhits=1; nlines=1;}
       if (strcmp(u,"")==0)
          {strcpy(u,csave);}
       else
          {strcpy(csave,u);}

       while (u[0]==' ') strcpy(u,&u[1]);

       if (u[0]=='>')
          {strcpy(u,&u[1]);
           j=imin(e,n+nlines-1);
           for (i=imax(1,n); i<=j; i++)
              {strcpy(w,b[i]);
               strcat(w,u);
               free(b[i]);
               valloc1(strlen(w));
               strcpy(v,w);
               b[i]=v;
               picommand(i);
              }
           if (n+nlines-1>e)
              {pecommand();}
           else
              {n=n+nlines-1;}
           return;
          }


       l=strlen(u);
       i=0;
       while (u[i] == ' ' && i<l) {i++;}
       i1=i; d=u[i]; i++;
       while (u[i] != d   && i<l) {i++;}
       i2=i; i=imin(i+1,l);
       while (u[i] != d   && i<l) {i++;}
       i3=i;
       if (i2==l || i3==l)
          {ercommand(); strcpy(csave,csavesave); return;}
       l=0; for (i=i1+1; i<i2; i++) {cf[i-i1-1]=u[i];l++;} cf[l]='\0';
       l=0; for (i=i2+1; i<i3; i++) {ct[i-i2-1]=u[i];l++;} ct[l]='\0';
       i=i3+1;
       while (u[i]==' ') i++;
       g=' ';
       if (u[i] == 'G' || u[i] == 'g') g='g';
       tb=0; while(cf[strlen(cf)-1-tb]==' ') tb++;
       lcf=strlen(cf);
       lct=strlen(ct);
       j=imin(e,n+nlines-1);
       k=0;
       for (i=imax(1,n); i<=j; i++)
          {
           strcpy(w,b[i]);
           if (tb>0)
              {l=strlen(w);
               for (m=l; m<l+tb; m++) w[m]=' ';
               w[m]='\0';
              }
           if (strpos(w,cf)>=0 || strcmp(cf,"")==0)
              {
               k=1;
               if (strcmp(cf,"")==0)
                  {strcpy(z,ct);
                   strcat(z,w);
                   strcpy(w,z);
                  }
               else
                  {in=0;
                   l=strposn(in,w,cf);
                   cont=1;
                   while (l>=0 && strlen(w)+lct-lcf<256 && cont==1)
                      {
                       lw=strlen(w);
                       for (x=l+lcf; x<=lw; x++)
                           {w[x-lcf]=w[x];}
                       w[x]='\0';
                       lw=strlen(w);
                       for (x=lw; x>=l; x--)
                           {w[x+lct]=w[x];}
                       w[lw+lct]='\0';
                       for (x=0; x<lct; x++)
                           {w[l+x]=ct[x];}
                       in=l+lct;
                       l=strposn(in,w,cf);
                       if (g==' ') cont=0;
                      }
                  }
               free(b[i]);
               while(w[strlen(w)-1]==' ')
                  w[strlen(w)-1]='\0';
               valloc1(strlen(w));
               strcpy(v,w);
               b[i]=v;
               picommand(i);
              }
          }
       if (k==0)
          {printf("No Changes\n");}
       else
          fmodsw=1;
       if (n+nlines-1>e)
          {pecommand();}
       else
          {n=n+nlines-1;}
      }

int  dcommand()
       {
        int i,j,k;
        parseu();
        k=0;
        for (i=0; i<strlen(us1); i++)
           if (!('0' <= us1[i] && us1[i] <= '9')) k=1;
        for (i=0; i<strlen(us2); i++)
           if (!('0' <= us2[i] && us2[i] <= '9')) k=1;
        if (k==1)
           {ercommand();
            return;
           }
        i=xatoi(us1);
        j=xatoi(us2);
        if (strcmp(u,"")==0)
           {i=n; j=n;}
        if (i==0)
           {ercommand();
            return;
           }
        if (j==0)
           {j=imin(e,n+i-1); i=n;}
        if (i>j)
           {ercommand();
            return;
           }
        if (i>e)
           {pecommand();
            return;
           }
        fmodsw=1;
        i=imax(1,i);
        j=imin(e,j);
        for (k=i; k<=j; k++)
            {free(b[k]);}
        for (k=j+1; k<=e; k++)
            {b[i+k-j-1]=b[k];}
        e=e-j+i-1;
        n=i-1;
        ppcommand();
       }

int  ecommand()
       {if (strcmp(u,"")!=0)
           ercommand();
        else
           n=e;
           ppcommand();
       }

int  fcommand()
       {
        int i,j,k,m,i1,i2,hits;
        if (u[0]=='?')
           {printf("%s\n",fsave);
            return;             }
        gethitslines();
        if (strcmp(u,"")==0)
           {strcpy(u,fsave);}
        else
        if (u[0] != ' ')
           {ercommand(); return;}
        else
           {strcpy(u,&u[1]); strcpy(fsave,u);}
        xtcommand();
    i=0;
    while (u[i]==' ') i++;
    i1=i;
    while (u[i]!='\0') i++;
    i2=i-1;
    k=imin(e,n+nlines);
    hits=0;
    for (i=n+1; i<=k; i++)
        {m=1;
             for (j=i1; j<=i2; j++)
         {if (b[i][j] != u[j]) m=0;}
         if (m==1)
        {picommand(i);
                 hits=hits+1;
                 if (hits==nhits)
                    {n=i; return;}
                }
            }
         if (hits==0) {
            printf("No Finds\n");
            pecommand();
            return;
         }
         if (n+nlines>e)
            {pecommand();}
         else
            {n=n+nlines;}
        }

int  gcommand() {ercommand();}

int  hcommand()
       {
        int i,j,hits;
        char ls[80];
        if (u[0]=='?')
           {printf("%s\n",hsave);
            return;
           }
        if (u[0]=='*')
           {ercommand(); return;}
        gethitslines();
        if ((nhits==1) && (nlines==e))
           {nlines=1;}
        i=0;
        while (u[i]==' ') i++;
        strcpy(u,&u[i]);
        if (strcmp(u,"")==0)
           {strcpy(u,hsave);}
        else
           {strcpy(hsave,u);}
        if ((u[0]=='\'') && (u[strlen(u)-1]=='\''))
           {strcpy(ls,&u[1]); ls[strlen(ls)-1]='\0';}
        else
        if ((u[0]=='"') && (u[strlen(u)-1]=='"'))
           {strcpy(ls,&u[1]); ls[strlen(ls)-1]='\0';}
        else
           strcpy(ls,u);
        if (strcmp(ls,"")==0)
           {ercommand(); return;}
        hits=0;
        for (i=n; i<=imin(n+nlines-1,e); i++)
            {j=strpos(b[i],ls);
             if ((j>=0) &&
                (strlen(b[i])>(j+strlen(ls))))
                {fmodsw=1;
                 hits=hits+1;
                 strcpy(w,b[i]);
                 w[j+strlen(ls)]='\0';
                 free(b[i]);
                 while(w[strlen(w)-1]==' ')
                    w[strlen(w)-1]='\0';
                 valloc1(strlen(w));
                 strcpy(v,w);
                 b[i]=v;
                 picommand(i);
                }
            }
        if (hits==0)
           {printf("No Hacks\n");}
        if (n+nlines-1>e)
           pecommand();
        else
           n=n+nlines-1;
       }

int  icommand()
       {
        int i,bsw;
        bsw=0;
        if ((u[0]=='b')||(u[0]=='B')) {
           if (n==0) {ercommand(); return;}
           bsw=1;
           strcpy(u,&u[1]);
        }
        if (strlen(u)==1)
           {ercommand(); return;}
        if (strlen(u)> 1)
           if (u[0]==' ')
              strcpy(u,&u[1]);
           else
              {ercommand(); return;}
        fmodsw=1;
        xtcommand();
        for (i=e; i > (n-bsw); i--)
            {b[i+1]=b[i];}
        n++;
        e++;
        valloc1(strlen(u));
        strcpy(v,u);
        b[n-bsw]=v;
       }

int  jcommand()
       {int i;
        if ((n==e) || (strcmp(u,"")!=0))
           {ercommand(); return;}
        strcpy(w,b[n]);
        strcat(w," ");
        strcpy(u,b[n+1]);
        while(u[0]==' ') strcpy(u,&u[1]);
        strcat(w,u);
        free(b[n]);
        free(b[n+1]);
        valloc1(strlen(w));
        strcpy(v,w);
        b[n]=v;
        for (i=n+1; i<e; i++) b[i]=b[i+1];
        e--;
        ppcommand();
       }

int  kcommand()
       {
        int i,j,k;
        parseu();
        k=0;
        for (i=0; i<strlen(us1); i++)
           if (!('0' <= us1[i] && us1[i] <= '9')) {k=1;}
        for (i=0; i<strlen(us2); i++)
           if (!('0' <= us2[i] && us2[i] <= '9')) k=1;
        if (k==1)
           {ercommand();
            return;
           }
        i=xatoi(us1);
        j=xatoi(us2);
        if ((i==0) && (j==0))
           {i=n;j=n;}
        else
        if ((i==0) && (!(j==0)))
           {ercommand(); return;}
        else
        if (j==0)
           {j=i;}
        if (i>j)
           {ercommand(); return;}
        if (i>e)
           {ercommand();
            printf("%dEOF>\n",e);
            return;
           }
        fmodsw=1;
        i=imax(i,1);
        j=imin(j,e);
        vb=(char **)calloc(j-i+1,sizeof(*vb));
        for (k=i; k<=j; k++)
            {valloc1(strlen(b[k]));
             strcpy(v,b[k]);
             vb[k-i]=v;
            }
        for (k=e; k>=n+1; k--) b[k+j-i+1]=b[k];
        for (k=i; k<=j; k++)   b[n+k-i+1]=vb[k-i];
        free(vb);
        n=n+j-i+1;
        e=e+j-i+1;
        for (k=imax(n-j+i,n-21); k<=n; k++) picommand(k);
        }

int  lcommand()
       {
        int i,j,hits;
        char ls[80];
        if (u[0]=='?')
           {printf("%s\n",lsave);
            return;
           }
        gethitslines();
        i=0;
        while (u[i]==' ') i++;
        strcpy(u,&u[i]);
        if (strcmp(u,"")==0)
           {strcpy(u,lsave);}
        else
           {strcpy(lsave,u);}
        if ((u[0]=='\'') && (u[strlen(u)-1]=='\''))
           {strcpy(ls,&u[1]); ls[strlen(ls)-1]='\0';}
        else
        if ((u[0]=='"') && (u[strlen(u)-1]=='"'))
           {strcpy(ls,&u[1]); ls[strlen(ls)-1]='\0';}
        else
           strcpy(ls,u);
        if (strcmp(ls,"")==0)
           {ercommand(); return;}
        hits=0;
        j=imin(e,n+nlines);
        for (i=n+1; i<=j; i++)
            {
             if (strpos(b[i],ls)>=0)
                {picommand(i);
                 hits=hits+1;
                 if (hits==nhits)
                    {n=i; return;}
                }
            }
        if (hits==0) {
           printf("No Locates\n");
           pecommand();
           return;
        }
        if (n+nlines>e)
           {pecommand(); return;}
        n=j;
       }

int  mcommand()
       {
        int i,j,k;
        parseu();
        k=0;
        for (i=0; i<strlen(us1); i++)
           if (!('0' <= us1[i] && us1[i] <= '9')) {k=1;}
        for (i=0; i<strlen(us2); i++)
           if (!('0' <= us2[i] && us2[i] <= '9')) k=1;
        if (k==1)
           {ercommand();
            return;
           }
        i=xatoi(us1);
        j=xatoi(us2);
        if (i==0)
           {ercommand(); return;}
        if (j==0)
           {j=i;}
        if (i>j)
           {ercommand(); return;}
        if (i>e)
           {ercommand();
            printf("%dEOF>\n",e);
            return;
           }
        i=imax(i,1);
        j=imin(j,e);
        if ((i-1<=n) && (n<=j))
           {ercommand(); return;}
        fmodsw=1;
        vb=(char **)calloc(j-i+1,sizeof(*vb));
        for (k=i; k<=j; k++)
            {valloc1(strlen(b[k]));
             strcpy(v,b[k]);
             vb[k-i]=v;
            }
        if (n>j)
            {for (k=j+1; k<=n; k++)
                 {b[k-j+i-1]=b[k];}
             for (k=0; k<=j-i; k++)
                 {b[n-j+i+k]=vb[k];}
             plcommand(imax(n-j+i,n-21),n);
            }
        else
            {for (k=i-1; k>n; k--)
                 {b[k+j-i+1]=b[k];}
             for (k=0; k<=j-i; k++)
                 {b[n+k+1]=vb[k];}
             plcommand(imax(n+1,n+j-i+1-21),n+j-i+1);
            }
        free(vb);
       }

int  ncommand()
       {command='+';
        pmcommand();
       }

int  ocommand()
       {
        char s[80];
        int  i;
        FILE *infile,*fopen();
        if (fmodsw==1)
           {printf(
 "\n>>> FILE <%s>   Not Saved: Enter S/s/Y/y to Save; C/c to Cancel:",f);
            gets(s);
            if (strcmp(s,"C")==0 || strcmp(s,"c")==0)
               {printf("\n"); return;}
            if (strcmp(s,"S")==0 || strcmp(s,"s")==0)
               scommand();
            if (strcmp(s,"Y")==0 || strcmp(s,"y")==0)
               scommand();
           }
        parseu();
        strcpy(f,us1);
        if ((infile=fopen(f,"r"))==NULL)
           {printf("\n??? FILE <%s>    UNABLE TO OPEN\n\n",f);
            return;
           }
        for (i=1; i<=e; i++) {free(b[i]);}
        n=0;
        e=0;
        while (fgets(u,MAXLENGTH,infile) != NULL)
           {
            n++;
            e++;
            if (u[strlen(u)-1]==10) u[strlen(u)-1]='\0';
            trimu();
            valloc1(strlen(u));
            strcpy(v,u);
            if (n<=MAXLINES) b[n]=v;
           }
        fclose(infile);
        printf("\n");
        printf(">>>>>>>>    FILE :%s\n",f);
        printf(">>>>>>>> # Lines :%6d\n\n",e);
        if (n > MAXLINES) {
           printf("\n??? CANT OPEN FILE <%s>   LINES:%d > MAXLINES:%d\n\n",f,n,MAXLINES);
           endsw=1;
           return;
        }
        n=0;
        fmodsw=0;
       }

int  pcommand()
       {
        int i,j,k;
        if (u[0]=='n' || u[0] =='N')
           {noln=1; strcpy(u,&u[1]);}
        parseu();
        if (u[0]=='p' || u[0] =='P')
           {if (n==0) n=1;
            j=n+20;
            plcommand(n,imin(n+20,e));
            if (j>e) pecommand();
            return;
           }
        if (u[0]=='l' || u[0] =='L')
           {if (n==0) n=1;
            j=n+33;
            plcommand(n,imin(n+33,e));
            if (j>e) pecommand();
            return;
           }
        if (u[0]=='z' || u[0] =='Z')
           {plcommand(imax(1,n-10),imin(e,n+10)); return;}
        if (u[0]=='h' || u[0] =='H')
           {plcommand(1,imin(e,20)); return;}
        if (u[0]=='t' || u[0] =='T')
           {plcommand(imax(e-20,1),e); return;}
        if (u[0]=='b' || u[0] =='B')
           {plcommand(imax(n-20,1),n); return;}
        if (u[0]=='u' || u[0] =='U')
           {plcommand(imax(n-40,1),imax(n-20,1)); return;}
        if (u[0]=='a' || u[0] =='A')
           {plcommand(1,e); pecommand(); return;}
        if (strcmp(us1,"")==0)
           {ppcommand(); return;}
        k=0;
        for (i=0; i<strlen(us1); i++)
           if (!('0' <= us1[i] && us1[i] <= '9')) {k=1;}
        for (i=0; i<strlen(us2); i++)
           if (!('0' <= us2[i] && us2[i] <= '9')) k=1;
        if (k==1)
           {ercommand();
            return;
           }
        i=xatoi(us1);
        j=xatoi(us2);
        if (j==0)
           {if (n==0) n=1;
            j=n+i-1;
            i=n;
           }
        i=imax(1,i);
        if (i>j)
           {ercommand(); return;}
        if (i>e)
           {ercommand();
            printf("%dEOF>\n",e);
            return;
           }
        plcommand(i,imin(e,j));
        if (j>e)
           {pecommand();
            return;
           }
        n=imin(e,j);
       }

int  qcommand()
       {
        char s[80];
        if (strcmp(u,"")!=0)
           {ercommand(); return;}
        if ((fmodsw==1) && (strcmp(f,"NONAME")!=0))
           {printf(
 "\n>>> FILE <%s>   Not Saved: Enter S/s/Y/y to Save; C/c to Cancel:",f);
            gets(s);
            if (strcmp(s,"C")==0 || strcmp(s,"c")==0)
               {printf("\n"); return;}
            if (strcmp(s,"S")==0 || strcmp(s,"s")==0)
               scommand();
            if (strcmp(s,"Y")==0 || strcmp(s,"y")==0)
               scommand();
           }
        endsw=1;
       }

int  rcommand()
      {
       int i,j;
       if (n==0)
          {ercommand(); return;}
       if (strlen(u)==0) strcpy(u," ");
       else
       if (strcmp(u," ")==0) ;
       else
       if (u[0] == '@')
          {strcpy(u,&u[1]);
           strcpy(w,b[n]);
           if (strlen(u)>strlen(w))
              {for (i=strlen(w);i<strlen(u);i++) w[i]=' ';
               w[i]='\0';
              }
           for (i=0; i<strlen(u); i++)
               {if (u[i]=='@') w[i]=' ';
           else if (u[i]!=' ') w[i]=u[i];}
           free(b[n]);
           valloc1(strlen(w));
           while(w[strlen(w)-1]==' ') w[strlen(w)-1]='\0';
           strcpy(v,w);
           b[n]=v;
           fmodsw=1;
           ppcommand();
           return;
          }
       else
       if (u[0] == '^')
          {strcpy(u,&u[1]);
           i=0; while (u[i]==' ') i++;
           if (i>=strlen(b[n]))
              {ercommand();
               return;
              }
           strcpy(u,&u[i]);
           j=0; while(u[j]!='\0') {if (u[j]=='^') u[j]=' '; j++;}
           strcpy(w,b[n]);
           w[i]='\0';
           strcat(w,u);
           strcat(w,&b[n][i]);
           free(b[n]);
           valloc1(strlen(w));
           strcpy(v,w);
           b[n]=v;
           fmodsw=1;
           ppcommand();
           return;
          }
       else
       if (u[0] == '#')
          {strcpy(u,&u[1]);
           if (strlen(u)>strlen(b[n])) u[strlen(b[n])]='\0';
           if (strlen(u)<strlen(b[n]))
              {
               for (i=strlen(u); i<strlen(b[n]); i++) u[i]=' ';
               u[i]='\0';
              }
           j=0;
           for (i=0; i<strlen(b[n]); i++)
               if (u[i]==' ') b[n][j++]=b[n][i];
           b[n][j]='\0';
           fmodsw=1;
           ppcommand();
           return;
          }
       else
       if (u[0] != ' ')
          {ercommand(); return;}
       fmodsw=1;
       strcpy(u,&u[1]);
       xtcommand();
       free(b[n]);
       valloc1(strlen(u));
       strcpy(v,u);
       b[n]=v;
       ppcommand();
      }

int  scommand()
       {
        FILE *ofile,*fopen();
        int i;
        if ((strcmp(u,"")==0) || (strcmp(u,"q")==0) || (strcmp(u,"Q")==0))
           ;
        else
           {ercommand(); return;}
        if ((ofile=fopen(f,"w"))==NULL)
           {printf("\n??? FILE <%s>    UNABLE TO OPEN\n\n",f);
            pause();
            return;
           }
        for (i=1;i<=e;i++)
            {fputs(b[i],ofile);
             fputs("\n",ofile);
            }
        fclose(ofile);
        fmodsw=0;
        printf("\n>>> FILE <%s>   %d Lines Written\n\n",f,e);
        if ((u[0]=='Q') || (u[0]=='q')) endsw=1;
       }

int  tcommand()
       {
        char c,s[80];
        int i,j,k,i1,i2,ts[9];
        i=1; j=0;
        while (u[i]==' ') i++;
        c=u[i];
        i++;
        while (u[i] != '\0' && j<10)
           {
            while (u[i]==' ') i++;
            i1=i;
            while ('0' <= u[i] && u[i] <= '9') i++;
            i2=i-1;
            for (k=i1; k<=i2; k++) s[k-i1]=u[k];
            s[k-i1]='\0';
            ts[j]=xatoi(s);
            if (j>0)
               if (ts[j]<=ts[j-1])
                  {ercommand();
                   return;
                  }
            j++;
           }
        tabc=c;
        tabn=j;
        for (i=1; i<=j; i++) tabs[i]=ts[i-1];
       }

int  ucommand() {ercommand();}

int  vcommand()
       {
        int i;
        if (strcmp(u,"")!=0)
           {ercommand(); return;}
        printf("\n>>>>>>>> ule VER :%s  FULL HELP = http://www.holg.com/ule\n",ver);
        printf(  ">>>>>>>> Copyright (c) 1998 - mark holgerson\n");
        printf(  ">>>>>>>>    FILE :%s\n",f);
        printf(  ">>>>>>>> # Lines :%6d\n",e);
        printf(  ">>>>>>>>    Tabs :%c",tabc);
        if (tabn>0)
           {for (i=1; i<=tabn; i++) printf(" %d",tabs[i]);}
        printf("\n");
        printf(  ">>>> Last Break  :%s\n",bsave);
        printf(  ">>>> Last Change :%s\n",csave);
        printf(  ">>>> Last Hack   :%s\n",hsave);
        printf(  ">>>> Last Locate :%s\n",lsave);
        printf(  ">>>> Last Find   :%s\n\n",fsave);

       }

int  wcommand()
       {
        FILE *ofile,*fopen();
        int i,fr,to;
        char s[80];
        parseu();
        if (strcmp(us2,"")==0)
           {fr=1; to=e;}
        else
           {for (i=0; i<strlen(us2); i++)
                if ((us2[i]<'0') || ('9'<us2[i]))
                   {ercommand(); return;}
            for (i=0; i<strlen(us3); i++)
                if ((us3[i]<'0') || ('9'<us3[i]))
                   {ercommand(); return;}
            fr=xatoi(us2);
            to=xatoi(us3);
            if ((fr>to) || (fr==0))
               {ercommand(); return;}
            if (fr>e)
               {printf("\n??? FILE <%s> contains %d Lines\n\n",f,e);
                return;}
            fr=imin(fr,e);
            to=imin(to,e);
           }
        if ((ofile=fopen(us1,"r"))!=NULL)
           {printf(
 "\n??? FILE <%s>    Exists: Enter O/o/Y/y to Overwrite; C/c to Cancel:",us1);
            fclose(ofile);
            gets(s);
            if (strcmp(s,"C")==0 || strcmp(s,"c")==0)
               {printf("\n"); return;}
            if ((strcmp(s,"O")==0 || strcmp(s,"o")==0 ||
                 strcmp(s,"Y")==0 || strcmp(s,"y")==0))
               ;
            else
               {printf("\n"); return;}
           }
        if ((ofile=fopen(us1,"w"))==NULL)
           {printf("\n??? FILE <%s>    UNABLE TO OPEN\n\n",us1);
            pause();
            return;
           }
        for (i=fr;i<=to;i++)
            {fputs(b[i],ofile);
             fputs("\n",ofile);
            }
        fclose(ofile);
        printf("\n>>> FILE <%s>   %d Lines Written\n\n",us1,to-fr+1);
        fmodsw=0;
       }

int  xcommand()
      {int i,j,k;
       if (n==0) {ercommand(); return;}
       k=0;
       if (strcmp(u,"")==0) k=1;
       else
       if (u[0]=='-')
          {k=0;
           while (u[0]=='-') {k--; strcpy(u,&u[1]);}
          }
       else
       if (u[0]=='x' || u[0]=='X')
          {k=1;
           while (u[0]=='x' || u[0]=='X') {k++; strcpy(u,&u[1]);}
          }
       else
       if (u[0]=='a' || u[0]=='A')
          {if (n==1) {ercommand(); return;}
           i=0; while(b[n-1][i]==' ') i++;
           j=0; while(b[n  ][j]==' ') j++;
           k=i-j;
          }
       else
          {ercommand(); return;}
       strcpy(w,"");
       k=imin(k,256-strlen(b[n]));
       if (k>0)
          {for (i=0; i<k; i++) strcat(w," ");
           strcat(w,b[n]);
           free(b[n]);
           valloc1(strlen(w));
           strcpy(v,w);
           b[n]=v;
          }
       if (k<0)
          {while (k<0 && b[n][0]==' ')
             {k++; strcpy(b[n],&b[n][1]);}
          }
       if (u[0]=='a' || u[0]=='A') picommand(n-1);
       ppcommand();
      }

int  ycommand() {ercommand();}

int  zcommand()
      {int i;
       char s[80];
        if ((strcmp(u,"")==0) || (strcmp(u,"z")==0) || (strcmp(u,"Z")==0))
           ;
        else
           {ercommand(); return;}
       if ((u[0]=='z') || (u[0]=='Z'))
          {for (i=1; i<=e; i++) {free(b[i]);}
           e=0; n=0; fmodsw=1; return;}
       printf("\n>>> ZAP - Erase Workarea - Enter Y/y to Erase:");
       gets(s);
       printf("\n");
       if (strcmp(s,"Y")==0 || strcmp(s,"y")==0)
          {for (i=1; i<=e; i++) {free(b[i]);}
           e=0; n=0; fmodsw=1; return;}
      }

int  pmcommand()
       {
        int i,j;
        parseu();
        j=xatoi(us1);
        if (j==0) {j=1;}
        if (command=='+')
            {if (strcmp(us1,"+")==0) {j=e-n;}
             i=imin(e,n+j);
             picommand(i);
             if (n+j>e)
                {pecommand();
                 return;
                 }
             n=i;
            }
        else
            {n=imax(n-j,0);
             ppcommand();
            }
       }

int  incommand()
       {
        int i;
        printf("%6dI>",n);
        gets(u);
        while (strlen(u)>0)
           {
            fmodsw=1;
            xtcommand();
            for (i=e; i > n; i--)
                {b[i+1]=b[i];}
            n++;
            e++;
            trimu();
            valloc1(strlen(u));
            strcpy(v,u);
            b[n]=v;
            printf("%6dI>",n);
            gets(u);
           }
       }

int  hlcommand()
       {
        vcommand();
        printf(">>>>    a-add file        j-lines           s-save (file)\n");
        printf(">>>>    b-break line      k-kopy line(s)    t-tab set\n");
        printf(">>>>    c-change line(s)  l-locate string   u-\n");
        printf(">>>>    d-delete line(s)  m-move line(s)    v-values\n");
        printf(">>>>    e-end of file     n-next line(s)    w-write file\n");
        printf(">>>>    f-find string     o-old file        x-spaces\n");
        printf(">>>>    g-                p-print line(s)   y-\n");
        printf(">>>>    h-hack string     q-quit            z-zap lines\n");
        printf(">>>>    i-insert line     r-replace line    !-scale\n");
        printf(">>>>    #-go to line #    --back line(s)    +-ahead line(s)\n");
        printf(">>>>    <CR>-toggle insert mode\n");
        printf("\n");

       }

int  plcommand(f,t)
       int f,t;
       {
        int i;
        if (noln==1) {pncommand(f,t); noln=0; return;}
        for (i=f;i<=t;i++)
            {if (i==0)
                printf("     0.>\n");
             else
                if (b[i]==NULL)
                   {printf("%6d.>\n",i);}
                else
                   {printf("%6d.>%s\n",i,b[i]);}
            n=t;
           }
       }

int  pncommand(f,t)
       int f,t;
       {
        int i;
        for (i=f;i<=t;i++)
            {if (i==0)
                printf("     0.>\n");
             else
                if (b[i]==NULL)
                   {printf("\n");}
                else
                   {printf("%s\n",b[i]);}
            n=t;
           }
       }

int  ppcommand() {plcommand(n,n);}

int  pecommand()
       {
        printf("%dEOF>\n",e);
        n=0;
        ppcommand();
       }

int  picommand(i) {plcommand(i,i);}

int  pscommand()
       {printf(
  "       >         1         2         3         4         5         6");
        printf("         7\n");
        printf (
  "       >123456789012345678901234567890123456789012345678901234567890");
        printf("1234567890\n");
       }

int  ercommand() {printf("\n%s\n??? -- You want fries with that? -- ???\n\n",u);}

int  xtcommand()
       {
        int i,j;
        char s[MAXLENGTH];
        i=0;
        while (u[i]==tabc && i<tabn) i++;
        if (i==0) return;
        for (j=0; j<tabs[i]-1; j++) s[j]=' ';
        s[j]='\0';
        strcat(s,&u[i]);
        strcpy(u,s);
       }

int  trimu()
       {while((strlen(u)>0) && (u[strlen(u)-1]==' ')) u[strlen(u)-1]='\0';}

int  parseu()
       {
        int i,i1,i2,i3,i4,i5,i6;
        strcpy(us1,"");
        strcpy(us2,"");
        strcpy(us3,"");
        for (i= 0;u[i]==' ' && u[i] !='\0';i++);
        i1=i;
        for (i=i1;!(u[i]==' ' || u[i]=='\0');i++);
        i2=i;
        for (i=i2;u[i]==' ' && u[i] !='\0';i++);
        i3=i;
        for (i=i3;!(u[i]==' ' || u[i]=='\0');i++);
        i4=i;
        for (i=i4;u[i]==' ' && u[i] !='\0';i++);
        i5=i;
        for (i=i5;!(u[i]==' ' || u[i]=='\0');i++);
        i6=i;
        for (i=0;i<i2-i1;i++) {us1[i]=u[i1+i];}
         us1[i]='\0';
        for (i=0;i<i4-i3;i++) {us2[i]=u[i3+i];}
         us2[i]='\0';
        for (i=0;i<i6-i5;i++) {us3[i]=u[i5+i];}
         us3[i]='\0';
       }

int  nncommand()
       {int i;
        char s[80];
        for (i=0; '0'<=u[i] && u[i]<='9'; i++)
            {s[i]=u[i];}
        s[i]='\0';
        while (s[0]=='0') strcpy(s,&s[1]);
        i=xatoi(s);
        if (i>e)
           {n=e;
            ppcommand();
            pecommand();
            return;
           }
        else
           {n=i;}
        ppcommand();
       }

int  pause()
       {
        char s[256];
        gets(s);
       }

int  imax(i,j)
       int i,j;
      {if (i>=j)
          return(i);
       else
          return(j);
      }

int  imin(i,j)
       int i,j;
      {if (i<=j)
          return(i);
       else
          return(j);
      }

int  strposn(int nth, char* str, char* substr)
       {
        int i=nth,j,k;
        while (str[i] != '\0')
           {
            for (j=i,k=0; str[j] == substr[k]; j++,k++)
               {if (substr[k+1] == '\0') return i;}
            i++;
           }
         return(-1);
        }

int  strpos(char* str, char* substr)
       {
        int i=0,j,k;
        while (str[i] != '\0')
           {
            for (j=i,k=0; str[j] == substr[k]; j++,k++)
               {if (substr[k+1] == '\0') return i;}
            i++;
           }
         return(-1);
        }

int xatoi(char *s)
      {
       return(atoi(s));
      }

int valloc1(int l)
      {v=(char *)calloc(l+1,sizeof(char));}

int  gethitslines()
       {
        int i,j,k;
        char s[80];
        nlines=e;
        nhits=1;
        if (u[0]=='a' || u[0]=='A')
           {nlines=e+2; nhits=e+2; strcpy(u,&u[1]); return;}
        if (!(u[0]==',' || u[0]=='*')) return;
        i=1;
        if (!('0' <= u[i] && u[i] <= '9')) return;
        while ('0' <= u[i] && u[i] <= '9') i++;
        for (j=1; j<=i; j++) s[j-1]=u[j];
        s[j-1]='\0';
        k=xatoi(s);
        if (u[0]==',')
           {nlines=k; nhits=e;}
        else
           {nhits=k; nlines=e;}
        strcpy(u,&u[j-1]);
       }
