summaryrefslogtreecommitdiffstats
path: root/usr.bin/more/prim.c
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2000-05-29 13:31:51 +0000
committerps <ps@FreeBSD.org>2000-05-29 13:31:51 +0000
commitcde9059fa3e4dc7e259c3864d7536252a5c580a0 (patch)
treef00074cf86c06f511c00cd5d238e6d67e893f975 /usr.bin/more/prim.c
parent9998c137973dea1fa9b7bfd2b915515ad59ba753 (diff)
downloadFreeBSD-src-cde9059fa3e4dc7e259c3864d7536252a5c580a0.zip
FreeBSD-src-cde9059fa3e4dc7e259c3864d7536252a5c580a0.tar.gz
Nuke more from the repository.
Diffstat (limited to 'usr.bin/more/prim.c')
-rw-r--r--usr.bin/more/prim.c842
1 files changed, 0 insertions, 842 deletions
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 <sys/types.h>
-
-#include <assert.h>
-#include <ctype.h>
-#include <limits.h>
-#include <regex.h>
-#include <stdio.h>
-
-#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);
-}
OpenPOWER on IntegriCloud