Annotation of coherent/d/usr/bin/elvis/move1.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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