Annotation of coherent/g/usr/bin/vi/vi.c, revision 1.1.1.1

1.1       root        1: /* vi.c */
                      2: 
                      3: /* Author:
                      4:  *     Steve Kirkendall
                      5:  *     Beaverton, OR 97005
                      6:  *     [email protected]
                      7:  */
                      8: 
                      9: 
                     10: #include "config.h"
                     11: #include "ctype.h"
                     12: #include "vi.h"
                     13: 
                     14: 
                     15: 
                     16: /* This array describes what each key does */
                     17: #define NO_FUNC                (MARK (*)())0
                     18: 
                     19: #define NO_ARGS                0
                     20: #define CURSOR         1
                     21: #define CURSOR_CNT_KEY 2
                     22: #define CURSOR_MOVED   3
                     23: #define CURSOR_EOL     4
                     24: #define ZERO           5
                     25: #define DIGIT          6
                     26: #define CURSOR_TEXT    7
                     27: #define KEYWORD                8
                     28: #define ARGSMASK       0x0f
                     29: #define        C_C_K_REP1      (CURSOR_CNT_KEY | 0x10)
                     30: #define C_C_K_CUT      (CURSOR_CNT_KEY | 0x20)
                     31: #define C_C_K_MARK     (CURSOR_CNT_KEY | 0x30)
                     32: #define C_C_K_CHAR     (CURSOR_CNT_KEY | 0x40)
                     33: #ifndef NO_SHOWMODE
                     34: static int keymodes[] = {0, WHEN_REP1, WHEN_CUT, WHEN_MARK, WHEN_CHAR};
                     35: # define KEYMODE(args) (keymodes[(args) >> 4])
                     36: #else
                     37: # define KEYMODE(args) 0
                     38: #endif
                     39: 
                     40: static struct keystru
                     41: {
                     42:        MARK    (*func)();      /* the function to run */
                     43:        uchar   args;           /* description of the args needed */
                     44: #ifndef NO_VISIBLE
                     45:        short   flags;
                     46: #else
                     47:        uchar   flags;          /* other stuff */
                     48: #endif
                     49: }
                     50:        vikeys[] =
                     51: {
                     52: /* NUL not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     53: #ifndef NO_EXTENSIONS
                     54: /* ^A  find cursor word */     {m_wsrch,       KEYWORD,        MVMT|NREL|VIZ},
                     55: #else
                     56: /* ^A  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     57: #endif
                     58: /* ^B  page backward   */      {m_scroll,      CURSOR,         FRNT|VIZ},
                     59: /* ^C  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     60: /* ^D  scroll dn 1/2page*/     {m_scroll,      CURSOR,         NCOL|VIZ},
                     61: /* ^E  scroll up       */      {m_scroll,      CURSOR,         NCOL|VIZ},
                     62: /* ^F  page forward    */      {m_scroll,      CURSOR,         FRNT|VIZ},
                     63: /* ^G  show file status        */      {v_status,      NO_ARGS,        NO_FLAGS},
                     64: /* ^H  move left, like h*/     {m_left,        CURSOR,         MVMT|VIZ},
                     65: /* ^I  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     66: /* ^J  move down       */      {m_updnto,      CURSOR,         MVMT|LNMD|VIZ|INCL},
                     67: /* ^K  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     68: /* ^L  redraw screen   */      {v_redraw,      NO_ARGS,        NO_FLAGS|VIZ},
                     69: /* ^M  mv front next ln */     {m_updnto,      CURSOR,         MVMT|FRNT|LNMD|VIZ|INCL},
                     70: /* ^N  move down       */      {m_updnto,      CURSOR,         MVMT|LNMD|VIZ|INCL|NCOL},
                     71: /* ^O  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     72: /* ^P  move up         */      {m_updnto,      CURSOR,         MVMT|LNMD|VIZ|INCL|NCOL},
                     73: /* ^Q  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     74: /* ^R  redraw screen   */      {v_redraw,      NO_ARGS,        NO_FLAGS|VIZ},
                     75: /* ^S  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     76: /* ^T  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     77: /* ^U  scroll up 1/2page*/     {m_scroll,      CURSOR,         NCOL|VIZ},
                     78: /* ^V  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     79: /* ^W  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     80: /* ^X  move to phys col        */      {m_tocol,       CURSOR,         MVMT|NREL|VIZ},
                     81: /* ^Y  scroll down     */      {m_scroll,      CURSOR,         NCOL|VIZ},
                     82: #ifdef SIGTSTP
                     83: /* ^Z  suspend elvis   */      {v_suspend,     NO_ARGS,        NO_FLAGS},
                     84: #else
                     85: /* ^Z  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     86: #endif
                     87: /* ESC not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     88: /* ^\  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     89: /* ^]  keyword is tag  */      {v_tag,         KEYWORD,        NO_FLAGS},
                     90: /* ^^  previous file   */      {v_switch,      CURSOR,         NO_FLAGS},
                     91: /* ^_  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     92: /* SPC move right,like l*/     {m_right,       CURSOR,         MVMT|INCL|VIZ},
                     93: /*  !  run thru filter */      {v_filter,      CURSOR_MOVED,   FRNT|LNMD|INCL|VIZ},
                     94: /*  "  select cut buffer*/     {v_selcut,      C_C_K_CUT,      PTMV|VIZ},
                     95: #ifndef NO_EXTENSIONS
                     96: /*  #  increment number        */      {v_increment,   KEYWORD,        SDOT},
                     97: #else
                     98: /*  #  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                     99: #endif
                    100: /*  $  move to rear    */      {m_rear,        CURSOR,         MVMT|INCL|VIZ},
                    101: /*  %  move to match   */      {m_match,       CURSOR,         MVMT|INCL|VIZ},
                    102: /*  &  repeat subst    */      {v_again,       CURSOR_MOVED,   SDOT|NCOL|LNMD|INCL},
                    103: /*  '  move to a mark  */      {m_tomark,      C_C_K_MARK,     MVMT|FRNT|NREL|LNMD|INCL|VIZ},
                    104: #ifndef NO_SENTENCE
                    105: /*  (  mv back sentence        */      {m_sentence,    CURSOR,         MVMT|VIZ},
                    106: /*  )  mv fwd sentence */      {m_sentence,    CURSOR,         MVMT|VIZ},
                    107: #else
                    108: /*  (  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    109: /*  )  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    110: #endif
                    111: #ifndef NO_ERRLIST
                    112: /*  *  errlist         */      {v_errlist,     CURSOR,         FRNT|NREL},
                    113: #else
                    114: /*  *  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    115: #endif
                    116: /*  +  mv front next ln */     {m_updnto,      CURSOR,         MVMT|FRNT|LNMD|VIZ|INCL},
                    117: #ifndef NO_CHARSEARCH
                    118: /*  ,  reverse [fFtT] cmd*/    {m__ch,         CURSOR,         MVMT|INCL|VIZ},
                    119: #else
                    120: /*  ,  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    121: #endif
                    122: /*  -  mv front prev ln        */      {m_updnto,      CURSOR,         MVMT|FRNT|LNMD|VIZ|INCL},
                    123: /*  .  special...      */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    124: /*  /  forward search  */      {m_fsrch,       CURSOR_TEXT,    MVMT|NREL|VIZ},
                    125: /*  0  part of count?  */      {NO_FUNC,       ZERO,           MVMT|PTMV|VIZ},
                    126: /*  1  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
                    127: /*  2  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
                    128: /*  3  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
                    129: /*  4  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
                    130: /*  5  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
                    131: /*  6  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
                    132: /*  7  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
                    133: /*  8  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
                    134: /*  9  part of count   */      {NO_FUNC,       DIGIT,          PTMV|VIZ},
                    135: /*  :  run single EX cmd*/     {v_1ex,         CURSOR_TEXT,    NO_FLAGS},
                    136: #ifndef NO_CHARSEARCH
                    137: /*  ;  repeat [fFtT] cmd*/     {m__ch,         CURSOR,         MVMT|INCL|VIZ},
                    138: #else
                    139: /*  ;  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS|VIZ},
                    140: #endif
                    141: /*  <  shift text left */      {v_lshift,      CURSOR_MOVED,   SDOT|FRNT|LNMD|INCL|VIZ},
                    142: /*  =  preset filter   */      {v_reformat,    CURSOR_MOVED,   SDOT|FRNT|LNMD|INCL|VIZ},
                    143: /*  >  shift text right        */      {v_rshift,      CURSOR_MOVED,   SDOT|FRNT|LNMD|INCL|VIZ},
                    144: /*  ?  backward search */      {m_bsrch,       CURSOR_TEXT,    MVMT|NREL|VIZ},
                    145: #ifndef NO_AT
                    146: /*  @  execute a cutbuf */     {v_at,          C_C_K_CUT,      NO_FLAGS},
                    147: #else
                    148: /*  @  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    149: #endif
                    150: /*  A  append at EOL   */      {v_insert,      CURSOR,         SDOT},
                    151: /*  B  move back Word  */      {m_bword,       CURSOR,         MVMT|VIZ},
                    152: /*  C  change to EOL   */      {v_change,      CURSOR_EOL,     SDOT},
                    153: /*  D  delete to EOL   */      {v_delete,      CURSOR_EOL,     SDOT},
                    154: /*  E  move end of Word        */      {m_eword,       CURSOR,         MVMT|INCL|VIZ},
                    155: #ifndef NO_CHARSEARCH
                    156: /*  F  move bk to char */      {m_Fch,         C_C_K_CHAR,     MVMT|INCL|VIZ},
                    157: #else
                    158: /*  F  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    159: #endif
                    160: /*  G  move to line #  */      {m_updnto,      CURSOR,         MVMT|NREL|LNMD|FRNT|INCL|VIZ},
                    161: /*  H  move to row     */      {m_row,         CURSOR,         MVMT|LNMD|FRNT|VIZ|INCL},
                    162: /*  I  insert at front */      {v_insert,      CURSOR,         SDOT},
                    163: /*  J  join lines      */      {v_join,        CURSOR,         SDOT},
                    164: #ifndef NO_EXTENSIONS
                    165: /*  K  look up keyword */      {v_keyword,     KEYWORD,        NO_FLAGS},
                    166: #else
                    167: /*  K  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    168: #endif
                    169: /*  L  move to last row        */      {m_row,         CURSOR,         MVMT|LNMD|FRNT|VIZ|INCL},
                    170: /*  M  move to mid row */      {m_row,         CURSOR,         MVMT|LNMD|FRNT|VIZ|INCL},
                    171: /*  N  reverse prev srch*/     {m_Nsrch,       CURSOR,         MVMT|NREL|VIZ},
                    172: /*  O  insert above line*/     {v_insert,      CURSOR,         SDOT},
                    173: /*  P  paste before    */      {v_paste,       CURSOR,         SDOT},
                    174: /*  Q  quit to EX mode */      {v_quit,        NO_ARGS,        NO_FLAGS},
                    175: /*  R  overtype                */      {v_overtype,    CURSOR,         SDOT},
                    176: /*  S  change line     */      {v_change,      CURSOR_MOVED,   SDOT},
                    177: #ifndef NO_CHARSEARCH
                    178: /*  T  move bk to char */      {m_Tch,         C_C_K_CHAR,     MVMT|INCL|VIZ},
                    179: #else
                    180: /*  T  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    181: #endif
                    182: /*  U  undo whole line */      {v_undoline,    CURSOR,         FRNT},
                    183: #ifndef NO_VISIBLE
                    184: /*  V  start visible   */      {v_start,       CURSOR,         INCL|LNMD|VIZ},
                    185: #else
                    186: /*  V  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    187: #endif
                    188: /*  W  move forward Word*/     {m_fword,       CURSOR,         MVMT|INCL|NWRP|VIZ},
                    189: /*  X  delete to left  */      {v_xchar,       CURSOR,         SDOT},
                    190: /*  Y  yank text       */      {v_yank,        CURSOR_MOVED,   NCOL},
                    191: /*  Z  save file & exit        */      {v_xit,         CURSOR_CNT_KEY, NO_FLAGS},
                    192: /*  [  move back section*/     {m_paragraph,   CURSOR,         MVMT|LNMD|NREL|VIZ},
                    193: #ifndef NO_POPUP
                    194: /*  \  pop-up menu     */      {v_popup,       CURSOR_MOVED,   VIZ},
                    195: #else
                    196: /*  \  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    197: #endif
                    198: /*  ]  move fwd section */     {m_paragraph,   CURSOR,         MVMT|LNMD|NREL|VIZ},
                    199: /*  ^  move to front   */      {m_front,       CURSOR,         MVMT|VIZ},
                    200: /*  _  current line    */      {m_updnto,      CURSOR,         MVMT|LNMD|FRNT|INCL},
                    201: /*  `  move to mark    */      {m_tomark,      C_C_K_MARK,     MVMT|NREL|VIZ},
                    202: /*  a  append at cursor        */      {v_insert,      CURSOR,         SDOT},
                    203: /*  b  move back word  */      {m_bword,       CURSOR,         MVMT|VIZ},
                    204: /*  c  change text     */      {v_change,      CURSOR_MOVED,   SDOT|VIZ},
                    205: /*  d  delete op       */      {v_delete,      CURSOR_MOVED,   SDOT|VIZ},
                    206: /*  e  move end word   */      {m_eword,       CURSOR,         MVMT|INCL|VIZ},
                    207: #ifndef NO_CHARSEARCH
                    208: /*  f  move fwd for char*/     {m_fch,         C_C_K_CHAR,     MVMT|INCL|VIZ},
                    209: #else
                    210: /*  f  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    211: #endif
                    212: /*  g  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    213: /*  h  move left       */      {m_left,        CURSOR,         MVMT|VIZ},
                    214: /*  i  insert at cursor        */      {v_insert,      CURSOR,         SDOT},
                    215: /*  j  move down       */      {m_updnto,      CURSOR,         MVMT|NCOL|LNMD|VIZ|INCL},
                    216: /*  k  move up         */      {m_updnto,      CURSOR,         MVMT|NCOL|LNMD|VIZ|INCL},
                    217: /*  l  move right      */      {m_right,       CURSOR,         MVMT|INCL|VIZ},
                    218: /*  m  define a mark   */      {v_mark,        C_C_K_MARK,     NO_FLAGS},
                    219: /*  n  repeat prev srch        */      {m_nsrch,       CURSOR,         MVMT|NREL|VIZ},
                    220: /*  o  insert below line*/     {v_insert,      CURSOR,         SDOT},
                    221: /*  p  paste after     */      {v_paste,       CURSOR,         SDOT},
                    222: /*  q  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    223: /*  r  replace chars   */      {v_replace,     C_C_K_REP1,     SDOT},
                    224: /*  s  subst N chars   */      {v_subst,       CURSOR,         SDOT},
                    225: #ifndef NO_CHARSEARCH
                    226: /*  t  move fwd to char        */      {m_tch,         C_C_K_CHAR,     MVMT|INCL|VIZ},
                    227: #else
                    228: /*  t  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    229: #endif
                    230: /*  u  undo            */      {v_undo,        CURSOR,         NO_FLAGS},
                    231: #ifndef NO_VISIBLE
                    232: /*  v  start visible   */      {v_start,       CURSOR,         INCL|VIZ},
                    233: #else
                    234: /*  v  not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS},
                    235: #endif
                    236: /*  w  move fwd word   */      {m_fword,       CURSOR,         MVMT|INCL|NWRP|VIZ},
                    237: /*  x  delete character        */      {v_xchar,       CURSOR,         SDOT},
                    238: /*  y  yank text       */      {v_yank,        CURSOR_MOVED,   NCOL|VIZ},
                    239: /*  z  adjust scrn row */      {m_z,           CURSOR_CNT_KEY, NCOL|VIZ},
                    240: /*  {  back paragraph  */      {m_paragraph,   CURSOR,         MVMT|VIZ},
                    241: /*  |  move to column  */      {m_tocol,       CURSOR,         MVMT|NREL|VIZ},
                    242: /*  }  fwd paragraph   */      {m_paragraph,   CURSOR,         MVMT|VIZ},
                    243: /*  ~  upper/lowercase */      {v_ulcase,      CURSOR,         SDOT},
                    244: /* DEL not defined     */      {NO_FUNC,       NO_ARGS,        NO_FLAGS}
                    245: };
                    246: 
                    247: 
                    248: 
                    249: void vi()
                    250: {
                    251:        REG int                 key;    /* keystroke from user */
                    252:        long                    count;  /* numeric argument to some functions */
                    253:        REG struct keystru      *keyptr;/* pointer to vikeys[] element */
                    254:        MARK                    tcurs;  /* temporary cursor */
                    255:        int                     prevkey;/* previous key, if d/c/y/</>/! */
                    256:        MARK                    range;  /* start of range for d/c/y/</>/! */
                    257:        char                    text[132];
                    258:        int                     dotkey; /* last "key" of a change */
                    259:        int                     dotpkey;/* last "prevkey" of a change */
                    260:        int                     dotkey2;/* last extra "getkey()" of a change */
                    261:        int                     dotcnt; /* last "count" of a change */
                    262:        int                     firstkey;
                    263:        REG int                 i;
                    264: 
                    265:        /* tell the redraw() function to start from scratch */
                    266:        redraw(MARK_UNSET, FALSE);
                    267: 
                    268: #ifdef lint
                    269:        /* lint says that "range" might be used before it is set.  This
                    270:         * can't really happen due to the way "range" and "prevkey" are used,
                    271:         * but lint doesn't know that.  This line is here ONLY to keep lint
                    272:         * happy.
                    273:         */
                    274:        range = 0L;
                    275: #endif
                    276: 
                    277:        /* safeguard against '.' with no previous command */
                    278:        dotkey = dotpkey = dotkey2 = dotcnt = 0;
                    279: 
                    280:        /* go immediately into insert mode, if ":set inputmode" */
                    281:        firstkey = 0;
                    282: #ifndef NO_EXTENSIONS
                    283:        if (*o_inputmode)
                    284:        {
                    285:                firstkey = 'i';
                    286:        }
                    287: #endif
                    288: 
                    289:        /* Repeatedly handle VI commands */
                    290:        for (count = 0, prevkey = '\0'; mode == MODE_VI; )
                    291:        {
                    292:                /* if we've moved off the undoable line, then we can't undo it at all */
                    293:                if (markline(cursor) != U_line)
                    294:                {
                    295:                        U_line = 0L;
                    296:                }
                    297: 
                    298:                /* report any changes from the previous command */
                    299:                if (rptlines >= *o_report)
                    300:                {
                    301:                        redraw(cursor, FALSE);
                    302:                        msg("%ld line%s %s", rptlines, (rptlines==1?"":"s"), rptlabel);
                    303:                }
                    304:                rptlines = 0L;
                    305: 
                    306:                /* get the next command key.  It must be ASCII */
                    307:                if (firstkey)
                    308:                {
                    309:                        key = firstkey;
                    310:                        firstkey = 0;
                    311:                }
                    312:                else
                    313:                {
                    314:                        do
                    315:                        {
                    316:                                key = getkey(WHEN_VICMD);
                    317:                        } while (key < 0 || key > 127);
                    318:                }
                    319: #ifdef DEBUG2
                    320:                debout("\nkey='%c'\n", key);
                    321: #endif
                    322: 
                    323:                /* Convert a doubled-up operator such as "dd" into "d_" */
                    324:                if (prevkey && key == prevkey)
                    325:                {
                    326:                        key = '_';
                    327:                }
                    328: 
                    329:                /* look up the structure describing this command */
                    330:                keyptr = &vikeys[key];
                    331: 
                    332:                /* '&' and uppercase operators always act like doubled */
                    333:                if (!prevkey && keyptr->args == CURSOR_MOVED
                    334:                        && (key == '&' || isupper(key)))
                    335:                {
                    336:                        range = cursor;
                    337:                        prevkey = key;
                    338:                        key = '_';
                    339:                        keyptr = &vikeys[key];
                    340:                }
                    341: 
                    342: #ifndef NO_VISIBLE
                    343:                /* if we're in the middle of a v/V command, reject commands
                    344:                 * that aren't operators or movement commands
                    345:                 */
                    346:                if (V_from && !(keyptr->flags & VIZ))
                    347:                {
                    348:                        beep();
                    349:                        prevkey = 0;
                    350:                        count = 0;
                    351:                        continue;
                    352:                }
                    353: #endif
                    354: 
                    355:                /* if we're in the middle of a d/c/y/</>/! command, reject
                    356:                 * anything but movement.
                    357:                 */
                    358:                if (prevkey && !(keyptr->flags & (MVMT|PTMV)))
                    359:                {
                    360:                        beep();
                    361:                        prevkey = 0;
                    362:                        count = 0;
                    363:                        continue;
                    364:                }
                    365: 
                    366:                /* set the "dot" variables, if we're supposed to */
                    367:                if (((keyptr->flags & SDOT)
                    368:                        || (prevkey && vikeys[prevkey].flags & SDOT))
                    369: #ifndef NO_VISIBLE
                    370:                    && !V_from
                    371: #endif
                    372:                )
                    373:                {
                    374:                        dotkey = key;
                    375:                        dotpkey = prevkey;
                    376:                        dotkey2 = '\0';
                    377:                        dotcnt = count;
                    378: 
                    379:                        /* remember the line before any changes are made */
                    380:                        if (U_line != markline(cursor))
                    381:                        {
                    382:                                U_line = markline(cursor);
                    383:                                strcpy(U_text, fetchline(U_line));
                    384:                        }
                    385:                }
                    386: 
                    387:                /* if this is "." then set other vars from the "dot" vars */
                    388:                if (key == '.')
                    389:                {
                    390:                        key = dotkey;
                    391:                        keyptr = &vikeys[key];
                    392:                        prevkey = dotpkey;
                    393:                        if (prevkey)
                    394:                        {
                    395:                                range = cursor;
                    396:                        }
                    397:                        if (count == 0)
                    398:                        {
                    399:                                count = dotcnt;
                    400:                        }
                    401:                        doingdot = TRUE;
                    402: 
                    403:                        /* remember the line before any changes are made */
                    404:                        if (U_line != markline(cursor))
                    405:                        {
                    406:                                U_line = markline(cursor);
                    407:                                strcpy(U_text, fetchline(U_line));
                    408:                        }
                    409:                }
                    410:                else
                    411:                {
                    412:                        doingdot = FALSE;
                    413:                }
                    414: 
                    415:                /* process the key as a command */
                    416:                tcurs = cursor;
                    417:                force_flags = NO_FLAGS;
                    418:                switch (keyptr->args & ARGSMASK)
                    419:                {
                    420:                  case ZERO:
                    421:                        if (count == 0)
                    422:                        {
                    423:                                tcurs = cursor & ~(BLKSIZE - 1);
                    424:                                break;
                    425:                        }
                    426:                        /* else fall through & treat like other digits... */
                    427: 
                    428:                  case DIGIT:
                    429:                        count = count * 10 + key - '0';
                    430:                        break;
                    431: 
                    432:                  case KEYWORD:
                    433:                        /* if not on a keyword, fail */
                    434:                        pfetch(markline(cursor));
                    435:                        key = markidx(cursor);
                    436:                        if (!isalnum(ptext[key]))
                    437:                        {
                    438:                                tcurs = MARK_UNSET;
                    439:                                break;
                    440:                        }
                    441: 
                    442:                        /* find the start of the keyword */
                    443:                        while (key > 0 && isalnum(ptext[key - 1]))
                    444:                        {
                    445:                                key--;
                    446:                        }
                    447:                        tcurs = (cursor & ~(BLKSIZE - 1)) + key;
                    448: 
                    449:                        /* copy it into a buffer, and NUL-terminate it */
                    450:                        i = 0;
                    451:                        do
                    452:                        {
                    453:                                text[i++] = ptext[key++];
                    454:                        } while (isalnum(ptext[key]));
                    455:                        text[i] = '\0';
                    456: 
                    457:                        /* call the function */
                    458:                        tcurs = (*keyptr->func)(text, tcurs, count);
                    459:                        count = 0L;
                    460:                        break;
                    461: 
                    462:                  case NO_ARGS:
                    463:                        if (keyptr->func)
                    464:                        {
                    465:                                (*keyptr->func)();
                    466:                        }
                    467:                        else
                    468:                        {
                    469:                                beep();
                    470:                        }
                    471:                        count = 0L;
                    472:                        break;
                    473:        
                    474:                  case CURSOR:
                    475:                        tcurs = (*keyptr->func)(cursor, count, key, prevkey);
                    476:                        count = 0L;
                    477:                        break;
                    478: 
                    479:                  case CURSOR_CNT_KEY:
                    480:                        if (doingdot)
                    481:                        {
                    482:                                tcurs = (*keyptr->func)(cursor, count, dotkey2);
                    483:                        }
                    484:                        else
                    485:                        {
                    486:                                /* get a key */
                    487:                                i = getkey(KEYMODE(keyptr->args));
                    488:                                if (i == '\033') /* ESC */
                    489:                                {
                    490:                                        count = 0;
                    491:                                        tcurs = MARK_UNSET;
                    492:                                        break; /* exit from "case CURSOR_CNT_KEY" */
                    493:                                }
                    494:                                else if (i == ctrl('V'))
                    495:                                {
                    496:                                        i = getkey(0);
                    497:                                }
                    498: 
                    499:                                /* if part of an SDOT command, remember it */
                    500:                                 if (keyptr->flags & SDOT
                    501:                                 || (prevkey && vikeys[prevkey].flags & SDOT))
                    502:                                {
                    503:                                        dotkey2 = i;
                    504:                                }
                    505: 
                    506:                                /* do it */
                    507:                                tcurs = (*keyptr->func)(cursor, count, i);
                    508:                        }
                    509:                        count = 0L;
                    510:                        break;
                    511:        
                    512:                  case CURSOR_MOVED:
                    513: #ifndef NO_VISIBLE
                    514:                        if (V_from)
                    515:                        {
                    516:                                range = cursor;
                    517:                                tcurs = V_from;
                    518:                                count = 0L;
                    519:                                prevkey = key;
                    520:                                key = (V_linemd ? 'V' : 'v');
                    521:                                keyptr = &vikeys[key];
                    522:                        }
                    523:                        else
                    524: #endif
                    525:                        {
                    526:                                prevkey = key;
                    527:                                range = cursor;
                    528:                                force_flags = LNMD|INCL;
                    529:                        }
                    530:                        break;
                    531: 
                    532:                  case CURSOR_EOL:
                    533:                        prevkey = key;
                    534:                        /* a zero-length line needs special treatment */
                    535:                        pfetch(markline(cursor));
                    536:                        if (plen == 0)
                    537:                        {
                    538:                                /* act on a zero-length section of text */
                    539:                                range = tcurs = cursor;
                    540:                                key = '0';
                    541:                        }
                    542:                        else
                    543:                        {
                    544:                                /* act like CURSOR_MOVED with '$' movement */
                    545:                                range = cursor;
                    546:                                tcurs = m_rear(cursor, 1L);
                    547:                                key = '$';
                    548:                        }
                    549:                        count = 0L;
                    550:                        keyptr = &vikeys[key];
                    551:                        break;
                    552: 
                    553:                  case CURSOR_TEXT:
                    554:                        do
                    555:                        {       
                    556:                                text[0] = key;
                    557:                                text[1] = '\0';
                    558:                                if (doingdot || vgets(key, text + 1, sizeof text - 1) >= 0)
                    559:                                {
                    560:                                        /* reassure user that <CR> was hit */
                    561:                                        qaddch('\r');
                    562:                                        refresh();
                    563: 
                    564:                                        /* call the function with the text */
                    565:                                        tcurs = (*keyptr->func)(cursor, text);
                    566:                                }
                    567:                                else
                    568:                                {
                    569:                                        if (exwrote || mode == MODE_COLON)
                    570:                                        {
                    571:                                                redraw(MARK_UNSET, FALSE);
                    572:                                        }
                    573:                                        mode = MODE_VI;
                    574:                                }
                    575:                        } while (mode == MODE_COLON);
                    576:                        count = 0L;
                    577:                        break;
                    578:                }
                    579: 
                    580:                /* if that command took us out of vi mode, then exit the loop
                    581:                 * NOW, without tweaking the cursor or anything.  This is very
                    582:                 * important when mode == MODE_QUIT.
                    583:                 */
                    584:                if (mode != MODE_VI)
                    585:                {
                    586:                        break;
                    587:                }
                    588: 
                    589:                /* now move the cursor, as appropriate */
                    590:                if (prevkey && ((keyptr->flags & MVMT)
                    591: #ifndef NO_VISIBLE
                    592:                                               || V_from
                    593: #endif
                    594:                                ) && count == 0L)
                    595:                {
                    596:                        /* movements used as targets are less strict */
                    597:                        tcurs = adjmove(cursor, tcurs, (int)(keyptr->flags | force_flags));
                    598:                }
                    599:                else if (keyptr->args == CURSOR_MOVED)
                    600:                {
                    601:                        /* the < and > keys have FRNT,
                    602:                         * but it shouldn't be applied yet
                    603:                         */
                    604:                        tcurs = adjmove(cursor, tcurs, FINL);
                    605:                }
                    606:                else
                    607:                {
                    608:                        tcurs = adjmove(cursor, tcurs, (int)(keyptr->flags | force_flags | FINL));
                    609:                }
                    610: 
                    611:                /* was that the end of a d/c/y/</>/! command? */
                    612:                if (prevkey && ((keyptr->flags & MVMT)
                    613: #ifndef NO_VISIBLE
                    614:                                               || V_from
                    615: #endif
                    616:                                ) && count == 0L)
                    617:                {
                    618: #ifndef NO_VISIBLE
                    619:                        /* turn off the hilight */
                    620:                        V_from = 0L;
                    621: #endif
                    622: 
                    623:                        /* if the movement command failed, cancel operation */
                    624:                        if (tcurs == MARK_UNSET)
                    625:                        {
                    626:                                prevkey = 0;
                    627:                                count = 0;
                    628:                                continue;
                    629:                        }
                    630: 
                    631:                        /* make sure range=front and tcurs=rear.  Either way,
                    632:                         * leave cursor=range since that's where we started.
                    633:                         */
                    634:                        cursor = range;
                    635:                        if (tcurs < range)
                    636:                        {
                    637:                                range = tcurs;
                    638:                                tcurs = cursor;
                    639:                        }
                    640: 
                    641:                        /* The 'w' and 'W' destinations should never take us
                    642:                         * to the front of a line.  Instead, they should take
                    643:                         * us only to the end of the preceding line.
                    644:                         */
                    645:                        if ((keyptr->flags & NWRP) == NWRP
                    646:                          && markline(range) < markline(tcurs)
                    647:                          && (markline(tcurs) > nlines || tcurs == m_front(tcurs, 0L)))
                    648:                        {
                    649:                                tcurs = (tcurs & ~(BLKSIZE - 1)) - BLKSIZE;
                    650:                                pfetch(markline(tcurs));
                    651:                                tcurs += plen;
                    652:                        }
                    653: 
                    654:                        /* adjust for line mode & inclusion of last char/line */
                    655:                        i = (keyptr->flags | vikeys[prevkey].flags);
                    656:                        switch ((i | force_flags) & (INCL|LNMD))
                    657:                        {
                    658:                          case INCL:
                    659:                                tcurs++;
                    660:                                break;
                    661: 
                    662:                          case INCL|LNMD:
                    663:                                tcurs += BLKSIZE;
                    664:                                /* fall through... */
                    665: 
                    666:                          case LNMD:
                    667:                                range &= ~(BLKSIZE - 1);
                    668:                                tcurs &= ~(BLKSIZE - 1);
                    669:                                break;
                    670:                        }
                    671: 
                    672:                        /* run the function */
                    673:                        tcurs = (*vikeys[prevkey].func)(range, tcurs);
                    674:                        if (mode == MODE_VI)
                    675:                        {
                    676:                                (void)adjmove(cursor, cursor, FINL);
                    677:                                cursor = adjmove(cursor, tcurs, (int)(vikeys[prevkey].flags | FINL));
                    678:                        }
                    679: 
                    680:                        /* cleanup */
                    681:                        prevkey = 0;
                    682:                }
                    683:                else if (!prevkey)
                    684:                {
                    685:                        if (tcurs != MARK_UNSET)
                    686:                                cursor = tcurs;
                    687:                }
                    688:        }
                    689: }
                    690: 
                    691: /* This function adjusts the MARK value that they return; here we make sure
                    692:  * it isn't past the end of the line, and that the column hasn't been
                    693:  * *accidentally* changed.
                    694:  */
                    695: MARK adjmove(old, new, flags)
                    696:        MARK            old;    /* the cursor position before the command */
                    697:        REG MARK        new;    /* the cursor position after the command */
                    698:        int             flags;  /* various flags regarding cursor mvmt */
                    699: {
                    700:        static int      colno;  /* the column number that we want */
                    701:        REG char        *text;  /* used to scan through the line's text */
                    702:        REG int         i;
                    703: 
                    704: #ifdef DEBUG2
                    705:        debout("adjmove(%ld.%d, %ld.%d, 0x%x)\n", markline(old), markidx(old), markline(new), markidx(new), flags);
                    706: #endif
                    707: #ifdef DEBUG
                    708:        watch();
                    709: #endif
                    710: 
                    711:        /* if the command failed, bag it! */
                    712:        if (new == MARK_UNSET)
                    713:        {
                    714:                if (flags & FINL)
                    715:                {
                    716:                        beep();
                    717:                        return old;
                    718:                }
                    719:                return new;
                    720:        }
                    721: 
                    722:        /* if this is a non-relative movement, set the '' mark */
                    723:        if (flags & NREL)
                    724:        {
                    725:                mark[26] = old;
                    726:        }
                    727: 
                    728:        /* make sure it isn't past the end of the file */
                    729:        if (markline(new) < 1)
                    730:        {
                    731:                new = MARK_FIRST;
                    732:        }
                    733:        else if (markline(new) > nlines)
                    734:        {
                    735:                if (!(flags & FINL))
                    736:                {
                    737:                        return MARK_EOF;
                    738:                }
                    739:                new = MARK_LAST;
                    740:        }
                    741: 
                    742:        /* fetch the new line */
                    743:        pfetch(markline(new));
                    744: 
                    745:        /* move to the front, if we're supposed to */
                    746:        if (flags & FRNT)
                    747:        {
                    748:                new = m_front(new, 1L);
                    749:        }
                    750: 
                    751:        /* change the column#, or change the mark to suit the column# */
                    752:        if (!(flags & NCOL))
                    753:        {
                    754:                /* change the column# */
                    755:                i = markidx(new);
                    756:                if (i == BLKSIZE - 1)
                    757:                {
                    758:                        new &= ~(BLKSIZE - 1);
                    759:                        if (plen > 0)
                    760:                        {
                    761:                                new += plen - 1;
                    762:                        }
                    763:                        colno = BLKSIZE * 8; /* one heck of a big colno */
                    764:                }
                    765:                else if (plen > 0)
                    766:                {
                    767:                        if (i >= plen)
                    768:                        {
                    769:                                new = (new & ~(BLKSIZE - 1)) + plen - 1;
                    770:                        }
                    771:                        colno = idx2col(new, ptext, FALSE);
                    772:                }
                    773:                else
                    774:                {
                    775:                        new &= ~(BLKSIZE - 1);
                    776:                        colno = 0;
                    777:                }
                    778:        }
                    779:        else
                    780:        {
                    781:                /* adjust the mark to get as close as possible to column# */
                    782:                for (i = 0, text = ptext; i <= colno && *text; text++)
                    783:                {
                    784:                        if (*text == '\t' && !*o_list)
                    785:                        {
                    786:                                i += *o_tabstop - (i % *o_tabstop);
                    787:                        }
                    788:                        else if (UCHAR(*text) < ' ' || *text == 127)
                    789:                        {
                    790:                                i += 2;
                    791:                        }
                    792: #ifndef NO_CHARATTR
                    793:                        else if (*o_charattr && text[0] == '\\' && text[1] == 'f' && text[2])
                    794:                        {
                    795:                                text += 2; /* plus one more in "for()" stmt */
                    796:                        }
                    797: #endif
                    798:                        else
                    799:                        {
                    800:                                i++;
                    801:                        }
                    802:                }
                    803:                if (text > ptext)
                    804:                {
                    805:                        text--;
                    806:                }
                    807:                new = (new & ~(BLKSIZE - 1)) + (int)(text - ptext);
                    808:        }
                    809: 
                    810:        return new;
                    811: }
                    812: 
                    813: 
                    814: #ifdef DEBUG
                    815: watch()
                    816: {
                    817:        static wasset;
                    818: 
                    819:        if (*origname)
                    820:        {
                    821:                wasset = TRUE;
                    822:        }
                    823:        else if (wasset)
                    824:        {
                    825:                mode = MODE_EX;
                    826:                msg("origname was clobbered");
                    827:                endwin();
                    828:                abort();
                    829:        }
                    830: 
                    831:        if (wasset && nlines == 0)
                    832:        {
                    833:                mode = MODE_EX;
                    834:                msg("nlines=0");
                    835:                endwin();
                    836:                abort();
                    837:        }
                    838: }
                    839: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.