#include <sys/ioctl.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <stdio.h>
#include <term.h>
#include <unistd.h>
#include "def.h"
static int charcost(const char *);
static int cci;
static int insdel;
static char *scroll_fwd;
static void winchhandler(int);
volatile sig_atomic_t winch_flag;
int tceeol;
int tcinsl;
int tcdell;
static void
winchhandler(int sig)
{
winch_flag = 1;
}
void
ttinit(void)
{
char *tty;
int errret;
if (batch == 1)
tty = "pty";
else
tty = NULL;
if (setupterm(tty, STDOUT_FILENO, &errret))
panic("Terminal setup failed");
signal(SIGWINCH, winchhandler);
signal(SIGCONT, winchhandler);
siginterrupt(SIGWINCH, 1);
scroll_fwd = scroll_forward;
if (scroll_fwd == NULL || *scroll_fwd == '\0') {
scroll_fwd = parm_down_cursor;
if (scroll_fwd == NULL || *scroll_fwd == '\0')
scroll_fwd = curbp->b_nlchr;
}
if (cursor_address == NULL || cursor_up == NULL)
panic("This terminal is too stupid to run mg");
ttresize();
if (!clr_eol)
tceeol = ncol;
else
tceeol = charcost(clr_eol);
if (change_scroll_region && scroll_reverse)
tcinsl = charcost(change_scroll_region) * 2 +
charcost(scroll_reverse);
else if (parm_insert_line)
tcinsl = charcost(parm_insert_line);
else if (insert_line)
tcinsl = charcost(insert_line);
else
tcinsl = nrow * ncol;
if (change_scroll_region)
tcdell = charcost(change_scroll_region) * 2 +
charcost(scroll_fwd);
else if (parm_delete_line)
tcdell = charcost(parm_delete_line);
else if (delete_line)
tcdell = charcost(delete_line);
else
tcdell = nrow * ncol;
insdel = (insert_line || parm_insert_line) &&
(delete_line || parm_delete_line);
if (enter_ca_mode)
putpad(enter_ca_mode, 1);
ttresize();
}
void
ttreinit(void)
{
if (fchecktime(curbp) != TRUE) {
curbp->b_flag |= BFDIRTY;
}
if (enter_ca_mode)
putpad(enter_ca_mode, 1);
if (keypad_xmit)
putpad(keypad_xmit, 1);
ttresize();
}
void
tttidy(void)
{
ttykeymaptidy();
if (exit_ca_mode)
putpad(exit_ca_mode, 1);
}
void
ttmove(int row, int col)
{
if (ttrow != row || ttcol != col) {
putpad(tgoto(cursor_address, col, row), 1);
ttrow = row;
ttcol = col;
}
}
void
tteeol(void)
{
int i;
if (clr_eol)
putpad(clr_eol, 1);
else {
i = ncol - ttcol;
while (i--)
ttputc(' ');
ttrow = ttcol = HUGE;
}
}
void
tteeop(void)
{
int line;
if (clr_eos)
putpad(clr_eos, nrow - ttrow);
else {
putpad(clr_eol, 1);
if (insdel)
ttdell(ttrow + 1, lines, lines - ttrow - 1);
else {
for (line = ttrow + 1; line <= lines; ++line) {
ttmove(line, 0);
tteeol();
}
}
ttrow = ttcol = HUGE;
}
}
void
ttbeep(void)
{
putpad(bell, 1);
ttflush();
}
void
ttinsl(int row, int bot, int nchunk)
{
int i, nl;
if (row == bot) {
ttmove(row, 0);
tteeol();
return;
}
if (change_scroll_region && scroll_reverse) {
nl = bot - row;
ttwindow(row, bot);
ttmove(row, 0);
while (nchunk--)
putpad(scroll_reverse, nl);
ttnowindow();
return;
} else if (insdel) {
ttmove(1 + bot - nchunk, 0);
nl = nrow - ttrow;
if (parm_delete_line)
putpad(tgoto(parm_delete_line, 0, nchunk), nl);
else
for (i = 0; i < nchunk; i++)
putpad(delete_line, nl);
ttmove(row, 0);
nl = nrow - ttrow;
if (parm_insert_line)
putpad(tgoto(parm_insert_line, 0, nchunk), nl);
else
for (i = 0; i < nchunk; i++)
putpad(insert_line, nl);
ttrow = HUGE;
ttcol = HUGE;
} else
panic("ttinsl: Can't insert/delete line");
}
void
ttdell(int row, int bot, int nchunk)
{
int i, nl;
if (row == bot) {
ttmove(row, 0);
tteeol();
return;
}
if (change_scroll_region) {
nl = bot - row;
ttwindow(row, bot);
ttmove(bot, 0);
while (nchunk--)
putpad(scroll_fwd, nl);
ttnowindow();
} else if (insdel) {
ttmove(row, 0);
nl = nrow - ttrow;
if (parm_delete_line)
putpad(tgoto(parm_delete_line, 0, nchunk), nl);
else
for (i = 0; i < nchunk; i++)
putpad(delete_line, nl);
ttmove(1 + bot - nchunk, 0);
nl = nrow - ttrow;
if (parm_insert_line)
putpad(tgoto(parm_insert_line, 0, nchunk), nl);
else
for (i = 0; i < nchunk; i++)
putpad(insert_line, nl);
ttrow = HUGE;
ttcol = HUGE;
} else
panic("ttdell: Can't insert/delete line");
}
void
ttwindow(int top, int bot)
{
if (change_scroll_region && (tttop != top || ttbot != bot)) {
putpad(tgoto(change_scroll_region, bot, top), nrow - ttrow);
ttrow = HUGE;
ttcol = HUGE;
tttop = top;
ttbot = bot;
}
}
void
ttnowindow(void)
{
if (change_scroll_region) {
putpad(tgoto(change_scroll_region,
(nrow > lines ? nrow : lines) - 1, 0), nrow - ttrow);
ttrow = HUGE;
ttcol = HUGE;
tttop = HUGE;
ttbot = HUGE;
}
}
void
ttcolor(int color)
{
if (color != tthue) {
if (color == CTEXT)
putpad(exit_standout_mode, 1);
else if (color == CMODE)
putpad(enter_standout_mode, 1);
tthue = color;
}
}
void
ttresize(void)
{
int newrow = 0, newcol = 0;
struct winsize winsize;
if (ioctl(0, TIOCGWINSZ, &winsize) == 0) {
newrow = winsize.ws_row;
newcol = winsize.ws_col;
}
if ((newrow <= 0 || newcol <= 0) &&
((newrow = lines) <= 0 || (newcol = columns) <= 0)) {
newrow = 24;
newcol = 80;
}
if (vtresize(1, newrow, newcol) != TRUE)
panic("vtresize failed");
}
static int
fakec(int c)
{
cci++;
return (0);
}
static int
charcost(const char *s)
{
cci = 0;
tputs(s, nrow, fakec);
return (cci);
}