#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)screen.c 8.2 (Berkeley) 4/20/94";
#else
__RCSID("$NetBSD: screen.c,v 1.7 2003/10/13 14:34:25 agc Exp $");
#endif
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "less.h"
#include "extern.h"
#define TERMIOS 1
#if TERMIO
#include <termio.h>
#else
#if TERMIOS
#include <termios.h>
#define TAB3 0
#include <sys/ioctl.h>
#else
#include <sgtty.h>
#endif
#endif
#ifdef __NetBSD__
#include <termcap.h>
#endif
#ifdef TIOCGWINSZ
#include <sys/ioctl.h>
#else
#include <sys/signal.h>
#ifdef SIGPHONE
#include <sys/window.h>
#endif
#endif
static char
*sc_pad,
*sc_home,
*sc_addline,
*sc_lower_left,
*sc_move,
*sc_clear,
*sc_eol_clear,
*sc_s_in,
*sc_s_out,
*sc_u_in,
*sc_u_out,
*sc_b_in,
*sc_b_out,
*sc_backspace,
*sc_init,
*sc_deinit;
int auto_wrap;
int ignaw;
int retain_below;
int erase_char, kill_char, werase_char;
int sc_width, sc_height = -1;
int sc_window = -1;
int bo_width, be_width;
int ul_width, ue_width;
int so_width, se_width;
short ospeed;
char PC;
void
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)
{
#if TERMIO
(void)ioctl(2, TCGETA, &s);
#else
tcgetattr(2, &s);
#endif
save_term = s;
#if TERMIO
ospeed = s.c_cflag & CBAUD;
#else
ospeed = cfgetospeed(&s);
#endif
erase_char = s.c_cc[VERASE];
kill_char = s.c_cc[VKILL];
werase_char = s.c_cc[VWERASE];
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
{
s = save_term;
}
#if TERMIO
(void)ioctl(2, TCSETAW, &s);
#else
tcsetattr(2, TCSADRAIN, &s);
#endif
#else
struct sgttyb s;
struct ltchars l;
static struct sgttyb save_term;
if (on)
{
(void)ioctl(2, TIOCGETP, &s);
(void)ioctl(2, TIOCGLTC, &l);
save_term = s;
ospeed = s.sg_ospeed;
erase_char = s.sg_erase;
kill_char = s.sg_kill;
werase_char = l.t_werasc;
s.sg_flags |= CBREAK;
s.sg_flags &= ~(ECHO|XTABS);
} else
{
s = save_term;
}
(void)ioctl(2, TIOCSETN, &s);
#endif
}
void
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];
if ((term = getenv("TERM")) == NULL)
term = "unknown";
if (tgetent(termbuf, term) <= 0)
(void)strlcpy(termbuf, "dumb:co#80:hc:", sizeof(termbuf));
#ifdef TIOCGWINSZ
if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_row > 0)
sc_height = w.ws_row;
#else
#ifdef WIOCGETD
if (ioctl(2, WIOCGETD, &w) == 0 && w.uw_height > 0)
sc_height = w.uw_height/w.uw_vs;
#endif
#endif
else
sc_height = tgetnum("li");
hard = (sc_height < 0 || tgetflag("hc"));
if (hard) {
sc_height = 24;
}
#ifdef TIOCGWINSZ
if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
sc_width = w.ws_col;
else
#ifdef WIOCGETD
if (ioctl(2, 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;
auto_wrap = tgetflag("am");
ignaw = tgetflag("xn");
retain_below = tgetflag("db");
if ((so_width = tgetnum("sg")) < 0)
so_width = 0;
be_width = bo_width = ue_width = ul_width = se_width = so_width;
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_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')
{
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')
{
sc_home = "|\b^";
} else
{
(void)strlcpy(sp, tgoto(sc_move, 0, 0),
sizeof(sbuf) - (sp - sbuf));
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
{
(void)strlcpy(sp, tgoto(sc_move, 0, sc_height-1),
sizeof(sbuf) - (sp - sbuf));
sc_lower_left = sp;
sp += strlen(sp) + 1;
}
}
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 = "";
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";
}
}
void
init()
{
tputs(sc_init, sc_height, putchr);
}
void
deinit()
{
tputs(sc_deinit, sc_height, putchr);
}
void
home()
{
tputs(sc_home, 1, putchr);
}
void
add_line()
{
tputs(sc_addline, sc_height, putchr);
}
int short_file;
void
lower_left()
{
if (short_file) {
putchr('\r');
flush();
}
else
tputs(sc_lower_left, 1, putchr);
}
void
bell()
{
putchr('\7');
}
void
clear()
{
tputs(sc_clear, sc_height, putchr);
}
void
clear_eol()
{
tputs(sc_eol_clear, 1, putchr);
}
void
so_enter()
{
tputs(sc_s_in, 1, putchr);
}
void
so_exit()
{
tputs(sc_s_out, 1, putchr);
}
void
ul_enter()
{
tputs(sc_u_in, 1, putchr);
}
void
ul_exit()
{
tputs(sc_u_out, 1, putchr);
}
void
bo_enter()
{
tputs(sc_b_in, 1, putchr);
}
void
bo_exit()
{
tputs(sc_b_out, 1, putchr);
}
void
backspace()
{
tputs(sc_backspace, 1, putchr);
putchr(' ');
tputs(sc_backspace, 1, putchr);
}
void
putbs()
{
tputs(sc_backspace, 1, putchr);
}