[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.3

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