From f14deec35766afdbf9de2ad46f3e1cedc818b63c Mon Sep 17 00:00:00 2001 From: Masayuki Yamamoto Date: Sun, 21 May 2017 12:24:24 +0900 Subject: [PATCH 1/4] bpo-25720: curses: Fix check for whether WINDOW is a pad WINDOW_HAS_FLAGS will be defined by the configure check, but if the platform has ncurses.h, defines the macro always. Therefore, codes that check directly the field of WINDOW are enabled regardless of NCURSES_OPAQUE (since ncurses 5.7), and a platform that WINDOW is actually opaque occurs compile error at that place. For this reason, the codes are modified to use py_is_pad macro to check WINDOW state. Note that if ncurses doesn't have both is_pad function (since 5.8) and _flags field of WINDOW, there is no method to check whether WINDOW is a pad. In this case, NCURSES_OPAQUE is defined as zero to make WINDOW to non-opaque type before including ncurses.h. --- Include/py_curses.h | 26 ++++++--- Modules/_cursesmodule.c | 126 +++++++++++++++++++++------------------- configure | 30 ++++++++++ configure.ac | 12 ++++ pyconfig.h.in | 3 + 5 files changed, 129 insertions(+), 68 deletions(-) diff --git a/Include/py_curses.h b/Include/py_curses.h index 336c95d360d159..a34dc25d7b9072 100644 --- a/Include/py_curses.h +++ b/Include/py_curses.h @@ -7,7 +7,7 @@ ** On Mac OS X 10.2 [n]curses.h and stdlib.h use different guards ** against multiple definition of wchar_t. */ -#ifdef _BSD_WCHAR_T_DEFINED_ +#ifdef _BSD_WCHAR_T_DEFINED_ #define _WCHAR_T #endif @@ -22,7 +22,7 @@ ** On FreeBSD, [n]curses.h and stdlib.h/wchar.h use different guards ** against multiple definition of wchar_t and wint_t. */ -#ifdef _XOPEN_SOURCE_EXTENDED +#ifdef _XOPEN_SOURCE_EXTENDED #ifndef __FreeBSD_version #include #endif @@ -44,6 +44,17 @@ #endif #endif +#ifdef HAVE_NCURSES_H +#if !defined(HAVE_CURSES_IS_PAD) && !defined(WINDOW_HAS_FLAGS) +/* If ncurses doesn't have both is_pad function and _flags field of WINDOW, + there is no method to check whether WINDOW is a pad. Therefore, add the + definitions to make WINDOW to non-opaque type before including ncurses.h. +*/ +#define NCURSES_OPAQUE 0 +#define WINDOW_HAS_FLAGS 1 +#endif +#endif + #ifdef HAVE_NCURSES_H #include #else @@ -57,9 +68,6 @@ #ifdef HAVE_NCURSES_H /* configure was checking , but we will use , which has all these features. */ -#ifndef WINDOW_HAS_FLAGS -#define WINDOW_HAS_FLAGS 1 -#endif #ifndef MVWDELCH_IS_EXPRESSION #define MVWDELCH_IS_EXPRESSION 1 #endif @@ -74,12 +82,12 @@ extern "C" { /* Type declarations */ typedef struct { - PyObject_HEAD - WINDOW *win; - char *encoding; + PyObject_HEAD + WINDOW *win; + char *encoding; } PyCursesWindowObject; -#define PyCursesWindow_Check(v) (Py_TYPE(v) == &PyCursesWindow_Type) +#define PyCursesWindow_Check(v) (Py_TYPE(v) == &PyCursesWindow_Type) #define PyCurses_CAPSULE_NAME "_curses._C_API" diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index f278268e6702ab..391aa142f6f0aa 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -928,6 +928,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 * @@ -1067,8 +1073,8 @@ 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 @@ -1602,41 +1608,42 @@ 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) -#endif - { - switch(PyTuple_Size(args)) { - case 6: - if (!PyArg_ParseTuple(args, - "iiiiii;" \ - "pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol", - &pminrow, &pmincol, &sminrow, - &smincol, &smaxrow, &smaxcol)) - return NULL; - Py_BEGIN_ALLOW_THREADS - rtn = pnoutrefresh(self->win, - pminrow, pmincol, sminrow, - smincol, smaxrow, smaxcol); - Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "pnoutrefresh"); - default: - PyErr_SetString(PyCursesError, - "noutrefresh() called for a pad " - "requires 6 arguments"); - return NULL; - } - } else { - if (!PyArg_ParseTuple(args, ":noutrefresh")) + if (py_is_pad(self->win)) +#endif + { + switch(PyTuple_Size(args)) { + case 6: + if (!PyArg_ParseTuple(args, + "iiiiii;" \ + "pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol", + &pminrow, &pmincol, &sminrow, + &smincol, &smaxrow, &smaxcol)) return NULL; Py_BEGIN_ALLOW_THREADS - rtn = wnoutrefresh(self->win); + rtn = pnoutrefresh(self->win, + pminrow, pmincol, sminrow, + smincol, smaxrow, smaxcol); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "wnoutrefresh"); + return PyCursesCheckERR(rtn, "pnoutrefresh"); + default: + PyErr_SetString(PyCursesError, + "noutrefresh() called for a pad " + "requires 6 arguments"); + return NULL; } + } else { + if (!PyArg_ParseTuple(args, ":noutrefresh")) + return NULL; + + Py_BEGIN_ALLOW_THREADS + rtn = wnoutrefresh(self->win); + Py_END_ALLOW_THREADS + return PyCursesCheckERR(rtn, "wnoutrefresh"); + } } static PyObject * @@ -1765,40 +1772,41 @@ 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) -#endif - { - switch(PyTuple_Size(args)) { - case 6: - if (!PyArg_ParseTuple(args, - "iiiiii;" \ - "pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol", - &pminrow, &pmincol, &sminrow, - &smincol, &smaxrow, &smaxcol)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - rtn = prefresh(self->win, - pminrow, pmincol, sminrow, - smincol, smaxrow, smaxcol); - Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); - default: - PyErr_SetString(PyCursesError, - "refresh() for a pad requires 6 arguments"); - return NULL; - } - } else { - if (!PyArg_ParseTuple(args, ":refresh")) + if (py_is_pad(self->win)) +#endif + { + switch(PyTuple_Size(args)) { + case 6: + if (!PyArg_ParseTuple(args, + "iiiiii;" \ + "pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol", + &pminrow, &pmincol, &sminrow, + &smincol, &smaxrow, &smaxcol)) return NULL; + Py_BEGIN_ALLOW_THREADS - rtn = wrefresh(self->win); + rtn = prefresh(self->win, + pminrow, pmincol, sminrow, + smincol, smaxrow, smaxcol); Py_END_ALLOW_THREADS return PyCursesCheckERR(rtn, "prefresh"); + default: + PyErr_SetString(PyCursesError, + "refresh() for a pad requires 6 arguments"); + return NULL; } + } else { + if (!PyArg_ParseTuple(args, ":refresh")) + return NULL; + + Py_BEGIN_ALLOW_THREADS + rtn = wrefresh(self->win); + Py_END_ALLOW_THREADS + return PyCursesCheckERR(rtn, "prefresh"); + } } static PyObject * @@ -1834,8 +1842,8 @@ 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 diff --git a/configure b/configure index c9340c68605483..70295f5e6c98f0 100755 --- a/configure +++ b/configure @@ -15886,6 +15886,36 @@ $as_echo "#define MVWDELCH_IS_EXPRESSION 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 () +{ + + bool b; + WINDOW *w; + b = is_pad(w); + + ; + 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 whether WINDOW has _flags" >&5 $as_echo_n "checking whether WINDOW has _flags... " >&6; } if ${ac_cv_window_has_flags+:} false; then : diff --git a/configure.ac b/configure.ac index e065ce554b4ec9..1a4ef4c74c828c 100644 --- a/configure.ac +++ b/configure.ac @@ -4989,6 +4989,18 @@ then [Define if mvwdelch in curses.h is an expression.]) fi +AC_MSG_CHECKING(for is_pad) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ + bool b; + WINDOW *w; + b = is_pad(w); + ]])], + [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(whether WINDOW has _flags) AC_CACHE_VAL(ac_cv_window_has_flags, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ diff --git a/pyconfig.h.in b/pyconfig.h.in index 0a3d59ef9ae602..512d4ade90ac9a 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -149,6 +149,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_CURSES_H +/* 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 From 21c0daa1670cc6ed45484989b482bfe934c0e8cc Mon Sep 17 00:00:00 2001 From: Masayuki Yamamoto Date: Sat, 24 Jun 2017 10:22:23 +0900 Subject: [PATCH 2/4] bpo-25720: Add Misc/NEWS entry --- Misc/NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index f33589d0085a5c..5f469907671f07 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -369,6 +369,8 @@ Core and Builtins Extension Modules ----------------- +- bpo-25720: curses: Fix check for whether WINDOW is a pad. + - Issue #29169: Update zlib to 1.2.11. Library From 2322fa0bba703aaf42d99956eb0d2de000a2bdc7 Mon Sep 17 00:00:00 2001 From: Masayuki Yamamoto Date: Sat, 24 Jun 2017 10:22:50 +0900 Subject: [PATCH 3/4] bpo-25720: Remove definition in __APPLE__ to unify compile condition --- Include/py_curses.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Include/py_curses.h b/Include/py_curses.h index a34dc25d7b9072..d98bf82655896b 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,16 +39,14 @@ #endif #endif -#ifdef HAVE_NCURSES_H #if !defined(HAVE_CURSES_IS_PAD) && !defined(WINDOW_HAS_FLAGS) /* If ncurses doesn't have both is_pad function and _flags field of WINDOW, there is no method to check whether WINDOW is a pad. Therefore, add the - definitions to make WINDOW to non-opaque type before including ncurses.h. + definitions to make WINDOW to non-opaque type before including [n]curses.h. */ #define NCURSES_OPAQUE 0 #define WINDOW_HAS_FLAGS 1 #endif -#endif #ifdef HAVE_NCURSES_H #include From f45d15de3f999fd928410bcd40d1efd59ece5048 Mon Sep 17 00:00:00 2001 From: Masayuki Yamamoto Date: Sat, 24 Jun 2017 13:47:47 +0900 Subject: [PATCH 4/4] bpo-25720: Add news using blurb New workflow was announced on Python-Dev. --- Misc/NEWS | 2 -- .../next/Library/2017-06-24-13-47-00.bpo-25720.iEVYvL.rst | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-06-24-13-47-00.bpo-25720.iEVYvL.rst diff --git a/Misc/NEWS b/Misc/NEWS index 5f469907671f07..f33589d0085a5c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -369,8 +369,6 @@ Core and Builtins Extension Modules ----------------- -- bpo-25720: curses: Fix check for whether WINDOW is a pad. - - Issue #29169: Update zlib to 1.2.11. Library diff --git a/Misc/NEWS.d/next/Library/2017-06-24-13-47-00.bpo-25720.iEVYvL.rst b/Misc/NEWS.d/next/Library/2017-06-24-13-47-00.bpo-25720.iEVYvL.rst new file mode 100644 index 00000000000000..f7a66fe11e937f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-06-24-13-47-00.bpo-25720.iEVYvL.rst @@ -0,0 +1 @@ +curses: Fix check for whether WINDOW is a pad.