Annotation of coherent/g/usr/bin/vi/vi.c, revision 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.