📄 prim.c
字号:
/* * Jump to a specified position in the file. */jump_loc(pos) off_t pos;{ register int nline; off_t tpos; if ((nline = onscreen(pos)) >= 0) { /* * The line is currently displayed. * Just scroll there. */ forw(nline, position(BOTTOM_PLUS_ONE), 0); return; } /* * Line is not on screen. * Seek to the desired location. */ if (ch_seek(pos)) { error("Cannot seek to that position"); return; } /* * See if the desired line is BEFORE the currently displayed screen. * If so, then move forward far enough so the line we're on will be * at the bottom of the screen, in order to be able to call back() * to make the screen scroll backwards & put the line at the top of * the screen. * {{ This seems inefficient, but it's not so bad, * since we can never move forward more than a * screenful before we stop to redraw the screen. }} */ tpos = position(TOP); if (tpos != NULL_POSITION && pos < tpos) { off_t npos = pos; /* * Note that we can't forw_line() past tpos here, * so there should be no EOI at this stage. */ for (nline = 0; npos < tpos && nline < sc_height - 1; nline++) npos = forw_line(npos); if (npos < tpos) { /* * More than a screenful back. */ lastmark(); clear(); pos_clear(); add_back_pos(npos); } /* * Note that back() will repaint() if nline > back_scroll. */ back(nline, npos, 0); return; } /* * Remember where we were; clear and paint the screen. */ lastmark(); prepaint(pos);}/* * The table of marks. * A mark is simply a position in the file. */#define NMARKS (27) /* 26 for a-z plus one for quote */#define LASTMARK (NMARKS-1) /* For quote */static off_t marks[NMARKS];/* * Initialize the mark table to show no marks are set. */init_mark(){ int i; for (i = 0; i < NMARKS; i++) marks[i] = NULL_POSITION;}/* * See if a mark letter is valid (between a and z). */ static intbadmark(c) int c;{ if (c < 'a' || c > 'z') { error("Choose a letter between 'a' and 'z'"); return (1); } return (0);}/* * Set a mark. */setmark(c) int c;{ if (badmark(c)) return; marks[c-'a'] = position(TOP);}lastmark(){ marks[LASTMARK] = position(TOP);}/* * Go to a previously set mark. */gomark(c) int c;{ off_t pos; if (c == '\'') { pos = marks[LASTMARK]; if (pos == NULL_POSITION) pos = 0; } else { if (badmark(c)) return; pos = marks[c-'a']; if (pos == NULL_POSITION) { error("mark not set"); return; } } jump_loc(pos);}/* * Get the backwards scroll limit. * Must call this function instead of just using the value of * back_scroll, because the default case depends on sc_height and * top_scroll, as well as back_scroll. */get_back_scroll(){ if (back_scroll >= 0) return (back_scroll); if (top_scroll) return (sc_height - 2); return (sc_height - 1);}/* * Search for the n-th occurence of a specified pattern, * either forward or backward. */search(search_forward, pattern, n, wantmatch) register int search_forward; register char *pattern; register int n; int wantmatch;{ off_t pos, linepos; register char *p; register char *q; int linenum; int linematch;#ifdef RECOMP char *re_comp(); char *errmsg;#else#ifdef REGCMP char *regcmp(); static char *cpattern = NULL;#else static char lpbuf[100]; static char *last_pattern = NULL; char *strcpy();#endif#endif /* * For a caseless search, convert any uppercase in the pattern to * lowercase. */ if (caseless && pattern != NULL) for (p = pattern; *p; p++) if (isupper(*p)) *p = tolower(*p);#ifdef RECOMP /* * (re_comp handles a null pattern internally, * so there is no need to check for a null pattern here.) */ if ((errmsg = re_comp(pattern)) != NULL) { error(errmsg); return(0); }#else#ifdef REGCMP if (pattern == NULL || *pattern == '\0') { /* * A null pattern means use the previous pattern. * The compiled previous pattern is in cpattern, so just use it. */ if (cpattern == NULL) { error("No previous regular expression"); return(0); } } else { /* * Otherwise compile the given pattern. */ char *s; if ((s = regcmp(pattern, 0)) == NULL) { error("Invalid pattern"); return(0); } if (cpattern != NULL) free(cpattern); cpattern = s; }#else if (pattern == NULL || *pattern == '\0') { /* * Null pattern means use the previous pattern. */ if (last_pattern == NULL) { error("No previous regular expression"); return(0); } pattern = last_pattern; } else { (void)strcpy(lpbuf, pattern); last_pattern = lpbuf; }#endif#endif /* * Figure out where to start the search. */ if (position(TOP) == NULL_POSITION) { /* * Nothing is currently displayed. Start at the beginning * of the file. (This case is mainly for searches from the * command line. */ pos = (off_t)0; } else if (!search_forward) { /* * Backward search: start just before the top line * displayed on the screen. */ pos = position(TOP); } else { /* * Start at the second screen line displayed on the screen. */ pos = position(TOP_PLUS_ONE); } if (pos == NULL_POSITION) { /* * Can't find anyplace to start searching from. */ error("Nothing to search"); return(0); } linenum = find_linenum(pos); for (;;) { /* * Get lines until we find a matching one or * until we hit end-of-file (or beginning-of-file * if we're going backwards). */ if (sigs) /* * A signal aborts the search. */ return(0); if (search_forward) { /* * Read the next line, and save the * starting position of that line in linepos. */ linepos = pos; pos = forw_raw_line(pos); if (linenum != 0) linenum++; } else { /* * Read the previous line and save the * starting position of that line in linepos. */ pos = back_raw_line(pos); linepos = pos; if (linenum != 0) linenum--; } if (pos == NULL_POSITION) { /* * We hit EOF/BOF without a match. */ error("Pattern not found"); return(0); } /* * If we're using line numbers, we might as well * remember the information we have now (the position * and line number of the current line). */ if (linenums) add_lnum(linenum, pos); /* * If this is a caseless search, convert uppercase in the * input line to lowercase. */ if (caseless) for (p = q = line; *p; p++, q++) *q = isupper(*p) ? tolower(*p) : *p; /* * Remove any backspaces along with the preceeding char. * This allows us to match text which is underlined or * overstruck. */ for (p = q = line; *p; p++, q++) if (q > line && *p == '\b') /* Delete BS and preceeding char. */ q -= 2; else /* Otherwise, just copy. */ *q = *p; /* * Test the next line to see if we have a match. * This is done in a variety of ways, depending * on what pattern matching functions are available. */#ifdef REGCMP linematch = (regex(cpattern, line) != NULL);#else#ifdef RECOMP linematch = (re_exec(line) == 1);#else linematch = match(pattern, line);#endif#endif /* * We are successful if wantmatch and linematch are * both true (want a match and got it), * or both false (want a non-match and got it). */ if (((wantmatch && linematch) || (!wantmatch && !linematch)) && --n <= 0) /* * Found the line. */ break; } jump_loc(linepos); return(1);}#if !defined(REGCMP) && !defined(RECOMP)/* * We have neither regcmp() nor re_comp(). * We use this function to do simple pattern matching. * It supports no metacharacters like *, etc. */staticmatch(pattern, buf) char *pattern, *buf;{ register char *pp, *lp; for ( ; *buf != '\0'; buf++) { for (pp = pattern, lp = buf; *pp == *lp; pp++, lp++) if (*pp == '\0' || *lp == '\0') break; if (*pp == '\0') return (1); } return (0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -