#include        "stdio.h"
#include        "ed.h"

/*
* Insert "n" copies of the character "c"
* at the current location of dot. In the easy case
* all that happens is the text is stored in the line.
* In the hard case, the line has to be reallocated.
* When the window list is updated, take special
* care; I screwed it up once. You always update dot
* in the current window. You update mark, and a
* dot in another window, if it is greater than
* the place where you did the insert. Return TRUE
* if all is well, and FALSE on errors.
*/
linsert(n, c)
{
#define cp1 (*(char **)0xa0)
#define cp2 (*(char **)0xa2)
       register LINE   *lp1;   /* 23 times. */
#define lp2 (*(LINE **)0xa8)
#define lp3 (*(LINE **)0xa4)
#define doto (*(int *)0xa6)
       register WINDOW *wp;    /* 15 times, but the best! */
#define localn (*(int *)0xaa)

       lchange( WFEDIT );
       wp = curwp;
       localn = n;

       if (( lp1 = wp->w_dotp ) == curbp->b_linep )
       {       /* At the end: special. Assert that w_doto == 0 */
               /* There is no line at all here, so we must
               ** allocate a new line ( lp2 ) and link it in.
               */
               if ( ( lp2 = lalloc( localn )) == NULL )
               {       /* must be out of memory. */
retfalse:               return ( 0 );
               }

               ( lp3 = lp1->l_bp )->l_fp = lp2;
               lp2->l_fp = lp1;
               ( wp->w_dotp = lp1->l_bp = lp2)->l_bp = lp3;

#ifdef SANITY
               if ( wp->w_doto = localn )
               {       /* not zero count. */
                       clear( &lp2->l_text[0], localn, c );
               }
#else
               clear( &lp2->l_text[0], ( wp->w_doto = localn ), c );
#endif
rettrue:        return ( 1 );
       }
       doto = wp->w_doto;
       if ( ( lp1->l_used + localn ) > lp1->l_size )
       {       /* The lp1 line grows and must be reallocated. */
               if ( ( lp2 = lalloc( lp1->l_used + localn )) == NULL )
                       goto retfalse;

               blockmv( lp2, lp1, 4 );
                       /* lp2->l_fp = lp1->l_fp; */
                       /* lp2->l_bp = lp1->l_bp; */
               blockmv( lp2->l_text, lp1->l_text, doto );
               blockmv( &lp2->l_text[ localn + doto ],
                       &lp1->l_text[ doto ],
                       lp1->l_used - doto );
               lp1->l_fp->l_bp = lp1->l_bp->l_fp = lp2;
               free((char *) lp1);
       } else
       {       /* Easy: in place       */
               (lp2 = lp1)->                   /* Pretend new line     */
                       l_used += localn;
               cp2 = &lp1->l_text[lp1->l_used];
               cp1 = cp2-localn;
               while (cp1 != &lp1->l_text[doto])
                       *--cp2 = *--cp1;
       }
       if ( localn ) clear( &lp2->l_text[doto], localn, c );
       wp = wheadp;                            /* Update windows       */
       while (wp != NULL)
       {       if (wp->w_linep == lp1)
                       wp->w_linep = lp2;
               if (wp->w_dotp == lp1)
               {       wp->w_dotp = lp2;
                       if ( wp == curwp || wp->w_doto > doto )
                       {       wp->w_doto += localn;
                       }
               }
               if ( wp->w_markp == lp1 )
               {       wp->w_markp = lp2;
                       if ( wp->w_marko > doto ) wp->w_marko += localn;
               }
               wp = wp->w_wndp;
       }
       return (TRUE);
}