|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.