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

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



/*
 * viins.c - pre-gnu-vi  rev. 0.3
 *
 * vi insert functions
 */




#include "vi.h"



addlines (cmd)

char cmd;

{
   auto char line [256], *newline, *nibuf;
   auto int newl, newc, indent;
   insnewlinea ("\n\n", curl);
   /*
    * 'O' command gets autoindent from line below,
    * all others get it from above.
    */
   if (cmd == 'O') {
      docurwhite (curl + 2, &newl, &newc);
      indent = textwidth (texts [curl + 2], newc, 0) - 1;
   } else {
      docurwhite (curl, &newl, &newc);
      indent = textwidth (texts [curl], newc, 0) - 1;
   }
   ++curl;
   curc = 1;
   updscr (1);
   while (getline (line, 0, &indent, 0, 0) ) {
      if ( !(newline = malloc (strlen (line) + 11) ) )
         nomem (9);
      newline [0] = '\n';
      strcpy (&newline [1], line);
      strcat (newline, "\n");
      if (free (texts [curl]) )
         nofree (6);
      texts [curl] = newline;
      /* Append new input line to end of insert buffer */
      strcat (line, "\n");
      if ( !(nibuf = malloc (strlen (ibuf) + strlen (line) + 3) ) )
         nomem (34);
      strcpy (nibuf, ibuf);
      strcat (nibuf, line);
      if (free (ibuf) )
         nofree (34);
      ibuf = nibuf;
      insnewlinea ("\n\n", curl);
      docurwhite (curl, &newl, &newc);
      indent = textwidth (texts [curl], newc, 0) - 1;
      ++curl;
      updscr (1);
   }
   /* Add the last line to the text buffer */
   if ( !(newline = malloc (strlen (line) + 7) ) )
      nomem (10);
   newline [0] = '\n';
   newline [1] = '\0';
   strcat (newline, line);
   strcat (newline, "\n");
   if (free (texts [curl]) )
      nofree (7);
   texts [curl] = newline;
   if ( !(nibuf = malloc (strlen (ibuf) + strlen (newline) ) ) )
      nomem (55);
   strcpy (nibuf, ibuf);
   strcat (nibuf, &newline [1]);
   if (free (ibuf) )
      nofree (55);
   ibuf = nibuf;
   curc = strlen (newline) - 2; 
   if (!curc)
      ++curc;
}


dochange (count)

int count;

{
   auto int oldl, oldc, newl, newc;
   auto char c;
   oldl = curl;
   oldc = curc;
   c = readch ();	/* skip 'c' */
   c = readch ();
   if (c == 'w')
      c = 'e';
   unreadch (c);
   if (docursor (count, &newl, &newc) ) {
      curl = oldl;
      curc = oldc;
      return (-1);
   }
   if (oldl == newl) {
      chginline (newc);
   } else {
      beep ();
      return (-1);
   }
   lastcmd = 'c';
   lastcount = count;
   if ( (c == '/') || (c == '?') )
      laststring [0] = 'n';
   else if ( (c == 'F') || (c == 'f') || (c == 'T') || (c == 't') )
      laststring [0] = ';';
   else
      laststring [0] = c;
   modflag = 1;
   return (0);
}

chginline (endc)

int endc;

{
   auto char line [256], *nibuf;
   auto int startc, zero, m, newl, newc, indent;
   zero = 0;
   texts [curl] [endc] = '$';
   updscr (1);
   startc = curc;
   m = getline (line, 0, &zero, textwidth (texts [curl], curc, 0), 
            textwidth (texts [curl], endc, 0) );
   delinline (curl, startc, endc);
   if (m) {
      reptailline (line);
      strcat (line, "\n");
      if ( !(ibuf = malloc (strlen (line) + 3) ) )
         nomem (132);
      strcpy (ibuf, line);
      updscr (1);
      docurwhite ( (curl - 1), &newl, &newc);
      indent = textwidth (texts [curl - 1], newc, 0) - 1;
      while (getline (line, 1, &indent, 0, 0) ) {
         reptailline (line);
         strcat (line, "\n");
         if ( !(nibuf = malloc (strlen (ibuf) + strlen (line) + 3) ) )
            nomem (33);
         strcpy (nibuf, ibuf);
         strcat (nibuf, line);
         if (free (ibuf) )
            nofree (31);
         ibuf = nibuf;
         docurwhite ( (curl - 1), &newl, &newc);
         indent = textwidth (texts [curl - 1], newc, 0) - 1;
         updscr (1);
      } 
      insheadline (line, curl);
      curc = strlen (line);
      if (curc == 0)
         curc = 1;
      strcat (line, "\n");
      if ( !(nibuf = malloc (strlen (ibuf) + strlen (line) + 3) ) )
         nomem (33);
      strcpy (nibuf, ibuf);
      strcat (nibuf, line);
      if (free (ibuf) )
         nofree (33);
      ibuf = nibuf;
   } else {
      insinline (line);
      curc = curc + strlen (line);
      if ( !(ibuf = malloc (strlen (line) + 3) ) )
         nomem (34);
      strcpy (ibuf, line);
   }
   updscr (1);
   return (0);
}



doinsert  ()


{
   auto char cmd, line [256], *nibuf;
   auto int m, newl, newc, zero, indent;
   zero = 0;
   modflag = 1;
   if (ibuf)
      free (ibuf);
   ibuf = NULL;
   cmd = readch ();
   lastuncmd = lastcmd = cmd;
   if  ( (cmd == 'O') || (cmd == 'o') ) {
      if ( (cmd == 'O') || ( (cmd == 'o') && (endl == curl) ) )
         --curl;
      ibuf = malloc (3);
      ibuf [0] = '\0';
      addlines (cmd);
   } else if ( (cmd == 'A') || (texts [curl] [curc] == '\n') ) {
      if (texts [curl] [curc] != '\n') {
         docureol (&newl, &newc);
         curl = newl;
         curc = newc;
         ++curc;
         updscr (1);
      }
      m = getline (line, 0, &zero, textwidth (texts [curl], curc, 0), 0);
      instailline (line, curl);
      curc = strlen (texts [curl]) - 2;
      if (curc < 1)
         curc = 1;
      if (m)
         strcat (line, "\n");
      if ( !(ibuf = malloc ( strlen (line) + 3) ) )
         nomem (31);
      strcpy (ibuf, line);
      if (m)
         addlines (cmd);
   } else if ( (cmd == 'i') || (cmd == 'I') || (cmd == 'a') ) {
      if (cmd == 'a') {
	 ++curc;
	 updscr (1);
      } else if (cmd == 'I') {
         docurwhite (curl, &newl, &newc);
	 curl = newl;
	 curc = newc;
	 updscr (1);
      }
      lastl1 = curl;
      lastc1 = curc;
      lastuncmd = 'i';
      m = getline (line, 1, &zero, textwidth (texts [curl], curc, 0), 0);
      if (m) {
         reptailline (line);
         strcat (line, "\n");
         if ( !(ibuf = malloc (strlen (line) + 3) ) )
            nomem (32);;
         strcpy (ibuf, line);
         updscr (1);
         docurwhite ( (curl - 1), &newl, &newc);
         indent = textwidth (texts [curl - 1], newc, 0) - 1;
         while (getline (line, 1, &indent, 0, 0) ) {
            reptailline (line);
            strcat (line, "\n");
            if ( !(nibuf = malloc (strlen (ibuf) + strlen (line) + 3) ) )
               nomem (33);
            strcpy (nibuf, ibuf);
            strcat (nibuf, line);
            if (free (ibuf) )
               nofree (31);
            ibuf = nibuf;
            docurwhite ( (curl - 1), &newl, &newc);
            indent = textwidth (texts [curl - 1], newc, 0) - 1;
            updscr (1);
         } 
         insheadline (line, curl);
         curc = strlen (line);
         if (curc < 1)
            curc = 1;
         strcat (line, "\n");
         if ( !(nibuf = malloc (strlen (ibuf) + strlen (line) + 3) ) )
            nomem (33);
         strcpy (nibuf, ibuf);
         strcat (nibuf, line);
         if (free (ibuf) )
            nofree (33);
         ibuf = nibuf;
      } else {
         insinline (line);
	 curc = curc + strlen (line) - 1;
         if ( !(ibuf = malloc (strlen (line) + 3) ) )
            nomem (34);
         strcpy (ibuf, line);
      }
      lastl2 = curl;
      lastc2 = curc + 1;
   }
   updscr (1);
   return (0);
}


doput ()

{
   auto int j, k, lines, oldl;
   auto char cmd, line [256];
   cmd = readch ();
   lastcmd = cmd;
   if (!dbuf) 
      /* No delete buffer */
      return (-1);
   k = 0;
   lines = 0;
   oldl = curl;
   if (dbufstat == LINEOP) {
      curc = 1;
      if (cmd == 'p')  {
         ++curl;
      }
   }
   while (dbuf [k]) {
      j = 0;
      while (dbuf [k] && (dbuf [k] != '\n') ) {
         if (j == 255) break;
         line [j++] = dbuf [k++];
      }
      line [j] = '\0';
      if (dbuf [k] == '\n') {
         reptailline (line);
         ++lines;
         ++k;
      } else {
         if (cmd == 'p') ++curc;
         insinline (line);
         if (cmd == 'P') --curc;
         curc = strlen (line) + curc - 1;
      }
   }
   if (lines > showchange) {
      sprintf (line, "Added %d", lines);
      movtobot ();
      cleareol ();
      writes (line);
      refscr ();
   }
   lastl2 = curl;
   lastc2 = curc;
   modflag = 1;
   curl = oldl;
   return (0);
}


doretype ()

{
   auto char line [256], *nibuf;
   auto int startc, newl, newc, indent, zero, m, n;
   startc = curc;
   zero = 0;
   updscr (1);
   startc = curc;
   m = getline (line, 0, &zero, textwidth (texts [curl], curc, 0), 4096);
   n = strlen (line) - 1;
   delinline (curl, curc, curc + n);
   if (m) {
      reptailline (line);
      strcat (line, "\n");
      if ( !(ibuf = malloc (strlen (line) + 3) ) )
         nomem (132);
      strcpy (ibuf, line);
      updscr (1);
      docurwhite ( (curl - 1), &newl, &newc);
      indent = textwidth (texts [curl - 1], newc, 0) - 1;
      while (getline (line, 1, &indent, 0, 0) ) {
         reptailline (line);
         strcat (line, "\n");
         if ( !(nibuf = malloc (strlen (ibuf) + strlen (line) + 3) ) )
            nomem (33);
         strcpy (nibuf, ibuf);
         strcat (nibuf, line);
         if (free (ibuf) )
            nofree (31);
         ibuf = nibuf;
         docurwhite ( (curl - 1), &newl, &newc);
         indent = textwidth (texts [curl - 1], newc, 0) - 1;
         updscr (1);
      } 
      insheadline (line, curl);
      curc = strlen (line);
      if (curc == 0)
         curc = 1;
      strcat (line, "\n");
      if ( !(nibuf = malloc (strlen (ibuf) + strlen (line) + 3) ) )
         nomem (33);
      strcpy (nibuf, ibuf);
      strcat (nibuf, line);
      if (free (ibuf) )
         nofree (33);
      ibuf = nibuf;
   } else {
      insinline (line);
      curc = curc + strlen (line);
      if ( !(ibuf = malloc (strlen (line) + 3) ) )
         nomem (34);
      strcpy (ibuf, line);
   }
   updscr (1);
   return (0);
}


   
int getline (line, insflag, indent, startcol, chgcol)

char line [];
int insflag, *indent;
int startcol, chgcol;

{
   auto int k, in, j, cury;
   auto char c;
   getyx (curwin->mywin, cury, j);
   if (!insflag && (chgcol <= 0) )
      cleareol ();
   if (autoindent && (*indent > 0) ) {
      in = *indent;
      for (j = 0; j < in; ++j) {
        if (insflag)
           vinsch (' ');
        else
           vaddch (' ');
        line [j] = ' ';
      }
      incol = k = j;
   } else {
      in = k = 0;
      if (startcol > 0)
         incol = startcol;
      else
         incol = 0;
   }
   c = readch ();
   while ( (c != AESC) && (c != '`') && (c != '\r') && (c != '\n') ) {
      if ( (chgcol > 0) && (chgcol < incol) )
         insflag = 1;
      if (c == '\b') {
         if (k > in) {
            --k;
            incol = textwidth (line, k - 1, startcol);
            movtoyx (cury, incol);
            refscr ();
         } else
	    beep ();
      } else if (c == 4) {
         if ( (k == in) && (k > 0) ) {
            k = k - shiftwidth;
            incol = incol - shiftwidth;
            movtoyx (cury, incol);
            refscr ();
            
            in = k;
         } else if ( (k == (in + 1) ) && (line [in] == '0') ) {
            incol = k = 0;
            movtoyx (cury, incol);
            refscr ();
            in = k;
         } else
            beep ();
      } else {
         if (insflag)
            incol = incol + vinsch (c);
         else
            incol = incol + vaddch (c);
         line [k++] = c;
      }	
      c = readch ();
   }
   line [k] = '\0';
   if (*indent > 0)
      *indent = in;
   return ( (c == '\r') || (c == '\n') );
}



insheadline (line, curl)

char line [];
int curl;

{
   auto char *newline;
   if ( !(newline = malloc (strlen (texts [curl]) + strlen (line) + 5) ) )
      nomem (6);
   newline [0] = '\n';
   newline [1] = '\0';
   strcat (newline, line);
   strcat (newline, &texts [curl] [1]);
   if (free (texts [curl]) )
      nofree (3);
   texts [curl] = newline;
   return (0);
}


insinline (line)

char line [];

{
   auto char *newline;
   auto int k;
   if ( !(newline = malloc (strlen (texts [curl]) + strlen (line) + 5) ) )
      nomem (5);
   for (k = 0; k < curc; ++k)
      newline [k] = texts [curl] [k];
   newline [k] = '\0';
   strcat (newline, line);
   strcat (newline, &texts [curl] [curc]);
   if (free (texts [curl]) )
      nofree (2);
   texts [curl] = newline;
   return (0);
}


insnewlinea (line, n)

char *line;
int n;

{
   auto int k;
   for (k = endl; k > n; --k)
      texts [k + 1] = texts [k];
   if ( !(texts [n + 1] = malloc (strlen (line) + 9) ) ) 
      nomem (11);
   strcpy (texts [n + 1], line);
   ++endl;
   for (k = 0; k < 128; ++k) {
      if (marks [k] >= n)
         ++marks [k];
   }
}


instailline (line, curl)

char line [];
int curl;

{
   auto char *newline;
   if ( !(newline = malloc (strlen (texts [curl]) + strlen (line) + 5) ) );
   strcpy (newline, texts [curl]);
   strcpy (&newline [strlen (newline) - 1], line);
   strcat (newline, "\n");
   if (free (texts [curl]) )
      nofree (5);
   texts [curl] = newline;
   return (0);
}   

reinsert (buf)

char *buf;

{
   auto int j, k;
   auto char line [256];
   if (!buf)
      /* Empty insert buffer */
      return (-1);
   k = 0;
   while (buf [k] ) {
      j = 0;
      while (buf [k] && (buf [k] != '\n') ) {
         if (j >= 254) break;
         line [j++] = buf [k++];
      }
      line [j] = '\0';
      if (buf [k] == '\n') {
         reptailline (line);
         ++k;
      } else {
         insinline (line);
         curc = curc + strlen (line);
      }
   }
   return (0);
}


reptailline (line)

char line [];

{
   auto char *newline, *newline2;
   auto int k;
   if ( !(newline = malloc (curc + strlen (line) + 7) ) )
      nomem (7);
   for (k = 0; k < curc; ++k)
      newline [k] = texts [curl] [k];
   newline [k] = '\0';
   strcat (newline, line);
   strcat (newline, "\n");
   if ( !(newline2 = malloc (strlen (&texts [curl] [curc]) + 6) ) )
      nomem (8);
   newline2 [0] = '\n';
   newline2 [1] = '\0';
   strcat (newline2, &texts [curl] [curc]);
   if (free (texts [curl]) )
      nofree (4);
   texts [curl] = newline;
   insnewlinea (newline2, curl);
   ++curl;
   curc = 1;
}

      
      
