|
|
1.1 ! root 1: /************************************************************************* ! 2: * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is * ! 3: * provided to you without charge for use only on a licensed Unix * ! 4: * system. You may copy JOVE provided that this notice is included with * ! 5: * the copy. You may not sell copies of this program or versions * ! 6: * modified for use on microcomputer systems, unless the copies are * ! 7: * included with a Unix system distribution and the source is provided. * ! 8: *************************************************************************/ ! 9: ! 10: #include "jove.h" ! 11: #include "io.h" ! 12: #include "re.h" ! 13: ! 14: static ! 15: substitute(query, l1, char1, l2, char2) ! 16: Line *l1, ! 17: *l2; ! 18: { ! 19: Line *lp; ! 20: int numdone = 0, ! 21: offset = curchar, ! 22: stop = 0; ! 23: disk_line UNDO_da = 0; ! 24: Line *UNDO_lp = 0; ! 25: ! 26: lsave(); ! 27: REdirection = FORWARD; ! 28: ! 29: lp = l1; ! 30: for (lp = l1; (lp != l2->l_next) && !stop; lp = lp->l_next) { ! 31: offset = (lp == l1) ? char1 : 0; ! 32: while (!stop && re_lindex(lp, offset, compbuf, alternates, 0)) { ! 33: if (lp == l2 && REeom > char2) /* nope, leave this alone */ ! 34: break; ! 35: DotTo(lp, REeom); ! 36: offset = curchar; ! 37: if (query) { ! 38: message("Replace (Type '?' for help)? "); ! 39: reswitch: redisplay(); ! 40: switch (Upper(getchar())) { ! 41: case '.': ! 42: stop++; ! 43: /* Fall into ... */ ! 44: ! 45: case ' ': ! 46: case 'Y': ! 47: break; ! 48: ! 49: case BS: ! 50: case RUBOUT: ! 51: case 'N': ! 52: if (linebuf[offset++] == '\0') ! 53: goto nxtline; ! 54: continue; ! 55: ! 56: case CTL(W): ! 57: re_dosub(linebuf, YES); ! 58: numdone++; ! 59: offset = curchar = REbom; ! 60: makedirty(curline); ! 61: /* Fall into ... */ ! 62: ! 63: case CTL(R): ! 64: case 'R': ! 65: RErecur(); ! 66: offset = curchar; ! 67: lp = curline; ! 68: continue; ! 69: ! 70: case CTL(U): ! 71: case 'U': ! 72: if (UNDO_lp == 0) ! 73: continue; ! 74: lp = UNDO_lp; ! 75: lp->l_dline = UNDO_da | DIRTY; ! 76: offset = 0; ! 77: numdone--; ! 78: continue; ! 79: ! 80: case 'P': ! 81: case '!': ! 82: query = 0; ! 83: break; ! 84: ! 85: case CR: ! 86: case LF: ! 87: case 'Q': ! 88: goto done; ! 89: ! 90: case CTL(L): ! 91: RedrawDisplay(); ! 92: goto reswitch; ! 93: ! 94: default: ! 95: rbell(); ! 96: message("Space or Y, Period, Rubout or N, C-R or R, C-W, C-U or U, P or !, Return."); ! 97: goto reswitch; ! 98: } ! 99: } ! 100: re_dosub(linebuf, NO); ! 101: numdone++; ! 102: modify(); ! 103: offset = curchar = REeom; ! 104: makedirty(curline); ! 105: if (query) { ! 106: message(mesgbuf); /* No blinking. */ ! 107: redisplay(); /* Show the change. */ ! 108: } ! 109: UNDO_da = curline->l_dline; ! 110: UNDO_lp = curline; ! 111: if (linebuf[offset] == 0) ! 112: nxtline: break; ! 113: } ! 114: } ! 115: SetMark(); ! 116: done: s_mess("%d substitution%n.", numdone, numdone); ! 117: } ! 118: ! 119: /* Prompt for search and replacement strings and do the substitution. The ! 120: point is restored when we're done. */ ! 121: ! 122: static ! 123: replace(query, inreg) ! 124: { ! 125: Mark *save = MakeMark(curline, curchar, FLOATER), ! 126: *m; ! 127: char *rep_ptr; ! 128: Line *l1 = curline, ! 129: *l2 = curbuf->b_last; ! 130: int char1 = curchar, ! 131: char2 = length(curbuf->b_last); ! 132: ! 133: if (inreg) { ! 134: m = CurMark(); ! 135: l2 = m->m_line; ! 136: char2 = m->m_char; ! 137: (void) fixorder(&l1, &char1, &l2, &char2); ! 138: } ! 139: ! 140: /* Get search string. */ ! 141: strcpy(rep_search, ask(rep_search[0] ? rep_search : (char *) 0, ProcFmt)); ! 142: REcompile(rep_search, UseRE, compbuf, alternates); ! 143: /* Now the replacement string. Do_ask() so the user can play with ! 144: the default (previous) replacement string by typing C-R in ask(), ! 145: OR, he can just hit Return to replace with nothing. */ ! 146: rep_ptr = do_ask("\r\n", (int (*)()) 0, rep_str, ": %f %s with ", rep_search); ! 147: if (rep_ptr == 0) ! 148: rep_ptr = NullStr; ! 149: strcpy(rep_str, rep_ptr); ! 150: ! 151: substitute(query, l1, char1, l2, char2); ! 152: ToMark(save); ! 153: DelMark(save); ! 154: } ! 155: ! 156: RegReplace() ! 157: { ! 158: replace(0, YES); ! 159: } ! 160: ! 161: QRepSearch() ! 162: { ! 163: replace(1, NO); ! 164: } ! 165: ! 166: RepSearch() ! 167: { ! 168: replace(0, NO); ! 169: } ! 170: ! 171: /* C tags package. */ ! 172: ! 173: static ! 174: lookup(searchbuf, filebuf, tag, file) ! 175: char *searchbuf, ! 176: *filebuf, ! 177: *tag, ! 178: *file; ! 179: { ! 180: register int taglen = strlen(tag); ! 181: char line[128], ! 182: pattern[100]; ! 183: File *fp; ! 184: ! 185: fp = open_file(file, iobuff, F_READ, !COMPLAIN, QUIET); ! 186: if (fp == NIL) ! 187: return 0; ! 188: sprintf(pattern, "^%s[^\t]*\t\\([^\t]*\\)\t[?/]\\(.*\\)[?/]$", tag); ! 189: while (f_gets(fp, line, sizeof line) != EOF) { ! 190: if (line[0] != *tag || strncmp(tag, line, taglen) != 0) ! 191: continue; ! 192: if (!LookingAt(pattern, line, 0)) { ! 193: complain("I thought I saw it!"); ! 194: break; ! 195: } else { ! 196: putmatch(2, searchbuf, 100); ! 197: putmatch(1, filebuf, 100); ! 198: close_file(fp); ! 199: return 1; ! 200: } ! 201: } ! 202: f_close(fp); ! 203: s_mess("Can't find tag \"%s\".", tag); ! 204: return 0; ! 205: } ! 206: ! 207: char TagFile[128] = "./tags"; ! 208: ! 209: find_tag(tag, localp) ! 210: char *tag; ! 211: { ! 212: char filebuf[FILESIZE], ! 213: sstr[100]; ! 214: register Bufpos *bp; ! 215: register Buffer *b; ! 216: char *tagfname; ! 217: ! 218: if (!localp) ! 219: tagfname = ask(TagFile, "With tag file (%s default): ", TagFile); ! 220: else ! 221: tagfname = TagFile; ! 222: if (lookup(sstr, filebuf, tag, tagfname) == 0) ! 223: return; ! 224: SetMark(); ! 225: b = do_find(curwind, filebuf, 0); ! 226: if (curbuf != b) ! 227: SetABuf(curbuf); ! 228: SetBuf(b); ! 229: if ((bp = dosearch(sstr, BACKWARD, 0)) == 0 && ! 230: (WrapScan || ((bp = dosearch(sstr, FORWARD, 0)) == 0))) ! 231: message("Well, I found the file, but the tag is missing."); ! 232: else ! 233: SetDot(bp); ! 234: } ! 235: ! 236: FindTag() ! 237: { ! 238: int localp = !exp_p; ! 239: char tag[128]; ! 240: ! 241: strcpy(tag, ask((char *) 0, ProcFmt)); ! 242: find_tag(tag, localp); ! 243: } ! 244: ! 245: /* Find Tag at Dot. */ ! 246: ! 247: FDotTag() ! 248: { ! 249: int c1 = curchar, ! 250: c2 = c1; ! 251: char tagname[50]; ! 252: ! 253: if (!ismword(linebuf[curchar])) ! 254: complain("Not a tag!"); ! 255: while (c1 > 0 && ismword(linebuf[c1 - 1])) ! 256: c1--; ! 257: while (ismword(linebuf[c2])) ! 258: c2++; ! 259: ! 260: null_ncpy(tagname, linebuf + c1, c2 - c1); ! 261: find_tag(tagname, !exp_p); ! 262: } ! 263: ! 264: /* I-search returns a code saying what to do: ! 265: STOP: We found the match, so unwind the stack and leave ! 266: where it is. ! 267: DELETE: Rubout the last command. ! 268: BACKUP: Back up to where the isearch was last NOT failing. ! 269: ! 270: When a character is typed it is appended to the search string, and ! 271: then, isearch is called recursively. When C-S or C-R is typed, isearch ! 272: is again called recursively. */ ! 273: ! 274: #define STOP 1 ! 275: #define DELETE 2 ! 276: #define BACKUP 3 ! 277: #define TOSTART 4 ! 278: ! 279: static char ISbuf[128], ! 280: *incp = 0; ! 281: int SExitChar = CR; ! 282: ! 283: #define cmp_char(a, b) ((a) == (b) || (CaseIgnore && (Upper(a) == Upper(b)))) ! 284: ! 285: static Bufpos * ! 286: doisearch(dir, c, failing) ! 287: register int c, ! 288: dir, ! 289: failing; ! 290: { ! 291: static Bufpos buf; ! 292: Bufpos *bp; ! 293: ! 294: if (c == CTL(S) || c == CTL(R)) ! 295: goto dosrch; ! 296: ! 297: if (failing) ! 298: return 0; ! 299: DOTsave(&buf); ! 300: if (dir == FORWARD) { ! 301: if (cmp_char(linebuf[curchar], c)) { ! 302: buf.p_char = curchar + 1; ! 303: return &buf; ! 304: } ! 305: } else { ! 306: if (look_at(ISbuf)) ! 307: return &buf; ! 308: } ! 309: dosrch: if ((bp = dosearch(ISbuf, dir, 0)) == 0) ! 310: rbell(); /* ring the first time there's no match */ ! 311: return bp; ! 312: } ! 313: ! 314: IncFSearch() ! 315: { ! 316: IncSearch(FORWARD); ! 317: } ! 318: ! 319: IncRSearch() ! 320: { ! 321: IncSearch(BACKWARD); ! 322: } ! 323: ! 324: static ! 325: IncSearch(dir) ! 326: { ! 327: Bufpos save_env; ! 328: ! 329: DOTsave(&save_env); ! 330: ISbuf[0] = 0; ! 331: incp = ISbuf; ! 332: if (isearch(dir, &save_env) == TOSTART) ! 333: SetDot(&save_env); ! 334: else { ! 335: if (LineDist(curline, save_env.p_line) >= MarkThresh) ! 336: DoSetMark(save_env.p_line, save_env.p_char); ! 337: } ! 338: setsearch(ISbuf); ! 339: message(ISbuf); ! 340: } ! 341: ! 342: /* Nicely recursive. */ ! 343: ! 344: static ! 345: isearch(dir, bp) ! 346: Bufpos *bp; ! 347: { ! 348: Bufpos pushbp; ! 349: int c, ! 350: ndir, ! 351: failing; ! 352: char *orig_incp; ! 353: ! 354: if (bp != 0) { /* Move to the new position. */ ! 355: pushbp.p_line = bp->p_line; ! 356: pushbp.p_char = bp->p_char; ! 357: SetDot(bp); ! 358: failing = 0; ! 359: } else { ! 360: DOTsave(&pushbp); ! 361: failing = 1; ! 362: } ! 363: orig_incp = incp; ! 364: ndir = dir; /* Same direction as when we got here, unless ! 365: we change it with C-S or C-R. */ ! 366: for (;;) { ! 367: SetDot(&pushbp); ! 368: message(NullStr); ! 369: if (failing) ! 370: add_mess("Failing "); ! 371: if (dir == BACKWARD) ! 372: add_mess("reverse-"); ! 373: add_mess("I-search: %s", ISbuf); ! 374: DrawMesg(NO); ! 375: add_mess(NullStr); /* tell me this is disgusting ... */ ! 376: c = getch(); ! 377: if (c == SExitChar) ! 378: return STOP; ! 379: switch (c) { ! 380: case RUBOUT: ! 381: case BS: ! 382: return DELETE; ! 383: ! 384: case CTL(G): ! 385: /* If we're failing, we backup until we're no longer ! 386: failing or we've reached the beginning; else, we ! 387: just about the search and go back to the start. */ ! 388: if (failing) ! 389: return BACKUP; ! 390: return TOSTART; ! 391: ! 392: case CTL(\\): ! 393: c = CTL(S); ! 394: case CTL(S): ! 395: case CTL(R): ! 396: /* If this is the first time through and we have a ! 397: search string left over from last time, use that ! 398: one now. */ ! 399: if (incp == ISbuf) { ! 400: strcpy(ISbuf, getsearch()); ! 401: incp = &ISbuf[strlen(ISbuf)]; ! 402: } ! 403: ndir = (c == CTL(S)) ? FORWARD : BACKWARD; ! 404: /* If we're failing and we're not changing our ! 405: direction, don't recur since there's no way ! 406: the search can work. */ ! 407: if (failing && ndir == dir) { ! 408: rbell(); ! 409: continue; ! 410: } ! 411: break; ! 412: ! 413: case '\\': ! 414: if (incp > &ISbuf[(sizeof ISbuf) - 1]) { ! 415: rbell(); ! 416: continue; ! 417: } ! 418: *incp++ = '\\'; ! 419: add_mess("\\"); ! 420: /* Fall into ... */ ! 421: ! 422: case CTL(Q): ! 423: case CTL(^): ! 424: add_mess(""); ! 425: c = getch() | 0400; ! 426: /* Fall into ... */ ! 427: ! 428: default: ! 429: if (c & 0400) ! 430: c &= 0177; ! 431: else { ! 432: if (c > RUBOUT || (c < ' ' && c != '\t')) { ! 433: Ungetc(c); ! 434: return STOP; ! 435: } ! 436: } ! 437: if (incp > &ISbuf[(sizeof ISbuf) - 1]) { ! 438: rbell(); ! 439: continue; ! 440: } ! 441: *incp++ = c; ! 442: *incp = 0; ! 443: break; ! 444: } ! 445: add_mess("%s", orig_incp); ! 446: add_mess(" ..."); /* so we know what's going on */ ! 447: DrawMesg(NO); /* do it now */ ! 448: switch (isearch(ndir, doisearch(ndir, c, failing))) { ! 449: case TOSTART: ! 450: return TOSTART; ! 451: ! 452: case STOP: ! 453: return STOP; ! 454: ! 455: case BACKUP: ! 456: /* If we're not failing, we just continue to to the ! 457: for loop; otherwise we keep returning to the ! 458: previous levels until we find one that isn't ! 459: failing OR we reach the beginning. */ ! 460: if (failing) ! 461: return BACKUP; ! 462: /* Fall into ... */ ! 463: ! 464: case DELETE: ! 465: incp = orig_incp; ! 466: *incp = 0; ! 467: continue; ! 468: } ! 469: } ! 470: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.