diff options
| author | Baptiste Daroussin <bapt@FreeBSD.org> | 2020-02-07 08:36:41 +0000 |
|---|---|---|
| committer | Baptiste Daroussin <bapt@FreeBSD.org> | 2020-02-07 08:36:41 +0000 |
| commit | f0179cb6083cc92e5947ae56e6a0a5c5328aead0 (patch) | |
| tree | bcee0ba9c2149b71f0bfc036df1e61e3105bf980 /ncurses/base | |
| parent | cea297eb34d2361e79529034397465068ae34ecd (diff) | |
Notes
Diffstat (limited to 'ncurses/base')
52 files changed, 2910 insertions, 774 deletions
diff --git a/ncurses/base/MKkeyname.awk b/ncurses/base/MKkeyname.awk index 7901611931698..e133858f28352 100644 --- a/ncurses/base/MKkeyname.awk +++ b/ncurses/base/MKkeyname.awk @@ -1,6 +1,6 @@ -# $Id: MKkeyname.awk,v 1.48 2013/08/24 17:37:22 tom Exp $ +# $Id: MKkeyname.awk,v 1.50 2017/04/11 01:18:08 tom Exp $ ############################################################################## -# Copyright (c) 1999-2012,2013 Free Software Foundation, Inc. # +# Copyright (c) 1999-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 "Software"), # @@ -70,14 +70,13 @@ END { print "NCURSES_EXPORT(NCURSES_CONST char *)" print "safe_keyname (SCREEN *sp, int c)" print "{" - print " int i;" print " char name[20];" - print " char *p;" print " NCURSES_CONST char *result = 0;" print "" print " if (c == -1) {" print " result = \"-1\";" print " } else {" + print " int i;" if (bigstrings) { print " for (i = 0; _nc_key_names[i].offset != -1; i++) {" print " if (_nc_key_names[i].code == c) {" @@ -114,7 +113,7 @@ END { print " /* create and cache result as needed */" print " if (MyTable[c] == 0) {" print " int cc = c;" - print " p = name;" + print " char *p = name;" print "#define P_LIMIT (sizeof(name) - (size_t) (p - name))" print " if (cc >= 128 && m_prefix) {" print " _nc_STRCPY(p, \"M-\", P_LIMIT);" @@ -135,7 +134,7 @@ END { print " } else if (result == 0 && HasTerminal(sp)) {" print " int j, k;" print " char * bound;" - print " TERMTYPE *tp = &(TerminalOf(sp)->type);" + print " TERMTYPE2 *tp = &TerminalType(TerminalOf(sp));" print " unsigned save_trace = _nc_tracing;" print "" print " _nc_tracing = 0; /* prevent recursion via keybound() */" @@ -166,8 +165,8 @@ END { print "#if NO_LEAKS" print "void _nc_keyname_leaks(void)" print "{" - print " int j;" print " if (MyTable != 0) {" + print " int j;" print " for (j = 0; j < SIZEOF_TABLE; ++j) {" print " FreeIfNeeded(MyTable[j]);" print " }" diff --git a/ncurses/base/MKlib_gen.sh b/ncurses/base/MKlib_gen.sh index d8cc3c9751faa..a1587c4244522 100755 --- a/ncurses/base/MKlib_gen.sh +++ b/ncurses/base/MKlib_gen.sh @@ -2,10 +2,10 @@ # # MKlib_gen.sh -- generate sources from curses.h macro definitions # -# ($Id: MKlib_gen.sh,v 1.46 2011/06/04 19:14:08 tom Exp $) +# ($Id: MKlib_gen.sh,v 1.62 2018/06/09 19:27:00 tom Exp $) # ############################################################################## -# Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. # +# Copyright (c) 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 "Software"), # @@ -62,10 +62,27 @@ if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi if test "${LC_COLLATE+set}" = set; then LC_COLLATE=C; export LC_COLLATE; fi -preprocessor="$1 -DNCURSES_INTERNALS -I../include" +preprocessor="$1 -DNCURSES_WATTR_MACROS -DNCURSES_INTERNALS -I../include" AWK="$2" USE="$3" +# A patch discussed here: +# https://gcc.gnu.org/ml/gcc-patches/2014-06/msg02185.html +# introduces spurious #line markers into the preprocessor output. The result +# appears in gcc 5.0 and (with modification) in 5.1, making it necessary to +# determine if we are using gcc, and if so, what version because the proposed +# solution uses a nonstandard option. +PRG=`echo "$1" | $AWK '{ sub(/^[ ]*/,""); sub(/[ ].*$/, ""); print; }' || exit 0` +FSF=`"$PRG" --version 2>/dev/null || exit 0 | fgrep "Free Software Foundation" | head -n 1` +ALL=`"$PRG" -dumpversion 2>/dev/null || exit 0` +ONE=`echo "$ALL" | sed -e 's/\..*$//'` +if test -n "$FSF" && test -n "$ALL" && test -n "$ONE" ; then + if test $ONE -ge 5 ; then + echo ".. adding -P option to work around $PRG $ALL" >&2 + preprocessor="$preprocessor -P" + fi +fi + PID=$$ ED1=sed1_${PID}.sed ED2=sed2_${PID}.sed @@ -74,7 +91,7 @@ ED4=sed4_${PID}.sed AW1=awk1_${PID}.awk AW2=awk2_${PID}.awk TMP=gen__${PID}.c -trap "rm -f $ED1 $ED2 $ED3 $ED4 $AW1 $AW2 $TMP" 0 1 2 5 15 +trap "rm -f $ED1 $ED2 $ED3 $ED4 $AW1 $AW2 $TMP" 0 1 2 3 15 ALL=$USE if test "$USE" = implemented ; then @@ -82,6 +99,7 @@ if test "$USE" = implemented ; then cat >$ED1 <<EOF1 /^extern.*implemented/{ h + s/GCC_DEPRECATED([^)]*)// s/NCURSES_SP_NAME(\([^)]*\))/NCURSES_SP_NAME___\1/ h s/^.*implemented:\([^ *]*\).*/P_POUNDCif_USE_\1_SUPPORT/p @@ -160,6 +178,7 @@ EOF3 if test "$USE" = generated ; then cat >$ED4 <<EOF s/^\(.*\) \(.*\) (\(.*\))\$/NCURSES_EXPORT(\1) (\2) (\3)/ + /attr_[sg]et.* z)/s,z),z GCC_UNUSED), EOF else cat >$ED4 <<EOF @@ -213,7 +232,7 @@ $0 !~ /^P_/ { } else if ( $first == "bool" || $first == "NCURSES_BOOL" ) { returnType = "Bool"; } else if ( $second == "*" ) { - returnType = "Ptr"; + returnType = ($1 == "NCURSES_CONST") ? "CPtr" : "Ptr"; } else { returnType = "Code"; } @@ -224,6 +243,9 @@ $0 !~ /^P_/ { break; } } + if (using == "implemented") { + printf "#undef %s\n", $myfunc; + } print $0; print "{"; argcount = 1; @@ -256,6 +278,11 @@ $0 !~ /^P_/ { dotrace = 0; } + do_getstr = 0; + if ($myfunc ~ /get[n]?str/) { + do_getstr = 1; + } + call = "@@T((T_CALLED(\"" args = "" comma = "" @@ -292,7 +319,11 @@ $0 !~ /^P_/ { call = call "%s" } else if (pointer) { if ( argtype == "char" ) { - call = call "%s" + if (do_getstr) { + call = call "%p" + } else { + call = call "%s" + } comma = comma "_nc_visbuf2(" num "," pointer = 0; } else { @@ -342,7 +373,7 @@ $0 !~ /^P_/ { call = call ")); " if (dotrace) - printf "%s", call + printf "%s\n\t@@", call if (match($0, "^void")) { call = "" @@ -381,9 +412,10 @@ EOF1 cat >$AW2 <<EOF1 BEGIN { + printf "/* This file was generated by $0 $USE */\n" + print "" print "/*" print " * DO NOT EDIT THIS FILE BY HAND!" - printf " * It is generated by $0 %s.\n", "$USE" if ( "$USE" == "generated" ) { print " *" print " * This is a file of trivial functions generated from macro" @@ -403,11 +435,6 @@ BEGIN { print "" print "#include <curses.priv.h>" print "" - print "#undef vw_scanw" - print "#undef vwscanw" - print "" - print "#undef vw_printw" - print "#undef vwprintw" } /^DECLARATIONS/ {start = 1; next;} { @@ -432,16 +459,16 @@ END { for (n = 1; n < start; ++n) { value = calls[n]; if ( value !~ /P_POUNDC/ ) { - gsub(/[[:blank:]]+/," ",value); - sub(/^[[:alnum:]_]+ /,"",value); + gsub(/[ \t]+/," ",value); + sub(/^[0-9a-zA-Z_]+ /,"",value); sub(/^\* /,"",value); - gsub(/[[:alnum:]_]+ \* /,"",value); + gsub(/[0-9a-zA-Z_]+ \* /,"",value); gsub(/ (const) /," ",value); gsub(/ (int|short|attr_t|chtype|wchar_t|NCURSES_BOOL|NCURSES_OUTC|NCURSES_OUTC_sp|va_list) /," ",value); gsub(/ void /,"",value); sub(/^/,"call_",value); - gsub(/ (a[[:digit:]]|z) /, " 0 ", value); - gsub(/ int[[:blank:]]*[(][^)]+[)][(][^)]+[)]/, "0", value); + gsub(/ (a[0-9]|z) /, " 0 ", value); + gsub(/ int[ \t]*[(][^)]+[)][(][^)]+[)]/, "0", value); printf "\t%s;\n", value; } else { print value; diff --git a/ncurses/base/MKunctrl.awk b/ncurses/base/MKunctrl.awk index 51ceb6343920d..0b505d0ce9123 100644 --- a/ncurses/base/MKunctrl.awk +++ b/ncurses/base/MKunctrl.awk @@ -1,6 +1,6 @@ -# $Id: MKunctrl.awk,v 1.27 2012/06/09 20:29:33 tom Exp $ +# $Id: MKunctrl.awk,v 1.28 2017/02/11 17:30:48 tom Exp $ ############################################################################## -# Copyright (c) 1998-2009,2012 Free Software Foundation, Inc. # +# Copyright (c) 1998-2012,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 "Software"), # @@ -143,6 +143,7 @@ END { print "\tint check = (int) ChCharOf(ch);" print "\tconst char *result;" print "" + print "(void) sp;" print "\tif (check >= 0 && check < (int)SIZEOF(unctrl_table)) {" print "#if NCURSES_EXT_FUNCS" print "\t\tif ((sp != 0)" diff --git a/ncurses/base/define_key.c b/ncurses/base/define_key.c index a49b094279c8f..c78375a72c254 100644 --- a/ncurses/base/define_key.c +++ b/ncurses/base/define_key.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2006,2009 Free Software Foundation, Inc. * + * Copyright (c) 1998-2009,2014 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 * @@ -33,7 +33,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: define_key.c,v 1.20 2009/11/28 22:53:17 tom Exp $") +MODULE_ID("$Id: define_key.c,v 1.21 2014/03/08 20:32:59 tom Exp $") NCURSES_EXPORT(int) NCURSES_SP_NAME(define_key) (NCURSES_SP_DCLx const char *str, int keycode) @@ -47,7 +47,7 @@ NCURSES_SP_NAME(define_key) (NCURSES_SP_DCLx const char *str, int keycode) unsigned ukey = (unsigned) keycode; #ifdef USE_TERM_DRIVER -#define CallHasKey(keycode) CallDriver_1(SP_PARM, kyExist, keycode) +#define CallHasKey(keycode) CallDriver_1(SP_PARM, td_kyExist, keycode) #else #define CallHasKey(keycode) NCURSES_SP_NAME(has_key)(NCURSES_SP_ARGx keycode) #endif diff --git a/ncurses/base/keyok.c b/ncurses/base/keyok.c index 00e936dacde99..180c54aa191c9 100644 --- a/ncurses/base/keyok.c +++ b/ncurses/base/keyok.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc. * + * Copyright (c) 1998-2014,2019 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 * @@ -33,7 +33,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: keyok.c,v 1.13 2012/11/18 02:14:35 tom Exp $") +MODULE_ID("$Id: keyok.c,v 1.15 2019/12/21 22:40:32 tom Exp $") /* * Enable (or disable) ncurses' interpretation of a keycode by adding (or @@ -53,9 +53,8 @@ NCURSES_SP_NAME(keyok) (NCURSES_SP_DCLx int c, bool flag) if (HasTerminal(SP_PARM)) { T((T_CALLED("keyok(%p, %d,%d)"), (void *) SP_PARM, c, flag)); #ifdef USE_TERM_DRIVER - code = CallDriver_2(sp, kyOk, c, flag); + code = CallDriver_2(sp, td_kyOk, c, flag); #else - T((T_CALLED("keyok(%d,%d)"), c, flag)); if (c >= 0) { int count = 0; char *s; diff --git a/ncurses/base/lib_addch.c b/ncurses/base/lib_addch.c index a7d498b490a0e..fdb26415b205c 100644 --- a/ncurses/base/lib_addch.c +++ b/ncurses/base/lib_addch.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc. * + * Copyright (c) 1998-2017,2019 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 * @@ -36,7 +36,7 @@ #include <curses.priv.h> #include <ctype.h> -MODULE_ID("$Id: lib_addch.c,v 1.128 2014/02/23 01:21:08 tom Exp $") +MODULE_ID("$Id: lib_addch.c,v 1.133 2019/05/11 19:51:02 tom Exp $") static const NCURSES_CH_T blankchar = NewChar(BLANK_TEXT); @@ -51,7 +51,7 @@ static const NCURSES_CH_T blankchar = NewChar(BLANK_TEXT); */ /* Return bit mask for clearing color pair number if given ch has color */ -#define COLOR_MASK(ch) (~(attr_t)((ch) & A_COLOR ? A_COLOR : 0)) +#define COLOR_MASK(ch) (~(attr_t)(((ch) & A_COLOR) ? A_COLOR : 0)) static NCURSES_INLINE NCURSES_CH_T render_char(WINDOW *win, NCURSES_CH_T ch) @@ -117,14 +117,18 @@ _nc_render(WINDOW *win, NCURSES_CH_T ch) #endif static bool -newline_forces_scroll(WINDOW *win, NCURSES_SIZE_T * ypos) +newline_forces_scroll(WINDOW *win, NCURSES_SIZE_T *ypos) { bool result = FALSE; - if (*ypos >= win->_regtop && *ypos == win->_regbottom) { - *ypos = win->_regbottom; - result = TRUE; - } else { + if (*ypos >= win->_regtop && *ypos <= win->_regbottom) { + if (*ypos == win->_regbottom) { + *ypos = win->_regbottom; + result = TRUE; + } else if (*ypos < win->_maxy) { + *ypos = (NCURSES_SIZE_T) (*ypos + 1); + } + } else if (*ypos < win->_maxy) { *ypos = (NCURSES_SIZE_T) (*ypos + 1); } return result; @@ -270,11 +274,11 @@ waddch_literal(WINDOW *win, NCURSES_CH_T ch) /* handle EILSEQ (i.e., when len >= -1) */ if (len == -1 && is8bits(CharOf(ch))) { - int rc = OK; const char *s = NCURSES_SP_NAME(unctrl) (NCURSES_SP_ARGx (chtype) CharOf(ch)); if (s[1] != '\0') { + int rc = OK; while (*s != '\0') { rc = waddch(win, UChar(*s) | attr); if (rc != OK) @@ -299,7 +303,7 @@ waddch_literal(WINDOW *win, NCURSES_CH_T ch) * adjustments. */ if_WIDEC({ - int len = wcwidth(CharOf(ch)); + int len = _nc_wacs_width(CharOf(ch)); int i; int j; wchar_t *chars; @@ -339,6 +343,7 @@ waddch_literal(WINDOW *win, NCURSES_CH_T ch) return ERR; x = win->_curx; y = win->_cury; + CHECK_POSITION(win, x, y); line = win->_line + y; } /* @@ -427,7 +432,7 @@ waddch_nosync(WINDOW *win, const NCURSES_CH_T ch) s[1] == 0 ) || ( - (isprint((int)t) && !iscntrl((int)t)) + (isprint((int) t) && !iscntrl((int) t)) #if USE_WIDEC_SUPPORT || ((sp == 0 || !sp->_legacy_coding) && (WINDOW_EXT(win, addch_used) @@ -443,6 +448,7 @@ waddch_nosync(WINDOW *win, const NCURSES_CH_T ch) */ x = win->_curx; y = win->_cury; + CHECK_POSITION(win, x, y); switch (t) { case '\t': @@ -501,7 +507,7 @@ waddch_nosync(WINDOW *win, const NCURSES_CH_T ch) default: while (*s) { NCURSES_CH_T sch; - SetChar(sch, *s++, AttrOf(ch)); + SetChar(sch, UChar(*s++), AttrOf(ch)); if_EXT_COLORS(SetPair(sch, GetPair(ch))); if (waddch_literal(win, sch) == ERR) return ERR; diff --git a/ncurses/base/lib_addstr.c b/ncurses/base/lib_addstr.c index a1a55cb8bfd8b..55dc440b00479 100644 --- a/ncurses/base/lib_addstr.c +++ b/ncurses/base/lib_addstr.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * + * Copyright (c) 1998-2017,2019 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 * @@ -44,7 +44,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_addstr.c,v 1.52 2011/05/28 23:02:09 tom Exp $") +MODULE_ID("$Id: lib_addstr.c,v 1.55 2019/05/04 20:46:24 tom Exp $") NCURSES_EXPORT(int) waddnstr(WINDOW *win, const char *astr, int n) @@ -87,7 +87,7 @@ waddchnstr(WINDOW *win, const chtype *astr, int n) T((T_CALLED("waddchnstr(%p,%p,%d)"), (void *) win, (const void *) astr, n)); - if (!win) + if (!win || !astr) returnCode(ERR); y = win->_cury; @@ -183,7 +183,7 @@ wadd_wchnstr(WINDOW *win, const cchar_t *astr, int n) if (isWidecExt(astr[i])) continue; - len = wcwidth(CharOf(astr[i])); + len = _nc_wacs_width(CharOf(astr[i])); if (x + len - 1 <= win->_maxx) { line->text[x] = _nc_render(win, astr[i]); @@ -194,6 +194,8 @@ wadd_wchnstr(WINDOW *win, const cchar_t *astr, int n) } SetWidecExt(line->text[x + j], j); } + } else { + len = 1; } x = (NCURSES_SIZE_T) (x + len); end += len - 1; diff --git a/ncurses/base/lib_beep.c b/ncurses/base/lib_beep.c index 4e14cb74a2bfc..b775d56e80011 100644 --- a/ncurses/base/lib_beep.c +++ b/ncurses/base/lib_beep.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2013 Free Software Foundation, Inc. * + * Copyright (c) 1998-2013,2014 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 * @@ -46,7 +46,7 @@ #define CUR SP_TERMTYPE #endif -MODULE_ID("$Id: lib_beep.c,v 1.16 2013/01/12 17:26:25 tom Exp $") +MODULE_ID("$Id: lib_beep.c,v 1.17 2014/03/08 20:32:59 tom Exp $") /* * beep() @@ -65,7 +65,7 @@ NCURSES_SP_NAME(beep) (NCURSES_SP_DCL0) #ifdef USE_TERM_DRIVER if (SP_PARM != 0) - res = CallDriver_1(SP_PARM, doBeepOrFlash, TRUE); + res = CallDriver_1(SP_PARM, td_doBeepOrFlash, TRUE); #else /* FIXME: should make sure that we are not in altchar mode */ if (cur_term == 0) { diff --git a/ncurses/base/lib_bkgd.c b/ncurses/base/lib_bkgd.c index 7bcd3ffb5a3fe..aa1db21e4fa8f 100644 --- a/ncurses/base/lib_bkgd.c +++ b/ncurses/base/lib_bkgd.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc. * + * Copyright (c) 1998-2018,2019 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 * @@ -36,7 +36,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_bkgd.c,v 1.48 2012/12/09 01:01:19 tom Exp $") +MODULE_ID("$Id: lib_bkgd.c,v 1.53 2019/08/17 20:59:41 tom Exp $") /* * Set the window's background information. @@ -117,29 +117,98 @@ static NCURSES_INLINE int #endif wbkgrnd(WINDOW *win, const ARG_CH_T ch) { +#undef SP_PARM +#define SP_PARM SP /* to use Charable() */ int code = ERR; - int x, y; T((T_CALLED("wbkgd(%p,%s)"), (void *) win, _tracech_t(ch))); - if (win) { + if (SP == 0) { + ; + } else if (win) { NCURSES_CH_T new_bkgd = CHDEREF(ch); - NCURSES_CH_T old_bkgrnd; + NCURSES_CH_T old_bkgd; + int y; + NCURSES_CH_T old_char; + attr_t old_attr; + int old_pair; + NCURSES_CH_T new_char; + attr_t new_attr; + int new_pair; + + /* SVr4 trims color info if non-color terminal */ + if (!SP->_pair_limit) { + RemAttr(new_bkgd, A_COLOR); + SetPair(new_bkgd, 0); + } + + memset(&old_bkgd, 0, sizeof(old_bkgd)); + (void) wgetbkgrnd(win, &old_bkgd); + + if (!memcmp(&old_bkgd, &new_bkgd, sizeof(new_bkgd))) { + T(("...unchanged")); + returnCode(OK); + } + + old_char = old_bkgd; + RemAttr(old_char, ~A_CHARTEXT); + old_attr = AttrOf(old_bkgd); + old_pair = GetPair(old_bkgd); + + if (!(old_attr & A_COLOR)) { + old_pair = 0; + } + T(("... old background char %s, attr %s, pair %d", + _tracechar(CharOf(old_char)), _traceattr(old_attr), old_pair)); - memset(&old_bkgrnd, 0, sizeof(old_bkgrnd)); - wgetbkgrnd(win, &old_bkgrnd); + new_char = new_bkgd; + RemAttr(new_char, ~A_CHARTEXT); + new_attr = AttrOf(new_bkgd); + new_pair = GetPair(new_bkgd); + + /* SVr4 limits background character to printable 7-bits */ + if (!Charable(new_bkgd)) { + new_char = old_char; + } + if (!(new_attr & A_COLOR)) { + new_pair = 0; + } + T(("... new background char %s, attr %s, pair %d", + _tracechar(CharOf(new_char)), _traceattr(new_attr), new_pair)); (void) wbkgrndset(win, CHREF(new_bkgd)); - (void) wattrset(win, (int) AttrOf(win->_nc_bkgd)); + + /* SVr4 updates color pair if old/new match, otherwise just attrs */ + if ((new_pair != 0) && (new_pair == old_pair)) { + WINDOW_ATTRS(win) = new_attr; + SET_WINDOW_PAIR(win, new_pair); + } else { + WINDOW_ATTRS(win) = new_attr; + } for (y = 0; y <= win->_maxy; y++) { + int x; + for (x = 0; x <= win->_maxx; x++) { - if (CharEq(win->_line[y].text[x], old_bkgrnd)) { - win->_line[y].text[x] = win->_nc_bkgd; + NCURSES_CH_T *cp = &(win->_line[y].text[x]); + int tmp_pair = GetPair(*cp); + attr_t tmp_attr = AttrOf(*cp); + + if (CharEq(*cp, old_bkgd)) { + SetChar2(*cp, CharOf(new_char)); + } + if (tmp_pair != 0) { + if (tmp_pair == old_pair) { + SetAttr(*cp, (tmp_attr & ~old_attr) | new_attr); + SetPair(*cp, new_pair); + } else { + SetAttr(*cp, + (tmp_attr & (~old_attr | A_COLOR)) + | (new_attr & ALL_BUT_COLOR)); + } } else { - NCURSES_CH_T wch = win->_line[y].text[x]; - RemAttr(wch, (~(A_ALTCHARSET | A_CHARTEXT))); - win->_line[y].text[x] = _nc_render(win, wch); + SetAttr(*cp, (tmp_attr & ~old_attr) | new_attr); + SetPair(*cp, new_pair); } } } diff --git a/ncurses/base/lib_box.c b/ncurses/base/lib_box.c index 6f17c97a5b07b..dccb8e12d61c6 100644 --- a/ncurses/base/lib_box.c +++ b/ncurses/base/lib_box.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. * + * Copyright (c) 1998-2010,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 * @@ -42,7 +42,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_box.c,v 1.24 2010/04/24 23:51:57 tom Exp $") +MODULE_ID("$Id: lib_box.c,v 1.25 2017/10/27 21:56:17 tom Exp $") #if USE_WIDEC_SUPPORT static NCURSES_INLINE chtype @@ -114,10 +114,20 @@ wborder(WINDOW *win, win->_line[endy].lastchar = win->_line[0].lastchar = endx; for (i = 0; i <= endy; i++) { +#if USE_WIDEC_SUPPORT + if (endx > 0 && isWidecExt(win->_line[i].text[endx])) { + SetChar2(win->_line[i].text[endx - 1], ' '); + } +#endif SetChar2(win->_line[i].text[0], wls); SetChar2(win->_line[i].text[endx], wrs); win->_line[i].firstchar = 0; win->_line[i].lastchar = endx; +#if USE_WIDEC_SUPPORT + if (isWidecExt(win->_line[i].text[1])) { + SetChar2(win->_line[i].text[1], ' '); + } +#endif } SetChar2(win->_line[0].text[0], wtl); SetChar2(win->_line[0].text[endx], wtr); diff --git a/ncurses/base/lib_chgat.c b/ncurses/base/lib_chgat.c index 1eb1f59e2385d..e969d69bebb76 100644 --- a/ncurses/base/lib_chgat.c +++ b/ncurses/base/lib_chgat.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2010,2014 Free Software Foundation, Inc. * + * Copyright (c) 1998-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 * @@ -42,35 +42,38 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_chgat.c,v 1.10 2014/02/01 22:13:31 tom Exp $") +MODULE_ID("$Id: lib_chgat.c,v 1.12 2017/03/16 23:45:20 tom Exp $") NCURSES_EXPORT(int) wchgat(WINDOW *win, int n, attr_t attr, - NCURSES_PAIRS_T color, + NCURSES_PAIRS_T pair_arg, const void *opts GCC_UNUSED) { - int i; + int code = ERR; + int color_pair = pair_arg; T((T_CALLED("wchgat(%p,%d,%s,%d)"), (void *) win, n, _traceattr(attr), - (int) color)); + color_pair)); + set_extended_pair(opts, color_pair); if (win) { struct ldat *line = &(win->_line[win->_cury]); + int i; - toggle_attr_on(attr, ColorPair(color)); + toggle_attr_on(attr, ColorPair(color_pair)); for (i = win->_curx; i <= win->_maxx && (n == -1 || (n-- > 0)); i++) { SetAttr(line->text[i], attr); - SetPair(line->text[i], color); + SetPair(line->text[i], color_pair); CHANGED_CELL(line, i); } - returnCode(OK); - } else - returnCode(ERR); + code = OK; + } + returnCode(code); } diff --git a/ncurses/base/lib_color.c b/ncurses/base/lib_color.c index 9f7250ddaffff..e2958051e6b8d 100644 --- a/ncurses/base/lib_color.c +++ b/ncurses/base/lib_color.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc. * + * Copyright (c) 1998-2018,2019 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 * @@ -38,14 +38,17 @@ * Handles color emulation of SYS V curses */ +#define NEW_PAIR_INTERNAL 1 + #include <curses.priv.h> +#include <new_pair.h> #include <tic.h> #ifndef CUR #define CUR SP_TERMTYPE #endif -MODULE_ID("$Id: lib_color.c,v 1.109 2014/02/01 22:22:30 tom Exp $") +MODULE_ID("$Id: lib_color.c,v 1.142 2019/12/22 00:57:53 tom Exp $") #ifdef USE_TERM_DRIVER #define CanChange InfoOf(SP_PARM).canchange @@ -137,13 +140,6 @@ NCURSES_EXPORT_VAR(const color_t*) _nc_hls_palette = hls_palette; /* *INDENT-ON* */ -/* - * Ensure that we use color pairs only when colors have been started, and also - * that the index is within the limits of the table which we allocated. - */ -#define ValidPair(pair) \ - ((SP_PARM != 0) && (pair >= 0) && (pair < SP_PARM->_pair_limit) && SP_PARM->_coloron) - #if NCURSES_EXT_FUNCS /* * These are called from _nc_do_color(), which in turn is called from @@ -188,7 +184,7 @@ static void set_background_color(NCURSES_SP_DCLx int bg, NCURSES_SP_OUTC outc) { #ifdef USE_TERM_DRIVER - CallDriver_3(SP_PARM, color, FALSE, bg, outc); + CallDriver_3(SP_PARM, td_color, FALSE, bg, outc); #else if (set_a_background) { TPUTS_TRACE("set_a_background"); @@ -208,7 +204,7 @@ static void set_foreground_color(NCURSES_SP_DCLx int fg, NCURSES_SP_OUTC outc) { #ifdef USE_TERM_DRIVER - CallDriver_3(SP_PARM, color, TRUE, fg, outc); + CallDriver_3(SP_PARM, td_color, TRUE, fg, outc); #else if (set_a_foreground) { TPUTS_TRACE("set_a_foreground"); @@ -251,6 +247,60 @@ init_color_table(NCURSES_SP_DCL0) } } +static bool +init_direct_colors(NCURSES_SP_DCL0) +{ + static NCURSES_CONST char name[] = "RGB"; + + int n; + const char *s; + int width; + rgb_bits_t *result = &(SP_PARM->_direct_color); + + result->value = 0; + + if (COLORS >= 8) { + /* find the number of bits needed for the maximum color value */ + for (width = 0; (1 << width) - 1 < (COLORS - 1); ++width) { + ; + } + + if ((n = tigetflag(name)) > 0) { + n = (width + 2) / 3; + result->bits.red = UChar(n); + result->bits.green = UChar(n); + result->bits.blue = UChar(width - (2 * n)); + } else if ((n = tigetnum(name)) > 0) { + result->bits.red = UChar(n); + result->bits.green = UChar(n); + result->bits.blue = UChar(n); + } else if ((s = tigetstr(name)) != 0 && VALID_STRING(s)) { + int red = n; + int green = n; + int blue = width - (2 * n); + + switch (sscanf(s, "%d/%d/%d", &red, &green, &blue)) { + default: + blue = width - (2 * n); + /* FALLTHRU */ + case 1: + green = n; + /* FALLTHRU */ + case 2: + red = n; + /* FALLTHRU */ + case 3: + /* okay */ + break; + } + result->bits.red = UChar(red); + result->bits.green = UChar(green); + result->bits.blue = UChar(blue); + } + } + return (result->value != 0); +} + /* * Reset the color pair, e.g., to whatever color pair 0 is. */ @@ -258,7 +308,7 @@ static bool reset_color_pair(NCURSES_SP_DCL0) { #ifdef USE_TERM_DRIVER - return CallDriver(SP_PARM, rescol); + return CallDriver(SP_PARM, td_rescol); #else bool result = FALSE; @@ -288,7 +338,7 @@ NCURSES_SP_NAME(_nc_reset_colors) (NCURSES_SP_DCL0) result = TRUE; #ifdef USE_TERM_DRIVER - result = CallDriver(SP_PARM, rescolors); + result = CallDriver(SP_PARM, td_rescolors); #else if (orig_colors != 0) { NCURSES_PUTP2("orig_colors", orig_colors); @@ -346,7 +396,10 @@ NCURSES_SP_NAME(start_color) (NCURSES_SP_DCL0) * allow for default-color as a component of a color-pair. */ SP_PARM->_pair_limit += (1 + (2 * maxcolors)); +#if !NCURSES_EXT_COLORS + SP_PARM->_pair_limit = limit_PAIRS(SP_PARM->_pair_limit); #endif +#endif /* NCURSES_EXT_FUNCS */ SP_PARM->_pair_count = maxpairs; SP_PARM->_color_count = maxcolors; #if !USE_REENTRANT @@ -354,19 +407,26 @@ NCURSES_SP_NAME(start_color) (NCURSES_SP_DCL0) COLORS = maxcolors; #endif - SP_PARM->_color_pairs = TYPE_CALLOC(colorpair_t, SP_PARM->_pair_limit); + ReservePairs(SP_PARM, 16); if (SP_PARM->_color_pairs != 0) { - SP_PARM->_color_table = TYPE_CALLOC(color_t, maxcolors); - if (SP_PARM->_color_table != 0) { - SP_PARM->_color_pairs[0] = PAIR_OF(default_fg(NCURSES_SP_ARG), - default_bg(NCURSES_SP_ARG)); - init_color_table(NCURSES_SP_ARG); + if (init_direct_colors(NCURSES_SP_ARG)) { + result = OK; + } else { + SP_PARM->_color_table = TYPE_CALLOC(color_t, maxcolors); + if (SP_PARM->_color_table != 0) { + MakeColorPair(SP_PARM->_color_pairs[0], + default_fg(NCURSES_SP_ARG), + default_bg(NCURSES_SP_ARG)); + init_color_table(NCURSES_SP_ARG); + result = OK; + } + } + if (result == OK) { T(("started color: COLORS = %d, COLOR_PAIRS = %d", COLORS, COLOR_PAIRS)); SP_PARM->_coloron = 1; - result = OK; } else if (SP_PARM->_color_pairs != 0) { FreeAndNull(SP_PARM->_color_pairs); } @@ -388,7 +448,7 @@ start_color(void) /* This function was originally written by Daniel Weaver <danw@znyx.com> */ static void -rgb2hls(int r, int g, int b, NCURSES_COLOR_T *h, NCURSES_COLOR_T *l, NCURSES_COLOR_T *s) +rgb2hls(int r, int g, int b, int *h, int *l, int *s) /* convert RGB to HLS system */ { int min, max, t; @@ -399,7 +459,7 @@ rgb2hls(int r, int g, int b, NCURSES_COLOR_T *h, NCURSES_COLOR_T *l, NCURSES_COL max = b; /* calculate lightness */ - *l = (NCURSES_COLOR_T) ((min + max) / 20); + *l = ((min + max) / 20); if (min == max) { /* black, white and all shades of gray */ *h = 0; @@ -409,19 +469,88 @@ rgb2hls(int r, int g, int b, NCURSES_COLOR_T *h, NCURSES_COLOR_T *l, NCURSES_COL /* calculate saturation */ if (*l < 50) - *s = (NCURSES_COLOR_T) (((max - min) * 100) / (max + min)); + *s = (((max - min) * 100) / (max + min)); else - *s = (NCURSES_COLOR_T) (((max - min) * 100) / (2000 - max - min)); + *s = (((max - min) * 100) / (2000 - max - min)); /* calculate hue */ if (r == max) - t = (NCURSES_COLOR_T) (120 + ((g - b) * 60) / (max - min)); + t = (120 + ((g - b) * 60) / (max - min)); else if (g == max) - t = (NCURSES_COLOR_T) (240 + ((b - r) * 60) / (max - min)); + t = (240 + ((b - r) * 60) / (max - min)); else - t = (NCURSES_COLOR_T) (360 + ((r - g) * 60) / (max - min)); + t = (360 + ((r - g) * 60) / (max - min)); + + *h = (t % 360); +} + +/* + * Change all cells which use(d) a given color pair to force a repaint. + */ +NCURSES_EXPORT(void) +_nc_change_pair(SCREEN *sp, int pair) +{ + int y, x; + + if (CurScreen(sp)->_clear) + return; +#if NO_LEAKS + if (_nc_globals.leak_checking) + return; +#endif + + for (y = 0; y <= CurScreen(sp)->_maxy; y++) { + struct ldat *ptr = &(CurScreen(sp)->_line[y]); + bool changed = FALSE; + for (x = 0; x <= CurScreen(sp)->_maxx; x++) { + if (GetPair(ptr->text[x]) == pair) { + /* Set the old cell to zero to ensure it will be + updated on the next doupdate() */ + SetChar(ptr->text[x], 0, 0); + CHANGED_CELL(ptr, x); + changed = TRUE; + } + } + if (changed) + NCURSES_SP_NAME(_nc_make_oldhash) (NCURSES_SP_ARGx y); + } +} + +NCURSES_EXPORT(void) +_nc_reserve_pairs(SCREEN *sp, int want) +{ + int have = sp->_pair_alloc; - *h = (NCURSES_COLOR_T) (t % 360); + if (have == 0) + have = 1; + while (have <= want) + have *= 2; + if (have > sp->_pair_limit) + have = sp->_pair_limit; + + if (sp->_color_pairs == 0) { + sp->_color_pairs = TYPE_CALLOC(colorpair_t, have); + } else if (have > sp->_pair_alloc) { +#if NCURSES_EXT_COLORS + colorpair_t *next; + + if ((next = typeCalloc(colorpair_t, have)) == 0) + _nc_err_abort(MSG_NO_MEMORY); + memcpy(next, sp->_color_pairs, (size_t) sp->_pair_alloc * sizeof(*next)); + _nc_copy_pairs(sp, next, sp->_color_pairs, sp->_pair_alloc); + free(sp->_color_pairs); + sp->_color_pairs = next; +#else + TYPE_REALLOC(colorpair_t, have, sp->_color_pairs); + if (sp->_color_pairs != 0) { + memset(sp->_color_pairs + sp->_pair_alloc, 0, + sizeof(colorpair_t) * (size_t) (have - sp->_pair_alloc)); + } +#endif + } + if (sp->_color_pairs != 0) { + sp->_pair_alloc = have; + } } /* @@ -429,32 +558,27 @@ rgb2hls(int r, int g, int b, NCURSES_COLOR_T *h, NCURSES_COLOR_T *l, NCURSES_COL * values. */ NCURSES_EXPORT(int) -NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx - NCURSES_PAIRS_T pair, - NCURSES_COLOR_T f, - NCURSES_COLOR_T b) +_nc_init_pair(SCREEN *sp, int pair, int f, int b) { - colorpair_t result; + static colorpair_t null_pair; + colorpair_t result = null_pair; colorpair_t previous; int maxcolors; - T((T_CALLED("init_pair(%p,%d,%d,%d)"), - (void *) SP_PARM, - (int) pair, - (int) f, - (int) b)); + T((T_CALLED("init_pair(%p,%d,%d,%d)"), (void *) sp, pair, f, b)); - if (!ValidPair(pair)) + if (!ValidPair(sp, pair)) returnCode(ERR); maxcolors = MaxColors; - previous = SP_PARM->_color_pairs[pair]; + ReservePairs(sp, pair); + previous = sp->_color_pairs[pair]; #if NCURSES_EXT_FUNCS - if (SP_PARM->_default_color || SP_PARM->_assumed_color) { + if (sp->_default_color || sp->_assumed_color) { bool isDefault = FALSE; bool wasDefault = FALSE; - int default_pairs = SP_PARM->_default_pairs; + int default_pairs = sp->_default_pairs; /* * Map caller's color number, e.g., -1, 0, 1, .., 7, etc., into @@ -479,8 +603,8 @@ NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx * Check if the table entry that we are going to init/update used * default colors. */ - if ((FORE_OF(previous) == COLOR_DEFAULT) - || (BACK_OF(previous) == COLOR_DEFAULT)) + if (isDefaultColor(FORE_OF(previous)) + || isDefaultColor(BACK_OF(previous))) wasDefault = TRUE; /* @@ -501,10 +625,10 @@ NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx * that does not will decrement the count - and possibly interfere * with sequentially adding new pairs. */ - if (pair > (SP_PARM->_pair_count + default_pairs)) { + if (pair > (sp->_pair_count + default_pairs)) { returnCode(ERR); } - SP_PARM->_default_pairs = default_pairs; + sp->_default_pairs = default_pairs; } else #endif { @@ -520,34 +644,22 @@ NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx * initialized before a screen update is performed replacing original * pair colors with the new ones). */ - result = PAIR_OF(f, b); - if (previous != 0 - && previous != result) { - int y, x; - - for (y = 0; y <= CurScreen(SP_PARM)->_maxy; y++) { - struct ldat *ptr = &(CurScreen(SP_PARM)->_line[y]); - bool changed = FALSE; - for (x = 0; x <= CurScreen(SP_PARM)->_maxx; x++) { - if (GetPair(ptr->text[x]) == pair) { - /* Set the old cell to zero to ensure it will be - updated on the next doupdate() */ - SetChar(ptr->text[x], 0, 0); - CHANGED_CELL(ptr, x); - changed = TRUE; - } - } - if (changed) - NCURSES_SP_NAME(_nc_make_oldhash) (NCURSES_SP_ARGx y); - } + MakeColorPair(result, f, b); + if ((FORE_OF(previous) != 0 + || BACK_OF(previous) != 0) + && !isSamePair(previous, result)) { + _nc_change_pair(sp, pair); } - SP_PARM->_color_pairs[pair] = result; - if (GET_SCREEN_PAIR(SP_PARM) == pair) - SET_SCREEN_PAIR(SP_PARM, (chtype) (~0)); /* force attribute update */ + _nc_reset_color_pair(sp, pair, &result); + sp->_color_pairs[pair] = result; + _nc_set_color_pair(sp, pair, cpINIT); + + if (GET_SCREEN_PAIR(sp) == pair) + SET_SCREEN_PAIR(sp, (int) (~0)); /* force attribute update */ #ifdef USE_TERM_DRIVER - CallDriver_3(SP_PARM, initpair, pair, f, b); + CallDriver_3(sp, td_initpair, pair, f, b); #else if (initialize_pair && InPalette(f) && InPalette(b)) { const color_t *tp = DefaultPalette; @@ -573,6 +685,15 @@ NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx returnCode(OK); } +NCURSES_EXPORT(int) +NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx + NCURSES_PAIRS_T pair, + NCURSES_COLOR_T f, + NCURSES_COLOR_T b) +{ + return _nc_init_pair(SP_PARM, pair, f, b); +} + #if NCURSES_SP_FUNCS NCURSES_EXPORT(int) init_pair(NCURSES_COLOR_T pair, NCURSES_COLOR_T f, NCURSES_COLOR_T b) @@ -584,59 +705,65 @@ init_pair(NCURSES_COLOR_T pair, NCURSES_COLOR_T f, NCURSES_COLOR_T b) #define okRGB(n) ((n) >= 0 && (n) <= 1000) NCURSES_EXPORT(int) -NCURSES_SP_NAME(init_color) (NCURSES_SP_DCLx - NCURSES_COLOR_T color, - NCURSES_COLOR_T r, - NCURSES_COLOR_T g, - NCURSES_COLOR_T b) +_nc_init_color(SCREEN *sp, int color, int r, int g, int b) { int result = ERR; int maxcolors; T((T_CALLED("init_color(%p,%d,%d,%d,%d)"), - (void *) SP_PARM, + (void *) sp, color, r, g, b)); - if (SP_PARM == 0) + if (sp == 0 || sp->_direct_color.value) returnCode(result); maxcolors = MaxColors; if (InitColor - && SP_PARM->_coloron + && sp->_coloron && (color >= 0 && OkColorHi(color)) && (okRGB(r) && okRGB(g) && okRGB(b))) { - SP_PARM->_color_table[color].init = 1; - SP_PARM->_color_table[color].r = r; - SP_PARM->_color_table[color].g = g; - SP_PARM->_color_table[color].b = b; + sp->_color_table[color].init = 1; + sp->_color_table[color].r = r; + sp->_color_table[color].g = g; + sp->_color_table[color].b = b; if (UseHlsPalette) { rgb2hls(r, g, b, - &SP_PARM->_color_table[color].red, - &SP_PARM->_color_table[color].green, - &SP_PARM->_color_table[color].blue); + &sp->_color_table[color].red, + &sp->_color_table[color].green, + &sp->_color_table[color].blue); } else { - SP_PARM->_color_table[color].red = r; - SP_PARM->_color_table[color].green = g; - SP_PARM->_color_table[color].blue = b; + sp->_color_table[color].red = r; + sp->_color_table[color].green = g; + sp->_color_table[color].blue = b; } #ifdef USE_TERM_DRIVER - CallDriver_4(SP_PARM, initcolor, color, r, g, b); + CallDriver_4(sp, td_initcolor, color, r, g, b); #else NCURSES_PUTP2("initialize_color", TPARM_4(initialize_color, color, r, g, b)); #endif - SP_PARM->_color_defs = max(color + 1, SP_PARM->_color_defs); + sp->_color_defs = max(color + 1, sp->_color_defs); result = OK; } returnCode(result); } +NCURSES_EXPORT(int) +NCURSES_SP_NAME(init_color) (NCURSES_SP_DCLx + NCURSES_COLOR_T color, + NCURSES_COLOR_T r, + NCURSES_COLOR_T g, + NCURSES_COLOR_T b) +{ + return _nc_init_color(SP_PARM, color, r, g, b); +} + #if NCURSES_SP_FUNCS NCURSES_EXPORT(int) init_color(NCURSES_COLOR_T color, @@ -676,7 +803,7 @@ NCURSES_SP_NAME(has_colors) (NCURSES_SP_DCL0) int code = FALSE; (void) SP_PARM; - T((T_CALLED("has_colors()"))); + T((T_CALLED("has_colors(%p)"), (void *) SP_PARM)); if (HasTerminal(SP_PARM)) { #ifdef USE_TERM_DRIVER code = HasColor; @@ -700,34 +827,54 @@ has_colors(void) } #endif -NCURSES_EXPORT(int) -NCURSES_SP_NAME(color_content) (NCURSES_SP_DCLx - NCURSES_COLOR_T color, - NCURSES_COLOR_T *r, - NCURSES_COLOR_T *g, - NCURSES_COLOR_T *b) +static int +_nc_color_content(SCREEN *sp, int color, int *r, int *g, int *b) { int result = ERR; int maxcolors; T((T_CALLED("color_content(%p,%d,%p,%p,%p)"), - (void *) SP_PARM, + (void *) sp, color, (void *) r, (void *) g, (void *) b)); - if (SP_PARM == 0) + if (sp == 0) returnCode(result); maxcolors = MaxColors; - if (color < 0 || !OkColorHi(color) || !SP_PARM->_coloron) { + if (color < 0 || !OkColorHi(color) || !sp->_coloron) { result = ERR; } else { - NCURSES_COLOR_T c_r = SP_PARM->_color_table[color].red; - NCURSES_COLOR_T c_g = SP_PARM->_color_table[color].green; - NCURSES_COLOR_T c_b = SP_PARM->_color_table[color].blue; + int c_r, c_g, c_b; + + if (sp->_direct_color.value) { + rgb_bits_t *work = &(sp->_direct_color); + +#define max_direct_color(name) ((1 << work->bits.name) - 1) +#define value_direct_color(max) (1000 * ((color >> bitoff) & max)) / max + + int max_r = max_direct_color(red); + int max_g = max_direct_color(green); + int max_b = max_direct_color(blue); + + int bitoff = 0; + + c_b = value_direct_color(max_b); + bitoff += work->bits.blue; + + c_g = value_direct_color(max_g); + bitoff += work->bits.green; + + c_r = value_direct_color(max_r); + + } else { + c_r = sp->_color_table[color].red; + c_g = sp->_color_table[color].green; + c_b = sp->_color_table[color].blue; + } if (r) *r = c_r; @@ -743,6 +890,23 @@ NCURSES_SP_NAME(color_content) (NCURSES_SP_DCLx returnCode(result); } +NCURSES_EXPORT(int) +NCURSES_SP_NAME(color_content) (NCURSES_SP_DCLx + NCURSES_COLOR_T color, + NCURSES_COLOR_T *r, + NCURSES_COLOR_T *g, + NCURSES_COLOR_T *b) +{ + int my_r, my_g, my_b; + int rc = _nc_color_content(SP_PARM, color, &my_r, &my_g, &my_b); + if (rc == OK) { + *r = limit_COLOR(my_r); + *g = limit_COLOR(my_g); + *b = limit_COLOR(my_b); + } + return rc; +} + #if NCURSES_SP_FUNCS NCURSES_EXPORT(int) color_content(NCURSES_COLOR_T color, @@ -755,29 +919,29 @@ color_content(NCURSES_COLOR_T color, #endif NCURSES_EXPORT(int) -NCURSES_SP_NAME(pair_content) (NCURSES_SP_DCLx - NCURSES_PAIRS_T pair, - NCURSES_COLOR_T *f, - NCURSES_COLOR_T *b) +_nc_pair_content(SCREEN *sp, int pair, int *f, int *b) { int result; T((T_CALLED("pair_content(%p,%d,%p,%p)"), - (void *) SP_PARM, + (void *) sp, (int) pair, (void *) f, (void *) b)); - if (!ValidPair(pair)) { + if (!ValidPair(sp, pair)) { result = ERR; } else { - NCURSES_COLOR_T fg = (NCURSES_COLOR_T) FORE_OF(SP_PARM->_color_pairs[pair]); - NCURSES_COLOR_T bg = (NCURSES_COLOR_T) BACK_OF(SP_PARM->_color_pairs[pair]); + int fg; + int bg; + ReservePairs(sp, pair); + fg = FORE_OF(sp->_color_pairs[pair]); + bg = BACK_OF(sp->_color_pairs[pair]); #if NCURSES_EXT_FUNCS - if (fg == COLOR_DEFAULT) + if (isDefaultColor(fg)) fg = -1; - if (bg == COLOR_DEFAULT) + if (isDefaultColor(bg)) bg = -1; #endif @@ -787,7 +951,7 @@ NCURSES_SP_NAME(pair_content) (NCURSES_SP_DCLx *b = bg; TR(TRACE_ATTRS, ("...pair_content(%p,%d,%d,%d)", - (void *) SP_PARM, + (void *) sp, (int) pair, (int) fg, (int) bg)); result = OK; @@ -795,6 +959,21 @@ NCURSES_SP_NAME(pair_content) (NCURSES_SP_DCLx returnCode(result); } +NCURSES_EXPORT(int) +NCURSES_SP_NAME(pair_content) (NCURSES_SP_DCLx + NCURSES_PAIRS_T pair, + NCURSES_COLOR_T *f, + NCURSES_COLOR_T *b) +{ + int my_f, my_b; + int rc = _nc_pair_content(SP_PARM, pair, &my_f, &my_b); + if (rc == OK) { + *f = limit_COLOR(my_f); + *b = limit_COLOR(my_b); + } + return rc; +} + #if NCURSES_SP_FUNCS NCURSES_EXPORT(int) pair_content(NCURSES_COLOR_T pair, NCURSES_COLOR_T *f, NCURSES_COLOR_T *b) @@ -811,14 +990,14 @@ NCURSES_SP_NAME(_nc_do_color) (NCURSES_SP_DCLx NCURSES_SP_OUTC outc) { #ifdef USE_TERM_DRIVER - CallDriver_4(SP_PARM, docolor, old_pair, pair, reverse, outc); + CallDriver_4(SP_PARM, td_docolor, old_pair, pair, reverse, outc); #else - NCURSES_COLOR_T fg = COLOR_DEFAULT; - NCURSES_COLOR_T bg = COLOR_DEFAULT; - NCURSES_COLOR_T old_fg = -1; - NCURSES_COLOR_T old_bg = -1; + int fg = COLOR_DEFAULT; + int bg = COLOR_DEFAULT; + int old_fg = -1; + int old_bg = -1; - if (!ValidPair(pair)) { + if (!ValidPair(SP_PARM, pair)) { return; } else if (pair != 0) { if (set_color_pair) { @@ -828,14 +1007,14 @@ NCURSES_SP_NAME(_nc_do_color) (NCURSES_SP_DCLx 1, outc); return; } else if (SP_PARM != 0) { - if (pair_content((NCURSES_COLOR_T) pair, &fg, &bg) == ERR) + if (_nc_pair_content(SP_PARM, pair, &fg, &bg) == ERR) return; } } if (old_pair >= 0 && SP_PARM != 0 - && pair_content((NCURSES_COLOR_T) 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 @@ -858,19 +1037,19 @@ NCURSES_SP_NAME(_nc_do_color) (NCURSES_SP_DCLx } } else { reset_color_pair(NCURSES_SP_ARG); - if (old_pair < 0) + if (old_pair < 0 && pair <= 0) return; } #if NCURSES_EXT_FUNCS if (isDefaultColor(fg)) - fg = (NCURSES_COLOR_T) default_fg(NCURSES_SP_ARG); + fg = default_fg(NCURSES_SP_ARG); if (isDefaultColor(bg)) - bg = (NCURSES_COLOR_T) default_bg(NCURSES_SP_ARG); + bg = default_bg(NCURSES_SP_ARG); #endif if (reverse) { - NCURSES_COLOR_T xx = fg; + int xx = fg; fg = bg; bg = xx; } @@ -899,3 +1078,87 @@ _nc_do_color(int old_pair, int pair, int reverse, NCURSES_OUTC outc) _nc_outc_wrapper); } #endif + +#if NCURSES_EXT_COLORS +NCURSES_EXPORT(int) +NCURSES_SP_NAME(init_extended_pair) (NCURSES_SP_DCLx int pair, int f, int b) +{ + return _nc_init_pair(SP_PARM, pair, f, b); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(init_extended_color) (NCURSES_SP_DCLx + int color, + int r, int g, int b) +{ + return _nc_init_color(SP_PARM, color, r, g, b); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(extended_color_content) (NCURSES_SP_DCLx + int color, + int *r, int *g, int *b) +{ + return _nc_color_content(SP_PARM, color, r, g, b); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(extended_pair_content) (NCURSES_SP_DCLx + int pair, + int *f, int *b) +{ + return _nc_pair_content(SP_PARM, pair, f, b); +} + +NCURSES_EXPORT(void) +NCURSES_SP_NAME(reset_color_pairs) (NCURSES_SP_DCL0) +{ + if (SP_PARM != 0) { + if (SP_PARM->_color_pairs) { + _nc_free_ordered_pairs(SP_PARM); + free(SP_PARM->_color_pairs); + SP_PARM->_color_pairs = 0; + SP_PARM->_pair_alloc = 0; + ReservePairs(SP_PARM, 16); + clearok(CurScreen(SP_PARM), TRUE); + touchwin(StdScreen(SP_PARM)); + } + } +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +init_extended_pair(int pair, int f, int b) +{ + return NCURSES_SP_NAME(init_extended_pair) (CURRENT_SCREEN, pair, f, b); +} + +NCURSES_EXPORT(int) +init_extended_color(int color, int r, int g, int b) +{ + return NCURSES_SP_NAME(init_extended_color) (CURRENT_SCREEN, + color, + r, g, b); +} + +NCURSES_EXPORT(int) +extended_color_content(int color, int *r, int *g, int *b) +{ + return NCURSES_SP_NAME(extended_color_content) (CURRENT_SCREEN, + color, + r, g, b); +} + +NCURSES_EXPORT(int) +extended_pair_content(int pair, int *f, int *b) +{ + return NCURSES_SP_NAME(extended_pair_content) (CURRENT_SCREEN, pair, f, b); +} + +NCURSES_EXPORT(void) +reset_color_pairs(void) +{ + NCURSES_SP_NAME(reset_color_pairs) (CURRENT_SCREEN); +} +#endif /* NCURSES_SP_FUNCS */ +#endif /* NCURSES_EXT_COLORS */ diff --git a/ncurses/base/lib_colorset.c b/ncurses/base/lib_colorset.c index e9354860ad0d0..f3aef7e391108 100644 --- a/ncurses/base/lib_colorset.c +++ b/ncurses/base/lib_colorset.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2014 Free Software Foundation, Inc. * + * Copyright (c) 1998-2004,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 * @@ -41,22 +41,23 @@ #include <curses.priv.h> #include <ctype.h> -MODULE_ID("$Id: lib_colorset.c,v 1.14 2014/02/01 22:10:42 tom Exp $") +MODULE_ID("$Id: lib_colorset.c,v 1.15 2017/03/16 23:45:30 tom Exp $") NCURSES_EXPORT(int) -wcolor_set(WINDOW *win, NCURSES_PAIRS_T color_pair_number, void *opts) +wcolor_set(WINDOW *win, NCURSES_PAIRS_T pair_arg, void *opts) { int code = ERR; + int color_pair = pair_arg; - T((T_CALLED("wcolor_set(%p,%d)"), (void *) win, (int) color_pair_number)); + T((T_CALLED("wcolor_set(%p,%d)"), (void *) win, color_pair)); + set_extended_pair(opts, color_pair); if (win - && !opts && (SP != 0) - && (color_pair_number >= 0) - && (color_pair_number < SP->_pair_limit)) { + && (color_pair >= 0) + && (color_pair < SP->_pair_limit)) { TR(TRACE_ATTRS, ("... current %ld", (long) GET_WINDOW_PAIR(win))); - SET_WINDOW_PAIR(win, color_pair_number); - if_EXT_COLORS(win->_color = color_pair_number); + SET_WINDOW_PAIR(win, color_pair); + if_EXT_COLORS(win->_color = color_pair); code = OK; } returnCode(code); diff --git a/ncurses/base/lib_dft_fgbg.c b/ncurses/base/lib_dft_fgbg.c index 00cbafb397304..d5fd1a03a8d63 100644 --- a/ncurses/base/lib_dft_fgbg.c +++ b/ncurses/base/lib_dft_fgbg.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2011 Free Software Foundation, Inc. * + * Copyright (c) 1998-2014,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 * @@ -37,7 +37,7 @@ #define CUR SP_TERMTYPE #endif -MODULE_ID("$Id: lib_dft_fgbg.c,v 1.26 2011/04/23 18:28:18 tom Exp $") +MODULE_ID("$Id: lib_dft_fgbg.c,v 1.29 2017/03/25 21:00:49 tom Exp $") /* * Modify the behavior of color-pair 0 so that the library doesn't assume that @@ -68,26 +68,27 @@ NCURSES_SP_NAME(assume_default_colors) (NCURSES_SP_DCLx int fg, int bg) int code = ERR; T((T_CALLED("assume_default_colors(%p,%d,%d)"), (void *) SP_PARM, fg, bg)); + if (SP_PARM != 0) { #ifdef USE_TERM_DRIVER - if (sp != 0) - code = CallDriver_2(sp, defaultcolors, fg, bg); + code = CallDriver_2(SP_PARM, td_defaultcolors, fg, bg); #else - if ((orig_pair || orig_colors) && !initialize_pair) { + if ((orig_pair || orig_colors) && !initialize_pair) { - SP_PARM->_default_color = isDefaultColor(fg) || isDefaultColor(bg); - SP_PARM->_has_sgr_39_49 = (tigetflag("AX") == TRUE); - SP_PARM->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : (fg & C_MASK); - SP_PARM->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : (bg & C_MASK); - if (SP_PARM->_color_pairs != 0) { - bool save = SP_PARM->_default_color; - SP_PARM->_assumed_color = TRUE; - SP_PARM->_default_color = TRUE; - init_pair(0, (short) fg, (short) bg); - SP_PARM->_default_color = save; + SP_PARM->_default_color = isDefaultColor(fg) || isDefaultColor(bg); + SP_PARM->_has_sgr_39_49 = (tigetflag("AX") == TRUE); + SP_PARM->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : fg; + SP_PARM->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : bg; + if (SP_PARM->_color_pairs != 0) { + bool save = SP_PARM->_default_color; + SP_PARM->_assumed_color = TRUE; + SP_PARM->_default_color = TRUE; + init_pair(0, (short) fg, (short) bg); + SP_PARM->_default_color = save; + } + code = OK; } - code = OK; - } #endif + } returnCode(code); } diff --git a/ncurses/base/lib_driver.c b/ncurses/base/lib_driver.c index 6301a5887d642..6211b70bec190 100644 --- a/ncurses/base/lib_driver.c +++ b/ncurses/base/lib_driver.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 2008-2010,2012 Free Software Foundation, Inc. * + * Copyright (c) 2008-2014,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 * @@ -33,7 +33,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_driver.c,v 1.4 2012/09/22 19:32:46 tom Exp $") +MODULE_ID("$Id: lib_driver.c,v 1.7 2018/06/24 00:06:37 tom Exp $") typedef struct DriverEntry { const char *name; @@ -42,8 +42,8 @@ typedef struct DriverEntry { static DRIVER_ENTRY DriverTable[] = { -#ifdef __MINGW32__ - {"win32con", &_nc_WIN_DRIVER}, +#ifdef _WIN32 + {"win32console", &_nc_WIN_DRIVER}, #endif {"tinfo", &_nc_TINFO_DRIVER} /* must be last */ }; @@ -63,24 +63,12 @@ _nc_get_driver(TERMINAL_CONTROL_BLOCK * TCB, const char *name, int *errret) for (i = 0; i < SIZEOF(DriverTable); i++) { res = DriverTable[i].driver; - /* - * Use "#" (a character which cannot begin a terminal's name) to - * select specific driver from the table. - * - * In principle, we could have more than one non-terminfo driver, - * e.g., "win32gui". - */ - if (name != 0 && *name == '#') { - size_t n = strlen(name + 1); - if (n != 0 - && strncmp(name + 1, DriverTable[i].name, n)) { - continue; + if (strcmp(DriverTable[i].name, res->td_name(TCB)) == 0) { + if (res->td_CanHandle(TCB, name, errret)) { + use = res; + break; } } - if (res->CanHandle(TCB, name, errret)) { - use = res; - break; - } } if (use != 0) { TCB->drv = use; @@ -93,7 +81,7 @@ NCURSES_EXPORT(int) NCURSES_SP_NAME(has_key) (SCREEN *sp, int keycode) { T((T_CALLED("has_key(%p, %d)"), (void *) sp, keycode)); - returnCode(IsValidTIScreen(sp) ? CallDriver_1(sp, kyExist, keycode) : FALSE); + returnCode(IsValidTIScreen(sp) ? CallDriver_1(sp, td_kyExist, keycode) : FALSE); } NCURSES_EXPORT(int) @@ -108,7 +96,7 @@ NCURSES_SP_NAME(_nc_mcprint) (SCREEN *sp, char *data, int len) int code = ERR; if (0 != TerminalOf(sp)) - code = CallDriver_2(sp, print, data, len); + code = CallDriver_2(sp, td_print, data, len); return (code); } @@ -126,7 +114,7 @@ NCURSES_SP_NAME(doupdate) (SCREEN *sp) T((T_CALLED("doupdate(%p)"), (void *) sp)); if (IsValidScreen(sp)) - code = CallDriver(sp, update); + code = CallDriver(sp, td_update); returnCode(code); } @@ -144,7 +132,7 @@ NCURSES_SP_NAME(mvcur) (SCREEN *sp, int yold, int xold, int ynew, int xnew) TR(TRACE_CALLS | TRACE_MOVE, (T_CALLED("mvcur(%p,%d,%d,%d,%d)"), (void *) sp, yold, xold, ynew, xnew)); if (HasTerminal(sp)) { - code = CallDriver_4(sp, hwcur, yold, xold, ynew, xnew); + code = CallDriver_4(sp, td_hwcur, yold, xold, ynew, xnew); } returnCode(code); } diff --git a/ncurses/base/lib_endwin.c b/ncurses/base/lib_endwin.c index 4596d07496332..c3ba37a652327 100644 --- a/ncurses/base/lib_endwin.c +++ b/ncurses/base/lib_endwin.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc. * + * Copyright (c) 1998-2014,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 * @@ -42,7 +42,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_endwin.c,v 1.22 2009/10/24 22:02:14 tom Exp $") +MODULE_ID("$Id: lib_endwin.c,v 1.24 2017/07/22 23:29:40 tom Exp $") NCURSES_EXPORT(int) NCURSES_SP_NAME(endwin) (NCURSES_SP_DCL0) @@ -55,11 +55,11 @@ NCURSES_SP_NAME(endwin) (NCURSES_SP_DCL0) #ifdef USE_TERM_DRIVER TERMINAL_CONTROL_BLOCK *TCB = TCBOf(SP_PARM); - SP_PARM->_endwin = TRUE; - if (TCB && TCB->drv && TCB->drv->scexit) - TCB->drv->scexit(SP_PARM); + SP_PARM->_endwin = ewSuspend; + if (TCB && TCB->drv && TCB->drv->td_scexit) + TCB->drv->td_scexit(SP_PARM); #else - SP_PARM->_endwin = TRUE; + SP_PARM->_endwin = ewSuspend; SP_PARM->_mouse_wrap(SP_PARM); _nc_screen_wrap(); _nc_mvcur_wrap(); /* wrap up cursor addressing */ diff --git a/ncurses/base/lib_erase.c b/ncurses/base/lib_erase.c index bbf10ef81b929..6bac1ba101788 100644 --- a/ncurses/base/lib_erase.c +++ b/ncurses/base/lib_erase.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2005,2009 Free Software Foundation, Inc. * + * Copyright (c) 1998-2009,2016 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,21 +41,25 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_erase.c,v 1.17 2009/10/24 22:32:29 tom Exp $") +MODULE_ID("$Id: lib_erase.c,v 1.18 2016/05/28 23:11:26 tom Exp $") NCURSES_EXPORT(int) werase(WINDOW *win) { int code = ERR; - int y; NCURSES_CH_T blank; - NCURSES_CH_T *sp, *end, *start; + NCURSES_CH_T *start; T((T_CALLED("werase(%p)"), (void *) win)); if (win) { + NCURSES_CH_T *sp; + int y; + blank = win->_nc_bkgd; for (y = 0; y <= win->_maxy; y++) { + NCURSES_CH_T *end; + start = win->_line[y].text; end = &start[win->_maxx]; diff --git a/ncurses/base/lib_flash.c b/ncurses/base/lib_flash.c index 3520177ea33fb..7f25038cea516 100644 --- a/ncurses/base/lib_flash.c +++ b/ncurses/base/lib_flash.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2011,2013 Free Software Foundation, Inc. * + * Copyright (c) 1998-2013,2014 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 * @@ -46,7 +46,7 @@ #define CUR SP_TERMTYPE #endif -MODULE_ID("$Id: lib_flash.c,v 1.13 2013/01/12 17:26:07 tom Exp $") +MODULE_ID("$Id: lib_flash.c,v 1.14 2014/03/08 20:32:59 tom Exp $") /* * flash() @@ -64,7 +64,7 @@ NCURSES_SP_NAME(flash) (NCURSES_SP_DCL0) T((T_CALLED("flash(%p)"), (void *) SP_PARM)); #ifdef USE_TERM_DRIVER if (SP_PARM != 0) - res = CallDriver_1(SP_PARM, doBeepOrFlash, FALSE); + res = CallDriver_1(SP_PARM, td_doBeepOrFlash, FALSE); #else if (HasTerminal(SP_PARM)) { /* FIXME: should make sure that we are not in altchar mode */ diff --git a/ncurses/base/lib_freeall.c b/ncurses/base/lib_freeall.c index 031374924f002..4e29ec0f632f5 100644 --- a/ncurses/base/lib_freeall.c +++ b/ncurses/base/lib_freeall.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc. * + * Copyright (c) 1998-2018,2019 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 * @@ -39,7 +39,7 @@ extern int malloc_errfd; /* FIXME */ #endif -MODULE_ID("$Id: lib_freeall.c,v 1.62 2012/11/17 23:53:03 tom Exp $") +MODULE_ID("$Id: lib_freeall.c,v 1.71 2019/12/15 00:30:49 tom Exp $") /* * Free all ncurses data. This is used for testing only (there's no practical @@ -48,11 +48,11 @@ MODULE_ID("$Id: lib_freeall.c,v 1.62 2012/11/17 23:53:03 tom Exp $") NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_freeall) (NCURSES_SP_DCL0) { - WINDOWLIST *p, *q; static va_list empty_va; T((T_CALLED("_nc_freeall()"))); #if NO_LEAKS + _nc_globals.leak_checking = TRUE; if (SP_PARM != 0) { if (SP_PARM->_oldnum_list != 0) { FreeAndNull(SP_PARM->_oldnum_list); @@ -60,12 +60,16 @@ NCURSES_SP_NAME(_nc_freeall) (NCURSES_SP_DCL0) if (SP_PARM->_panelHook.destroy != 0) { SP_PARM->_panelHook.destroy(SP_PARM->_panelHook.stdscr_pseudo_panel); } +#if NCURSES_EXT_COLORS + _nc_new_pair_leaks(SP_PARM); +#endif } #endif if (SP_PARM != 0) { _nc_lock_global(curses); while (WindowList(SP_PARM) != 0) { + WINDOWLIST *p, *q; bool deleted = FALSE; /* Delete only windows that're not a parent */ @@ -73,8 +77,19 @@ NCURSES_SP_NAME(_nc_freeall) (NCURSES_SP_DCL0) WINDOW *p_win = &(p->win); bool found = FALSE; +#ifndef USE_SP_WINDOWLIST + if (p->screen != SP_PARM) + continue; +#endif + for (each_window(SP_PARM, q)) { WINDOW *q_win = &(q->win); + +#ifndef USE_SP_WINDOWLIST + if (q->screen != SP_PARM) + continue; +#endif + if ((p != q) && (q_win->_flags & _SUBWIN) && (p_win == q_win->_parent)) { @@ -131,22 +146,20 @@ _nc_freeall(void) NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_free_and_exit) (NCURSES_SP_DCLx int code) { - char *last_buffer = (SP_PARM != 0) ? SP_PARM->out_buffer : 0; - + T((T_CALLED("_nc_free_and_exit(%d)"), code)); NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); NCURSES_SP_NAME(_nc_freeall) (NCURSES_SP_ARG); #ifdef TRACE - trace(0); /* close trace file, freeing its setbuf */ + curses_trace(0); /* close trace file, freeing its setbuf */ { static va_list fake; free(_nc_varargs("?", fake)); } #endif - FreeIfNeeded(last_buffer); exit(code); } -#else +#else /* !HAVE_NC_FREEALL */ NCURSES_EXPORT(void) _nc_freeall(void) { @@ -162,7 +175,7 @@ NCURSES_SP_NAME(_nc_free_and_exit) (NCURSES_SP_DCLx int code) } exit(code); } -#endif +#endif /* HAVE_NC_FREEALL */ #if NCURSES_SP_FUNCS NCURSES_EXPORT(void) @@ -171,3 +184,16 @@ _nc_free_and_exit(int code) NCURSES_SP_NAME(_nc_free_and_exit) (CURRENT_SCREEN, code); } #endif + +NCURSES_EXPORT(void) +exit_curses(int code) +{ +#if NO_LEAKS +#if NCURSES_SP_FUNCS + NCURSES_SP_NAME(_nc_free_and_exit) (CURRENT_SCREEN, code); +#else + _nc_free_and_exit(code); /* deprecated... */ +#endif +#endif + exit(code); +} diff --git a/ncurses/base/lib_getch.c b/ncurses/base/lib_getch.c index 0a04ef5a6e1bf..66c9f87e57d61 100644 --- a/ncurses/base/lib_getch.c +++ b/ncurses/base/lib_getch.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * + * Copyright (c) 1998-2018,2019 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 * @@ -42,7 +42,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_getch.c,v 1.126 2013/02/16 18:30:37 tom Exp $") +MODULE_ID("$Id: lib_getch.c,v 1.138 2019/11/03 00:11:16 tom Exp $") #include <fifo_defs.h> @@ -69,16 +69,20 @@ NCURSES_EXPORT(int) NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_DCLx int value) { int code = OK; -#if USE_REENTRANT - if (SP_PARM) { - SET_ESCDELAY(value); - } else { + if (value < 0) { code = ERR; - } + } else { +#if USE_REENTRANT + if (SP_PARM) { + SET_ESCDELAY(value); + } else { + code = ERR; + } #else - (void) SP_PARM; - ESCDELAY = value; + (void) SP_PARM; + ESCDELAY = value; #endif + } return code; } @@ -87,12 +91,16 @@ NCURSES_EXPORT(int) set_escdelay(int value) { int code; + if (value < 0) { + code = ERR; + } else { #if USE_REENTRANT - code = NCURSES_SP_NAME(set_escdelay) (CURRENT_SCREEN, value); + code = NCURSES_SP_NAME(set_escdelay) (CURRENT_SCREEN, value); #else - ESCDELAY = value; - code = OK; + ESCDELAY = value; + code = OK; #endif + } return code; } #endif @@ -124,6 +132,17 @@ _nc_use_meta(WINDOW *win) return (sp ? sp->_use_meta : 0); } +#ifdef USE_TERM_DRIVER +# ifdef _WIN32 +static HANDLE +_nc_get_handle(int fd) +{ + intptr_t value = _get_osfhandle(fd); + return (HANDLE) value; +} +# endif +#endif + /* * Check for mouse activity, returning nonzero if we find any. */ @@ -133,7 +152,16 @@ check_mouse_activity(SCREEN *sp, int delay EVENTLIST_2nd(_nc_eventlist * evl)) int rc; #ifdef USE_TERM_DRIVER - rc = TCBOf(sp)->drv->testmouse(TCBOf(sp), delay EVENTLIST_2nd(evl)); + TERMINAL_CONTROL_BLOCK *TCB = TCBOf(sp); + rc = TCBOf(sp)->drv->td_testmouse(TCBOf(sp), delay EVENTLIST_2nd(evl)); +# ifdef _WIN32 + /* if we emulate terminfo on console, we have to use the console routine */ + if (IsTermInfoOnConsole(sp)) { + HANDLE fd = _nc_get_handle(sp->_ifd); + rc = _nc_mingw_testmouse(sp, fd, delay EVENTLIST_2nd(evl)); + } else +# endif + rc = TCB->drv->td_testmouse(TCB, delay EVENTLIST_2nd(evl)); #else #if USE_SYSMOUSE if ((sp->_mouse_type == M_SYSMOUSE) @@ -204,11 +232,6 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) if (tail < 0) return ERR; -#ifdef HIDE_EINTR - again: - errno = 0; -#endif - #ifdef NCURSES_WGETCH_EVENTS if (evl #if USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE @@ -259,7 +282,7 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) } else #endif #if USE_KLIBC_KBD - if (isatty(sp->_ifd) && sp->_cbreak) { + if (NC_ISATTY(sp->_ifd) && sp->_cbreak) { ch = _read_kbd(0, 1, !sp->_raw); n = (ch == -1) ? -1 : 1; sp->_extended_key = (ch == 0); @@ -268,7 +291,14 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) { /* Can block... */ #ifdef USE_TERM_DRIVER int buf; - n = CallDriver_1(sp, read, &buf); +#ifdef _WIN32 + if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && sp->_cbreak) + n = _nc_mingw_console_read(sp, + _nc_get_handle(sp->_ifd), + &buf); + else +#endif + n = CallDriver_1(sp, td_read, &buf); ch = buf; #else unsigned char c2 = 0; @@ -286,24 +316,6 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) #endif } -#ifdef HIDE_EINTR - /* - * Under System V curses with non-restarting signals, getch() returns - * with value ERR when a handled signal keeps it from completing. - * If signals restart system calls, OTOH, the signal is invisible - * except to its handler. - * - * We don't want this difference to show. This piece of code - * tries to make it look like we always have restarting signals. - */ - if (n <= 0 && errno == EINTR -# if USE_PTHREADS_EINTR - && (_nc_globals.have_sigwinch == 0) -# endif - ) - goto again; -#endif - if ((n == -1) || (n == 0)) { TR(TRACE_IEVENT, ("read(%d,&ch,1)=%d, errno=%d", sp->_ifd, n, errno)); ch = ERR; @@ -333,7 +345,7 @@ fifo_clear(SCREEN *sp) tail = peek = 0; } -static int kgetch(SCREEN *EVENTLIST_2nd(_nc_eventlist * evl)); +static int kgetch(SCREEN *, bool EVENTLIST_2nd(_nc_eventlist *)); static void recur_wrefresh(WINDOW *win) @@ -399,7 +411,7 @@ _nc_wgetch(WINDOW *win, int ch; int rc = 0; #ifdef NCURSES_WGETCH_EVENTS - long event_delay = -1; + int event_delay = -1; #endif T((T_CALLED("_nc_wgetch(%p)"), (void *) win)); @@ -510,7 +522,7 @@ _nc_wgetch(WINDOW *win, int runcount = 0; do { - ch = kgetch(sp EVENTLIST_2nd(evl)); + ch = kgetch(sp, win->_notimeout EVENTLIST_2nd(evl)); if (ch == KEY_MOUSE) { ++runcount; if (sp->_mouse_inline(sp)) @@ -622,7 +634,7 @@ wgetch_events(WINDOW *win, _nc_eventlist * evl) int code; int value; - T((T_CALLED("wgetch_events(%p,%p)"), win, evl)); + T((T_CALLED("wgetch_events(%p,%p)"), (void *) win, (void *) evl)); code = _nc_wgetch(win, &value, _nc_use_meta(win) @@ -665,11 +677,11 @@ wgetch(WINDOW *win) */ static int -kgetch(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) +kgetch(SCREEN *sp, bool forever EVENTLIST_2nd(_nc_eventlist * evl)) { TRIES *ptr; int ch = 0; - int timeleft = GetEscdelay(sp); + int timeleft = forever ? 9999999 : GetEscdelay(sp); TR(TRACE_IEVENT, ("kgetch() called")); diff --git a/ncurses/base/lib_getstr.c b/ncurses/base/lib_getstr.c index 0e446349ca173..fc18e40fcaa4d 100644 --- a/ncurses/base/lib_getstr.c +++ b/ncurses/base/lib_getstr.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2011 Free Software Foundation, Inc. * + * Copyright (c) 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 * @@ -40,7 +40,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_getstr.c,v 1.30 2011/10/22 16:31:35 tom Exp $") +MODULE_ID("$Id: lib_getstr.c,v 1.33 2018/09/01 20:18:09 tom Exp $") /* * This wipes out the last character, no matter whether it was a tab, control @@ -85,9 +85,11 @@ wgetnstr_events(WINDOW *win, T((T_CALLED("wgetnstr(%p,%p,%d)"), (void *) win, (void *) str, maxlen)); - if (!win) + if (!win || !str) returnCode(ERR); + maxlen = _nc_getstr_limit(maxlen); + NCURSES_SP_NAME(_nc_get_tty_mode) (NCURSES_SP_ARGx &buf); oldnl = sp->_nl; @@ -142,7 +144,7 @@ wgetnstr_events(WINDOW *win, str = WipeOut(win, y, x, oldstr, str, oldecho); } } else if (ch >= KEY_MIN - || (maxlen >= 0 && str - oldstr >= maxlen)) { + || (str - oldstr >= maxlen)) { NCURSES_SP_NAME(beep) (NCURSES_SP_ARG); } else { *str++ = (char) ch; diff --git a/ncurses/base/lib_hline.c b/ncurses/base/lib_hline.c index 1f0380830ddc7..0fac51de74fb8 100644 --- a/ncurses/base/lib_hline.c +++ b/ncurses/base/lib_hline.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. * + * Copyright (c) 1998-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 * @@ -29,6 +29,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * + * and: Sven Verdoolaege 2001 * ****************************************************************************/ /* @@ -40,23 +42,21 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_hline.c,v 1.13 2010/12/19 01:48:39 tom Exp $") +MODULE_ID("$Id: lib_hline.c,v 1.15 2017/10/28 19:57:42 tom Exp $") NCURSES_EXPORT(int) whline(WINDOW *win, chtype ch, int n) { int code = ERR; - int start; - int end; T((T_CALLED("whline(%p,%s,%d)"), (void *) win, _tracechtype(ch), n)); if (win) { struct ldat *line = &(win->_line[win->_cury]); NCURSES_CH_T wch; + int start = win->_curx; + int end = start + n - 1; - start = win->_curx; - end = start + n - 1; if (end > win->_maxx) end = win->_maxx; @@ -68,6 +68,14 @@ whline(WINDOW *win, chtype ch, int n) SetChar2(wch, ch); wch = _nc_render(win, wch); +#if USE_WIDEC_SUPPORT + if (start > 0 && isWidecExt(line->text[start])) { + SetChar2(line->text[start - 1], ' '); + } + if (end < win->_maxx && isWidecExt(line->text[end + 1])) { + SetChar2(line->text[end + 1], ' '); + } +#endif while (end >= start) { line->text[end] = wch; end--; diff --git a/ncurses/base/lib_inchstr.c b/ncurses/base/lib_inchstr.c index aebb6d625d5c8..bf30e3ce26637 100644 --- a/ncurses/base/lib_inchstr.c +++ b/ncurses/base/lib_inchstr.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. * + * Copyright (c) 1998-2010,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 * @@ -41,7 +41,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_inchstr.c,v 1.12 2010/12/20 01:37:41 tom Exp $") +MODULE_ID("$Id: lib_inchstr.c,v 1.16 2017/04/30 00:10:25 tom Exp $") NCURSES_EXPORT(int) winchnstr(WINDOW *win, chtype *str, int n) @@ -50,16 +50,19 @@ winchnstr(WINDOW *win, chtype *str, int n) T((T_CALLED("winchnstr(%p,%p,%d)"), (void *) win, (void *) str, n)); - if (!str) - returnCode(0); + if (!win || !str) { + i = ERR; + } else { + int row = win->_cury; + int col = win->_curx; + NCURSES_CH_T *text = win->_line[row].text; - if (win) { - for (; (n < 0 || (i < n)) && (win->_curx + i <= win->_maxx); i++) - str[i] = - (chtype) CharOf(win->_line[win->_cury].text[win->_curx + i]) | - AttrOf(win->_line[win->_cury].text[win->_curx + i]); + for (; (n < 0 || (i < n)) && (col + i <= win->_maxx); i++) { + str[i] = (((chtype) CharOf(text[col + i]) & A_CHARTEXT) | + AttrOf(text[col + i])); + } + str[i] = (chtype) 0; } - str[i] = (chtype) 0; returnCode(i); } diff --git a/ncurses/base/lib_initscr.c b/ncurses/base/lib_initscr.c index 334682fab71d1..60f5e4d0d3932 100644 --- a/ncurses/base/lib_initscr.c +++ b/ncurses/base/lib_initscr.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc. * + * Copyright (c) 1998-2017,2019 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 * @@ -29,7 +29,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * - * and: Thomas E. Dickey 1996-2003 * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -45,15 +45,13 @@ #include <sys/termio.h> /* needed for ISC */ #endif -MODULE_ID("$Id: lib_initscr.c,v 1.39 2009/02/14 20:55:49 tom Exp $") +MODULE_ID("$Id: lib_initscr.c,v 1.44 2019/06/22 00:02:01 tom Exp $") NCURSES_EXPORT(WINDOW *) initscr(void) { WINDOW *result; - NCURSES_CONST char *name; - START_TRACE(); T((T_CALLED("initscr()"))); @@ -62,11 +60,19 @@ initscr(void) /* Portable applications must not call initscr() more than once */ if (!_nc_globals.init_screen) { + const char *env; + char *name; + _nc_globals.init_screen = TRUE; - if ((name = getenv("TERM")) == 0 - || *name == '\0') - name = "unknown"; + if ((env = getenv("TERM")) == 0 + || *env == '\0') { + env = "unknown"; + } + if ((name = strdup(env)) == NULL) { + fprintf(stderr, "Error opening allocating $TERM.\n"); + ExitProgram(EXIT_FAILURE); + } #ifdef __CYGWIN__ /* * 2002/9/21 @@ -75,9 +81,9 @@ initscr(void) * core when attempting to write to stdout. Opening /dev/tty * explicitly seems to fix the problem. */ - if (isatty(fileno(stdout))) { + if (NC_ISATTY(fileno(stdout))) { FILE *fp = fopen("/dev/tty", "w"); - if (fp != 0 && isatty(fileno(fp))) { + if (fp != 0 && NC_ISATTY(fileno(fp))) { fclose(stdout); dup2(fileno(fp), STDOUT_FILENO); stdout = fdopen(STDOUT_FILENO, "w"); @@ -86,7 +92,7 @@ initscr(void) #endif if (newterm(name, stdout, stdin) == 0) { fprintf(stderr, "Error opening terminal: %s.\n", name); - exit(EXIT_FAILURE); + ExitProgram(EXIT_FAILURE); } /* def_shell_mode - done in newterm/_nc_setupscreen */ @@ -95,6 +101,7 @@ initscr(void) #else def_prog_mode(); #endif + free(name); } result = stdscr; _nc_unlock_global(curses); diff --git a/ncurses/base/lib_insch.c b/ncurses/base/lib_insch.c index 32eaed7394430..1ec70e3af83d3 100644 --- a/ncurses/base/lib_insch.c +++ b/ncurses/base/lib_insch.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * + * Copyright (c) 1998-2013,2016 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 * @@ -43,7 +43,7 @@ #include <curses.priv.h> #include <ctype.h> -MODULE_ID("$Id: lib_insch.c,v 1.35 2013/05/18 21:58:56 tom Exp $") +MODULE_ID("$Id: lib_insch.c,v 1.36 2016/05/28 23:11:26 tom Exp $") /* * Insert the given character, updating the current location to simplify @@ -56,7 +56,6 @@ _nc_insert_ch(SCREEN *sp, WINDOW *win, chtype ch) int ch8 = (int) ChCharOf(ch); NCURSES_CH_T wch; int count; - NCURSES_CONST char *s; int tabsize = ( #if USE_REENTRANT sp->_TABSIZE @@ -102,6 +101,7 @@ _nc_insert_ch(SCREEN *sp, WINDOW *win, chtype ch) win->_curx++; } } else if (iscntrl(ch8)) { + NCURSES_CONST char *s; s = NCURSES_SP_NAME(unctrl) (NCURSES_SP_ARGx (chtype) ch8); while (*s != '\0') { code = _nc_insert_ch(sp, win, ChAttrOf(ch) | UChar(*s)); @@ -121,6 +121,7 @@ _nc_insert_ch(SCREEN *sp, WINDOW *win, chtype ch) if (count > 0) { code = _nc_insert_wch(win, &wch); } else if (count == -1) { + NCURSES_CONST char *s; /* handle EILSEQ */ s = NCURSES_SP_NAME(unctrl) (NCURSES_SP_ARGx (chtype) ch8); if (strlen(s) > 1) { @@ -145,15 +146,13 @@ _nc_insert_ch(SCREEN *sp, WINDOW *win, chtype ch) NCURSES_EXPORT(int) winsch(WINDOW *win, chtype c) { - NCURSES_SIZE_T oy; - NCURSES_SIZE_T ox; int code = ERR; T((T_CALLED("winsch(%p, %s)"), (void *) win, _tracechtype(c))); if (win != 0) { - oy = win->_cury; - ox = win->_curx; + NCURSES_SIZE_T oy = win->_cury; + NCURSES_SIZE_T ox = win->_curx; code = _nc_insert_ch(_nc_screen_of(win), win, c); diff --git a/ncurses/base/lib_insnstr.c b/ncurses/base/lib_insnstr.c index ce03e64be0020..8ee26a8091c1e 100644 --- a/ncurses/base/lib_insnstr.c +++ b/ncurses/base/lib_insnstr.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 2004,2009 Free Software Foundation, Inc. * + * Copyright (c) 2004-2016,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 * @@ -40,31 +40,55 @@ #include <curses.priv.h> #include <ctype.h> -MODULE_ID("$Id: lib_insnstr.c,v 1.3 2009/10/24 22:04:35 tom Exp $") +MODULE_ID("$Id: lib_insnstr.c,v 1.6 2018/03/10 20:13:59 Gyorgy.Jeney Exp $") NCURSES_EXPORT(int) winsnstr(WINDOW *win, const char *s, int n) { int code = ERR; - NCURSES_SIZE_T oy; - NCURSES_SIZE_T ox; const unsigned char *str = (const unsigned char *) s; - const unsigned char *cp; T((T_CALLED("winsnstr(%p,%s,%d)"), (void *) win, _nc_visbufn(s, n), n)); if (win != 0 && str != 0) { SCREEN *sp = _nc_screen_of(win); +#if USE_WIDEC_SUPPORT + /* + * If the output contains "wide" (multibyte) characters, we will not + * really know the width of a character until we get the last byte + * of the character. Since the preceding byte(s) may use more columns + * on the screen than the final character, it is best to route the + * call to the wins_nwstr() function. + */ + if (sp->_screen_unicode) { + size_t nn = (n > 0) ? (size_t) n : strlen(s); + wchar_t *buffer = typeMalloc(wchar_t, nn + 1); + if (buffer != 0) { + mbstate_t state; + size_t n3; + init_mb(state); + n3 = mbstowcs(buffer, s, nn); + if (n3 != (size_t) (-1)) { + code = wins_nwstr(win, buffer, (int) n3); + } + free(buffer); + } + } + if (code == ERR) +#endif + { + NCURSES_SIZE_T oy = win->_cury; + NCURSES_SIZE_T ox = win->_curx; + const unsigned char *cp; - oy = win->_cury; - ox = win->_curx; - for (cp = str; *cp && (n <= 0 || (cp - str) < n); cp++) { - _nc_insert_ch(sp, win, (chtype) UChar(*cp)); + for (cp = str; (n <= 0 || (cp - str) < n) && *cp; cp++) { + _nc_insert_ch(sp, win, (chtype) UChar(*cp)); + } + win->_curx = ox; + win->_cury = oy; + _nc_synchook(win); + code = OK; } - win->_curx = ox; - win->_cury = oy; - _nc_synchook(win); - code = OK; } returnCode(code); } diff --git a/ncurses/base/lib_instr.c b/ncurses/base/lib_instr.c index f708ecc51e4ac..dbd2a020ac61d 100644 --- a/ncurses/base/lib_instr.c +++ b/ncurses/base/lib_instr.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc. * + * Copyright (c) 1998-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 * @@ -41,41 +41,44 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_instr.c,v 1.21 2014/02/01 22:09:27 tom Exp $") +MODULE_ID("$Id: lib_instr.c,v 1.23 2017/04/29 21:16:20 tom Exp $") NCURSES_EXPORT(int) winnstr(WINDOW *win, char *str, int n) { - int i = 0, row, col; + int i = 0; T((T_CALLED("winnstr(%p,%p,%d)"), (void *) win, str, n)); - if (!str) - returnCode(0); - - if (win) { - getyx(win, row, col); + if (!win || !str) { + i = ERR; + } else { + int row = win->_cury; + int col = win->_curx; + NCURSES_CH_T *text = win->_line[row].text; if (n < 0) - n = win->_maxx - win->_curx + 1; + n = win->_maxx - col + 1; for (; i < n;) { #if USE_WIDEC_SUPPORT - cchar_t *cell = &(win->_line[row].text[col]); - wchar_t *wch; + cchar_t *cell = &(text[col]); attr_t attrs; NCURSES_PAIRS_T pair; - int n2; - bool done = FALSE; mbstate_t state; - size_t i3, n3; char *tmp; if (!isWidecExt(*cell)) { + wchar_t *wch; + int n2; + n2 = getcchar(cell, 0, 0, 0, 0); if (n2 > 0 && (wch = typeCalloc(wchar_t, (unsigned) n2 + 1)) != 0) { + bool done = FALSE; + if (getcchar(cell, wch, &attrs, &pair, 0) == OK) { + size_t n3; init_mb(state); n3 = wcstombs(0, wch, (size_t) 0); @@ -89,6 +92,8 @@ winnstr(WINDOW *win, char *str, int n) } else if ((tmp = typeCalloc(char, need)) == 0) { done = TRUE; } else { + size_t i3; + init_mb(state); wcstombs(tmp, wch, n3); for (i3 = 0; i3 < n3; ++i3) @@ -103,14 +108,14 @@ winnstr(WINDOW *win, char *str, int n) } } #else - str[i++] = (char) CharOf(win->_line[row].text[col]); + str[i++] = (char) CharOf(text[col]); #endif if (++col > win->_maxx) { break; } } + str[i] = '\0'; /* SVr4 does not seem to count the null */ } - str[i] = '\0'; /* SVr4 does not seem to count the null */ T(("winnstr returns %s", _nc_visbuf(str))); returnCode(i); } diff --git a/ncurses/base/lib_isendwin.c b/ncurses/base/lib_isendwin.c index 923e35bf122f4..d8507fa35cfa5 100644 --- a/ncurses/base/lib_isendwin.c +++ b/ncurses/base/lib_isendwin.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2000,2009 Free Software Foundation, Inc. * + * Copyright (c) 1998-2009,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 * @@ -42,14 +42,14 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_isendwin.c,v 1.7 2009/02/15 00:36:24 tom Exp $") +MODULE_ID("$Id: lib_isendwin.c,v 1.8 2017/07/22 23:29:49 tom Exp $") NCURSES_EXPORT(bool) NCURSES_SP_NAME(isendwin) (NCURSES_SP_DCL0) { if (SP_PARM == NULL) return FALSE; - return SP_PARM->_endwin; + return (SP_PARM->_endwin == ewSuspend); } #if NCURSES_SP_FUNCS diff --git a/ncurses/base/lib_mouse.c b/ncurses/base/lib_mouse.c index b0e0f613ebc31..34723f08941ab 100644 --- a/ncurses/base/lib_mouse.c +++ b/ncurses/base/lib_mouse.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * + * Copyright (c) 1998-2018,2019 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 * @@ -84,7 +84,7 @@ #define CUR SP_TERMTYPE #endif -MODULE_ID("$Id: lib_mouse.c,v 1.141 2013/09/21 19:09:19 tom Exp $") +MODULE_ID("$Id: lib_mouse.c,v 1.183 2019/08/10 17:11:50 tom Exp $") #include <tic.h> @@ -225,7 +225,7 @@ write_event(SCREEN *sp, int down, int button, int x, int y) char buf[6]; unsigned long ignore; - strcpy(buf, "\033[M"); /* should be the same as key_mouse */ + _nc_STRCPY(buf, "\033[M", sizeof(buf)); /* should be the same as key_mouse */ buf[3] = ' ' + (button - 1) + (down ? 0 : 0x40); buf[4] = ' ' + x - LEFT_COL + 1; buf[5] = ' ' + y - TOP_ROW + 1; @@ -376,9 +376,46 @@ static void init_xterm_mouse(SCREEN *sp) { sp->_mouse_type = M_XTERM; + sp->_mouse_format = MF_X10; sp->_mouse_xtermcap = tigetstr("XM"); - if (!VALID_STRING(sp->_mouse_xtermcap)) + if (VALID_STRING(sp->_mouse_xtermcap)) { + char *code = strstr(sp->_mouse_xtermcap, "[?"); + if (code != 0) { + code += 2; + while ((*code >= '0') && (*code <= '9')) { + char *next = code; + while ((*next >= '0') && (*next <= '9')) { + ++next; + } + if (!strncmp(code, "1006", (size_t) (next - code))) { + sp->_mouse_format = MF_SGR1006; + } +#ifdef EXP_XTERM_1005 + if (!strncmp(code, "1005", (size_t) (next - code))) { + sp->_mouse_format = MF_XTERM_1005; + } +#endif + if (*next == ';') { + while (*next == ';') { + ++next; + } + code = next; + } else { + break; + } + } + } + } else { + int code = tigetnum("XM"); + switch (code) { + case 1006: + break; + default: + code = 1000; + break; + } sp->_mouse_xtermcap = "\033[?1000%?%p1%{1}%=%th%el%;"; + } } #endif @@ -395,22 +432,22 @@ enable_xterm_mouse(SCREEN *sp, int enable) #if USE_GPM_SUPPORT static bool -allow_gpm_mouse(SCREEN *sp) +allow_gpm_mouse(SCREEN *sp GCC_UNUSED) { bool result = FALSE; #if USE_WEAK_SYMBOLS /* Danger Robinson: do not use dlopen for libgpm if already loaded */ - if ((Gpm_Wgetch)) { + if ((Gpm_Wgetch) != 0) { if (!sp->_mouse_gpm_loaded) { T(("GPM library was already dlopen'd, not by us")); } } else #endif /* GPM does printf's without checking if stdout is a terminal */ - if (isatty(fileno(stdout))) { - char *list = getenv("NCURSES_GPM_TERMS"); - char *env = getenv("TERM"); + if (NC_ISATTY(fileno(stdout))) { + const char *list = getenv("NCURSES_GPM_TERMS"); + const char *env = getenv("TERM"); if (list != 0) { if (env != 0) { result = _nc_name_match(list, env, "|:"); @@ -449,10 +486,17 @@ load_gpm_library(SCREEN *sp) { sp->_mouse_gpm_found = FALSE; if ((sp->_dlopen_gpm = dlopen(LIBGPM_SONAME, my_RTLD)) != 0) { +#if (defined(__GNUC__) && (__GNUC__ >= 5)) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif if (GET_DLSYM(gpm_fd) == 0 || GET_DLSYM(Gpm_Open) == 0 || GET_DLSYM(Gpm_Close) == 0 || GET_DLSYM(Gpm_GetEvent) == 0) { +#if (defined(__GNUC__) && (__GNUC__ >= 5)) || defined(__clang__) +#pragma GCC diagnostic pop +#endif T(("GPM initialization failed: %s", dlerror())); unload_gpm_library(sp); } else { @@ -560,8 +604,8 @@ initialize_mousetype(SCREEN *sp) /* OS/2 VIO */ #if USE_EMX_MOUSE if (!sp->_emxmouse_thread - && strstr(TerminalOf(sp)->type.term_names, "xterm") == 0 - && key_mouse) { + && strstr(SP_TERMTYPE term_names, "xterm") == 0 + && NonEmpty(key_mouse)) { int handles[2]; if (pipe(handles) < 0) { @@ -571,7 +615,7 @@ initialize_mousetype(SCREEN *sp) int rc; if (!sp->_emxmouse_buttons[0]) { - char *s = getenv("MOUSE_BUTTONS_123"); + const char *s = getenv("MOUSE_BUTTONS_123"); sp->_emxmouse_buttons[0] = 1; if (s && strlen(s) >= 3) { @@ -604,13 +648,14 @@ initialize_mousetype(SCREEN *sp) #if USE_SYSMOUSE { + static char dev_tty[] = "/dev/tty"; struct mouse_info the_mouse; char *the_device = 0; - if (isatty(sp->_ifd)) + if (NC_ISATTY(sp->_ifd)) the_device = ttyname(sp->_ifd); if (the_device == 0) - the_device = "/dev/tty"; + the_device = dev_tty; sp->_mouse_fd = open(the_device, O_RDWR); @@ -668,15 +713,12 @@ initialize_mousetype(SCREEN *sp) #endif /* USE_SYSMOUSE */ #ifdef USE_TERM_DRIVER - CallDriver(sp, initmouse); + CallDriver(sp, td_initmouse); #else /* we know how to recognize mouse events under "xterm" */ - 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); } @@ -690,10 +732,11 @@ _nc_mouse_init(SCREEN *sp) /* initialize the mouse */ { bool result = FALSE; - int i; if (sp != 0) { if (!sp->_mouse_initialized) { + int i; + sp->_mouse_initialized = TRUE; TR(MY_TRACE, ("_nc_mouse_init() called")); @@ -846,173 +889,431 @@ _nc_mouse_event(SCREEN *sp) return result; /* true if we found an event */ } +#if USE_EMX_MOUSE +#define PRESS_POSITION(n) \ + do { \ + eventp->bstate = MASK_PRESS(n); \ + sp->_mouse_bstate |= MASK_PRESS(n); \ + if (button & 0x40) { \ + eventp->bstate = MASK_RELEASE(n); \ + sp->_mouse_bstate &= ~MASK_PRESS(n); \ + } \ + } while (0) +#else +#define PRESS_POSITION(n) \ + do { \ + eventp->bstate = (mmask_t) ((sp->_mouse_bstate & MASK_PRESS(n)) \ + ? REPORT_MOUSE_POSITION \ + : MASK_PRESS(n)); \ + sp->_mouse_bstate |= MASK_PRESS(n); \ + } while (0) +#endif + static bool -_nc_mouse_inline(SCREEN *sp) -/* mouse report received in the keyboard stream -- parse its info */ +handle_wheel(SCREEN *sp, MEVENT * eventp, int button, int wheel) { - int b; - bool result = FALSE; - MEVENT *eventp = sp->_mouse_eventp; + bool result = TRUE; - TR(MY_TRACE, ("_nc_mouse_inline() called")); + switch (button & 3) { + case 0: + if (wheel) { + eventp->bstate = MASK_PRESS(4); + /* Do not record in sp->_mouse_bstate; there will be no + * corresponding release event. + */ + } else { + PRESS_POSITION(1); + } + break; + case 1: + if (wheel) { +#if NCURSES_MOUSE_VERSION == 2 + eventp->bstate = MASK_PRESS(5); + /* See comment above for button 4 */ +#else + /* Ignore this event as it is not a true press of the button */ + eventp->bstate = REPORT_MOUSE_POSITION; +#endif + } else { + PRESS_POSITION(2); + } + break; + case 2: + PRESS_POSITION(3); + break; + default: + result = FALSE; + break; + } + return result; +} - if (sp->_mouse_type == M_XTERM) { - unsigned char kbuf[4]; - size_t grabbed; - int res; +static bool +decode_X10_bstate(SCREEN *sp, MEVENT * eventp, unsigned intro) +{ + bool result; + + eventp->bstate = 0; - /* This code requires that your xterm entry contain the kmous - * capability and that it be set to the \E[M documented in the - * Xterm Control Sequences reference. This is how we - * arrange for mouse events to be reported via a KEY_MOUSE - * return value from wgetch(). After this value is received, - * _nc_mouse_inline() gets called and is immediately - * responsible for parsing the mouse status information - * following the prefix. - * - * The following quotes from the ctrlseqs.ms document in the - * X distribution, describing the X mouse tracking feature: - * - * Parameters for all mouse tracking escape sequences - * generated by xterm encode numeric parameters in a single - * character as value+040. For example, ! is 1. - * - * On button press or release, xterm sends ESC [ M CbCxCy. - * The low two bits of Cb encode button information: 0=MB1 - * pressed, 1=MB2 pressed, 2=MB3 pressed, 3=release. The - * upper bits encode what modifiers were down when the - * button was pressed and are added together. 4=Shift, - * 8=Meta, 16=Control. Cx and Cy are the x and y coordinates - * of the mouse event. The upper left corner is (1,1). - * - * (End quote) By the time we get here, we've eaten the - * key prefix. FYI, the loop below is necessary because - * mouse click info isn't guaranteed to present as a - * single clist item. - * - * Wheel mice may return buttons 4 and 5 when the wheel is turned. - * We encode those as button presses. + if (!handle_wheel(sp, eventp, (int) intro, (intro & 96) == 96)) { + + /* + * Release events aren't reported for individual buttons, just for + * the button set as a whole. However, because there are normally + * no mouse events under xterm that intervene between press and + * release, we can infer the button actually released by looking at + * the previous event. */ + if (sp->_mouse_bstate & BUTTON_PRESSED) { + int b; + + eventp->bstate = BUTTON_RELEASED; + for (b = 1; b <= MAX_BUTTONS; ++b) { + if (!(sp->_mouse_bstate & MASK_PRESS(b))) + eventp->bstate &= ~MASK_RELEASE(b); + } + sp->_mouse_bstate = 0; + } else { + /* + * xterm will return a stream of release-events to let the + * application know where the mouse is going, if private mode + * 1002 or 1003 is enabled. + */ + eventp->bstate = REPORT_MOUSE_POSITION; + } + } + + if (intro & 4) { + eventp->bstate |= BUTTON_SHIFT; + } + if (intro & 8) { + eventp->bstate |= BUTTON_ALT; + } + if (intro & 16) { + eventp->bstate |= BUTTON_CTRL; + } + result = (eventp->bstate & REPORT_MOUSE_POSITION) ? TRUE : FALSE; + return result; +} + +/* This code requires that your xterm entry contain the kmous capability and + * that it be set to the \E[M documented in the Xterm Control Sequences + * reference. This is how we arrange for mouse events to be reported via a + * KEY_MOUSE return value from wgetch(). After this value is received, + * _nc_mouse_inline() gets called and is immediately responsible for parsing + * the mouse status information following the prefix. + * + * The following quotes from the ctlseqs.ms document in the XTerm distribution, + * describing the mouse tracking feature: + * + * Parameters for all mouse tracking escape sequences generated by xterm encode + * numeric parameters in a single character as value+040. For example, ! is + * 1. + * + * On button press or release, xterm sends ESC [ M CbCxCy. The low two bits of + * Cb encode button information: 0=MB1 pressed, 1=MB2 pressed, 2=MB3 pressed, + * 3=release. The upper bits encode what modifiers were down when the button + * was pressed and are added together. 4=Shift, 8=Meta, 16=Control. Cx and Cy + * are the x and y coordinates of the mouse event. The upper left corner is + * (1,1). + * + * (End quote) By the time we get here, we've eaten the key prefix. FYI, the + * loop below is necessary because mouse click info isn't guaranteed to present + * as a single clist item. + * + * Wheel mice may return buttons 4 and 5 when the wheel is turned. We encode + * those as button presses. + */ +static bool +decode_xterm_X10(SCREEN *sp, MEVENT * eventp) +{ +#define MAX_KBUF 3 + unsigned char kbuf[MAX_KBUF + 1]; + size_t grabbed; + int res; + bool result; + # if USE_PTHREADS_EINTR # if USE_WEAK_SYMBOLS - if ((pthread_self) && (pthread_kill) && (pthread_equal)) + if ((pthread_self) && (pthread_kill) && (pthread_equal)) # endif - _nc_globals.read_thread = pthread_self(); + _nc_globals.read_thread = pthread_self(); # endif - for (grabbed = 0; grabbed < 3; grabbed += (size_t) res) { + for (grabbed = 0; grabbed < MAX_KBUF; grabbed += (size_t) res) { - /* For VIO mouse we add extra bit 64 to disambiguate button-up. */ + /* For VIO mouse we add extra bit 64 to disambiguate button-up. */ + res = (int) read( #if USE_EMX_MOUSE - res = (int) read(M_FD(sp) >= 0 ? M_FD(sp) : sp->_ifd, &kbuf, 3); + (M_FD(sp) >= 0) ? M_FD(sp) : sp->_ifd, #else - res = (int) read(sp->_ifd, kbuf + grabbed, 3 - grabbed); + sp->_ifd, #endif - if (res == -1) - break; - } + kbuf + grabbed, (size_t) (MAX_KBUF - (int) grabbed)); + if (res == -1) + break; + } #if USE_PTHREADS_EINTR - _nc_globals.read_thread = 0; + _nc_globals.read_thread = 0; #endif - kbuf[3] = '\0'; + kbuf[MAX_KBUF] = '\0'; - TR(TRACE_IEVENT, - ("_nc_mouse_inline sees the following xterm data: '%s'", kbuf)); + TR(TRACE_IEVENT, + ("_nc_mouse_inline sees the following xterm data: '%s'", kbuf)); - /* there's only one mouse... */ - eventp->id = NORMAL_EVENT; + /* there's only one mouse... */ + eventp->id = NORMAL_EVENT; + + result = decode_X10_bstate(sp, eventp, kbuf[0]); + + eventp->x = (kbuf[1] - ' ') - 1; + eventp->y = (kbuf[2] - ' ') - 1; + + return result; +} - /* processing code goes here */ - eventp->bstate = 0; +#ifdef EXP_XTERM_1005 +/* + * This is identical to X10/X11 responses except that there are two UTF-8 + * characters storing the ordinates instead of two bytes. + */ +static bool +decode_xterm_1005(SCREEN *sp, MEVENT * eventp) +{ + char kbuf[80]; + size_t grabbed; + size_t limit = (sizeof(kbuf) - 1); + unsigned coords[2]; + bool result; + + coords[0] = 0; + coords[1] = 0; + +# if USE_PTHREADS_EINTR +# if USE_WEAK_SYMBOLS + if ((pthread_self) && (pthread_kill) && (pthread_equal)) +# endif + _nc_globals.read_thread = pthread_self(); +# endif + for (grabbed = 0; grabbed < limit;) { + int res; + res = (int) read( #if USE_EMX_MOUSE -#define PRESS_POSITION(n) \ - do { \ - eventp->bstate = MASK_PRESS(n); \ - sp->_mouse_bstate |= MASK_PRESS(n); \ - if (kbuf[0] & 0x40) { \ - eventp->bstate = MASK_RELEASE(n); \ - sp->_mouse_bstate &= ~MASK_PRESS(n); \ - } \ - } while (0) + (M_FD(sp) >= 0) ? M_FD(sp) : sp->_ifd, #else -#define PRESS_POSITION(n) \ - do { \ - eventp->bstate = (mmask_t) (sp->_mouse_bstate & MASK_PRESS(n) \ - ? REPORT_MOUSE_POSITION \ - : MASK_PRESS(n)); \ - sp->_mouse_bstate |= MASK_PRESS(n); \ - } while (0) + sp->_ifd, #endif + (kbuf + grabbed), (size_t) 1); + if (res == -1) + break; + grabbed += (size_t) res; + if (grabbed > 1) { + size_t check = 1; + int n; - switch (kbuf[0] & 0x3) { - case 0x0: - if ((kbuf[0] & 96) == 96) { - eventp->bstate = MASK_PRESS(4); - /* Do not record in sp->_mouse_bstate; there will be no - * corresponding release event. - */ - } else { - PRESS_POSITION(1); + for (n = 0; n < 2; ++n) { + int rc; + + if (check >= grabbed) + break; + rc = _nc_conv_to_utf32(&coords[n], kbuf + check, (unsigned) + (grabbed - check)); + if (!rc) + break; + check += (size_t) rc; } - break; + if (n >= 2) + break; + } + } +#if USE_PTHREADS_EINTR + _nc_globals.read_thread = 0; +#endif - case 0x1: - if ((kbuf[0] & 96) == 96) { -#if NCURSES_MOUSE_VERSION == 2 - eventp->bstate = MASK_PRESS(5); - /* See comment above for button 4 */ + TR(TRACE_IEVENT, + ("_nc_mouse_inline sees the following xterm data: %s", + _nc_visbufn(kbuf, (int) grabbed))); + + /* there's only one mouse... */ + eventp->id = NORMAL_EVENT; + + result = decode_X10_bstate(sp, eventp, UChar(kbuf[0])); + + eventp->x = (int) (coords[0] - ' ') - 1; + eventp->y = (int) (coords[1] - ' ') - 1; + + return result; +} +#endif /* EXP_XTERM_1005 */ + +/* + * ECMA-48 section 5.4 + */ +#define isInter(c) ((c) >= 0x20 && (c) <= 0x2f) +#define isParam(c) ((c) >= 0x30 && (c) <= 0x3f) +#define isFinal(c) ((c) >= 0x40 && (c) <= 0x7e) + +#define MAX_PARAMS 9 + +typedef struct { + int nerror; /* nonzero if there are unexpected chars */ + int nparam; /* number of numeric parameters */ + int params[MAX_PARAMS]; + int final; /* the final-character */ +} SGR_DATA; + +static bool +read_SGR(SCREEN *sp, SGR_DATA * result) +{ + char kbuf[80]; /* bigger than any possible mouse response */ + int grabbed = 0; + int ch = 0; + int now = -1; + int marker = 1; + + memset(result, 0, sizeof(*result)); +# if USE_PTHREADS_EINTR +# if USE_WEAK_SYMBOLS + if ((pthread_self) && (pthread_kill) && (pthread_equal)) +# endif + _nc_globals.read_thread = pthread_self(); +# endif + + do { + int res; + + res = (int) read( +#if USE_EMX_MOUSE + (M_FD(sp) >= 0) ? M_FD(sp) : sp->_ifd, #else - /* Ignore this event as it is not a true press of the button */ - eventp->bstate = REPORT_MOUSE_POSITION; + sp->_ifd, #endif - } else { - PRESS_POSITION(2); + (kbuf + grabbed), (size_t) 1); + if (res == -1) + break; + if ((grabbed + MAX_KBUF) >= (int) sizeof(kbuf)) { + result->nerror++; + break; + } + ch = UChar(kbuf[grabbed]); + kbuf[grabbed + 1] = 0; + switch (ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (marker) { + ++now; + result->nparam = (now + 1); } + marker = 0; + result->params[now] = (result->params[now] * 10) + (ch - '0'); break; - - case 0x2: - PRESS_POSITION(3); + case ';': + if (marker) { + ++now; + result->nparam = (now + 1); + } + marker = 1; break; - - case 0x3: - /* - * Release events aren't reported for individual buttons, just for - * the button set as a whole. However, because there are normally - * no mouse events under xterm that intervene between press and - * release, we can infer the button actually released by looking at - * the previous event. - */ - if (sp->_mouse_bstate & BUTTON_PRESSED) { - eventp->bstate = BUTTON_RELEASED; - for (b = 1; b <= MAX_BUTTONS; ++b) { - if (!(sp->_mouse_bstate & MASK_PRESS(b))) - eventp->bstate &= ~MASK_RELEASE(b); - } - sp->_mouse_bstate = 0; - } else { + default: + if (ch < 32 || ch > 126) { /* - * XFree86 xterm will return a stream of release-events to - * let the application know where the mouse is going, if the - * private mode 1002 or 1003 is enabled. + * Technically other characters could be interspersed in the + * response. Ignore those for now. */ - eventp->bstate = REPORT_MOUSE_POSITION; + result->nerror++; + continue; + } else if (isFinal(ch)) { + if (marker) { + result->nparam++; + } + result->final = ch; + } else { + result->nerror++; } break; } - result = (eventp->bstate & REPORT_MOUSE_POSITION) ? TRUE : FALSE; + ++grabbed; + } while (!isFinal(ch)); +#if USE_PTHREADS_EINTR + _nc_globals.read_thread = 0; +#endif - if (kbuf[0] & 4) { + kbuf[++grabbed] = 0; + TR(TRACE_IEVENT, + ("_nc_mouse_inline sees the following xterm data: '%s'", kbuf)); + return (grabbed > 0) && (result->nerror == 0); +} + +static bool +decode_xterm_SGR1006(SCREEN *sp, MEVENT * eventp) +{ + SGR_DATA data; + bool result = FALSE; + if (read_SGR(sp, &data)) { + int b = data.params[0]; + int b3 = 1 + (b & 3); + + eventp->id = NORMAL_EVENT; + if (data.final == 'M') { + (void) handle_wheel(sp, eventp, b, (b & 64) == 64); + } else { + mmask_t pressed = (mmask_t) NCURSES_MOUSE_MASK(b3, NCURSES_BUTTON_PRESSED); + mmask_t release = (mmask_t) NCURSES_MOUSE_MASK(b3, NCURSES_BUTTON_RELEASED); + if (sp->_mouse_bstate & pressed) { + eventp->bstate = release; + sp->_mouse_bstate &= ~pressed; + } else { + eventp->bstate = REPORT_MOUSE_POSITION; + } + } + if (b & 4) { eventp->bstate |= BUTTON_SHIFT; } - if (kbuf[0] & 8) { + if (b & 8) { eventp->bstate |= BUTTON_ALT; } - if (kbuf[0] & 16) { + if (b & 16) { eventp->bstate |= BUTTON_CTRL; } + result = (eventp->bstate & REPORT_MOUSE_POSITION) ? TRUE : FALSE; + eventp->x = (data.params[1] ? (data.params[1] - 1) : 0); + eventp->y = (data.params[2] ? (data.params[2] - 1) : 0); + } + return result; +} + +static bool +_nc_mouse_inline(SCREEN *sp) +/* mouse report received in the keyboard stream -- parse its info */ +{ + bool result = FALSE; + MEVENT *eventp = sp->_mouse_eventp; + + TR(MY_TRACE, ("_nc_mouse_inline() called")); + + if (sp->_mouse_type == M_XTERM) { + switch (sp->_mouse_format) { + case MF_X10: + result = decode_xterm_X10(sp, eventp); + break; + case MF_SGR1006: + result = decode_xterm_SGR1006(sp, eventp); + break; +#ifdef EXP_XTERM_1005 + case MF_XTERM_1005: + result = decode_xterm_1005(sp, eventp); + break; +#endif + } - eventp->x = (kbuf[1] - ' ') - 1; - eventp->y = (kbuf[2] - ' ') - 1; TR(MY_TRACE, ("_nc_mouse_inline: primitive mouse-event %s has slot %ld", _nc_tracemouse(sp, eventp), @@ -1020,9 +1321,23 @@ _nc_mouse_inline(SCREEN *sp) /* bump the next-free pointer into the circular list */ sp->_mouse_eventp = NEXT(eventp); -#if 0 /* this return would be needed for QNX's mods to lib_getch.c */ - return (TRUE); -#endif + + if (!result) { + /* If this event is from a wheel-mouse, treat it like position + * reports and avoid waiting for the release-events which will + * never come. + */ + if (eventp->bstate & BUTTON_PRESSED) { + int b; + + for (b = 4; b <= MAX_BUTTONS; ++b) { + if ((eventp->bstate & MASK_PRESS(b))) { + result = TRUE; + break; + } + } + } + } } return (result); @@ -1445,11 +1760,14 @@ NCURSES_EXPORT(int) NCURSES_SP_NAME(getmouse) (NCURSES_SP_DCLx MEVENT * aevent) { int result = ERR; + MEVENT *eventp; T((T_CALLED("getmouse(%p,%p)"), (void *) SP_PARM, (void *) aevent)); - if ((aevent != 0) && (SP_PARM != 0) && (SP_PARM->_mouse_type != M_NONE)) { - MEVENT *eventp = SP_PARM->_mouse_eventp; + if ((aevent != 0) && + (SP_PARM != 0) && + (SP_PARM->_mouse_type != M_NONE) && + (eventp = SP_PARM->_mouse_eventp) != 0) { /* compute the current-event pointer */ MEVENT *prev = PREV(eventp); @@ -1498,11 +1816,13 @@ NCURSES_EXPORT(int) NCURSES_SP_NAME(ungetmouse) (NCURSES_SP_DCLx MEVENT * aevent) { int result = ERR; + MEVENT *eventp; T((T_CALLED("ungetmouse(%p,%p)"), (void *) SP_PARM, (void *) aevent)); - if (aevent != 0 && SP_PARM != 0) { - MEVENT *eventp = SP_PARM->_mouse_eventp; + if (aevent != 0 && + SP_PARM != 0 && + (eventp = SP_PARM->_mouse_eventp) != 0) { /* stick the given event in the next-free slot */ *eventp = *aevent; @@ -1530,7 +1850,6 @@ NCURSES_SP_NAME(mousemask) (NCURSES_SP_DCLx mmask_t newmask, mmask_t * oldmask) /* set the mouse event mask */ { mmask_t result = 0; - int b; T((T_CALLED("mousemask(%p,%#lx,%p)"), (void *) SP_PARM, @@ -1543,7 +1862,10 @@ NCURSES_SP_NAME(mousemask) (NCURSES_SP_DCLx mmask_t newmask, mmask_t * oldmask) if (newmask || SP_PARM->_mouse_initialized) { _nc_mouse_init(SP_PARM); + if (SP_PARM->_mouse_type != M_NONE) { + int b; + result = newmask & (REPORT_MOUSE_POSITION | BUTTON_ALT diff --git a/ncurses/base/lib_newterm.c b/ncurses/base/lib_newterm.c index 435763d096ea4..84963db46f2c8 100644 --- a/ncurses/base/lib_newterm.c +++ b/ncurses/base/lib_newterm.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * + * Copyright (c) 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 * @@ -48,7 +48,7 @@ #include <tic.h> -MODULE_ID("$Id: lib_newterm.c,v 1.90 2013/09/28 21:02:56 tom Exp $") +MODULE_ID("$Id: lib_newterm.c,v 1.101 2018/04/07 20:36:22 tom Exp $") #ifdef USE_TERM_DRIVER #define NumLabels InfoOf(SP_PARM).numlabels @@ -76,6 +76,7 @@ _nc_initscr(NCURSES_SP_DCL0) /* for extended XPG4 conformance requires cbreak() at this point */ /* (SVr4 curses does this anyway) */ + T((T_CALLED("_nc_initscr(%p) ->term %p"), (void *) SP_PARM, (void *) term)); if (NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG) == OK) { TTY buf; @@ -93,7 +94,7 @@ _nc_initscr(NCURSES_SP_DCL0) if (result == OK) term->Nttyb = buf; } - return result; + returnCode(result); } /* @@ -162,20 +163,16 @@ nofilter(void) NCURSES_EXPORT(SCREEN *) NCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx - NCURSES_CONST char *name, + const char *name, FILE *ofp, FILE *ifp) { - int value; int errret; SCREEN *result = 0; SCREEN *current; TERMINAL *its_term; FILE *_ofp = ofp ? ofp : stdout; FILE *_ifp = ifp ? ifp : stdin; - int cols; - int slk_format; - int filter_mode; TERMINAL *new_term = 0; START_TRACE(); @@ -200,11 +197,10 @@ NCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx INIT_TERM_DRIVER(); /* this loads the capability entry, then sets LINES and COLS */ if ( -#if NCURSES_SP_FUNCS - SP_PARM->_prescreen && -#endif TINFO_SETUP_TERM(&new_term, name, fileno(_ofp), &errret, FALSE) != ERR) { + int slk_format; + int filter_mode; _nc_set_screen(0); #ifdef USE_TERM_DRIVER @@ -235,6 +231,9 @@ NCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx _nc_set_screen(current); result = 0; } else { + int value; + int cols; + #ifdef USE_TERM_DRIVER TERMINAL_CONTROL_BLOCK *TCB; #elif !NCURSES_SP_FUNCS @@ -268,7 +267,11 @@ NCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx /* allow user to set maximum escape delay from the environment */ if ((value = _nc_getenv_num("ESCDELAY")) >= 0) { +#if NCURSES_EXT_FUNCS NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_ARGx value); +#else + ESCDELAY = value; +#endif } /* if the terminal type has real soft labels, set those up */ @@ -284,7 +287,7 @@ NCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx #else SP_PARM->_use_meta = FALSE; #endif - SP_PARM->_endwin = FALSE; + SP_PARM->_endwin = ewInitial; #ifndef USE_TERM_DRIVER /* * Check whether we can optimize scrolling under dumb terminals in @@ -306,7 +309,7 @@ NCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx /* compute movement costs so we can do better move optimization */ #ifdef USE_TERM_DRIVER - TCBOf(SP_PARM)->drv->scinit(SP_PARM); + TCBOf(SP_PARM)->drv->td_scinit(SP_PARM); #else /* ! USE_TERM_DRIVER */ /* * Check for mismatched graphic-rendition capabilities. Most SVr4 @@ -344,8 +347,14 @@ NCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx #if NCURSES_SP_FUNCS NCURSES_EXPORT(SCREEN *) -newterm(NCURSES_CONST char *name, FILE *ofp, FILE *ifp) +newterm(const char *name, FILE *ofp, FILE *ifp) { - return NCURSES_SP_NAME(newterm) (CURRENT_SCREEN_PRE, name, ofp, ifp); + SCREEN *rc; + _nc_lock_global(prescreen); + START_TRACE(); + rc = NCURSES_SP_NAME(newterm) (CURRENT_SCREEN_PRE, name, ofp, ifp); + _nc_forget_prescr(); + _nc_unlock_global(prescreen); + return rc; } #endif diff --git a/ncurses/base/lib_newwin.c b/ncurses/base/lib_newwin.c index a6c64beaaf4a1..5d48107a3003d 100644 --- a/ncurses/base/lib_newwin.c +++ b/ncurses/base/lib_newwin.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * + * Copyright (c) 1998-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 * @@ -43,7 +43,7 @@ #include <curses.priv.h> #include <stddef.h> -MODULE_ID("$Id: lib_newwin.c,v 1.71 2011/05/28 21:32:51 tom Exp $") +MODULE_ID("$Id: lib_newwin.c,v 1.74 2017/05/13 23:17:29 tom Exp $") #define window_is(name) ((sp)->_##name == win) @@ -91,8 +91,6 @@ remove_window_from_screen(WINDOW *win) NCURSES_EXPORT(int) _nc_freewin(WINDOW *win) { - WINDOWLIST *p, *q; - int i; int result = ERR; #ifdef USE_SP_WINDOWLIST SCREEN *sp = _nc_screen_of(win); /* pretend this is parameter */ @@ -101,17 +99,23 @@ _nc_freewin(WINDOW *win) T((T_CALLED("_nc_freewin(%p)"), (void *) win)); if (win != 0) { + if (_nc_nonsp_try_global(curses) == 0) { + WINDOWLIST *p, *q; + q = 0; - for (each_window(SP_PARM, p)) { + for (each_window(sp, p)) { + if (&(p->win) == win) { remove_window_from_screen(win); if (q == 0) - WindowList(SP_PARM) = p->next; + WindowList(sp) = p->next; else q->next = p->next; if (!(win->_flags & _SUBWIN)) { + int i; + for (i = 0; i <= win->_maxy; i++) FreeIfNeeded(win->_line[i].text); } @@ -384,18 +388,18 @@ NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_DCLx NCURSES_EXPORT(WINDOW *) _nc_curscr_of(SCREEN *sp) { - return sp == 0 ? 0 : CurScreen(sp); + return (sp == 0) ? NULL : CurScreen(sp); } NCURSES_EXPORT(WINDOW *) _nc_newscr_of(SCREEN *sp) { - return sp == 0 ? 0 : NewScreen(sp); + return (sp == 0) ? NULL : NewScreen(sp); } NCURSES_EXPORT(WINDOW *) _nc_stdscr_of(SCREEN *sp) { - return sp == 0 ? 0 : StdScreen(sp); + return (sp == 0) ? NULL : StdScreen(sp); } #endif diff --git a/ncurses/base/lib_overlay.c b/ncurses/base/lib_overlay.c index a206248a1e74e..64356ff1c8c64 100644 --- a/ncurses/base/lib_overlay.c +++ b/ncurses/base/lib_overlay.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2013 Free Software Foundation, Inc. * + * Copyright (c) 1998-2013,2016 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 * @@ -40,21 +40,19 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_overlay.c,v 1.31 2013/04/06 23:47:13 tom Exp $") +MODULE_ID("$Id: lib_overlay.c,v 1.32 2016/05/28 23:11:26 tom Exp $") static int overlap(const WINDOW *const src, WINDOW *const dst, int const flag) { int rc = ERR; - int sx1, sy1, sx2, sy2; - int dx1, dy1, dx2, dy2; - int sminrow, smincol; - int dminrow, dmincol; - int dmaxrow, dmaxcol; T((T_CALLED("overlap(%p,%p,%d)"), (const void *) src, (void *) dst, flag)); if (src != 0 && dst != 0) { + int sx1, sy1, sx2, sy2; + int dx1, dy1, dx2, dy2; + _nc_lock_global(curses); T(("src : begy %ld, begx %ld, maxy %ld, maxx %ld", @@ -79,12 +77,12 @@ overlap(const WINDOW *const src, WINDOW *const dst, int const flag) dy2 = dy1 + dst->_maxy; if (dx2 >= sx1 && dx1 <= sx2 && dy2 >= sy1 && dy1 <= sy2) { - sminrow = max(sy1, dy1) - sy1; - smincol = max(sx1, dx1) - sx1; - dminrow = max(sy1, dy1) - dy1; - dmincol = max(sx1, dx1) - dx1; - dmaxrow = min(sy2, dy2) - dy1; - dmaxcol = min(sx2, dx2) - dx1; + int sminrow = max(sy1, dy1) - sy1; + int smincol = max(sx1, dx1) - sx1; + int dminrow = max(sy1, dy1) - dy1; + int dmincol = max(sx1, dx1) - dx1; + int dmaxrow = min(sy2, dy2) - dy1; + int dmaxcol = min(sx2, dx2) - dx1; rc = copywin(src, dst, sminrow, smincol, @@ -139,10 +137,6 @@ copywin(const WINDOW *src, WINDOW *dst, int over) { int rc = ERR; - int sx, sy, dx, dy; - bool touched; - attr_t bk; - attr_t mask; T((T_CALLED("copywin(%p, %p, %d, %d, %d, %d, %d, %d, %d)"), (const void *) src, @@ -155,6 +149,9 @@ copywin(const WINDOW *src, WINDOW *dst, && dst != 0 && dmaxrow >= dminrow && dmaxcol >= dmincol) { + attr_t bk; + attr_t mask; + _nc_lock_global(curses); bk = AttrOf(dst->_nc_bkgd); @@ -163,18 +160,20 @@ copywin(const WINDOW *src, WINDOW *dst, /* make sure rectangle exists in source */ if ((sminrow + dmaxrow - dminrow) <= (src->_maxy + 1) && (smincol + dmaxcol - dmincol) <= (src->_maxx + 1)) { - bool copied = FALSE; T(("rectangle exists in source")); /* make sure rectangle fits in destination */ if (dmaxrow <= dst->_maxy && dmaxcol <= dst->_maxx) { + int sx, sy, dx, dy; + bool copied = FALSE; T(("rectangle fits in destination")); for (dy = dminrow, sy = sminrow; dy <= dmaxrow; sy++, dy++) { + bool touched; if (dy < 0 || sy < 0) continue; diff --git a/ncurses/base/lib_pad.c b/ncurses/base/lib_pad.c index b87498b500cd8..8c7e5af01c9c5 100644 --- a/ncurses/base/lib_pad.c +++ b/ncurses/base/lib_pad.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. * + * Copyright (c) 1998-2010,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 * @@ -42,7 +42,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_pad.c,v 1.46 2010/04/24 23:50:45 tom Exp $") +MODULE_ID("$Id: lib_pad.c,v 1.47 2017/10/22 19:57:26 tom Exp $") NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(newpad) (NCURSES_SP_DCLx int l, int c) @@ -188,6 +188,12 @@ pnoutrefresh(WINDOW *win, T(("pad being refreshed")); +#ifdef TRACE + if (USE_TRACEF(TRACE_UPDATE)) { + _tracedump("...pad", win); + _nc_unlock_global(tracef); + } +#endif /* TRACE */ #if USE_SCROLL_HINTS if (win->_pad._pad_y >= 0) { displaced = pminrow - win->_pad._pad_y diff --git a/ncurses/base/lib_printw.c b/ncurses/base/lib_printw.c index 56528f6bc7a7c..41bd2f98946e0 100644 --- a/ncurses/base/lib_printw.c +++ b/ncurses/base/lib_printw.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2012 Free Software Foundation, Inc. * + * Copyright (c) 1998-2018,2019 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 * @@ -39,10 +39,10 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_printw.c,v 1.23 2012/09/03 17:55:28 tom Exp $") +MODULE_ID("$Id: lib_printw.c,v 1.27 2019/01/19 15:46:25 tom Exp $") NCURSES_EXPORT(int) -printw(const char *fmt,...) +printw(const char *fmt, ...) { va_list argp; int code; @@ -56,14 +56,14 @@ printw(const char *fmt,...) #endif va_start(argp, fmt); - code = vwprintw(stdscr, fmt, argp); + code = vw_printw(stdscr, fmt, argp); va_end(argp); returnCode(code); } NCURSES_EXPORT(int) -wprintw(WINDOW *win, const char *fmt,...) +wprintw(WINDOW *win, const char *fmt, ...) { va_list argp; int code; @@ -77,16 +77,15 @@ wprintw(WINDOW *win, const char *fmt,...) #endif va_start(argp, fmt); - code = vwprintw(win, fmt, argp); + code = vw_printw(win, fmt, argp); va_end(argp); returnCode(code); } NCURSES_EXPORT(int) -mvprintw(int y, int x, const char *fmt,...) +mvprintw(int y, int x, const char *fmt, ...) { - va_list argp; int code; #ifdef TRACE @@ -98,17 +97,18 @@ mvprintw(int y, int x, const char *fmt,...) #endif if ((code = move(y, x)) != ERR) { + va_list argp; + va_start(argp, fmt); - code = vwprintw(stdscr, fmt, argp); + code = vw_printw(stdscr, fmt, argp); va_end(argp); } returnCode(code); } NCURSES_EXPORT(int) -mvwprintw(WINDOW *win, int y, int x, const char *fmt,...) +mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...) { - va_list argp; int code; #ifdef TRACE @@ -120,8 +120,10 @@ mvwprintw(WINDOW *win, int y, int x, const char *fmt,...) #endif if ((code = wmove(win, y, x)) != ERR) { + va_list argp; + va_start(argp, fmt); - code = vwprintw(win, fmt, argp); + code = vw_printw(win, fmt, argp); va_end(argp); } returnCode(code); @@ -144,3 +146,21 @@ vwprintw(WINDOW *win, const char *fmt, va_list argp) } returnCode(code); } + +NCURSES_EXPORT(int) +vw_printw(WINDOW *win, const char *fmt, va_list argp) +{ + char *buf; + int code = ERR; +#if NCURSES_SP_FUNCS + SCREEN *sp = _nc_screen_of(win); +#endif + + T((T_CALLED("vw_printw(%p,%s,va_list)"), (void *) win, _nc_visbuf(fmt))); + + buf = NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_ARGx fmt, argp); + if (buf != 0) { + code = waddstr(win, buf); + } + returnCode(code); +} diff --git a/ncurses/base/lib_restart.c b/ncurses/base/lib_restart.c index 3a3756e385e83..5bfb0788266d0 100644 --- a/ncurses/base/lib_restart.c +++ b/ncurses/base/lib_restart.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc. * + * Copyright (c) 1998-2012,2015 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 +41,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_restart.c,v 1.15 2012/12/08 20:40:06 tom Exp $") +MODULE_ID("$Id: lib_restart.c,v 1.16 2015/06/27 18:12:15 tom Exp $") NCURSES_EXPORT(int) NCURSES_SP_NAME(restartterm) (NCURSES_SP_DCLx @@ -54,6 +54,7 @@ NCURSES_SP_NAME(restartterm) (NCURSES_SP_DCLx TERMINAL *new_term = 0; #endif + START_TRACE(); T((T_CALLED("restartterm(%p,%s,%d,%p)"), (void *) SP_PARM, termp, @@ -110,6 +111,7 @@ NCURSES_SP_NAME(restartterm) (NCURSES_SP_DCLx NCURSES_EXPORT(int) restartterm(NCURSES_CONST char *termp, int filenum, int *errret) { + START_TRACE(); return NCURSES_SP_NAME(restartterm) (CURRENT_SCREEN, termp, filenum, errret); } #endif diff --git a/ncurses/base/lib_scanw.c b/ncurses/base/lib_scanw.c index 637aa46ece01a..26a47d1abf559 100644 --- a/ncurses/base/lib_scanw.c +++ b/ncurses/base/lib_scanw.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2011 Free Software Foundation, Inc. * + * Copyright (c) 1998-2018,2019 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 * @@ -40,21 +40,40 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_scanw.c,v 1.13 2011/10/22 16:31:35 tom Exp $") +MODULE_ID("$Id: lib_scanw.c,v 1.18 2019/01/19 15:46:25 tom Exp $") NCURSES_EXPORT(int) -vwscanw(WINDOW *win, NCURSES_CONST char *fmt, va_list argp) +vwscanw(WINDOW *win, const char *fmt, va_list argp) { char buf[BUFSIZ]; + int code = ERR; - if (wgetnstr(win, buf, (int) sizeof(buf) - 1) == ERR) - return (ERR); + if (wgetnstr(win, buf, (int) sizeof(buf) - 1) != ERR) { + if ((code = vsscanf(buf, fmt, argp)) == EOF) { + code = ERR; + } + } - return (vsscanf(buf, fmt, argp)); + return code; } NCURSES_EXPORT(int) -scanw(NCURSES_CONST char *fmt,...) +vw_scanw(WINDOW *win, const char *fmt, va_list argp) +{ + char buf[BUFSIZ]; + int code = ERR; + + if (wgetnstr(win, buf, (int) sizeof(buf) - 1) != ERR) { + if ((code = vsscanf(buf, fmt, argp)) == EOF) { + code = ERR; + } + } + + return code; +} + +NCURSES_EXPORT(int) +scanw(const char *fmt, ...) { int code; va_list ap; @@ -62,13 +81,13 @@ scanw(NCURSES_CONST char *fmt,...) T(("scanw(\"%s\",...) called", fmt)); va_start(ap, fmt); - code = vwscanw(stdscr, fmt, ap); + code = vw_scanw(stdscr, fmt, ap); va_end(ap); return (code); } NCURSES_EXPORT(int) -wscanw(WINDOW *win, NCURSES_CONST char *fmt,...) +wscanw(WINDOW *win, const char *fmt, ...) { int code; va_list ap; @@ -76,31 +95,31 @@ wscanw(WINDOW *win, NCURSES_CONST char *fmt,...) T(("wscanw(%p,\"%s\",...) called", (void *) win, fmt)); va_start(ap, fmt); - code = vwscanw(win, fmt, ap); + code = vw_scanw(win, fmt, ap); va_end(ap); return (code); } NCURSES_EXPORT(int) -mvscanw(int y, int x, NCURSES_CONST char *fmt,...) +mvscanw(int y, int x, const char *fmt, ...) { int code; va_list ap; va_start(ap, fmt); - code = (move(y, x) == OK) ? vwscanw(stdscr, fmt, ap) : ERR; + code = (move(y, x) == OK) ? vw_scanw(stdscr, fmt, ap) : ERR; va_end(ap); return (code); } NCURSES_EXPORT(int) -mvwscanw(WINDOW *win, int y, int x, NCURSES_CONST char *fmt,...) +mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...) { int code; va_list ap; va_start(ap, fmt); - code = (wmove(win, y, x) == OK) ? vwscanw(win, fmt, ap) : ERR; + code = (wmove(win, y, x) == OK) ? vw_scanw(win, fmt, ap) : ERR; va_end(ap); return (code); } diff --git a/ncurses/base/lib_screen.c b/ncurses/base/lib_screen.c index 695ed30e7e100..9e942eaf84940 100644 --- a/ncurses/base/lib_screen.c +++ b/ncurses/base/lib_screen.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2011 Free Software Foundation, Inc. * + * Copyright (c) 1998-2018,2019 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 * @@ -35,32 +35,509 @@ #include <curses.priv.h> +#include <ctype.h> + #ifndef CUR #define CUR SP_TERMTYPE #endif -MODULE_ID("$Id: lib_screen.c,v 1.41 2011/10/22 15:03:11 tom Exp $") +MODULE_ID("$Id: lib_screen.c,v 1.96 2019/07/20 20:23:21 tom Exp $") #define MAX_SIZE 0x3fff /* 16k is big enough for a window or pad */ +#define MARKER '\\' +#define APPEND '+' +#define GUTTER '|' +#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 - (target - base)) +#define TOP_SLIMIT _nc_SLIMIT(sizeof(buffer)) + +/* + * 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'}; + +#if NCURSES_EXT_PUTWIN +typedef enum { + pINT /* int */ + ,pSHORT /* short */ + ,pBOOL /* bool */ + ,pATTR /* attr_t */ + ,pCHAR /* chtype */ + ,pSIZE /* NCURSES_SIZE_T */ +#if NCURSES_WIDECHAR + ,pCCHAR /* cchar_t */ +#endif +} PARAM_TYPE; + +typedef struct { + const char name[11]; + attr_t attr; +} SCR_ATTRS; + +typedef struct { + const char name[17]; + PARAM_TYPE type; + size_t size; + size_t offset; +} SCR_PARAMS; + +#define DATA(name) { { #name }, A_##name } +static const SCR_ATTRS scr_attrs[] = +{ + DATA(NORMAL), + DATA(STANDOUT), + DATA(UNDERLINE), + DATA(REVERSE), + DATA(BLINK), + DATA(DIM), + DATA(BOLD), + DATA(ALTCHARSET), + DATA(INVIS), + DATA(PROTECT), + DATA(HORIZONTAL), + DATA(LEFT), + DATA(LOW), + DATA(RIGHT), + DATA(TOP), + DATA(VERTICAL), + +#ifdef A_ITALIC + DATA(ITALIC), +#endif +}; +#undef DATA + +#define sizeof2(type,name) sizeof(((type *)0)->name) +#define DATA(name, type) { { #name }, type, sizeof2(WINDOW, name), offsetof(WINDOW, name) } + +static const SCR_PARAMS scr_params[] = +{ + DATA(_cury, pSIZE), + DATA(_curx, pSIZE), + DATA(_maxy, pSIZE), + DATA(_maxx, pSIZE), + DATA(_begy, pSIZE), + DATA(_begx, pSIZE), + DATA(_flags, pSHORT), + DATA(_attrs, pATTR), + DATA(_bkgd, pCHAR), + DATA(_notimeout, pBOOL), + DATA(_clear, pBOOL), + DATA(_leaveok, pBOOL), + DATA(_scroll, pBOOL), + DATA(_idlok, pBOOL), + DATA(_idcok, pBOOL), + DATA(_immed, pBOOL), + DATA(_sync, pBOOL), + DATA(_use_keypad, pBOOL), + DATA(_delay, pINT), + DATA(_regtop, pSIZE), + DATA(_regbottom, pSIZE), + DATA(_pad._pad_y, pSIZE), + DATA(_pad._pad_x, pSIZE), + DATA(_pad._pad_top, pSIZE), + DATA(_pad._pad_left, pSIZE), + DATA(_pad._pad_bottom, pSIZE), + DATA(_pad._pad_right, pSIZE), + DATA(_yoffset, pSIZE), +#if NCURSES_WIDECHAR + DATA(_bkgrnd, pCCHAR), +#if NCURSES_EXT_COLORS + DATA(_color, pINT), +#endif +#endif +}; +#undef DATA + +static const NCURSES_CH_T blank = NewChar(BLANK_TEXT); + +/* + * Allocate and read a line of text. Caller must free it. + */ +static char * +read_txt(FILE *fp) +{ + size_t limit = 1024; + char *result = malloc(limit); + char *buffer; + + if (result != 0) { + int ch = 0; + size_t used = 0; + + clearerr(fp); + result[used] = '\0'; + do { + if (used + 2 >= limit) { + limit += 1024; + buffer = realloc(result, limit); + if (buffer == 0) { + free(result); + result = 0; + break; + } + result = buffer; + } + ch = fgetc(fp); + if (ch == EOF) + break; + result[used++] = (char) ch; + result[used] = '\0'; + } while (ch != '\n'); + + if (ch == '\n') { + result[--used] = '\0'; + T(("READ:%s", result)); + } else if (used == 0) { + free(result); + result = 0; + } + } + return result; +} + +static char * +decode_attr(char *source, attr_t *target, int *color) +{ + bool found = FALSE; + + T(("decode_attr '%s'", source)); + + while (*source) { + if (source[0] == MARKER && source[1] == L_CURL) { + source += 2; + found = TRUE; + } else if (source[0] == R_CURL) { + source++; + found = FALSE; + } else if (found) { + size_t n; + char *next = source; + + if (source[0] == GUTTER) { + ++next; + } else if (*next == 'C') { + int value = 0; + unsigned pair; + next++; + while (isdigit(UChar(*next))) { + value = value * 10 + (*next++ - '0'); + } + *target &= ~A_COLOR; + pair = (unsigned) ((value > 256) + ? COLOR_PAIR(255) + : COLOR_PAIR(value)); + *target |= pair; + *color = value; + } else { + while (isalnum(UChar(*next))) { + ++next; + } + for (n = 0; n < SIZEOF(scr_attrs); ++n) { + if ((size_t) (next - source) == strlen(scr_attrs[n].name)) { + if (scr_attrs[n].attr) { + *target |= scr_attrs[n].attr; + } else { + *target = A_NORMAL; + } + break; + } + } + } + source = next; + } else { + break; + } + } + return source; +} + +static char * +decode_char(char *source, int *target) +{ + int limit = 0; + int base = 16; + const char digits[] = "0123456789abcdef"; + + T(("decode_char '%s'", source)); + *target = ' '; + switch (*source) { + case MARKER: + switch (*++source) { + case APPEND: + break; + case MARKER: + *target = MARKER; + ++source; + break; + case 's': + *target = ' '; + ++source; + break; + case '0': + case '1': + case '2': + case '3': + base = 8; + limit = 3; + break; + case 'u': + limit = 4; + ++source; + break; + case 'U': + limit = 8; + ++source; + break; + } + if (limit) { + *target = 0; + while (limit-- > 0) { + char *find = strchr(digits, *source++); + int ch = (find != 0) ? (int) (find - digits) : -1; + *target *= base; + if (ch >= 0 && ch < base) { + *target += ch; + } + } + } + break; + default: + *target = *source++; + break; + } + return source; +} + +static char * +decode_chtype(char *source, chtype fillin, chtype *target) +{ + attr_t attr = ChAttrOf(fillin); + int color = PAIR_NUMBER((int) attr); + int value; + + T(("decode_chtype '%s'", source)); + source = decode_attr(source, &attr, &color); + source = decode_char(source, &value); + *target = (ChCharOf(value) | attr | (chtype) COLOR_PAIR(color)); + /* FIXME - ignore combining characters */ + return source; +} + +#if NCURSES_WIDECHAR +static char * +decode_cchar(char *source, cchar_t *fillin, cchar_t *target) +{ + int color; + attr_t attr = fillin->attr; + wchar_t chars[CCHARW_MAX]; + int append = 0; + int value = 0; + + T(("decode_cchar '%s'", source)); + *target = blank; +#if NCURSES_EXT_COLORS + color = fillin->ext_color; +#else + color = (int) PAIR_NUMBER(attr); +#endif + source = decode_attr(source, &attr, &color); + memset(chars, 0, sizeof(chars)); + source = decode_char(source, &value); + chars[0] = (wchar_t) value; + /* handle combining characters */ + while (source[0] == MARKER && source[1] == APPEND) { + source += 2; + source = decode_char(source, &value); + if (++append < CCHARW_MAX) { + chars[append] = (wchar_t) value; + } + } + setcchar(target, chars, attr, (short) color, &color); + return source; +} +#endif + +static int +read_win(WINDOW *win, FILE *fp) +{ + int code = ERR; + size_t n; + int color; +#if NCURSES_WIDECHAR + NCURSES_CH_T prior; +#endif + chtype prior2; + + memset(win, 0, sizeof(WINDOW)); + for (;;) { + char *name; + char *value; + char *txt = read_txt(fp); + + if (txt == 0) + break; + if (!strcmp(txt, "rows:")) { + free(txt); + code = OK; + break; + } + if ((value = strchr(txt, '=')) == 0) { + free(txt); + continue; + } + *value++ = '\0'; + name = !strcmp(txt, "flag") ? value : txt; + for (n = 0; n < SIZEOF(scr_params); ++n) { + if (!strcmp(name, scr_params[n].name)) { + void *data = (void *) ((char *) win + scr_params[n].offset); + + switch (scr_params[n].type) { + case pATTR: + (void) decode_attr(value, data, &color); + break; + case pBOOL: + *(bool *) data = TRUE; + break; + case pCHAR: + prior2 = ' '; + decode_chtype(value, prior2, data); + break; + case pINT: + *(int *) data = atoi(value); + break; + case pSHORT: + *(short *) data = (short) atoi(value); + break; + case pSIZE: + *(NCURSES_SIZE_T *) data = (NCURSES_SIZE_T) atoi(value); + break; +#if NCURSES_WIDECHAR + case pCCHAR: + prior = blank; + decode_cchar(value, &prior, data); + break; +#endif + } + break; + } + } + free(txt); + } + return code; +} + +static int +read_row(char *source, NCURSES_CH_T * prior, NCURSES_CH_T * target, int length) +{ + while (*source != '\0' && length > 0) { +#if NCURSES_WIDECHAR + int len; + + source = decode_cchar(source, prior, target); + 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]; + SetWidecExt(CHDEREF(target), n); + } + target += (len - 1); + length -= (len - 1); + } +#else + source = decode_chtype(source, *prior, target); +#endif + *prior = *target; + ++target; + --length; + } + while (length-- > 0) { + *target++ = blank; + } + /* FIXME - see what error conditions should apply if I need to return ERR */ + return 0; +} +#endif /* NCURSES_EXT_PUTWIN */ + +/* + * Originally, getwin/putwin used fread/fwrite, because they used binary data. + * The new format uses printable ASCII, which does not have as predictable + * sizes. Consequently, we use buffered I/O, e.g., fgetc/fprintf, which need + * special handling if we want to read screen dumps from an older library. + */ +static int +read_block(void *target, size_t length, FILE *fp) +{ + int result = 0; + char *buffer = target; + + clearerr(fp); + while (length-- != 0) { + int ch = fgetc(fp); + if (ch == EOF) { + result = -1; + break; + } + *buffer++ = (char) ch; + } + return result; +} + NCURSES_EXPORT(WINDOW *) 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)); if (filep == 0) { returnWin(0); } - clearerr(filep); - if (fread(&tmp, (size_t) 1, sizeof(WINDOW), filep) < sizeof(WINDOW) - || ferror(filep) - || tmp._maxy == 0 - || tmp._maxy > MAX_SIZE - || tmp._maxx == 0 - || tmp._maxx > MAX_SIZE) { + + /* + * Read the first 4 bytes to determine first if this is an old-format + * screen-dump, or new-format. + */ + 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, (size_t) 4)) { +#if NCURSES_EXT_PUTWIN + if (read_win(&tmp, filep) < 0) +#endif + returnWin(0); + } else if (read_block(((char *) &tmp) + 4, sizeof(WINDOW) - 4, filep) < 0) { + returnWin(0); + } else { + old_format = TRUE; + } + + /* + * Check the window-size: + */ + if (tmp._maxy == 0 || + tmp._maxy > MAX_SIZE || + tmp._maxx == 0 || + tmp._maxx > MAX_SIZE) { returnWin(0); } @@ -80,6 +557,7 @@ NCURSES_SP_NAME(getwin) (NCURSES_SP_DCLx FILE *filep) * 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; @@ -111,14 +589,55 @@ NCURSES_SP_NAME(getwin) (NCURSES_SP_DCLx FILE *filep) if (tmp._flags & _ISPAD) nwin->_pad = tmp._pad; - for (n = 0; n <= nwin->_maxy; n++) { - clearerr(filep); - if (fread(nwin->_line[n].text, (size_t) 1, linesize, filep) < linesize - || ferror(filep)) { + if (old_format) { + T(("reading old-format screen dump")); + for (n = 0; n <= nwin->_maxy; n++) { + if (read_block(nwin->_line[n].text, linesize, filep) < 0) { + delwin(nwin); + returnWin(0); + } + } + } +#if NCURSES_EXT_PUTWIN + else { + char *txt = 0; + bool success = TRUE; + NCURSES_CH_T prior = blank; + + T(("reading new-format screen dump")); + for (n = 0; n <= nwin->_maxy; n++) { + long row; + char *next; + + if ((txt = read_txt(filep)) == 0) { + T(("...failed to read string for row %d", n + 1)); + success = FALSE; + break; + } + row = strtol(txt, &next, 10); + if (row != (n + 1) || *next != ':') { + T(("...failed to read row-number %d", n + 1)); + success = FALSE; + break; + } + + if (read_row(++next, &prior, nwin->_line[n].text, tmp._maxx + + 1) < 0) { + T(("...failed to read cells for row %d", n + 1)); + success = FALSE; + break; + } + free(txt); + txt = 0; + } + + if (!success) { + free(txt); delwin(nwin); returnWin(0); } } +#endif touchwin(nwin); } returnWin(nwin); @@ -132,24 +651,283 @@ getwin(FILE *filep) } #endif +#if NCURSES_EXT_PUTWIN +static void +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) || (source_color != prior_color)) { + size_t n; + bool first = TRUE; + + *target++ = MARKER; + *target++ = L_CURL; + + for (n = 0; n < SIZEOF(scr_attrs); ++n) { + if ((source & scr_attrs[n].attr) != 0 || + ((source & ALL_BUT_COLOR) == 0 && + (scr_attrs[n].attr == A_NORMAL))) { + if (first) { + first = FALSE; + } else { + *target++ = '|'; + } + _nc_STRCPY(target, scr_attrs[n].name, limit); + target += strlen(target); + } + } + if (source_color != prior_color) { + if (!first) + *target++ = '|'; + _nc_SPRINTF(target, CUR_SLIMIT "C%d", source_color); + target += strlen(target); + } + + *target++ = R_CURL; + *target = '\0'; + } +} + +static void +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) || (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) { + _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) { + unsigned uch = (unsigned) source->chars[n]; + if (uch == 0) + continue; + if (n) { + *target++ = MARKER; + *target++ = APPEND; + } + *target++ = MARKER; + if (uch > 0xffff) { + _nc_SPRINTF(target, CUR_SLIMIT "U%08x", uch); + } else if (uch > 0xff) { + _nc_SPRINTF(target, CUR_SLIMIT "u%04x", uch); + } else if (uch < 32 || uch >= 127) { + _nc_SPRINTF(target, CUR_SLIMIT "%03o", uch & 0xff); + } else { + switch (uch) { + case ' ': + _nc_STRCPY(target, "s", limit); + break; + case MARKER: + *target++ = MARKER; + *target = '\0'; + break; + default: + --target; + _nc_SPRINTF(target, CUR_SLIMIT "%c", uch); + break; + } + } + target += strlen(target); + } +#else + chtype ch = CharOfD(source); + + *target = '\0'; + if (AttrOfD(previous) != AttrOfD(source)) { + encode_attr(target, CUR_SLIMIT + AttrOfD(source), + AttrOfD(previous), + GetPair(source), + GetPair(previous)); + } + target += strlen(target); + *target++ = MARKER; + if (ch < 32 || ch >= 127) { + _nc_SPRINTF(target, CUR_SLIMIT "%03o", UChar(ch)); + } else { + switch (ch) { + case ' ': + _nc_STRCPY(target, "s", limit); + break; + case MARKER: + *target++ = MARKER; + *target = '\0'; + break; + default: + --target; + _nc_SPRINTF(target, CUR_SLIMIT "%c", UChar(ch)); + break; + } + } +#endif +} +#endif + NCURSES_EXPORT(int) putwin(WINDOW *win, FILE *filep) { int code = ERR; - int n; T((T_CALLED("putwin(%p,%p)"), (void *) win, (void *) filep)); +#if NCURSES_EXT_PUTWIN + if (win != 0) { + const char *version = curses_version(); + char buffer[1024]; + NCURSES_CH_T last_cell; + int y; + + memset(&last_cell, 0, sizeof(last_cell)); + + clearerr(filep); + + /* + * Our magic number is technically nonprinting, but aside from that, + * all of the file is printable ASCII. + */ +#define PUTS(s) if (fputs(s, filep) == EOF || ferror(filep)) returnCode(code) + PUTS(my_magic); + PUTS(version); + PUTS("\n"); + for (y = 0; y < (int) SIZEOF(scr_params); ++y) { + 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.", (size_t) 5) && !(win->_flags & _ISPAD)) { + continue; + } + switch (scr_params[y].type) { + case pATTR: + 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; + } + _nc_STRCPY(buffer, name, sizeof(buffer)); + name = "flag"; + break; + case pCHAR: + 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; + _nc_SPRINTF(buffer, TOP_SLIMIT + "%d", *(const int *) dp); + break; + case pSHORT: + if (!(*(const short *) dp)) + continue; + _nc_SPRINTF(buffer, TOP_SLIMIT + "%d", *(const short *) dp); + break; + case pSIZE: + if (!(*(const NCURSES_SIZE_T *) dp)) + continue; + _nc_SPRINTF(buffer, TOP_SLIMIT + "%d", *(const NCURSES_SIZE_T *) dp); + break; +#if NCURSES_WIDECHAR + case pCCHAR: + encode_cell(buffer, TOP_SLIMIT + (CARG_CH_T) dp, CHREF(last_cell)); + break; +#endif + } + /* + * Only write non-default data. + */ + if (*buffer != '\0') { + if (fprintf(filep, "%s=%s\n", name, buffer) <= 0 + || ferror(filep)) + returnCode(code); + } + } + /* Write row-data */ + fprintf(filep, "rows:\n"); + for (y = 0; y <= win->_maxy; y++) { + NCURSES_CH_T *data = win->_line[y].text; + int x; + if (fprintf(filep, "%d:", y + 1) <= 0 + || ferror(filep)) + returnCode(code); + for (x = 0; x <= win->_maxx; x++) { +#if NCURSES_WIDECHAR + 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, TOP_SLIMIT CHREF(data[x]), CHREF(last_cell)); + last_cell = data[x]; + PUTS(buffer); +#endif + } + PUTS("\n"); + } + code = OK; + } +#else + /* + * This is the original putwin(): + * A straight binary dump is simple, but its format can depend on whether + * ncurses is compiled with wide-character support, and also may depend + * on the version of ncurses, e.g., if the WINDOW structure is extended. + */ 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 || ferror(filep)) returnCode(code); - for (n = 0; n <= win->_maxy; n++) { - if (fwrite(win->_line[n].text, + for (y = 0; y <= win->_maxy; y++) { + if (fwrite(win->_line[y].text, sizeof(NCURSES_CH_T), len, filep) != len || ferror(filep)) { returnCode(code); @@ -157,6 +935,7 @@ putwin(WINDOW *win, FILE *filep) } code = OK; } +#endif returnCode(code); } @@ -164,21 +943,23 @@ NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_restore) (NCURSES_SP_DCLx const char *file) { FILE *fp = 0; + int code = ERR; 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) { - returnCode(ERR); - } else { + if (_nc_access(file, R_OK) >= 0 + && (fp = fopen(file, BIN_R)) != 0) { delwin(NewScreen(SP_PARM)); NewScreen(SP_PARM) = getwin(fp); #if !USE_REENTRANT newscr = NewScreen(SP_PARM); #endif (void) fclose(fp); - returnCode(OK); + if (NewScreen(SP_PARM) != 0) { + code = OK; + } } + returnCode(code); } #if NCURSES_SP_FUNCS @@ -198,7 +979,7 @@ scr_dump(const char *file) T((T_CALLED("scr_dump(%s)"), _nc_visbuf(file))); if (_nc_access(file, W_OK) < 0 - || (fp = fopen(file, "wb")) == 0) { + || (fp = fopen(file, BIN_W)) == 0) { result = ERR; } else { (void) putwin(newscr, fp); @@ -211,7 +992,6 @@ scr_dump(const char *file) 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))); @@ -223,15 +1003,19 @@ NCURSES_SP_NAME(scr_init) (NCURSES_SP_DCLx const char *file) !(exit_ca_mode && non_rev_rmcup) #endif ) { + FILE *fp = 0; + if (_nc_access(file, R_OK) >= 0 - && (fp = fopen(file, "rb")) != 0) { + && (fp = fopen(file, BIN_R)) != 0) { delwin(CurScreen(SP_PARM)); CurScreen(SP_PARM) = getwin(fp); #if !USE_REENTRANT curscr = CurScreen(SP_PARM); #endif (void) fclose(fp); - code = OK; + if (CurScreen(SP_PARM) != 0) { + code = OK; + } } } returnCode(code); @@ -248,18 +1032,21 @@ scr_init(const char *file) NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_set) (NCURSES_SP_DCLx const char *file) { + int code = ERR; + T((T_CALLED("scr_set(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file))); - if (NCURSES_SP_NAME(scr_init) (NCURSES_SP_ARGx file) == ERR) { - returnCode(ERR); - } else { + if (NCURSES_SP_NAME(scr_init) (NCURSES_SP_ARGx file) == OK) { delwin(NewScreen(SP_PARM)); NewScreen(SP_PARM) = dupwin(curscr); #if !USE_REENTRANT newscr = NewScreen(SP_PARM); #endif - returnCode(OK); + if (NewScreen(SP_PARM) != 0) { + code = OK; + } } + returnCode(code); } #if NCURSES_SP_FUNCS diff --git a/ncurses/base/lib_scroll.c b/ncurses/base/lib_scroll.c index 8684e2519294f..000f128fb0d63 100644 --- a/ncurses/base/lib_scroll.c +++ b/ncurses/base/lib_scroll.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * + * Copyright (c) 1998-2011,2019 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 * @@ -43,7 +43,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_scroll.c,v 1.29 2011/10/22 16:34:50 tom Exp $") +MODULE_ID("$Id: lib_scroll.c,v 1.31 2019/08/03 22:27:55 tom Exp $") NCURSES_EXPORT(void) _nc_scroll_window(WINDOW *win, @@ -77,11 +77,13 @@ _nc_scroll_window(WINDOW *win, * setup cost. So there is no point in trying to be excessively * clever -- esr. */ +#define BottomLimit(n) ((n) >= 0 && (n) >= top) +#define TopLimit(n) ((n) <= win->_maxy && (n) <= bottom) /* shift n lines downwards */ if (n < 0) { limit = top - n; - for (line = bottom; line >= limit && line >= 0; line--) { + for (line = bottom; line >= limit && BottomLimit(line); line--) { TR(TRACE_MOVE, ("...copying %d to %d", line + n, line)); memcpy(win->_line[line].text, win->_line[line + n].text, @@ -89,7 +91,7 @@ _nc_scroll_window(WINDOW *win, if_USE_SCROLL_HINTS(win->_line[line].oldindex = win->_line[line + n].oldindex); } - for (line = top; line < limit && line <= win->_maxy; line++) { + for (line = top; line < limit && TopLimit(line); line++) { TR(TRACE_MOVE, ("...filling %d", line)); for (j = 0; j <= win->_maxx; j++) win->_line[line].text[j] = blank; @@ -100,14 +102,14 @@ _nc_scroll_window(WINDOW *win, /* shift n lines upwards */ if (n > 0) { limit = bottom - n; - for (line = top; line <= limit && line <= win->_maxy; line++) { + for (line = top; line <= limit && TopLimit(line); line++) { memcpy(win->_line[line].text, win->_line[line + n].text, to_copy); if_USE_SCROLL_HINTS(win->_line[line].oldindex = win->_line[line + n].oldindex); } - for (line = bottom; line > limit && line >= 0; line--) { + for (line = bottom; line > limit && BottomLimit(line); line--) { for (j = 0; j <= win->_maxx; j++) win->_line[line].text[j] = blank; if_USE_SCROLL_HINTS(win->_line[line].oldindex = _NEWINDEX); diff --git a/ncurses/base/lib_set_term.c b/ncurses/base/lib_set_term.c index acf6bc1f71cd1..fb0465a940a6b 100644 --- a/ncurses/base/lib_set_term.c +++ b/ncurses/base/lib_set_term.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * + * Copyright (c) 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 * @@ -43,11 +43,10 @@ #include <curses.priv.h> #include <tic.h> -#ifndef CUR +#undef CUR #define CUR SP_TERMTYPE -#endif -MODULE_ID("$Id: lib_set_term.c,v 1.148 2013/08/31 13:33:06 tom Exp $") +MODULE_ID("$Id: lib_set_term.c,v 1.168 2018/12/15 23:49:43 tom Exp $") #ifdef USE_TERM_DRIVER #define MaxColors InfoOf(sp).maxcolors @@ -134,7 +133,6 @@ delink_screen(SCREEN *sp) NCURSES_EXPORT(void) delscreen(SCREEN *sp) { - int i; T((T_CALLED("delscreen(%p)"), (void *) sp)); @@ -159,7 +157,10 @@ delscreen(SCREEN *sp) (void) _nc_freewin(StdScreen(sp)); if (sp->_slk != 0) { + if (sp->_slk->ent != 0) { + int i; + for (i = 0; i < sp->_slk->labcnt; ++i) { FreeIfNeeded(sp->_slk->ent[i].ent_text); FreeIfNeeded(sp->_slk->ent[i].form_text); @@ -181,6 +182,7 @@ delscreen(SCREEN *sp) FreeIfNeeded(sp->_color_table); FreeIfNeeded(sp->_color_pairs); + FreeIfNeeded(sp->_oldnum_list); FreeIfNeeded(sp->oldhash); FreeIfNeeded(sp->newhash); FreeIfNeeded(sp->hashtab); @@ -190,6 +192,10 @@ delscreen(SCREEN *sp) NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx sp->_term); + FreeIfNeeded(sp->out_buffer); + if (_nc_find_prescr() == sp) { + _nc_forget_prescr(); + } free(sp); /* @@ -206,6 +212,12 @@ delscreen(SCREEN *sp) COLOR_PAIRS = 0; #endif _nc_set_screen(0); +#if USE_WIDEC_SUPPORT + if (SP == 0) { + FreeIfNeeded(_nc_wacs); + _nc_wacs = 0; + } +#endif } } _nc_unlock_global(curses); @@ -242,16 +254,17 @@ no_mouse_wrap(SCREEN *sp GCC_UNUSED) } #if NCURSES_EXT_FUNCS && USE_COLORFGBG -static char * -extract_fgbg(char *src, int *result) +static const char * +extract_fgbg(const char *src, int *result) { - char *dst = 0; - long value = strtol(src, &dst, 0); + const char *dst = 0; + char *tmp = 0; + long value = strtol(src, &tmp, 0); - if (dst == 0) { + if ((dst = tmp) == 0) { dst = src; } else if (value >= 0) { - *result = value; + *result = (int) value; } while (*dst != 0 && *dst != ';') dst++; @@ -261,7 +274,7 @@ extract_fgbg(char *src, int *result) } #endif -#define ReturnScreenError() { _nc_set_screen(0); \ +#define ReturnScreenError() do { _nc_set_screen(0); \ returnCode(ERR); } while (0) /* OS-independent screen initializations */ @@ -276,9 +289,11 @@ NCURSES_SP_NAME(_nc_setupscreen) ( int filtered, int slk_format) { +#ifndef USE_TERM_DRIVER + static const TTY null_TTY; /* all zeros iff uninitialized */ +#endif char *env; int bottom_stolen = 0; - ripoff_t *rop; SCREEN *sp; #ifndef USE_TERM_DRIVER bool support_cookies = USE_XMC_SUPPORT; @@ -295,6 +310,7 @@ NCURSES_SP_NAME(_nc_setupscreen) ( if (!sp) { sp = _nc_alloc_screen_sp(); + T(("_nc_alloc_screen_sp %p", (void *) sp)); *spp = sp; } if (!sp @@ -351,15 +367,21 @@ NCURSES_SP_NAME(_nc_setupscreen) ( slines = 1; SET_LINES(slines); #ifdef USE_TERM_DRIVER - CallDriver(sp, setfilter); + CallDriver(sp, td_setfilter); #else - clear_screen = 0; - cursor_down = parm_down_cursor = 0; - cursor_address = 0; - cursor_up = parm_up_cursor = 0; - row_address = 0; + /* *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; - cursor_home = carriage_return; #endif T(("filter screensize %dx%d", slines, scolumns)); } @@ -411,8 +433,8 @@ NCURSES_SP_NAME(_nc_setupscreen) ( sp->_default_fg = COLOR_WHITE; sp->_default_bg = COLOR_BLACK; #else - sp->_default_fg = C_MASK; - sp->_default_bg = C_MASK; + sp->_default_fg = COLOR_DEFAULT; + sp->_default_bg = COLOR_DEFAULT; #endif /* @@ -424,9 +446,9 @@ NCURSES_SP_NAME(_nc_setupscreen) ( char sep1, sep2; int count = sscanf(env, "%d%c%d%c", &fg, &sep1, &bg, &sep2); if (count >= 1) { - sp->_default_fg = ((fg >= 0 && fg < MaxColors) ? fg : C_MASK); + sp->_default_fg = ((fg >= 0 && fg < MaxColors) ? fg : COLOR_DEFAULT); if (count >= 3) { - sp->_default_bg = ((bg >= 0 && bg < MaxColors) ? bg : C_MASK); + sp->_default_bg = ((bg >= 0 && bg < MaxColors) ? bg : COLOR_DEFAULT); } TR(TRACE_CHARPUT | TRACE_MOVE, ("from environment assumed fg=%d, bg=%d", @@ -442,7 +464,7 @@ NCURSES_SP_NAME(_nc_setupscreen) ( * decide later if it is worth having default attributes as well. */ if (getenv("COLORFGBG") != 0) { - char *p = getenv("COLORFGBG"); + const char *p = getenv("COLORFGBG"); TR(TRACE_CHARPUT | TRACE_MOVE, ("decoding COLORFGBG %s", p)); p = extract_fgbg(p, &(sp->_default_fg)); p = extract_fgbg(p, &(sp->_default_bg)); @@ -453,7 +475,7 @@ NCURSES_SP_NAME(_nc_setupscreen) ( if (sp->_default_fg >= MaxColors) { if (set_a_foreground != ABSENT_STRING && !strcmp(set_a_foreground, "\033[3%p1%dm")) { - set_a_foreground = "\033[3%?%p1%{8}%>%t9%e%p1%d%;m"; + set_a_foreground = strdup("\033[3%?%p1%{8}%>%t9%e%p1%d%;m"); } else { sp->_default_fg %= MaxColors; } @@ -461,7 +483,7 @@ NCURSES_SP_NAME(_nc_setupscreen) ( if (sp->_default_bg >= MaxColors) { if (set_a_background != ABSENT_STRING && !strcmp(set_a_background, "\033[4%p1%dm")) { - set_a_background = "\033[4%?%p1%{8}%>%t9%e%p1%d%;m"; + set_a_background = strdup("\033[4%?%p1%{8}%>%t9%e%p1%d%;m"); } else { sp->_default_bg %= MaxColors; } @@ -573,7 +595,9 @@ NCURSES_SP_NAME(_nc_setupscreen) ( NCURSES_SP_NAME(_nc_init_acs) (NCURSES_SP_ARG); #if USE_WIDEC_SUPPORT sp->_screen_unicode = _nc_unicode_locale(); - _nc_init_wacs(); + if (_nc_wacs == 0) { + _nc_init_wacs(); + } if (_nc_wacs == 0) { ReturnScreenError(); } @@ -617,10 +641,22 @@ NCURSES_SP_NAME(_nc_setupscreen) ( NewScreen(sp)->_clear = TRUE; CurScreen(sp)->_clear = FALSE; - NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG); - NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG); + /* + * Get the current tty-modes. setupterm() may already have done this, + * unless we use the term-driver. + */ +#ifndef USE_TERM_DRIVER + if (cur_term != 0 && + !memcmp(&cur_term->Ottyb, &null_TTY, sizeof(TTY))) +#endif + { + NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG); + NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG); + } if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) { + ripoff_t *rop; + for (rop = safe_ripoff_stack; rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS; rop++) { @@ -714,9 +750,12 @@ NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_DCLx int (*init) (WINDOW *, int)) { int code = ERR; + TR_FUNC_BFR(1); START_TRACE(); - T((T_CALLED("ripoffline(%p,%d,%p)"), (void *) SP_PARM, line, init)); + T((T_CALLED("ripoffline(%p,%d,%s)"), + (void *) SP_PARM, line, + TR_FUNC_ARG(0, init))); #if NCURSES_SP_FUNCS if (SP_PARM != 0 && SP_PARM->_prescreen) @@ -725,12 +764,15 @@ NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_DCLx if (line == 0) { code = OK; } else { - if (safe_ripoff_sp == 0) + if (safe_ripoff_sp == 0) { safe_ripoff_sp = safe_ripoff_stack; + } if (safe_ripoff_sp < safe_ripoff_stack + N_RIPS) { safe_ripoff_sp->line = line; safe_ripoff_sp->hook = init; (safe_ripoff_sp)++; + T(("ripped-off %d:%d chunks", + (int) (safe_ripoff_sp - safe_ripoff_stack), N_RIPS)); code = OK; } } @@ -743,7 +785,12 @@ NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_DCLx NCURSES_EXPORT(int) _nc_ripoffline(int line, int (*init) (WINDOW *, int)) { - return NCURSES_SP_NAME(_nc_ripoffline) (CURRENT_SCREEN_PRE, line, init); + int rc; + _nc_lock_global(prescreen); + START_TRACE(); + rc = NCURSES_SP_NAME(_nc_ripoffline) (CURRENT_SCREEN_PRE, line, init); + _nc_unlock_global(prescreen); + return rc; } #endif @@ -762,6 +809,11 @@ NCURSES_SP_NAME(ripoffline) (NCURSES_SP_DCLx NCURSES_EXPORT(int) ripoffline(int line, int (*init) (WINDOW *, int)) { - return NCURSES_SP_NAME(ripoffline) (CURRENT_SCREEN_PRE, line, init); + int rc; + _nc_lock_global(prescreen); + START_TRACE(); + rc = NCURSES_SP_NAME(ripoffline) (CURRENT_SCREEN_PRE, line, init); + _nc_unlock_global(prescreen); + return rc; } #endif diff --git a/ncurses/base/lib_slkatr_set.c b/ncurses/base/lib_slkatr_set.c index a3132e9ced1a5..fa701f0b10089 100644 --- a/ncurses/base/lib_slkatr_set.c +++ b/ncurses/base/lib_slkatr_set.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2014 Free Software Foundation, Inc. * + * Copyright (c) 1998-2004,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 * @@ -38,30 +38,31 @@ */ #include <curses.priv.h> -MODULE_ID("$Id: lib_slkatr_set.c,v 1.15 2014/02/01 22:10:42 tom Exp $") +MODULE_ID("$Id: lib_slkatr_set.c,v 1.16 2017/03/16 23:45:36 tom Exp $") NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attr_set) (NCURSES_SP_DCLx const attr_t attr, - NCURSES_PAIRS_T color_pair_number, + NCURSES_PAIRS_T pair_arg, void *opts) { int code = ERR; + int color_pair = pair_arg; T((T_CALLED("slk_attr_set(%p,%s,%d)"), (void *) SP_PARM, _traceattr(attr), - (int) color_pair_number)); + color_pair)); + set_extended_pair(opts, color_pair); if (SP_PARM != 0 && SP_PARM->_slk != 0 - && !opts - && color_pair_number >= 0 - && color_pair_number < SP_PARM->_pair_limit) { + && color_pair >= 0 + && color_pair < SP_PARM->_pair_limit) { TR(TRACE_ATTRS, ("... current %s", _tracech_t(CHREF(SP_PARM->_slk->attr)))); SetAttr(SP_PARM->_slk->attr, attr); - if (color_pair_number > 0) { - SetPair(SP_PARM->_slk->attr, color_pair_number); + if (color_pair > 0) { + SetPair(SP_PARM->_slk->attr, color_pair); } TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP_PARM->_slk->attr)))); code = OK; @@ -71,9 +72,9 @@ NCURSES_SP_NAME(slk_attr_set) (NCURSES_SP_DCLx #if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -slk_attr_set(const attr_t attr, NCURSES_COLOR_T color_pair_number, void *opts) +slk_attr_set(const attr_t attr, NCURSES_COLOR_T pair_arg, void *opts) { return NCURSES_SP_NAME(slk_attr_set) (CURRENT_SCREEN, attr, - color_pair_number, opts); + pair_arg, opts); } #endif diff --git a/ncurses/base/lib_slkcolor.c b/ncurses/base/lib_slkcolor.c index 2cf9e5d7f1213..7edbe1afcc938 100644 --- a/ncurses/base/lib_slkcolor.c +++ b/ncurses/base/lib_slkcolor.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2014 Free Software Foundation, Inc. * + * Copyright (c) 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 * @@ -38,31 +38,53 @@ */ #include <curses.priv.h> -MODULE_ID("$Id: lib_slkcolor.c,v 1.17 2014/02/01 22:10:42 tom Exp $") +MODULE_ID("$Id: lib_slkcolor.c,v 1.19 2018/03/01 15:02:12 tom Exp $") -NCURSES_EXPORT(int) -NCURSES_SP_NAME(slk_color) (NCURSES_SP_DCLx NCURSES_PAIRS_T color_pair_number) +static int +_nc_slk_color(SCREEN *sp, int pair_arg) { int code = ERR; - T((T_CALLED("slk_color(%p,%d)"), (void *) SP_PARM, (int) color_pair_number)); + T((T_CALLED("slk_color(%p,%d)"), (void *) sp, pair_arg)); - if (SP_PARM != 0 - && SP_PARM->_slk != 0 - && color_pair_number >= 0 - && color_pair_number < SP_PARM->_pair_limit) { - TR(TRACE_ATTRS, ("... current is %s", _tracech_t(CHREF(SP_PARM->_slk->attr)))); - SetPair(SP_PARM->_slk->attr, color_pair_number); - TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP_PARM->_slk->attr)))); + if (sp != 0 + && sp->_slk != 0 + && pair_arg >= 0 + && pair_arg < sp->_pair_limit) { + TR(TRACE_ATTRS, ("... current is %s", _tracech_t(CHREF(sp->_slk->attr)))); + SetPair(sp->_slk->attr, pair_arg); + TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(sp->_slk->attr)))); code = OK; } returnCode(code); } +NCURSES_EXPORT(int) +NCURSES_SP_NAME(slk_color) (NCURSES_SP_DCLx NCURSES_PAIRS_T pair_arg) +{ + return _nc_slk_color(SP_PARM, pair_arg); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_color(NCURSES_PAIRS_T pair_arg) +{ + return NCURSES_SP_NAME(slk_color) (CURRENT_SCREEN, pair_arg); +} +#endif + +#if NCURSES_EXT_COLORS +NCURSES_EXPORT(int) +NCURSES_SP_NAME(extended_slk_color) (NCURSES_SP_DCLx int pair_arg) +{ + return _nc_slk_color(SP_PARM, pair_arg); +} + #if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -slk_color(NCURSES_PAIRS_T color_pair_number) +extended_slk_color(int pair_arg) { - return NCURSES_SP_NAME(slk_color) (CURRENT_SCREEN, color_pair_number); + return NCURSES_SP_NAME(extended_slk_color) (CURRENT_SCREEN, pair_arg); } #endif +#endif diff --git a/ncurses/base/lib_slkinit.c b/ncurses/base/lib_slkinit.c index 9cbdfea98430b..11bbdef6ccf7c 100644 --- a/ncurses/base/lib_slkinit.c +++ b/ncurses/base/lib_slkinit.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc. * + * Copyright (c) 1998-2009,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 * @@ -40,7 +40,7 @@ */ #include <curses.priv.h> -MODULE_ID("$Id: lib_slkinit.c,v 1.13 2009/10/31 00:10:46 tom Exp $") +MODULE_ID("$Id: lib_slkinit.c,v 1.14 2017/06/30 11:47:34 tom Exp $") #ifdef USE_SP_RIPOFF #define SoftkeyFormat SP_PARM->slk_format @@ -75,6 +75,11 @@ NCURSES_SP_NAME(slk_init) (NCURSES_SP_DCLx int format) NCURSES_EXPORT(int) slk_init(int format) { - return NCURSES_SP_NAME(slk_init) (CURRENT_SCREEN_PRE, format); + int rc; + _nc_lock_global(prescreen); + START_TRACE(); + rc = NCURSES_SP_NAME(slk_init) (CURRENT_SCREEN_PRE, format); + _nc_unlock_global(prescreen); + return rc; } #endif diff --git a/ncurses/base/lib_slkrefr.c b/ncurses/base/lib_slkrefr.c index 6d9fcd63507c7..382f9c4b00f7a 100644 --- a/ncurses/base/lib_slkrefr.c +++ b/ncurses/base/lib_slkrefr.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * + * Copyright (c) 1998-2013,2014 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 * @@ -43,7 +43,7 @@ #define CUR SP_TERMTYPE #endif -MODULE_ID("$Id: lib_slkrefr.c,v 1.29 2013/01/12 17:25:48 tom Exp $") +MODULE_ID("$Id: lib_slkrefr.c,v 1.30 2014/03/08 20:32:59 tom Exp $") #ifdef USE_TERM_DRIVER #define NumLabels InfoOf(SP_PARM).numlabels @@ -97,7 +97,7 @@ slk_intern_refresh(SCREEN *sp) if (slk->ent[i].visible) { if (numlab > 0 && SLK_STDFMT(fmt)) { #ifdef USE_TERM_DRIVER - CallDriver_2(sp, hwlabel, i + 1, slk->ent[i].form_text); + CallDriver_2(sp, td_hwlabel, i + 1, slk->ent[i].form_text); #else if (i < num_labels) { NCURSES_PUTP2("plab_norm", @@ -125,7 +125,7 @@ slk_intern_refresh(SCREEN *sp) if (numlab > 0) { #ifdef USE_TERM_DRIVER - CallDriver_1(sp, hwlabelOnOff, slk->hidden ? FALSE : TRUE); + CallDriver_1(sp, td_hwlabelOnOff, slk->hidden ? FALSE : TRUE); #else if (slk->hidden) { NCURSES_PUTP2("label_off", label_off); diff --git a/ncurses/base/lib_slkset.c b/ncurses/base/lib_slkset.c index 9091e001a91d6..66a4d043a6878 100644 --- a/ncurses/base/lib_slkset.c +++ b/ncurses/base/lib_slkset.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc. * + * Copyright (c) 1998-2012,2019 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 * @@ -44,7 +44,7 @@ #endif #endif -MODULE_ID("$Id: lib_slkset.c,v 1.24 2012/12/08 23:09:25 tom Exp $") +MODULE_ID("$Id: lib_slkset.c,v 1.25 2019/05/04 20:46:24 tom Exp $") NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_set) (NCURSES_SP_DCLx int i, const char *astr, int format) @@ -89,9 +89,9 @@ NCURSES_SP_NAME(slk_set) (NCURSES_SP_DCLx int i, const char *astr, int format) mbrtowc(&wc, p, need, &state); if (!iswprint((wint_t) wc)) break; - if (wcwidth(wc) + numcols > limit) + if (_nc_wacs_width(wc) + numcols > limit) break; - numcols += wcwidth(wc); + numcols += _nc_wacs_width(wc); p += need; } numchrs = (int) (p - str); diff --git a/ncurses/base/lib_touch.c b/ncurses/base/lib_touch.c index 20ac9450f15f6..451606483b86f 100644 --- a/ncurses/base/lib_touch.c +++ b/ncurses/base/lib_touch.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2010,2012 Free Software Foundation, Inc. * + * Copyright (c) 1998-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 * @@ -43,16 +43,19 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_touch.c,v 1.12 2012/06/09 20:29:33 tom Exp $") +MODULE_ID("$Id: lib_touch.c,v 1.15 2017/11/21 00:14:26 tom Exp $") + +#undef is_linetouched NCURSES_EXPORT(bool) is_linetouched(WINDOW *win, int line) { T((T_CALLED("is_linetouched(%p,%d)"), (void *) win, line)); - /* XSI doesn't define any error */ - if (!win || (line > win->_maxy) || (line < 0)) - returnCode((bool) ERR); + /* XSI doesn't define any error, and gcc ultimately made it impossible */ + if (!win || (line > win->_maxy) || (line < 0)) { + returnCode(FALSE); + } returnCode(win->_line[line].firstchar != _NOCHANGE ? TRUE : FALSE); } @@ -60,14 +63,15 @@ is_linetouched(WINDOW *win, int line) NCURSES_EXPORT(bool) is_wintouched(WINDOW *win) { - int i; - T((T_CALLED("is_wintouched(%p)"), (void *) win)); - if (win) + if (win) { + int i; + for (i = 0; i <= win->_maxy; i++) if (win->_line[i].firstchar != _NOCHANGE) returnCode(TRUE); + } returnCode(FALSE); } diff --git a/ncurses/base/lib_vline.c b/ncurses/base/lib_vline.c index 2f3148eca77c6..acb5dfd125f88 100644 --- a/ncurses/base/lib_vline.c +++ b/ncurses/base/lib_vline.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. * + * Copyright (c) 1998-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 * @@ -29,6 +29,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * + * and: Sven Verdoolaege 2001 * ****************************************************************************/ /* @@ -40,22 +42,21 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_vline.c,v 1.12 2010/12/19 01:22:58 tom Exp $") +MODULE_ID("$Id: lib_vline.c,v 1.14 2017/10/28 19:55:44 tom Exp $") NCURSES_EXPORT(int) wvline(WINDOW *win, chtype ch, int n) { int code = ERR; - int row, col; - int end; T((T_CALLED("wvline(%p,%s,%d)"), (void *) win, _tracechtype(ch), n)); if (win) { NCURSES_CH_T wch; - row = win->_cury; - col = win->_curx; - end = row + n - 1; + int row = win->_cury; + int col = win->_curx; + int end = row + n - 1; + if (end > win->_maxy) end = win->_maxy; @@ -67,6 +68,14 @@ wvline(WINDOW *win, chtype ch, int n) while (end >= row) { struct ldat *line = &(win->_line[end]); +#if USE_WIDEC_SUPPORT + if (col > 0 && isWidecExt(line->text[col])) { + SetChar2(line->text[col - 1], ' '); + } + if (col < win->_maxx && isWidecExt(line->text[col + 1])) { + SetChar2(line->text[col + 1], ' '); + } +#endif line->text[col] = wch; CHANGED_CELL(line, col); end--; diff --git a/ncurses/base/lib_window.c b/ncurses/base/lib_window.c index 4baa36943c44a..d755e88d66a38 100644 --- a/ncurses/base/lib_window.c +++ b/ncurses/base/lib_window.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. * + * Copyright (c) 1998-2010,2016 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 * @@ -39,7 +39,7 @@ #include <curses.priv.h> -MODULE_ID("$Id: lib_window.c,v 1.29 2010/12/19 01:47:22 tom Exp $") +MODULE_ID("$Id: lib_window.c,v 1.30 2016/05/28 23:11:26 tom Exp $") NCURSES_EXPORT(void) _nc_synchook(WINDOW *win) @@ -56,7 +56,6 @@ mvderwin(WINDOW *win, int y, int x) /* move a derived window */ { WINDOW *orig; - int i; int rc = ERR; T((T_CALLED("mvderwin(%p,%d,%d)"), (void *) win, y, x)); @@ -66,6 +65,8 @@ mvderwin(WINDOW *win, int y, int x) && (x >= 0 && y >= 0) && (x + getmaxx(win) <= getmaxx(orig)) && (y + getmaxy(win) <= getmaxy(orig))) { + int i; + wsyncup(win); win->_parx = x; win->_pary = y; @@ -177,8 +178,6 @@ dupwin(WINDOW *win) /* make an exact duplicate of the given window */ { WINDOW *nwin = 0; - size_t linesize; - int i; T((T_CALLED("dupwin(%p)"), (void *) win)); @@ -200,6 +199,8 @@ dupwin(WINDOW *win) } if (nwin != 0) { + int i; + size_t linesize; nwin->_curx = win->_curx; nwin->_cury = win->_cury; diff --git a/ncurses/base/new_pair.c b/ncurses/base/new_pair.c new file mode 100644 index 0000000000000..2c3c2fb82a2d4 --- /dev/null +++ b/ncurses/base/new_pair.c @@ -0,0 +1,385 @@ +/**************************************************************************** + * Copyright (c) 2017-2018,2019 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: Thomas E. Dickey * + ****************************************************************************/ + +/* new_pair.c + * + * New color-pair functions, alloc_pair and free_pair + */ + +#define NEW_PAIR_INTERNAL 1 +#include <curses.priv.h> + +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +#ifdef USE_TERM_DRIVER +#define MaxColors InfoOf(SP_PARM).maxcolors +#else +#define MaxColors max_colors +#endif + +#if NCURSES_EXT_COLORS + +/* fix redefinition versys tic.h */ +#undef entry +#define entry my_entry +#undef ENTRY +#define ENTRY my_ENTRY + +#include <search.h> + +#endif + +MODULE_ID("$Id: new_pair.c,v 1.18 2019/01/21 14:54:47 tom Exp $") + +#if NCURSES_EXT_COLORS + +#ifdef NEW_PAIR_DEBUG + +static int +prev_len(SCREEN *sp, int pair) +{ + int result = 1; + int base = pair; + colorpair_t *list = sp->_color_pairs; + while (list[pair].prev != base) { + result++; + pair = list[pair].prev; + } + return result; +} + +static int +next_len(SCREEN *sp, int pair) +{ + int result = 1; + int base = pair; + colorpair_t *list = sp->_color_pairs; + while (list[pair].next != base) { + result++; + pair = list[pair].next; + } + return result; +} + +/* + * Trace the contents of LRU color-pairs. + */ +static void +dumpit(SCREEN *sp, int pair, const char *tag) +{ + colorpair_t *list = sp->_color_pairs; + char bigbuf[256 * 20]; + char *p = bigbuf; + int n; + size_t have = sizeof(bigbuf); + + _nc_STRCPY(p, tag, have); + for (n = 0; n < sp->_pair_limit; ++n) { + if (list[n].mode != cpFREE) { + p += strlen(p); + if ((size_t) (p - bigbuf) + 50 > have) + break; + _nc_SPRINTF(p, _nc_SLIMIT(have - (p - bigbuf)) + " %d%c(%d,%d)", + n, n == pair ? '@' : ':', list[n].next, list[n].prev); + } + } + T(("(%d/%d) %ld - %s", + next_len(sp, 0), + prev_len(sp, 0), + strlen(bigbuf), bigbuf)); + + if (next_len(sp, 0) != prev_len(sp, 0)) { + endwin(); + ExitProgram(EXIT_FAILURE); + } +} +#else +#define dumpit(sp, pair, tag) /* nothing */ +#endif + +static int +compare_data(const void *a, const void *b) +{ + const colorpair_t *p = (const colorpair_t *) a; + const colorpair_t *q = (const colorpair_t *) b; + return ((p->fg == q->fg) + ? (p->bg - q->bg) + : (p->fg - q->fg)); +} + +static int +_nc_find_color_pair(SCREEN *sp, int fg, int bg) +{ + colorpair_t find; + int result; + void *pp; + + find.fg = fg; + find.bg = bg; + if (sp != 0 && + (pp = tfind(&find, &sp->_ordered_pairs, compare_data)) != 0) { + colorpair_t *temp = *(colorpair_t **) pp; + result = (int) (temp - sp->_color_pairs); + } else { + result = -1; + } + return result; +} + +static void +delink_color_pair(SCREEN *sp, int pair) +{ + colorpair_t *list = sp->_color_pairs; + int prev = list[pair].prev; + int next = list[pair].next; + + /* delink this from its current location */ + if (list[prev].next == pair && + list[next].prev == pair) { + list[prev].next = next; + list[next].prev = prev; + dumpit(sp, pair, "delinked"); + } +} + +/* + * Discard all nodes in the fast-index. + */ +NCURSES_EXPORT(void) +_nc_free_ordered_pairs(SCREEN *sp) +{ + if (sp && sp->_ordered_pairs && sp->_pair_alloc) { + int n; + for (n = 0; n < sp->_pair_alloc; ++n) { + tdelete(&sp->_color_pairs[n], &sp->_ordered_pairs, compare_data); + } + } +} + +/* + * Use this call to update the fast-index when modifying an entry in the color + * pair table. + */ +NCURSES_EXPORT(void) +_nc_reset_color_pair(SCREEN *sp, int pair, colorpair_t * next) +{ + colorpair_t *last; + if (ValidPair(sp, pair)) { + ReservePairs(sp, pair); + last = &(sp->_color_pairs[pair]); + delink_color_pair(sp, pair); + if (last->mode > cpFREE && + (last->fg != next->fg || last->bg != next->bg)) { + /* remove the old entry from fast index */ + tdelete(last, &sp->_ordered_pairs, compare_data); + /* create a new entry in fast index */ + *last = *next; + tsearch(last, &sp->_ordered_pairs, compare_data); + } + } +} + +/* + * Use this call to relink the newest pair to the front of the list, keeping + * "0" first. + */ +NCURSES_EXPORT(void) +_nc_set_color_pair(SCREEN *sp, int pair, int mode) +{ + if (ValidPair(sp, pair)) { + colorpair_t *list = sp->_color_pairs; + dumpit(sp, pair, "SET_PAIR"); + list[0].mode = cpKEEP; + if (list[pair].mode <= cpFREE) + sp->_pairs_used++; + list[pair].mode = mode; + if (list[0].next != pair) { + /* link it at the front of the list */ + list[pair].next = list[0].next; + list[list[pair].next].prev = pair; + list[pair].prev = 0; + list[0].next = pair; + } + dumpit(sp, pair, "...after"); + } +} + +/* + * If we reallocate the color-pair array, we have to adjust the fast-index. + */ +NCURSES_EXPORT(void) +_nc_copy_pairs(SCREEN *sp, colorpair_t * target, colorpair_t * source, int length) +{ + int n; + for (n = 0; n < length; ++n) { + void *find = tfind(source + n, &sp->_ordered_pairs, compare_data); + if (find != 0) { + tdelete(source + n, &sp->_ordered_pairs, compare_data); + tsearch(target + n, &sp->_ordered_pairs, compare_data); + } + } +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(alloc_pair) (NCURSES_SP_DCLx int fg, int bg) +{ + int pair; + + T((T_CALLED("alloc_pair(%d,%d)"), fg, bg)); + if (SP_PARM == 0) { + pair = -1; + } else if ((pair = _nc_find_color_pair(SP_PARM, fg, bg)) < 0) { + /* + * Check if all of the slots have been used. If not, find one and + * use that. + */ + if (SP_PARM->_pairs_used + 1 < SP_PARM->_pair_limit) { + bool found = FALSE; + int hint = SP_PARM->_recent_pair; + + /* + * The linear search is done to allow mixing calls to init_pair() + * and alloc_pair(). The former can make gaps... + */ + for (pair = hint + 1; pair < SP_PARM->_pair_alloc; pair++) { + if (SP_PARM->_color_pairs[pair].mode == cpFREE) { + T(("found gap %d", pair)); + found = TRUE; + break; + } + } + if (!found && (SP_PARM->_pair_alloc < SP_PARM->_pair_limit)) { + pair = SP_PARM->_pair_alloc; + ReservePairs(SP_PARM, pair); + if (SP_PARM->_color_pairs == 0) { + pair = -1; + } else { + found = TRUE; + } + } + if (!found) { + for (pair = 1; pair <= hint; pair++) { + if (SP_PARM->_color_pairs[pair].mode == cpFREE) { + T(("found gap %d", pair)); + found = TRUE; + break; + } + } + } + if (found) { + SP_PARM->_recent_pair = pair; + } else { + pair = ERR; + } + } else { + /* reuse the oldest one */ + pair = SP_PARM->_color_pairs[0].prev; + T(("reusing %d", pair)); + } + + if (_nc_init_pair(SP_PARM, pair, fg, bg) == ERR) + pair = ERR; + } + returnCode(pair); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(find_pair) (NCURSES_SP_DCLx int fg, int bg) +{ + int pair; + + T((T_CALLED("find_pair(%d,%d)"), fg, bg)); + pair = _nc_find_color_pair(SP_PARM, fg, bg); + returnCode(pair); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(free_pair) (NCURSES_SP_DCLx int pair) +{ + int result = ERR; + T((T_CALLED("free_pair(%d)"), pair)); + if (ValidPair(SP_PARM, pair) && pair < SP_PARM->_pair_alloc) { + colorpair_t *cp = &(SP_PARM->_color_pairs[pair]); + if (pair != 0) { + _nc_change_pair(SP_PARM, pair); + delink_color_pair(SP_PARM, pair); + tdelete(cp, &SP_PARM->_ordered_pairs, compare_data); + cp->mode = cpFREE; + result = OK; + SP_PARM->_pairs_used--; + } + } + returnCode(result); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +alloc_pair(int f, int b) +{ + return NCURSES_SP_NAME(alloc_pair) (CURRENT_SCREEN, f, b); +} + +NCURSES_EXPORT(int) +find_pair(int f, int b) +{ + return NCURSES_SP_NAME(find_pair) (CURRENT_SCREEN, f, b); +} + +NCURSES_EXPORT(int) +free_pair(int pair) +{ + return NCURSES_SP_NAME(free_pair) (CURRENT_SCREEN, pair); +} +#endif + +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_new_pair_leaks(SCREEN *sp) +{ + if (sp->_color_pairs) { + while (sp->_color_pairs[0].next) { + free_pair(sp->_color_pairs[0].next); + } + } +} +#endif + +#else +void _nc_new_pair(void); +void +_nc_new_pair(void) +{ +} +#endif /* NCURSES_EXT_COLORS */ diff --git a/ncurses/base/resizeterm.c b/ncurses/base/resizeterm.c index 03d52a448b093..c99109a69dff7 100644 --- a/ncurses/base/resizeterm.c +++ b/ncurses/base/resizeterm.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2009,2011 Free Software Foundation, Inc. * + * Copyright (c) 1998-2015,2016 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 * @@ -45,7 +45,7 @@ #define CUR SP_TERMTYPE #endif -MODULE_ID("$Id: resizeterm.c,v 1.45 2012/07/07 17:07:23 tom Exp $") +MODULE_ID("$Id: resizeterm.c,v 1.49 2016/05/28 23:11:26 tom Exp $") /* * If we're trying to be reentrant, do not want any local statics. @@ -62,6 +62,12 @@ static int current_cols; #define EXTRA_DCLS /* nothing */ #endif +#if NCURSES_SP_FUNCS && !defined(USE_SP_WINDOWLIST) +#define UNUSED_SP (void) sp +#else +#define UNUSED_SP /* nothing */ +#endif + #ifdef TRACE static void show_window_sizes(const char *name) @@ -140,9 +146,10 @@ static int ripped_bottom(WINDOW *win) { int result = 0; - ripoff_t *rop; if (win != 0) { + ripoff_t *rop; + #ifdef USE_SP_RIPOFF SCREEN *sp = _nc_screen_of(win); #endif @@ -276,6 +283,7 @@ decrease_size(NCURSES_SP_DCLx int ToLines, int ToCols, int stolen EXTRA_DCLS) WINDOWLIST *wp; T((T_CALLED("decrease_size(%p, %d, %d)"), (void *) SP_PARM, ToLines, ToCols)); + UNUSED_SP; do { found = FALSE; @@ -310,6 +318,7 @@ increase_size(NCURSES_SP_DCLx int ToLines, int ToCols, int stolen EXTRA_DCLS) WINDOWLIST *wp; T((T_CALLED("increase_size(%p, %d, %d)"), (void *) SP_PARM, ToLines, ToCols)); + UNUSED_SP; do { found = FALSE; @@ -347,7 +356,7 @@ NCURSES_SP_NAME(resize_term) (NCURSES_SP_DCLx int ToLines, int ToCols) (SP_PARM == 0) ? -1 : screen_lines(SP_PARM), (SP_PARM == 0) ? -1 : screen_columns(SP_PARM))); - if (SP_PARM == 0) { + if (SP_PARM == 0 || ToLines <= 0 || ToCols <= 0) { returnCode(ERR); } @@ -397,7 +406,7 @@ NCURSES_SP_NAME(resize_term) (NCURSES_SP_DCLx int ToLines, int ToCols) screen_columns(SP_PARM) = (NCURSES_SIZE_T) ToCols; #ifdef USE_TERM_DRIVER - CallDriver_2(SP_PARM, setsize, ToLines, ToCols); + CallDriver_2(SP_PARM, td_setsize, ToLines, ToCols); #else lines = (NCURSES_SIZE_T) ToLines; columns = (NCURSES_SIZE_T) ToCols; @@ -440,7 +449,7 @@ NCURSES_SP_NAME(resize_term) (NCURSES_SP_DCLx int ToLines, int ToCols) NCURSES_EXPORT(int) resize_term(int ToLines, int ToCols) { - int res = ERR; + int res; _nc_sp_lock_global(curses); res = NCURSES_SP_NAME(resize_term) (CURRENT_SCREEN, ToLines, ToCols); _nc_sp_unlock_global(curses); @@ -466,7 +475,7 @@ NCURSES_SP_NAME(resizeterm) (NCURSES_SP_DCLx int ToLines, int ToCols) (SP_PARM == 0) ? -1 : screen_lines(SP_PARM), (SP_PARM == 0) ? -1 : screen_columns(SP_PARM))); - if (SP_PARM != 0) { + if (SP_PARM != 0 && ToLines > 0 && ToCols > 0) { result = OK; SP_PARM->_sig_winch = FALSE; diff --git a/ncurses/base/safe_sprintf.c b/ncurses/base/safe_sprintf.c index 34abd2f8cf474..e41da4ac27d17 100644 --- a/ncurses/base/safe_sprintf.c +++ b/ncurses/base/safe_sprintf.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * + * Copyright (c) 1998-2013,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 * @@ -33,7 +33,7 @@ #include <curses.priv.h> #include <ctype.h> -MODULE_ID("$Id: safe_sprintf.c,v 1.27 2013/01/20 01:04:32 tom Exp $") +MODULE_ID("$Id: safe_sprintf.c,v 1.32 2018/12/15 22:26:38 tom Exp $") #if USE_SAFE_SPRINTF @@ -41,7 +41,7 @@ typedef enum { Flags, Width, Prec, Type, Format } PRINTF; -#define VA_INTGR(type) ival = va_arg(ap, type) +#define VA_INTGR(type) ival = (int) va_arg(ap, type) #define VA_FLOAT(type) fval = va_arg(ap, type) #define VA_POINT(type) pval = (void *)va_arg(ap, type) @@ -157,9 +157,9 @@ _nc_printf_length(const char *fmt, va_list ap) case 's': VA_POINT(char *); if (prec < 0) - prec = strlen(pval); + prec = (int) strlen(pval); if (prec > (int) length) { - length = length + prec; + length = length + (size_t) prec; buffer = typeRealloc(char, length, buffer); if (buffer == 0) { free(format); @@ -224,7 +224,7 @@ NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_DCLx { char *result = 0; - if (fmt != 0) { + if (SP_PARM != 0 && fmt != 0) { #if USE_SAFE_SPRINTF va_list ap2; int len; @@ -234,7 +234,7 @@ NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_DCLx end_va_copy(ap2); if ((int) my_length < len + 1) { - my_length = 2 * (len + 1); + my_length = (size_t) (2 * (len + 1)); my_buffer = typeRealloc(char, my_length, my_buffer); } if (my_buffer != 0) { @@ -259,9 +259,9 @@ NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_DCLx if (my_buffer != 0) { # if HAVE_VSNPRINTF - vsnprintf(my_buffer, my_length, fmt, ap); /* GNU extension */ + vsnprintf(my_buffer, my_length, fmt, ap); /* SUSv2, 1997 */ # else - vsprintf(my_buffer, fmt, ap); /* ANSI */ + vsprintf(my_buffer, fmt, ap); /* ISO/ANSI C, 1989 */ # endif result = my_buffer; } diff --git a/ncurses/base/use_window.c b/ncurses/base/use_window.c index 8eb733919848a..c3a5b7237e617 100644 --- a/ncurses/base/use_window.c +++ b/ncurses/base/use_window.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 2007-2008,2009 Free Software Foundation, Inc. * + * Copyright (c) 2007-2016,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 * @@ -32,14 +32,19 @@ #include <curses.priv.h> -MODULE_ID("$Id: use_window.c,v 1.9 2009/10/24 22:40:24 tom Exp $") +MODULE_ID("$Id: use_window.c,v 1.12 2018/12/15 23:53:20 tom Exp $") NCURSES_EXPORT(int) use_window(WINDOW *win, NCURSES_WINDOW_CB func, void *data) { int code = OK; + TR_FUNC_BFR(1); + + T((T_CALLED("use_window(%p,%s,%p)"), + (void *) win, + TR_FUNC_ARG(0, func), + data)); - T((T_CALLED("use_window(%p,%p,%p)"), (void *) win, func, data)); _nc_lock_global(curses); code = func(win, data); _nc_unlock_global(curses); diff --git a/ncurses/base/wresize.c b/ncurses/base/wresize.c index bc6b5732ea41f..ee0594034d375 100644 --- a/ncurses/base/wresize.c +++ b/ncurses/base/wresize.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * + * Copyright (c) 1998-2011,2019 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 * @@ -33,13 +33,13 @@ #include <curses.priv.h> -MODULE_ID("$Id: wresize.c,v 1.35 2011/05/21 18:55:07 tom Exp $") +MODULE_ID("$Id: wresize.c,v 1.38 2019/05/11 20:15:15 tom Exp $") static int cleanup_lines(struct ldat *data, int length) { while (--length >= 0) - free(data[length].text); + FreeAndNull(data[length].text); free(data); return ERR; } @@ -65,15 +65,29 @@ repair_subwindows(WINDOW *cmp) if (tst->_parent == cmp) { - if (tst->_pary > cmp->_maxy) - tst->_pary = cmp->_maxy; - if (tst->_parx > cmp->_maxx) - tst->_parx = cmp->_maxx; +#define REPAIR1(field, limit) \ + if (tst->field > cmp->limit) \ + tst->field = cmp->limit - if (tst->_maxy + tst->_pary > cmp->_maxy) - tst->_maxy = (NCURSES_SIZE_T) (cmp->_maxy - tst->_pary); - if (tst->_maxx + tst->_parx > cmp->_maxx) - tst->_maxx = (NCURSES_SIZE_T) (cmp->_maxx - tst->_parx); + REPAIR1(_pary, _maxy); + REPAIR1(_parx, _maxx); + +#define REPAIR2(field, limit) \ + if (tst->limit + tst->field > cmp->limit) \ + tst->limit = (NCURSES_SIZE_T) (cmp->limit - tst->field) + + REPAIR2(_pary, _maxy); + REPAIR2(_parx, _maxx); + +#define REPAIR3(field, limit) \ + if (tst->field > tst->limit) \ + tst->field = tst->limit + + REPAIR3(_cury, _maxy); + REPAIR3(_curx, _maxx); + + REPAIR3(_regtop, _maxy); + REPAIR3(_regbottom, _maxy); for (row = 0; row <= tst->_maxy; ++row) { tst->_line[row].text = &pline[tst->_pary + row].text[tst->_parx]; @@ -204,16 +218,16 @@ wresize(WINDOW *win, int ToLines, int ToCols) if (!(win->_flags & _SUBWIN)) { if (ToCols == size_x) { for (row = ToLines + 1; row <= size_y; row++) { - free(win->_line[row].text); + FreeAndNull(win->_line[row].text); } } else { for (row = 0; row <= size_y; row++) { - free(win->_line[row].text); + FreeAndNull(win->_line[row].text); } } } - free(win->_line); + FreeAndNull(win->_line); win->_line = new_lines; /* |
