head 1.9; access; symbols RELENG_4_0_0_RELEASE:1.8 RELENG_4:1.8.0.2 RELENG_4_BP:1.8 RELENG_3_4_0_RELEASE:1.7 RELENG_3_3_0_RELEASE:1.7 RELENG_3_2_PAO:1.7.0.4 RELENG_3_2_PAO_BP:1.7 RELENG_3_2_0_RELEASE:1.7 RELENG_3_1_0_RELEASE:1.7 RELENG_3:1.7.0.2 RELENG_3_BP:1.7 RELENG_2_2_8_RELEASE:1.5.2.1 RELENG_3_0_0_RELEASE:1.7 RELENG_2_2_7_RELEASE:1.5.2.1 RELENG_2_2_6_RELEASE:1.5 RELENG_2_2_5_RELEASE:1.5 bsd_44_lite_2:1.1.1.1 RELENG_2_2_2_RELEASE:1.5 RELENG_2_2_1_RELEASE:1.5 RELENG_2_2_0_RELEASE:1.5 RELENG_2_1_7_RELEASE:1.3.4.1 RELENG_2_1_6_1_RELEASE:1.3.4.1 RELENG_2_1_6_RELEASE:1.3.4.1 RELENG_2_2:1.5.0.2 RELENG_2_2_BP:1.5 RELENG_2_1_5_RELEASE:1.3.4.1 RELENG_2_1_0_RELEASE:1.3.4.1 RELENG_2_1_0:1.3.0.4 RELENG_2_1_0_BP:1.3 RELENG_2_0_5_RELEASE:1.3 RELENG_2_0_5:1.3.0.2 RELENG_2_0_5_BP:1.3 RELENG_2_0_5_ALPHA:1.2 RELEASE_2_0:1.2 BETA_2_0:1.2 ALPHA_2_0:1.2.0.2 bsd_44_lite:1.1.1.1 CSRG:1.1.1; locks; comment @ * @; 1.9 date 2000.05.12.04.00.23; author hoek; state Exp; branches; next 1.8; 1.8 date 99.09.03.22.31.19; author hoek; state Exp; branches; next 1.7; 1.7 date 98.07.26.16.15.26; author hoek; state Exp; branches; next 1.6; 1.6 date 98.02.20.04.13.29; author jb; state Exp; branches; next 1.5; 1.5 date 95.08.05.21.25.28; author ache; state Exp; branches 1.5.2.1; next 1.4; 1.4 date 95.08.04.06.58.45; author ache; state Exp; branches; next 1.3; 1.3 date 95.05.30.06.32.36; author rgrimes; state Exp; branches 1.3.4.1; next 1.2; 1.2 date 94.09.22.01.19.12; author ache; state Exp; branches; next 1.1; 1.1 date 94.05.27.12.30.45; author rgrimes; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 94.05.27.12.30.46; author rgrimes; state Exp; branches; next ; 1.3.4.1 date 95.09.02.17.43.08; author davidg; state Exp; branches; next ; 1.5.2.1 date 98.07.17.04.19.52; author jkh; state Exp; branches; next ; desc @@ 1.9 log @Create magic variables that return termcap(5) strings for function keys. @ text @/* * Copyright (c) 1988 Mark Nudleman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static char sccsid[] = "@@(#)screen.c 8.2 (Berkeley) 4/20/94"; #endif /* not lint */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ /* * Routines which deal with the characteristics of the terminal. * Uses termcap to be as terminal-independent as possible. * * {{ Someday this should be rewritten to use curses. }} */ #include #include #include #include #include #include "less.h" #define TERMIOS 1 #if TERMIO #include #else #if TERMIOS #include #define TAB3 0 #include #else #include #endif #endif #ifdef TIOCGWINSZ #include #else /* * For the Unix PC (ATT 7300 & 3B1): * Since WIOCGETD is defined in sys/window.h, we can't use that to decide * whether to include sys/window.h. Use SIGPHONE from sys/signal.h instead. */ #include #ifdef SIGPHONE #include #endif #endif /* * Strings passed to tputs() to do various terminal functions. */ static char *sc_pad, /* Pad string */ *sc_home, /* Cursor home */ *sc_addline, /* Add line, scroll down following lines */ *sc_lower_left, /* Cursor to last line, first column */ *sc_move, /* General cursor positioning */ *sc_clear, /* Clear screen */ *sc_eol_clear, /* Clear to end of line */ *sc_s_in, /* Enter standout (highlighted) mode */ *sc_s_out, /* Exit standout mode */ *sc_u_in, /* Enter underline mode */ *sc_u_out, /* Exit underline mode */ *sc_b_in, /* Enter bold mode */ *sc_b_out, /* Exit bold mode */ *sc_backspace, /* Backspace cursor */ *sc_init, /* Startup terminal initialization */ *sc_deinit, /* Exit terminal de-intialization */ *sc_keypad_on, /* Enter keypad mode */ *sc_keypad_off; /* Exit keypad mode */ int auto_wrap; /* Terminal does \r\n when write past margin */ int ignaw; /* Terminal ignores \n immediately after wrap */ /* The user's erase and line-kill chars */ int retain_below; /* Terminal retains text below the screen */ int erase_char, kill_char, werase_char; int sc_width, sc_height = -1; /* Height & width of screen */ int bo_width, be_width; /* Printing width of boldface sequences */ int ul_width, ue_width; /* Printing width of underline sequences */ int so_width, se_width; /* Printing width of standout sequences */ int mode_flags = 0; #define M_SO 1 #define M_UL 2 #define M_BO 4 /* * These two variables are sometimes defined in, * and needed by, the termcap library. * It may be necessary on some systems to declare them extern here. */ /*extern*/ speed_t ospeed; /* Terminal output baud rate */ /*extern*/ char PC; /* Pad character */ extern int back_scroll; /* * Change terminal to "raw mode", or restore to "normal" mode. * "Raw mode" means * 1. An outstanding read will complete on receipt of a single keystroke. * 2. Input is not echoed. * 3. On output, \n is mapped to \r\n. * 4. \t is NOT expanded into spaces. * 5. Signal-causing characters such as ctrl-C (interrupt), * etc. are NOT disabled. * It doesn't matter whether an input \n is mapped to \r, or vice versa. */ raw_mode(on) int on; { #if TERMIO || TERMIOS #if TERMIO struct termio s; static struct termio save_term; #else struct termios s; static struct termios save_term; #endif if (on) { /* * Get terminal modes. */ #if TERMIO (void)ioctl(2, TCGETA, &s); #else tcgetattr(2, &s); #endif /* * Save modes and set certain variables dependent on modes. */ save_term = s; #if TERMIO ospeed = s.c_cflag & CBAUD; #else /* more work needed here */ #endif erase_char = s.c_cc[VERASE]; kill_char = s.c_cc[VKILL]; werase_char = s.c_cc[VWERASE]; /* * Set the modes to the way we want them. */ s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL); s.c_oflag |= (OPOST|ONLCR|TAB3); #if TERMIO s.c_oflag &= ~(OCRNL|ONOCR|ONLRET); #endif s.c_cc[VMIN] = 1; s.c_cc[VTIME] = 0; } else { /* * Restore saved modes. */ s = save_term; } #if TERMIO (void)ioctl(STDERR_FILENO, TCSETAW, &s); #else tcsetattr(STDERR_FILENO, TCSADRAIN, &s); #endif #else struct sgttyb s; struct ltchars l; static struct sgttyb save_term; if (on) { /* * Get terminal modes. */ (void)ioctl(STDERR_FILENO, TIOCGETP, &s); (void)ioctl(STDERR_FILENO, TIOCGLTC, &l); /* * Save modes and set certain variables dependent on modes. */ save_term = s; ospeed = s.sg_ospeed; erase_char = s.sg_erase; kill_char = s.sg_kill; werase_char = l.t_werasc; /* * Set the modes to the way we want them. */ s.sg_flags |= CBREAK; s.sg_flags &= ~(ECHO|XTABS); } else { /* * Restore saved modes. */ s = save_term; } (void)ioctl(STDERR_FILENO, TIOCSETN, &s); #endif } /* * Get terminal capabilities via termcap. */ get_term() { char termbuf[2048]; char *sp; char *term; int hard; #ifdef TIOCGWINSZ struct winsize w; #else #ifdef WIOCGETD struct uwdata w; #endif #endif static char sbuf[1024]; /* * Find out what kind of terminal this is. */ if ((term = getenv("TERM")) == NULL) term = "unknown"; if (tgetent(termbuf, term) <= 0) (void)strcpy(termbuf, "dumb:co#80:hc:"); /* * Get size of the screen. */ #ifdef TIOCGWINSZ if (ioctl(STDERR_FILENO, TIOCGWINSZ, &w) == 0 && w.ws_row > 0) sc_height = w.ws_row; else #else #ifdef WIOCGETD if (ioctl(STDERR_FILENO, WIOCGETD, &w) == 0 && w.uw_height > 0) sc_height = w.uw_height/w.uw_vs; else #endif #endif sc_height = tgetnum("li"); hard = (sc_height < 0 || tgetflag("hc")); if (hard) { /* Oh no, this is a hardcopy terminal. */ sc_height = 24; } #ifdef TIOCGWINSZ if (ioctl(STDERR_FILENO, TIOCGWINSZ, &w) == 0 && w.ws_col > 0) sc_width = w.ws_col; else #ifdef WIOCGETD if (ioctl(STDERR_FILENO, WIOCGETD, &w) == 0 && w.uw_width > 0) sc_width = w.uw_width/w.uw_hs; else #endif #endif sc_width = tgetnum("co"); if (sc_width < 0) sc_width = 80; (void) setvari("_sc_height", (long) sc_height - 1); (void) setvari("_sc_width", (long) sc_width); auto_wrap = tgetflag("am"); ignaw = tgetflag("xn"); retain_below = tgetflag("db"); /* * Assumes termcap variable "sg" is the printing width of * the standout sequence, the end standout sequence, * the underline sequence, the end underline sequence, * the boldface sequence, and the end boldface sequence. */ if ((so_width = tgetnum("sg")) < 0) so_width = 0; be_width = bo_width = ue_width = ul_width = se_width = so_width; /* * Get various string-valued capabilities. */ sp = sbuf; sc_pad = tgetstr("pc", &sp); if (sc_pad != NULL) PC = *sc_pad; sc_init = tgetstr("ti", &sp); if (sc_init == NULL) sc_init = ""; sc_deinit = tgetstr("te", &sp); if (sc_deinit == NULL) sc_deinit = ""; sc_keypad_on = tgetstr("ks", &sp); if (sc_keypad_on == NULL) sc_keypad_on = ""; sc_keypad_off = tgetstr("ke", &sp); if (sc_keypad_off == NULL) sc_keypad_off = ""; sc_eol_clear = tgetstr("ce", &sp); if (hard || sc_eol_clear == NULL || *sc_eol_clear == '\0') { sc_eol_clear = ""; } sc_clear = tgetstr("cl", &sp); if (hard || sc_clear == NULL || *sc_clear == '\0') { sc_clear = "\n\n"; } sc_move = tgetstr("cm", &sp); if (hard || sc_move == NULL || *sc_move == '\0') { /* * This is not an error here, because we don't * always need sc_move. * We need it only if we don't have home or lower-left. */ sc_move = ""; } sc_s_in = tgetstr("so", &sp); if (hard || sc_s_in == NULL) sc_s_in = ""; sc_s_out = tgetstr("se", &sp); if (hard || sc_s_out == NULL) sc_s_out = ""; sc_u_in = tgetstr("us", &sp); if (hard || sc_u_in == NULL) sc_u_in = sc_s_in; sc_u_out = tgetstr("ue", &sp); if (hard || sc_u_out == NULL) sc_u_out = sc_s_out; sc_b_in = tgetstr("md", &sp); if (hard || sc_b_in == NULL) { sc_b_in = sc_s_in; sc_b_out = sc_s_out; } else { sc_b_out = tgetstr("me", &sp); if (hard || sc_b_out == NULL) sc_b_out = ""; } sc_home = tgetstr("ho", &sp); if (hard || sc_home == NULL || *sc_home == '\0') { if (*sc_move == '\0') { /* * This last resort for sc_home is supposed to * be an up-arrow suggesting moving to the * top of the "virtual screen". (The one in * your imagination as you try to use this on * a hard copy terminal.) */ sc_home = "|\b^"; } else { /* * No "home" string, * but we can use "move(0,0)". */ (void)strcpy(sp, tgoto(sc_move, 0, 0)); sc_home = sp; sp += strlen(sp) + 1; } } sc_lower_left = tgetstr("ll", &sp); if (hard || sc_lower_left == NULL || *sc_lower_left == '\0') { if (*sc_move == '\0') { sc_lower_left = "\r"; } else { /* * No "lower-left" string, * but we can use "move(0,last-line)". */ (void)strcpy(sp, tgoto(sc_move, 0, sc_height-1)); sc_lower_left = sp; sp += strlen(sp) + 1; } } /* * To add a line at top of screen and scroll the display down, * we use "al" (add line) or "sr" (scroll reverse). */ if ((sc_addline = tgetstr("al", &sp)) == NULL || *sc_addline == '\0') sc_addline = tgetstr("sr", &sp); if (hard || sc_addline == NULL || *sc_addline == '\0') { sc_addline = ""; /* Force repaint on any backward movement */ back_scroll = 0; } if (tgetflag("bs")) sc_backspace = "\b"; else { sc_backspace = tgetstr("bc", &sp); if (sc_backspace == NULL || *sc_backspace == '\0') sc_backspace = "\b"; } } /* * Retrieves string (if any) associated with tcap from the termcap. If the * capability is not a string capability, an ascii approximation of the * capability will be returned. Returns NULL if tcap cannot be found. * The returned string is valid until the next call to gettermcap(). */ const char * gettermcap(tcap) char *tcap; { char termbuf[2048]; char *term; static char sbuf[1024]; char *sp = sbuf; int i; /* * Find out what kind of terminal this is. */ if ((term = getenv("TERM")) == NULL) term = "unknown"; if (tgetent(termbuf, term) <= 0) (void)strcpy(termbuf, "dumb:co#80:hc:"); sp = tgetstr(tcap, &sp); if (sp == NULL || !*sp) { sprintf (sbuf, "%d", i=tgetnum(tcap)); if (i == -1) sprintf (sbuf, "%d", tgetflag(tcap)); } return sbuf; } /* * Below are the functions which perform all the * terminal-specific screen manipulation. */ int putchr(); /* * Initialize terminal */ init() { tputs(sc_init, sc_height, putchr); tputs(sc_keypad_on, 1, putchr); } /* * Deinitialize terminal */ deinit() { tputs(sc_deinit, sc_height, putchr); tputs(sc_keypad_off, 1, putchr); } /* * Home cursor (move to upper left corner of screen). */ home() { tputs(sc_home, 1, putchr); } /* * Add a blank line (called with cursor at home). * Should scroll the display down. */ add_line() { tputs(sc_addline, sc_height, putchr); } int short_file; /* if file less than a screen */ lower_left() { if (short_file) { putchr('\r'); flush(); } else tputs(sc_lower_left, 1, putchr); } /* * Ring the terminal bell. */ bell() { putchr('\7'); } /* * Clear the screen. */ clear() { if (mode_flags & M_SO) so_exit(); if (mode_flags & M_UL) ul_exit(); if (mode_flags & M_BO) bo_exit(); tputs(sc_clear, sc_height, putchr); } /* * Clear from the cursor to the end of the cursor's line. * {{ This must not move the cursor. }} */ clear_eol() { if (mode_flags & M_SO) so_exit(); if (mode_flags & M_UL) ul_exit(); if (mode_flags & M_BO) bo_exit(); tputs(sc_eol_clear, 1, putchr); } /* * Begin "standout" (bold, underline, or whatever). */ so_enter() { tputs(sc_s_in, 1, putchr); mode_flags |= M_SO; } /* * End "standout". */ so_exit() { tputs(sc_s_out, 1, putchr); mode_flags &= ~M_SO; } /* * Begin "underline" (hopefully real underlining, * otherwise whatever the terminal provides). */ ul_enter() { tputs(sc_u_in, 1, putchr); mode_flags |= M_UL; } /* * End "underline". */ ul_exit() { tputs(sc_u_out, 1, putchr); mode_flags &= ~M_UL; } /* * Begin "bold" */ bo_enter() { tputs(sc_b_in, 1, putchr); mode_flags |= M_BO; } /* * End "bold". */ bo_exit() { tputs(sc_b_out, 1, putchr); mode_flags &= ~M_BO; } /* * Erase the character to the left of the cursor * and move the cursor left. */ backspace() { /* * Try to erase the previous character by overstriking with a space. */ tputs(sc_backspace, 1, putchr); putchr(' '); tputs(sc_backspace, 1, putchr); } /* * Output a plain backspace, without erasing the previous char. */ putbs() { tputs(sc_backspace, 1, putchr); } @ 1.8 log @Thorough revamp of how input commands are processed. This allows customization of user keys (documentation pending). The only key whose semantics have changed is the capital 'N' key, which now performs a repeat-search in the opposite direction (just like in vi). This commit is a little bulkier than what I had originally planned. I'm not completely happy with the direction it went, but it's definately an improvement, and the alternative is to continue becoming irrelevant compared to GNU less. (Does anyone even _use_ /usr/bin/more these days?) @ text @d39 5 d52 1 d54 4 a57 1 #include d106 3 a108 1 *sc_deinit; /* Exit terminal de-intialization */ d130 1 a130 1 /*extern*/ short ospeed; /* Terminal output baud rate */ a133 2 char *tgetstr(); char *tgoto(); d201 1 a201 1 (void)ioctl(2, TCSETAW, &s); d203 1 a203 1 tcsetattr(2, TCSADRAIN, &s); d215 2 a216 2 (void)ioctl(2, TIOCGETP, &s); (void)ioctl(2, TIOCGLTC, &l); d239 1 a239 1 (void)ioctl(2, TIOCSETN, &s); a260 2 char *getenv(), *strcpy(); d273 1 a273 1 if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_row > 0) d278 1 a278 1 if (ioctl(2, WIOCGETD, &w) == 0 && w.uw_height > 0) d291 1 a291 1 if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_col > 0) d295 1 a295 1 if (ioctl(2, WIOCGETD, &w) == 0 && w.uw_width > 0) d302 1 a302 1 sc_width = 80; d333 1 a333 1 sc_deinit= tgetstr("te", &sp); d337 8 d464 32 d510 1 d519 1 @ 1.7 log @Fix compilation for the case where neither ioctl(TIOCGWINSZ) nor ioctl(WIOCGETD) exist. This case doesn't occur under FreeBSD. PR: bin/5996 Submitted by: Max Euston @ text @a104 1 int sc_window = -1; /* window size for forward and backward */ d296 2 @ 1.6 log @Add #include to get prototypes for functions that gcc has builtin (and wants to know that the prototypes match). @ text @d269 1 d274 1 a276 1 else @ 1.5 log @Remove _set_ospeed, trick done in tgetent now @ text @d47 1 @ 1.5.2.1 log @MFC: doc fixes, enhancements to locate & more, new tail functionality. @ text @a46 1 #include @ 1.4 log @Replace wrong ospeed setting (overflows) with new _set_ospeed function. @ text @d168 1 a168 1 _set_ospeed(cfgetospeed(&s)); @ 1.3 log @Remove trailing whitespace. @ text @d168 1 a168 1 ospeed = cfgetospeed(&s); @ 1.3.4.1 log @Brought in changes from main branch: Andrey's "ospeed" fixes, plus some minor (mostly compiler warning) fixes in related files. @ text @d168 1 a168 1 /* more work needed here */ @ 1.2 log @1) Make ctype-aware expect chars in range 0200-0204 treated as controls in any case. 2) Fix bug with incorrect column position when standouts occurse 3) Fix bug when last standouted char cause clearing next line in standout @ text @d128 1 a128 1 * "Raw mode" means d130 1 a130 1 * 2. Input is not echoed. d343 1 a343 1 * This is not an error here, because we don't d385 1 a385 1 * be an up-arrow suggesting moving to the d393 1 a393 1 /* d412 1 a412 1 * No "lower-left" string, d425 1 a425 1 if ((sc_addline = tgetstr("al", &sp)) == NULL || d448 1 a448 1 * Below are the functions which perform all the d554 1 a554 1 * Begin "underline" (hopefully real underlining, d591 1 a591 1 * Erase the character to the left of the cursor d596 1 a596 1 /* @ 1.1 log @Initial revision @ text @d109 5 d511 6 d526 6 d541 1 d550 1 d560 1 d569 1 d578 1 d587 1 @ 1.1.1.1 log @BSD 4.4 Lite Usr.bin Sources @ text @@