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/base/lib_screen.c b/ncurses/base/lib_screen.c
index a03ceec..e2647b5 100644
--- a/ncurses/base/lib_screen.c
+++ b/ncurses/base/lib_screen.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2011,2015 Free Software Foundation, Inc.              *
+ * Copyright 2019-2021,2023 Thomas E. Dickey                                *
+ * Copyright 1998-2017,2018 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            *
@@ -41,7 +42,7 @@
 #define CUR SP_TERMTYPE
 #endif
 
-MODULE_ID("$Id: lib_screen.c,v 1.77 2015/07/04 22:54:14 tom Exp $")
+MODULE_ID("$Id: lib_screen.c,v 1.105 2023/04/28 20:58:54 tom Exp $")
 
 #define MAX_SIZE 0x3fff		/* 16k is big enough for a window or pad */
 
@@ -51,13 +52,22 @@
 #define L_CURL '{'
 #define R_CURL '}'
 
+#if USE_STRING_HACKS && HAVE_SNPRINTF
+#define ARG_SLIMIT(name) size_t name,
+#else
+#define ARG_SLIMIT(name)	/* nothing */
+#endif
+
+#define CUR_SLIMIT _nc_SLIMIT(limit - (size_t) (target - base))
+#define TOP_SLIMIT _nc_SLIMIT(sizeof(buffer))
+
 /*
- * Use 0x8888 as the magic number for new-format files, since it cannot be
+ * Use 0x888888 as the magic number for new-format files, since it cannot be
  * mistaken for the _cury/_curx pair of 16-bit numbers which start the old
  * format.  It happens to be unused in the file 5.22 database (2015/03/07).
  */
 static const char my_magic[] =
-{'\210', '\210', '\210', '\210'};
+{'\210', '\210', '\210', '\210', 0};
 
 #if NCURSES_EXT_PUTWIN
 typedef enum {
@@ -80,7 +90,6 @@
 typedef struct {
     const char name[17];
     PARAM_TYPE type;
-    size_t size;
     size_t offset;
 } SCR_PARAMS;
 
@@ -110,8 +119,7 @@
 };
 #undef DATA
 
-#define sizeof2(type,name) sizeof(((type *)0)->name)
-#define DATA(name, type) { { #name }, type, sizeof2(WINDOW, name), offsetof(WINDOW, name) }
+#define DATA(name, type) { { #name }, type, offsetof(WINDOW, name) }
 
 static const SCR_PARAMS scr_params[] =
 {
@@ -161,12 +169,12 @@
 read_txt(FILE *fp)
 {
     size_t limit = 1024;
-    size_t used = 0;
     char *result = malloc(limit);
     char *buffer;
 
     if (result != 0) {
 	int ch = 0;
+	size_t used = 0;
 
 	clearerr(fp);
 	result[used] = '\0';
@@ -190,7 +198,7 @@
 
 	if (ch == '\n') {
 	    result[--used] = '\0';
-	    T(("READ:%s", result));
+	    TR(TRACE_IEVENT, ("READ:%s", result));
 	} else if (used == 0) {
 	    free(result);
 	    result = 0;
@@ -204,7 +212,7 @@
 {
     bool found = FALSE;
 
-    T(("decode_attr   '%s'", source));
+    TR(TRACE_IEVENT, ("decode_attr   '%s'", source));
 
     while (*source) {
 	if (source[0] == MARKER && source[1] == L_CURL) {
@@ -262,7 +270,7 @@
     int base = 16;
     const char digits[] = "0123456789abcdef";
 
-    T(("decode_char   '%s'", source));
+    TR(TRACE_IEVENT, ("decode_char   '%s'", source));
     *target = ' ';
     switch (*source) {
     case MARKER:
@@ -319,7 +327,7 @@
     int color = PAIR_NUMBER((int) attr);
     int value;
 
-    T(("decode_chtype '%s'", source));
+    TR(TRACE_IEVENT, ("decode_chtype '%s'", source));
     source = decode_attr(source, &attr, &color);
     source = decode_char(source, &value);
     *target = (ChCharOf(value) | attr | (chtype) COLOR_PAIR(color));
@@ -337,7 +345,7 @@
     int append = 0;
     int value = 0;
 
-    T(("decode_cchar  '%s'", source));
+    TR(TRACE_IEVENT, ("decode_cchar  '%s'", source));
     *target = blank;
 #if NCURSES_EXT_COLORS
     color = fillin->ext_color;
@@ -356,7 +364,7 @@
 	    chars[append] = (wchar_t) value;
 	}
     }
-    setcchar(target, chars, attr, (short) color, NULL);
+    setcchar(target, chars, attr, (short) color, &color);
     return source;
 }
 #endif
@@ -365,9 +373,6 @@
 read_win(WINDOW *win, FILE *fp)
 {
     int code = ERR;
-    char *txt;
-    char *name;
-    char *value;
     size_t n;
     int color;
 #if NCURSES_WIDECHAR
@@ -377,7 +382,10 @@
 
     memset(win, 0, sizeof(WINDOW));
     for (;;) {
-	txt = read_txt(fp);
+	char *name;
+	char *value;
+	char *txt = read_txt(fp);
+
 	if (txt == 0)
 	    break;
 	if (!strcmp(txt, "rows:")) {
@@ -431,14 +439,17 @@
 }
 
 static int
-read_row(char *source, NCURSES_CH_T * prior, NCURSES_CH_T * target, int length)
+read_row(char *source, NCURSES_CH_T *prior, NCURSES_CH_T *target, int length)
 {
     while (*source != '\0' && length > 0) {
 #if NCURSES_WIDECHAR
-	int n, len;
+	int len;
+
 	source = decode_cchar(source, prior, target);
-	len = wcwidth(target->chars[0]);
+	len = _nc_wacs_width(target->chars[0]);
 	if (len > 1) {
+	    int n;
+
 	    SetWidecExt(CHDEREF(target), 0);
 	    for (n = 1; n < len; ++n) {
 		target[n] = target[0];
@@ -490,7 +501,6 @@
 NCURSES_SP_NAME(getwin) (NCURSES_SP_DCLx FILE *filep)
 {
     WINDOW tmp, *nwin;
-    int n;
     bool old_format = FALSE;
 
     T((T_CALLED("getwin(%p)"), (void *) filep));
@@ -503,13 +513,13 @@
      * Read the first 4 bytes to determine first if this is an old-format
      * screen-dump, or new-format.
      */
-    if (read_block(&tmp, 4, filep) < 0) {
+    if (read_block(&tmp, (size_t) 4, filep) < 0) {
 	returnWin(0);
     }
     /*
      * If this is a new-format file, and we do not support it, give up.
      */
-    if (!memcmp(&tmp, my_magic, 4)) {
+    if (!memcmp(&tmp, my_magic, (size_t) 4)) {
 #if NCURSES_EXT_PUTWIN
 	if (read_win(&tmp, filep) < 0)
 #endif
@@ -530,7 +540,7 @@
 	returnWin(0);
     }
 
-    if (tmp._flags & _ISPAD) {
+    if (IS_PAD(&tmp)) {
 	nwin = NCURSES_SP_NAME(newpad) (NCURSES_SP_ARGx
 					tmp._maxy + 1,
 					tmp._maxx + 1);
@@ -546,6 +556,7 @@
      * made sense is probably gone.
      */
     if (nwin != 0) {
+	int n;
 	size_t linesize = sizeof(NCURSES_CH_T) * (size_t) (tmp._maxx + 1);
 
 	nwin->_curx = tmp._curx;
@@ -574,7 +585,7 @@
 	nwin->_regtop = tmp._regtop;
 	nwin->_regbottom = tmp._regbottom;
 
-	if (tmp._flags & _ISPAD)
+	if (IS_PAD(&tmp))
 	    nwin->_pad = tmp._pad;
 
 	if (old_format) {
@@ -588,7 +599,7 @@
 	}
 #if NCURSES_EXT_PUTWIN
 	else {
-	    char *txt;
+	    char *txt = 0;
 	    bool success = TRUE;
 	    NCURSES_CH_T prior = blank;
 
@@ -641,13 +652,20 @@
 
 #if NCURSES_EXT_PUTWIN
 static void
-encode_attr(char *target, attr_t source, attr_t prior)
+encode_attr(char *target, ARG_SLIMIT(limit)
+	    attr_t source,
+	    attr_t prior,
+	    int source_color,
+	    int prior_color)
 {
+#if USE_STRING_HACKS && HAVE_SNPRINTF
+    char *base = target;
+#endif
     source &= ~A_CHARTEXT;
     prior &= ~A_CHARTEXT;
 
     *target = '\0';
-    if (source != prior) {
+    if ((source != prior) || (source_color != prior_color)) {
 	size_t n;
 	bool first = TRUE;
 
@@ -663,14 +681,14 @@
 		} else {
 		    *target++ = '|';
 		}
-		strcpy(target, scr_attrs[n].name);
+		_nc_STRCPY(target, scr_attrs[n].name, limit);
 		target += strlen(target);
 	    }
 	}
-	if ((source & A_COLOR) != (prior & A_COLOR)) {
+	if (source_color != prior_color) {
 	    if (!first)
 		*target++ = '|';
-	    sprintf(target, "C%d", PAIR_NUMBER((int) source));
+	    _nc_SPRINTF(target, CUR_SLIMIT "C%d", source_color);
 	    target += strlen(target);
 	}
 
@@ -680,19 +698,29 @@
 }
 
 static void
-encode_cell(char *target, CARG_CH_T source, CARG_CH_T previous)
+encode_cell(char *target, ARG_SLIMIT(limit) CARG_CH_T source, CARG_CH_T previous)
 {
+#if USE_STRING_HACKS && HAVE_SNPRINTF
+    char *base = target;
+#endif
 #if NCURSES_WIDECHAR
     size_t n;
+    int source_pair = GetPair(*source);
+    int previous_pair = GetPair(*previous);
 
     *target = '\0';
-    if (previous->attr != source->attr) {
-	encode_attr(target, source->attr, previous->attr);
+    if ((previous->attr != source->attr) || (previous_pair != source_pair)) {
+	encode_attr(target, CUR_SLIMIT
+		    source->attr,
+		    previous->attr,
+		    source_pair,
+		    previous_pair);
     }
     target += strlen(target);
 #if NCURSES_EXT_COLORS
     if (previous->ext_color != source->ext_color) {
-	sprintf(target, "%c%cC%d%c", MARKER, L_CURL, source->ext_color, R_CURL);
+	_nc_SPRINTF(target, CUR_SLIMIT
+		    "%c%cC%d%c", MARKER, L_CURL, source->ext_color, R_CURL);
     }
 #endif
     for (n = 0; n < SIZEOF(source->chars); ++n) {
@@ -705,22 +733,23 @@
 	}
 	*target++ = MARKER;
 	if (uch > 0xffff) {
-	    sprintf(target, "U%08x", uch);
+	    _nc_SPRINTF(target, CUR_SLIMIT "U%08x", uch);
 	} else if (uch > 0xff) {
-	    sprintf(target, "u%04x", uch);
+	    _nc_SPRINTF(target, CUR_SLIMIT "u%04x", uch);
 	} else if (uch < 32 || uch >= 127) {
-	    sprintf(target, "%03o", uch & 0xff);
+	    _nc_SPRINTF(target, CUR_SLIMIT "%03o", uch & 0xff);
 	} else {
 	    switch (uch) {
 	    case ' ':
-		strcpy(target, "s");
+		_nc_STRCPY(target, "s", limit);
 		break;
 	    case MARKER:
 		*target++ = MARKER;
 		*target = '\0';
 		break;
 	    default:
-		sprintf(--target, "%c", uch);
+		--target;
+		_nc_SPRINTF(target, CUR_SLIMIT "%c", uch);
 		break;
 	    }
 	}
@@ -731,27 +760,31 @@
 
     *target = '\0';
     if (AttrOfD(previous) != AttrOfD(source)) {
-	encode_attr(target, AttrOfD(source), AttrOfD(previous));
+	encode_attr(target, CUR_SLIMIT
+		    AttrOfD(source),
+		    AttrOfD(previous),
+		    GetPair(source),
+		    GetPair(previous));
     }
     target += strlen(target);
     *target++ = MARKER;
     if (ch < 32 || ch >= 127) {
-	sprintf(target, "%03o", UChar(ch));
+	_nc_SPRINTF(target, CUR_SLIMIT "%03o", UChar(ch));
     } else {
 	switch (ch) {
 	case ' ':
-	    strcpy(target, "s");
+	    _nc_STRCPY(target, "s", limit);
 	    break;
 	case MARKER:
 	    *target++ = MARKER;
 	    *target = '\0';
 	    break;
 	default:
-	    sprintf(--target, "%c", UChar(ch));
+	    --target;
+	    _nc_SPRINTF(target, CUR_SLIMIT "%c", UChar(ch));
 	    break;
 	}
     }
-    target += strlen(target);
 #endif
 }
 #endif
@@ -760,7 +793,6 @@
 putwin(WINDOW *win, FILE *filep)
 {
     int code = ERR;
-    int y;
 
     T((T_CALLED("putwin(%p,%p)"), (void *) win, (void *) filep));
 
@@ -769,6 +801,7 @@
 	const char *version = curses_version();
 	char buffer[1024];
 	NCURSES_CH_T last_cell;
+	int y;
 
 	memset(&last_cell, 0, sizeof(last_cell));
 
@@ -786,43 +819,58 @@
 	    const char *name = scr_params[y].name;
 	    const char *data = (char *) win + scr_params[y].offset;
 	    const void *dp = (const void *) data;
+	    attr_t attr;
 
 	    *buffer = '\0';
-	    if (!strncmp(name, "_pad.", 5) && !(win->_flags & _ISPAD)) {
+	    if (!strncmp(name, "_pad.", (size_t) 5) && !IS_PAD(win)) {
 		continue;
 	    }
 	    switch (scr_params[y].type) {
 	    case pATTR:
-		encode_attr(buffer, (*(const attr_t *) dp) & ~A_CHARTEXT, A_NORMAL);
+		attr = (*(const attr_t *) dp) & ~A_CHARTEXT;
+		encode_attr(buffer, TOP_SLIMIT
+			    (*(const attr_t *) dp) & ~A_CHARTEXT,
+			    A_NORMAL,
+			    COLOR_PAIR((int) attr),
+			    0);
 		break;
 	    case pBOOL:
 		if (!(*(const bool *) data)) {
 		    continue;
 		}
-		strcpy(buffer, name);
+		_nc_STRCPY(buffer, name, sizeof(buffer));
 		name = "flag";
 		break;
 	    case pCHAR:
-		encode_attr(buffer, *(const attr_t *) dp, A_NORMAL);
+		attr = (*(const attr_t *) dp);
+		encode_attr(buffer, TOP_SLIMIT
+			    * (const attr_t *) dp,
+			    A_NORMAL,
+			    COLOR_PAIR((int) attr),
+			    0);
 		break;
 	    case pINT:
 		if (!(*(const int *) dp))
 		    continue;
-		sprintf(buffer, "%d", *(const int *) dp);
+		_nc_SPRINTF(buffer, TOP_SLIMIT
+			    "%d", *(const int *) dp);
 		break;
 	    case pSHORT:
 		if (!(*(const short *) dp))
 		    continue;
-		sprintf(buffer, "%d", *(const short *) dp);
+		_nc_SPRINTF(buffer, TOP_SLIMIT
+			    "%d", *(const short *) dp);
 		break;
 	    case pSIZE:
 		if (!(*(const NCURSES_SIZE_T *) dp))
 		    continue;
-		sprintf(buffer, "%d", *(const NCURSES_SIZE_T *) dp);
+		_nc_SPRINTF(buffer, TOP_SLIMIT
+			    "%d", *(const NCURSES_SIZE_T *) dp);
 		break;
 #if NCURSES_WIDECHAR
 	    case pCCHAR:
-		encode_cell(buffer, (CARG_CH_T) dp, CHREF(last_cell));
+		encode_cell(buffer, TOP_SLIMIT
+			    (CARG_CH_T) dp, CHREF(last_cell));
 		break;
 #endif
 	    }
@@ -845,20 +893,21 @@
 		returnCode(code);
 	    for (x = 0; x <= win->_maxx; x++) {
 #if NCURSES_WIDECHAR
-		int len = wcwidth(data[x].chars[0]);
-		encode_cell(buffer, CHREF(data[x]), CHREF(last_cell));
+		int len = _nc_wacs_width(data[x].chars[0]);
+		encode_cell(buffer, TOP_SLIMIT CHREF(data[x]), CHREF(last_cell));
 		last_cell = data[x];
 		PUTS(buffer);
 		if (len > 1)
 		    x += (len - 1);
 #else
-		encode_cell(buffer, CHREF(data[x]), CHREF(last_cell));
+		encode_cell(buffer, TOP_SLIMIT CHREF(data[x]), CHREF(last_cell));
 		last_cell = data[x];
 		PUTS(buffer);
 #endif
 	    }
 	    PUTS("\n");
 	}
+	code = OK;
     }
 #else
     /*
@@ -869,6 +918,7 @@
      */
     if (win != 0) {
 	size_t len = (size_t) (win->_maxx + 1);
+	int y;
 
 	clearerr(filep);
 	if (fwrite(win, sizeof(WINDOW), (size_t) 1, filep) != 1
@@ -888,6 +938,31 @@
     returnCode(code);
 }
 
+/*
+ * Replace a window covering the whole screen, i.e., newscr or curscr.
+ */
+static WINDOW *
+replace_window(WINDOW *target, FILE *source)
+{
+    WINDOW *result = getwin(source);
+#if NCURSES_EXT_FUNCS
+    if (result != NULL) {
+	if (getmaxx(result) != getmaxx(target)
+	    || getmaxy(result) != getmaxy(target)) {
+	    int code = wresize(result,
+			       1 + getmaxy(target),
+			       1 + getmaxx(target));
+	    if (code != OK) {
+		delwin(result);
+		result = NULL;
+	    }
+	}
+    }
+#endif
+    delwin(target);
+    return result;
+}
+
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(scr_restore) (NCURSES_SP_DCLx const char *file)
 {
@@ -897,9 +972,8 @@
     T((T_CALLED("scr_restore(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file)));
 
     if (_nc_access(file, R_OK) >= 0
-	&& (fp = fopen(file, "rb")) != 0) {
-	delwin(NewScreen(SP_PARM));
-	NewScreen(SP_PARM) = getwin(fp);
+	&& (fp = safe_fopen(file, BIN_R)) != 0) {
+	NewScreen(SP_PARM) = replace_window(NewScreen(SP_PARM), fp);
 #if !USE_REENTRANT
 	newscr = NewScreen(SP_PARM);
 #endif
@@ -928,7 +1002,7 @@
     T((T_CALLED("scr_dump(%s)"), _nc_visbuf(file)));
 
     if (_nc_access(file, W_OK) < 0
-	|| (fp = fopen(file, "wb")) == 0) {
+	|| (fp = safe_fopen(file, BIN_W)) == 0) {
 	result = ERR;
     } else {
 	(void) putwin(newscr, fp);
@@ -941,7 +1015,6 @@
 NCURSES_EXPORT(int)
 NCURSES_SP_NAME(scr_init) (NCURSES_SP_DCLx const char *file)
 {
-    FILE *fp = 0;
     int code = ERR;
 
     T((T_CALLED("scr_init(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file)));
@@ -953,10 +1026,11 @@
 	!(exit_ca_mode && non_rev_rmcup)
 #endif
 	) {
+	FILE *fp = 0;
+
 	if (_nc_access(file, R_OK) >= 0
-	    && (fp = fopen(file, "rb")) != 0) {
-	    delwin(CurScreen(SP_PARM));
-	    CurScreen(SP_PARM) = getwin(fp);
+	    && (fp = safe_fopen(file, BIN_R)) != 0) {
+	    CurScreen(SP_PARM) = replace_window(CurScreen(SP_PARM), fp);
 #if !USE_REENTRANT
 	    curscr = CurScreen(SP_PARM);
 #endif