libncurses: Import https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.5.tar.gz changes

Change-Id: I3433d30ca01359fd2e3623ede96b531f0b39cbfa
Signed-off-by: micky387 <mickaelsaibi@free.fr>
diff --git a/ncurses/tinfo/tinfo_driver.c b/ncurses/tinfo/tinfo_driver.c
index c6a1c22..fd993b8 100644
--- a/ncurses/tinfo/tinfo_driver.c
+++ b/ncurses/tinfo/tinfo_driver.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2008-2014,2015 Free Software Foundation, Inc.              *
+ * Copyright 2018-2022,2023 Thomas E. Dickey                                *
+ * Copyright 2008-2016,2017 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            *
@@ -28,12 +29,13 @@
 
 /****************************************************************************
  *  Author: Juergen Pfeifer                                                 *
- *                                                                          *
+ *     and: Thomas E. Dickey                                                *
  ****************************************************************************/
 
 #include <curses.priv.h>
-#define CUR ((TERMINAL*)TCB)->type.
+#define CUR TerminalType((TERMINAL*)TCB).
 #include <tic.h>
+#include <termcap.h>		/* ospeed */
 
 #if HAVE_NANOSLEEP
 #include <time.h>
@@ -50,7 +52,7 @@
 # endif
 #endif
 
-MODULE_ID("$Id: tinfo_driver.c,v 1.40 2015/06/27 01:20:41 tom Exp $")
+MODULE_ID("$Id: tinfo_driver.c,v 1.74 2023/09/16 10:44:33 tom Exp $")
 
 /*
  * SCO defines TIOCGSIZE and the corresponding struct.  Other systems (SunOS,
@@ -113,9 +115,43 @@
     return "tinfo";
 }
 
+static void
+get_baudrate(TERMINAL *termp)
+{
+    int my_ospeed;
+    int result;
+    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
+    }
+#ifdef USE_OLD_TTY
+    result = (int) cfgetospeed(&(termp->Nttyb));
+    my_ospeed = (NCURSES_OSPEED) _nc_ospeed(result);
+#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
+    result = _nc_baudrate(my_ospeed);
+#endif
+    termp->_baudrate = result;
+    ospeed = (NCURSES_OSPEED) my_ospeed;
+}
+
 #undef SETUP_FAIL
 #define SETUP_FAIL FALSE
 
+#define NO_COPY {}
+
 static bool
 drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret)
 {
@@ -125,7 +161,7 @@
     SCREEN *sp;
 
     START_TRACE();
-    T((T_CALLED("tinfo::drv_CanHandle(%p)"), TCB));
+    T((T_CALLED("tinfo::drv_CanHandle(%p)"), (void *) TCB));
 
     assert(TCB != 0 && tname != 0);
     termp = (TERMINAL *) TCB;
@@ -133,17 +169,20 @@
     TCB->magic = TCBMAGIC;
 
 #if (NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP)
-    status = _nc_setup_tinfo(tname, &termp->type);
+    status = _nc_setup_tinfo(tname, &TerminalType(termp));
+    T(("_nc_setup_tinfo returns %d", status));
 #else
+    T(("no database available"));
     status = TGETENT_NO;
 #endif
 
     /* try fallback list if entry on disk */
     if (status != TGETENT_YES) {
-	const TERMTYPE *fallback = _nc_fallback(tname);
+	const TERMTYPE2 *fallback = _nc_fallback2(tname);
 
 	if (fallback) {
-	    termp->type = *fallback;
+	    T(("found fallback entry"));
+	    TerminalType(termp) = *fallback;
 	    status = TGETENT_YES;
 	}
     }
@@ -153,17 +192,40 @@
 	if (status == TGETENT_ERR) {
 	    ret_error0(status, "terminals database is inaccessible\n");
 	} else if (status == TGETENT_NO) {
-	    ret_error1(status, "unknown terminal type.\n", tname);
+	    ret_error1(status, "unknown terminal type.\n",
+		       tname, NO_COPY);
+	} else {
+	    ret_error0(status, "unexpected return-code\n");
 	}
     }
     result = TRUE;
+#if NCURSES_EXT_NUMBERS
+    _nc_export_termtype2(&termp->type, &TerminalType(termp));
+#endif
 #if !USE_REENTRANT
-    strncpy(ttytype, termp->type.term_names, (size_t) NAMESIZE - 1);
-    ttytype[NAMESIZE - 1] = '\0';
+    save_ttytype(termp);
 #endif
 
-    if (command_character)
-	_nc_tinfo_cmdch(termp, *command_character);
+    if (VALID_STRING(command_character))
+	_nc_tinfo_cmdch(termp, UChar(*command_character));
+
+    /*
+     * If an application calls setupterm() rather than initscr() or
+     * newterm(), we will not have the def_prog_mode() call in
+     * _nc_setupscreen().  Do it now anyway, so we can initialize the
+     * baudrate.
+     */
+    if (sp == 0 && NC_ISATTY(termp->Filedes)) {
+	get_baudrate(termp);
+    }
+#if NCURSES_EXT_NUMBERS
+#define cleanup_termtype() \
+    _nc_free_termtype2(&TerminalType(termp)); \
+    _nc_free_termtype(&termp->type)
+#else
+#define cleanup_termtype() \
+    _nc_free_termtype2(&TerminalType(termp))
+#endif
 
     if (generic_type) {
 	/*
@@ -173,13 +235,19 @@
 	if ((VALID_STRING(cursor_address)
 	     || (VALID_STRING(cursor_down) && VALID_STRING(cursor_home)))
 	    && VALID_STRING(clear_screen)) {
-	    ret_error1(TGETENT_YES, "terminal is not really generic.\n", tname);
+	    cleanup_termtype();
+	    ret_error1(TGETENT_YES, "terminal is not really generic.\n",
+		       tname, NO_COPY);
 	} else {
-	    ret_error1(TGETENT_NO, "I need something more specific.\n", tname);
+	    cleanup_termtype();
+	    ret_error1(TGETENT_NO, "I need something more specific.\n",
+		       tname, NO_COPY);
 	}
     }
     if (hard_copy) {
-	ret_error1(TGETENT_YES, "I can't handle hardcopy terminals.\n", tname);
+	cleanup_termtype();
+	ret_error1(TGETENT_YES, "I can't handle hardcopy terminals.\n",
+		   tname, NO_COPY);
     }
 
     returnBool(result);
@@ -261,8 +329,8 @@
 	sp->_has_sgr_39_49 = (NCURSES_SP_NAME(tigetflag) (NCURSES_SP_ARGx
 							  "AX")
 			      == TRUE);
-	sp->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : (fg & C_MASK);
-	sp->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : (bg & C_MASK);
+	sp->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : fg;
+	sp->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : bg;
 	if (sp->_color_pairs != 0) {
 	    bool save = sp->_default_color;
 	    sp->_default_color = TRUE;
@@ -293,23 +361,23 @@
 	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);
 	}
     }
 }
@@ -358,18 +426,25 @@
 
     if (sp) {
 	useEnv = sp->_use_env;
-	useTioctl = sp->_use_tioctl;
+	useTioctl = sp->use_tioctl;
     } else {
 	useEnv = _nc_prescreen.use_env;
 	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;
 
@@ -539,6 +614,8 @@
 	    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
@@ -564,6 +641,8 @@
 #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;
@@ -701,10 +780,10 @@
 	    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));
     }
 }
 
@@ -737,7 +816,7 @@
     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));
     }
 }
 
@@ -749,9 +828,9 @@
 	     NCURSES_SP_OUTC outc)
 {
     SCREEN *sp = TCB->csp;
-    NCURSES_COLOR_T fg = COLOR_DEFAULT;
-    NCURSES_COLOR_T bg = COLOR_DEFAULT;
-    NCURSES_COLOR_T old_fg, old_bg;
+    int fg = COLOR_DEFAULT;
+    int bg = COLOR_DEFAULT;
+    int old_fg, old_bg;
 
     AssertTCB();
     if (sp == 0)
@@ -763,22 +842,16 @@
 	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) {
-	    NCURSES_SP_NAME(pair_content) (NCURSES_SP_ARGx
-					   (short) pair,
-					   &fg,
-					   &bg);
+	    _nc_pair_content(SP_PARM, pair, &fg, &bg);
 	}
     }
 
     if (old_pair >= 0
 	&& sp != 0
-	&& NCURSES_SP_NAME(pair_content) (NCURSES_SP_ARGx
-					  (short) old_pair,
-					  &old_fg,
-					  &old_bg) !=ERR) {
+	&& _nc_pair_content(SP_PARM, old_pair, &old_fg, &old_bg) != ERR) {
 	if ((isDefaultColor(fg) && !isDefaultColor(old_fg))
 	    || (isDefaultColor(bg) && !isDefaultColor(old_bg))) {
 #if NCURSES_EXT_FUNCS
@@ -807,13 +880,13 @@
 
 #if NCURSES_EXT_FUNCS
     if (isDefaultColor(fg))
-	fg = (NCURSES_COLOR_T) default_fg(sp);
+	fg = default_fg(sp);
     if (isDefaultColor(bg))
-	bg = (NCURSES_COLOR_T) default_bg(sp);
+	bg = default_bg(sp);
 #endif
 
     if (reverse) {
-	NCURSES_COLOR_T xx = fg;
+	int xx = fg;
 	fg = bg;
 	bg = xx;
     }
@@ -849,12 +922,9 @@
 
     /* we know how to recognize mouse events under "xterm" */
     if (sp != 0) {
-	if (key_mouse != 0) {
-	    if (!strcmp(key_mouse, xterm_kmous)
-		|| strstr(TerminalOf(sp)->type.term_names, "xterm") != 0) {
-		init_xterm_mouse(sp);
-	    }
-	} else if (strstr(TerminalOf(sp)->type.term_names, "xterm") != 0) {
+	if (NonEmpty(key_mouse)) {
+	    init_xterm_mouse(sp);
+	} else if (strstr(SP_TERMTYPE term_names, "xterm") != 0) {
 	    if (_nc_add_to_try(&(sp->_keytry), xterm_kmous, KEY_MOUSE) == OK)
 		init_xterm_mouse(sp);
 	}
@@ -879,11 +949,18 @@
     } 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)
@@ -979,12 +1056,18 @@
 {
     AssertTCB();
 
-    clear_screen = 0;
-    cursor_down = parm_down_cursor = 0;
-    cursor_address = 0;
-    cursor_up = parm_up_cursor = 0;
-    row_address = 0;
-    cursor_home = carriage_return;
+    /* *INDENT-EQLS* */
+    clear_screen     = ABSENT_STRING;
+    cursor_address   = ABSENT_STRING;
+    cursor_down      = ABSENT_STRING;
+    cursor_up        = ABSENT_STRING;
+    parm_down_cursor = ABSENT_STRING;
+    parm_up_cursor   = ABSENT_STRING;
+    row_address      = ABSENT_STRING;
+    cursor_home      = carriage_return;
+
+    if (back_color_erase)
+	clr_eos = ABSENT_STRING;
 }
 
 static void
@@ -1031,8 +1114,13 @@
 	while (i + 1 < length) {
 	    if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) {
 		real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET;
-		if (sp != 0)
+		T(("#%d real_map[%s] = %s",
+		   (int) i,
+		   _tracechar(UChar(acs_chars[i])),
+		   _tracechtype(real_map[UChar(acs_chars[i])])));
+		if (sp != 0) {
 		    sp->_screen_acs_map[UChar(acs_chars[i])] = TRUE;
+		}
 	    }
 	    i += 2;
 	}
@@ -1062,7 +1150,6 @@
 		   ? "DIFF"
 		   : "SAME"),
 		_nc_visbuf(show));
-
 	_nc_unlock_global(tracef);
     }
 #endif /* TRACE */
@@ -1171,30 +1258,42 @@
 
     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);
     SetSP();
 
-# if USE_PTHREADS_EINTR
-    if ((pthread_self) && (pthread_kill) && (pthread_equal))
-	_nc_globals.read_thread = pthread_self();
-# endif
+    _nc_set_read_thread(TRUE);
+#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);
-#if USE_PTHREADS_EINTR
-    _nc_globals.read_thread = 0;
 #endif
+    _nc_set_read_thread(FALSE);
+#ifndef EXP_WIN32_DRIVER
     *buf = (int) c2;
+#endif
     return n;
 }
 
@@ -1211,6 +1310,8 @@
 	    request = remaining;
 	}
     }
+#elif defined(EXP_WIN32_DRIVER)
+    Sleep((DWORD) ms);
 #else
     _nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0));
 #endif
@@ -1279,23 +1380,29 @@
 	unsigned ch = (unsigned) c;
 	if (flag) {
 	    while ((s = _nc_expand_try(sp->_key_ok,
-				       ch, &count, (size_t) 0)) != 0
-		   && _nc_remove_key(&(sp->_key_ok), ch)) {
-		code = _nc_add_to_try(&(sp->_keytry), s, ch);
-		free(s);
-		count = 0;
-		if (code != OK)
-		    break;
+				       ch, &count, (size_t) 0)) != 0) {
+		if (_nc_remove_key(&(sp->_key_ok), ch)) {
+		    code = _nc_add_to_try(&(sp->_keytry), s, ch);
+		    free(s);
+		    count = 0;
+		    if (code != OK)
+			break;
+		} else {
+		    free(s);
+		}
 	    }
 	} else {
 	    while ((s = _nc_expand_try(sp->_keytry,
-				       ch, &count, (size_t) 0)) != 0
-		   && _nc_remove_key(&(sp->_keytry), ch)) {
-		code = _nc_add_to_try(&(sp->_key_ok), s, ch);
-		free(s);
-		count = 0;
-		if (code != OK)
-		    break;
+				       ch, &count, (size_t) 0)) != 0) {
+		if (_nc_remove_key(&(sp->_keytry), ch)) {
+		    code = _nc_add_to_try(&(sp->_key_ok), s, ch);
+		    free(s);
+		    count = 0;
+		    if (code != OK)
+			break;
+		} else {
+		    free(s);
+		}
 	    }
 	}
     }
@@ -1382,3 +1489,66 @@
 	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 */