home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / editors / pur_c_vi.zoo / edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-11  |  6.8 KB  |  356 lines

  1. /*
  2.  * STevie - ST editor for VI enthusiasts.     ...Tim Thompson...twitch!tjt...
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include "stevie.h"
  8.  
  9. edit()
  10. {
  11.     int c, c1, c2;
  12.     char *p, *q;
  13.  
  14.     Prenum = 0;
  15.  
  16.     /* position the display and the cursor at the top of the file. */
  17.     Topchar = Filemem;
  18.     Curschar = Filemem;
  19.     Cursrow = Curscol = 0;
  20.  
  21.     for ( ;; ) {
  22.     /* Figure out where the cursor is based on Curschar. */
  23.     cursupdate();
  24.     if ( State == INSERT )
  25.         message("Insert Mode");
  26.     /* printf("Curschar=(%d,%d) row/col=(%d,%d)",
  27.         Curschar,*Curschar,Cursrow,Curscol); */
  28.     windgoto(Cursrow,Curscol);
  29.     windrefresh();
  30.     c = vgetc();
  31.     if ( State != INSERT )
  32.         message("");
  33.     switch(State) {
  34.     case NORMAL:
  35.         /* We're in the normal (non-insert) mode. */
  36.  
  37.         /* Pick up any leading digits and compute 'Prenum' */
  38.         if ( (Prenum>0 && isdigit(c)) || (isdigit(c) && c!='0') ){
  39.             Prenum = Prenum*10 + (c-'0');
  40.             break;
  41.         }
  42.         /* execute the command */
  43.         normal(c);
  44.         Prenum = 0;
  45.         break;
  46.     case INSERT:
  47.         /* We're in insert mode. */
  48.         switch(c){
  49.         case '\033':    /* an ESCape ends input mode */
  50.  
  51.             /* If we're past the end of the file, (which should */
  52.             /* only happen when we're editing a new file or a */
  53.             /* file that doesn't have a newline at the end of */
  54.             /* the line), add a newline automatically. */
  55.             if ( Curschar >= Fileend ) {
  56.                 insertchar('\n');
  57.                 Curschar--;
  58.             }
  59.  
  60.             /* Don't end up on a '\n' if you can help it. */
  61.             if ( Curschar>Filemem && *Curschar=='\n'
  62.                 && *(Curschar-1)!='\n' ) {
  63.                 Curschar--;
  64.             }
  65.             State = NORMAL;
  66.             message("");
  67.             Uncurschar = Insstart;
  68.             Undelchars = Ninsert;
  69.             /* Undobuff[0] = '\0'; */
  70.             /* construct the Redo buffer */
  71.             p=Redobuff;
  72.             q=Insbuff;
  73.             while ( q<Insptr )
  74.                 *p++ = *q++;
  75.             *p++ = '\033';
  76.             *p = '\0';
  77.             updatescreen();
  78.             break;
  79.         case '\b':
  80.             if ( Curschar <= Insstart )
  81.                 beep();
  82.             else {
  83.                 int wasnewline = 0;
  84.                 if ( *Curschar == '\n' )
  85.                     wasnewline=1;
  86.                 Curschar--;
  87.                 delchar();
  88.                 Insptr--;
  89.                 Ninsert--;
  90.                 if ( wasnewline )
  91.                     Curschar++;
  92.                 cursupdate();
  93.                 updatescreen();
  94.             }
  95.             break;
  96.         case '\030':    /* control-x */ 
  97.             { int wasnewline = 0; char *p1;
  98.             p1 = Curschar;
  99.             if ( *Curschar == '\n' )
  100.                 wasnewline = 1;
  101.             inschar('[');
  102.             inschar('x');
  103.             cursupdate();
  104.             updatescreen();
  105.             c1 = gethexchar();
  106.             inschar(c1);
  107.             cursupdate();
  108.             updatescreen();
  109.             c2 = gethexchar();
  110.             Curschar = p1;
  111.             delchar();
  112.             delchar();
  113.             delchar();
  114.             c = 16*hextoint(c1)+hextoint(c2);
  115.             if(Debug)printf("(c=%d)",c);
  116.             if ( wasnewline )
  117.                 Curschar++;
  118.             inschar(c);
  119.             Ninsert++;
  120.             *Insptr++ = c;
  121.             updatescreen();
  122.             break;
  123.             }
  124.         case '\017':
  125.             break;
  126.         case '\r':
  127.             c = '\n';
  128.             /* This is SUPPOSED to fall down into 'default' */
  129.         default:
  130.             insertchar(c);
  131.             break;
  132.         }
  133.         break;
  134.     }
  135.     }
  136. }
  137.  
  138. insertchar(c)
  139. int c;
  140. {
  141.     char *p;
  142.  
  143.     if ( ! anyinput() ) {
  144.         inschar(c);
  145.         *Insptr++ = c;
  146.         Ninsert++;
  147.     }
  148.     else {
  149.         /* If there's any pending input, grab */
  150.         /* it all at once. */
  151.         p = Insptr;
  152.         *Insptr++ = c;
  153.         Ninsert++;
  154.         while ( (c=vpeekc()) != '\033' ) {
  155.             c = vgetc();
  156.             *Insptr++ = c;
  157.             Ninsert++;
  158.         }
  159.         *Insptr = '\0';
  160.         insstr(p);
  161.     }
  162.     updatescreen();
  163. }
  164.  
  165. gethexchar()
  166. {
  167.     int c;
  168.  
  169.     for ( ;; ) {
  170.         windgoto(Cursrow,Curscol);
  171.         windrefresh();
  172.         c = vgetc();
  173.         if ( hextoint(c) >= 0 )
  174.             break;
  175.         message("Expecting a hexidecimal character (0-9 or a-f)");
  176.         beep();
  177.         sleep(1);
  178.     }
  179.     return(c);
  180. }
  181.  
  182. getout()
  183. {
  184.     windgoto(Rows-1,0);
  185.     windrefresh();
  186.     putchar('\r');
  187.     putchar('\n');
  188.     windexit(0);
  189. }
  190.  
  191. cursupdate()
  192. {
  193.     char *p;
  194.     int inc, c, nlines;
  195.  
  196.     /* special case: file is completely empty */
  197.     if ( Fileend == Filemem ) {
  198.         Topchar = Curschar = Filemem;
  199.     }
  200.     else if ( Curschar < Topchar ) {
  201.         nlines = cntlines(Curschar,Topchar);
  202.         /* if the cursor is above the top of */
  203.         /* the screen, put it at the top of the screen.. */
  204.         Topchar = Curschar;
  205.         /* ... and, if we weren't very close to begin with, */
  206.         /* we scroll so that the line is close to the middle. */
  207.         if ( nlines > Rows/3 )
  208.             scrolldown(Rows/3);
  209.         else {
  210.             /* make sure we have the current line completely */
  211.             /* on the screen, by setting Topchar to the */
  212.             /* beginning of the current line (in a strange way). */
  213.             if ( (p=prevline(Topchar))!=NULL &&
  214.                 (p=nextline(p))!=NULL ) {
  215.                 Topchar = p;
  216.             }
  217.         }
  218.         updatescreen();
  219.     }
  220.     else if ( Curschar >= Botchar && Curschar < Fileend ) {
  221.         nlines = cntlines(Botchar,Curschar);
  222.         /* If the cursor is off the bottom of the screen, */
  223.         /* put it at the top of the screen.. */
  224.         Topchar = Curschar;
  225.         /* ... and back up */
  226.         if ( nlines > Rows/3 )
  227.             scrolldown((2*Rows)/3);
  228.         else
  229.             scrolldown(Rows-2);
  230.         updatescreen();
  231.     }
  232.  
  233.     Cursrow = Curscol = Cursvcol = 0;
  234.     for ( p=Topchar; p<Curschar; p++ ) {
  235.         c = *p;
  236.         if ( c == '\n' ) {
  237.             Cursrow++;
  238.             Curscol = Cursvcol = 0;
  239.             continue;
  240.         }
  241.         /* A tab gets expanded, depending on the current column */
  242.         if ( c == '\t' )
  243.             inc = (8 - (Curscol)%8);
  244.         else
  245.             inc = chars[(unsigned)(c & 0xff)].ch_size;
  246.         Curscol += inc;
  247.         Cursvcol += inc;
  248.         if ( Curscol >= Columns ) {
  249.             Curscol -= Columns;
  250.             Cursrow++;
  251.         }
  252.     }
  253. }
  254.  
  255. scrolldown(nlines)
  256. int nlines;
  257. {
  258.     int n;
  259.     char *p;
  260.  
  261.     /* Scroll up 'nlines' lines. */
  262.     for ( n=nlines; n>0; n-- ) {
  263.         if ( (p=prevline(Topchar)) == NULL )
  264.             break;
  265.         Topchar = p;
  266.     }
  267. }
  268.  
  269. /*
  270.  * oneright
  271.  * oneleft
  272.  * onedown
  273.  * oneup
  274.  *
  275.  * Move one char {right,left,down,up}.  Return 1 when
  276.  * sucessful, 0 when we hit a boundary (of a line, or the file).
  277.  */
  278.  
  279. oneright()
  280. {
  281.     char *p;
  282.  
  283.     p = Curschar;
  284.     if ( (*p++)=='\n' || p>=Fileend || *p == '\n' )
  285.         return(0);
  286.     Curschar++;
  287.     return(1);
  288. }
  289.  
  290. oneleft()
  291. {
  292.     char *p;
  293.  
  294.     p = Curschar;
  295.     if ( *p=='\n' || p==Filemem || *(p-1) == '\n' )
  296.         return(0);
  297.     Curschar--;
  298.     return(1);
  299. }
  300.  
  301. beginline()
  302. {
  303.     while ( oneleft() )
  304.         ;
  305. }
  306.  
  307. oneup(n)
  308. {
  309.     char *p, *np;
  310.     int savevcol, k;
  311.  
  312.     savevcol = Cursvcol;
  313.     p = Curschar;
  314.     for ( k=0; k<n; k++ ) {
  315.         /* Look for the previous line */
  316.         if ( (np=prevline(p)) == NULL ) {
  317.             /* If we've at least backed up a little .. */
  318.             if ( k > 0 )
  319.                 break;    /* to update the cursor, etc. */
  320.             else
  321.                 return(0);
  322.         }
  323.         p = np;
  324.     }
  325.     Curschar = p;
  326.     /* This makes sure Topchar gets updated so the complete line */
  327.     /* is one the screen. */
  328.     cursupdate();
  329.     /* try to advance to the same (virtual) column */
  330.     /* that we were at before. */
  331.     Curschar = coladvance(p,savevcol);
  332.     return(1);
  333. }
  334.  
  335. onedown(n)
  336. {
  337.     char *p, *np;
  338.     int k;
  339.  
  340.     p = Curschar;
  341.     for ( k=0; k<n; k++ ) {
  342.         /* Look for the next line */
  343.         if ( (np=nextline(p)) == NULL ) {
  344.             if ( k > 0 )
  345.                 break;
  346.             else
  347.                 return(0);
  348.         }
  349.         p = np;
  350.     }
  351.     /* try to advance to the same (virtual) column */
  352.     /* that we were at before. */
  353.     Curschar = coladvance(p,Cursvcol);
  354.     return(1);
  355. }
  356.