/* Copyright (C) 1987 Free Software Foundation, Inc.

   This will be free software eventually,
   but not until it is finished.  */



/*
 * vimain.c - pre-gnu-vi  rev. 0.3
 *
 * main vi functions
 */




#include "vi.h"


int _stack = 6000;

char **texts;

char oldscreen [MAXSCRHEIGHT] [MAXSCRWIDTH];

char *dbuf;

int dbufstat, lastdl, lastdc;

char *ibuf = NULL;

char lasts2 = '/', lastsearch [256] = " ";

char lastfcmd = 'f', lastfchar = ' ';

char curfname [64];

struct winbuf *curwin, *mainwin, *win2, *wins [MAXWINS];

int marks [128];

int incol;

char lastcmd, lastcount, laststring [256];

char lastuncmd;

int curl, curc;

int endl;

int bscrl, escrl;

int mode;

int gj = 0, gk = 0;

int autoindent = 1;
int ignorecase = 0;
int magic = 1;
int shiftwidth = 3;
int wrapscan = 1;
int showchange = 1;
int modflag = 0;
int tabstop = 8;

int seekeol = 0;


#define CMDMODE 0
#define INPMODE 1
#define COLMODE 2

main (argc, argv)

int argc;
char *argv [];

{
   auto int k;
   initscr ();
   for (k = 0; k < MAXWINS; ++k)
      wins [k] = NULL;
   wins [0] = (struct winbuf *) malloc (sizeof (struct winbuf) );
   win2 = (struct winbuf *) malloc (sizeof (struct winbuf) );
   wins [0]->mytexts = (char **) malloc (4096 * sizeof (char *) );
   wins [0]->height = SCRHEIGHT;
   wins [0]->width = SCRWIDTH;
   wins [0]->begx = 0;
   wins [0]->begy = 0;
   wins [0]->wcurl = wins [0]->wcurc = wins [0]->wbscrl = wins [0]->wendl = 1;
   wins [0]->mywin = newwin (0, 0, 0, 0);
   curwin = wins [0];
   /*cbreak ();*/
   noecho ();
   texts = wins [0]->mytexts;
   if (!texts)
      nomem (600);
   curl = endl = -1;
   if (argc > 1)
      newfile (argv [1]);
   else
      newfile ("");
   updscr (1);
   do {
   } while (parse () );
   /*nocbreak ();*/
   echo ();
   delwin (wins [0]->mywin);
   endwin ();
}



int parse ()

/*char c;*/

{
   auto char c;
   auto int newl, newc;
   extern int docursor (), docurzero (), docureol ();
   static int count = -1;
   c = readch ();
   unreadch (c);
   switch (c) {
      case '1' :
      case '2' :
      case '3' :
      case '4' :
      case '5' :
      case '6' :
      case '7' :
      case '8' :
      case '9' :
         if (count == -1)
	    count = c - '0';
         else
	    count = 10 * count + c - '0';
         c = readch ();
	 break;

      case '0' :
         if (count != -1) {
	    count = 10 * count;
            c = readch ();
	 } else {
            if (!docursor (1, &newl, &newc) ) {
	       curl = newl;
	       curc = newc;
	       seekeol = 0;
	    }
            updscr (0);
         }
	 break;
         
      case 'j' :
      case '+' :
      case '\r' :
      case 'k' :
      case '-' :
      case 'l' :
      case ' ' :
      case 'h' :
      case '\b' :
      case '$' :
      case '%' :
      case 'f' :
      case 'F' :
      case 't' :
      case 'T' :
      case ';' :
      case ',' :
      case 'w' :
      case 'e' :
      case 'b' :	
      case 'G' : 
      case '/' :
      case '?' :
      case 'n' :
      case 'N' :
      case ']' :
      case '[' :
      case '^' :
      case 4 :
      case 21 :
      case 5 :
      case 25 :
      case 14 :
      case 'H' :
      case 'L' :
      case 'M' :
      case '\'' :
      case '`' :
       
	 if ( (count == -1) && (c != 'G') && (c != 'H') && (c != 'L') &&
              (c != 'M') )
            count = 1;
         if (!docursor (count, &newl, &newc) ) {
            if (c != '$') {
	       if ( (curl == newl) && (curc == newc) )
		  beep ();
	    } 
            curl = newl;
	    curc = newc;
            if (c == '$') {
	       seekeol = -2;
	    } else if ( (c == 'j') || (c == 'k') ) {
	       if (seekeol == -2) {
		  docureol (&newl, &newc);
		  curl = newl;
		  curc = newc;
	       }
	    } else
	       seekeol = 0;
         } else 
	    beep ();
         if ( (c == 5) || (c == 25) || (c == 4) || (c == 21) )
            updscr (1);
         else
            updscr (0);
	 count = -1;
	 break;
      

      case 'I' :
      case 'i' :
      case 'A' :
      case 'a' :
      case 'o' :
      case 'O' :
	 if (count == -1)
	    doinsert ();
         count = -1;
	 break;


      case 'c' :
	 if (count == -1)
	    count = 1;
	 dochange (count);
	 count = -1;
	 updscr (1);
	 break;
	
      case 'd' :
         if (count == -1)
            count = 1;
	 if (dodelete (count) )
            beep ();
         count = -1;
	 updscr (1);
         break;	
   
      case 'y' :
         if (count == -1)
            count = 1;
         if (dodelete (count) )
            beep ();
         count = -1;
         updscr (1);
         break;
      

      case 'x' :
	 if (count == -1)
	    count = 1; 
         c = readch ();
         unreadch ('l');
         unreadch ('d');
         if (dodelete (count) ) 
	    beep ();
	 count = -1;
	 updscr (1);
	 break;

      case 'X' :
          if (count == -1)
             count = 1;
         c = readch ();
         unreadch ('h');
         unreadch ('d');
          if (dodelete (count) )
             beep ();
          count = -1;
          updscr (1);
          break;
           
      case 'Y' :
         if (count == -1)
            count = 1;
         c = readch ();
         unreadch ('y');
         unreadch ('y');
         if (dodelete (count) )
            beep ();
         count = -1;
         updscr (1);
         break;
         
      case 'p' :
      case 'P' :
         if (count != -1) {
            beep ();
            break;
         }
         doput ();
         updscr (1);
         break;
         

      case 'R' :
         doretype ();
         break;
         
      case 'r' :
         if (texts [curl] [curc] == '\n') {
            beep ();
         } else {
            c = readch ();	/* skip 'r' */
	    texts [curl] [curc] = readch ();
            lastcmd = 'r';
            laststring [0] = texts [curl] [curc];
         }
	 count = -1;
         modflag = 1;
	 updscr (1);
	 break;


      case 12 :
         doredraw ();
         break;
         
      case '~' :
         if ( ('a' <= texts [curl] [curc]) && (texts [curl] [curc] <= 'z') )
            texts [curl] [curc] = texts [curl] [curc] - ('a' - 'A');
         else if ( ('A' <= texts [curl] [curc]) && (texts [curl] [curc] <= 'Z') )
            texts [curl] [curc] = texts [curl] [curc] + ('a' - 'A');
         lastcmd = '~';
         c = readch ();
         count = -1;
         modflag = 1;
         updscr (1);
         break;
         
      case '<' :
         c = readch ();
         unreadch ('<');
         if (dolshift (count) )
            beep ();
         count = -1;
         updscr (1);
         break;
         
      case '>' :
         c = readch ();
         unreadch ('>');
         if (dorshift (count) )
            beep ();
         count = -1;
         updscr (1);
         break;
         
      case 7 :
         dostat ();
         count = -1;
         c = readch ();
         updscr (0);
         break;
         
      case 'm' :
         if (count == -1) {
            if (domark () )
               beep ();
         } else
            beep ();
         count = -1;
         updscr (0);
         break;
         
         
      case 'J' :
         if (count == -1)
            count = 1;
         if (dojoin (count) )
            beep ();
         count = -1;
         updscr (1);
         break;
         
      case '.' :
         if (count == -1) {
	    if (dodot () )
	       beep ();
	 } else
	    beep ();
	 count = -1;
	 updscr (1);
	 break;

      case 'u' :
         if (count == -1) {
            if (doundo () )
               beep ();
         } else
            beep ();
         count = -1;
         updscr (1);
         break;
         
      case ':' :
	 if (count == -1) {
	    if (docommand () )
	       updscr (1);
	    else
	       return (0);
         }
	 break;
	
      default :
         beep ();
         c = readch ();
         count = -1;
         break;
         
   }
   return (1);
}



