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

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



/*
 * vi.c - pre-gnu-vi  rev. 0.2
 */


static int unbufptr = 0;
static char unbuf [128];


#include "vi.h"


beep () {putchar (7); }

refscr ()

{
   wrefresh (curwin->mywin);
}

movtobot ()

{
   wmove (curwin->mywin, curwin->height - 1, 0);
}

movtoyx (y, x)

int y, x;

{
   wmove (curwin->mywin, y, x);
}



clearscr ()

{
   werase (curwin->mywin);
}

cleareol ()

{
   wclrtoeol (curwin->mywin);
}

writech (c)

char c;

{
   waddch (curwin->mywin, c);
}

writes (s)

char *s;

{
   waddstr (curwin->mywin, s);
}

readch ()

{
   if (unbufptr > 0) 
      return ( (int) unbuf [--unbufptr] );
   return (getch () );
}

unreadch (c)

{
   unbuf [unbufptr] = c;
   ++unbufptr;
}

reads (buf, startcol)

char buf [];
int startcol;

{
   char c, tbuf [256];
   int k;
   k = 0;
   while (1) {
      c = readch ();
      if ( (c == '\n') || (c == '\r') ) {
         tbuf [k] = '\0';
         strcpy (buf, tbuf);
         return (0);
      } else if (c == '\b') {
         if (k > 0) {
            --k;
            --startcol;
            movtoyx (curwin->height - 1, startcol);
            refscr ();
         } else {
            strcpy (buf, "");
            return (-1);
         }
      } else {
         startcol = startcol + vaddch (c);
         /*refscr ();*/
         tbuf [k] = c;
         ++k;
      }
   }
}
            

               
int charwidth (c, col)

char c;
int col;

{
   if (c < ' ') {
      if (c == '\n')
	 return (0);
      else if (c == '\t')
	 return (tabstop - (col % tabstop) );
      else
	 return (2);
   }
   return (1);
}





int chknewscr (y, x)

int *y, *x;

{
   auto int cx, cy, dl, dx, row, col, n;
   auto char c;
   col = row = 0;
   cx = cy = -1;
   dl = bscrl;
   dx = 1;
   while (dl < endl) {
      if ( (dl == curl) && (dx == curc) ) {
         cy = row;
         cx = col;
      }
      c = texts [dl] [dx];
      if ( (c < ' ') && (c != '\n') && (c != '\t') ) {
         col = col + 2;
         ++dx;
      } else if (c == '\t') {
         n = tabstop - ( col % tabstop);
         col = col + n;
         ++dx;
      } else if (c == '\n') {
         ++dl;
         dx = 1;
         ++row;
         col = 0;
      } else {
         ++dx;
         ++col;
      }
      if ( col > SCRWIDTH) {
         ++row;
         col = 0;
      }
      if (row >= (curwin->height - 1) ) 
         break;
   }
   if (endl == 1) {
      *y = *x = 0;
      return (0);
   }		
   *y = cy;
   *x = cx;
   return (dl);
}



doredraw ()

{
   auto int i;
   auto char c;
   extern char oldscreen [] [MAXSCRWIDTH];
   c = readch ();	/* skip '^L' */
   for (i = 0; i < MAXSCRHEIGHT; ++i) {
      oldscreen [i] [0] = oldscreen [i] [0] + 1;
      if (oldscreen [i] [0] == 1)
         oldscreen [i] [1] = '\0';
   }
   movtoyx (0, 0);
   clearscr ();
   refscr ();
   updscr (1);
   return (0);
}
	



int drawscr (s, fl, y, x)

char s [] [MAXSCRWIDTH];
int fl, *y, *x;

{
   auto int cx, cy, dl, dx, row, col, n, k;
   auto char c, *l, *p;
   col = row = 0;
   cx = cy = -1;
   dl = bscrl;
   dx = 1;
   l = p = s [0];
   while (dl < endl) {
      if ( (dl == curl) && (dx == curc) ) {
         cy = row;
         cx = p - l;
      }
      c = texts [dl] [dx];
      if ( (c < ' ') && (c != '\n') && (c != '\t') ) {
         *p++ = '^';
         *p++ = c + 'A' - 1;
         ++dx;
      } else if (c == '\t') {
         n = tabstop - ( (p - l) % tabstop);
         for (k = 0; k < n; ++k) 
            *p++ = ' ';
         ++dx;
      } else if (c == '\n') {
         *p++ = '\n';
         *p++ = '\0';
         ++dl;
         dx = 1;
         ++row;
         l = p = s [row];
      } else {
         *p++ = c;
         ++dx;
      }
      if ( (p - l) > SCRWIDTH) {
         *p++ = '\n';
         *p++ = '\0';
         ++row;
         l = p = s [row];
      }
      if (row >= (curwin->height - 1) )
         break;
   }
   while (row < (curwin->height - 1) ) {
      s [row] [0] = '~';
      s [row] [1] = '\n';
      s [row] [2] = '\0';
      ++row;
   }
   if (endl == 1) {
      *y = *x = 0;
      return (0);
   }		
   *y = cy;
   *x = cx;
   return (dl);
}

isalphanum (c)

char c;
  
{
   return ( ( ('0' <= c) && (c <= '9') ) || ( ('A' <= c) && (c <= 'Z') ) ||
       ( ('a' <= c) && (c <= 'z') ) );
}

iswhite (c)

char c;

{
   return ( (c == ' ') || (c == '\t') || (c == '\n') );
}

isspecial (c)

char c;

{
   return (! (iswhite (c) || isalphanum (c) ) );
}



paintscreen (s)

char s [] [MAXSCRWIDTH];

{
   auto int j, k;
   extern char oldscreen [] [MAXSCRWIDTH];
   for (k = 0; k < (curwin->height - 1) ; ++k) {
      if (strcmp (oldscreen [k], s [k]) )
         break;
   }
   if (k >= (curwin->height - 1) )
      return (0);
   for (k = 0; k < (curwin->height - 1) ; ++k) {
      if (strcmp (oldscreen [k], s[k]) ) {
         movtoyx (k, 0);
         cleareol ();
         strcpy (oldscreen [k], s [k]);
         for (j = 0; j <= SCRWIDTH; ++j) {
            if (s [k] [j] == '\n')
               break;
            writech (s [k] [j]);
         }
      }
   }
}


saddch (s, c, row, col)

char c, s [][MAXSCRWIDTH];
int row, col;

{
   auto int k, n;
   if ( (c < ' ') && (c != '\n') && (c != '\t') ) {
      s [row] [col++] = '^';
      s [row] [col] = c + 'A' - 1;
      n = 2;
   } else if (c == '\t') {
      n = tabstop - (col % tabstop);
      for (k = 0; k < n; ++k) 
         s [row] [col++] = ' ';
   } else if (c == '\n') {
      s [row] [col++] = '\n';
      s [row] [col] = '\0';
      n = 0;
   } else {
      s [row] [col] = c;
      n = 1;
   }
   return (n);
}

int textwidth (line, n, width)

char line [];
int n;

{
   auto int k;
   for (k = 0; k <= n; ++k) {
      if (line [k] == '\t') 
         width = width + (tabstop - width % tabstop);
      else if (line [k] == '\n')
         width = width;
      else if (line [k] < ' ')
         width = width + 2;
      else
         ++width;
   }
   return (width);
}


updscr (fl)

int fl;

{
   int cx, cy;
   char newscreen [MAXSCRHEIGHT] [MAXSCRWIDTH];
   cx = cy = -1;
   if (fl)
      escrl = drawscr (newscreen, fl, &cy, &cx);
   else
      escrl = chknewscr (&cy, &cx);
   if (cx == -1) {
      if (bscrl > curl) {
         /* scroll back */
	 if ( (bscrl - curl) < 6)
	    bscrl = curl;
	 else
	    bscrl = (curl > 11) ? (curl - 10) : curl;
         escrl = drawscr (newscreen, 1, &cy, &cx);
      } else {
	 /* scroll forward */
         if ( (curl - escrl) < 6)
            bscrl = bscrl + (curl - escrl) + 1;
         else
	    bscrl = ( (endl - curl) > 11) ? curl - 10 : curl;
	 escrl = drawscr (newscreen, 1, &cy, &cx);
      }
   } else if (fl == 0) {
      if (texts [curl] [curc] == '\t')
         cx = textwidth (texts [curl], curc, 0);
      else if ( (texts [curl] [curc] < ' ') && (texts [curl] [curc] != '\n') )
         ++cx;
      movtoyx (cy, cx);
      refscr ();
      return (0);
   }
   paintscreen (newscreen);
   if (texts [curl] [curc] == '\t')
      cx = textwidth (texts [curl], curc, 0) - 1;
   else if ( (texts [curl] [curc] < ' ') && (texts [curl] [curc] != '\n') )
      ++cx;
   movtoyx (cy, cx);
   refscr ();
}
 
         
vaddch (c)

char c;

{
   auto int k, n;     /* used to be external */
   if ( (c < ' ') && (c != '\n') && (c != '\t') ) {
      writech ('^');
      writech (c + 'A' - 1);
      n = 2;
   } else if (c == '\t') {
      n = tabstop - (incol % tabstop);
      for (k = 0; k < n; ++k) {
         writech (' '); 
      }
   } else {
      writech (c);
      n = 1;
   }
   refscr ();
   return (n);
}

         
vinsch (c)

char c;

{
   auto int k, n;     /* used to be external */
   if ( (c < ' ') && (c != '\n') && (c != '\t') ) {
      winsch (curwin->mywin,'^');
      winsch (curwin->mywin, c + 'A' - 1);
      n = 2;
   } else if (c == '\t') {
      n = tabstop - (incol % tabstop);
      for (k = 0; k < n; ++k) {
         winsch (curwin->mywin, ' '); 
      }
   } else {
      winsch (curwin->mywin, c);
      n = 1;
   }
   refscr ();
   return (n);
}


      
      
      
/* bottom */
