From 8bc7d63560024681dce9f40445f2877b2987e92c Mon Sep 17 00:00:00 2001 From: Masayuki Yamamoto Date: Wed, 1 Nov 2017 21:05:26 +0900 Subject: [PATCH] bpo-25720: Fix the method for checking pad state of curses WINDOW (#4164) Modify the code to use ncurses is_pad() instead of checking WINDOW _flags field. If your platform does not provide the is_pad(), the existing way that checks the field will be enabled. Note: This change does not drop support for platforms where do not have both WINDOW _flags field and is_pad(). --- Include/py_curses.h | 19 +++++---- .../2017-10-29-17-52-40.bpo-25720.vSvb5h.rst | 2 + Modules/_cursesmodule.c | 24 ++++++++---- configure | 39 ++++++++++++++++++- configure.ac | 20 +++++++++- pyconfig.h.in | 3 ++ 6 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-10-29-17-52-40.bpo-25720.vSvb5h.rst diff --git a/Include/py_curses.h b/Include/py_curses.h index 2e88112259a..597f419eaca 100644 --- a/Include/py_curses.h +++ b/Include/py_curses.h @@ -10,11 +10,6 @@ #ifdef _BSD_WCHAR_T_DEFINED_ #define _WCHAR_T #endif - -/* the following define is necessary for OS X 10.6; without it, the - Apple-supplied ncurses.h sets NCURSES_OPAQUE to 1, and then Python - can't get at the WINDOW flags field. */ -#define NCURSES_OPAQUE 0 #endif /* __APPLE__ */ #ifdef __FreeBSD__ @@ -44,6 +39,13 @@ #endif #endif +#if !defined(HAVE_CURSES_IS_PAD) && defined(WINDOW_HAS_FLAGS) +/* The following definition is necessary for ncurses 5.7; without it, + some of [n]curses.h set NCURSES_OPAQUE to 1, and then Python + can't get at the WINDOW flags field. */ +#define NCURSES_OPAQUE 0 +#endif + #ifdef HAVE_NCURSES_H #include #else @@ -52,10 +54,13 @@ #ifdef HAVE_NCURSES_H /* configure was checking , but we will - use , which has all these features. */ -#ifndef WINDOW_HAS_FLAGS + use , which has some or all these features. */ +#if !defined(WINDOW_HAS_FLAGS) && !(NCURSES_OPAQUE+0) #define WINDOW_HAS_FLAGS 1 #endif +#if !defined(HAVE_CURSES_IS_PAD) && NCURSES_VERSION_PATCH+0 >= 20090906 +#define HAVE_CURSES_IS_PAD 1 +#endif #ifndef MVWDELCH_IS_EXPRESSION #define MVWDELCH_IS_EXPRESSION 1 #endif diff --git a/Misc/NEWS.d/next/Library/2017-10-29-17-52-40.bpo-25720.vSvb5h.rst b/Misc/NEWS.d/next/Library/2017-10-29-17-52-40.bpo-25720.vSvb5h.rst new file mode 100644 index 00000000000..a405cd4b544 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-10-29-17-52-40.bpo-25720.vSvb5h.rst @@ -0,0 +1,2 @@ +Fix the method for checking pad state of curses WINDOW. Patch by Masayuki +Yamamoto. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index d30bd1ab20f..2a2eed2c487 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -934,6 +934,12 @@ int py_mvwdelch(WINDOW *w, int y, int x) } #endif +#if defined(HAVE_CURSES_IS_PAD) +#define py_is_pad(win) is_pad(win) +#elif defined(WINDOW_HAS_FLAGS) +#define py_is_pad(win) ((win) ? ((win)->_flags & _ISPAD) != 0 : FALSE) +#endif + /* chgat, added by Fabian Kreutz */ static PyObject * @@ -1073,10 +1079,11 @@ PyCursesWindow_EchoChar(PyCursesWindowObject *self, PyObject *args) if (!PyCurses_ConvertToChtype(self, temp, &ch)) return NULL; -#ifdef WINDOW_HAS_FLAGS - if (self->win->_flags & _ISPAD) +#ifdef py_is_pad + if (py_is_pad(self->win)) { return PyCursesCheckERR(pechochar(self->win, ch | attr), "echochar"); + } else #endif return PyCursesCheckERR(wechochar(self->win, ch | attr), @@ -1603,10 +1610,10 @@ PyCursesWindow_NoOutRefresh(PyCursesWindowObject *self, PyObject *args) int pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol; int rtn; -#ifndef WINDOW_HAS_FLAGS +#ifndef py_is_pad if (0) #else - if (self->win->_flags & _ISPAD) + if (py_is_pad(self->win)) #endif { switch(PyTuple_Size(args)) { @@ -1766,10 +1773,10 @@ PyCursesWindow_Refresh(PyCursesWindowObject *self, PyObject *args) int pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol; int rtn; -#ifndef WINDOW_HAS_FLAGS +#ifndef py_is_pad if (0) #else - if (self->win->_flags & _ISPAD) + if (py_is_pad(self->win)) #endif { switch(PyTuple_Size(args)) { @@ -1835,9 +1842,10 @@ PyCursesWindow_SubWin(PyCursesWindowObject *self, PyObject *args) } /* printf("Subwin: %i %i %i %i \n", nlines, ncols, begin_y, begin_x); */ -#ifdef WINDOW_HAS_FLAGS - if (self->win->_flags & _ISPAD) +#ifdef py_is_pad + if (py_is_pad(self->win)) { win = subpad(self->win, nlines, ncols, begin_y, begin_x); + } else #endif win = subwin(self->win, nlines, ncols, begin_y, begin_x); diff --git a/configure b/configure index bb7cc51407a..00cfd64a2bd 100755 --- a/configure +++ b/configure @@ -15699,6 +15699,10 @@ $as_echo "#define MVWDELCH_IS_EXPRESSION 1" >>confdefs.h fi +# Issue #25720: ncurses has introduced the NCURSES_OPAQUE symbol making opaque +# structs since version 5.7. If the macro is defined as zero before including +# [n]curses.h, ncurses will expose fields of the structs regardless of the +# configuration. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether WINDOW has _flags" >&5 $as_echo_n "checking whether WINDOW has _flags... " >&6; } if ${ac_cv_window_has_flags+:} false; then : @@ -15706,7 +15710,10 @@ if ${ac_cv_window_has_flags+:} false; then : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + + #define NCURSES_OPAQUE 0 + #include + int main () { @@ -15737,6 +15744,36 @@ $as_echo "#define WINDOW_HAS_FLAGS 1" >>confdefs.h fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for is_pad" >&5 +$as_echo_n "checking for is_pad... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef is_pad +void *x=is_pad +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_CURSES_IS_PAD 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for is_term_resized" >&5 $as_echo_n "checking for is_term_resized... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext diff --git a/configure.ac b/configure.ac index 8c687d731d5..724f7ce64c4 100644 --- a/configure.ac +++ b/configure.ac @@ -4955,9 +4955,16 @@ then [Define if mvwdelch in curses.h is an expression.]) fi +# Issue #25720: ncurses has introduced the NCURSES_OPAQUE symbol making opaque +# structs since version 5.7. If the macro is defined as zero before including +# [n]curses.h, ncurses will expose fields of the structs regardless of the +# configuration. AC_MSG_CHECKING(whether WINDOW has _flags) AC_CACHE_VAL(ac_cv_window_has_flags, -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #define NCURSES_OPAQUE 0 + #include +]], [[ WINDOW *w; w->_flags = 0; ]])], @@ -4972,6 +4979,17 @@ then [Define if WINDOW in curses.h offers a field _flags.]) fi +AC_MSG_CHECKING(for is_pad) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ +#ifndef is_pad +void *x=is_pad +#endif +]])], + [AC_DEFINE(HAVE_CURSES_IS_PAD, 1, Define if you have the 'is_pad' function or macro.) + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no)] +) + AC_MSG_CHECKING(for is_term_resized) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=is_term_resized]])], [AC_DEFINE(HAVE_CURSES_IS_TERM_RESIZED, 1, Define if you have the 'is_term_resized' function.) diff --git a/pyconfig.h.in b/pyconfig.h.in index afd161c15f0..f63022449f3 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -158,6 +158,9 @@ /* Define if you have the 'immedok' function. */ #undef HAVE_CURSES_IMMEDOK +/* Define if you have the 'is_pad' function or macro. */ +#undef HAVE_CURSES_IS_PAD + /* Define if you have the 'is_term_resized' function. */ #undef HAVE_CURSES_IS_TERM_RESIZED