[BACK]Return to search.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/search.c, Revision 1.6

1.6     ! art         1: /*     $OpenBSD: search.c,v 1.5 2001/05/03 20:43:12 art Exp $  */
1.4       niklas      2:
1.1       deraadt     3: /*
                      4:  *             Search commands.
1.3       millert     5:  * The functions in this file implement the search commands (both plain and
                      6:  * incremental searches are supported) and the query-replace command.
1.1       deraadt     7:  *
1.3       millert     8:  * The plain old search code is part of the original MicroEMACS "distribution".
                      9:  * The incremental search code and the query-replace code is by Rich Ellison.
1.1       deraadt    10:  */
1.3       millert    11:
                     12: #include "def.h"
                     13:
1.1       deraadt    14: #ifndef NO_MACRO
1.3       millert    15: #include "macro.h"
                     16: #endif /* !NO_MACRO */
1.1       deraadt    17:
1.2       millert    18: #define SRCH_BEGIN     (0)     /* Search sub-codes.     */
1.1       deraadt    19: #define SRCH_FORW      (-1)
                     20: #define SRCH_BACK      (-2)
                     21: #define SRCH_NOPR      (-3)
                     22: #define SRCH_ACCM      (-4)
                     23: #define SRCH_MARK      (-5)
                     24:
1.2       millert    25: typedef struct {
1.3       millert    26:        int      s_code;
                     27:        LINE    *s_dotp;
                     28:        int      s_doto;
                     29: } SRCHCOM;
                     30:
                     31: static int     isearch         __P((int));
1.6     ! art        32: static void    is_cpush        __P((int));
        !            33: static void    is_lpush        __P((void));
        !            34: static void    is_pop          __P((void));
1.3       millert    35: static int     is_peek         __P((void));
1.6     ! art        36: static void    is_undo         __P((int *, int *));
1.3       millert    37: static int     is_find         __P((int));
1.6     ! art        38: static void    is_prompt       __P((int, int, int));
        !            39: static void    is_dspl         __P((char *, int));
1.3       millert    40: static int     eq              __P((int, int));
                     41:
                     42: static SRCHCOM cmds[NSRCH];
                     43: static int     cip;
                     44:
                     45: int            srch_lastdir = SRCH_NOPR;       /* Last search flags.    */
                     46:
                     47: /*
                     48:  * Search forward.  Get a search string from the user, and search for it
                     49:  * starting at ".".  If found, "." gets moved to just after the matched
                     50:  * characters, and display does all the hard stuff.  If not found, it just
                     51:  * prints a message.
1.1       deraadt    52:  */
1.2       millert    53: /* ARGSUSED */
1.3       millert    54: int
1.1       deraadt    55: forwsearch(f, n)
1.3       millert    56:        int f, n;
1.1       deraadt    57: {
1.3       millert    58:        int     s;
1.1       deraadt    59:
1.2       millert    60:        if ((s = readpattern("Search")) != TRUE)
1.1       deraadt    61:                return s;
                     62:        if (forwsrch() == FALSE) {
                     63:                ewprintf("Search failed: \"%s\"", pat);
                     64:                return FALSE;
                     65:        }
                     66:        srch_lastdir = SRCH_FORW;
                     67:        return TRUE;
                     68: }
                     69:
                     70: /*
1.3       millert    71:  * Reverse search.  Get a search string from the user, and search, starting
                     72:  * at "." and proceeding toward the front of the buffer.  If found "." is
                     73:  * left pointing at the first character of the pattern [the last character
                     74:  * that was matched].
1.1       deraadt    75:  */
1.2       millert    76: /* ARGSUSED */
1.3       millert    77: int
1.1       deraadt    78: backsearch(f, n)
1.3       millert    79:        int f, n;
1.1       deraadt    80: {
1.3       millert    81:        int     s;
1.1       deraadt    82:
1.2       millert    83:        if ((s = readpattern("Search backward")) != TRUE)
1.1       deraadt    84:                return (s);
                     85:        if (backsrch() == FALSE) {
                     86:                ewprintf("Search failed: \"%s\"", pat);
                     87:                return FALSE;
                     88:        }
                     89:        srch_lastdir = SRCH_BACK;
                     90:        return TRUE;
                     91: }
                     92:
                     93: /*
1.3       millert    94:  * Search again, using the same search string and direction as the last
                     95:  * search command. The direction has been saved in "srch_lastdir", so you
                     96:  * know which way to go.
1.1       deraadt    97:  */
1.2       millert    98: /* ARGSUSED */
1.3       millert    99: int
1.1       deraadt   100: searchagain(f, n)
1.3       millert   101:        int f, n;
1.1       deraadt   102: {
                    103:        if (srch_lastdir == SRCH_FORW) {
                    104:                if (forwsrch() == FALSE) {
                    105:                        ewprintf("Search failed: \"%s\"", pat);
                    106:                        return FALSE;
                    107:                }
                    108:                return TRUE;
                    109:        }
                    110:        if (srch_lastdir == SRCH_BACK) {
                    111:                if (backsrch() == FALSE) {
                    112:                        ewprintf("Search failed: \"%s\"", pat);
                    113:                        return FALSE;
                    114:                }
                    115:                return TRUE;
                    116:        }
                    117:        ewprintf("No last search");
                    118:        return FALSE;
                    119: }
                    120:
                    121: /*
1.3       millert   122:  * Use incremental searching, initially in the forward direction.
1.1       deraadt   123:  * isearch ignores any explicit arguments.
                    124:  */
1.2       millert   125: /* ARGSUSED */
1.3       millert   126: int
1.1       deraadt   127: forwisearch(f, n)
1.3       millert   128:        int f, n;
1.1       deraadt   129: {
                    130:        return isearch(SRCH_FORW);
                    131: }
                    132:
                    133: /*
                    134:  * Use incremental searching, initially in the reverse direction.
                    135:  * isearch ignores any explicit arguments.
                    136:  */
1.2       millert   137: /* ARGSUSED */
1.3       millert   138: int
1.1       deraadt   139: backisearch(f, n)
1.3       millert   140:        int f, n;
1.1       deraadt   141: {
                    142:        return isearch(SRCH_BACK);
                    143: }
                    144:
                    145: /*
                    146:  * Incremental Search.
                    147:  *     dir is used as the initial direction to search.
                    148:  *     ^S      switch direction to forward
                    149:  *     ^R      switch direction to reverse
                    150:  *     ^Q      quote next character (allows searching for ^N etc.)
                    151:  *     <ESC>   exit from Isearch
                    152:  *     <DEL>   undoes last character typed. (tricky job to do this correctly).
                    153:  *     other ^ exit search, don't set mark
                    154:  *     else    accumulate into search string
                    155:  */
1.3       millert   156: static int
1.2       millert   157: isearch(dir)
1.3       millert   158:        int dir;
1.2       millert   159: {
1.3       millert   160:        LINE    *clp;
                    161:
                    162:        int      c;
                    163:        int      cbo;
                    164:        int      success;
                    165:        int      pptr;
                    166:
                    167:        char     opat[NPAT];
1.1       deraadt   168:
                    169: #ifndef NO_MACRO
1.2       millert   170:        if (macrodef) {
                    171:                ewprintf("Can't isearch in macro");
                    172:                return FALSE;
1.1       deraadt   173:        }
1.3       millert   174: #endif /* !NO_MACRO */
1.2       millert   175:        for (cip = 0; cip < NSRCH; cip++)
1.1       deraadt   176:                cmds[cip].s_code = SRCH_NOPR;
1.3       millert   177:
1.6     ! art       178:        (void)strcpy(opat, pat);
1.1       deraadt   179:        cip = 0;
                    180:        pptr = -1;
                    181:        clp = curwp->w_dotp;
                    182:        cbo = curwp->w_doto;
                    183:        is_lpush();
                    184:        is_cpush(SRCH_BEGIN);
                    185:        success = TRUE;
                    186:        is_prompt(dir, TRUE, success);
1.3       millert   187:
1.1       deraadt   188:        for (;;) {
                    189:                update();
1.3       millert   190:
1.1       deraadt   191:                switch (c = getkey(FALSE)) {
                    192:                case CCHR('['):
1.5       art       193:                        /*
                    194:                         * If new characters come in the next 300 msec,
                    195:                         * we can assume that they belong to a longer
                    196:                         * escaped sequence so we should ungetkey the
                    197:                         * ESC to avoid writing out garbage.
                    198:                         */
                    199:                        if (ttwait(300) == FALSE)
                    200:                                ungetkey(c);
1.1       deraadt   201:                        srch_lastdir = dir;
                    202:                        curwp->w_markp = clp;
                    203:                        curwp->w_marko = cbo;
                    204:                        ewprintf("Mark set");
                    205:                        return (TRUE);
                    206:                case CCHR('G'):
                    207:                        if (success != TRUE) {
                    208:                                while (is_peek() == SRCH_ACCM)
                    209:                                        is_undo(&pptr, &dir);
                    210:                                success = TRUE;
                    211:                                is_prompt(dir, pptr < 0, success);
                    212:                                break;
                    213:                        }
                    214:                        curwp->w_dotp = clp;
                    215:                        curwp->w_doto = cbo;
                    216:                        curwp->w_flag |= WFMOVE;
                    217:                        srch_lastdir = dir;
1.6     ! art       218:                        (void)ctrlg(FFRAND, 0);
        !           219:                        (void)strcpy(pat, opat);
1.1       deraadt   220:                        return ABORT;
                    221:                case CCHR(']'):
                    222:                case CCHR('S'):
                    223:                        if (dir == SRCH_BACK) {
                    224:                                dir = SRCH_FORW;
                    225:                                is_lpush();
                    226:                                is_cpush(SRCH_FORW);
                    227:                                success = TRUE;
                    228:                        }
1.2       millert   229:                        if (success == FALSE && dir == SRCH_FORW)
1.1       deraadt   230:                                break;
                    231:                        is_lpush();
                    232:                        pptr = strlen(pat);
1.6     ! art       233:                        (void)forwchar(FFRAND, 1);
1.2       millert   234:                        if (is_find(SRCH_FORW) != FALSE)
                    235:                                is_cpush(SRCH_MARK);
1.1       deraadt   236:                        else {
1.6     ! art       237:                                (void)backchar(FFRAND, 1);
1.1       deraadt   238:                                ttbeep();
                    239:                                success = FALSE;
                    240:                        }
                    241:                        is_prompt(dir, pptr < 0, success);
                    242:                        break;
                    243:                case CCHR('R'):
                    244:                        if (dir == SRCH_FORW) {
                    245:                                dir = SRCH_BACK;
                    246:                                is_lpush();
                    247:                                is_cpush(SRCH_BACK);
                    248:                                success = TRUE;
                    249:                        }
1.2       millert   250:                        if (success == FALSE && dir == SRCH_BACK)
1.1       deraadt   251:                                break;
                    252:                        is_lpush();
                    253:                        pptr = strlen(pat);
1.6     ! art       254:                        (void)backchar(FFRAND, 1);
1.2       millert   255:                        if (is_find(SRCH_BACK) != FALSE)
                    256:                                is_cpush(SRCH_MARK);
1.1       deraadt   257:                        else {
1.6     ! art       258:                                (void)forwchar(FFRAND, 1);
1.1       deraadt   259:                                ttbeep();
                    260:                                success = FALSE;
                    261:                        }
                    262:                        is_prompt(dir, pptr < 0, success);
                    263:                        break;
                    264:                case CCHR('H'):
                    265:                case CCHR('?'):
                    266:                        is_undo(&pptr, &dir);
1.2       millert   267:                        if (is_peek() != SRCH_ACCM)
                    268:                                success = TRUE;
1.1       deraadt   269:                        is_prompt(dir, pptr < 0, success);
                    270:                        break;
                    271:                case CCHR('\\'):
                    272:                case CCHR('Q'):
1.3       millert   273:                        c = (char)getkey(FALSE);
1.2       millert   274:                        goto addchar;
1.1       deraadt   275:                case CCHR('M'):
                    276:                        c = CCHR('J');
1.2       millert   277:                        goto addchar;
1.1       deraadt   278:                default:
                    279:                        if (ISCTRL(c)) {
                    280:                                ungetkey(c);
                    281:                                curwp->w_markp = clp;
                    282:                                curwp->w_marko = cbo;
                    283:                                ewprintf("Mark set");
                    284:                                curwp->w_flag |= WFMOVE;
1.2       millert   285:                                return TRUE;
1.1       deraadt   286:                        }       /* and continue */
                    287:                case CCHR('I'):
                    288:                case CCHR('J'):
1.2       millert   289:        addchar:
1.1       deraadt   290:                        if (pptr == -1)
                    291:                                pptr = 0;
                    292:                        if (pptr == 0)
                    293:                                success = TRUE;
                    294:                        pat[pptr++] = c;
                    295:                        if (pptr == NPAT) {
                    296:                                ewprintf("Pattern too long");
                    297:                                return FALSE;
                    298:                        }
                    299:                        pat[pptr] = '\0';
                    300:                        is_lpush();
                    301:                        if (success != FALSE) {
                    302:                                if (is_find(dir) != FALSE)
                    303:                                        is_cpush(c);
                    304:                                else {
                    305:                                        success = FALSE;
                    306:                                        ttbeep();
                    307:                                        is_cpush(SRCH_ACCM);
                    308:                                }
                    309:                        } else
                    310:                                is_cpush(SRCH_ACCM);
                    311:                        is_prompt(dir, FALSE, success);
                    312:                }
                    313:        }
1.2       millert   314:        /* NOTREACHED */
1.1       deraadt   315: }
                    316:
1.6     ! art       317: static void
1.2       millert   318: is_cpush(cmd)
1.3       millert   319:        int cmd;
1.2       millert   320: {
1.1       deraadt   321:        if (++cip >= NSRCH)
                    322:                cip = 0;
                    323:        cmds[cip].s_code = cmd;
                    324: }
                    325:
1.6     ! art       326: static void
1.2       millert   327: is_lpush()
                    328: {
1.3       millert   329:        int     ctp;
1.1       deraadt   330:
1.2       millert   331:        ctp = cip + 1;
1.1       deraadt   332:        if (ctp >= NSRCH)
                    333:                ctp = 0;
                    334:        cmds[ctp].s_code = SRCH_NOPR;
                    335:        cmds[ctp].s_doto = curwp->w_doto;
                    336:        cmds[ctp].s_dotp = curwp->w_dotp;
                    337: }
                    338:
1.6     ! art       339: static void
1.2       millert   340: is_pop()
                    341: {
1.1       deraadt   342:        if (cmds[cip].s_code != SRCH_NOPR) {
1.2       millert   343:                curwp->w_doto = cmds[cip].s_doto;
                    344:                curwp->w_dotp = cmds[cip].s_dotp;
1.1       deraadt   345:                curwp->w_flag |= WFMOVE;
                    346:                cmds[cip].s_code = SRCH_NOPR;
                    347:        }
                    348:        if (--cip <= 0)
1.2       millert   349:                cip = NSRCH - 1;
1.1       deraadt   350: }
                    351:
                    352: static int
1.2       millert   353: is_peek()
                    354: {
1.1       deraadt   355:        return cmds[cip].s_code;
                    356: }
                    357:
                    358: /* this used to always return TRUE (the return value was checked) */
1.6     ! art       359: static void
1.2       millert   360: is_undo(pptr, dir)
1.3       millert   361:        int *pptr, *dir;
1.2       millert   362: {
1.3       millert   363:        int     redo = FALSE;
                    364:
1.1       deraadt   365:        switch (cmds[cip].s_code) {
                    366:        case SRCH_BEGIN:
                    367:        case SRCH_NOPR:
                    368:                *pptr = -1;
                    369:        case SRCH_MARK:
                    370:                break;
                    371:        case SRCH_FORW:
                    372:                *dir = SRCH_BACK;
                    373:                redo = TRUE;
                    374:                break;
                    375:        case SRCH_BACK:
                    376:                *dir = SRCH_FORW;
                    377:                redo = TRUE;
                    378:                break;
                    379:        case SRCH_ACCM:
                    380:        default:
                    381:                *pptr -= 1;
                    382:                if (*pptr < 0)
                    383:                        *pptr = 0;
                    384:                pat[*pptr] = '\0';
                    385:                break;
                    386:        }
                    387:        is_pop();
1.2       millert   388:        if (redo)
                    389:                is_undo(pptr, dir);
1.1       deraadt   390: }
                    391:
                    392: static int
1.2       millert   393: is_find(dir)
1.3       millert   394:        int     dir;
1.2       millert   395: {
1.3       millert   396:        int      plen, odoto;
                    397:        LINE    *odotp;
1.1       deraadt   398:
                    399:        odoto = curwp->w_doto;
                    400:        odotp = curwp->w_dotp;
                    401:        plen = strlen(pat);
                    402:        if (plen != 0) {
1.2       millert   403:                if (dir == SRCH_FORW) {
1.6     ! art       404:                        (void)backchar(FFARG | FFRAND, plen);
1.1       deraadt   405:                        if (forwsrch() == FALSE) {
                    406:                                curwp->w_doto = odoto;
                    407:                                curwp->w_dotp = odotp;
                    408:                                return FALSE;
                    409:                        }
                    410:                        return TRUE;
                    411:                }
1.2       millert   412:                if (dir == SRCH_BACK) {
1.6     ! art       413:                        (void)forwchar(FFARG | FFRAND, plen);
1.1       deraadt   414:                        if (backsrch() == FALSE) {
                    415:                                curwp->w_doto = odoto;
                    416:                                curwp->w_dotp = odotp;
                    417:                                return FALSE;
                    418:                        }
                    419:                        return TRUE;
                    420:                }
                    421:                ewprintf("bad call to is_find");
                    422:                return FALSE;
                    423:        }
                    424:        return FALSE;
                    425: }
                    426:
                    427: /*
1.3       millert   428:  * If called with "dir" not one of SRCH_FORW or SRCH_BACK, this routine used
                    429:  * to print an error message.  It also used to return TRUE or FALSE, depending
                    430:  * on if it liked the "dir".  However, none of the callers looked at the
                    431:  * status, so I just made the checking vanish.
1.1       deraadt   432:  */
1.6     ! art       433: static void
1.2       millert   434: is_prompt(dir, flag, success)
1.3       millert   435:        int dir, flag, success;
1.2       millert   436: {
1.1       deraadt   437:        if (dir == SRCH_FORW) {
                    438:                if (success != FALSE)
                    439:                        is_dspl("I-search", flag);
                    440:                else
                    441:                        is_dspl("Failing I-search", flag);
                    442:        } else if (dir == SRCH_BACK) {
                    443:                if (success != FALSE)
                    444:                        is_dspl("I-search backward", flag);
                    445:                else
                    446:                        is_dspl("Failing I-search backward", flag);
1.2       millert   447:        } else
                    448:                ewprintf("Broken call to is_prompt");
1.1       deraadt   449: }
                    450:
                    451: /*
1.3       millert   452:  * Prompt writing routine for the incremental search.  The "prompt" is just
                    453:  * a string. The "flag" determines whether pat should be printed.
1.1       deraadt   454:  */
1.6     ! art       455: static void
1.2       millert   456: is_dspl(prompt, flag)
1.3       millert   457:        char *prompt;
                    458:        int flag;
1.2       millert   459: {
1.1       deraadt   460:        if (flag != FALSE)
                    461:                ewprintf("%s: ", prompt);
                    462:        else
                    463:                ewprintf("%s: %s", prompt, pat);
                    464: }
                    465:
                    466: /*
                    467:  * Query Replace.
                    468:  *     Replace strings selectively.  Does a search and replace operation.
                    469:  */
1.2       millert   470: /* ARGSUSED */
1.3       millert   471: int
1.1       deraadt   472: queryrepl(f, n)
1.3       millert   473:        int f, n;
1.1       deraadt   474: {
1.3       millert   475:        int     s;
                    476:        int     rcnt = 0;               /* replacements made so far     */
                    477:        int     plen;                   /* length of found string       */
                    478:        char    news[NPAT];             /* replacement string           */
1.1       deraadt   479:
                    480: #ifndef NO_MACRO
1.2       millert   481:        if (macrodef) {
                    482:                ewprintf("Can't query replace in macro");
                    483:                return FALSE;
1.1       deraadt   484:        }
1.3       millert   485: #endif /* !NO_MACRO */
                    486:
1.2       millert   487:        if ((s = readpattern("Query replace")) != TRUE)
1.1       deraadt   488:                return (s);
1.2       millert   489:        if ((s = ereply("Query replace %s with: ", news, NPAT, pat)) == ABORT)
1.1       deraadt   490:                return (s);
                    491:        if (s == FALSE)
                    492:                news[0] = '\0';
                    493:        ewprintf("Query replacing %s with %s:", pat, news);
                    494:        plen = strlen(pat);
                    495:
                    496:        /*
                    497:         * Search forward repeatedly, checking each time whether to insert
                    498:         * or not.  The "!" case makes the check always true, so it gets put
                    499:         * into a tighter loop for efficiency.
                    500:         */
                    501:        while (forwsrch() == TRUE) {
1.2       millert   502: retry:
1.1       deraadt   503:                update();
                    504:                switch (getkey(FALSE)) {
                    505:                case ' ':
1.3       millert   506:                        if (lreplace((RSIZE)plen, news, f) == FALSE)
1.1       deraadt   507:                                return (FALSE);
                    508:                        rcnt++;
                    509:                        break;
                    510:                case '.':
1.3       millert   511:                        if (lreplace((RSIZE)plen, news, f) == FALSE)
1.1       deraadt   512:                                return (FALSE);
                    513:                        rcnt++;
                    514:                        goto stopsearch;
1.3       millert   515:                /* ^G or ESC */
                    516:                case CCHR('G'):
1.6     ! art       517:                        (void)ctrlg(FFRAND, 0);
1.1       deraadt   518:                case CCHR('['):
                    519:                        goto stopsearch;
                    520:                case '!':
                    521:                        do {
1.3       millert   522:                                if (lreplace((RSIZE)plen, news, f) == FALSE)
1.1       deraadt   523:                                        return (FALSE);
                    524:                                rcnt++;
                    525:                        } while (forwsrch() == TRUE);
                    526:                        goto stopsearch;
                    527:                case CCHR('H'):
1.3       millert   528:                /* To not replace */
                    529:                case CCHR('?'):
1.1       deraadt   530:                        break;
                    531:                default:
1.2       millert   532:                        ewprintf("<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit");
1.1       deraadt   533:                        goto retry;
                    534:                }
                    535:        }
                    536: stopsearch:
                    537:        curwp->w_flag |= WFHARD;
                    538:        update();
                    539:        if (rcnt == 0)
                    540:                ewprintf("(No replacements done)");
                    541:        else if (rcnt == 1)
                    542:                ewprintf("(1 replacement done)");
                    543:        else
                    544:                ewprintf("(%d replacements done)", rcnt);
                    545:        return TRUE;
                    546: }
                    547:
                    548: /*
1.3       millert   549:  * This routine does the real work of a forward search.  The pattern is sitting
                    550:  * in the external variable "pat".  If found, dot is updated, the window system
                    551:  * is notified of the change, and TRUE is returned.  If the string isn't found,
                    552:  * FALSE is returned.
1.1       deraadt   553:  */
1.3       millert   554: int
1.2       millert   555: forwsrch()
                    556: {
1.3       millert   557:        LINE    *clp, *tlp;
                    558:        int      cbo, tbo, c;
                    559:        char    *pp;
1.1       deraadt   560:
                    561:        clp = curwp->w_dotp;
                    562:        cbo = curwp->w_doto;
1.2       millert   563:        for (;;) {
1.1       deraadt   564:                if (cbo == llength(clp)) {
1.2       millert   565:                        if ((clp = lforw(clp)) == curbp->b_linep)
                    566:                                break;
1.1       deraadt   567:                        cbo = 0;
                    568:                        c = CCHR('J');
                    569:                } else
                    570:                        c = lgetc(clp, cbo++);
                    571:                if (eq(c, pat[0]) != FALSE) {
                    572:                        tlp = clp;
                    573:                        tbo = cbo;
1.2       millert   574:                        pp = &pat[1];
1.1       deraadt   575:                        while (*pp != 0) {
                    576:                                if (tbo == llength(tlp)) {
                    577:                                        tlp = lforw(tlp);
                    578:                                        if (tlp == curbp->b_linep)
                    579:                                                goto fail;
                    580:                                        tbo = 0;
                    581:                                        c = CCHR('J');
                    582:                                } else
                    583:                                        c = lgetc(tlp, tbo++);
                    584:                                if (eq(c, *pp++) == FALSE)
                    585:                                        goto fail;
                    586:                        }
1.2       millert   587:                        curwp->w_dotp = tlp;
                    588:                        curwp->w_doto = tbo;
1.1       deraadt   589:                        curwp->w_flag |= WFMOVE;
                    590:                        return TRUE;
                    591:                }
1.2       millert   592: fail:          ;
1.1       deraadt   593:        }
                    594:        return FALSE;
                    595: }
                    596:
                    597: /*
1.3       millert   598:  * This routine does the real work of a backward search.  The pattern is
                    599:  * sitting in the external variable "pat".  If found, dot is updated, the
                    600:  * window system is notified of the change, and TRUE is returned.  If the
1.1       deraadt   601:  * string isn't found, FALSE is returned.
                    602:  */
1.3       millert   603: int
1.2       millert   604: backsrch()
                    605: {
1.3       millert   606:        LINE    *clp, *tlp;
                    607:        int      cbo, tbo, c;
                    608:        char    *epp, *pp;
1.1       deraadt   609:
1.2       millert   610:        for (epp = &pat[0]; epp[1] != 0; ++epp);
1.1       deraadt   611:        clp = curwp->w_dotp;
                    612:        cbo = curwp->w_doto;
                    613:        for (;;) {
                    614:                if (cbo == 0) {
                    615:                        clp = lback(clp);
                    616:                        if (clp == curbp->b_linep)
                    617:                                return FALSE;
1.2       millert   618:                        cbo = llength(clp) + 1;
1.1       deraadt   619:                }
                    620:                if (--cbo == llength(clp))
                    621:                        c = CCHR('J');
                    622:                else
1.2       millert   623:                        c = lgetc(clp, cbo);
1.1       deraadt   624:                if (eq(c, *epp) != FALSE) {
                    625:                        tlp = clp;
                    626:                        tbo = cbo;
1.2       millert   627:                        pp = epp;
1.1       deraadt   628:                        while (pp != &pat[0]) {
                    629:                                if (tbo == 0) {
                    630:                                        tlp = lback(tlp);
                    631:                                        if (tlp == curbp->b_linep)
                    632:                                                goto fail;
1.2       millert   633:                                        tbo = llength(tlp) + 1;
1.1       deraadt   634:                                }
                    635:                                if (--tbo == llength(tlp))
                    636:                                        c = CCHR('J');
                    637:                                else
1.2       millert   638:                                        c = lgetc(tlp, tbo);
1.1       deraadt   639:                                if (eq(c, *--pp) == FALSE)
                    640:                                        goto fail;
                    641:                        }
1.2       millert   642:                        curwp->w_dotp = tlp;
                    643:                        curwp->w_doto = tbo;
1.1       deraadt   644:                        curwp->w_flag |= WFMOVE;
                    645:                        return TRUE;
                    646:                }
1.2       millert   647: fail:          ;
1.1       deraadt   648:        }
1.2       millert   649:        /* NOTREACHED */
1.1       deraadt   650: }
                    651:
                    652: /*
1.3       millert   653:  * Compare two characters.  The "bc" comes from the buffer.  It has its case
                    654:  * folded out. The "pc" is from the pattern.
1.1       deraadt   655:  */
                    656: static int
                    657: eq(bc, pc)
1.3       millert   658:        int bc, pc;
1.1       deraadt   659: {
                    660:        bc = CHARMASK(bc);
                    661:        pc = CHARMASK(pc);
1.2       millert   662:        if (bc == pc)
                    663:                return TRUE;
                    664:        if (ISUPPER(bc))
                    665:                return TOLOWER(bc) == pc;
                    666:        if (ISUPPER(pc))
                    667:                return bc == TOLOWER(pc);
1.1       deraadt   668:        return FALSE;
                    669: }
                    670:
                    671: /*
1.3       millert   672:  * Read a pattern.  Stash it in the external variable "pat".  The "pat" is not
                    673:  * updated if the user types in an empty line.  If the user typed an empty
                    674:  * line, and there is no old pattern, it is an error.  Display the old pattern,
                    675:  * in the style of Jeff Lomicka.  There is some do-it-yourself control
                    676:  * expansion.
1.1       deraadt   677:  */
1.3       millert   678: int
1.2       millert   679: readpattern(prompt)
1.3       millert   680:        char *prompt;
1.2       millert   681: {
1.3       millert   682:        int     s;
                    683:        char    tpat[NPAT];
1.1       deraadt   684:
1.2       millert   685:        if (tpat[0] == '\0')
                    686:                s = ereply("%s: ", tpat, NPAT, prompt);
                    687:        else
                    688:                s = ereply("%s: (default %s) ", tpat, NPAT, prompt, pat);
1.1       deraadt   689:
1.3       millert   690:        /* specified */
                    691:        if (s == TRUE)
1.6     ! art       692:                (void) strcpy(pat, tpat);
1.3       millert   693:        /* CR, but old one */
                    694:        else if (s == FALSE && pat[0] != 0)
1.1       deraadt   695:                s = TRUE;
                    696:        return s;
                    697: }