Path: utzoo!utgpu!cs.utexas.edu!usc!apple!amdcad!pyramid!ctnews!unix386!mark From: mark@unix386.Convergent.COM (Mark Nudelman) Newsgroups: alt.sources Subject: less (part 6 of 6) Message-ID: <6427@unix386.Convergent.COM> Date: 6 Mar 91 00:14:56 GMT Organization: Unisys/Convergent, San Jose, CA Lines: 2339 #! /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 X#include X#endif X X#if TERMIO X#include X#else X#include X#endif X X#if !TERMIO && defined(TIOCGWINSZ) X#include 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 X#ifdef SIGPHONE X#include 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 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 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 X#include X#include X#include 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 "+" argument 9/25/84 markn X * v10: Fixed bug in -b 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 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