less (part 6 of 6)

Mark Nudelman mark at unix386.Convergent.COM
Wed Mar 6 10:14:56 AEST 1991


#! /bin/sh
# This is a shell archive.
# Remove anything before this line, then unpack it
# by saving it into a file and typing "sh file".

echo shar: Extracting \"mark.c\"
sed "s/^X//" >'mark.c' <<'END_OF_FILE'
X#include "less.h"
X#include "position.h"
X
Xextern IFILE curr_ifile;
Xextern int sc_height;
Xextern int jump_sline;
X
X/*
X * A mark is an ifile (input file) plus a position within the file.
X */
Xstruct mark {
X	IFILE m_ifile;
X	struct scrpos m_scrpos;
X};
X
X/*
X * The table of marks.
X * Each mark is identified by a lowercase or uppercase letter.
X */
X#define	NMARKS		(2*26)		/* a-z, A-Z */
Xstatic struct mark marks[NMARKS];
X
X/*
X * Special mark for the "last mark"; addressed by the apostrophe.
X */
Xstatic struct mark lmark;
X
X/*
X * Initialize the mark table to show no marks are set.
X */
X	public void
Xinit_mark()
X{
X	int i;
X
X	for (i = 0;  i < NMARKS;  i++)
X		marks[i].m_scrpos.pos = NULL_POSITION;
X	lmark.m_scrpos.pos = NULL_POSITION;
X}
X
X/*
X * See if a mark letter is valid (between a and z).
X */
X	static struct mark *
Xgetumark(c)
X	int c;
X{
X	if (c >= 'a' && c <= 'z')
X		return (&marks[c-'a']);
X
X	if (c >= 'A' && c <= 'Z')
X		return (&marks[c-'A'+26]);
X
X	error("Invalid mark letter", NULL_PARG);
X	return (NULL);
X}
X
X/*
X * Get the mark structure identified by a character.
X * The mark struct may come either from the mark table
X * or may be constructed on the fly for certain characters like ^, $.
X */
X	static struct mark *
Xgetmark(c)
X	int c;
X{
X	register struct mark *m;
X	static struct mark sm;
X
X	switch (c)
X	{
X	case '^':
X		/*
X		 * Beginning of the current file.
X		 */
X		m = &sm;
X		m->m_scrpos.pos = ch_zero();
X		m->m_scrpos.ln = 0;
X		m->m_ifile = curr_ifile;
X		break;
X	case '$':
X		/*
X		 * End of the current file.
X		 */
X		if (ch_end_seek())
X		{
X			error("Cannot seek to end of file", NULL_PARG);
X			return (NULL);
X		}
X		m = &sm;
X		m->m_scrpos.pos = ch_tell();
X		m->m_scrpos.ln = sc_height-1;
X		m->m_ifile = curr_ifile;
X		break;
X	case '.':
X		/*
X		 * Current position in the current file.
X		 */
X		m = &sm;
X		m->m_scrpos.pos = ch_tell();
X		m->m_scrpos.ln = 0;
X		m->m_ifile = curr_ifile;
X		break;
X	case '\'':
X		/*
X		 * The "last mark".
X		 */
X		m = &lmark;
X		break;
X	default:
X		/*
X		 * Must be a user-defined mark.
X		 */
X		m = getumark(c);
X		if (m == NULL)
X			break;
X		if (m->m_scrpos.pos == NULL_POSITION)
X		{
X			error("Mark not set", NULL_PARG);
X			return (NULL);
X		}
X		break;
X	}
X	return (m);
X}
X
X/*
X * Is a mark letter is invalid?
X */
X	public int
Xbadmark(c)
X	int c;
X{
X	return (getmark(c) == NULL);
X}
X
X/*
X * Set a user-defined mark.
X */
X	public void
Xsetmark(c)
X	int c;
X{
X	register struct mark *m;
X	struct scrpos scrpos;
X
X	m = getumark(c);
X	if (m == NULL)
X		return;
X	get_scrpos(&scrpos);
X	m->m_scrpos = scrpos;
X	m->m_ifile = curr_ifile;
X}
X
X/*
X * Set lmark (the mark named by the apostrophe).
X */
X	public void
Xlastmark()
X{
X	struct scrpos scrpos;
X
X	get_scrpos(&scrpos);
X	if (scrpos.pos == NULL_POSITION)
X		return;
X	lmark.m_scrpos = scrpos;
X	lmark.m_ifile = curr_ifile;
X}
X
X/*
X * Go to a mark.
X */
X	public void
Xgomark(c)
X	int c;
X{
X	register struct mark *m;
X	struct scrpos scrpos;
X
X	m = getmark(c);
X	if (m == NULL)
X		return;
X
X	/*
X	 * If we're trying to go to the lastmark and 
X	 * it has not been set to anything yet,
X	 * set it to the beginning of the current file.
X	 */
X	if (m == &lmark && m->m_scrpos.pos == NULL_POSITION)
X	{
X		m->m_ifile = curr_ifile;
X		m->m_scrpos.pos = ch_zero();
X		m->m_scrpos.ln = jump_sline;
X	}
X
X	/*
X	 * If we're using lmark, we must save the screen position now,
X	 * because if we call edit() below, lmark will change.
X	 * (We save the screen position even if we're not using lmark.)
X	 */
X	scrpos = m->m_scrpos;
X	if (m->m_ifile != curr_ifile)
X	{
X		/*
X		 * Not in the current file; edit the correct file.
X		 */
X		if (edit(get_filename(m->m_ifile), 0))
X			return;
X	}
X
X	jump_loc(scrpos.pos, scrpos.ln);
X}
X
X/*
X * Return the position associated with a given mark letter.
X *
X * We don't return which screen line the position 
X * is associated with, but this doesn't matter much,
X * because it's always the first non-blank line on the screen.
X */
X	public POSITION
Xmarkpos(c)
X	int c;
X{
X	register struct mark *m;
X
X	m = getmark(c);
X	if (m == NULL)
X		return (NULL_POSITION);
X
X	if (m->m_ifile != curr_ifile)
X	{
X		error("Mark not in current file", NULL_PARG);
X		return (NULL_POSITION);
X	}
X	return (m->m_scrpos.pos);
X}
END_OF_FILE
echo shar: Extracting \"prompt.c\"
sed "s/^X//" >'prompt.c' <<'END_OF_FILE'
X/*
X * Prompting and other messages.
X * There are three flavors of prompts, SHORT, MEDIUM and LONG,
X * selected by the -m/-M options.
X * There is also the "equals message", printed by the = command.
X * A prompt is a message composed of various pieces, such as the 
X * name of the file being viewed, the percentage into the file, etc.
X */
X
X#include "less.h"
X#include "position.h"
X
Xextern int pr_type;
Xextern int hit_eof;
Xextern int new_file;
Xextern int sc_width;
Xextern int so_s_width, so_e_width;
Xextern int linenums;
Xextern int sc_height;
Xextern int jump_sline;
Xextern IFILE curr_ifile;
X#if EDITOR
Xextern char *editor;
X#endif
X
X/*
X * Prototypes for the three flavors of prompts.
X * These strings are expanded by pr_expand().
X */
Xstatic char s_proto[] =
X  "?n?f%f .?m(file %i of %m) ..?e(END) ?x- Next\\: %x..%t";
Xstatic char m_proto[] =
X  "?n?f%f .?m(file %i of %m) ..?e(END) ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t";
Xstatic char M_proto[] =
X  "?f%f .?n?m(file %i of %m) ..?ltline %lt?L/%L. :byte %bB?s/%s. .?e(END) ?x- Next\\: %x.:?pB%pB\\%..%t";
Xstatic char e_proto[] =
X  "?f%f .?m(file %i of %m) .?ltline %lt?L/%L. .byte %bB?s/%s. ?e(END) :?pB%pB\\%..%t";
X
Xpublic char *prproto[3];
Xpublic char *eqproto = e_proto;
X
Xstatic char message[250];
Xstatic char *mp;
X
X/*
X * Initialize the prompt prototype strings.
X */
X	public void
Xinit_prompt()
X{
X	prproto[0] = save(s_proto);
X	prproto[1] = save(m_proto);
X	prproto[2] = save(M_proto);
X	eqproto = save(e_proto);
X}
X
X/*
X * Set the message pointer to the end of the message string.
X */
X	static void
Xsetmp()
X{
X	while (*mp != '\0')
X		mp++;
X}
X
X/*
X * Append a POSITION (as a decimal integer) to the end of the message.
X */
X	static void
Xap_pos(pos)
X	POSITION pos;
X{
X	sprintf(mp, "%ld", (long)pos);
X	setmp();
X}
X
X/*
X * Append an integer to the end of the message.
X */
X	static void
Xap_int(n)
X	int n;
X{
X	sprintf(mp, "%d", n);
X	setmp();
X}
X
X/*
X * Append a string to the end of the message.
X */
X	static void
Xap_str(s)
X	char *s;
X{
X	strtcpy(mp, s, (unsigned int)(&message[sizeof(message)] - mp));
X	setmp();
X}
X
X/*
X * Append a question mark to the end of the message.
X */
X	static void
Xap_quest()
X{
X	*mp++ = '?';
X}
X
X/*
X * Return the "current" byte offset in the file.
X */
X	static POSITION
Xcurr_byte(where)
X	int where;
X{
X	POSITION pos;
X
X	pos = position(where);
X	while (pos == NULL_POSITION && where >= 0 && where < sc_height)
X		pos = position(++where);
X	if (pos == NULL_POSITION)
X		pos = ch_length();
X	return (pos);
X}
X
X/*
X * Return the value of a prototype conditional.
X * A prototype string may include conditionals which consist of a 
X * question mark followed by a single letter.
X * Here we decode that letter and return the appropriate boolean value.
X */
X	static int
Xcond(c, where)
X	char c;
X	int where;
X{
X	switch (c)
X	{
X	case 'a':	/* Anything in the message yet? */
X		return (mp > message);
X	case 'b':	/* Current byte offset known? */
X		return (curr_byte(where) != NULL_POSITION);
X	case 'e':	/* At end of file? */
X		return (hit_eof);
X	case 'f':	/* Filename known? */
X		return (strcmp(get_filename(curr_ifile), "-") != 0);
X	case 'l':	/* Line number known? */
X		return (linenums);
X	case 'L':	/* Final line number known? */
X		return (linenums && ch_length() != NULL_POSITION);
X	case 'm':	/* More than one file? */
X		return (nifile() > 1);
X	case 'n':	/* First prompt in a new file? */
X		return (new_file);
X	case 'p':	/* Percent into file known? */
X		return (curr_byte(where) != NULL_POSITION && 
X				ch_length() > 0);
X	case 's':	/* Size of file known? */
X	case 'B':
X		return (ch_length() != NULL_POSITION);
X	case 'x':	/* Is there a "next" file? */
X		return (next_ifile(curr_ifile) != NULL_IFILE);
X	}
X	return (0);
X}
X
X/*
X * Decode a "percent" prototype character.
X * A prototype string may include various "percent" escapes;
X * that is, a percent sign followed by a single letter.
X * Here we decode that letter and take the appropriate action,
X * usually by appending something to the message being built.
X */
X	static void
Xprotochar(c, where)
X	int c;
X	int where;
X{
X	POSITION pos;
X	POSITION len;
X	int n;
X	IFILE h;
X
X	switch (c)
X	{
X	case 'b':	/* Current byte offset */
X		pos = curr_byte(where);
X		if (pos != NULL_POSITION)
X			ap_pos(pos);
X		else
X			ap_quest();
X		break;
X#if EDITOR
X	case 'E':	/* Editor name */
X		ap_str(editor);
X		break;
X#endif
X	case 'f':	/* File name */
X		ap_str(get_filename(curr_ifile));
X		break;
X	case 'i':	/* Index into list of files */
X		ap_int(get_index(curr_ifile));
X		break;
X	case 'l':	/* Current line number */
X		n = currline(where);
X		if (n != 0)
X			ap_int(n);
X		else
X			ap_quest();
X		break;
X	case 'L':	/* Final line number */
X		len = ch_length();
X		if (len == NULL_POSITION || len == ch_zero() ||
X		    (n = find_linenum(len)) <= 0)
X			ap_quest();
X		else
X			ap_int(n-1);
X		break;
X	case 'm':	/* Number of files */
X		ap_int(nifile());
X		break;
X	case 'p':	/* Percent into file */
X		pos = curr_byte(where);
X		len = ch_length();
X		if (pos != NULL_POSITION && len > 0)
X			/*
X			 * {{ This calculation may overflow! }}
X			 */
X			ap_int((int)(100*pos / len));
X		else
X			ap_quest();
X		break;
X	case 's':	/* Size of file */
X	case 'B':
X		len = ch_length();
X		if (len != NULL_POSITION)
X			ap_pos(len);
X		else
X			ap_quest();
X		break;
X	case 't':	/* Truncate trailing spaces in the message */
X		while (mp > message && mp[-1] == ' ')
X			mp--;
X		break;
X	case 'x':	/* Name of next file */
X		h = next_ifile(curr_ifile);
X		if (h != NULL_IFILE)
X			ap_str(get_filename(h));
X		else
X			ap_quest();
X		break;
X	}
X}
X
X/*
X * Skip a false conditional.
X * When a false condition is found (either a false IF or the ELSE part 
X * of a true IF), this routine scans the prototype string to decide
X * where to resume parsing the string.
X * We must keep track of nested IFs and skip them properly.
X */
X	static char *
Xskipcond(p)
X	register char *p;
X{
X	register int iflevel;
X
X	/*
X	 * We came in here after processing a ? or :,
X	 * so we start nested one level deep.
X	 */
X	iflevel = 1;
X
X	for (;;) switch (*++p)
X	{
X	case '?':
X		/*
X		 * Start of a nested IF.
X		 */
X		iflevel++;
X		break;
X	case ':':
X		/*
X		 * Else.
X		 * If this matches the IF we came in here with,
X		 * then we're done.
X		 */
X		if (iflevel == 1)
X			return (p);
X		break;
X	case '.':
X		/*
X		 * Endif.
X		 * If this matches the IF we came in here with,
X		 * then we're done.
X		 */
X		if (--iflevel == 0)
X			return (p);
X		break;
X	case '\\':
X		/*
X		 * Backslash escapes the next character.
X		 */
X		++p;
X		break;
X	case '\0':
X		/*
X		 * Whoops.  Hit end of string.
X		 * This is a malformed conditional, but just treat it
X		 * as if all active conditionals ends here.
X		 */
X		return (p-1);
X	}
X	/*NOTREACHED*/
X}
X
X	static char *
Xwherechar(p, wp)
X	char *p;
X	int *wp;
X{
X	switch (*p)
X	{
X	case 'b': case 'l': case 'p':
X		switch (*++p)
X		{
X		case 't':   *wp = TOP;			break;
X		case 'm':   *wp = MIDDLE;		break;
X		case 'b':   *wp = BOTTOM;		break;
X		case 'B':   *wp = BOTTOM_PLUS_ONE;	break;
X		case 'j':   *wp = adjsline(jump_sline);	break;
X		default:    *wp = TOP;  p--;		break;
X		}
X	}
X	return (p);
X}
X
X/*
X * Construct a message based on a prototype string.
X */
X	public char *
Xpr_expand(proto, maxwidth)
X	char *proto;
X	int maxwidth;
X{
X	register char *p;
X	register int c;
X	int where;
X
X	mp = message;
X
X	if (*proto == '\0')
X		return ("");
X
X	for (p = proto;  *p != '\0';  p++)
X	{
X		switch (*p)
X		{
X		default:	/* Just put the character in the message */
X			*mp++ = *p;
X			break;
X		case '\\':	/* Backslash escapes the next character */
X			p++;
X			*mp++ = *p;
X			break;
X		case '?':	/* Conditional (IF) */
X			if ((c = *++p) == '\0')
X				--p;
X			else
X			{
X				p = wherechar(p, &where);
X				if (!cond(c, where))
X					p = skipcond(p);
X			}
X			break;
X		case ':':	/* ELSE */
X			p = skipcond(p);
X			break;
X		case '.':	/* ENDIF */
X			break;
X		case '%':	/* Percent escape */
X			if ((c = *++p) == '\0')
X				--p;
X			else
X			{
X				p = wherechar(p, &where);
X				protochar(c, where);
X			}
X			break;
X		}
X	}
X
X	new_file = 0;
X	if (mp == message)
X		return (NULL);
X	*mp = '\0';
X	if (maxwidth > 0 && mp >= message + maxwidth)
X	{
X		/*
X		 * Message is too long.
X		 * Return just the final portion of it.
X		 */
X		return (mp - maxwidth);
X	}
X	return (message);
X}
X
X/*
X * Return a message suitable for printing by the "=" command.
X */
X	public char *
Xeq_message()
X{
X	return (pr_expand(eqproto, 0));
X}
X
X/*
X * Return a prompt.
X * This depends on the prompt type (SHORT, MEDIUM, LONG), etc.
X * If we can't come up with an appropriate prompt, return NULL
X * and the caller will prompt with a colon.
X */
X	public char *
Xpr_string()
X{
X	return (pr_expand(prproto[pr_type], sc_width-so_s_width-so_e_width-2));
X}
END_OF_FILE
echo shar: Extracting \"screen.c\"
sed "s/^X//" >'screen.c' <<'END_OF_FILE'
X/*
X * Routines which deal with the characteristics of the terminal.
X * Uses termcap to be as terminal-independent as possible.
X *
X * {{ Someday this should be rewritten to use curses. }}
X */
X
X#include "less.h"
X#if XENIX
X#include <sys/types.h>
X#include <sys/ioctl.h>
X#endif
X
X#if TERMIO
X#include <termio.h>
X#else
X#include <sgtty.h>
X#endif
X
X#if !TERMIO && defined(TIOCGWINSZ)
X#include <sys/ioctl.h>
X#else
X/*
X * For the Unix PC (ATT 7300 & 3B1):
X * Since WIOCGETD is defined in sys/window.h, we can't use that to decide
X * whether to include sys/window.h.  Use SIGPHONE from signal.h instead.
X */
X#include <signal.h>
X#ifdef SIGPHONE
X#include <sys/window.h>
X#endif
X#endif
X
X/*
X * Strings passed to tputs() to do various terminal functions.
X */
Xstatic char
X	*sc_pad,		/* Pad string */
X	*sc_home,		/* Cursor home */
X	*sc_addline,		/* Add line, scroll down following lines */
X	*sc_lower_left,		/* Cursor to last line, first column */
X	*sc_move,		/* General cursor positioning */
X	*sc_clear,		/* Clear screen */
X	*sc_eol_clear,		/* Clear to end of line */
X	*sc_s_in,		/* Enter standout (highlighted) mode */
X	*sc_s_out,		/* Exit standout mode */
X	*sc_u_in,		/* Enter underline mode */
X	*sc_u_out,		/* Exit underline mode */
X	*sc_b_in,		/* Enter bold mode */
X	*sc_b_out,		/* Exit bold mode */
X	*sc_bl_in,		/* Enter blink mode */
X	*sc_bl_out,		/* Exit blink mode */
X	*sc_visual_bell,	/* Visual bell (flash screen) sequence */
X	*sc_backspace,		/* Backspace cursor */
X	*sc_init,		/* Startup terminal initialization */
X	*sc_deinit;		/* Exit terminal de-initialization */
X
Xstatic int init_done = 0;
X
Xpublic int auto_wrap;		/* Terminal does \r\n when write past margin */
Xpublic int ignaw;		/* Terminal ignores \n immediately after wrap */
Xpublic int erase_char, kill_char; /* The user's erase and line-kill chars */
Xpublic int sc_width, sc_height;	/* Height & width of screen */
Xpublic int bo_s_width, bo_e_width;	/* Printing width of boldface seq */
Xpublic int ul_s_width, ul_e_width;	/* Printing width of underline seq */
Xpublic int so_s_width, so_e_width;	/* Printing width of standout seq */
Xpublic int bl_s_width, bl_e_width;	/* Printing width of blink seq */
X
Xstatic char *cheaper();
X
X/*
X * These two variables are sometimes defined in,
X * and needed by, the termcap library.
X * It may be necessary on some systems to declare them extern here.
X */
X/*extern*/ short ospeed;	/* Terminal output baud rate */
X/*extern*/ char PC;		/* Pad character */
X
Xextern int quiet;		/* If VERY_QUIET, use visual bell for bell */
Xextern int know_dumb;		/* Don't complain about a dumb terminal */
Xextern int back_scroll;
Xextern int swindow;
Xextern char *tgetstr();
Xextern char *tgoto();
Xextern char *getenv();
X
X
X/*
X * Change terminal to "raw mode", or restore to "normal" mode.
X * "Raw mode" means 
X *	1. An outstanding read will complete on receipt of a single keystroke.
X *	2. Input is not echoed.  
X *	3. On output, \n is mapped to \r\n.
X *	4. \t is NOT expanded into spaces.
X *	5. Signal-causing characters such as ctrl-C (interrupt),
X *	   etc. are NOT disabled.
X * It doesn't matter whether an input \n is mapped to \r, or vice versa.
X */
X	public void
Xraw_mode(on)
X	int on;
X{
X	static int curr_on = 0;
X
X	if (on == curr_on)
X		return;
X#if TERMIO
X    {
X	struct termio s;
X	static struct termio save_term;
X
X	if (on)
X	{
X		/*
X		 * Get terminal modes.
X		 */
X		ioctl(2, TCGETA, &s);
X
X		/*
X		 * Save modes and set certain variables dependent on modes.
X		 */
X		save_term = s;
X		ospeed = s.c_cflag & CBAUD;
X		erase_char = s.c_cc[VERASE];
X		kill_char = s.c_cc[VKILL];
X
X		/*
X		 * Set the modes to the way we want them.
X		 */
X		s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
X		s.c_oflag |=  (OPOST|ONLCR|TAB3);
X		s.c_oflag &= ~(OCRNL|ONOCR|ONLRET);
X		s.c_cc[VMIN] = 1;
X		s.c_cc[VTIME] = 0;
X	} else
X	{
X		/*
X		 * Restore saved modes.
X		 */
X		s = save_term;
X	}
X	ioctl(2, TCSETAW, &s);
X    }
X#else
X    {
X	struct sgttyb s;
X	static struct sgttyb save_term;
X
X	if (on)
X	{
X		/*
X		 * Get terminal modes.
X		 */
X		ioctl(2, TIOCGETP, &s);
X
X		/*
X		 * Save modes and set certain variables dependent on modes.
X		 */
X		save_term = s;
X		ospeed = s.sg_ospeed;
X		erase_char = s.sg_erase;
X		kill_char = s.sg_kill;
X
X		/*
X		 * Set the modes to the way we want them.
X		 */
X		s.sg_flags |= CBREAK;
X		s.sg_flags &= ~(ECHO|XTABS);
X	} else
X	{
X		/*
X		 * Restore saved modes.
X		 */
X		s = save_term;
X	}
X	ioctl(2, TIOCSETN, &s);
X    }
X#endif
X	curr_on = on;
X}
X
X	static void
Xcannot(s)
X	char *s;
X{
X	PARG parg;
X
X	if (know_dumb)
X		/* 
X		 * User knows this is a dumb terminal, so don't tell him.
X		 */
X		return;
X
X	parg.p_string = s;
X	error("WARNING: terminal cannot %s", &parg);
X}
X
X/*
X * Get size of the output screen.
X */
X	public void
Xget_scrsize(p_height, p_width)
X	int *p_height;
X	int *p_width;
X{
X	register char *s;
X#ifdef TIOCGWINSZ
X	struct winsize w;
X#else
X#ifdef WIOCGETD
X	struct uwdata w;
X#endif
X#endif
X
X#ifdef TIOCGWINSZ
X	if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_row > 0)
X		*p_height = w.ws_row;
X	else
X#else
X#ifdef WIOCGETD
X	if (ioctl(2, WIOCGETD, &w) == 0 && w.uw_height > 0)
X		*p_height = w.uw_height/w.uw_vs;
X	else
X#endif
X#endif
X	if ((s = getenv("LINES")) != NULL)
X		*p_height = atoi(s);
X	else
X 		*p_height = tgetnum("li");
X
X	if (*p_height <= 0)
X		*p_height = 24;
X
X#ifdef TIOCGWINSZ
X 	if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
X		*p_width = w.ws_col;
X	else
X#ifdef WIOCGETD
X	if (ioctl(2, WIOCGETD, &w) == 0 && w.uw_width > 0)
X		*p_width = w.uw_width/w.uw_hs;
X	else
X#endif
X#endif
X	if ((s = getenv("COLUMNS")) != NULL)
X		*p_width = atoi(s);
X	else
X 		*p_width = tgetnum("co");
X
X 	if (*p_width <= 0)
X  		*p_width = 80;
X}
X
X/*
X * Get terminal capabilities via termcap.
X */
X	public void
Xget_term()
X{
X	char *sp;
X	register char *t1, *t2;
X	register int hard;
X	char *term;
X	char termbuf[2048];
X
X	static char sbuf[1024];
X
X	/*
X	 * Find out what kind of terminal this is.
X	 */
X 	if ((term = getenv("TERM")) == NULL)
X 		term = "unknown";
X 	if (tgetent(termbuf, term) <= 0)
X 		strcpy(termbuf, "dumb:hc:");
X
X 	hard = tgetflag("hc");
X
X	/*
X	 * Get size of the screen.
X	 */
X	get_scrsize(&sc_height, &sc_width);
X	pos_init();
X	if (swindow < 0)
X		swindow = sc_height - 1;
X
X	auto_wrap = tgetflag("am");
X	ignaw = tgetflag("xn");
X
X	/*
X	 * Assumes termcap variable "sg" is the printing width of:
X	 * the standout sequence, the end standout sequence,
X	 * the underline sequence, the end underline sequence,
X	 * the boldface sequence, and the end boldface sequence.
X	 */
X	if ((so_s_width = tgetnum("sg")) < 0)
X		so_s_width = 0;
X	so_e_width = so_s_width;
X
X	bo_s_width = bo_e_width = so_s_width;
X	ul_s_width = ul_e_width = so_s_width;
X	bl_s_width = bl_e_width = so_s_width;
X
X	/*
X	 * Get various string-valued capabilities.
X	 */
X	sp = sbuf;
X
X	sc_pad = tgetstr("pc", &sp);
X	if (sc_pad != NULL)
X		PC = *sc_pad;
X
X	sc_init = tgetstr("ti", &sp);
X	if (sc_init == NULL)
X		sc_init = "";
X
X	sc_deinit= tgetstr("te", &sp);
X	if (sc_deinit == NULL)
X		sc_deinit = "";
X
X	sc_eol_clear = tgetstr("ce", &sp);
X	if (hard || sc_eol_clear == NULL || *sc_eol_clear == '\0')
X	{
X		cannot("clear to end of line");
X		sc_eol_clear = "";
X	}
X
X	sc_clear = tgetstr("cl", &sp);
X	if (hard || sc_clear == NULL || *sc_clear == '\0')
X	{
X		cannot("clear screen");
X		sc_clear = "\n\n";
X	}
X
X	sc_move = tgetstr("cm", &sp);
X	if (hard || sc_move == NULL || *sc_move == '\0')
X	{
X		/*
X		 * This is not an error here, because we don't 
X		 * always need sc_move.
X		 * We need it only if we don't have home or lower-left.
X		 */
X		sc_move = "";
X	}
X
X	sc_s_in = tgetstr("so", &sp);
X	if (hard || sc_s_in == NULL)
X		sc_s_in = "";
X
X	sc_s_out = tgetstr("se", &sp);
X	if (hard || sc_s_out == NULL)
X		sc_s_out = "";
X
X	sc_u_in = tgetstr("us", &sp);
X	if (hard || sc_u_in == NULL)
X		sc_u_in = sc_s_in;
X
X	sc_u_out = tgetstr("ue", &sp);
X	if (hard || sc_u_out == NULL)
X		sc_u_out = sc_s_out;
X
X	sc_b_in = tgetstr("md", &sp);
X	if (hard || sc_b_in == NULL)
X	{
X		sc_b_in = sc_s_in;
X		sc_b_out = sc_s_out;
X	} else
X	{
X		sc_b_out = tgetstr("me", &sp);
X		if (hard || sc_b_out == NULL)
X			sc_b_out = "";
X	}
X
X	sc_bl_in = tgetstr("mb", &sp);
X	if (hard || sc_bl_in == NULL)
X	{
X		sc_bl_in = sc_s_in;
X		sc_bl_out = sc_s_out;
X	} else
X	{
X		sc_bl_out = sc_b_out;
X	}
X
X	sc_visual_bell = tgetstr("vb", &sp);
X	if (hard || sc_visual_bell == NULL)
X		sc_visual_bell = "";
X
X	if (tgetflag("bs"))
X		sc_backspace = "\b";
X	else
X	{
X		sc_backspace = tgetstr("bc", &sp);
X		if (sc_backspace == NULL || *sc_backspace == '\0')
X			sc_backspace = "\b";
X	}
X
X	/*
X	 * Choose between using "ho" and "cm" ("home" and "cursor move")
X	 * to move the cursor to the upper left corner of the screen.
X	 */
X	t1 = tgetstr("ho", &sp);
X	if (hard || t1 == NULL)
X		t1 = "";
X	if (*sc_move == '\0')
X		t2 = "";
X	else
X	{
X		strcpy(sp, tgoto(sc_move, 0, 0));
X		t2 = sp;
X		sp += strlen(sp) + 1;
X	}
X	sc_home = cheaper(t1, t2, "home cursor", "|\b^");
X
X	/*
X	 * Choose between using "ll" and "cm"  ("lower left" and "cursor move")
X	 * to move the cursor to the lower left corner of the screen.
X	 */
X	t1 = tgetstr("ll", &sp);
X	if (hard || t1 == NULL)
X		t1 = "";
X	if (*sc_move == '\0')
X		t2 = "";
X	else
X	{
X		strcpy(sp, tgoto(sc_move, 0, sc_height-1));
X		t2 = sp;
X		sp += strlen(sp) + 1;
X	}
X	sc_lower_left = cheaper(t1, t2,
X		"move cursor to lower left of screen", "\r");
X
X	/*
X	 * Choose between using "al" or "sr" ("add line" or "scroll reverse")
X	 * to add a line at the top of the screen.
X	 */
X	t1 = tgetstr("al", &sp);
X	if (hard || t1 == NULL)
X		t1 = "";
X	t2 = tgetstr("sr", &sp);
X	if (hard || t2 == NULL)
X		t2 = "";
X	sc_addline = cheaper(t1, t2, "scroll backwards", "");
X	if (*sc_addline == '\0')
X	{
X		/*
X		 * Force repaint on any backward movement.
X		 */
X		back_scroll = 0;
X	}
X}
X
X/*
X * Return the "best" of the two given termcap strings.
X * The best, if both exist, is the one with the lower 
X * cost (see cost() function).
X */
X	static char *
Xcheaper(t1, t2, doit, def)
X	char *t1, *t2;
X	char *doit;
X	char *def;
X{
X	if (*t1 == '\0' && *t2 == '\0')
X	{
X		cannot(doit);
X		return (def);
X	}
X	if (*t1 == '\0')
X		return (t2);
X	if (*t2 == '\0')
X		return (t1);
X	if (cost(t1) < cost(t2))
X		return (t1);
X	return (t2);
X}
X
X/*
X * Return the cost of displaying a termcap string.
X * We use the trick of calling tputs, but as a char printing function
X * we give it inc_costcount, which just increments "costcount".
X * This tells us how many chars would be printed by using this string.
X * {{ Couldn't we just use strlen? }}
X */
Xstatic int costcount;
X
X/*ARGSUSED*/
X	static void
Xinc_costcount(c)
X	int c;
X{
X	costcount++;
X}
X
X	static int
Xcost(t)
X	char *t;
X{
X	costcount = 0;
X	tputs(t, sc_height, inc_costcount);
X	return (costcount);
X}
X
X
X/*
X * Below are the functions which perform all the 
X * terminal-specific screen manipulation.
X */
X
X
X/*
X * Initialize terminal
X */
X	public void
Xinit()
X{
X	tputs(sc_init, sc_height, putchr);
X	init_done = 1;
X}
X
X/*
X * Deinitialize terminal
X */
X	public void
Xdeinit()
X{
X	if (!init_done)
X		return;
X	tputs(sc_deinit, sc_height, putchr);
X	init_done = 0;
X}
X
X/*
X * Home cursor (move to upper left corner of screen).
X */
X	public void
Xhome()
X{
X	tputs(sc_home, 1, putchr);
X}
X
X/*
X * Add a blank line (called with cursor at home).
X * Should scroll the display down.
X */
X	public void
Xadd_line()
X{
X	tputs(sc_addline, sc_height, putchr);
X}
X
X/*
X * Move cursor to lower left corner of screen.
X */
X	public void
Xlower_left()
X{
X	tputs(sc_lower_left, 1, putchr);
X}
X
X/*
X * Ring the terminal bell.
X */
X	public void
Xbell()
X{
X	if (quiet == VERY_QUIET)
X		vbell();
X	else
X		putchr('\7');
X}
X
X/*
X * Output the "visual bell", if there is one.
X */
X	public void
Xvbell()
X{
X	if (*sc_visual_bell == '\0')
X		return;
X	tputs(sc_visual_bell, sc_height, putchr);
X}
X
X/*
X * Clear the screen.
X */
X	public void
Xclear()
X{
X	tputs(sc_clear, sc_height, putchr);
X}
X
X/*
X * Clear from the cursor to the end of the cursor's line.
X * {{ This must not move the cursor. }}
X */
X	public void
Xclear_eol()
X{
X	tputs(sc_eol_clear, 1, putchr);
X}
X
X/*
X * Begin "standout" (bold, underline, or whatever).
X */
X	public void
Xso_enter()
X{
X	tputs(sc_s_in, 1, putchr);
X}
X
X/*
X * End "standout".
X */
X	public void
Xso_exit()
X{
X	tputs(sc_s_out, 1, putchr);
X}
X
X/*
X * Begin "underline" (hopefully real underlining, 
X * otherwise whatever the terminal provides).
X */
X	public void
Xul_enter()
X{
X	tputs(sc_u_in, 1, putchr);
X}
X
X/*
X * End "underline".
X */
X	public void
Xul_exit()
X{
X	tputs(sc_u_out, 1, putchr);
X}
X
X/*
X * Begin "bold"
X */
X	public void
Xbo_enter()
X{
X	tputs(sc_b_in, 1, putchr);
X}
X
X/*
X * End "bold".
X */
X	public void
Xbo_exit()
X{
X	tputs(sc_b_out, 1, putchr);
X}
X
X/*
X * Begin "blink"
X */
X	public void
Xbl_enter()
X{
X	tputs(sc_bl_in, 1, putchr);
X}
X
X/*
X * End "blink".
X */
X	public void
Xbl_exit()
X{
X	tputs(sc_bl_out, 1, putchr);
X}
X
X/*
X * Erase the character to the left of the cursor 
X * and move the cursor left.
X */
X	public void
Xbackspace()
X{
X	/* 
X	 * Try to erase the previous character by overstriking with a space.
X	 */
X	tputs(sc_backspace, 1, putchr);
X	putchr(' ');
X	tputs(sc_backspace, 1, putchr);
X}
X
X/*
X * Output a plain backspace, without erasing the previous char.
X */
X	public void
Xputbs()
X{
X	tputs(sc_backspace, 1, putchr);
X}
END_OF_FILE
echo shar: Extracting \"signal.c\"
sed "s/^X//" >'signal.c' <<'END_OF_FILE'
X/*
X * Routines dealing with signals.
X *
X * A signal usually merely causes a bit to be set in the "signals" word.
X * At some convenient time, the mainline code checks to see if any
X * signals need processing by calling psignal().
X * If we happen to be reading from a file [in iread()] at the time
X * the signal is received, we call intread to interrupt the iread.
X */
X
X#include "less.h"
X#include <signal.h>
X
X/*
X * "sigs" contains bits indicating signals which need to be processed.
X */
Xpublic int sigs;
X
X#define	S_INTERRUPT	01
X#ifdef SIGTSTP
X#define	S_STOP		02
X#endif
X#if defined(SIGWINCH) || defined(SIGWIND)
X#define S_WINCH		04
X#endif
X
Xextern int sc_width, sc_height;
Xextern int swindow;
Xextern int screen_trashed;
Xextern int lnloop;
Xextern int linenums;
Xextern int scroll;
Xextern int reading;
X
X/*
X * Interrupt signal handler.
X */
X	/* ARGSUSED*/
X	static HANDLER
Xu_interrupt(type)
X	int type;
X{
X	SIGNAL(SIGINT, u_interrupt);
X	sigs |= S_INTERRUPT;
X	if (reading)
X		intread();
X}
X
X	public void
Xfake_interrupt()
X{
X	sigs |= S_INTERRUPT;
X}
X
X#ifdef SIGTSTP
X/*
X * "Stop" (^Z) signal handler.
X */
X	/* ARGSUSED*/
X	static HANDLER
Xstop(type)
X	int type;
X{
X	SIGNAL(SIGTSTP, stop);
X	sigs |= S_STOP;
X	if (reading)
X		intread();
X}
X#endif
X
X#ifdef SIGWINCH
X/*
X * "Window" change handler
X */
X	/* ARGSUSED*/
X	public HANDLER
Xwinch(type)
X	int type;
X{
X	SIGNAL(SIGWINCH, winch);
X	sigs |= S_WINCH;
X	if (reading)
X		intread();
X}
X#else
X#ifdef SIGWIND
X/*
X * "Window" change handler
X */
X	/* ARGSUSED*/
X	public HANDLER
Xwinch(type)
X	int type;
X{
X	SIGNAL(SIGWIND, winch);
X	sigs |= S_WINCH;
X	if (reading)
X		intread();
X}
X#endif
X#endif
X
X/*
X * Set up the signal handlers.
X */
X	public void
Xinit_signals(on)
X	int on;
X{
X	if (on)
X	{
X		/*
X		 * Set signal handlers.
X		 */
X		(void) SIGNAL(SIGINT, u_interrupt);
X#ifdef SIGTSTP
X		(void) SIGNAL(SIGTSTP, stop);
X#endif
X#ifdef SIGWINCH
X		(void) SIGNAL(SIGWINCH, winch);
X#else
X#ifdef SIGWIND
X		(void) SIGNAL(SIGWIND, winch);
X#endif
X#endif
X	} else
X	{
X		/*
X		 * Restore signals to defaults.
X		 */
X		(void) SIGNAL(SIGINT, SIG_DFL);
X#ifdef SIGTSTP
X		(void) SIGNAL(SIGTSTP, SIG_DFL);
X#endif
X#ifdef SIGWINCH
X		(void) SIGNAL(SIGWINCH, SIG_IGN);
X#endif
X#ifdef SIGWIND
X		(void) SIGNAL(SIGWIND, SIG_IGN);
X#endif
X	}
X}
X
X/*
X * Process any signals we have received.
X * A received signal cause a bit to be set in "sigs".
X */
X	public void
Xpsignals()
X{
X	register int tsignals;
X
X	if ((tsignals = sigs) == 0)
X		return;
X	sigs = 0;
X
X#ifdef S_WINCH
X	if (tsignals & S_WINCH)
X	{
X		int old_width, old_height;
X		/*
X		 * Re-execute get_term() to read the new window size.
X		 */
X		old_width = sc_width;
X		old_height = sc_height;
X		swindow = -1;
X		get_term();
X		if (sc_width != old_width || sc_height != old_height)
X		{
X			scroll = (sc_height + 1) / 2;
X			screen_trashed = 1;
X		}
X	}
X#endif
X#ifdef SIGTSTP
X	if (tsignals & S_STOP)
X	{
X		/*
X		 * Clean up the terminal.
X		 */
X#ifdef SIGTTOU
X		SIGNAL(SIGTTOU, SIG_IGN);
X#endif
X		lower_left();
X		clear_eol();
X		deinit();
X		flush();
X		raw_mode(0);
X#ifdef SIGTTOU
X		SIGNAL(SIGTTOU, SIG_DFL);
X#endif
X		SIGNAL(SIGTSTP, SIG_DFL);
X		kill(getpid(), SIGTSTP);
X		/*
X		 * ... Bye bye. ...
X		 * Hopefully we'll be back later and resume here...
X		 * Reset the terminal and arrange to repaint the
X		 * screen when we get back to the main command loop.
X		 */
X		SIGNAL(SIGTSTP, stop);
X		raw_mode(1);
X		init();
X		screen_trashed = 1;
X	}
X#endif
X	if (tsignals & S_INTERRUPT)
X	{
X		bell();
X		/*
X		 * {{ You may wish to replace the bell() with 
X		 *    error("Interrupt", NULL_PARG); }}
X		 */
X
X		/*
X		 * If we were interrupted while in the "calculating 
X		 * line numbers" loop, turn off line numbers.
X		 */
X		if (lnloop)
X		{
X			lnloop = 0;
X			if (linenums == 2)
X				screen_trashed = 1;
X			linenums = 0;
X			error("Line numbers turned off", NULL_PARG);
X		}
X
X	}
X}
END_OF_FILE
echo shar: Extracting \"tags.c\"
sed "s/^X//" >'tags.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include "less.h"
X
X#define	WHITESP(c)	((c)==' ' || (c)=='\t')
X
X#if TAGS
X
Xpublic char *tagfile;
Xpublic char *tagpattern;
X
Xpublic char *tags = "tags";
X
Xextern int linenums;
Xextern int sigs;
Xextern int jump_sline;
X
X/*
X * Find a tag in the "tags" file.
X * Sets "tagfile" to the name of the file containing the tag,
X * and "tagpattern" to the search pattern which should be used
X * to find the tag.
X */
X	public int
Xfindtag(tag)
X	register char *tag;
X{
X	register char *p;
X	register FILE *f;
X	register int taglen;
X	int search_char;
X	static char tline[200];
X
X	if ((f = fopen(tags, "r")) == NULL)
X	{
X		error("No tags file", NULL_PARG);
X		tagfile = NULL;
X		return;
X	}
X
X	taglen = strlen(tag);
X
X	/*
X	 * Search the tags file for the desired tag.
X	 */
X	while (fgets(tline, sizeof(tline), f) != NULL)
X	{
X		if (strncmp(tag, tline, taglen) != 0 || !WHITESP(tline[taglen]))
X			continue;
X
X		/*
X		 * Found it.
X		 * The line contains the tag, the filename and the
X		 * pattern, separated by white space.
X		 * The pattern is surrounded by a pair of identical
X		 * search characters.
X		 * Parse the line and extract these parts.
X		 */
X		tagfile = tagpattern = NULL;
X
X		/*
X		 * Skip over the whitespace after the tag name.
X		 */
X		for (p = tline;  !WHITESP(*p) && *p != '\0';  p++)
X			continue;
X		while (WHITESP(*p))
X			p++;
X		if (*p == '\0')
X			/* File name is missing! */
X			continue;
X
X		/*
X		 * Save the file name.
X		 * Skip over the whitespace after the file name.
X		 */
X		tagfile = p;
X		while (!WHITESP(*p) && *p != '\0')
X			p++;
X		*p++ = '\0';
X		while (WHITESP(*p))
X			p++;
X		if (*p == '\0')
X			/* Pattern is missing! */
X			continue;
X
X		/*
X		 * Save the pattern.
X		 * Skip to the end of the pattern.
X		 * Delete the initial "^" and the final "$" from the pattern.
X		 */
X		search_char = *p++;
X		if (*p == '^')
X			p++;
X		tagpattern = p;
X		while (*p != search_char && *p != '\0')
X			p++;
X		if (p[-1] == '$')
X			p--;
X		*p = '\0';
X
X		fclose(f);
X		return;
X	}
X	fclose(f);
X	error("No such tag in tags file", NULL_PARG);
X	tagfile = NULL;
X}
X
X/*
X * Search for a tag.
X * This is a stripped-down version of search().
X * We don't use search() for several reasons:
X *   -	We don't want to blow away any search string we may have saved.
X *   -	The various regular-expression functions (from different systems:
X *	regcmp vs. re_comp) behave differently in the presence of 
X *	parentheses (which are almost always found in a tag).
X */
X	public int
Xtagsearch()
X{
X	POSITION pos, linepos;
X	int linenum;
X	char *line;
X
X	pos = ch_zero();
X	linenum = find_linenum(pos);
X
X	for (;;)
X	{
X		/*
X		 * Get lines until we find a matching one or 
X		 * until we hit end-of-file.
X		 */
X		if (sigs)
X			return (1);
X
X		/*
X		 * Read the next line, and save the 
X		 * starting position of that line in linepos.
X		 */
X		linepos = pos;
X		pos = forw_raw_line(pos, &line);
X		if (linenum != 0)
X			linenum++;
X
X		if (pos == NULL_POSITION)
X		{
X			/*
X			 * We hit EOF without a match.
X			 */
X			error("Tag not found", NULL_PARG);
X			return (1);
X		}
X
X		/*
X		 * If we're using line numbers, we might as well
X		 * remember the information we have now (the position
X		 * and line number of the current line).
X		 */
X		if (linenums)
X			add_lnum(linenum, pos);
X
X		/*
X		 * Test the line to see if we have a match.
X		 * Use strncmp because the pattern may be
X		 * truncated (in the tags file) if it is too long.
X		 */
X		if (strncmp(tagpattern, line, strlen(tagpattern)) == 0)
X			break;
X	}
X
X	jump_loc(linepos, jump_sline);
X	return (0);
X}
X
X#endif
END_OF_FILE
echo shar: Extracting \"ttyin.c\"
sed "s/^X//" >'ttyin.c' <<'END_OF_FILE'
X/*
X * Routines dealing with getting input from the keyboard (i.e. from the user).
X */
X
X#include "less.h"
X#if __MSDOS__
X#include <io.h>
X#include <stdio.h>
X#include <fcntl.h>
X#include <signal.h>
X#endif
X
Xstatic int tty;
X
X/*
X * Open keyboard for input.
X */
X	public void
Xopen_getchr()
X{
X#if __MDDOS__
X	/*
X	 * Open a new handle to CON: in binary mode 
X	 * for unbuffered keyboard read.
X	 */
X	tty = open("CON", O_RDONLY|O_BINARY);
X#else
X	/*
X	 * Just use file descriptor 2, which in Unix
X	 * is usually attached to the screen and keyboard.
X	 */
X	tty = 2;
X#endif
X}
X
X/*
X * Get a character from the keyboard.
X */
X	public int
Xgetchr()
X{
X	char c;
X	int result;
X
X	do
X	{
X		result = iread(tty, &c, sizeof(char));
X		if (result == READ_INTR)
X			return (READ_INTR);
X		if (result < 0)
X		{
X			/*
X			 * Don't call error() here,
X			 * because error calls getchr!
X			 */
X			quit(1);
X		}
X#if __MSDOS__
X		/*
X		 * In raw read, we don't see ^C so look here for it.
X		 */
X		if (c == '\003')
X			raise(SIGINT);
X#endif
X		/*
X		 * Various parts of the program cannot handle
X		 * an input character of '\0'.
X		 * If a '\0' was actually typed, convert it to '\200' here.
X		 */
X		if (c == '\0')
X			c = '\200';
X	} while (result != 1);
X
X	return (c);
X}
END_OF_FILE
echo shar: Extracting \"version.c\"
sed "s/^X//" >'version.c' <<'END_OF_FILE'
X/*
X *		less
X *	Copyright (c) 1984,1985,1989  Mark Nudelman
X *
X *	This program may be freely used and/or modified, 
X *	with the following provisions:
X *	1. This notice and the above copyright notice must remain intact.
X *	2. Neither this program, nor any modification of it,
X *	   may be sold for profit without written consent of the author.
X *
X *	 ---------------------------------------------------------------
X *	|  Special note to the person who ported "less" to the Amiga:	|
X *	|  If you're going to be vain enough to splash your name on	|
X *	|  the screen every time someone runs less, you might at	|
X *	|  least credit the author.					|
X *	 ---------------------------------------------------------------
X *
X *	This program is a paginator similar to "more", 
X *	but allows you to move both forward and backward in the file.  
X *	Commands are based on "more" and "vi".
X *
X *	----------------------- CHANGES ---------------------------------
X *
X *	    Allowed use on standard input		1/29/84   markn
X *	    Added E, N, P commands			2/1/84    markn
X *	    Added '=' command, 'stop' signal handling	4/17/84   markn
X *	    Added line folding				4/20/84   markn
X *	v2: Fixed '=' command to use BOTTOM_PLUS_ONE, 
X *	    instead of TOP, added 'p' & 'v' commands	4/27/84   markn
X *	v3: Added -m and -t options, '-' command	5/3/84    markn
X *	v4: Added LESS environment variable		5/3/84    markn
X *	v5: New comments, fixed '-' command slightly	5/3/84    markn
X *	v6: Added -Q, visual bell			5/15/84   markn
X *	v7: Fixed jump_back(n) bug: n should count real
X *	    lines, not folded lines.  Also allow number
X *	    on G command.				5/24/84   markn
X *	v8: Re-do -q and -Q commands			5/30/84   markn
X *	v9: Added "+<cmd>" argument			9/25/84   markn
X *	v10: Fixed bug in -b<n> argument processing	10/10/84  markn
X *	v11: Made error() ring bell if \n not entered.	10/18/84  markn
X *	-----------------------------------------------------------------
X *	v12: Reorganized signal handling and made
X *	     portable to 4.2bsd.			2/13/85   mark
X *	v13: Reword error message for '-' command.	2/16/85   mark
X *	v14: Added -bf and -bp variants of -b.		2/22/85   mark
X *	v15: Miscellaneous changes.			2/25/85   mark
X *	v16: Added -u flag for backspace processing.	3/13/85   mark
X *	v17: Added j and k commands, 
X *		changed -t default.			4/13/85   mark
X *	v18: Rewrote signal handling code.		4/20/85   mark
X *	v19: Got rid of "verbose" eq_message().		5/2/85    mark
X *	     Made search() scroll in some cases.
X *	v20: Fixed screen.c ioctls for System V.	5/21/85   mark
X *	v21: Fixed some first_cmd bugs.			5/23/85   mark
X *	v22: Added support for no RECOMP nor REGCMP.	5/24/85   mark
X * 	v23: Miscellanous changes and prettying up.	5/25/85   mark
X *		Posted to USENET.
X *	-----------------------------------------------------------------
X *      v24: Added ti,te terminal init & de-init       6/3/85 Mike Kersenbrock
X *	v25: Added -U flag, standout mode underlining.	6/8/85    mark
X *	v26: Added -M flag.				6/9/85    mark
X *	     Use underline termcap (us) if it exists.
X *	v27: Renamed some variables to make unique in	6/15/85   mark
X *	     6 chars.  Minor fix to -m.
X *	v28: Fixed right margin bug.			6/28/85   mark
X *	v29: Incorporated M.Rose's changes to signal.c	6/28/85   mark
X *	v30: Fixed stupid bug in argument processing.	6/29/85   mark
X *	v31: Added -p flag, changed repaint algorithm.  7/15/85   mark
X *	     Added kludge for magic cookie terminals.
X *	v32: Added cat_file if output not a tty.	7/16/85   mark
X *	v33: Added -e flag and EDITOR.			7/23/85   mark
X *	v34: Added -s flag.				7/26/85   mark
X *	v35: Rewrote option handling; added option.c.	7/27/85   mark
X *	v36: Fixed -e flag to work if not last file.	7/29/85   mark
X *	v37: Added -x flag.				8/10/85   mark
X *	v38: Changed prompting; created prompt.c.	8/19/85   mark
X *	v39: (Not -p) does not initially clear screen.	8/24/85   mark
X *	v40: Added "skipping" indicator in forw().	8/26/85   mark
X *		Posted to USENET.
X *	-----------------------------------------------------------------
X *	v41: ONLY_RETURN, control char commands,	9/17/85   mark
X *	     faster search, other minor fixes.
X *	v42: Added ++ command line syntax;		9/25/85   mark
X *	     ch_fsize for pipes.
X *	v43: Added -h flag, changed prim.c algorithms.	10/15/85  mark
X *	v44: Made END print in all cases of eof;	10/16/85  mark
X *	     ignore SIGTTOU after receiving SIGTSTP.
X *	v45: Never print backspaces unless -u.		10/16/85  mark
X *	v46: Backwards scroll in jump_loc.		10/24/85  mark
X *	v47: Fixed bug in edit(): *first_cmd==0		10/30/85  mark
X *	v48: Use TIOCSETN instead of TIOCSETP.		11/16/85  mark
X *	     Added marks (m and ' commands).
X *		Posted to USENET.
X *	-----------------------------------------------------------------
X *	v49: Fixed bug: signal didn't clear mcc.	1/9/86    mark
X *	v50: Added ' (quote) to gomark.			1/15/86   mark
X *	v51: Added + cmd, fixed problem if first_cmd
X *	     fails, made g cmd sort of "work" on pipes
X *	     even if bof is no longer buffered.		1/16/86   mark
X *	v52: Made short files work better.		1/17/86   mark
X *	v53: Added -P option.				1/20/86   mark
X *	v54: Changed help to use HELPFILE.		1/20/86   mark
X *	v55: Messages work better if not tty output.	1/23/86   mark
X *	v56: Added -l option.				1/24/86   mark
X *	v57: Fixed -l to get confirmation before
X *	     overwriting an existing file.		1/31/86   mark
X *	v58: Added filename globbing.			8/28/86   mark
X *	v59: Fixed some bugs with very long filenames.	9/15/86   mark
X *	v60: Incorporated changes from Leith (Casey)
X *	     Leedom for boldface and -z option.		9/26/86   mark
X *	v61: Got rid of annoying repaints after ! cmd.	9/26/86   mark
X *		Posted to USENET.
X *	-----------------------------------------------------------------
X *	v62: Added is_directory(); change -z default to
X *	     -1 instead of 24; cat-and-exit if -e and
X *	     file is less than a screenful.		12/23/86  mark
X *	v63: Fixed bug in cat-and-exit if > 1 file.	1/8/87    mark
X *	v64: Changed puts/putstr, putc/putchr, 
X *	     getc/getchr to avoid name conflict with 
X *	     stdio functions.				1/12/87  mark
X *	v65: Allowed '-' command to change NUMBER
X *	     valued options (thanks to Gary Puckering)	1/26/87  mark
X *	v66: Fixed bug: prepaint should use force=1.	2/13/87  mark
X *	v67: Added !! and % expansion to ! command.	2/24/87  mark
X *	v68: Added SIGWINCH and TIOCGWINSZ support;
X *	     changed is_directory to bad_file.
X *	     (thanks to J. Robert Ward)			2/25/87  mark
X *	v69: Added SIGWIND and WIOCGETD (for Unix PC).	2/25/87  mark
X *	v70: Changed help cmd from 'h' to 'H'; better 
X *	     error msgs in bad_file, errno_message.	3/13/87  mark
X *	v71: Changed -p to -c, made triple -c/-C
X *	     for clear-eol like more's -c.		5/11/87  mark
X *	v72: Added -E, -L, use $SHELL in lsystem().	6/26/87  mark
X *	     (thanks to Steve Spearman)
X *	v73: Allow Examine "#" for previous file.	6/26/87  mark
X *		Posted to USENET 8/25/87.
X *	-----------------------------------------------------------------
X *	v74: Fix conflict in EOF symbol with stdio.h,	9/18/87  mark
X *	     Make os.c more portable to BSD.
X *	v75: Fix problems in get_term (thanks to 	9/23/87  mark
X *	     Paul Eggert); new backwards scrolling in
X *	     jump_loc (thanks to Marion Hakanson).
X *	v76: Added -i flag; allow single "!" to		9/23/87  mark
X *	     invoke a shell (thanks to Franco Barber).
X *	v77: Added -n flag and line number support.	9/24/87  mark
X *	v78: Fixed problem with prompts longer than	9/25/87  mark
X *	     the screen width.	
X *	v79: Added the _ command.			9/29/87  mark
X *	v80: Allow signal to break out of linenum scan.	10/6/87  mark
X *	v81: Allow -b to be changed from within less.	10/6/87  mark
X *	v82: Add cmd_decode to use a table for key	10/7/87  mark
X *	     binding (thanks to David Nason).
X *	v83: Allow .less file for user-defined keys.	10/9/87  mark
X *	v84: Fix -e/-E problems (thanks to Felix Lee).	10/11/87 mark
X *	v85: Search now keeps track of line numbers.	10/15/87 mark
X *	v86: Added -B option and autobuf; fixed		10/20/87 mark
X *	     "pipe error" bug.
X *	v87: Fix bug re BSD signals while reading file.	3/1/88   mark
X *	v88: Use new format for -P option (thanks to	3/12/88  mark
X *	     der Mouse), allow "+-c" without message,
X *	     fix bug re BSD hangup.
X *	v89: Turn off line numbers if linenum scan	3/18/88  mark
X *	     is interrupted.
X *	v90: Allow -P from within less.			3/30/88  mark
X *	v91: Added tags file support (new -t option)	3/30/88  mark
X *	     (thanks to Brian Campbell).
X *	v92: Added -+option syntax.			4/4/88   mark
X *	v93: Add support for slow input (thanks to	4/11/88  mark
X *	     Joe Orost & apologies for taking almost
X *	     3 years to get this in!)
X *	v94: Redo reading/signal stuff.			4/11/88  mark
X *	v95: Repaint screen better after signal.	4/20/88  mark
X *	v96: Add /! and ?! commands.			4/21/88  mark
X *	v97: Allow -l/-L from within less.		5/17/88  mark
X *	     Eliminate some static arrays (use calloc).
X *		Posted to USENET.
X *	-----------------------------------------------------------------
X *	v98: Fix incorrect calloc call; uninitialized	10/14/88 mark
X *	     var in exec_mca; core dump on unknown TERM.
X *	     Make v cmd work if past last line of file.
X *	     Fix some signal bugs.
X *	v99: Allow space between -X and string,		10/29/88 mark
X *	     when X is a string-valued option.
X *	v100: Fix globbing bug when $SHELL not set;	1/5/89   mark
X *	      allow spaces after -t command.
X *	v101: Fix problem with long (truncated) lines	1/6/89   mark
X *	      in tags file (thanks to Neil Dixon).
X *	v102: Fix bug with E# when no prev file;	1/6/89   mark
X *	      allow spaces after -l command.
X *	v103: Add -N, -f and -? options.  Add z and w	3/14/89  mark
X *	      commands.  Add %L for prompt strings.
X *	v104: Added EDITPROTO.				3/16/89  mark
X *	v105: Fix bug in find_linenum which cached	3/20/89  mark
X *	      incorrectly on long lines.
X *	v106: Added -k option and multiple lesskey      3/31/89  mark
X *	      files.
X *	v107: Add 8-bit char support and -g option.	4/27/89  mark
X *	      Split option code into 3 files.
X *	v108: Allocate position table dynamically       5/5/89   mark
X *	      (thanks to Paul Eggert); change % command
X *	      from "percent" to vi-style brace finder.
X *	v109: Added ESC-% command, split prim.c.	5/10/89  mark
X *	v110: Fixed bug in + option; fixed repaint bug	5/24/89  mark
X *	      under Sun windows (thanks to Paul Eggert).
X *	v111: Generalized # and % expansion; use 	5/25/89  mark
X *	      calloc for some error messages.
X *	v112: Get rid of ESC-%, add {}()[] commands.	5/30/89  mark
X *	v113: Optimize lseeks (thanks to Paul Eggert).	5/31/89  mark
X *	v114: Added ESC-/ and ESC-/! commands.		7/25/89  mark
X *	v115: Added ESC-n command.			7/26/89  mark
X *	v116: Added find_pos to optimize g command.	7/31/89  mark
X *	v117: Change -f option to -r.			8/1/89   mark
X *	v118: Save positions for all previous files,	8/2/89   mark
X *	      not just the immediately previous one.
X *	v119: Save marks across file boundaries.	8/7/89   mark
X *	      Add file handle stuff.
X *	v120: Add :ta command.				8/11/89  mark
X *	v121: Add -f option.				8/16/89  mark
X *	v122: Fix performance with many buffers.	8/30/89  mark
X *	v123: Verbose prompts for string options.	8/31/89  mark
X *		Posted beta to USENET.
X *	-----------------------------------------------------------------
X *	v124: Reorganize search commands,		9/18/89  mark
X *	      N = rev, ESC-n = span, add ESC-N.
X *	v125: Fix tab bug (thanks to Alex Liu).		9/18/89  mark
X *	      Fix EOF bug when both -w and -c.
X *	v126: Add -j option.				10/25/89 mark
X *	v127: Fix problems with blank lines before BOF.	10/27/89 mark
X *	v128: Add %bj, etc. to prompt strings.		10/27/89 mark
X *	v129: Add -+,-- commands; add set-option and	11/3/89  mark
X *	      unset-option to lesskey.
X *	v130: Generalize A_EXTRA to string, remove	11/6/89  mark
X *	      set-option, unset-option from lesskey.
X *	v131: Changed name of EDITPROTO to LESSEDIT.	11/7/89  mark
X *	v132: Allow editing of command prefix.		11/8/89  mark
X *	v133: Add -y option (thanks to Jeff Sullivan).	11/16/89 mark
X *	v134: Glob filenames in the -l command.		12/1/89  mark
X *	v135: Combined {}()[] commands into one, and	12/5/89  mark
X *	      added ESC-^F and ESC-^B commands.
X *	v136: Added -S, -R flags.  Added | command.	1/20/90  mark
X *	      Added warning for binary files. (thanks 
X *	      to Richard Brittain and J. Sullivan).
X *	v137: Rewrote horrible pappend code.		1/21/90  mark
X *	      Added * notation for hi-bit chars.
X *	v138: Fix magic cookie terminal handling.	1/24/90  mark
X *	      Get rid of "cleanup" loop in ch_get.
X *	v139: Added MSDOS support.  (many thanks	1/27/90  mark
X *	      to Richard Brittain).
X *	v140: Editing a new file adds it to the		2/7/90   mark
X *	      command line list.
X *	v141: Add edit_list for editing >1 file.	2/8/90   mark
X *	v142: Add :x command.				2/10/90  mark
X *	v143: Add * and @ modifies to search cmds.	2/11/90  mark
X *	      Change ESC-/ cmd from /@* to /*.
X *	v144: Messed around with ch_zero; 		3/1/90   mark
X *	      no real change.
X *	v145: Added -R and -v/-V for MSDOS;		3/2/90   mark
X *	      renamed FILENAME to avoid conflict.
X *	v146: Pull cmdbuf functions out of command.c	3/5/90   mark
X *	v147: Implement ?@; fix multi-file edit bugs.	3/7/90   mark
X *	v148: Fixed bug in :e<file> then :e#.		3/29/90  mark
X *	v149: Change error,ierror,query to use PARG.	4/3/90   mark
X *	v150: Add LESS_CHARSET, LESS_CHARDEF.		4/6/90   mark
X *	v151: Remove -g option; clean up ispipe.	4/13/90  mark
X *	v152: lsystem() closes input file, for		4/14/90  mark
X *	      editors which require exclusive open.
X *	v153: Fix bug if SHELL unset; 			4/18/90  mark
X *	      fix bug in overstrike control char.
X *	v154: Output to fd 2 via buffer.		4/25/90  mark
X *	v155: Ignore -i if uppercase in pattern		4/30/90  mark
X *	      (thanks to Michael Rendell.)
X *	v156: Remove scroll limits in forw() & back();	5/3/90   mark
X *	      causes problems with -c.
X *	v157: Forward search starts at next real line	5/4/90   mark
X *	      (not screen line) after jump target.
X *	v158: Added F command.				6/14/90  mark
X *	v159: Fix bug in exiting: output not flushed.	7/29/90  mark
X *	v160: Clear screen before initial output w/ -c.	7/29/90  mark
X *	v161: Add -T flag.				7/29/90  mark
X *	v162: Fix bug with +F on command line.		8/14/90  mark
X *	v163: Added LESSBINFMT variable.		8/21/90  mark
X *	v164: Added -p, LINES, COLUMNS and		9/5/90   mark
X *	      unset mark ' == BOF, for 1003.2 D5.
X *	v165: At EOF with -c set, don't display empty	9/6/90   mark
X *	      screen when try to page forward.
X *	v166: Fix G when final line in file wraps.	9/6/90   mark
X *	v167: Translate CR/LF -> LF for 1003.2.		9/11/90  mark
X *	v168: Return to curr file if "tag not found".	9/13/90  mark
X *	v169: G goes to EOF even if file has grown.	12/12/90 mark
X *	v170: Add optimization for BSD _setjmp;		1/17/91  mark
X *	      fix #include ioctl.h TERMIO problem.
X *	      (thanks to Paul Eggert)
X */
X
Xchar version[] = "@(#) less  version 170";
END_OF_FILE
echo shar: Extracting \"funcs.h\"
sed "s/^X//" >'funcs.h' <<'END_OF_FILE'
X	public void end_logfile ();
X	public void sync_logfile ();
X	public int ch_seek ();
X	public int ch_end_seek ();
X	public int ch_beg_seek ();
X	public POSITION ch_length ();
X	public POSITION ch_tell ();
X	public int ch_forw_get ();
X	public int ch_back_get ();
X	public int ch_nbuf ();
X	public void ch_flush ();
X	public void ch_pipe ();
X	public void ch_nonpipe ();
X	public void cmd_reset ();
X	public int len_cmdbuf ();
X	public int cmd_erase ();
X	public int cmd_char ();
X	public int cmd_int ();
X	public void cmd_putstr ();
X	public char * get_cmdbuf ();
X	public void ungetcc ();
X	public void ungetsc ();
X	public void commands ();
X	public int cmd_decode ();
X	public int add_cmdtable ();
X	public void add_hometable ();
X	public void help ();
X	public POSITION forw_line ();
X	public POSITION back_line ();
X	public void prewind ();
X	public void plinenum ();
X	public int pappend ();
X	public void pdone ();
X	public int gline ();
X	public void null_line ();
X	public POSITION forw_raw_line ();
X	public POSITION back_raw_line ();
X	public void clr_linenum ();
X	public void add_lnum ();
X	public int find_linenum ();
X	public POSITION find_pos ();
X	public int currline ();
X	public void strtcpy ();
X	public char * save ();
X	public VOID_POINTER ecalloc ();
X	public char * skipsp ();
X	public void quit ();
X	public int edit ();
X	public void edit_list ();
X	public int edit_first ();
X	public int edit_last ();
X	public int edit_next ();
X	public int edit_prev ();
X	public int edit_index ();
X	public void cat_file ();
X	public void use_logfile ();
X	public void scan_option ();
X	public void toggle_option ();
X	public int single_char_option ();
X	public char * opt_prompt ();
X	public int isoptpending ();
X	public void nopendopt ();
X	public int getnum ();
X	public void opt_o ();
X	public void opt__O ();
X	public void opt_l ();
X	public void opt__L ();
X	public void opt_k ();
X	public void opt_t ();
X	public void opt__T ();
X	public void opt_p ();
X	public void opt__P ();
X	public void opt_b ();
X	public void opt_v ();
X	public void opt_W ();
X	public void opt_query ();
X	public void init_option ();
X	public struct option * findopt ();
X	public int iread ();
X	public void intread ();
X	public long get_time ();
X	public char * errno_message ();
X	public char * errno_message ();
X	public void init_charset ();
X	public int binary_char ();
X	public int control_char ();
X	public char * prchar ();
X	public char * homefile ();
X	public char * find_helpfile ();
X	public char * fexpand ();
X	public char * glob ();
X	public char * glob ();
X	public char * bad_file ();
X	public POSITION filesize ();
X	public char * bad_file ();
X	public POSITION filesize ();
X	public void lsystem ();
X	public int pipe_mark ();
X	public int pipe_data ();
X	public void put_line ();
X	public void flush ();
X	public void putchr ();
X	public void putstr ();
X	public void error ();
X	public void ierror ();
X	public int query ();
X	public POSITION position ();
X	public void add_forw_pos ();
X	public void add_back_pos ();
X	public void pos_clear ();
X	public void pos_init ();
X	public int onscreen ();
X	public int empty_screen ();
X	public int empty_lines ();
X	public void get_scrpos ();
X	public int adjsline ();
X	public IFILE next_ifile ();
X	public IFILE prev_ifile ();
X	public int nifile ();
X	public IFILE get_ifile ();
X	public char * get_filename ();
X	public int get_index ();
X	public void store_pos ();
X	public void get_pos ();
X	public void match_brac ();
X	public void forw ();
X	public void back ();
X	public void forward ();
X	public void backward ();
X	public int get_back_scroll ();
X	public void jump_forw ();
X	public void jump_back ();
X	public void repaint ();
X	public void jump_percent ();
X	public void jump_line_loc ();
X	public void jump_loc ();
X	public int search ();
X	public void init_mark ();
X	public int badmark ();
X	public void setmark ();
X	public void lastmark ();
X	public void gomark ();
X	public POSITION markpos ();
X	public void init_prompt ();
X	public char * pr_expand ();
X	public char * eq_message ();
X	public char * pr_string ();
X	public void raw_mode ();
X	public void get_scrsize ();
X	public void get_term ();
X	public void init ();
X	public void deinit ();
X	public void home ();
X	public void add_line ();
X	public void lower_left ();
X	public void bell ();
X	public void vbell ();
X	public void clear ();
X	public void clear_eol ();
X	public void so_enter ();
X	public void so_exit ();
X	public void ul_enter ();
X	public void ul_exit ();
X	public void bo_enter ();
X	public void bo_exit ();
X	public void bl_enter ();
X	public void bl_exit ();
X	public void backspace ();
X	public void putbs ();
X	public void fake_interrupt ();
X	public HANDLER winch ();
X	public HANDLER winch ();
X	public void init_signals ();
X	public void psignals ();
X	public int findtag ();
X	public int tagsearch ();
X	public void open_getchr ();
X	public int getchr ();
END_OF_FILE



More information about the Alt.sources mailing list