2013-09-25 09:45:05 -04:00
|
|
|
/* tcap.c -- implements terminal.h */
|
|
|
|
#include "terminal.h"
|
|
|
|
|
2010-08-29 21:21:42 -04:00
|
|
|
/* tcap.c
|
2005-05-31 11:50:56 -04:00
|
|
|
*
|
|
|
|
* Unix V7 SysV and BS4 Termcap video driver
|
|
|
|
*
|
|
|
|
* modified by Petri Kutvonen
|
|
|
|
*/
|
|
|
|
|
2013-10-08 21:43:15 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2005-05-31 11:50:56 -04:00
|
|
|
/*
|
2010-08-29 21:21:42 -04:00
|
|
|
* Defining this to 1 breaks tcapopen() - it doesn't check if the
|
2005-05-31 11:50:56 -04:00
|
|
|
* sceen size has changed.
|
|
|
|
* -lbt
|
|
|
|
*/
|
|
|
|
#define USE_BROKEN_OPTIMIZATION 0
|
2010-08-29 21:21:42 -04:00
|
|
|
#define termdef 1 /* Don't define "term" external. */
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2013-04-30 23:46:06 -04:00
|
|
|
#include <curses.h>
|
|
|
|
#include <term.h>
|
|
|
|
|
2013-05-28 02:57:03 -04:00
|
|
|
#include "display.h"
|
2010-08-29 21:21:42 -04:00
|
|
|
#include "estruct.h"
|
2013-05-28 03:17:15 -04:00
|
|
|
#include "termio.h"
|
2005-09-30 20:08:36 -04:00
|
|
|
|
2005-05-31 11:50:56 -04:00
|
|
|
#if TERMCAP
|
|
|
|
|
2013-10-09 04:11:43 -04:00
|
|
|
boolean eolexist = TRUE ; /* does clear to EOL exist */
|
|
|
|
boolean revexist = FALSE ; /* does reverse video exist? */
|
2013-10-09 04:58:33 -04:00
|
|
|
boolean sgarbf = TRUE ; /* TRUE if screen is garbage */
|
2013-10-09 04:11:43 -04:00
|
|
|
|
2013-10-10 23:20:06 -04:00
|
|
|
char sres[ 16] ; /* current screen resolution */
|
|
|
|
/* NORMAL, CGA, EGA, VGA */
|
2013-10-09 02:38:55 -04:00
|
|
|
|
2005-05-31 11:50:56 -04:00
|
|
|
#if UNIX
|
|
|
|
#include <signal.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define MARGIN 8
|
|
|
|
#define SCRSIZ 64
|
2010-08-29 21:21:42 -04:00
|
|
|
#define NPAUSE 10 /* # times thru update to pause. */
|
2005-05-31 11:50:56 -04:00
|
|
|
#define BEL 0x07
|
|
|
|
#define ESC 0x1B
|
|
|
|
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapkopen(void);
|
|
|
|
static void tcapkclose(void);
|
|
|
|
static void tcapmove(int, int);
|
|
|
|
static void tcapeeol(void);
|
|
|
|
static void tcapeeop(void);
|
|
|
|
static void tcapbeep(void);
|
|
|
|
static void tcaprev(int);
|
|
|
|
static int tcapcres(char *);
|
|
|
|
static void tcapscrollregion(int top, int bot);
|
|
|
|
static void putpad(char *str);
|
|
|
|
|
|
|
|
static void tcapopen(void);
|
2010-08-29 21:21:42 -04:00
|
|
|
#if PKCODE
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapclose(void);
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
2005-10-01 03:22:55 -04:00
|
|
|
|
2010-08-29 21:21:42 -04:00
|
|
|
#if COLOR
|
2005-10-01 03:22:55 -04:00
|
|
|
static void tcapfcol(void);
|
|
|
|
static void tcapbcol(void);
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
2010-08-29 21:21:42 -04:00
|
|
|
#if SCROLLCODE
|
2005-10-01 03:22:55 -04:00
|
|
|
static void tcapscroll_reg(int from, int to, int linestoscroll);
|
|
|
|
static void tcapscroll_delins(int from, int to, int linestoscroll);
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define TCAPSLEN 315
|
2005-10-01 03:33:44 -04:00
|
|
|
static char tcapbuf[TCAPSLEN];
|
2020-06-16 02:09:44 -04:00
|
|
|
static char *_UP, _PC, *CM, *CE, *CL, *SO, *SE;
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2010-08-29 21:21:42 -04:00
|
|
|
#if PKCODE
|
2005-10-01 03:33:44 -04:00
|
|
|
static char *TI, *TE;
|
2006-11-19 14:52:18 -05:00
|
|
|
#if USE_BROKEN_OPTIMIZATION
|
2005-10-01 03:33:44 -04:00
|
|
|
static int term_init_ok = 0;
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
2006-11-19 14:52:18 -05:00
|
|
|
#endif
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2010-08-29 21:21:42 -04:00
|
|
|
#if SCROLLCODE
|
2005-10-01 03:33:44 -04:00
|
|
|
static char *CS, *DL, *AL, *SF, *SR;
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
|
2010-07-11 13:54:48 -04:00
|
|
|
struct terminal term = {
|
2020-08-13 22:53:55 -04:00
|
|
|
480, /* actual 479 on 2560x1440 landscape terminal window */
|
|
|
|
2550, /* actual 2541 */
|
2017-06-01 01:02:47 -04:00
|
|
|
0, /* These four values are set dynamically at open time. */
|
2005-05-31 11:50:56 -04:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
MARGIN,
|
|
|
|
SCRSIZ,
|
|
|
|
NPAUSE,
|
2005-09-30 18:26:09 -04:00
|
|
|
tcapopen,
|
2005-05-31 11:50:56 -04:00
|
|
|
#if PKCODE
|
|
|
|
tcapclose,
|
|
|
|
#else
|
2005-09-30 18:26:09 -04:00
|
|
|
ttclose,
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
2005-09-30 18:26:09 -04:00
|
|
|
tcapkopen,
|
|
|
|
tcapkclose,
|
|
|
|
ttgetc,
|
|
|
|
ttputc,
|
|
|
|
ttflush,
|
|
|
|
tcapmove,
|
|
|
|
tcapeeol,
|
|
|
|
tcapeeop,
|
|
|
|
tcapbeep,
|
|
|
|
tcaprev,
|
|
|
|
tcapcres
|
2005-05-31 11:50:56 -04:00
|
|
|
#if COLOR
|
2005-09-30 18:26:09 -04:00
|
|
|
, tcapfcol,
|
2005-05-31 11:50:56 -04:00
|
|
|
tcapbcol
|
|
|
|
#endif
|
2005-09-30 18:26:09 -04:00
|
|
|
#if SCROLLCODE
|
|
|
|
, NULL /* set dynamically at open time */
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapopen(void)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2005-09-30 20:08:36 -04:00
|
|
|
char *t, *p;
|
2005-09-30 18:26:09 -04:00
|
|
|
char tcbuf[1024];
|
|
|
|
char *tv_stype;
|
|
|
|
int int_col, int_row;
|
2005-05-31 11:50:56 -04:00
|
|
|
|
|
|
|
#if PKCODE && USE_BROKEN_OPTIMIZATION
|
2005-09-30 18:26:09 -04:00
|
|
|
if (!term_init_ok) {
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
2005-09-30 18:26:09 -04:00
|
|
|
if ((tv_stype = getenv("TERM")) == NULL) {
|
2015-03-23 07:12:38 -04:00
|
|
|
fputs( "Environment variable TERM not defined!\n", stderr) ;
|
|
|
|
exit( EXIT_FAILURE) ;
|
2005-09-30 18:26:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((tgetent(tcbuf, tv_stype)) != 1) {
|
2015-03-23 07:12:38 -04:00
|
|
|
fputs( "Unknown terminal type ", stderr) ;
|
|
|
|
fputs( tv_stype, stderr) ;
|
|
|
|
fputs( "!\n", stderr) ;
|
|
|
|
exit( EXIT_FAILURE) ;
|
2005-09-30 18:26:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get screen size from system, or else from termcap. */
|
2017-05-29 04:27:46 -04:00
|
|
|
getscreensize( &int_col, &int_row) ;
|
|
|
|
if( (int_row <= 0)
|
|
|
|
&& ((int_row = tgetnum("li")) == -1)) {
|
2015-03-23 07:12:38 -04:00
|
|
|
fputs( "termcap entry incomplete (lines)\n", stderr) ;
|
|
|
|
exit( EXIT_FAILURE) ;
|
2005-09-30 18:26:09 -04:00
|
|
|
}
|
|
|
|
|
2017-05-29 04:27:46 -04:00
|
|
|
if( (int_col <= 0)
|
|
|
|
&& ((int_col = tgetnum("co")) == -1)) {
|
2015-03-23 07:12:38 -04:00
|
|
|
fputs( "Termcap entry incomplete (columns)\n", stderr) ;
|
|
|
|
exit( EXIT_FAILURE) ;
|
2005-09-30 18:26:09 -04:00
|
|
|
}
|
2017-05-31 20:05:59 -04:00
|
|
|
|
2017-06-01 01:02:47 -04:00
|
|
|
term.t_mrow = int_row < term.t_maxrow ? int_row : term.t_maxrow ;
|
2017-05-29 04:27:46 -04:00
|
|
|
term.t_nrow = term.t_mrow - 1 ;
|
2017-06-01 01:02:47 -04:00
|
|
|
term.t_mcol = int_col < term.t_maxcol ? int_col : term.t_maxcol ;
|
2017-05-29 04:27:46 -04:00
|
|
|
term.t_ncol = term.t_mcol ;
|
2017-06-01 01:02:47 -04:00
|
|
|
|
2005-09-30 18:26:09 -04:00
|
|
|
p = tcapbuf;
|
|
|
|
t = tgetstr("pc", &p);
|
|
|
|
if (t)
|
2020-06-16 02:09:44 -04:00
|
|
|
_PC = *t;
|
2005-09-30 18:26:09 -04:00
|
|
|
else
|
2020-06-16 02:09:44 -04:00
|
|
|
_PC = 0;
|
2005-09-30 18:26:09 -04:00
|
|
|
|
|
|
|
CL = tgetstr("cl", &p);
|
|
|
|
CM = tgetstr("cm", &p);
|
|
|
|
CE = tgetstr("ce", &p);
|
2020-06-16 02:09:44 -04:00
|
|
|
_UP = tgetstr("up", &p);
|
2005-09-30 18:26:09 -04:00
|
|
|
SE = tgetstr("se", &p);
|
|
|
|
SO = tgetstr("so", &p);
|
|
|
|
if (SO != NULL)
|
|
|
|
revexist = TRUE;
|
2005-05-31 11:50:56 -04:00
|
|
|
#if PKCODE
|
2005-09-30 18:26:09 -04:00
|
|
|
if (tgetnum("sg") > 0) { /* can reverse be used? P.K. */
|
|
|
|
revexist = FALSE;
|
|
|
|
SE = NULL;
|
|
|
|
SO = NULL;
|
|
|
|
}
|
|
|
|
TI = tgetstr("ti", &p); /* terminal init and exit */
|
|
|
|
TE = tgetstr("te", &p);
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
|
2020-06-16 02:09:44 -04:00
|
|
|
if (CL == NULL || CM == NULL || _UP == NULL) {
|
2015-03-23 07:12:38 -04:00
|
|
|
fputs( "Incomplete termcap entry\n", stderr) ;
|
|
|
|
exit( EXIT_FAILURE) ;
|
2005-09-30 18:26:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (CE == NULL) /* will we be able to use clear to EOL? */
|
|
|
|
eolexist = FALSE;
|
|
|
|
#if SCROLLCODE
|
|
|
|
CS = tgetstr("cs", &p);
|
|
|
|
SF = tgetstr("sf", &p);
|
|
|
|
SR = tgetstr("sr", &p);
|
|
|
|
DL = tgetstr("dl", &p);
|
|
|
|
AL = tgetstr("al", &p);
|
|
|
|
|
|
|
|
if (CS && SR) {
|
|
|
|
if (SF == NULL) /* assume '\n' scrolls forward */
|
|
|
|
SF = "\n";
|
|
|
|
term.t_scroll = tcapscroll_reg;
|
|
|
|
} else if (DL && AL) {
|
|
|
|
term.t_scroll = tcapscroll_delins;
|
|
|
|
} else {
|
|
|
|
term.t_scroll = NULL;
|
|
|
|
}
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
2005-09-30 18:26:09 -04:00
|
|
|
|
|
|
|
if (p >= &tcapbuf[TCAPSLEN]) {
|
2015-03-23 07:12:38 -04:00
|
|
|
fputs( "Terminal description too big!\n", stderr) ;
|
|
|
|
exit( EXIT_FAILURE) ;
|
2005-09-30 18:26:09 -04:00
|
|
|
}
|
2005-05-31 11:50:56 -04:00
|
|
|
#if PKCODE && USE_BROKEN_OPTIMIZATION
|
2005-09-30 18:26:09 -04:00
|
|
|
term_init_ok = 1;
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
#endif
|
2005-09-30 18:26:09 -04:00
|
|
|
ttopen();
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#if PKCODE
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapclose(void)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
|
|
|
putpad(tgoto(CM, 0, term.t_nrow));
|
|
|
|
putpad(TE);
|
|
|
|
ttflush();
|
|
|
|
ttclose();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapkopen(void)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
|
|
|
#if PKCODE
|
|
|
|
putpad(TI);
|
|
|
|
ttflush();
|
2011-08-25 16:45:08 -04:00
|
|
|
ttrow = 999;
|
|
|
|
ttcol = 999;
|
|
|
|
sgarbf = TRUE;
|
2005-05-31 11:50:56 -04:00
|
|
|
#endif
|
|
|
|
strcpy(sres, "NORMAL");
|
|
|
|
}
|
|
|
|
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapkclose(void)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2011-08-25 16:45:08 -04:00
|
|
|
#if PKCODE
|
|
|
|
putpad(TE);
|
|
|
|
ttflush();
|
|
|
|
#endif
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapmove(int row, int col)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2005-09-30 18:26:09 -04:00
|
|
|
putpad(tgoto(CM, col, row));
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapeeol(void)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2005-09-30 18:26:09 -04:00
|
|
|
putpad(CE);
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapeeop(void)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2005-09-30 18:26:09 -04:00
|
|
|
putpad(CL);
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
|
2005-09-30 20:08:36 -04:00
|
|
|
/*
|
2010-08-29 21:21:42 -04:00
|
|
|
* Change reverse video status
|
2005-09-30 20:08:36 -04:00
|
|
|
*
|
2010-08-29 21:21:42 -04:00
|
|
|
* @state: FALSE = normal video, TRUE = reverse video.
|
2005-09-30 20:08:36 -04:00
|
|
|
*/
|
|
|
|
static void tcaprev(int state)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
|
|
|
if (state) {
|
|
|
|
if (SO != NULL)
|
|
|
|
putpad(SO);
|
2005-09-30 18:26:09 -04:00
|
|
|
} else if (SE != NULL)
|
|
|
|
putpad(SE);
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
|
2010-08-29 21:21:42 -04:00
|
|
|
/* Change screen resolution. */
|
2005-09-30 20:08:36 -04:00
|
|
|
static int tcapcres(char *res)
|
2010-08-29 21:21:42 -04:00
|
|
|
{
|
2010-08-29 06:03:55 -04:00
|
|
|
return TRUE;
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
|
2005-09-30 18:26:09 -04:00
|
|
|
#if SCROLLCODE
|
|
|
|
|
2005-05-31 11:50:56 -04:00
|
|
|
/* move howmanylines lines starting at from to to */
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapscroll_reg(int from, int to, int howmanylines)
|
2005-09-30 18:26:09 -04:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
if (to == from)
|
|
|
|
return;
|
|
|
|
if (to < from) {
|
|
|
|
tcapscrollregion(to, from + howmanylines - 1);
|
|
|
|
tcapmove(from + howmanylines - 1, 0);
|
|
|
|
for (i = from - to; i > 0; i--)
|
|
|
|
putpad(SF);
|
|
|
|
} else { /* from < to */
|
|
|
|
tcapscrollregion(from, to + howmanylines - 1);
|
|
|
|
tcapmove(from, 0);
|
|
|
|
for (i = to - from; i > 0; i--)
|
|
|
|
putpad(SR);
|
|
|
|
}
|
2005-05-31 11:50:56 -04:00
|
|
|
tcapscrollregion(0, term.t_nrow);
|
|
|
|
}
|
2005-09-30 18:26:09 -04:00
|
|
|
|
2005-05-31 11:50:56 -04:00
|
|
|
/* move howmanylines lines starting at from to to */
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapscroll_delins(int from, int to, int howmanylines)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2005-09-30 18:26:09 -04:00
|
|
|
int i;
|
|
|
|
if (to == from)
|
|
|
|
return;
|
|
|
|
if (to < from) {
|
|
|
|
tcapmove(to, 0);
|
|
|
|
for (i = from - to; i > 0; i--)
|
|
|
|
putpad(DL);
|
|
|
|
tcapmove(to + howmanylines, 0);
|
|
|
|
for (i = from - to; i > 0; i--)
|
|
|
|
putpad(AL);
|
|
|
|
} else {
|
|
|
|
tcapmove(from + howmanylines, 0);
|
|
|
|
for (i = to - from; i > 0; i--)
|
|
|
|
putpad(DL);
|
|
|
|
tcapmove(from, 0);
|
|
|
|
for (i = to - from; i > 0; i--)
|
|
|
|
putpad(AL);
|
|
|
|
}
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
2005-09-30 18:26:09 -04:00
|
|
|
|
2005-05-31 11:50:56 -04:00
|
|
|
/* cs is set up just like cm, so we use tgoto... */
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapscrollregion(int top, int bot)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2020-06-16 02:09:44 -04:00
|
|
|
ttputc(_PC);
|
2005-09-30 18:26:09 -04:00
|
|
|
putpad(tgoto(CS, bot, top));
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
|
2005-09-30 18:26:09 -04:00
|
|
|
#endif
|
2005-05-31 11:50:56 -04:00
|
|
|
|
2010-08-29 21:21:42 -04:00
|
|
|
#if COLOR
|
|
|
|
/* No colors here, ignore this. */
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapfcol(void)
|
2010-08-29 21:21:42 -04:00
|
|
|
{
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
2010-08-29 21:21:42 -04:00
|
|
|
/* No colors here, ignore this. */
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapbcol(void)
|
2010-08-29 21:21:42 -04:00
|
|
|
{
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-09-30 20:08:36 -04:00
|
|
|
static void tcapbeep(void)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
|
|
|
ttputc(BEL);
|
|
|
|
}
|
|
|
|
|
2005-09-30 20:08:36 -04:00
|
|
|
static void putpad(char *str)
|
2005-05-31 11:50:56 -04:00
|
|
|
{
|
2016-04-08 23:46:40 -04:00
|
|
|
tputs( str, 1, (int (*)( int)) ttputc) ;
|
2005-05-31 11:50:56 -04:00
|
|
|
}
|
2010-08-29 21:21:42 -04:00
|
|
|
#endif /* TERMCAP */
|