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

1.1       root        1: /* move1.c */
                      2: 
                      3: /* Author:
                      4:  *     Steve Kirkendall
                      5:  *     14407 SW Teal Blvd. #C
                      6:  *     Beaverton, OR 97005
                      7:  *     [email protected]
                      8:  */
                      9: 
                     10: 
                     11: /* This file contains most movement functions */
                     12: 
                     13: #include "config.h"
                     14: #include "vi.h"
                     15: #include "ctype.h"
                     16: 
                     17: MARK   m_updnto(m, cnt, cmd)
                     18:        MARK    m;      /* movement is relative to this mark */
                     19:        long    cnt;    /* a numeric argument */
                     20:        int     cmd;    /* the command character */
                     21: {
                     22:        DEFAULT(cmd == 'G' ? nlines : 1L);
                     23: 
                     24:        /* move up or down 'cnt' lines */
                     25:        switch (cmd)
                     26:        {
                     27:          case ctrl('P'):
                     28:          case '-':
                     29:          case 'k':
                     30:                m -= MARK_AT_LINE(cnt);
                     31:                break;
                     32: 
                     33:          case 'G':
                     34:                if (cnt < 1L || cnt > nlines)
                     35:                {
                     36:                        msg("Only %ld lines", nlines);
                     37:                        return MARK_UNSET;
                     38:                }
                     39:                m = MARK_AT_LINE(cnt);
                     40:                break;
                     41: 
                     42:          case '_':
                     43:                cnt--;
                     44:                /* fall through... */
                     45: 
                     46:          default:
                     47:                m += MARK_AT_LINE(cnt);
                     48:        }
                     49: 
                     50:        /* if that left us screwed up, then fail */
                     51:        if (m < MARK_FIRST || markline(m) > nlines)
                     52:        {
                     53:                return MARK_UNSET;
                     54:        }
                     55: 
                     56:        return m;
                     57: }
                     58: 
                     59: /*ARGSUSED*/
                     60: MARK   m_right(m, cnt, key, prevkey)
                     61:        MARK    m;      /* movement is relative to this mark */
                     62:        long    cnt;    /* a numeric argument */
                     63:        int     key;    /* movement keystroke */
                     64:        int     prevkey;/* operator keystroke, or 0 if none */
                     65: {
                     66:        int             idx;    /* index of the new cursor position */
                     67: 
                     68:        DEFAULT(1);
                     69: 
                     70:        /* If used with an operator, then move 1 less character, since the 'l'
                     71:         * command includes the character that it moves onto.
                     72:         */
                     73:        if (prevkey != '\0')
                     74:        {
                     75:                cnt--;
                     76:        }
                     77: 
                     78:        /* move to right, if that's OK */
                     79:        pfetch(markline(m));
                     80:        idx = markidx(m) + cnt;
                     81:        if (idx < plen)
                     82:        {
                     83:                m += cnt;
                     84:        }
                     85:        else
                     86:        {
                     87:                return MARK_UNSET;
                     88:        }
                     89: 
                     90:        return m;
                     91: }
                     92: 
                     93: /*ARGSUSED*/
                     94: MARK   m_left(m, cnt)
                     95:        MARK    m;      /* movement is relative to this mark */
                     96:        long    cnt;    /* a numeric argument */
                     97: {
                     98:        DEFAULT(1);
                     99: 
                    100:        /* move to the left, if that's OK */
                    101:        if (markidx(m) >= cnt)
                    102:        {
                    103:                m -= cnt;
                    104:        }
                    105:        else
                    106:        {
                    107:                return MARK_UNSET;
                    108:        }
                    109: 
                    110:        return m;
                    111: }
                    112: 
                    113: /*ARGSUSED*/
                    114: MARK   m_tocol(m, cnt, cmd)
                    115:        MARK    m;      /* movement is relative to this mark */
                    116:        long    cnt;    /* a numeric argument */
                    117:        int     cmd;    /* either ctrl('X') or '|' */
                    118: {
                    119:        char    *text;  /* text of the line */
                    120:        int     col;    /* column number */
                    121:        int     idx;    /* index into the line */
                    122: 
                    123: 
                    124:        /* if doing ^X, then adjust for sideways scrolling */
                    125:        if (cmd == ctrl('X'))
                    126:        {
                    127:                DEFAULT(*o_columns & 0xff);
                    128:                cnt += leftcol;
                    129:        }
                    130:        else
                    131:        {
                    132:                DEFAULT(1);
                    133:        }
                    134: 
                    135:        /* internally, columns are numbered 0..COLS-1, not 1..COLS */
                    136:        cnt--;
                    137: 
                    138:        /* if 0, that's easy */
                    139:        if (cnt == 0)
                    140:        {
                    141:                m &= ~(BLKSIZE - 1);
                    142:                return m;
                    143:        }
                    144: 
                    145:        /* find that column within the line */
                    146:        pfetch(markline(m));
                    147:        text = ptext;
                    148:        for (col = idx = 0; col < cnt && *text; text++, idx++)
                    149:        {
                    150:                if (*text == '\t' && !*o_list)
                    151:                {
                    152:                        col += *o_tabstop;
                    153:                        col -= col % *o_tabstop;
                    154:                }
                    155:                else if (UCHAR(*text) < ' ' || *text == '\177')
                    156:                {
                    157:                        col += 2;
                    158:                }
                    159: #ifndef NO_CHARATTR
                    160:                else if (text[0] == '\\' && text[1] == 'f' && text[2] && *o_charattr)
                    161:                {
                    162:                        text += 2; /* plus one more as part of for loop */
                    163:                }
                    164: #endif
                    165:                else
                    166:                {
                    167:                        col++;
                    168:                }
                    169:        }
                    170:        if (!*text)
                    171:        {
                    172:                /* the desired column was past the end of the line, so
                    173:                 * act like the user pressed "$" instead.
                    174:                 */
                    175:                return m | (BLKSIZE - 1);
                    176:        }
                    177:        else
                    178:        {
                    179:                m = (m & ~(BLKSIZE - 1)) + idx;
                    180:        }
                    181:        return m;
                    182: }
                    183: 
                    184: /*ARGSUSED*/
                    185: MARK   m_front(m, cnt)
                    186:        MARK    m;      /* movement is relative to this mark */
                    187:        long    cnt;    /* a numeric argument (ignored) */
                    188: {
                    189:        char    *scan;
                    190: 
                    191:        /* move to the first non-whitespace character */
                    192:        pfetch(markline(m));
                    193:        scan = ptext;
                    194:        m &= ~(BLKSIZE - 1);
                    195:        while (*scan == ' ' || *scan == '\t')
                    196:        {
                    197:                scan++;
                    198:                m++;
                    199:        }
                    200: 
                    201:        return m;
                    202: }
                    203: 
                    204: /*ARGSUSED*/
                    205: MARK   m_rear(m, cnt)
                    206:        MARK    m;      /* movement is relative to this mark */
                    207:        long    cnt;    /* a numeric argument (ignored) */
                    208: {
                    209:        /* Try to move *EXTREMELY* far to the right.  It is fervently hoped
                    210:         * that other code will convert this to a more reasonable MARK before
                    211:         * anything tries to actually use it.  (See adjmove() in vi.c)
                    212:         */
                    213:        return m | (BLKSIZE - 1);
                    214: }
                    215: 
                    216: #ifndef NO_SENTENCE
                    217: static int isperiod(ptr)
                    218:        char    *ptr;   /* pointer to possible sentence-ender */
                    219: {
                    220:        /* if not '.', '?', or '!', then it isn't a sentence ender */
                    221:        if (*ptr != '.' && *ptr != '?' && *ptr != '!')
                    222:        {
                    223:                return FALSE;
                    224:        }
                    225: 
                    226:        /* skip any intervening ')', ']', or '"' characters */
                    227:        do
                    228:        {
                    229:                ptr++;
                    230:        } while (*ptr == ')' || *ptr == ']' || *ptr == '"');
                    231: 
                    232:        /* do we have two spaces or EOL? */
                    233:        if (!*ptr || ptr[0] == ' ' && ptr[1] == ' ')
                    234:        {
                    235:                return TRUE;
                    236:        }
                    237:        return FALSE;
                    238: }
                    239: 
                    240: /*ARGSUSED*/
                    241: MARK   m_sentence(m, cnt, cmd)
                    242:        MARK    m;      /* movement is relative to this mark */
                    243:        long    cnt;    /* a numeric argument */
                    244:        int     cmd;    /* either '(' or ')' */
                    245: {
                    246:        REG char        *text;
                    247:        REG long        l;
                    248: 
                    249:        DEFAULT(1);
                    250: 
                    251:        /* If '(' command, then move back one word, so that if we hit '(' at
                    252:         * the start of a sentence we don't simply stop at the end of the
                    253:         * previous sentence and bounce back to the start of this one again.
                    254:         */
                    255:        if (cmd == '(')
                    256:        {
                    257:                m = m_bword(m, 1L, 'b');
                    258:                if (!m)
                    259:                {
                    260:                        return m;
                    261:                }
                    262:        }
                    263: 
                    264:        /* get the current line */
                    265:        l = markline(m);
                    266:        pfetch(l);
                    267:        text = ptext + markidx(m);
                    268: 
                    269:        /* for each requested sentence... */
                    270:        while (cnt-- > 0)
                    271:        {
                    272:                /* search forward for one of [.?!] followed by spaces or EOL */
                    273:                do
                    274:                {
                    275:                        if (cmd == ')')
                    276:                        {
                    277:                                /* move forward, wrap at end of line */
                    278:                                if (!text[0])
                    279:                                {
                    280:                                        l++;
                    281:                                        if (l > nlines)
                    282:                                        {
                    283:                                                return MARK_EOF;
                    284:                                        }
                    285:                                        pfetch(l);
                    286:                                        text = ptext;
                    287:                                }
                    288:                                else
                    289:                                {
                    290:                                        text++;
                    291:                                }
                    292:                        }
                    293:                        else
                    294:                        {
                    295:                                /* move backward, wrap at beginning of line */
                    296:                                if (text == ptext)
                    297:                                {
                    298:                                        do
                    299:                                        {
                    300:                                                if (l <= 1)
                    301:                                                {
                    302:                                                        return MARK_FIRST;
                    303:                                                }
                    304:                                                l--;
                    305:                                                pfetch(l);
                    306:                                        } while (!*ptext);
                    307:                                        text = ptext + plen - 1;
                    308:                                }
                    309:                                else
                    310:                                {
                    311:                                        text--;
                    312:                                }
                    313:                        }
                    314:                } while (!isperiod(text));
                    315:        }
                    316: 
                    317:        /* construct a mark for this location */
                    318:        m = buildmark(text);
                    319: 
                    320:        /* move forward to the first word of the next sentence */
                    321:        m = m_fword(m, 1L, 'w', '\0');
                    322:        if (m == MARK_UNSET)
                    323:        {
                    324:                m = MARK_EOF;
                    325:        }
                    326: 
                    327:        return m;
                    328: }
                    329: #endif
                    330: 
                    331: MARK   m_paragraph(m, cnt, cmd)
                    332:        MARK    m;      /* movement is relative to this mark */
                    333:        long    cnt;    /* a numeric argument */
                    334:        int     cmd;    /* either '{' or '}' */
                    335: {
                    336:        char    *text;  /* text of the current line */
                    337:        char    *pscn;  /* used to scan thru value of "paragraphs" option */
                    338:        long    l, ol;  /* current line number, original line number */
                    339:        int     dir;    /* -1 if we're moving up, or 1 if down */
                    340:        char    col0;   /* character to expect in column 0 */
                    341: #ifndef NO_SENTENCE
                    342: # define SENTENCE(x)   (x)
                    343:        char    *list;  /* either o_sections or o_paragraph */
                    344: #else
                    345: # define SENTENCE(x)
                    346: #endif
                    347: 
                    348:        DEFAULT(1);
                    349: 
                    350:        /* set the direction, based on the command */
                    351:        switch (cmd)
                    352:        {
                    353:          case '{':
                    354:                dir = -1;
                    355:                col0 = '\0';
                    356:                SENTENCE(list = o_paragraphs); 
                    357:                break;
                    358: 
                    359:          case '}':
                    360:                dir = 1;
                    361:                col0 = '\0';
                    362:                SENTENCE(list = o_paragraphs); 
                    363:                break;
                    364: 
                    365:          case '[':
                    366:                if (getkey(0) != '[')
                    367:                {
                    368:                        return MARK_UNSET;
                    369:                }
                    370:                dir = -1;
                    371:                col0 = '{';
                    372:                SENTENCE(list = o_sections); 
                    373:                break;
                    374: 
                    375:          case ']':
                    376:                if (getkey(0) != ']')
                    377:                {
                    378:                        return MARK_UNSET;
                    379:                }
                    380:                dir = 1;
                    381:                col0 = '{';
                    382:                SENTENCE(list = o_sections); 
                    383:                break;
                    384:        }
                    385:        ol = l = markline(m);
                    386: 
                    387:        /* for each paragraph that we want to travel through... */
                    388:        while (l > 0 && l <= nlines && cnt-- > 0)
                    389:        {
                    390:                /* skip blank lines between paragraphs */
                    391:                while (l > 0 && l <= nlines && col0 == *(text = fetchline(l)))
                    392:                {
                    393:                        l += dir;
                    394:                }
                    395: 
                    396:                /* skip non-blank lines that aren't paragraph separators
                    397:                 */
                    398:                do
                    399:                {
                    400: #ifndef NO_SENTENCE
                    401:                        if (*text == '.' && l != ol)
                    402:                        {
                    403:                                for (pscn = list; pscn[0] && pscn[1]; pscn += 2)
                    404:                                {
                    405:                                        if (pscn[0] == text[1] && pscn[1] == text[2])
                    406:                                        {
                    407:                                                pscn = (char *)0;
                    408:                                                goto BreakBreak;
                    409:                                        }
                    410:                                }
                    411:                        }
                    412: #endif
                    413:                        l += dir;
                    414:                } while (l > 0 && l <= nlines && col0 != *(text = fetchline(l)));
                    415: BreakBreak:    ;
                    416:        }
                    417: 
                    418:        if (l > nlines)
                    419:        {
                    420:                m = MARK_EOF;
                    421:        }
                    422:        else if (l <= 0)
                    423:        {
                    424:                m = MARK_FIRST;
                    425:        }
                    426:        else
                    427:        {
                    428:                m = MARK_AT_LINE(l);
                    429:        }
                    430: #ifdef DEBUG2
                    431:        debout("m_paragraph() returning %ld.%d\n", markline(m), markidx(m));
                    432: #endif
                    433:        return m;
                    434: }
                    435: 
                    436: 
                    437: /*ARGSUSED*/
                    438: MARK   m_match(m, cnt)
                    439:        MARK    m;      /* movement is relative to this mark */
                    440:        long    cnt;    /* a numeric argument (normally 0) */
                    441: {
                    442:        long    l;
                    443:        REG char        *text;
                    444:        REG char        match;
                    445:        REG char        nest;
                    446:        REG int         count;
                    447: 
                    448: #ifndef NO_EXTENSIONS
                    449:        /* if we're given a number, then treat it as a percentage of the file */
                    450:        if (cnt > 0)
                    451:        {
                    452:                /* make sure it is a reasonable number */
                    453:                if (cnt > 100)
                    454:                {
                    455:                        msg("can only be from 1%% to 100%%");
                    456:                        return MARK_UNSET;
                    457:                }
                    458: 
                    459:                /* return the appropriate line number */
                    460:                l = (nlines - 1L) * cnt / 100L + 1L;
                    461:                return MARK_AT_LINE(l);
                    462:        }
                    463: #endif /* undef NO_EXTENSIONS */
                    464: 
                    465:        /* get the current line */
                    466:        l = markline(m);
                    467:        pfetch(l);
                    468:        text = ptext + markidx(m);
                    469: 
                    470:        /* search forward within line for one of "[](){}" */
                    471:        for (match = '\0'; !match && *text; text++)
                    472:        {
                    473:                /* tricky way to recognize 'em in ASCII */
                    474:                nest = *text;
                    475:                if ((nest & 0xdf) == ']' || (nest & 0xdf) == '[')
                    476:                {
                    477:                        match = nest ^ ('[' ^ ']');
                    478:                }
                    479:                else if ((nest & 0xfe) == '(')
                    480:                {
                    481:                        match = nest ^ ('(' ^ ')');
                    482:                }
                    483:                else
                    484:                {
                    485:                        match = 0;
                    486:                }
                    487:        }
                    488:        if (!match)
                    489:        {
                    490:                return MARK_UNSET;
                    491:        }
                    492:        text--;
                    493: 
                    494:        /* search forward or backward for match */
                    495:        if (match == '(' || match == '[' || match == '{')
                    496:        {
                    497:                /* search backward */
                    498:                for (count = 1; count > 0; )
                    499:                {
                    500:                        /* wrap at beginning of line */
                    501:                        if (text == ptext)
                    502:                        {
                    503:                                do
                    504:                                {
                    505:                                        if (l <= 1L)
                    506:                                        {
                    507:                                                return MARK_UNSET;
                    508:                                        }
                    509:                                        l--;
                    510:                                        pfetch(l);
                    511:                                } while (!*ptext);
                    512:                                text = ptext + plen - 1;
                    513:                        }
                    514:                        else
                    515:                        {
                    516:                                text--;
                    517:                        }
                    518: 
                    519:                        /* check the char */
                    520:                        if (*text == match)
                    521:                                count--;
                    522:                        else if (*text == nest)
                    523:                                count++;
                    524:                }
                    525:        }
                    526:        else
                    527:        {
                    528:                /* search forward */
                    529:                for (count = 1; count > 0; )
                    530:                {
                    531:                        /* wrap at end of line */
                    532:                        if (!*text)
                    533:                        {
                    534:                                if (l >= nlines)
                    535:                                {
                    536:                                        return MARK_UNSET;
                    537:                                }
                    538:                                l++;
                    539:                                pfetch(l);
                    540:                                text = ptext;
                    541:                        }
                    542:                        else
                    543:                        {
                    544:                                text++;
                    545:                        }
                    546: 
                    547:                        /* check the char */
                    548:                        if (*text == match)
                    549:                                count--;
                    550:                        else if (*text == nest)
                    551:                                count++;
                    552:                }
                    553:        }
                    554: 
                    555:        /* construct a mark for this place */
                    556:        m = buildmark(text);
                    557:        return m;
                    558: }
                    559: 
                    560: /*ARGSUSED*/
                    561: MARK   m_tomark(m, cnt, key)
                    562:        MARK    m;      /* movement is relative to this mark */
                    563:        long    cnt;    /* (ignored) */
                    564:        int     key;    /* keystroke - the mark to move to */
                    565: {
                    566:        /* mark '' is a special case */
                    567:        if (key == '\'' || key == '`')
                    568:        {
                    569:                if (mark[26] == MARK_UNSET)
                    570:                {
                    571:                        return MARK_FIRST;
                    572:                }
                    573:                else
                    574:                {
                    575:                        return mark[26];
                    576:                }
                    577:        }
                    578: 
                    579:        /* if not a valid mark number, don't move */
                    580:        if (key < 'a' || key > 'z')
                    581:        {
                    582:                return MARK_UNSET;
                    583:        }
                    584: 
                    585:        /* return the selected mark -- may be MARK_UNSET */
                    586:        if (!mark[key - 'a'])
                    587:        {
                    588:                msg("mark '%c is unset", key);
                    589:        }
                    590:        return mark[key - 'a'];
                    591: }
                    592: 

unix.superglobalmegacorp.com

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