#include        "stdio.h"
#include        "ed.h"
/* ovudfb31.c: (read "up down forward back" for "udfb")
** overlay 31 source code.
** this large overlay is a portmanteau of frequently-used
** commands. One can hardly justify having some of them in
** overlays UNLESS the overlay in question is one which is
** likely to be in memory at all times -- so, this overlay
** includes gobs of the most useful commands.
*/

extern int   wstyle;    /* Which kind of Word operations? */
extern int   currow;    /* set by update() */
extern int   tabsize;   /* if tabs are expanded to spaces. */
extern char *kbufp;     /* Kill buffer data */
extern int   kused;     /* # of bytes used in KB */
extern int   ksize;     /* # of bytes allocated in KB */

#define TABCASE 40      /* case TABCASE and above are special. */
       /* cases < TABCASE are numbered so that we can handle a negative
       ** parameter with "casenumber ^= 1"
       */

ovmain( x )
#define cmdflag (*(int *)0x102)
#define cmdparm (*(int *)0x104)
{
       register LINE   * mylp;
       register WINDOW * mywp;

#define temp_int (*(int *)0xc0)
#define mydoto   (*(int *)0xc2)
#define xbufchar (*(int *)0xc4)
#define limitp   (*(LINE **)0xc6)
#define localx   (*(int *)0xc8)
#define xinsct   (*(int *)0xca)
#define mylen    (*(int *)0xcc)
#define Wdoto    (*(int *)0xce)
       /* the above #defines are temporary variables, in effect:
       ** the compiler generates much smaller code for specific addresses
       ** than it does for stack variables.
       */

       xinsct = 1;
       mywp = curwp;
       mylp = mywp->w_dotp;
       limitp = curbp->b_linep;
       temp_int = mydoto =  0;
       mylen = llength( mylp );
       Wdoto = mywp->w_doto;

       if ( ( localx = x ) < TABCASE )
       {       /* most commands here have negative-parameter counterparts. */

               if ( cmdparm < 0 )
               {       localx ^= 1;
                       cmdparm = -cmdparm;
               }
       }

       switch ( localx )
       {
               case 13:        /* goto end of line. */
                       mydoto = mylen;
                       goto dotpset;
               case 12:        /* goto start of line. */
                       if ( cmdflag && ( mydoto = cmdparm -1 ) > mylen )
                               mydoto = mylen;
                       goto dotpset;
               case 10:        /* page forwards */
               case 11:        /* page back. */
                       cmdparm *= ( mywp->w_ntrows - 1 );
                       goto linemotion;
               case 1: /* up arrow.  */
                       ++cmdparm;
                       goto linemo2;   /* backward goes n+1 lines! */
               case 9: /* gotoeob */
                       if ( cmdparm ) --cmdparm;
               case 8: /* gotobob */
                       mylp = curbp->b_linep;
linemotion:
                       /* if ( localx & 1 ) */
                       /* {    mylp = lforw( mylp ); */
                       /* } */
                       curgoal = curcol = 0;
                       /* mywp->w_flag |= WFHARD; */
linemo2:                /* fall through. */
               case 0: /* down arrow */
               {       /* up or down */
                       if ( ! ( lastflag & CFCPCN ))
                       {       /* Reset goal if last not up/down */
                               curgoal = curcol;
                       }
                       thisflag |= CFCPCN;

                       if ( localx & 1 )       /* backward */
                       {       while ( decparm()
                                       && ( mylp = lback( mylp )) != limitp
                               );
                       }
                       else
                       {       while ( decparm()
                                       && ( mylp = lforw( mylp )) != limitp
                               );
                       }       /* "--n >= 0" for n+1 lines. */

                       while ( mydoto != llength( mylp ))/* NOT mylen! */
                       {       if ( ( xbufchar = lgetc( mylp, mydoto ))
                                       == '\t' )
                                               temp_int |= 0x07;
                               else if ( ! isinsert( xbufchar ))
                                       plustemp();
                               if ( ++temp_int > curgoal ) break;
                               ++mydoto;
                       }
dotpmove:               wfmove();
dotpset:                mywp->w_dotp  = mylp;
                       mywp->w_doto  = mydoto;
                       goto rettrue;   /* return ( 1 ); */
               }       /* end case 0 or 1 */
               case 2: /* word forward */
               case 4: /* del word forward */
               {       /* mylp = curwp->w_dotp; at top (mylp) */
                       mydoto = Wdoto;
                       while ( decparm())
                       {       if ( ! ( wstyle & 2 ) && ! fwx())
                               {       goto retfalse;
                               }
                               while ( inword( ))
                               {       fc1();
                                       /* assert the above cannot fail. */
                                       plustemp();
                               }
                               if ( wstyle & 2 && ! fwx())
                               {       goto retfalse;
                               }
                       }
                       if ( localx == 2 ) goto rettrue;
                       mywp->w_dotp = mylp;
                       mywp->w_doto = mydoto;
                       goto retldel;   /* return ( ldelete( temp_int, 1 )); */
               }       /* end case 2 or 4 */
               case 3: /* word backward */
               case 5: /* del word backward */
               {
                       if ( ! bc1( )) goto retfalse; /* TOF */
                       /* temp_int++; */
                       while ( decparm())
                       {
                               while ( ! inword( ))
                               {       if ( ! bc1()) goto retfalse;
                                       plustemp();
                               }
                               while ( inword( ))
                               {       if ( ! bc1())
                                       {       /* top of file. */
retfalse:                                       return ( 0 );
                                       }
                                       plustemp();
                               }
                       }
                       /* temp_int--; */
                       fc1();  /* can't fail. */
                       if ( localx == 5 )
                       {       /* delword. */
retldel:                        cmdflag = 1;
ret2ldel:                       return ( ldelete( temp_int, cmdflag ));
                       }
rettrue:                return ( 1 );
               }       /* end case 3 or 5. */
               case 6: /* forwdel() */
               case 7: /* backdel() */
               {
                       if ( cmdflag )
                       {       /* Really a kill.       */
                               kdcheck();
                       }
                       if ( ( localx & 1 ) && ! backchar( cmdflag, cmdparm ))
                               goto retfalse;
                       temp_int = cmdparm;
                       goto ret2ldel; /*return(ldelete(cmdparm,cmdflag));*/
               }       /* end cases 6 and 7 */
               case TABCASE:
               {       /* with no parameter, perform tab function;
                       ** with one, set tabsize.
                       */
                       if ( cmdparm < 0 ) return ( 0 );
                       if ( cmdparm != 1 )
                       {       tabsize = cmdparm;
                               return( 1 );
                       }
                       xbufchar = '\t';
                       if ( tabsize )
                       {       xinsct = tabsize -
                                       ( ( curcol + 1 ) % tabsize );
                               xbufchar = ' ';
                       }
                       return( xlinsc( ));
               }       /* end case TABCASE */
               case TABCASE+1: /* openline() */
               case TABCASE+2: /* indent() */
               {       /* openline() keeps cursor in same place,
                       ** inserts arg newlines.
                       ** indent() moves forward with its newlines,
                       ** adds whitespace to match the current line.
                       */
                       mylp = lback( mylp );
                       mydoto = Wdoto;
                       while ( decparm()) if ( ! lnewline()) goto retfalse;
                       mylp = lforw( mylp );
                               /* lnewline() may delete the original
                               ** target of mylp.
                               */
                       if ( localx == ( TABCASE + 1 ))
                       {       /* openline(), done. */
                               goto dotpset;
                       }
                       while ( ( xbufchar = lgetc( mylp, ++cmdparm )) == ' '
                               || xbufchar == '\t' )
                       {       xlinsc( );
                       }
                       if ( xbufchar == '{' )
                       {       /* C indent */
                               xbufchar = '\t';
                               xlinsc();
                       }
                       goto rettrue;
               }       /* end case indent() and openline() */
               case TABCASE+7: /* vi-style kill. */
                       cmdflag = 1;
                       mywp->w_doto = Wdoto = 0;       /* fall through. */
               case TABCASE+3: /* kill() */
               {       kdcheck();
                       mydoto = Wdoto;
                       if ( ! cmdflag )
                       {       temp_int = mylen - mydoto;
                               if ( temp_int == 0 ) temp_int = 1;
                       } else if ( ! cmdparm )
                       {       temp_int = mydoto;
                               mywp->w_doto = 0;
                       } else if ( decparm())  /* "if n > 0" */
                       {       temp_int = mylen - mydoto + 1;
                               mylp = lforw( mylp );
                               while (decparm()) /* while --n */
                               {       if ( mylp == limitp )
                                       goto retfalse;
                                       temp_int += llength( mylp ) + 1;
                                       mylp = lforw( mylp );
                               }
                       } else
                       {       /* mlwrite("neg kill"); */
                               ctrlg();
                               goto retfalse;
                       }
                       goto retldel; /*return(ldelete(temp_int,TRUE));*/
               }       /* end case "kill()" */
               case TABCASE+4: /* yank() */
               {       if ( ! decparm()) goto retfalse;
                       do      /* make cmdparm copies. */
                       {       temp_int = 0;
                               while ( temp_int < kused )
                               {       if ( ( xbufchar = kbufp[ temp_int ])
                                               == '\n' )
                                       {       lnewline( );
                                       } else
                                       {       if ( ! xlinsc())
                                                       goto retfalse;
                                       }
                                       plustemp();
                               }
                       } while ( decparm( ));
                       goto rettrue;
               }       /* end case yank() */
               case TABCASE+5: /* set mark */
               {       mlwrite("[Mark]");
markset:                mywp->w_markp = mylp;
                       mywp->w_marko = Wdoto;
                       goto rettrue;
               }       /* end case set mark */
               case TABCASE+6: /* exchange mark and cursor. */
               {       if ( mywp->w_markp == NULL )
                       {       mlwrite("No mark");
                               return ( 0 );
                       }
                       mywp->w_dotp  = mywp->w_markp;
                       mywp->w_doto  = mywp->w_marko;
                       wfmove();
                       goto markset;
               }       /* end case ^X^X */
       }
}

fc1()   /* saves 10 bytes per call to it. */
{       return( forwchar( 0, 1 ));
}
bc1()   /* saves 10 bytes per call to it. */
{       return( backchar( 0, 1 ));
}
fwx()   /* loop used twice in forwword. */
{       while ( ! inword( ))
       {       if ( ! fc1( )) return ( 0 );
               plustemp();
       }
       return ( 1 );
}
plustemp()      /* temp_int++ : saves 2 bytes per call. */
{       ++temp_int;
}
decparm()       /* --cmdparm >= 0 */
{       return ( --cmdparm >= 0 );
}
xlinsc()
{       return( linsert( xinsct, xbufchar ));
}
kdcheck()
{       if ( ! ( lastflag & CFKILL )) kdelete();
       thisflag |= CFKILL;
}
wfmove()
{       curwp->w_flag |= WFMOVE;
}