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

1.1       root        1: 
                      2: /*
                      3:  * The functions in this file implement the search commands (both plain
                      4:  * and incremental searches are supported) and the query-replace command.
                      5:  *
                      6:  * The plain old search code is part of the original MicroEMACS "distribution".
                      7:  * The incremental search code, and the query-replace code, is by Rich Ellison,
                      8:  * with some stylistic modifications.
                      9:  */
                     10: #include       <stdio.h>
                     11: #include       "ed.h"
                     12: 
                     13: #define CCHR(x)                ((x)-'@')
                     14: 
                     15: #define SRCH_BEGIN     (0)                     /* Search sub-codes.    */
                     16: #define        SRCH_FORW       (-1)
                     17: #define SRCH_BACK      (-2)
                     18: #define SRCH_PREV      (-3)
                     19: #define SRCH_NEXT      (-4)
                     20: #define SRCH_NOPR      (-5)
                     21: #define SRCH_ACCM      (-6)
                     22: 
                     23: typedef struct  {
                     24:        int     s_code;
                     25:        LINE    *s_dotp;
                     26:        int     s_doto;
                     27: }      SRCHCOM;
                     28: 
                     29: extern int     ctrlg();
                     30: 
                     31: static SRCHCOM cmds[NSRCH];
                     32: static int     cip;
                     33: 
                     34: int    srch_lastdir = SRCH_NOPR;               /* Last search flags.   */
                     35: 
                     36: /*
                     37:  * Search forward.
                     38:  * Get a search string from the user, and search for it, starting at ".".
                     39:  * If found, "." gets moved to just after the matched characters, and display
                     40:  * does all the hard stuff.  If not found, it just prints a message.
                     41:  * This is normally bound to "M-S".
                     42:  */
                     43: forwsearch(f, n)
                     44: {
                     45:        register int    s;
                     46: 
                     47:        if ((s=readpattern("Search")) != TRUE)
                     48:                return (s);
                     49:        if (forwsrch() == FALSE) {
                     50:                mlwrite("Not found");
                     51:                return (FALSE);
                     52:        }
                     53:        srch_lastdir = SRCH_FORW;
                     54:        return (TRUE);
                     55: }
                     56: 
                     57: /*
                     58:  * Reverse search.
                     59:  * Get a search string from the  user, and search, starting at "."
                     60:  * and proceeding toward the front of the buffer. If found "." is left
                     61:  * pointing at the first character of the pattern [the last character that
                     62:  * was matched]. Bound to "M-R".
                     63:  */
                     64: backsearch(f, n)
                     65: {
                     66:        register int    s;
                     67: 
                     68:        if ((s=readpattern("Reverse search")) != TRUE)
                     69:                return (s);
                     70:        if (backsrch() == FALSE) {
                     71:                mlwrite("Not found");
                     72:                return (FALSE);
                     73:        }
                     74:        srch_lastdir = SRCH_BACK;
                     75:        return (TRUE);
                     76: }
                     77: 
                     78: /* 
                     79:  * Search again, using the same search string and direction as the last search
                     80:  * command.  The direction has been saved in "srch_lastdir", so you know which
                     81:  * way to go.
                     82:  * Bound to "M-/".
                     83:  */
                     84: searchagain(f, n)
                     85: {
                     86:        if (srch_lastdir == SRCH_FORW) {
                     87:                if (forwsrch() == FALSE) {
                     88:                        mlwrite("Not found");
                     89:                        return (FALSE);
                     90:                }
                     91:                return (TRUE);
                     92:        }
                     93:        if (srch_lastdir == SRCH_BACK) {
                     94:                if (backsrch() == FALSE) {
                     95:                        mlwrite("Not found");
                     96:                        return (FALSE);
                     97:                }
                     98:                return (TRUE);
                     99:        }
                    100:        mlwrite("No last search");
                    101:        return (FALSE);
                    102: }
                    103: 
                    104: /*
                    105:  * Use incremental searching, initially in the forward direction.
                    106:  * isearch ignores any explicit arguments.
                    107:  */
                    108: forwisearch(f, n)
                    109: {
                    110:        return (isearch(SRCH_FORW));
                    111: }
                    112: 
                    113: /*
                    114:  * Use incremental searching, initially in the reverse direction.
                    115:  * isearch ignores any explicit arguments.
                    116:  */
                    117: backisearch(f, n)
                    118: {
                    119:        return (isearch(SRCH_BACK));
                    120: }
                    121: 
                    122: /*
                    123:  * Incremental Search.
                    124:  *     dir is used as the initial direction to search.
                    125:  *     ^N      find next occurance  (if first thing typed reuse old string).
                    126:  *     ^P      find prev occurance  (if first thing typed reuse old string).
                    127:  *     ^S      switch direction to forward, find next
                    128:  *     ^R      switch direction to reverse, find prev
                    129:  *     ^Q      quote next character (allows searching for ^N etc.)
                    130:  *     <ESC>   exit from Isearch.
                    131:  *     <DEL>
                    132:  *     ^H      undoes last character typed. (tricky job to do this correctly).
                    133:  *     else    accumulate into search string
                    134:  */
                    135: isearch(dir)
                    136: {
                    137:        int     c;
                    138:        int     pptr;
                    139:        LINE    *clp;
                    140:        int     cbo;
                    141:        int     success;
                    142: 
                    143:        for (cip=0; cip<NSRCH; cip++)
                    144:                cmds[cip].s_code = SRCH_NOPR;
                    145:        cip = 0;
                    146:        pptr = -1;
                    147:        clp = curwp->w_dotp;
                    148:        cbo = curwp->w_doto;
                    149:        isrch_lpush();
                    150:        isrch_cpush(SRCH_BEGIN);
                    151:        success = TRUE;
                    152:        isrch_prompt(dir,TRUE,success);
                    153:        for (;;) {
                    154:                update();
                    155:                c = ttgetc();
                    156:                bracketoff();
                    157:                switch (c) {
                    158: 
                    159:                case CCHR('M'):
                    160:                case METACH:
                    161: #if LK201
                    162:                case AGRAVE:
                    163: #endif
                    164:                        srch_lastdir = dir;
                    165:                        mlwrite("[Done]");
                    166:                        return (TRUE);
                    167: 
                    168:                case CCHR('G'):
                    169:                        curwp->w_dotp = clp;
                    170:                        curwp->w_doto = cbo;
                    171:                        curwp->w_flag |= WFMOVE;
                    172:                        srch_lastdir = dir;
                    173:                        mlwrite("Aborting");
                    174:                        return (FALSE);
                    175: 
                    176:                case CCHR('S'):
                    177:                case CCHR('F'):
                    178:                        if (dir == SRCH_BACK) {
                    179:                                dir = SRCH_FORW;
                    180:                                isrch_lpush();
                    181:                                isrch_cpush(SRCH_FORW);
                    182:                                success = TRUE;
                    183:                        }
                    184:                        /* drop through to find next    */
                    185: 
                    186:                case CCHR('N'):
                    187:                        if ((success == FALSE)&&(dir == SRCH_FORW))
                    188:                                break;
                    189:                        isrch_lpush();
                    190:                        forwchar(FALSE, 1);
                    191:                        if (isrch_find(SRCH_NEXT) != FALSE) {
                    192:                                isrch_cpush(SRCH_NEXT);
                    193:                                pptr = strlen(pat);
                    194:                        } else {
                    195:                                backchar(FALSE, 1);
                    196:                                tbeep();
                    197:                                success = FALSE;
                    198:                        }
                    199:                        isrch_prompt(dir,FALSE,success);
                    200:                        break;
                    201: 
                    202:                case CCHR('R'):
                    203:                case CCHR('B'):
                    204:                        if (dir == SRCH_FORW) {
                    205:                                dir = SRCH_BACK;
                    206:                                isrch_lpush();
                    207:                                isrch_cpush(SRCH_BACK);
                    208:                                success = TRUE;
                    209:                        }
                    210:                        /* drop through to find prev    */
                    211: 
                    212:                case CCHR('P'):
                    213:                        if ((success == FALSE)&&(dir == SRCH_BACK))
                    214:                                break;
                    215:                        isrch_lpush();
                    216:                        backchar(FALSE, 1);
                    217:                        if (isrch_find(SRCH_PREV) != FALSE) {
                    218:                                isrch_cpush(SRCH_PREV);
                    219:                                pptr = strlen(pat);
                    220:                        } else {
                    221:                                forwchar(FALSE, 1);
                    222:                                tbeep();
                    223:                                success = FALSE;
                    224:                        }
                    225:                        isrch_prompt(dir,FALSE,success);
                    226:                        break;
                    227: 
                    228:                case CCHR('H'):
                    229:                case 0x7f:
                    230:                        if (isrch_undo(&pptr,&dir) != TRUE) {
                    231:                                return (ABORT);
                    232:                        }
                    233:                        if (isrch_peek() != SRCH_ACCM)
                    234:                                success = TRUE;
                    235:                        isrch_prompt(dir,FALSE,success);
                    236:                        break;
                    237: 
                    238:                case CCHR('^'):
                    239:                case CCHR('Q'):
                    240:                        c = ttgetc();
                    241:                case CCHR('U'):
                    242:                case CCHR('X'):
                    243:                case CCHR('I'):
                    244:                case CCHR('J'):
                    245:                        goto  addchar;
                    246:                default:
                    247:                        if (c < ' ') {          /* uninterpreted ctrl   */
                    248:                                c += '@';
                    249:                                c |= CTRL;
                    250:                                success = execute(c, FALSE, 1);
                    251:                                curwp->w_flag |= WFMOVE;
                    252:                                return (success);
                    253:                        }                               
                    254: addchar:
                    255:                        if (pptr == -1)
                    256:                                pptr=0;
                    257:                        if (pptr == 0)
                    258:                                success = TRUE;
                    259:                        pat[pptr++] = c;
                    260:                        if (pptr==NPAT) {
                    261:                                mlwrite("Pattern too long");
                    262:                                ctrlg(FALSE, 0);
                    263:                                return (ABORT);
                    264:                        }
                    265:                        pat[pptr] = '\0';
                    266:                        isrch_lpush();
                    267:                        if (success != FALSE) {
                    268:                                if (isrch_find(dir) != FALSE) {
                    269:                                        isrch_cpush(c);
                    270:                                } else {
                    271:                                        success = FALSE;
                    272:                                        tbeep();
                    273:                                        isrch_cpush(SRCH_ACCM);
                    274:                                }
                    275:                        } else {
                    276:                                isrch_cpush(SRCH_ACCM);
                    277:                        }
                    278:                        isrch_prompt(dir, FALSE, success);
                    279:                }
                    280:        }
                    281: }
                    282: 
                    283: isrch_cpush(cmd)
                    284: register int   cmd;
                    285: {
                    286:        if (++cip >= NSRCH)
                    287:                cip = 0;
                    288:        cmds[cip].s_code = cmd;
                    289: }
                    290: 
                    291: isrch_lpush()
                    292: {
                    293:        register int    ctp;
                    294: 
                    295:        ctp = cip+1;
                    296:        if (ctp >= NSRCH)
                    297:                ctp = 0;
                    298:        cmds[ctp].s_code = SRCH_NOPR;
                    299:        cmds[ctp].s_doto = curwp->w_doto;
                    300:        cmds[ctp].s_dotp = curwp->w_dotp;
                    301: }
                    302: 
                    303: isrch_pop()
                    304: {
                    305:        if (cmds[cip].s_code != SRCH_NOPR) {
                    306:                curwp->w_doto  = cmds[cip].s_doto; 
                    307:                curwp->w_dotp  = cmds[cip].s_dotp;
                    308:                curwp->w_flag |= WFMOVE;        /* Was "=", wrong.      */
                    309:                cmds[cip].s_code = SRCH_NOPR;
                    310:        }
                    311:        if (--cip <= 0)                         /* Is "=" right?        */
                    312:                cip = NSRCH-1;
                    313: }
                    314: 
                    315: int
                    316: isrch_peek()   
                    317: {
                    318:        if (cip == 0)
                    319:                return (cmds[NSRCH-1].s_code);
                    320:        else
                    321:                return (cmds[cip-1].s_code);
                    322: }
                    323: 
                    324: int
                    325: isrch_undo(pptr,dir)
                    326: register int   *pptr;
                    327: register int   *dir;
                    328: {
                    329:        switch (cmds[cip].s_code) {
                    330:        case SRCH_NOPR:
                    331:        case SRCH_BEGIN:
                    332:        case SRCH_NEXT:
                    333:        case SRCH_PREV:
                    334:                break;
                    335: 
                    336:        case SRCH_FORW:
                    337:                if (*dir == SRCH_BACK) {
                    338:                        mlwrite("ISEARCH error,  to back when already back");
                    339:                        return (FALSE);
                    340:                }
                    341:                *dir = SRCH_BACK;
                    342:                break;
                    343: 
                    344:        case SRCH_BACK:
                    345:                if (*dir == SRCH_FORW) {
                    346:                        mlwrite("ISEARCH error,  to forw when already forw");
                    347:                        return (FALSE);
                    348:                }
                    349:                *dir = SRCH_FORW;
                    350:                break;
                    351: 
                    352:        case SRCH_ACCM:
                    353:        default:
                    354:                if (*pptr == 0) {
                    355:                        mlwrite("ISEARCH error,  delete without character");
                    356:                        return (FALSE);
                    357:                }
                    358:                *pptr -= 1;
                    359:                if (*pptr < 0)
                    360:                        *pptr = 0;
                    361:                pat[*pptr] = '\0';
                    362:                break;
                    363:        }
                    364:        isrch_pop();
                    365:        return (TRUE);
                    366: }
                    367: 
                    368: isrch_find(dir)
                    369: register int   dir;
                    370: {
                    371:        register int    plen;
                    372: 
                    373:        plen = strlen(pat);
                    374:        if (plen != 0) {
                    375:                if (dir==SRCH_FORW || dir==SRCH_NEXT) {
                    376:                        backchar(FALSE, plen);
                    377:                        if (forwsrch() == FALSE) {
                    378:                                forwchar(FALSE, plen);
                    379:                                return (FALSE);
                    380:                        }
                    381:                        return (TRUE);
                    382:                }
                    383:                if (dir==SRCH_BACK || dir==SRCH_PREV) {
                    384:                        forwchar(FALSE, plen);
                    385:                        if (backsrch() == FALSE) {
                    386:                                backchar(FALSE, plen);
                    387:                                return (FALSE);
                    388:                        }
                    389:                        return (TRUE);
                    390:                }
                    391:                mlwrite("bad call to isrch_find");
                    392:                ctrlg(FALSE, 0);
                    393:                return (FALSE);
                    394:        }
                    395:        return (FALSE);
                    396: }
                    397: 
                    398: /*
                    399:  * If called with "dir" not one of SRCH_FORW
                    400:  * or SRCH_BACK, this routine used to print an error
                    401:  * message. It also used to return TRUE or FALSE,
                    402:  * depending on if it liked the "dir". However, none
                    403:  * of the callers looked at the status, so I just
                    404:  * made the checking vanish.
                    405:  */
                    406: isrch_prompt(dir, flag, success)
                    407: {
                    408:        if (dir == SRCH_FORW) {
                    409:                if (success != FALSE)
                    410:                        isrch_dspl("i-search forward", flag);
                    411:                else {
                    412:                        isrch_dspl("failing i-search forward", flag);
                    413:                        curwp->w_flag |= WFEDIT;
                    414:                }
                    415: 
                    416:        } else if (dir == SRCH_BACK) {
                    417:                if (success != FALSE)
                    418:                        isrch_dspl("i-search backward", flag);
                    419:                else {
                    420:                        isrch_dspl("failing i-search backward", flag);
                    421:                        curwp->w_flag |= WFEDIT;
                    422:                }
                    423:        }
                    424: }
                    425: 
                    426: /*
                    427:  * Prompt writing routine for the incremental
                    428:  * search. The "prompt" is just a string. The "flag" determines
                    429:  * if a "[ ]" or ":" embelishment is used. The string is packed
                    430:  * into a big buffer and zapped out with a single call to
                    431:  * "mlwrite". The "26" in the "tpat" declaration is the length
                    432:  * of the longest prompt string. This actually isn't long
                    433:  * enough if the pattern is full of control characters
                    434:  * and other things that need an "^".
                    435:  */
                    436: isrch_dspl(prompt, flag)
                    437: uchar  *prompt;
                    438: {
                    439:        register uchar  *cp1;
                    440:        register uchar  *cp2;
                    441:        register unsigned c;
                    442:        uchar           tpat[NPAT+26+2+1+1];
                    443: 
                    444:        cp1 = &tpat[0];
                    445:        cp2 = prompt;
                    446:        while ((c = *cp2++) != '\0')
                    447:                *cp1++ = c;
                    448:        if (flag != FALSE) {
                    449:                *cp1++ = ' ';
                    450:                *cp1++ = '[';
                    451:        } else {
                    452:                *cp1++ = ':';
                    453:                *cp1++ = ' ';
                    454:        }
                    455:        cp2 = &pat[0];
                    456:        while ((c = *cp2++) != 0) {
                    457:                if (cp1 < &tpat[NPAT+20-4]) {   /* "??]\0"              */
                    458:                        if (dblchr(c)) {
                    459:                                *cp1++ = '^';
                    460:                                c ^= 0x40;
                    461:                        } else if (c == '%')    /* Map "%" to           */
                    462:                                *cp1++ = c;     /* "%%".                */
                    463:                        *cp1++ = c;
                    464:                }
                    465:        }
                    466:        if (flag != FALSE)
                    467:                *cp1++ = ']';
                    468:        *cp1= '\0';
                    469:        mlwrite(tpat);
                    470: }
                    471: 
                    472: /*
                    473:  * Query Replace.
                    474:  *     Replace strings selectively.  Does a search and replace operation.
                    475:  *     A space or a comma replaces the string, a period replaces and quits,
                    476:  *     an n doesn't replace, a C-G quits.
                    477:  */
                    478: queryrepl(f, n)
                    479: {
                    480:        register int    s;
                    481:        uchar           news[NPAT];
                    482:        LINE            *clp;
                    483:        int             cbo;
                    484:        register int    flg;
                    485:        register int    flgc;
                    486:        int             rcnt;
                    487: 
                    488:        if ((s=readpattern("Old string")) != TRUE)
                    489:                return (s);
                    490:        if ((s=mlreply("New string: ",news, NPAT)) == ABORT)
                    491:                return (s);
                    492:        if (s == FALSE)                         /* Null string.         */
                    493:                news[0] = '\0';
                    494:        mlwrite("Query Replace:  [%s] -> [%s]", pat, news);
                    495:        clp = curwp->w_dotp;
                    496:        cbo = curwp->w_doto;
                    497:        rcnt = 0;
                    498:        flg = TRUE;
                    499:        flgc = FALSE;
                    500:        while (flg==TRUE && forwsrch()==TRUE) {
                    501:                if (flgc != TRUE) {
                    502:                retry:
                    503:                        update();
                    504:                        switch (ttgetc()) {
                    505:                        case ' ':
                    506:                        case ',':
                    507:                                replstring(news, f);
                    508:                                rcnt++;
                    509:                                break;
                    510: 
                    511:                        case '.':
                    512:                                replstring(news, f);
                    513:                                rcnt++;
                    514:                                flg = FALSE;
                    515:                                break;
                    516: 
                    517:                        case '\007':
                    518:                                flg = ABORT;
                    519:                                ctrlg(FALSE, 0);
                    520:                                break;
                    521: 
                    522:                        case '!':
                    523:                                replstring(news, f);
                    524:                                rcnt++;
                    525:                                flgc = TRUE;
                    526:                                break;
                    527: 
                    528:                        case 'n':
                    529:                                break;
                    530: 
                    531:                        default:
                    532: mlwrite("<SP>[,] replace,  [.] rep-end,  [n] dont,  [!] repl rest  <C-G> quit");
                    533:                                goto retry;
                    534:                        }
                    535:                } else {
                    536:                        replstring(news, f);
                    537:                        rcnt++;
                    538:                }
                    539:        }
                    540:        curwp->w_dotp = clp;
                    541:        curwp->w_doto = cbo;
                    542:        curwp->w_flag |= WFHARD;
                    543:        update();
                    544:        if (rcnt == 0)
                    545:                mlwrite("[No replacements done]");
                    546:        else if (rcnt == 1)
                    547:                mlwrite("[1 replacement done]");
                    548:        else
                    549:                mlwrite("[%d replacements done]", rcnt);
                    550:        return (TRUE);
                    551: }
                    552: 
                    553: #define        FLOWER  0                               /* Found lower case.    */
                    554: #define        FCAPTL  1                               /* Found capital.       */
                    555: #define        FUPPER  2                               /* Found upper case.    */
                    556: 
                    557: replstring(st, f)
                    558: uchar  *st;
                    559: int    f;
                    560: {
                    561:        register uchar  *tpt;
                    562:        register int    plen;
                    563:        register int    rtype;
                    564:        register int    c, d;
                    565: 
                    566:        plen = strlen(pat);
                    567:        backchar(TRUE, plen);
                    568:        c = lgetc(curwp->w_dotp, curwp->w_doto);
                    569:        rtype = FLOWER;
                    570:        if (ishi(c)) {
                    571:                rtype = FCAPTL;
                    572:                if (curwp->w_doto+1 != llength(curwp->w_dotp)) {
                    573:                        c = lgetc(curwp->w_dotp, curwp->w_doto+1);
                    574:                        if (ishi(c))
                    575:                                rtype = FUPPER;
                    576:                }
                    577:        }
                    578:        ldelete(plen, FALSE);
                    579:        tpt = &st[0];
                    580:        if (f != FALSE) {
                    581:                while (*tpt != '\0')
                    582:                        linsert(1, *tpt++);
                    583:        } else {
                    584:                switch (rtype) {
                    585:                case FLOWER:
                    586:                        while (*tpt != '\0') {
                    587:                                linsert(1, *tpt++);
                    588:                        }
                    589:                        break;
                    590: 
                    591:                case FCAPTL:
                    592:                        if (*tpt != '\0') {
                    593:                                if (d = islow(*tpt))
                    594:                                        linsert(1, d);
                    595:                                else
                    596:                                        linsert(1, *tpt);
                    597:                                tpt++;
                    598:                        }
                    599:                        while (*tpt != '\0')
                    600:                                linsert(1, *tpt++);
                    601:                        break;
                    602: 
                    603:                case FUPPER:
                    604:                        while (*tpt != '\0') {
                    605:                                if (d = islow(*tpt))
                    606:                                        linsert(1, d);
                    607:                                else
                    608:                                        linsert(1, *tpt);
                    609:                                tpt++;
                    610:                        }
                    611:                        break;
                    612:                }
                    613:        }
                    614:        curwp->w_flag |= WFHARD;
                    615: }
                    616: 
                    617: /*
                    618:  * This routine does the real work of a
                    619:  * forward search. The pattern is sitting in the external
                    620:  * variable "pat". If found, dot is updated, the window system
                    621:  * is notified of the change, and TRUE is returned. If the
                    622:  * string isn't found, FALSE is returned.
                    623:  */
                    624: forwsrch()
                    625: {
                    626:        register LINE   *clp;
                    627:        register int    cbo;
                    628:        register LINE   *tlp;
                    629:        register int    tbo;
                    630:        register uchar  *pp;
                    631:        register int    c;
                    632: 
                    633:        clp = curwp->w_dotp;
                    634:        cbo = curwp->w_doto;
                    635:        while (clp != curbp->b_linep) {
                    636:                if (cbo == llength(clp)) {
                    637:                        clp = lforw(clp);
                    638:                        cbo = 0;
                    639:                        c = '\n';
                    640:                } else
                    641:                        c = lgetc(clp, cbo++);
                    642:                if (eq(c, pat[0]) != FALSE) {
                    643:                        tlp = clp;
                    644:                        tbo = cbo;
                    645:                        pp  = &pat[1];
                    646:                        while (*pp != 0) {
                    647:                                if (tlp == curbp->b_linep)
                    648:                                        goto fail;
                    649:                                if (tbo == llength(tlp)) {
                    650:                                        tlp = lforw(tlp);
                    651:                                        tbo = 0;
                    652:                                        c = '\n';
                    653:                                } else
                    654:                                        c = lgetc(tlp, tbo++);
                    655:                                if (eq(c, *pp++) == FALSE)
                    656:                                        goto fail;
                    657:                        }
                    658:                        curwp->w_dotp  = tlp;
                    659:                        curwp->w_doto  = tbo;
                    660:                        curwp->w_flag |= WFMOVE;
                    661:                        return (TRUE);
                    662:                }
                    663:        fail:   ;
                    664:        }
                    665:        return (FALSE);
                    666: }
                    667: 
                    668: /*
                    669:  * This routine does the real work of a
                    670:  * backward search. The pattern is sitting in the external
                    671:  * variable "pat". If found, dot is updated, the window system
                    672:  * is notified of the change, and TRUE is returned. If the
                    673:  * string isn't found, FALSE is returned.
                    674:  */
                    675: backsrch()
                    676: {
                    677:        register LINE   *clp;
                    678:        register int    cbo;
                    679:        register LINE   *tlp;
                    680:        register int    tbo;
                    681:        register int    c;
                    682:        register uchar  *epp;
                    683:        register uchar  *pp;
                    684: 
                    685:        for (epp = &pat[0]; epp[1] != 0; ++epp)
                    686:                ;
                    687:        clp = curwp->w_dotp;
                    688:        cbo = curwp->w_doto;
                    689:        for (;;) {
                    690:                if (cbo == 0) {
                    691:                        clp = lback(clp);
                    692:                        if (clp == curbp->b_linep)
                    693:                                return (FALSE);
                    694:                        cbo = llength(clp)+1;
                    695:                }
                    696:                if (--(cbo) == llength(clp))
                    697:                        c = '\n';
                    698:                else
                    699:                        c = lgetc(clp,cbo);
                    700:                if (eq(c, *epp) != FALSE) {
                    701:                        tlp = clp;
                    702:                        tbo = cbo;
                    703:                        pp  = epp;
                    704:                        while (pp != &pat[0]) {
                    705:                                if (tbo == 0) {
                    706:                                        tlp = lback(tlp);
                    707:                                        if (tlp == curbp->b_linep)
                    708:                                                goto fail;
                    709:                                        tbo = llength(tlp)+1;
                    710:                                }
                    711:                                if (--(tbo) == llength(tlp))
                    712:                                        c = '\n';
                    713:                                else
                    714:                                        c = lgetc(tlp,tbo);
                    715:                                if (eq(c, *--pp) == FALSE)
                    716:                                        goto fail;
                    717:                        }
                    718:                        curwp->w_dotp  = tlp;
                    719:                        curwp->w_doto  = tbo;
                    720:                        curwp->w_flag |= WFMOVE;
                    721:                        return (TRUE);
                    722:                }
                    723:        fail:   ;
                    724:        }
                    725: }
                    726: 
                    727: /*
                    728:  * Compare two characters.
                    729:  * The "bc" comes from the buffer.
                    730:  * It has it's case folded out. The
                    731:  * "pc" is from the pattern.
                    732:  */
                    733: eq(bc, pc)
                    734: register int   bc;
                    735: register int   pc;
                    736: {
                    737:        int c;
                    738: 
                    739:        if (bind.ffold) {
                    740:                if (c = islow(bc))
                    741:                        bc = c;
                    742:                if (c = islow(pc))
                    743:                        pc = c;
                    744:        }
                    745:        if (bc == pc)
                    746:                return (TRUE);
                    747:        return (FALSE);
                    748: }
                    749: 
                    750: /*
                    751:  * Read a pattern.
                    752:  * Stash it in the external variable "pat". The "pat" is
                    753:  * not updated if the user types in an empty line. If the user typed
                    754:  * an empty line, and there is no old pattern, it is an error.
                    755:  * Display the old pattern, in the style of Jeff Lomicka. There is
                    756:  * some do-it-yourself control expansion.
                    757:  */
                    758: readpattern(prompt)
                    759: uchar  *prompt;
                    760: {
                    761:        register uchar  *cp1;
                    762:        register uchar  *cp2;
                    763:        register unsigned c;
                    764:        register int    s;
                    765:        uchar           tpat[NPAT+20];
                    766: 
                    767:        cp1 = &tpat[0];                         /* Copy prompt          */
                    768:        cp2 = prompt;
                    769:        while ((c = *cp2++) != '\0')
                    770:                *cp1++ = c;
                    771:        if (pat[0] != '\0') {                   /* Old pattern          */
                    772:                *cp1++ = ' ';
                    773:                *cp1++ = '[';
                    774:                cp2 = &pat[0];
                    775:                while ((c = *cp2++) != 0) {
                    776:                        if (cp1 < &tpat[NPAT+20-6]) {   /* "??]: \0"    */
                    777:                                if (dblchr(c)) {
                    778:                                        *cp1++ = '^';
                    779:                                        c ^= 0x40;
                    780:                                } else if (c == '%')    /* Map "%" to   */
                    781:                                        *cp1++ = c;     /* "%%".        */
                    782:                                *cp1++ = c;
                    783:                        }
                    784:                }
                    785:                *cp1++ = ']';
                    786:        }
                    787:        *cp1++ = ':';                           /* Finish prompt        */
                    788:        *cp1++ = ' ';
                    789:        *cp1++ = '\0';
                    790:        s = mlreply(tpat, tpat, NPAT);          /* Read pattern         */
                    791:        if (s == TRUE)                          /* Specified            */
                    792:                strcpy(pat, tpat);
                    793:        else if (s==FALSE && pat[0]!=0)         /* CR, but old one      */
                    794:                s = TRUE;
                    795:        return (s);
                    796: }

unix.superglobalmegacorp.com

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