From cde9059fa3e4dc7e259c3864d7536252a5c580a0 Mon Sep 17 00:00:00 2001 From: ps Date: Mon, 29 May 2000 13:31:51 +0000 Subject: Nuke more from the repository. --- usr.bin/more/prim.c | 842 ---------------------------------------------------- 1 file changed, 842 deletions(-) delete mode 100644 usr.bin/more/prim.c (limited to 'usr.bin/more/prim.c') diff --git a/usr.bin/more/prim.c b/usr.bin/more/prim.c deleted file mode 100644 index 30e020b..0000000 --- a/usr.bin/more/prim.c +++ /dev/null @@ -1,842 +0,0 @@ -/* - * Copyright (c) 1988 Mark Nudleman - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)prim.c 8.1 (Berkeley) 6/6/93"; -#endif /* not lint */ - -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -/* - * Primitives for displaying the file on the screen. - */ - -#include - -#include -#include -#include -#include -#include - -#include "less.h" - -int back_scroll = -1; -int hit_eof; /* true if we're displaying the end of the input */ -int screen_trashed; - -static int squished; - -extern int sigs; -extern int top_scroll; -extern int sc_width, sc_height; -extern int horiz_off; -extern int wraplines; -extern int caseless; -extern int linenums; -extern int tagoption; -extern char *line; -extern int retain_below; - -off_t position(), forw_line(), back_line(), forw_raw_line(), back_raw_line(); -off_t ch_length(), ch_tell(); - -/* - * Check to see if the end of file is currently "displayed". - */ -static -eof_check() -{ - off_t pos; - - if (sigs) - return; - /* - * If the bottom line is empty, we are at EOF. - * If the bottom line ends at the file length, - * we must be just at EOF. - */ - pos = position(BOTTOM_PLUS_ONE); - if (pos == NULL_POSITION || pos == ch_length()) - hit_eof++; -} - -/* - * If the screen is "squished", repaint it. - * "Squished" means the first displayed line is not at the top - * of the screen; this can happen when we display a short file - * for the first time. - */ -static -squish_check() -{ - if (squished) { - squished = 0; - repaint(); - } -} - -/* - * Display n lines, scrolling forward, starting at position pos in the - * input file. "only_last" means display only the last screenful if - * n > screen size. - */ -static -forw(n, pos, only_last) - register int n; - off_t pos; - int only_last; -{ - extern int short_file; - static int first_time = 1; - int eof = 0, do_repaint; - - squish_check(); - - /* - * do_repaint tells us not to display anything till the end, - * then just repaint the entire screen. - */ - do_repaint = (only_last && n > sc_height-1); - - if (!do_repaint) { - if (top_scroll && n >= sc_height - 1) { - /* - * Start a new screen. - * {{ This is not really desirable if we happen - * to hit eof in the middle of this screen, - * but we don't yet know if that will happen. }} - */ - clear(); - home(); - } else { - lower_left(); - clear_eol(); - } - - /* - * This is not contiguous with what is currently displayed. - * Clear the screen image (position table) and start a new - * screen. - */ - if (pos != position(BOTTOM_PLUS_ONE)) { - pos_clear(); - add_forw_pos(pos); - if (top_scroll) { - clear(); - home(); - } - } - } - - for (short_file = 0; --n >= 0;) { - /* - * Read the next line of input. - */ - pos = forw_line(pos); - if (pos == NULL_POSITION) { - /* - * end of file; copy the table if the file was - * too small for an entire screen. - */ - eof = 1; - if (position(TOP) == NULL_POSITION) { - copytable(); - if (!position(TOP)) - short_file = 1; - } - break; - } - /* - * Add the position of the next line to the position table. - * Display the current line on the screen. - */ - add_forw_pos(pos); - if (do_repaint) - continue; - /* - * If this is the first screen displayed and we hit an early - * EOF (i.e. before the requested number of lines), we - * "squish" the display down at the bottom of the screen. - * But don't do this if a -t option was given; it can cause - * us to start the display after the beginning of the file, - * and it is not appropriate to squish in that case. - */ - if (first_time && line == NULL && !top_scroll && !tagoption) { - squished = 1; - continue; - } - put_line(); - } - - if (eof && !sigs) - hit_eof++; - else - eof_check(); - if (do_repaint) - repaint(); - first_time = 0; - (void) currline(BOTTOM); -} - -/* - * Display n lines, scrolling backward. - */ -static -back(n, pos, only_last) - register int n; - off_t pos; - int only_last; -{ - int do_repaint; - - squish_check(); - do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1)); - hit_eof = 0; - while (--n >= 0) - { - /* - * Get the previous line of input. - */ - pos = back_line(pos); - if (pos == NULL_POSITION) - break; - /* - * Add the position of the previous line to the position table. - * Display the line on the screen. - */ - add_back_pos(pos); - if (!do_repaint) - { - if (retain_below) - { - lower_left(); - clear_eol(); - } - home(); - add_line(); - put_line(); - } - } - - eof_check(); - if (do_repaint) - repaint(); - (void) currline(BOTTOM); -} - -/* - * Display n more lines, forward. - * Start just after the line currently displayed at the bottom of the screen. - */ -forward(n, only_last) - int n; - int only_last; -{ - off_t pos; - - if (hit_eof) { - /* - * If we're trying to go forward from end-of-file, - * go on to the next file. - */ - next_file(1); - return; - } - - pos = position(BOTTOM_PLUS_ONE); - if (pos == NULL_POSITION) - { - hit_eof++; - return; - } - forw(n, pos, only_last); -} - -/* - * Display n more lines, backward. - * Start just before the line currently displayed at the top of the screen. - */ -backward(n, only_last) - int n; - int only_last; -{ - off_t pos; - - pos = position(TOP); - /* - * This will almost never happen, because the top line is almost - * never empty. - */ - if (pos == NULL_POSITION) - return; - back(n, pos, only_last); -} - -/* - * Repaint the screen, starting from a specified position. - */ -prepaint(pos) - off_t pos; -{ - hit_eof = 0; - forw(sc_height - 1, pos, 0); - screen_trashed = 0; -} - -/* - * Repaint the screen. - */ -repaint() -{ - /* - * Start at the line currently at the top of the screen - * and redisplay the screen. - */ - prepaint(position(TOP)); -} - -/* - * Jump to the end of the file. - * It is more convenient to paint the screen backward, - * from the end of the file toward the beginning. - */ -jump_forw() -{ - off_t pos; - - if (ch_end_seek()) - { - error("Cannot seek to end of file"); - return; - } - lastmark(); - pos = ch_tell(); - clear(); - pos_clear(); - add_back_pos(pos); - back(sc_height - 1, pos, 0); -} - -/* - * Jump to line n in the file. - */ -jump_back(n) - register int n; -{ - register int c, nlines; - - /* - * This is done the slow way, by starting at the beginning - * of the file and counting newlines. - * - * {{ Now that we have line numbering (in linenum.c), - * we could improve on this by starting at the - * nearest known line rather than at the beginning. }} - */ - if (ch_seek((off_t)0)) { - /* - * Probably a pipe with beginning of file no longer buffered. - * If he wants to go to line 1, we do the best we can, - * by going to the first line which is still buffered. - */ - if (n <= 1 && ch_beg_seek() == 0) - jump_loc(ch_tell()); - error("Cannot get to beginning of file"); - return; - } - - /* - * Start counting lines. - */ - for (nlines = 1; nlines < n; nlines++) - while ((c = ch_forw_get()) != '\n') - if (c == EOI) { - char message[40]; - (void)snprintf(message, sizeof(message), - "File has only %d lines", nlines - 1); - error(message); - return; - } - jump_loc(ch_tell()); -} - -/* - * Jump to a specified percentage into the file. - * This is a poor compensation for not being able to - * quickly jump to a specific line number. - */ -jump_percent(percent) - int percent; -{ - off_t pos, len, ch_length(); - register int c; - - /* - * Determine the position in the file - * (the specified percentage of the file's length). - */ - if ((len = ch_length()) == NULL_POSITION) - { - error("Don't know length of file"); - return; - } - pos = (percent * len) / 100; - - /* - * Back up to the beginning of the line. - */ - if (ch_seek(pos) == 0) - { - while ((c = ch_back_get()) != '\n' && c != EOI) - ; - if (c == '\n') - (void) ch_forw_get(); - pos = ch_tell(); - } - jump_loc(pos); -} - -/* - * 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 struct mark { - int horiz_off; - int wraplines; - off_t pos; - char *file; -} marks[NMARKS]; - -/* - * Initialize the mark table to show no marks are set. - */ -init_mark() -{ - int i; - - for (i = 0; i < NMARKS; i++) - marks[i].pos = NULL_POSITION, marks[i].file = NULL; -} - -/* - * See if a mark letter is valid (between a and z). - */ -static int -badmark(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; -{ - extern char *current_file; - - if (badmark(c)) - return; - marks[c-'a'].pos = position(TOP); - marks[c-'a'].horiz_off = horiz_off; - marks[c-'a'].wraplines = wraplines; - if (marks[c-'a'].file) free(marks[c-'a'].file); - asprintf(&marks[c-'a'].file, "%s", current_file); -} - -/* - * This function should be called whenever the file position we are viewing - * is changed by a significant amount. The function will record the current - * position and remember it for the user. - */ -lastmark() -{ - extern char *current_file; - - marks[LASTMARK].pos = position(TOP); - marks[LASTMARK].horiz_off = horiz_off; - marks[LASTMARK].wraplines = wraplines; - if (marks[LASTMARK].file) free(marks[LASTMARK].file); - asprintf(&marks[LASTMARK].file, "%s", current_file); -} - -/* - * Go to a previously set mark. - */ -gomark(c) - int c; -{ - off_t pos; - char *file; - int new_horiz_off, new_wraplines; - extern char *current_file; - - if (c == '\'') { - pos = marks[LASTMARK].pos; - if (pos == NULL_POSITION) - pos = 0; - file = marks[LASTMARK].file; - new_horiz_off = marks[LASTMARK].horiz_off; - new_wraplines = marks[LASTMARK].wraplines; - } else { - if (badmark(c)) - return; - pos = marks[c-'a'].pos; - if (pos == NULL_POSITION) { - error("mark not set"); - return; - } - file = marks[c-'a'].file; - new_horiz_off = marks[c-'a'].horiz_off; - new_wraplines = marks[c-'a'].wraplines; - } - - /* - * This can only fail if gomark('\'') is called before lastmark() - * is called, which is in turn impossible since both edit() and - * jump_back() call jump_loc() which calls lastmark() to start - * all files. - */ - assert (file); - - /* - * This can only fail if gomark() is called before any file has - * been opened. Calling gomark() before any file has been - * opened would be non-sensical. - */ - assert (current_file); - - /* - * XXX The edit() needs to return success or failure so that we - * can abort at this point if edit() fails. - */ - edit(file, NO_FORCE_OPEN); - - /* Try to be nice about changing the horizontal scroll and wrapping */ - if (new_horiz_off > horiz_off + sc_width / 3 || - new_horiz_off < horiz_off - sc_width / 3 || - wraplines != new_wraplines || strcmp(file, current_file)) { - /* - * We should change horiz_off: if we don't change horiz_off - * the bookmarked location won't be readily visible. - */ - - /* - * A prepaint() doesn't call lastmark() (jump_loc() does), - * but we need to call repaint() somewhere since we've - * changed the horizontal offset. We don't want to call - * jump_loc() followed by repaint() since that represents - * more unnecessary screen redrawing than I'm comfortable - * with. Manually calling lastmark() here means, however, - * that lastmark() is always called even if we scroll only - * a few lines --- unlike letting jump_loc() call lastmark() - * where lastmark() is only called for jumps of more than - * a screenful. A better interface is needed. - */ - lastmark(); - - horiz_off = new_horiz_off; - wraplines = new_wraplines; - prepaint(pos); - } else { - /* - * We can honour the bookmark request without doing any - * horizontal scrolling. - */ - 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; - static regex_t rx; - static int oncethru; - int regerr; - char errbuf[_POSIX2_LINE_MAX]; - - if (pattern && pattern[0]) { - if (oncethru) { - regfree(&rx); - } - - regerr = regcomp(&rx, pattern, (REG_EXTENDED | REG_NOSUB - | (caseless ? REG_ICASE : 0))); - - if (regerr) { - regerror(regerr, &rx, errbuf, sizeof errbuf); - error(errbuf); - oncethru = 0; - regfree(&rx); - return (0); - } - oncethru = 1; - } else if (!oncethru) { - error("No previous regular expression"); - return (0); - } - - /* - * Figure out where to start the search. - * - * XXX This should probably be adapted to handle horizontal - * scrolling. Consider a long line at the top of the screen - * that might be hiding more matches to its right (when doing - * successive searches). - */ - - 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); - - /* - * 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. - */ - linematch = !regexec(&rx, line, 0, 0, 0); - - /* - * 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); -} -- cgit v1.1