Annotation of coherent/d/usr/bin/elvis/vi.c, revision 1.1

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

unix.superglobalmegacorp.com

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