aboutsummaryrefslogtreecommitdiff
path: root/ncurses/tinfo
diff options
context:
space:
mode:
Diffstat (limited to 'ncurses/tinfo')
-rwxr-xr-x[-rw-r--r--]ncurses/tinfo/MKcaptab.sh0
-rwxr-xr-xncurses/tinfo/MKfallback.sh16
-rw-r--r--ncurses/tinfo/access.c12
-rw-r--r--ncurses/tinfo/captoinfo.c13
-rw-r--r--ncurses/tinfo/comp_parse.c4
-rw-r--r--ncurses/tinfo/doalloc.c4
-rw-r--r--ncurses/tinfo/lib_baudrate.c20
-rw-r--r--ncurses/tinfo/lib_cur_term.c7
-rw-r--r--ncurses/tinfo/lib_data.c7
-rw-r--r--ncurses/tinfo/lib_kernel.c12
-rw-r--r--ncurses/tinfo/lib_napms.c4
-rw-r--r--ncurses/tinfo/lib_options.c6
-rw-r--r--ncurses/tinfo/lib_print.c6
-rw-r--r--ncurses/tinfo/lib_raw.c11
-rw-r--r--ncurses/tinfo/lib_setup.c29
-rw-r--r--ncurses/tinfo/lib_tgoto.c4
-rw-r--r--ncurses/tinfo/lib_tparm.c459
-rw-r--r--ncurses/tinfo/lib_tputs.c16
-rw-r--r--ncurses/tinfo/lib_ttyflags.c6
-rw-r--r--ncurses/tinfo/lib_win32con.c1256
-rw-r--r--ncurses/tinfo/lib_win32util.c134
-rw-r--r--ncurses/tinfo/parse_entry.c10
-rw-r--r--ncurses/tinfo/read_entry.c16
-rw-r--r--ncurses/tinfo/tinfo_driver.c137
-rw-r--r--ncurses/tinfo/trim_sgr0.c4
-rw-r--r--ncurses/tinfo/write_entry.c4
26 files changed, 1992 insertions, 205 deletions
diff --git a/ncurses/tinfo/MKcaptab.sh b/ncurses/tinfo/MKcaptab.sh
index c800023d105a..c800023d105a 100644..100755
--- a/ncurses/tinfo/MKcaptab.sh
+++ b/ncurses/tinfo/MKcaptab.sh
diff --git a/ncurses/tinfo/MKfallback.sh b/ncurses/tinfo/MKfallback.sh
index 319ab066c885..64c65f197e0d 100755
--- a/ncurses/tinfo/MKfallback.sh
+++ b/ncurses/tinfo/MKfallback.sh
@@ -27,7 +27,7 @@
# use or other dealings in this Software without prior written #
# authorization. #
##############################################################################
-# $Id: MKfallback.sh,v 1.24 2020/02/08 21:52:37 tom Exp $
+# $Id: MKfallback.sh,v 1.25 2020/08/16 15:58:44 tom Exp $
#
# MKfallback.sh -- create fallback table for entry reads
#
@@ -44,12 +44,14 @@ terminfo_src=$1
shift
tic_path=$1
+test -z "$tic_path" && tic_path=tic
shift
infocmp_path=$1
+test -z "$infocmp_path" && infocmp_path=infocmp
shift
-case $tic_path in #(vi
+case "$tic_path" in #(vi
/*)
tic_head=`echo "$tic_path" | sed -e 's,/[^/]*$,,'`
PATH=$tic_head:$PATH
@@ -67,7 +69,7 @@ if test $# != 0 ; then
TERMINFO_DIRS=$TERMINFO:$terminfo_dir
export TERMINFO_DIRS
- $tic_path -x $terminfo_src >&2
+ "$tic_path" -x "$terminfo_src" >&2
else
tmp_info=
fi
@@ -90,10 +92,10 @@ then
/* fallback entries for: $* */
EOF
- for x in $*
+ for x in "$@"
do
echo "/* $x */"
- $infocmp_path -E $x | sed -e 's/\<short\>/NCURSES_INT2/g'
+ "$infocmp_path" -E "$x" | sed -e 's/\<short\>/NCURSES_INT2/g'
done
cat <<EOF
@@ -101,10 +103,10 @@ static const TERMTYPE2 fallbacks[$#] =
{
EOF
comma=""
- for x in $*
+ for x in "$@"
do
echo "$comma /* $x */"
- $infocmp_path -e $x
+ "$infocmp_path" -e "$x"
comma=","
done
diff --git a/ncurses/tinfo/access.c b/ncurses/tinfo/access.c
index c69707feb2c6..15593688266e 100644
--- a/ncurses/tinfo/access.c
+++ b/ncurses/tinfo/access.c
@@ -37,10 +37,16 @@
#include <tic.h>
-MODULE_ID("$Id: access.c,v 1.25 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: access.c,v 1.27 2020/08/29 16:22:03 juergen Exp $")
#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
+#ifdef _NC_MSC
+# define ACCESS(FN, MODE) access((FN), (MODE)&(R_OK|W_OK))
+#else
+# define ACCESS access
+#endif
+
NCURSES_EXPORT(char *)
_nc_rootname(char *path)
{
@@ -112,7 +118,7 @@ _nc_access(const char *path, int mode)
if (path == 0) {
result = -1;
- } else if (access(path, mode) < 0) {
+ } else if (ACCESS(path, mode) < 0) {
if ((mode & W_OK) != 0
&& errno == ENOENT
&& strlen(path) < PATH_MAX) {
@@ -127,7 +133,7 @@ _nc_access(const char *path, int mode)
if (head == leaf)
_nc_STRCPY(head, ".", sizeof(head));
- result = access(head, R_OK | W_OK | X_OK);
+ result = ACCESS(head, R_OK | W_OK | X_OK);
} else {
result = -1;
}
diff --git a/ncurses/tinfo/captoinfo.c b/ncurses/tinfo/captoinfo.c
index 8b3b83d18239..de0133b386c6 100644
--- a/ncurses/tinfo/captoinfo.c
+++ b/ncurses/tinfo/captoinfo.c
@@ -98,7 +98,7 @@
#include <ctype.h>
#include <tic.h>
-MODULE_ID("$Id: captoinfo.c,v 1.98 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: captoinfo.c,v 1.100 2020/07/08 21:39:54 tom Exp $")
#if 0
#define DEBUG_THIS(p) DEBUG(9, p)
@@ -216,12 +216,15 @@ cvtchar(register const char *sp)
}
break;
case '^':
+ len = 2;
c = UChar(*++sp);
- if (c == '?')
+ if (c == '?') {
c = 127;
- else
+ } else if (c == '\0') {
+ len = 1;
+ } else {
c &= 0x1f;
- len = 2;
+ }
break;
default:
c = UChar(*sp);
@@ -636,7 +639,7 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz
/* we may have to move some trailing mandatory padding up front */
padding = str + strlen(str) - 1;
if (padding > str && *padding == '>') {
- if (*--padding == '/')
+ if (padding > (str + 1) && *--padding == '/')
--padding;
while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
padding--;
diff --git a/ncurses/tinfo/comp_parse.c b/ncurses/tinfo/comp_parse.c
index ab25d5b1f03d..2a89a866c374 100644
--- a/ncurses/tinfo/comp_parse.c
+++ b/ncurses/tinfo/comp_parse.c
@@ -48,10 +48,10 @@
#include <tic.h>
-MODULE_ID("$Id: comp_parse.c,v 1.109 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: comp_parse.c,v 1.110 2020/02/29 15:46:00 anonymous.maarten Exp $")
static void sanity_check2(TERMTYPE2 *, bool);
-NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE2 *, bool) = sanity_check2;
+NCURSES_IMPEXP void (NCURSES_API *_nc_check_termtype2) (TERMTYPE2 *, bool) = sanity_check2;
static void fixup_acsc(TERMTYPE2 *, int);
diff --git a/ncurses/tinfo/doalloc.c b/ncurses/tinfo/doalloc.c
index f0c8141ad05e..0bda12cae8be 100644
--- a/ncurses/tinfo/doalloc.c
+++ b/ncurses/tinfo/doalloc.c
@@ -40,9 +40,9 @@
#include <curses.priv.h>
-MODULE_ID("$Id: doalloc.c,v 1.12 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: doalloc.c,v 1.13 2020/08/30 00:27:15 tom Exp $")
-NCURSES_EXPORT(void *)
+void *
_nc_doalloc(void *oldp, size_t amount)
{
void *newp;
diff --git a/ncurses/tinfo/lib_baudrate.c b/ncurses/tinfo/lib_baudrate.c
index 4f72de50f652..311c41ac97fa 100644
--- a/ncurses/tinfo/lib_baudrate.c
+++ b/ncurses/tinfo/lib_baudrate.c
@@ -84,7 +84,7 @@
#undef USE_OLD_TTY
#endif /* USE_OLD_TTY */
-MODULE_ID("$Id: lib_baudrate.c,v 1.44 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_baudrate.c,v 1.45 2020/09/05 21:15:32 tom Exp $")
/*
* int
@@ -99,6 +99,7 @@ struct speed {
int actual_speed; /* the actual speed */
};
+#if !defined(EXP_WIN32_DRIVER)
#define DATA(number) { B##number, number }
static struct speed const speeds[] =
@@ -188,10 +189,16 @@ static struct speed const speeds[] =
#endif
#endif
};
+#endif /* !EXP_WIN32_DRIVER */
NCURSES_EXPORT(int)
_nc_baudrate(int OSpeed)
{
+#if defined(EXP_WIN32_DRIVER)
+ /* On Windows this is a noop */
+ (void) OSpeed;
+ return (OK);
+#else
#if !USE_REENTRANT
static int last_OSpeed;
static int last_baudrate;
@@ -230,13 +237,16 @@ _nc_baudrate(int OSpeed)
#endif
}
return (result);
+#endif /* !EXP_WIN32_DRIVER */
}
NCURSES_EXPORT(int)
_nc_ospeed(int BaudRate)
{
int result = 1;
-
+#if defined(EXP_WIN32_DRIVER)
+ (void) BaudRate;
+#else
if (BaudRate >= 0) {
unsigned i;
@@ -247,6 +257,7 @@ _nc_ospeed(int BaudRate)
}
}
}
+#endif
return (result);
}
@@ -257,6 +268,9 @@ NCURSES_SP_NAME(baudrate) (NCURSES_SP_DCL0)
T((T_CALLED("baudrate(%p)"), (void *) SP_PARM));
+#if defined(EXP_WIN32_DRIVER)
+ result = OK;
+#else
/*
* In debugging, allow the environment symbol to override when we're
* redirecting to a file, so we can construct repeatable test-cases
@@ -290,7 +304,7 @@ NCURSES_SP_NAME(baudrate) (NCURSES_SP_DCL0)
} else {
result = ERR;
}
-
+#endif /* !EXP_WIN32_DRIVER */
returnCode(result);
}
diff --git a/ncurses/tinfo/lib_cur_term.c b/ncurses/tinfo/lib_cur_term.c
index 4a90335d5e33..0373aebb11b9 100644
--- a/ncurses/tinfo/lib_cur_term.c
+++ b/ncurses/tinfo/lib_cur_term.c
@@ -39,8 +39,9 @@
#include <curses.priv.h>
#include <termcap.h> /* ospeed */
+#include <tic.h> /* VALID_STRING */
-MODULE_ID("$Id: lib_cur_term.c,v 1.42 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_cur_term.c,v 1.43 2020/10/24 18:54:32 tom Exp $")
#undef CUR
#define CUR TerminalType(termp).
@@ -99,13 +100,13 @@ NCURSES_SP_NAME(set_curterm) (NCURSES_SP_DCLx TERMINAL *termp)
if (TCB->drv &&
TCB->drv->isTerminfo &&
TerminalType(termp).Strings) {
- PC = (char) ((pad_char != NULL) ? pad_char[0] : 0);
+ PC = (char) (VALID_STRING(pad_char) ? pad_char[0] : 0);
}
TCB->csp = SP_PARM;
#else
ospeed = (NCURSES_OSPEED) _nc_ospeed(termp->_baudrate);
if (TerminalType(termp).Strings) {
- PC = (char) ((pad_char != NULL) ? pad_char[0] : 0);
+ PC = (char) (VALID_STRING(pad_char) ? pad_char[0] : 0);
}
#endif
#if !USE_REENTRANT
diff --git a/ncurses/tinfo/lib_data.c b/ncurses/tinfo/lib_data.c
index bf3e554df70d..39274f4e7c39 100644
--- a/ncurses/tinfo/lib_data.c
+++ b/ncurses/tinfo/lib_data.c
@@ -43,7 +43,7 @@
#include <curses.priv.h>
-MODULE_ID("$Id: lib_data.c,v 1.80 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_data.c,v 1.81 2020/06/13 22:01:14 tom Exp $")
/*
* OS/2's native linker complains if we don't initialize public data when
@@ -155,6 +155,11 @@ NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals = {
0, /* dbd_time */
{ { 0, 0 } }, /* dbd_vars */
+#if HAVE_TSEARCH
+ NULL, /* cached_tparm */
+ 0, /* count_tparm */
+#endif /* HAVE_TSEARCH */
+
#ifdef USE_TERM_DRIVER
0, /* term_driver */
#endif
diff --git a/ncurses/tinfo/lib_kernel.c b/ncurses/tinfo/lib_kernel.c
index 482657add7cf..d5b021b80728 100644
--- a/ncurses/tinfo/lib_kernel.c
+++ b/ncurses/tinfo/lib_kernel.c
@@ -49,8 +49,9 @@
#include <curses.priv.h>
-MODULE_ID("$Id: lib_kernel.c,v 1.32 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_kernel.c,v 1.34 2020/11/21 22:05:58 tom Exp $")
+#ifdef TERMIOS
static int
_nc_vdisable(void)
{
@@ -71,6 +72,7 @@ _nc_vdisable(void)
#endif
return value;
}
+#endif /* TERMIOS */
/*
* erasechar()
@@ -92,6 +94,8 @@ NCURSES_SP_NAME(erasechar) (NCURSES_SP_DCL0)
result = termp->Ottyb.c_cc[VERASE];
if (result == _nc_vdisable())
result = ERR;
+#elif defined(EXP_WIN32_DRIVER)
+ result = ERR;
#else
result = termp->Ottyb.sg_erase;
#endif
@@ -127,6 +131,8 @@ NCURSES_SP_NAME(killchar) (NCURSES_SP_DCL0)
result = termp->Ottyb.c_cc[VKILL];
if (result == _nc_vdisable())
result = ERR;
+#elif defined(EXP_WIN32_DRIVER)
+ result = ERR;
#else
result = termp->Ottyb.sg_kill;
#endif
@@ -162,7 +168,11 @@ NCURSES_SP_NAME(flushinp) (NCURSES_SP_DCL0)
#else
errno = 0;
do {
+#if defined(EXP_WIN32_DRIVER)
+ _nc_console_flush(_nc_console_fd2handle(termp->Filedes));
+#else
ioctl(termp->Filedes, TIOCFLUSH, 0);
+#endif
} while
(errno == EINTR);
#endif
diff --git a/ncurses/tinfo/lib_napms.c b/ncurses/tinfo/lib_napms.c
index 99dacd722928..3a9fc3168784 100644
--- a/ncurses/tinfo/lib_napms.c
+++ b/ncurses/tinfo/lib_napms.c
@@ -52,7 +52,7 @@
#endif
#endif
-MODULE_ID("$Id: lib_napms.c,v 1.26 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_napms.c,v 1.27 2020/08/15 19:45:23 tom Exp $")
NCURSES_EXPORT(int)
NCURSES_SP_NAME(napms) (NCURSES_SP_DCLx int ms)
@@ -75,6 +75,8 @@ NCURSES_SP_NAME(napms) (NCURSES_SP_DCLx int ms)
request = remaining;
}
}
+#elif defined(_NC_WINDOWS)
+ Sleep((DWORD) ms);
#else
_nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0));
#endif
diff --git a/ncurses/tinfo/lib_options.c b/ncurses/tinfo/lib_options.c
index 784e06c17fa1..017a34aac6e7 100644
--- a/ncurses/tinfo/lib_options.c
+++ b/ncurses/tinfo/lib_options.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright 2020 Thomas E. Dickey *
+ * Copyright 2020,2021 Thomas E. Dickey *
* Copyright 1998-2014,2017 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
@@ -47,7 +47,7 @@
#define CUR SP_TERMTYPE
#endif
-MODULE_ID("$Id: lib_options.c,v 1.81 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_options.c,v 1.82 2021/02/14 00:17:35 tom Exp $")
NCURSES_EXPORT(int)
idlok(WINDOW *win, bool flag)
@@ -361,7 +361,7 @@ _nc_keypad(SCREEN *sp, int flag)
#else
if (flag) {
(void) NCURSES_PUTP2_FLUSH("keypad_xmit", keypad_xmit);
- } else if (!flag && keypad_local) {
+ } else if (keypad_local) {
(void) NCURSES_PUTP2_FLUSH("keypad_local", keypad_local);
}
diff --git a/ncurses/tinfo/lib_print.c b/ncurses/tinfo/lib_print.c
index eb9214925a92..4accdf6786ea 100644
--- a/ncurses/tinfo/lib_print.c
+++ b/ncurses/tinfo/lib_print.c
@@ -40,7 +40,7 @@
#define CUR SP_TERMTYPE
#endif
-MODULE_ID("$Id: lib_print.c,v 1.25 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_print.c,v 1.28 2020/08/29 16:22:03 juergen Exp $")
NCURSES_EXPORT(int)
NCURSES_SP_NAME(mcprint) (NCURSES_SP_DCLx char *data, int len)
@@ -60,7 +60,7 @@ NCURSES_SP_NAME(mcprint) (NCURSES_SP_DCLx char *data, int len)
}
if (prtr_non) {
- switchon = TPARM_1(prtr_non, len);
+ switchon = TIPARM_1(prtr_non, len);
onsize = strlen(switchon);
offsize = 0;
} else {
@@ -96,7 +96,7 @@ NCURSES_SP_NAME(mcprint) (NCURSES_SP_DCLx char *data, int len)
* kernel will ship the contiguous clist items from the last write
* immediately.
*/
-#ifndef _WIN32
+#ifndef _NC_WINDOWS
(void) sleep(0);
#endif
free(mybuf);
diff --git a/ncurses/tinfo/lib_raw.c b/ncurses/tinfo/lib_raw.c
index a691a266b703..1e47f3b6fbfb 100644
--- a/ncurses/tinfo/lib_raw.c
+++ b/ncurses/tinfo/lib_raw.c
@@ -50,7 +50,7 @@
#include <curses.priv.h>
-MODULE_ID("$Id: lib_raw.c,v 1.24 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_raw.c,v 1.26 2020/11/21 22:07:48 tom Exp $")
#if HAVE_SYS_TERMIO_H
#include <sys/termio.h> /* needed for ISC */
@@ -97,6 +97,8 @@ NCURSES_SP_NAME(raw) (NCURSES_SP_DCL0)
buf.c_iflag &= (unsigned) ~(COOKED_INPUT);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
+#elif defined(EXP_WIN32_DRIVER)
+ buf.dwFlagIn &= (unsigned long) ~CONMODE_NORAW;
#else
buf.sg_flags |= RAW;
#endif
@@ -152,6 +154,9 @@ NCURSES_SP_NAME(cbreak) (NCURSES_SP_DCL0)
buf.c_lflag |= ISIG;
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
+#elif defined(EXP_WIN32_DRIVER)
+ buf.dwFlagIn |= CONMODE_NORAW;
+ buf.dwFlagIn &= (unsigned long) ~CONMODE_NOCBREAK;
#else
buf.sg_flags |= CBREAK;
#endif
@@ -231,6 +236,8 @@ NCURSES_SP_NAME(noraw) (NCURSES_SP_DCL0)
buf.c_lflag |= ISIG | ICANON |
(termp->Ottyb.c_lflag & IEXTEN);
buf.c_iflag |= COOKED_INPUT;
+#elif defined(EXP_WIN32_DRIVER)
+ buf.dwFlagIn |= CONMODE_NORAW;
#else
buf.sg_flags &= ~(RAW | CBREAK);
#endif
@@ -283,6 +290,8 @@ NCURSES_SP_NAME(nocbreak) (NCURSES_SP_DCL0)
#ifdef TERMIOS
buf.c_lflag |= ICANON;
buf.c_iflag |= ICRNL;
+#elif defined(EXP_WIN32_DRIVER)
+ buf.dwFlagIn |= (CONMODE_NOCBREAK | CONMODE_NORAW);
#else
buf.sg_flags &= ~CBREAK;
#endif
diff --git a/ncurses/tinfo/lib_setup.c b/ncurses/tinfo/lib_setup.c
index a6527bfd0967..976227effade 100644
--- a/ncurses/tinfo/lib_setup.c
+++ b/ncurses/tinfo/lib_setup.c
@@ -49,7 +49,7 @@
#include <locale.h>
#endif
-MODULE_ID("$Id: lib_setup.c,v 1.207 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_setup.c,v 1.212 2020/09/09 19:43:00 juergen Exp $")
/****************************************************************************
*
@@ -305,11 +305,19 @@ _nc_get_screensize(SCREEN *sp,
bool useEnv = _nc_prescreen.use_env;
bool useTioctl = _nc_prescreen.use_tioctl;
+#ifdef EXP_WIN32_DRIVER
+ /* If we are here, then Windows console is used in terminfo mode.
+ We need to figure out the size using the console API
+ */
+ _nc_console_size(linep, colp);
+ T(("screen size: winconsole lines = %d columns = %d", *linep, *colp));
+#else
/* figure out the size of the screen */
T(("screen size: terminfo lines = %d columns = %d", lines, columns));
*linep = (int) lines;
*colp = (int) columns;
+#endif
#if NCURSES_SP_FUNCS
if (sp) {
@@ -566,7 +574,7 @@ NCURSES_EXPORT(int)
_nc_unicode_locale(void)
{
int result = 0;
-#if defined(_WIN32) && USE_WIDEC_SUPPORT
+#if defined(_NC_WINDOWS) && USE_WIDEC_SUPPORT
result = 1;
#elif HAVE_LANGINFO_CODESET
char *env = nl_langinfo(CODESET);
@@ -655,13 +663,20 @@ TINFO_SETUP_TERM(TERMINAL **tp,
if (tname == 0) {
tname = getenv("TERM");
- if (tname == 0 || *tname == '\0') {
-#ifdef USE_TERM_DRIVER
+#if defined(EXP_WIN32_DRIVER)
+ if (!VALID_TERM_ENV(tname, NO_TERMINAL)) {
+ T(("Failure with TERM=%s", NonNull(tname)));
+ ret_error0(TGETENT_ERR, "TERM environment variable not set.\n");
+ }
+#elif defined(USE_TERM_DRIVER)
+ if (!NonEmpty(tname))
tname = "unknown";
#else
+ if (!NonEmpty(tname)) {
+ T(("Failure with TERM=%s", NonNull(tname)));
ret_error0(TGETENT_ERR, "TERM environment variable not set.\n");
-#endif
}
+#endif
}
myname = strdup(tname);
@@ -680,6 +695,10 @@ TINFO_SETUP_TERM(TERMINAL **tp,
*/
if (Filedes == STDOUT_FILENO && !NC_ISATTY(Filedes))
Filedes = STDERR_FILENO;
+#if defined(EXP_WIN32_DRIVER)
+ if (Filedes != STDERR_FILENO && NC_ISATTY(Filedes))
+ _setmode(Filedes, _O_BINARY);
+#endif
/*
* Check if we have already initialized to use this terminal. If so, we
diff --git a/ncurses/tinfo/lib_tgoto.c b/ncurses/tinfo/lib_tgoto.c
index 8e240856f823..9cf5e100ce87 100644
--- a/ncurses/tinfo/lib_tgoto.c
+++ b/ncurses/tinfo/lib_tgoto.c
@@ -36,7 +36,7 @@
#include <ctype.h>
#include <termcap.h>
-MODULE_ID("$Id: lib_tgoto.c,v 1.19 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_tgoto.c,v 1.21 2020/05/27 23:55:56 tom Exp $")
#if !PURE_TERMINFO
static bool
@@ -207,6 +207,6 @@ tgoto(const char *string, int x, int y)
result = tgoto_internal(string, x, y);
else
#endif
- result = TPARM_2(string, y, x);
+ result = TIPARM_2(string, y, x);
returnPtr(result);
}
diff --git a/ncurses/tinfo/lib_tparm.c b/ncurses/tinfo/lib_tparm.c
index 400cd31996f8..b8104eabcd5e 100644
--- a/ncurses/tinfo/lib_tparm.c
+++ b/ncurses/tinfo/lib_tparm.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright 2018-2019,2020 Thomas E. Dickey *
+ * Copyright 2018-2020,2021 Thomas E. Dickey *
* Copyright 1998-2016,2017 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
@@ -38,12 +38,22 @@
*
*/
+#define entry _ncu_entry
+#define ENTRY _ncu_ENTRY
+
#include <curses.priv.h>
+#undef entry
+#undef ENTRY
+
+#if HAVE_TSEARCH
+#include <search.h>
+#endif
+
#include <ctype.h>
#include <tic.h>
-MODULE_ID("$Id: lib_tparm.c,v 1.108 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_tparm.c,v 1.129 2021/02/14 00:09:49 tom Exp $")
/*
* char *
@@ -110,17 +120,81 @@ NCURSES_EXPORT_VAR(int) _nc_tparm_err = 0;
#define TPS(var) _nc_prescreen.tparm_state.var
#define popcount _nc_popcount /* workaround for NetBSD 6.0 defect */
+#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z')
+#define isLOWER(c) ((c) >= 'a' && (c) <= 'z')
+#define tc_BUMP() if (level < 0 && number < 2) number++
+
+typedef struct {
+ const char *format; /* format-string can be used as cache-key */
+ int tparm_type; /* bit-set for each string-parameter */
+ int num_actual;
+ int num_parsed;
+ int num_popped;
+ TPARM_ARG param[NUM_PARM];
+ char *p_is_s[NUM_PARM];
+} TPARM_DATA;
+
+#if HAVE_TSEARCH
+#define MyCache _nc_globals.cached_tparm
+#define MyCount _nc_globals.count_tparm
#if NO_LEAKS
+static int which_tparm;
+static TPARM_DATA **delete_tparm;
+#endif
+#endif /* HAVE_TSEARCH */
+
+static char dummy[] = ""; /* avoid const-cast */
+
+#if HAVE_TSEARCH
+static int
+cmp_format(const void *p, const void *q)
+{
+ const char *a = *(char *const *) p;
+ const char *b = *(char *const *) q;
+ return strcmp(a, b);
+}
+#endif
+
+#if NO_LEAKS
+#if HAVE_TSEARCH
+static void
+visit_nodes(const void *nodep, const VISIT which, const int depth)
+{
+ (void) depth;
+ if (which == preorder || which == leaf) {
+ delete_tparm[which_tparm] = *(TPARM_DATA **) nodep;
+ which_tparm++;
+ }
+}
+#endif
+
NCURSES_EXPORT(void)
_nc_free_tparm(void)
{
- if (TPS(out_buff) != 0) {
- FreeAndNull(TPS(out_buff));
- TPS(out_size) = 0;
- TPS(out_used) = 0;
- FreeAndNull(TPS(fmt_buff));
- TPS(fmt_size) = 0;
+#if HAVE_TSEARCH
+ if (MyCount != 0) {
+ delete_tparm = typeMalloc(TPARM_DATA *, MyCount);
+ which_tparm = 0;
+ twalk(MyCache, visit_nodes);
+ for (which_tparm = 0; which_tparm < MyCount; ++which_tparm) {
+ TPARM_DATA *ptr = delete_tparm[which_tparm];
+ tdelete(ptr, &MyCache, cmp_format);
+ free((char *) ptr->format);
+ free(ptr);
+ }
+ which_tparm = 0;
+ twalk(MyCache, visit_nodes);
+ FreeAndNull(delete_tparm);
+ MyCount = 0;
+ which_tparm = 0;
}
+#endif
+ FreeAndNull(TPS(out_buff));
+ TPS(out_size) = 0;
+ TPS(out_used) = 0;
+
+ FreeAndNull(TPS(fmt_buff));
+ TPS(fmt_size) = 0;
}
#endif
@@ -137,10 +211,7 @@ get_space(size_t need)
static NCURSES_INLINE void
save_text(const char *fmt, const char *s, int len)
{
- size_t s_len = strlen(s);
- if (len > (int) s_len)
- s_len = (size_t) len;
-
+ size_t s_len = (size_t) len + strlen(s) + strlen(fmt);
get_space(s_len + 1);
_nc_SPRINTF(TPS(out_buff) + TPS(out_used),
@@ -152,10 +223,8 @@ save_text(const char *fmt, const char *s, int len)
static NCURSES_INLINE void
save_number(const char *fmt, int number, int len)
{
- if (len < 30)
- len = 30; /* actually log10(MAX_INT)+1 */
-
- get_space((size_t) len + 1);
+ size_t s_len = (size_t) len + 30 + strlen(fmt);
+ get_space(s_len + 1);
_nc_SPRINTF(TPS(out_buff) + TPS(out_used),
_nc_SLIMIT(TPS(out_size) - TPS(out_used))
@@ -216,7 +285,6 @@ spush(char *x)
static NCURSES_INLINE char *
spop(void)
{
- static char dummy[] = ""; /* avoid const-cast */
char *result = dummy;
if (TPS(stack_ptr) > 0) {
TPS(stack_ptr)--;
@@ -325,10 +393,6 @@ parse_format(const char *s, char *format, int *len)
return s;
}
-#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z')
-#define isLOWER(c) ((c) >= 'a' && (c) <= 'z')
-#define tc_BUMP() if (level < 0 && number < 2) number++
-
/*
* Analyze the string to see how many parameters we need from the varargs list,
* and what their types are. We will only accept string parameters if they
@@ -341,7 +405,7 @@ parse_format(const char *s, char *format, int *len)
* may be cases that we cannot see the explicit parameter numbers.
*/
NCURSES_EXPORT(int)
-_nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount)
+_nc_tparm_analyze(const char *string, char **p_is_s, int *popcount)
{
size_t len2;
int i;
@@ -350,7 +414,6 @@ _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount)
int number = 0;
int level = -1;
const char *cp = string;
- static char dummy[] = "";
if (cp == 0)
return 0;
@@ -469,106 +532,179 @@ _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount)
return number;
}
-static NCURSES_INLINE char *
-tparam_internal(int use_TPARM_ARG, const char *string, va_list ap)
+/*
+ * Analyze the capability string, finding the number of parameters and their
+ * types.
+ *
+ * TODO: cache the result so that this is done once per capability per term.
+ */
+static int
+tparm_setup(const char *string, TPARM_DATA * result)
{
- char *p_is_s[NUM_PARM];
- TPARM_ARG param[NUM_PARM];
- int popcount = 0;
- int number;
- int num_args;
- int len;
- int level;
- int x, y;
- int i;
- const char *cp = string;
- size_t len2;
- bool termcap_hack;
- bool incremented_two;
+ int rc = OK;
- if (cp == NULL) {
+ TPS(out_used) = 0;
+ memset(result, 0, sizeof(*result));
+
+ if (string == NULL) {
TR(TRACE_CALLS, ("%s: format is null", TPS(tname)));
- return NULL;
- }
+ rc = ERR;
+ } else {
+#if HAVE_TSEARCH
+ TPARM_DATA *fs;
+ void *ft;
+
+ result->format = string;
+ if ((ft = tfind(result, &MyCache, cmp_format)) != 0) {
+ fs = *(TPARM_DATA **) ft;
+ *result = *fs;
+ } else
+#endif
+ {
+ /*
+ * Find the highest parameter-number referred to in the format
+ * string. Use this value to limit the number of arguments copied
+ * from the variable-length argument list.
+ */
+ result->num_parsed = _nc_tparm_analyze(string,
+ result->p_is_s,
+ &(result->num_popped));
+ if (TPS(fmt_buff) == 0) {
+ TR(TRACE_CALLS, ("%s: error in analysis", TPS(tname)));
+ rc = ERR;
+ } else {
+ int n;
- TPS(out_used) = 0;
- len2 = strlen(cp);
-
- /*
- * Find the highest parameter-number referred to in the format string.
- * Use this value to limit the number of arguments copied from the
- * variable-length argument list.
- */
- number = _nc_tparm_analyze(cp, p_is_s, &popcount);
- if (TPS(fmt_buff) == 0) {
- TR(TRACE_CALLS, ("%s: error in analysis", TPS(tname)));
- return NULL;
+ if (result->num_parsed > NUM_PARM)
+ result->num_parsed = NUM_PARM;
+ if (result->num_popped > NUM_PARM)
+ result->num_popped = NUM_PARM;
+ result->num_actual = max(result->num_popped, result->num_parsed);
+
+ for (n = 0; n < result->num_actual; ++n) {
+ if (result->p_is_s[n])
+ result->tparm_type |= (1 << n);
+ }
+#if HAVE_TSEARCH
+ if ((fs = typeCalloc(TPARM_DATA, 1)) != 0) {
+ *fs = *result;
+ if ((fs->format = strdup(string)) != 0) {
+ if (tsearch(fs, &MyCache, cmp_format) != 0) {
+ ++MyCount;
+ } else {
+ rc = ERR;
+ }
+ } else {
+ rc = ERR;
+ }
+ } else {
+ rc = ERR;
+ }
+#endif
+ }
+ }
}
- incremented_two = FALSE;
+ return rc;
+}
- if (number > NUM_PARM)
- number = NUM_PARM;
- if (popcount > NUM_PARM)
- popcount = NUM_PARM;
- num_args = max(popcount, number);
+/*
+ * A few caps (such as plab_norm) have string-valued parms. We'll have to
+ * assume that the caller knows the difference, since a char* and an int may
+ * not be the same size on the stack. The normal prototype for tparm uses 9
+ * long's, which is consistent with our va_arg() usage.
+ */
+static void
+tparm_copy_valist(TPARM_DATA * data, int use_TPARM_ARG, va_list ap)
+{
+ int i;
- for (i = 0; i < num_args; i++) {
- /*
- * A few caps (such as plab_norm) have string-valued parms.
- * We'll have to assume that the caller knows the difference, since
- * a char* and an int may not be the same size on the stack. The
- * normal prototype for this uses 9 long's, which is consistent with
- * our va_arg() usage.
- */
- if (p_is_s[i] != 0) {
- p_is_s[i] = va_arg(ap, char *);
- param[i] = 0;
+ for (i = 0; i < data->num_actual; i++) {
+ if (data->p_is_s[i] != 0) {
+ char *value = va_arg(ap, char *);
+ if (value == 0)
+ value = dummy;
+ data->p_is_s[i] = value;
+ data->param[i] = 0;
} else if (use_TPARM_ARG) {
- param[i] = va_arg(ap, TPARM_ARG);
+ data->param[i] = va_arg(ap, TPARM_ARG);
} else {
- param[i] = (TPARM_ARG) va_arg(ap, int);
+ data->param[i] = (TPARM_ARG) va_arg(ap, int);
}
}
+}
+
+/*
+ * This is a termcap compatibility hack. If there are no explicit pop
+ * operations in the string, load the stack in such a way that successive pops
+ * will grab successive parameters. That will make the expansion of (for
+ * example) \E[%d;%dH work correctly in termcap style, which means tparam()
+ * will expand termcap strings OK.
+ */
+static bool
+tparm_tc_compat(TPARM_DATA * data)
+{
+ bool termcap_hack = FALSE;
- /*
- * This is a termcap compatibility hack. If there are no explicit pop
- * operations in the string, load the stack in such a way that
- * successive pops will grab successive parameters. That will make
- * the expansion of (for example) \E[%d;%dH work correctly in termcap
- * style, which means tparam() will expand termcap strings OK.
- */
TPS(stack_ptr) = 0;
- termcap_hack = FALSE;
- if (popcount == 0) {
+
+ if (data->num_popped == 0) {
+ int i;
+
termcap_hack = TRUE;
- for (i = number - 1; i >= 0; i--) {
- if (p_is_s[i])
- spush(p_is_s[i]);
+ for (i = data->num_parsed - 1; i >= 0; i--) {
+ if (data->p_is_s[i])
+ spush(data->p_is_s[i]);
else
- npush((int) param[i]);
+ npush((int) data->param[i]);
}
}
+ return termcap_hack;
+}
+
#ifdef TRACE
+static void
+tparm_trace_call(const char *string, TPARM_DATA * data)
+{
if (USE_TRACEF(TRACE_CALLS)) {
- for (i = 0; i < num_args; i++) {
- if (p_is_s[i] != 0) {
- save_text(", %s", _nc_visbuf(p_is_s[i]), 0);
- } else if ((long) param[i] > MAX_OF_TYPE(NCURSES_INT2) ||
- (long) param[i] < 0) {
+ int i;
+ for (i = 0; i < data->num_actual; i++) {
+ if (data->p_is_s[i] != 0) {
+ save_text(", %s", _nc_visbuf(data->p_is_s[i]), 0);
+ } else if ((long) data->param[i] > MAX_OF_TYPE(NCURSES_INT2) ||
+ (long) data->param[i] < 0) {
_tracef("BUG: problem with tparm parameter #%d of %d",
- i + 1, num_args);
+ i + 1, data->num_actual);
break;
} else {
- save_number(", %d", (int) param[i], 0);
+ save_number(", %d", (int) data->param[i], 0);
}
}
- _tracef(T_CALLED("%s(%s%s)"), TPS(tname), _nc_visbuf(cp), TPS(out_buff));
+ _tracef(T_CALLED("%s(%s%s)"), TPS(tname), _nc_visbuf(string), TPS(out_buff));
TPS(out_used) = 0;
_nc_unlock_global(tracef);
}
+}
+
+#else
+#define tparm_trace_call(string, data) /* nothing */
#endif /* TRACE */
+static NCURSES_INLINE char *
+tparam_internal(const char *string, TPARM_DATA * data)
+{
+ int number;
+ int len;
+ int level;
+ int x, y;
+ int i;
+ const char *cp = string;
+ size_t len2 = strlen(cp);
+ bool incremented_two = FALSE;
+ bool termcap_hack = tparm_tc_compat(data);
+
+ tparm_trace_call(string, data);
+
while ((cp - string) < (int) len2) {
if (*cp != '%') {
save_char(UChar(*cp));
@@ -619,10 +755,10 @@ tparam_internal(int use_TPARM_ARG, const char *string, va_list ap)
cp++;
i = (UChar(*cp) - '1');
if (i >= 0 && i < NUM_PARM) {
- if (p_is_s[i]) {
- spush(p_is_s[i]);
+ if (data->p_is_s[i]) {
+ spush(data->p_is_s[i]);
} else {
- npush((int) param[i]);
+ npush((int) data->param[i]);
}
}
break;
@@ -751,15 +887,15 @@ tparam_internal(int use_TPARM_ARG, const char *string, va_list ap)
*/
if (!incremented_two) {
incremented_two = TRUE;
- if (p_is_s[0] == 0) {
- param[0]++;
+ if (data->p_is_s[0] == 0) {
+ data->param[0]++;
if (termcap_hack)
- TPS(stack)[0].data.num = (int) param[0];
+ TPS(stack)[0].data.num = (int) data->param[0];
}
- if (p_is_s[1] == 0) {
- param[1]++;
+ if (data->p_is_s[1] == 0) {
+ data->param[1]++;
if (termcap_hack)
- TPS(stack)[1].data.num = (int) param[1];
+ TPS(stack)[1].data.num = (int) data->param[1];
}
}
break;
@@ -830,61 +966,130 @@ tparam_internal(int use_TPARM_ARG, const char *string, va_list ap)
get_space((size_t) 1);
TPS(out_buff)[TPS(out_used)] = '\0';
+ if (TPS(stack_ptr) && !_nc_tparm_err) {
+ DEBUG(2, ("tparm: stack has %d item%s on return",
+ TPS(stack_ptr),
+ TPS(stack_ptr) == 1 ? "" : "s"));
+ _nc_tparm_err++;
+ }
+
T((T_RETURN("%s"), _nc_visbuf(TPS(out_buff))));
return (TPS(out_buff));
}
#if NCURSES_TPARM_VARARGS
-#define tparm_varargs tparm
-#else
-#define tparm_proto tparm
-#endif
NCURSES_EXPORT(char *)
-tparm_varargs(const char *string, ...)
+tparm(const char *string, ...)
{
+ TPARM_DATA myData;
va_list ap;
- char *result;
+ char *result = NULL;
_nc_tparm_err = 0;
- va_start(ap, string);
#ifdef TRACE
TPS(tname) = "tparm";
#endif /* TRACE */
- result = tparam_internal(TRUE, string, ap);
- va_end(ap);
+
+ if (tparm_setup(string, &myData) == OK) {
+
+ va_start(ap, string);
+ tparm_copy_valist(&myData, TRUE, ap);
+ va_end(ap);
+
+ result = tparam_internal(string, &myData);
+ }
return result;
}
-#if !NCURSES_TPARM_VARARGS
+#else /* !NCURSES_TPARM_VARARGS */
+
NCURSES_EXPORT(char *)
-tparm_proto(const char *string,
- TPARM_ARG a1,
- TPARM_ARG a2,
- TPARM_ARG a3,
- TPARM_ARG a4,
- TPARM_ARG a5,
- TPARM_ARG a6,
- TPARM_ARG a7,
- TPARM_ARG a8,
- TPARM_ARG a9)
+tparm(const char *string,
+ TPARM_ARG a1,
+ TPARM_ARG a2,
+ TPARM_ARG a3,
+ TPARM_ARG a4,
+ TPARM_ARG a5,
+ TPARM_ARG a6,
+ TPARM_ARG a7,
+ TPARM_ARG a8,
+ TPARM_ARG a9)
{
- return tparm_varargs(string, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ TPARM_DATA myData;
+ char *result = NULL;
+
+ _nc_tparm_err = 0;
+#ifdef TRACE
+ TPS(tname) = "tparm";
+#endif /* TRACE */
+
+ if (tparm_setup(string, &myData) == OK) {
+
+ myData.param[0] = a1;
+ myData.param[1] = a2;
+ myData.param[2] = a3;
+ myData.param[3] = a4;
+ myData.param[4] = a5;
+ myData.param[5] = a6;
+ myData.param[6] = a7;
+ myData.param[7] = a8;
+ myData.param[8] = a9;
+
+ result = tparam_internal(string, &myData);
+ }
+ return result;
}
+
#endif /* NCURSES_TPARM_VARARGS */
NCURSES_EXPORT(char *)
tiparm(const char *string, ...)
{
+ TPARM_DATA myData;
va_list ap;
- char *result;
+ char *result = NULL;
_nc_tparm_err = 0;
- va_start(ap, string);
#ifdef TRACE
TPS(tname) = "tiparm";
#endif /* TRACE */
- result = tparam_internal(FALSE, string, ap);
- va_end(ap);
+
+ if (tparm_setup(string, &myData) == OK) {
+
+ va_start(ap, string);
+ tparm_copy_valist(&myData, FALSE, ap);
+ va_end(ap);
+
+ result = tparam_internal(string, &myData);
+ }
+ return result;
+}
+
+/*
+ * The internal-use flavor ensures that the parameters are numbers, not strings
+ */
+NCURSES_EXPORT(char *)
+_nc_tiparm(int expected, const char *string, ...)
+{
+ TPARM_DATA myData;
+ va_list ap;
+ char *result = NULL;
+
+ _nc_tparm_err = 0;
+#ifdef TRACE
+ TPS(tname) = "_nc_tiparm";
+#endif /* TRACE */
+
+ if (tparm_setup(string, &myData) == OK
+ && myData.num_actual <= expected
+ && myData.tparm_type == 0) {
+
+ va_start(ap, string);
+ tparm_copy_valist(&myData, FALSE, ap);
+ va_end(ap);
+
+ result = tparam_internal(string, &myData);
+ }
return result;
}
diff --git a/ncurses/tinfo/lib_tputs.c b/ncurses/tinfo/lib_tputs.c
index bfde26efd980..3eb19d2d9662 100644
--- a/ncurses/tinfo/lib_tputs.c
+++ b/ncurses/tinfo/lib_tputs.c
@@ -52,7 +52,7 @@
#include <termcap.h> /* ospeed */
#include <tic.h>
-MODULE_ID("$Id: lib_tputs.c,v 1.103 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_tputs.c,v 1.106 2020/11/29 00:40:08 tom Exp $")
NCURSES_EXPORT_VAR(char) PC = 0; /* used by termcap library */
NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed = 0; /* used by termcap library */
@@ -120,16 +120,21 @@ delay_output(int ms)
NCURSES_EXPORT(void)
NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_DCL0)
{
+ T((T_CALLED("_nc_flush(%p)"), (void *) SP_PARM));
if (SP_PARM != 0 && SP_PARM->_ofd >= 0) {
+ TR(TRACE_CHARPUT, ("ofd:%d inuse:%lu buffer:%p",
+ SP_PARM->_ofd,
+ (unsigned long) SP_PARM->out_inuse,
+ SP_PARM->out_buffer));
if (SP_PARM->out_inuse) {
char *buf = SP_PARM->out_buffer;
size_t amount = SP->out_inuse;
SP->out_inuse = 0;
- TR(TRACE_CHARPUT, ("flushing %ld bytes", (unsigned long) amount));
+ TR(TRACE_CHARPUT, ("flushing %ld/%ld bytes",
+ (unsigned long) amount, _nc_outchars));
while (amount) {
ssize_t res = write(SP_PARM->_ofd, buf, amount);
-
if (res > 0) {
/* if the write was incomplete, try again */
amount -= (size_t) res;
@@ -142,10 +147,15 @@ NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_DCL0)
break; /* an error we can not recover from */
}
}
+ } else if (SP_PARM->out_buffer == 0) {
+ TR(TRACE_CHARPUT, ("flushing stdout"));
+ fflush(stdout);
}
} else {
+ TR(TRACE_CHARPUT, ("flushing stdout"));
fflush(stdout);
}
+ returnVoid;
}
#if NCURSES_SP_FUNCS
diff --git a/ncurses/tinfo/lib_ttyflags.c b/ncurses/tinfo/lib_ttyflags.c
index bfcd64af58b1..6363a805be9c 100644
--- a/ncurses/tinfo/lib_ttyflags.c
+++ b/ncurses/tinfo/lib_ttyflags.c
@@ -42,7 +42,7 @@
#define CUR SP_TERMTYPE
#endif
-MODULE_ID("$Id: lib_ttyflags.c,v 1.34 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: lib_ttyflags.c,v 1.36 2020/09/05 22:54:47 tom Exp $")
NCURSES_EXPORT(int)
NCURSES_SP_NAME(_nc_get_tty_mode) (NCURSES_SP_DCLx TTY * buf)
@@ -156,6 +156,8 @@ NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_DCL0)
#ifdef TERMIOS
if (termp->Ottyb.c_oflag & OFLAGS_TABS)
tab = back_tab = NULL;
+#elif defined(EXP_WIN32_DRIVER)
+ /* noop */
#else
if (termp->Ottyb.sg_flags & XTABS)
tab = back_tab = NULL;
@@ -193,6 +195,8 @@ NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_DCL0)
if (_nc_get_tty_mode(&termp->Nttyb) == OK) {
#ifdef TERMIOS
termp->Nttyb.c_oflag &= (unsigned) (~OFLAGS_TABS);
+#elif defined(EXP_WIN32_DRIVER)
+ /* noop */
#else
termp->Nttyb.sg_flags &= (unsigned) (~XTABS);
#endif
diff --git a/ncurses/tinfo/lib_win32con.c b/ncurses/tinfo/lib_win32con.c
new file mode 100644
index 000000000000..3c0fe8160734
--- /dev/null
+++ b/ncurses/tinfo/lib_win32con.c
@@ -0,0 +1,1256 @@
+/****************************************************************************
+ * Copyright 2020 Thomas E. Dickey *
+ * Copyright 1998-2009,2010 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), to deal in the Software without restriction, including *
+ * without limitation the rights to use, copy, modify, merge, publish, *
+ * distribute, distribute with modifications, sublicense, and/or sell *
+ * copies of the Software, and to permit persons to whom the Software is *
+ * furnished to do so, subject to the following conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included *
+ * in all copies or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+ * *
+ * Except as contained in this notice, the name(s) of the above copyright *
+ * holders shall not be used in advertising or otherwise to promote the *
+ * sale, use or other dealings in this Software without prior written *
+ * authorization. *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Author: Juergen Pfeifer *
+ * and: Thomas E. Dickey *
+ ****************************************************************************/
+
+/*
+ * TODO - GetMousePos(POINT * result) from ntconio.c
+ */
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: lib_win32con.c,v 1.6 2020/11/21 23:44:58 tom Exp $")
+
+#ifdef _NC_WINDOWS
+
+#ifdef _NC_MINGW
+#include <wchar.h>
+#else
+#include <tchar.h>
+#endif
+
+#include <io.h>
+
+#if USE_WIDEC_SUPPORT
+#define write_screen WriteConsoleOutputW
+#define read_screen ReadConsoleOutputW
+#else
+#define write_screen WriteConsoleOutput
+#define read_screen ReadConsoleOutput
+#endif
+
+static BOOL IsConsoleHandle(HANDLE hdl);
+static bool save_original_screen(void);
+static bool restore_original_screen(void) GCC_UNUSED;
+static bool read_screen_data(void);
+static int Adjust(int milliseconds, int diff);
+static int decode_mouse(SCREEN *sp, int mask);
+static bool handle_mouse(SCREEN *sp, MOUSE_EVENT_RECORD mer);
+static int rkeycompare(const void *el1, const void *el2);
+static int keycompare(const void *el1, const void *el2);
+static int MapKey(WORD vKey);
+static int AnsiKey(WORD vKey);
+
+static ULONGLONG tdiff(FILETIME fstart, FILETIME fend);
+
+#define GenMap(vKey,key) MAKELONG(key, vKey)
+static const LONG keylist[] =
+{
+ GenMap(VK_PRIOR, KEY_PPAGE),
+ GenMap(VK_NEXT, KEY_NPAGE),
+ GenMap(VK_END, KEY_END),
+ GenMap(VK_HOME, KEY_HOME),
+ GenMap(VK_LEFT, KEY_LEFT),
+ GenMap(VK_UP, KEY_UP),
+ GenMap(VK_RIGHT, KEY_RIGHT),
+ GenMap(VK_DOWN, KEY_DOWN),
+ GenMap(VK_DELETE, KEY_DC),
+ GenMap(VK_INSERT, KEY_IC)
+};
+static const LONG ansi_keys[] =
+{
+ GenMap(VK_PRIOR, 'I'),
+ GenMap(VK_NEXT, 'Q'),
+ GenMap(VK_END, 'O'),
+ GenMap(VK_HOME, 'H'),
+ GenMap(VK_LEFT, 'K'),
+ GenMap(VK_UP, 'H'),
+ GenMap(VK_RIGHT, 'M'),
+ GenMap(VK_DOWN, 'P'),
+ GenMap(VK_DELETE, 'S'),
+ GenMap(VK_INSERT, 'R')
+};
+#define array_length(a) (sizeof(a)/sizeof(a[0]))
+#define N_INI ((int)array_length(keylist))
+#define FKEYS 24
+#define MAPSIZE (FKEYS + N_INI)
+
+/* A process can only have a single console, so it's safe
+ to maintain all the information about it in a single
+ static structure.
+ */
+NCURSES_EXPORT_VAR(ConsoleInfo) _nc_CONSOLE;
+static bool console_initialized = FALSE;
+
+#define EnsureInit() (void)(console_initialized ? TRUE : _nc_console_checkinit(TRUE, TRUE))
+
+#define REQUIRED_MAX_V (DWORD)10
+#define REQUIRED_MIN_V (DWORD)0
+#define REQUIRED_BUILD (DWORD)17763
+/*
+ This function returns 0 if the Windows version has no support for
+ the modern Console interface, otherwise it returns 1
+ */
+NCURSES_EXPORT(int)
+_nc_console_vt_supported(void)
+{
+ OSVERSIONINFO osvi;
+ int res = 0;
+
+ T((T_CALLED("lib_win32con::_nc_console_vt_supported")));
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ GetVersionEx(&osvi);
+ T(("GetVersionEx returnedMajor=%ld, Minor=%ld, Build=%ld",
+ osvi.dwMajorVersion,
+ osvi.dwMinorVersion,
+ osvi.dwBuildNumber));
+ if (osvi.dwMajorVersion >= REQUIRED_MAX_V) {
+ if (osvi.dwMajorVersion == REQUIRED_MAX_V) {
+ if (((osvi.dwMinorVersion == REQUIRED_MIN_V) &&
+ (osvi.dwBuildNumber >= REQUIRED_BUILD)) ||
+ ((osvi.dwMinorVersion > REQUIRED_MIN_V)))
+ res = 1;
+ } else
+ res = 1;
+ }
+ returnCode(res);
+}
+
+NCURSES_EXPORT(void)
+_nc_console_size(int* Lines, int* Cols)
+{
+ EnsureInit();
+ if (Lines != NULL && Cols != NULL) {
+ if (WINCONSOLE.buffered) {
+ *Lines = (int) (WINCONSOLE.SBI.dwSize.Y);
+ *Cols = (int) (WINCONSOLE.SBI.dwSize.X);
+ } else {
+ *Lines = (int) (WINCONSOLE.SBI.srWindow.Bottom + 1 -
+ WINCONSOLE.SBI.srWindow.Top);
+ *Cols = (int) (WINCONSOLE.SBI.srWindow.Right + 1 -
+ WINCONSOLE.SBI.srWindow.Left);
+ }
+ }
+}
+
+/* Convert a file descriptor into a HANDLE
+ That's not necessarily a console HANDLE
+*/
+NCURSES_EXPORT(HANDLE)
+_nc_console_handle(int fd)
+{
+ intptr_t value = _get_osfhandle(fd);
+ return (HANDLE) value;
+}
+
+/* Validate that a HANDLE is actually a
+ console HANDLE
+*/
+static BOOL
+IsConsoleHandle(HANDLE hdl)
+{
+ DWORD dwFlag = 0;
+ BOOL result = FALSE;
+
+ T((T_CALLED("lib_win32con::IsConsoleHandle(HANDLE=%p"), hdl));
+
+ EnsureInit();
+
+ if (!GetConsoleMode(hdl, &dwFlag)) {
+ T(("GetConsoleMode failed"));
+ } else {
+ result = TRUE;
+ }
+
+ returnBool(result);
+}
+
+/* This is used when running in terminfo mode to discover,
+ whether or not the "terminal" is actually a Windows
+ Console. It's the responsibility of the console to deal
+ with the terminal escape sequences that are sent by
+ terminfo.
+ */
+NCURSES_EXPORT(int)
+_nc_console_test(int fd)
+{
+ int code = 0;
+ HANDLE hdl = INVALID_HANDLE_VALUE;
+ T((T_CALLED("lib_win32con::_nc_console_test(%d)"), fd));
+ hdl = _nc_console_handle(fd);
+ code = (int) IsConsoleHandle(hdl);
+ returnCode(code);
+}
+
+#define OutHandle() ((WINCONSOLE.isTermInfoConsole || WINCONSOLE.progMode) ? WINCONSOLE.hdl : WINCONSOLE.out)
+
+NCURSES_EXPORT(void)
+_nc_console_selectActiveHandle(void)
+{
+ if (WINCONSOLE.lastOut != WINCONSOLE.hdl) {
+ WINCONSOLE.lastOut = WINCONSOLE.hdl;
+ SetConsoleActiveScreenBuffer(WINCONSOLE.lastOut);
+ }
+}
+
+NCURSES_EXPORT(HANDLE)
+_nc_console_fd2handle(int fd)
+{
+ HANDLE hdl = _nc_console_handle(fd);
+ if (hdl==WINCONSOLE.inp) {
+ T(("lib_win32con:validateHandle %d -> WINCONSOLE.inp", fd));
+ } else if (hdl==WINCONSOLE.hdl) {
+ T(("lib_win32con:validateHandle %d -> WINCONSOLE.hdl", fd));
+ } else if (hdl==WINCONSOLE.out) {
+ T(("lib_win32con:validateHandle %d -> WINCONSOLE.out", fd));
+ } else {
+ T(("lib_win32con:validateHandle %d maps to unknown HANDLE", fd));
+ hdl = INVALID_HANDLE_VALUE;
+ }
+#if 1
+ assert(hdl != INVALID_HANDLE_VALUE);
+#endif
+ if (hdl != INVALID_HANDLE_VALUE) {
+ if (hdl != WINCONSOLE.inp && (!WINCONSOLE.isTermInfoConsole && WINCONSOLE.progMode)) {
+ if (hdl==WINCONSOLE.out && hdl!=WINCONSOLE.hdl) {
+ T(("lib_win32con:validateHandle forcing WINCONSOLE.out -> WINCONSOLE.hdl"));
+ hdl = WINCONSOLE.hdl;
+ }
+ }
+ }
+ return hdl;
+}
+
+NCURSES_EXPORT(int)
+_nc_console_setmode(HANDLE hdl, const TTY *arg)
+{
+ DWORD dwFlag = 0;
+ int code = ERR;
+ HANDLE alt;
+
+ if (arg) {
+#ifdef TRACE
+ TTY TRCTTY;
+#define TRCTTYOUT(flag) TRCTTY.dwFlagOut = flag
+#define TRCTTYIN(flag) TRCTTY.dwFlagIn = flag
+#else
+#define TRCTTYOUT(flag)
+#define TRCTTYIN(flag)
+#endif
+ T(("lib_win32con:_nc_console_setmode %s", _nc_trace_ttymode(arg)));
+ if (hdl==WINCONSOLE.inp) {
+ dwFlag = arg->dwFlagIn | ENABLE_MOUSE_INPUT | VT_FLAG_IN;
+ if (WINCONSOLE.isTermInfoConsole)
+ dwFlag |= (VT_FLAG_IN);
+ else
+ dwFlag &= (DWORD) ~(VT_FLAG_IN);
+ TRCTTYIN(dwFlag);
+ SetConsoleMode(hdl, dwFlag);
+
+ alt = OutHandle();
+ dwFlag = arg->dwFlagOut;
+ if (WINCONSOLE.isTermInfoConsole)
+ dwFlag |= (VT_FLAG_OUT);
+ else
+ dwFlag |= (VT_FLAG_OUT);
+ TRCTTYOUT(dwFlag);
+ SetConsoleMode(alt, dwFlag);
+ } else {
+ dwFlag = arg->dwFlagOut;
+ if (WINCONSOLE.isTermInfoConsole)
+ dwFlag |= (VT_FLAG_OUT);
+ else
+ dwFlag |= (VT_FLAG_OUT);
+ TRCTTYOUT(dwFlag);
+ SetConsoleMode(hdl, dwFlag);
+
+ alt = WINCONSOLE.inp;
+ dwFlag = arg->dwFlagIn | ENABLE_MOUSE_INPUT;
+ if (WINCONSOLE.isTermInfoConsole)
+ dwFlag |= (VT_FLAG_IN);
+ else
+ dwFlag &= (DWORD) ~(VT_FLAG_IN);
+ TRCTTYIN(dwFlag);
+ SetConsoleMode(alt, dwFlag);
+ T(("effective mode set %s", _nc_trace_ttymode(&TRCTTY)));
+ }
+ code = OK;
+ }
+ return(code);
+}
+
+NCURSES_EXPORT(int)
+_nc_console_getmode(HANDLE hdl, TTY *arg)
+{
+ int code = ERR;
+
+ if (arg) {
+ DWORD dwFlag = 0;
+ HANDLE alt;
+
+ if (hdl==WINCONSOLE.inp) {
+ if(GetConsoleMode(hdl, &dwFlag)) {
+ arg->dwFlagIn = dwFlag;
+ alt = OutHandle();
+ if (GetConsoleMode(alt, &dwFlag)) {
+ arg->dwFlagOut = dwFlag;
+ code = OK;
+ }
+ }
+ } else {
+ if (GetConsoleMode(hdl, &dwFlag)) {
+ arg->dwFlagOut = dwFlag;
+ alt = WINCONSOLE.inp;
+ if (GetConsoleMode(alt, &dwFlag)) {
+ arg->dwFlagIn = dwFlag;
+ code = OK;
+ }
+ }
+ }
+ }
+ T(("lib_win32con:_nc_console_getmode %s", _nc_trace_ttymode(arg)));
+ return(code);
+}
+
+NCURSES_EXPORT(int)
+_nc_console_flush(HANDLE hdl)
+{
+ int code = OK;
+
+ T((T_CALLED("lib_win32con::_nc_console_flush(hdl=%p"), hdl));
+
+ if (hdl != INVALID_HANDLE_VALUE) {
+ if (hdl == WINCONSOLE.hdl ||
+ hdl == WINCONSOLE.inp ||
+ hdl == WINCONSOLE.out) {
+ if (!FlushConsoleInputBuffer(WINCONSOLE.inp))
+ code = ERR;
+ } else {
+ code = ERR;
+ T(("_nc_console_flush not requesting a handle owned by console."));
+ }
+ }
+ returnCode(code);
+}
+
+NCURSES_EXPORT(WORD)
+_nc_console_MapColor(bool fore, int color)
+{
+ static const int _cmap[] =
+ {0, 4, 2, 6, 1, 5, 3, 7};
+ int a;
+ if (color < 0 || color > 7)
+ a = fore ? 7 : 0;
+ else
+ a = _cmap[color];
+ if (!fore)
+ a = a << 4;
+ return (WORD) a;
+}
+
+
+/*
+ * Attempt to save the screen contents. PDCurses does this if
+ * PDC_RESTORE_SCREEN is set, giving the same visual appearance on
+ * restoration as if the library had allocated a console buffer. MSDN
+ * says that the data which can be read is limited to 64Kb (and may be
+ * less).
+ */
+static bool
+save_original_screen(void)
+{
+ bool result = FALSE;
+
+ WINCONSOLE.save_region.Top = 0;
+ WINCONSOLE.save_region.Left = 0;
+ WINCONSOLE.save_region.Bottom = (SHORT) (WINCONSOLE.SBI.dwSize.Y - 1);
+ WINCONSOLE.save_region.Right = (SHORT) (WINCONSOLE.SBI.dwSize.X - 1);
+
+ if (read_screen_data()) {
+ result = TRUE;
+ } else {
+
+ WINCONSOLE.save_region.Top = WINCONSOLE.SBI.srWindow.Top;
+ WINCONSOLE.save_region.Left = WINCONSOLE.SBI.srWindow.Left;
+ WINCONSOLE.save_region.Bottom = WINCONSOLE.SBI.srWindow.Bottom;
+ WINCONSOLE.save_region.Right = WINCONSOLE.SBI.srWindow.Right;
+
+ WINCONSOLE.window_only = TRUE;
+
+ if (read_screen_data()) {
+ result = TRUE;
+ }
+ }
+
+ T(("... save original screen contents %s", result ? "ok" : "err"));
+ return result;
+}
+
+static bool
+restore_original_screen(void)
+{
+ COORD bufferCoord;
+ bool result = FALSE;
+ SMALL_RECT save_region = WINCONSOLE.save_region;
+
+ T(("... restoring %s",
+ WINCONSOLE.window_only ? "window" : "entire buffer"));
+
+ bufferCoord.X = (SHORT) (WINCONSOLE.window_only ?
+ WINCONSOLE.SBI.srWindow.Left : 0);
+ bufferCoord.Y = (SHORT) (WINCONSOLE.window_only ?
+ WINCONSOLE.SBI.srWindow.Top : 0);
+
+ if (write_screen(WINCONSOLE.hdl,
+ WINCONSOLE.save_screen,
+ WINCONSOLE.save_size,
+ bufferCoord,
+ &save_region)) {
+ result = TRUE;
+ mvcur(-1, -1, LINES - 2, 0);
+ T(("... restore original screen contents ok %dx%d (%d,%d - %d,%d)",
+ WINCONSOLE.save_size.Y,
+ WINCONSOLE.save_size.X,
+ save_region.Top,
+ save_region.Left,
+ save_region.Bottom,
+ save_region.Right));
+ } else {
+ T(("... restore original screen contents err"));
+ }
+ return result;
+}
+
+static bool
+read_screen_data(void)
+{
+ bool result = FALSE;
+ COORD bufferCoord;
+ size_t want;
+
+ WINCONSOLE.save_size.X = (SHORT) (WINCONSOLE.save_region.Right
+ - WINCONSOLE.save_region.Left + 1);
+ WINCONSOLE.save_size.Y = (SHORT) (WINCONSOLE.save_region.Bottom
+ - WINCONSOLE.save_region.Top + 1);
+
+ want = (size_t) (WINCONSOLE.save_size.X * WINCONSOLE.save_size.Y);
+
+ if ((WINCONSOLE.save_screen = malloc(want * sizeof(CHAR_INFO))) != 0) {
+ bufferCoord.X = (SHORT) (WINCONSOLE.window_only ?
+ WINCONSOLE.SBI.srWindow.Left : 0);
+ bufferCoord.Y = (SHORT) (WINCONSOLE.window_only ?
+ WINCONSOLE.SBI.srWindow.Top : 0);
+
+ T(("... reading console %s %dx%d into %d,%d - %d,%d at %d,%d",
+ WINCONSOLE.window_only ? "window" : "buffer",
+ WINCONSOLE.save_size.Y, WINCONSOLE.save_size.X,
+ WINCONSOLE.save_region.Top,
+ WINCONSOLE.save_region.Left,
+ WINCONSOLE.save_region.Bottom,
+ WINCONSOLE.save_region.Right,
+ bufferCoord.Y,
+ bufferCoord.X));
+
+ if (read_screen(WINCONSOLE.hdl,
+ WINCONSOLE.save_screen,
+ WINCONSOLE.save_size,
+ bufferCoord,
+ &WINCONSOLE.save_region)) {
+ result = TRUE;
+ } else {
+ T((" error %#lx", (unsigned long) GetLastError()));
+ FreeAndNull(WINCONSOLE.save_screen);
+ }
+ }
+
+ return result;
+}
+
+NCURSES_EXPORT(bool)
+_nc_console_get_SBI(void)
+{
+ bool rc = FALSE;
+ if (GetConsoleScreenBufferInfo(WINCONSOLE.hdl, &(WINCONSOLE.SBI))) {
+ T(("GetConsoleScreenBufferInfo"));
+ T(("... buffer(X:%d Y:%d)",
+ WINCONSOLE.SBI.dwSize.X,
+ WINCONSOLE.SBI.dwSize.Y));
+ T(("... window(X:%d Y:%d)",
+ WINCONSOLE.SBI.dwMaximumWindowSize.X,
+ WINCONSOLE.SBI.dwMaximumWindowSize.Y));
+ T(("... cursor(X:%d Y:%d)",
+ WINCONSOLE.SBI.dwCursorPosition.X,
+ WINCONSOLE.SBI.dwCursorPosition.Y));
+ T(("... display(Top:%d Bottom:%d Left:%d Right:%d)",
+ WINCONSOLE.SBI.srWindow.Top,
+ WINCONSOLE.SBI.srWindow.Bottom,
+ WINCONSOLE.SBI.srWindow.Left,
+ WINCONSOLE.SBI.srWindow.Right));
+ if (WINCONSOLE.buffered) {
+ WINCONSOLE.origin.X = 0;
+ WINCONSOLE.origin.Y = 0;
+ } else {
+ WINCONSOLE.origin.X = WINCONSOLE.SBI.srWindow.Left;
+ WINCONSOLE.origin.Y = WINCONSOLE.SBI.srWindow.Top;
+ }
+ rc = TRUE;
+ } else {
+ T(("GetConsoleScreenBufferInfo ERR"));
+ }
+ return rc;
+}
+
+#define MIN_WIDE 80
+#define MIN_HIGH 24
+
+/*
+ * In "normal" mode, reset the buffer- and window-sizes back to their original values.
+ */
+NCURSES_EXPORT(void)
+_nc_console_set_scrollback(bool normal, CONSOLE_SCREEN_BUFFER_INFO * info)
+{
+ SMALL_RECT rect;
+ COORD coord;
+ bool changed = FALSE;
+
+ T((T_CALLED("lib_win32con::_nc_console_set_scrollback(%s)"),
+ (normal
+ ? "normal"
+ : "application")));
+
+ T(("... SBI.srWindow %d,%d .. %d,%d",
+ info->srWindow.Top,
+ info->srWindow.Left,
+ info->srWindow.Bottom,
+ info->srWindow.Right));
+ T(("... SBI.dwSize %dx%d",
+ info->dwSize.Y,
+ info->dwSize.X));
+
+ if (normal) {
+ rect = info->srWindow;
+ coord = info->dwSize;
+ if (memcmp(info, &WINCONSOLE.SBI, sizeof(*info)) != 0) {
+ changed = TRUE;
+ WINCONSOLE.SBI = *info;
+ }
+ } else {
+ int high = info->srWindow.Bottom - info->srWindow.Top + 1;
+ int wide = info->srWindow.Right - info->srWindow.Left + 1;
+
+ if (high < MIN_HIGH) {
+ T(("... height %d < %d", high, MIN_HIGH));
+ high = MIN_HIGH;
+ changed = TRUE;
+ }
+ if (wide < MIN_WIDE) {
+ T(("... width %d < %d", wide, MIN_WIDE));
+ wide = MIN_WIDE;
+ changed = TRUE;
+ }
+
+ rect.Left =
+ rect.Top = 0;
+ rect.Right = (SHORT) (wide - 1);
+ rect.Bottom = (SHORT) (high - 1);
+
+ coord.X = (SHORT) wide;
+ coord.Y = (SHORT) high;
+
+ if (info->dwSize.Y != high ||
+ info->dwSize.X != wide ||
+ info->srWindow.Top != 0 ||
+ info->srWindow.Left != 0) {
+ changed = TRUE;
+ }
+
+ }
+
+ if (changed) {
+ T(("... coord %d,%d", coord.Y, coord.X));
+ T(("... rect %d,%d - %d,%d",
+ rect.Top, rect.Left,
+ rect.Bottom, rect.Right));
+ SetConsoleScreenBufferSize(WINCONSOLE.hdl, coord); /* dwSize */
+ SetConsoleWindowInfo(WINCONSOLE.hdl, TRUE, &rect); /* srWindow */
+ _nc_console_get_SBI();
+ }
+ returnVoid;
+}
+
+static ULONGLONG
+tdiff(FILETIME fstart, FILETIME fend)
+{
+ ULARGE_INTEGER ustart;
+ ULARGE_INTEGER uend;
+ ULONGLONG diff;
+
+ ustart.LowPart = fstart.dwLowDateTime;
+ ustart.HighPart = fstart.dwHighDateTime;
+ uend.LowPart = fend.dwLowDateTime;
+ uend.HighPart = fend.dwHighDateTime;
+
+ diff = (uend.QuadPart - ustart.QuadPart) / 10000;
+ return diff;
+}
+
+static int
+Adjust(int milliseconds, int diff)
+{
+ if (milliseconds != INFINITY) {
+ milliseconds -= diff;
+ if (milliseconds < 0)
+ milliseconds = 0;
+ }
+ return milliseconds;
+}
+
+#define BUTTON_MASK (FROM_LEFT_1ST_BUTTON_PRESSED | \
+ FROM_LEFT_2ND_BUTTON_PRESSED | \
+ FROM_LEFT_3RD_BUTTON_PRESSED | \
+ FROM_LEFT_4TH_BUTTON_PRESSED | \
+ RIGHTMOST_BUTTON_PRESSED)
+
+static int
+decode_mouse(SCREEN *sp, int mask)
+{
+ int result = 0;
+
+ (void) sp;
+ assert(sp && console_initialized);
+
+ if (mask & FROM_LEFT_1ST_BUTTON_PRESSED)
+ result |= BUTTON1_PRESSED;
+ if (mask & FROM_LEFT_2ND_BUTTON_PRESSED)
+ result |= BUTTON2_PRESSED;
+ if (mask & FROM_LEFT_3RD_BUTTON_PRESSED)
+ result |= BUTTON3_PRESSED;
+ if (mask & FROM_LEFT_4TH_BUTTON_PRESSED)
+ result |= BUTTON4_PRESSED;
+
+ if (mask & RIGHTMOST_BUTTON_PRESSED) {
+ switch (WINCONSOLE.numButtons) {
+ case 1:
+ result |= BUTTON1_PRESSED;
+ break;
+ case 2:
+ result |= BUTTON2_PRESSED;
+ break;
+ case 3:
+ result |= BUTTON3_PRESSED;
+ break;
+ case 4:
+ result |= BUTTON4_PRESSED;
+ break;
+ }
+ }
+
+ return result;
+}
+
+#define AdjustY() (WINCONSOLE.buffered ? 0 : (int) WINCONSOLE.SBI.srWindow.Top)
+
+static bool
+handle_mouse(SCREEN *sp, MOUSE_EVENT_RECORD mer)
+{
+ MEVENT work;
+ bool result = FALSE;
+
+ assert(sp);
+
+ sp->_drv_mouse_old_buttons = sp->_drv_mouse_new_buttons;
+ sp->_drv_mouse_new_buttons = mer.dwButtonState & BUTTON_MASK;
+
+ /*
+ * We're only interested if the button is pressed or released.
+ * FIXME: implement continuous event-tracking.
+ */
+ if (sp->_drv_mouse_new_buttons != sp->_drv_mouse_old_buttons) {
+ memset(&work, 0, sizeof(work));
+
+ if (sp->_drv_mouse_new_buttons) {
+ work.bstate |=
+ (mmask_t) decode_mouse(sp,
+ sp->_drv_mouse_new_buttons);
+ } else {
+ /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
+ work.bstate |=
+ (mmask_t) (decode_mouse(sp,
+ sp->_drv_mouse_old_buttons)
+ >> 1);
+ result = TRUE;
+ }
+
+ work.x = mer.dwMousePosition.X;
+ work.y = mer.dwMousePosition.Y - AdjustY();
+
+ sp->_drv_mouse_fifo[sp->_drv_mouse_tail] = work;
+ sp->_drv_mouse_tail += 1;
+ }
+ return result;
+}
+
+static int
+rkeycompare(const void *el1, const void *el2)
+{
+ WORD key1 = (LOWORD((*((const LONG *) el1)))) & 0x7fff;
+ WORD key2 = (LOWORD((*((const LONG *) el2)))) & 0x7fff;
+
+ return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
+}
+
+
+static int
+keycompare(const void *el1, const void *el2)
+{
+ WORD key1 = HIWORD((*((const LONG *) el1)));
+ WORD key2 = HIWORD((*((const LONG *) el2)));
+
+ return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
+}
+
+static int
+MapKey(WORD vKey)
+{
+ int code = -1;
+
+ if (!WINCONSOLE.isTermInfoConsole) {
+ WORD nKey = 0;
+ void *res;
+ LONG key = GenMap(vKey, 0);
+
+ res = bsearch(&key,
+ WINCONSOLE.map,
+ (size_t) (N_INI + FKEYS),
+ sizeof(keylist[0]),
+ keycompare);
+ if (res) {
+ key = *((LONG *) res);
+ nKey = LOWORD(key);
+ code = (int) (nKey & 0x7fff);
+ if (nKey & 0x8000)
+ code = -code;
+ }
+ }
+ return code;
+}
+
+static int
+AnsiKey(WORD vKey)
+{
+ int code = -1;
+
+ if (!WINCONSOLE.isTermInfoConsole) {
+ WORD nKey = 0;
+ void *res;
+ LONG key = GenMap(vKey, 0);
+
+ res = bsearch(&key,
+ WINCONSOLE.ansi_map,
+ (size_t) (N_INI + FKEYS),
+ sizeof(keylist[0]),
+ keycompare);
+ if (res) {
+ key = *((LONG *) res);
+ nKey = LOWORD(key);
+ code = (int) (nKey & 0x7fff);
+ if (nKey & 0x8000)
+ code = -code;
+ }
+ }
+ return code;
+}
+
+NCURSES_EXPORT(int)
+_nc_console_keyok(int keycode, int flag)
+{
+ int code = ERR;
+ WORD nKey;
+ WORD vKey;
+ void *res;
+ LONG key = GenMap(0, (WORD) keycode);
+
+ T((T_CALLED("lib_win32con::_nc_console_keyok(%d, %d)"), keycode, flag));
+
+ res = bsearch(&key,
+ WINCONSOLE.rmap,
+ (size_t) (N_INI + FKEYS),
+ sizeof(keylist[0]),
+ rkeycompare);
+ if (res) {
+ key = *((LONG *) res);
+ vKey = HIWORD(key);
+ nKey = (LOWORD(key)) & 0x7fff;
+ if (!flag)
+ nKey |= 0x8000;
+ *(LONG *) res = GenMap(vKey, nKey);
+ }
+ returnCode(code);
+}
+
+NCURSES_EXPORT(bool)
+_nc_console_keyExist(int keycode)
+{
+ WORD nKey;
+ void *res;
+ bool found = FALSE;
+ LONG key = GenMap(0, (WORD) keycode);
+
+ T((T_CALLED("lib_win32con::_nc_console_keyExist(%d)"), keycode));
+ res = bsearch(&key,
+ WINCONSOLE.rmap,
+ (size_t) (N_INI + FKEYS),
+ sizeof(keylist[0]),
+ rkeycompare);
+ if (res) {
+ key = *((LONG *) res);
+ nKey = LOWORD(key);
+ if (!(nKey & 0x8000))
+ found = TRUE;
+ }
+ returnCode(found);
+}
+
+NCURSES_EXPORT(int)
+_nc_console_twait(
+ SCREEN *sp,
+ HANDLE hdl,
+ int mode,
+ int milliseconds,
+ int *timeleft
+ EVENTLIST_2nd(_nc_eventlist * evl))
+{
+ INPUT_RECORD inp_rec;
+ BOOL b;
+ DWORD nRead = 0, rc = (DWORD) (-1);
+ int code = 0;
+ FILETIME fstart;
+ FILETIME fend;
+ int diff;
+ bool isNoDelay = (milliseconds == 0);
+
+#ifdef NCURSES_WGETCH_EVENTS
+ (void) evl; /* TODO: implement wgetch-events */
+#endif
+
+#define IGNORE_CTRL_KEYS (SHIFT_PRESSED|LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED| \
+ LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)
+#define CONSUME() ReadConsoleInput(hdl, &inp_rec, 1, &nRead)
+
+ assert(sp);
+
+ TR(TRACE_IEVENT, ("start twait: hdl=%p, %d milliseconds, mode: %d",
+ hdl, milliseconds, mode));
+
+ if (milliseconds < 0)
+ milliseconds = INFINITY;
+
+ memset(&inp_rec, 0, sizeof(inp_rec));
+
+ while (true) {
+ if (!isNoDelay) {
+ GetSystemTimeAsFileTime(&fstart);
+ rc = WaitForSingleObject(hdl, (DWORD) milliseconds);
+ GetSystemTimeAsFileTime(&fend);
+ diff = (int) tdiff(fstart, fend);
+ milliseconds = Adjust(milliseconds, diff);
+ if (milliseconds< 0)
+ break;
+ }
+
+ if (isNoDelay || (rc == WAIT_OBJECT_0)) {
+ if (mode) {
+ nRead = 0;
+ b = GetNumberOfConsoleInputEvents(hdl, &nRead);
+ if (!b) {
+ T(("twait:err GetNumberOfConsoleInputEvents"));
+ }
+ if (isNoDelay && b) {
+ T(("twait: Events Available: %ld", nRead));
+ if (nRead==0) {
+ code = 0;
+ goto end;
+ } else {
+ DWORD n = 0;
+ INPUT_RECORD* pInpRec =
+ TypeAlloca(INPUT_RECORD, nRead);
+ if (pInpRec != NULL) {
+ DWORD i;
+ BOOL f;
+ memset(pInpRec, 0, sizeof(INPUT_RECORD)*nRead);
+ f = PeekConsoleInput(hdl, pInpRec, nRead, &n);
+ if (f) {
+ for(i = 0; i < n; i++) {
+ if (pInpRec[i].EventType==KEY_EVENT) {
+ if(pInpRec[i].Event.KeyEvent.bKeyDown) {
+ DWORD ctrlMask =
+ (pInpRec[i].Event.KeyEvent.dwControlKeyState &
+ IGNORE_CTRL_KEYS);
+ if (!ctrlMask) {
+ code = TW_INPUT;
+ goto end;
+ }
+ }
+ }
+ }
+ } else {
+ T(("twait:err PeekConsoleInput"));
+ }
+ code = 0;
+ goto end;
+ } else {
+ T(("twait:err could not alloca input records"));
+ }
+ }
+ }
+ if (b && nRead > 0) {
+ b = PeekConsoleInput(hdl, &inp_rec, 1, &nRead);
+ if (!b) {
+ T(("twait:err PeekConsoleInput"));
+ }
+ if (b && nRead > 0) {
+ switch (inp_rec.EventType) {
+ case KEY_EVENT:
+ if (mode & TW_INPUT) {
+ WORD vk =
+ inp_rec.Event.KeyEvent.wVirtualKeyCode;
+ char ch =
+ inp_rec.Event.KeyEvent.uChar.AsciiChar;
+ T(("twait:event KEY_EVENT"));
+ T(("twait vk=%d, ch=%d, keydown=%d",
+ vk, ch, inp_rec.Event.KeyEvent.bKeyDown));
+ if (inp_rec.Event.KeyEvent.bKeyDown) {
+ T(("twait:event KeyDown"));
+ if (!WINCONSOLE.isTermInfoConsole &&
+ (0 == ch)) {
+ int nKey = MapKey(vk);
+ if (nKey < 0) {
+ CONSUME();
+ continue;
+ }
+ }
+ code = TW_INPUT;
+ goto end;
+ } else {
+ CONSUME();
+ }
+ }
+ continue;
+ case MOUSE_EVENT:
+ T(("twait:event MOUSE_EVENT"));
+ if (decode_mouse(sp,
+ (inp_rec.Event.MouseEvent.dwButtonState
+ & BUTTON_MASK)) == 0) {
+ CONSUME();
+ } else if (mode & TW_MOUSE) {
+ code = TW_MOUSE;
+ goto end;
+ }
+ continue;
+ /* e.g., FOCUS_EVENT */
+ default:
+ T(("twait:event Tyoe %d", inp_rec.EventType));
+ CONSUME();
+ _nc_console_selectActiveHandle();
+ continue;
+ }
+ }
+ }
+ }
+ continue;
+ } else {
+ if (rc != WAIT_TIMEOUT) {
+ code = -1;
+ break;
+ } else {
+ code = 0;
+ break;
+ }
+ }
+ }
+end:
+
+ TR(TRACE_IEVENT, ("end twait: returned %d (%lu), remaining time %d msec",
+ code, GetLastError(), milliseconds));
+
+ if (timeleft)
+ *timeleft = milliseconds;
+
+ return code;
+}
+
+NCURSES_EXPORT(int)
+_nc_console_testmouse(
+ SCREEN *sp,
+ HANDLE hdl,
+ int delay
+ EVENTLIST_2nd(_nc_eventlist * evl))
+{
+ int rc = 0;
+
+ assert(sp);
+
+ if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
+ rc = TW_MOUSE;
+ } else {
+ rc = _nc_console_twait(sp,
+ hdl,
+ TWAIT_MASK,
+ delay,
+ (int *) 0
+ EVENTLIST_2nd(evl));
+ }
+ return rc;
+}
+
+NCURSES_EXPORT(int)
+_nc_console_read(
+ SCREEN *sp,
+ HANDLE hdl,
+ int *buf)
+{
+ int rc = -1;
+ INPUT_RECORD inp_rec;
+ BOOL b;
+ DWORD nRead;
+ WORD vk;
+
+ assert(sp);
+ assert(buf);
+
+ memset(&inp_rec, 0, sizeof(inp_rec));
+
+ T((T_CALLED("lib_win32con::_nc_console_read(%p)"), sp));
+
+ while ((b = ReadConsoleInput(hdl, &inp_rec, 1, &nRead))) {
+ if (b && nRead > 0) {
+ if (rc < 0)
+ rc = 0;
+ rc = rc + (int) nRead;
+ if (inp_rec.EventType == KEY_EVENT) {
+ if (!inp_rec.Event.KeyEvent.bKeyDown)
+ continue;
+ *buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar;
+ vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
+ /*
+ * There are 24 virtual function-keys, and typically
+ * 12 function-keys on a keyboard. Use the shift-modifier
+ * to provide the remaining 12 keys.
+ */
+ if (vk >= VK_F1 && vk <= VK_F12) {
+ if (inp_rec.Event.KeyEvent.dwControlKeyState &
+ SHIFT_PRESSED) {
+ vk = (WORD) (vk + 12);
+ }
+ }
+ if (*buf == 0) {
+ int key = MapKey(vk);
+ if (key < 0)
+ continue;
+ if (sp->_keypad_on) {
+ *buf = key;
+ } else {
+ ungetch('\0');
+ *buf = AnsiKey(vk);
+ }
+ }
+ break;
+ } else if (inp_rec.EventType == MOUSE_EVENT) {
+ if (handle_mouse(sp,
+ inp_rec.Event.MouseEvent)) {
+ *buf = KEY_MOUSE;
+ break;
+ }
+ }
+ continue;
+ }
+ }
+ returnCode(rc);
+}
+
+/* Our replacement for the systems _isatty to include also
+ a test for mintty. This is called from the NC_ISATTY macro
+ defined in curses.priv.h
+
+ Return codes:
+ - 0 : Not a TTY
+ - 1 : A Windows character device detected by _isatty
+ - 2 : A future implementation may return 2 for mintty
+ */
+NCURSES_EXPORT(int)
+_nc_console_isatty(int fd)
+{
+ int result = 0;
+ T((T_CALLED("lib_win32con::_nc_console_isatty(%d"), fd));
+
+ if (_isatty(fd))
+ result = 1;
+#ifdef _NC_CHECK_MINTTY
+ else {
+ if (_nc_console_checkmintty(fd, NULL)) {
+ result = 2;
+ fprintf(stderr, "ncurses on Windows must run in a Windows console.\n");
+ fprintf(stderr, "On newer versions of Windows, the calling program should create a PTY-like.\n");
+ fprintf(stderr, "device using the CreatePseudoConsole Windows API call.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+#endif
+ returnCode(result);
+}
+
+NCURSES_EXPORT(bool)
+_nc_console_checkinit(bool initFlag, bool assumeTermInfo)
+{
+ bool res = FALSE;
+
+ T((T_CALLED("lib_win32con::_nc_console_checkinit(initFlag=%d, assumeTermInfo=%d)"),
+ initFlag, assumeTermInfo));
+
+ if (!initFlag) {
+ res = console_initialized;
+ } else {
+ /* initialize once, or not at all */
+ if (!console_initialized) {
+ int i;
+ DWORD num_buttons;
+ WORD a;
+ BOOL buffered = FALSE;
+ BOOL b;
+
+ START_TRACE();
+ WINCONSOLE.isTermInfoConsole = assumeTermInfo;
+
+ WINCONSOLE.map = (LPDWORD)malloc(sizeof(DWORD)*MAPSIZE);
+ WINCONSOLE.rmap = (LPDWORD)malloc(sizeof(DWORD)*MAPSIZE);
+ WINCONSOLE.ansi_map = (LPDWORD)malloc(sizeof(DWORD)*MAPSIZE);
+
+ for (i = 0; i < (N_INI + FKEYS); i++) {
+ if (i < N_INI) {
+ WINCONSOLE.rmap[i] = WINCONSOLE.map[i] =
+ (DWORD) keylist[i];
+ WINCONSOLE.ansi_map[i] = (DWORD) ansi_keys[i];
+ } else {
+ WINCONSOLE.rmap[i] = WINCONSOLE.map[i] =
+ (DWORD) GenMap((VK_F1 + (i - N_INI)),
+ (KEY_F(1) + (i - N_INI)));
+ WINCONSOLE.ansi_map[i] =
+ (DWORD) GenMap((VK_F1 + (i - N_INI)),
+ (';' + (i - N_INI)));
+ }
+ }
+ qsort(WINCONSOLE.ansi_map,
+ (size_t) (MAPSIZE),
+ sizeof(keylist[0]),
+ keycompare);
+ qsort(WINCONSOLE.map,
+ (size_t) (MAPSIZE),
+ sizeof(keylist[0]),
+ keycompare);
+ qsort(WINCONSOLE.rmap,
+ (size_t) (MAPSIZE),
+ sizeof(keylist[0]),
+ rkeycompare);
+
+ if (GetNumberOfConsoleMouseButtons(&num_buttons)) {
+ WINCONSOLE.numButtons = (int) num_buttons;
+ } else {
+ WINCONSOLE.numButtons = 1;
+ }
+
+ a = _nc_console_MapColor(true, COLOR_WHITE) |
+ _nc_console_MapColor(false, COLOR_BLACK);
+ for (i = 0; i < CON_NUMPAIRS; i++)
+ WINCONSOLE.pairs[i] = a;
+
+ WINCONSOLE.inp = GetStdHandle(STD_INPUT_HANDLE);
+ WINCONSOLE.out = GetStdHandle(STD_OUTPUT_HANDLE);
+ WINCONSOLE.hdl = WINCONSOLE.out;
+
+ GetConsoleMode(WINCONSOLE.inp, &WINCONSOLE.originalMode.dwFlagIn);
+ GetConsoleMode(WINCONSOLE.out, &WINCONSOLE.originalMode.dwFlagOut);
+
+ if (!WINCONSOLE.isTermInfoConsole) {
+ b = AllocConsole();
+
+ if (!b)
+ b = AttachConsole(ATTACH_PARENT_PROCESS);
+
+ if (getenv("NCGDB") || getenv("NCURSES_CONSOLE2")) {
+ T(("... will not buffer console"));
+ } else {
+ T(("... creating console buffer"));
+ WINCONSOLE.hdl =
+ CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ CONSOLE_TEXTMODE_BUFFER,
+ NULL);
+ buffered = TRUE;
+ }
+ }
+
+ /* We set binary I/O even when using the console
+ driver to cover the situation, that the
+ TERM variable is set to #win32con, but actually
+ Windows supports virtual terminal processing.
+ So if terminfo functions are used in this setup,
+ they actually may work.
+ */
+ _setmode(fileno(stdin), _O_BINARY);
+ _setmode(fileno(stdout), _O_BINARY);
+
+ if (WINCONSOLE.hdl != INVALID_HANDLE_VALUE) {
+ WINCONSOLE.buffered = buffered;
+ _nc_console_get_SBI();
+ WINCONSOLE.save_SBI = WINCONSOLE.SBI;
+ if (!buffered) {
+ save_original_screen();
+ _nc_console_set_scrollback(FALSE, &WINCONSOLE.SBI);
+ }
+ GetConsoleCursorInfo(WINCONSOLE.hdl, &WINCONSOLE.save_CI);
+ T(("... initial cursor is %svisible, %d%%",
+ (WINCONSOLE.save_CI.bVisible ? "" : "not-"),
+ (int) WINCONSOLE.save_CI.dwSize));
+ }
+
+ WINCONSOLE.initialized = TRUE;
+ console_initialized = TRUE;
+ }
+ res = (WINCONSOLE.hdl != INVALID_HANDLE_VALUE);
+ }
+ returnBool(res);
+}
+
+#endif // _NC_WINDOWS
diff --git a/ncurses/tinfo/lib_win32util.c b/ncurses/tinfo/lib_win32util.c
new file mode 100644
index 000000000000..d5bcd70199ed
--- /dev/null
+++ b/ncurses/tinfo/lib_win32util.c
@@ -0,0 +1,134 @@
+/****************************************************************************
+ * Copyright 2020 Thomas E. Dickey *
+ * Copyright 1998-2009,2010 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), to deal in the Software without restriction, including *
+ * without limitation the rights to use, copy, modify, merge, publish, *
+ * distribute, distribute with modifications, sublicense, and/or sell *
+ * copies of the Software, and to permit persons to whom the Software is *
+ * furnished to do so, subject to the following conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included *
+ * in all copies or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+ * *
+ * Except as contained in this notice, the name(s) of the above copyright *
+ * holders shall not be used in advertising or otherwise to promote the *
+ * sale, use or other dealings in this Software without prior written *
+ * authorization. *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Author: Juergen Pfeifer *
+ * and: Thomas E. Dickey *
+ ****************************************************************************/
+
+#include <curses.priv.h>
+
+MODULE_ID("$Id: lib_win32util.c,v 1.1 2020/08/14 21:57:01 juergen Exp $")
+
+#ifdef _NC_WINDOWS
+#include <io.h>
+
+#ifdef _NC_CHECK_MINTTY
+#define PSAPI_VERSION 2
+#include <psapi.h>
+#include <tchar.h>
+
+#define array_length(a) (sizeof(a)/sizeof(a[0]))
+
+/* This function tests, whether or not the ncurses application
+ is running as a descendant of MSYS2/cygwin mintty terminal
+ application. mintty doesn't use Windows Console for it's screen
+ I/O, so the native Windows _isatty doesn't recognize it as
+ character device. But we can discover we are at the end of an
+ Pipe and can query the server side of the pipe, looking whether
+ or not this is mintty.
+ For now we terminate the program if we discover that situation.
+ Althogh in theory it would be possible, to remotely manipulate
+ the terminal state of mintty, this is out of scope for now and
+ not worth the significant effort.
+ */
+NCURSES_EXPORT(int)
+_nc_console_checkmintty(int fd, LPHANDLE pMinTTY)
+{
+ HANDLE handle = _nc_console_handle(fd);
+ DWORD dw;
+ int code = 0;
+
+ T((T_CALLED("lib_winhelper::_nc_console_checkmintty(%d, %p)"), fd, pMinTTY));
+
+ if (handle != INVALID_HANDLE_VALUE) {
+ dw = GetFileType(handle);
+ if (dw == FILE_TYPE_PIPE) {
+ if (GetNamedPipeInfo(handle, 0, 0, 0, 0)) {
+ ULONG pPid;
+ /* Requires NT6 */
+ if (GetNamedPipeServerProcessId(handle, &pPid)) {
+ TCHAR buf[MAX_PATH];
+ DWORD len = 0;
+ /* These security attributes may allow us to
+ create a remote thread in mintty to manipulate
+ the terminal state remotely */
+ HANDLE pHandle = OpenProcess(
+ PROCESS_CREATE_THREAD
+ | PROCESS_QUERY_INFORMATION
+ | PROCESS_VM_OPERATION
+ | PROCESS_VM_WRITE
+ | PROCESS_VM_READ,
+ FALSE,
+ pPid);
+ if (pMinTTY)
+ *pMinTTY = INVALID_HANDLE_VALUE;
+ if (pHandle != INVALID_HANDLE_VALUE) {
+ if ((len = GetProcessImageFileName(
+ pHandle,
+ buf,
+ (DWORD)
+ array_length(buf)))) {
+ TCHAR *pos = _tcsrchr(buf, _T('\\'));
+ if (pos) {
+ pos++;
+ if (_tcsnicmp(pos, _TEXT("mintty.exe"), 10)
+ == 0) {
+ if (pMinTTY)
+ *pMinTTY = pHandle;
+ code = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ returnCode(code);
+}
+#endif /* _NC_CHECK_MINTTY */
+
+#define JAN1970 116444736000000000LL /* the value for 01/01/1970 00:00 */
+
+NCURSES_EXPORT(int)
+_nc_gettimeofday(struct timeval *tv, void *tz GCC_UNUSED)
+{
+ union {
+ FILETIME ft;
+ long long since1601; /* time since 1 Jan 1601 in 100ns units */
+ } data;
+
+ GetSystemTimeAsFileTime(&data.ft);
+ tv->tv_usec = (long) ((data.since1601 / 10LL) % 1000000LL);
+ tv->tv_sec = (long) ((data.since1601 - JAN1970) / 10000000LL);
+ return (0);
+}
+
+#endif // _NC_WINDOWS
diff --git a/ncurses/tinfo/parse_entry.c b/ncurses/tinfo/parse_entry.c
index 23574b6626bf..ec2d3364234e 100644
--- a/ncurses/tinfo/parse_entry.c
+++ b/ncurses/tinfo/parse_entry.c
@@ -48,7 +48,7 @@
#include <ctype.h>
#include <tic.h>
-MODULE_ID("$Id: parse_entry.c,v 1.99 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: parse_entry.c,v 1.101 2020/10/24 21:37:13 tom Exp $")
#ifdef LINT
static short const parametrized[] =
@@ -544,10 +544,14 @@ _nc_parse_entry(ENTRY * entryp, int literal, bool silent)
case STRING:
ptr = _nc_curr_token.tk_valstring;
- if (_nc_syntax == SYN_TERMCAP)
+ if (_nc_syntax == SYN_TERMCAP) {
+ int n = entry_ptr->nte_index;
ptr = _nc_captoinfo(_nc_curr_token.tk_name,
ptr,
- parametrized[entry_ptr->nte_index]);
+ (n < (int) SIZEOF(parametrized))
+ ? parametrized[n]
+ : 0);
+ }
entryp->tterm.Strings[entry_ptr->nte_index] = _nc_save_str(ptr);
break;
diff --git a/ncurses/tinfo/read_entry.c b/ncurses/tinfo/read_entry.c
index 5b570b0fe192..9741e103b7a9 100644
--- a/ncurses/tinfo/read_entry.c
+++ b/ncurses/tinfo/read_entry.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright 2018-2019,2020 Thomas E. Dickey *
+ * Copyright 2018-2020,2021 Thomas E. Dickey *
* Copyright 1998-2016,2017 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
@@ -42,7 +42,7 @@
#include <tic.h>
-MODULE_ID("$Id: read_entry.c,v 1.157 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: read_entry.c,v 1.159 2021/02/14 00:17:09 tom Exp $")
#define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts))
@@ -160,11 +160,11 @@ convert_strings(char *buf, char **Strings, int count, int size, char *table)
/* make sure all strings are NUL terminated */
if (VALID_STRING(Strings[i])) {
- for (p = Strings[i]; p <= table + size; p++)
+ for (p = Strings[i]; p < table + size; p++)
if (*p == '\0')
break;
/* if there is no NUL, ignore the string */
- if (p > table + size)
+ if (p >= table + size)
Strings[i] = ABSENT_STRING;
}
}
@@ -257,7 +257,6 @@ _nc_read_termtype(TERMTYPE2 *ptr, char *buffer, int limit)
char buf[MAX_ENTRY_SIZE + 2];
char *string_table;
unsigned want, have;
- bool need_ints;
size_t (*convert_numbers) (char *, NCURSES_INT2 *, int);
int size_of_numbers;
int max_entry_size = MAX_ENTRY_SIZE;
@@ -276,7 +275,7 @@ _nc_read_termtype(TERMTYPE2 *ptr, char *buffer, int limit)
returnDB(TGETENT_NO);
}
#if NCURSES_EXT_NUMBERS
- if ((need_ints = (LOW_MSB(buf) == MAGIC2))) {
+ if (LOW_MSB(buf) == MAGIC2) {
convert_numbers = convert_32bits;
size_of_numbers = SIZEOF_INT2;
} else {
@@ -285,7 +284,7 @@ _nc_read_termtype(TERMTYPE2 *ptr, char *buffer, int limit)
size_of_numbers = SIZEOF_SHORT;
}
#else
- if ((need_ints = (LOW_MSB(buf) == MAGIC2))) {
+ if (LOW_MSB(buf) == MAGIC2) {
convert_numbers = convert_32bits;
size_of_numbers = SIZEOF_32BITS;
} else {
@@ -666,11 +665,10 @@ decode_hex(const char **source)
{
int result = 0;
int nibble;
- int ch;
for (nibble = 0; nibble < 2; ++nibble) {
+ int ch = UChar(**source);
result <<= 4;
- ch = UChar(**source);
*source += 1;
if (ch >= '0' && ch <= '9') {
ch -= '0';
diff --git a/ncurses/tinfo/tinfo_driver.c b/ncurses/tinfo/tinfo_driver.c
index 7919a9b09276..c28d76415549 100644
--- a/ncurses/tinfo/tinfo_driver.c
+++ b/ncurses/tinfo/tinfo_driver.c
@@ -52,7 +52,7 @@
# endif
#endif
-MODULE_ID("$Id: tinfo_driver.c,v 1.67 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: tinfo_driver.c,v 1.71 2020/12/12 01:06:40 tom Exp $")
/*
* SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS,
@@ -123,6 +123,8 @@ get_baudrate(TERMINAL *termp)
if (GET_TTY(termp->Filedes, &termp->Nttyb) == OK) {
#ifdef TERMIOS
termp->Nttyb.c_oflag &= (unsigned) (~OFLAGS_TABS);
+#elif defined(EXP_WIN32_DRIVER)
+ /* noop */
#else
termp->Nttyb.sg_flags &= (unsigned) (~XTABS);
#endif
@@ -133,6 +135,9 @@ get_baudrate(TERMINAL *termp)
#else /* !USE_OLD_TTY */
#ifdef TERMIOS
my_ospeed = (NCURSES_OSPEED) cfgetospeed(&(termp->Nttyb));
+#elif defined(EXP_WIN32_DRIVER)
+ /* noop */
+ my_ospeed = 0;
#else
my_ospeed = (NCURSES_OSPEED) termp->Nttyb.sg_ospeed;
#endif
@@ -356,23 +361,23 @@ drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB,
if (set_a_foreground) {
TPUTS_TRACE("set_a_foreground");
NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
- TPARM_1(set_a_foreground, color), 1, outc);
+ TIPARM_1(set_a_foreground, color), 1, outc);
} else {
TPUTS_TRACE("set_foreground");
NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
- TPARM_1(set_foreground,
- toggled_colors(color)), 1, outc);
+ TIPARM_1(set_foreground,
+ toggled_colors(color)), 1, outc);
}
} else {
if (set_a_background) {
TPUTS_TRACE("set_a_background");
NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
- TPARM_1(set_a_background, color), 1, outc);
+ TIPARM_1(set_a_background, color), 1, outc);
} else {
TPUTS_TRACE("set_background");
NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
- TPARM_1(set_background,
- toggled_colors(color)), 1, outc);
+ TIPARM_1(set_background,
+ toggled_colors(color)), 1, outc);
}
}
}
@@ -427,12 +432,19 @@ drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *linep, int *colp)
useTioctl = _nc_prescreen.use_tioctl;
}
+#ifdef EXP_WIN32_DRIVER
+ /* If we are here, then Windows console is used in terminfo mode.
+ We need to figure out the size using the console API
+ */
+ _nc_console_size(linep, colp);
+ T(("screen size: winconsole lines = %d columns = %d", *linep, *colp));
+#else
/* figure out the size of the screen */
T(("screen size: terminfo lines = %d columns = %d", lines, columns));
*linep = (int) lines;
*colp = (int) columns;
-
+#endif
if (useEnv || useTioctl) {
int value;
@@ -602,6 +614,8 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
if ((drv_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
#ifdef TERMIOS
_term->Nttyb.c_oflag &= (unsigned) ~OFLAGS_TABS;
+#elif defined(EXP_WIN32_DRIVER)
+ /* noop */
#else
_term->Nttyb.sg_flags &= (unsigned) ~XTABS;
#endif
@@ -627,6 +641,8 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
#ifdef TERMIOS
if (_term->Ottyb.c_oflag & OFLAGS_TABS)
tab = back_tab = NULL;
+#elif defined(EXP_WIN32_DRIVER)
+ /* noop */
#else
if (_term->Ottyb.sg_flags & XTABS)
tab = back_tab = NULL;
@@ -764,10 +780,10 @@ drv_initpair(TERMINAL_CONTROL_BLOCK * TCB, int pair, int f, int b)
tp[b].red, tp[b].green, tp[b].blue));
NCURSES_PUTP2("initialize_pair",
- TPARM_7(initialize_pair,
- pair,
- tp[f].red, tp[f].green, tp[f].blue,
- tp[b].red, tp[b].green, tp[b].blue));
+ TIPARM_7(initialize_pair,
+ pair,
+ tp[f].red, tp[f].green, tp[f].blue,
+ tp[b].red, tp[b].green, tp[b].blue));
}
}
@@ -800,7 +816,7 @@ drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
AssertTCB();
if (initialize_color != NULL) {
NCURSES_PUTP2("initialize_color",
- TPARM_4(initialize_color, color, r, g, b));
+ TIPARM_4(initialize_color, color, r, g, b));
}
}
@@ -826,7 +842,7 @@ drv_do_color(TERMINAL_CONTROL_BLOCK * TCB,
if (set_color_pair) {
TPUTS_TRACE("set_color_pair");
NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
- TPARM_1(set_color_pair, pair), 1, outc);
+ TIPARM_1(set_color_pair, pair), 1, outc);
return;
} else if (sp != 0) {
_nc_pair_content(SP_PARM, pair, &fg, &bg);
@@ -933,11 +949,18 @@ drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB,
} else
#endif
{
+#ifdef EXP_WIN32_DRIVER
+ rc = _nc_console_testmouse(sp,
+ _nc_console_handle(sp->_ifd),
+ delay
+ EVENTLIST_2nd(evl));
+#else
rc = TCBOf(sp)->drv->td_twait(TCBOf(sp),
TWAIT_MASK,
delay,
(int *) 0
EVENTLIST_2nd(evl));
+#endif
#if USE_SYSMOUSE
if ((sp->_mouse_type == M_SYSMOUSE)
&& (sp->_sysmouse_head < sp->_sysmouse_tail)
@@ -1235,16 +1258,25 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
AssertTCB();
SetSP();
-
+#ifdef EXP_WIN32_DRIVER
+ return _nc_console_twait(sp,
+ _nc_console_handle(sp->_ifd),
+ mode,
+ milliseconds,
+ timeleft EVENTLIST_2nd(evl));
+#else
return _nc_timed_wait(sp, mode, milliseconds, timeleft EVENTLIST_2nd(evl));
+#endif
}
static int
drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
{
SCREEN *sp;
- unsigned char c2 = 0;
int n;
+#ifndef EXP_WIN32_DRIVER
+ unsigned char c2 = 0;
+#endif
AssertTCB();
assert(buf);
@@ -1254,11 +1286,19 @@ drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
if ((pthread_self) && (pthread_kill) && (pthread_equal))
_nc_globals.read_thread = pthread_self();
# endif
+#ifdef EXP_WIN32_DRIVER
+ n = _nc_console_read(sp,
+ _nc_console_handle(sp->_ifd),
+ buf);
+#else
n = (int) read(sp->_ifd, &c2, (size_t) 1);
+#endif
#if USE_PTHREADS_EINTR
_nc_globals.read_thread = 0;
#endif
+#ifndef EXP_WIN32_DRIVER
*buf = (int) c2;
+#endif
return n;
}
@@ -1275,6 +1315,8 @@ drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
request = remaining;
}
}
+#elif defined(EXP_WIN32_DRIVER)
+ Sleep((DWORD) ms);
#else
_nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0));
#endif
@@ -1452,3 +1494,66 @@ NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_TINFO_DRIVER = {
drv_kyExist, /* kyExist */
drv_cursorSet /* cursorSet */
};
+
+#ifdef EXP_WIN32_DRIVER
+/*
+ * The terminfo driver is mandatory and must always be present.
+ * So this is the natural place for the driver initialisation
+ * logic.
+ */
+
+typedef struct DriverEntry {
+ const char *name;
+ TERM_DRIVER *driver;
+} DRIVER_ENTRY;
+
+static DRIVER_ENTRY DriverTable[] =
+{
+#ifdef _NC_WINDOWS
+ {"win32console", &_nc_WIN_DRIVER},
+#endif
+ {"tinfo", &_nc_TINFO_DRIVER} /* must be last */
+};
+
+NCURSES_EXPORT(int)
+_nc_get_driver(TERMINAL_CONTROL_BLOCK * TCB, const char *name, int *errret)
+{
+ int code = ERR;
+ size_t i;
+ TERM_DRIVER *res = (TERM_DRIVER *) 0;
+ TERM_DRIVER *use = 0;
+
+ T((T_CALLED("_nc_get_driver(%p, %s, %p)"),
+ (void *) TCB, NonNull(name), (void *) errret));
+
+ assert(TCB != 0);
+
+ for (i = 0; i < SIZEOF(DriverTable); i++) {
+ res = DriverTable[i].driver;
+#ifdef _NC_WINDOWS
+ if ((i + 1) == SIZEOF(DriverTable)) {
+ /* For Windows >= 10.0.17763 Windows Console interface implements
+ virtual Terminal functionality.
+ If on Windows td_CanHandle returned FALSE although the terminal
+ name is empty, we default to ms-terminal as tinfo TERM type.
+ */
+ if (name == 0 || *name == 0 || (strcmp(name, "unknown") == 0)) {
+ name = MS_TERMINAL;
+ T(("Set TERM=%s", name));
+ }
+ }
+#endif
+ if (strcmp(DriverTable[i].name, res->td_name(TCB)) == 0) {
+ if (res->td_CanHandle(TCB, name, errret)) {
+ use = res;
+ break;
+ }
+ }
+ }
+ if (use != 0) {
+ TCB->drv = use;
+ code = OK;
+ }
+ returnCode(code);
+}
+#endif /* EXP_WIN32_DRIVER */
diff --git a/ncurses/tinfo/trim_sgr0.c b/ncurses/tinfo/trim_sgr0.c
index 4d10529c029f..30c8f75c1e8a 100644
--- a/ncurses/tinfo/trim_sgr0.c
+++ b/ncurses/tinfo/trim_sgr0.c
@@ -37,7 +37,7 @@
#include <tic.h>
-MODULE_ID("$Id: trim_sgr0.c,v 1.18 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: trim_sgr0.c,v 1.20 2020/05/27 23:54:31 tom Exp $")
#undef CUR
#define CUR tp->
@@ -52,7 +52,7 @@ set_attribute_9(TERMTYPE2 *tp, int flag)
const char *value;
char *result;
- value = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag);
+ value = TIPARM_9(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag);
if (PRESENT(value))
result = strdup(value);
else
diff --git a/ncurses/tinfo/write_entry.c b/ncurses/tinfo/write_entry.c
index 138517651e12..5bb7aee7f360 100644
--- a/ncurses/tinfo/write_entry.c
+++ b/ncurses/tinfo/write_entry.c
@@ -51,7 +51,7 @@
#define TRACE_NUM(n) /* nothing */
#endif
-MODULE_ID("$Id: write_entry.c,v 1.115 2020/02/02 23:34:34 tom Exp $")
+MODULE_ID("$Id: write_entry.c,v 1.116 2020/08/29 16:22:03 juergen Exp $")
static int total_written;
static int total_parts;
@@ -192,7 +192,7 @@ make_db_root(const char *path)
if ((rc = stat(path, &statbuf)) < 0) {
rc = mkdir(path
-#if !defined(_WIN32)
+#ifndef _NC_WINDOWS
,0777
#endif
);