.. versionadded:: 3.14
+.. function:: alloc_pair(fg, bg)
+
+ Allocate a color pair for foreground color *fg* and background color *bg*,
+ and return its number. If a color pair for the same combination of colors
+ already exists, return its number. Otherwise allocate a new color pair and
+ return its number.
+
+ This function is only available if Python was built against a wide-character
+ version of the underlying curses library with extended-color support (see
+ :func:`has_extended_color_support`).
+
+ .. versionadded:: next
+
+
.. function:: baudrate()
Return the output speed of the terminal in bits per second. On software
.. versionadded:: next
+.. function:: find_pair(fg, bg)
+
+ Return the number of a color pair for foreground color *fg* and background
+ color *bg*, or ``-1`` if no color pair for this combination of colors has
+ been allocated.
+
+ This function is only available if Python was built against a wide-character
+ version of the underlying curses library with extended-color support (see
+ :func:`has_extended_color_support`).
+
+ .. versionadded:: next
+
+
.. function:: flash()
Flash the screen. That is, change it to reverse-video and then change it back
by the user and has not yet been processed by the program.
+.. function:: free_pair(pair_number)
+
+ Free the color pair *pair_number*, which must have been allocated by
+ :func:`alloc_pair`. The pair must not be in use.
+
+ This function is only available if Python was built against a wide-character
+ version of the underlying curses library with extended-color support (see
+ :func:`has_extended_color_support`).
+
+ .. versionadded:: next
+
+
.. function:: getmouse()
After :meth:`~window.getch` returns :const:`KEY_MOUSE` to signal a mouse event, this
presented to curses input functions one by one.
+.. function:: reset_color_pairs()
+
+ Discard all color-pair definitions, releasing the color pairs allocated by
+ :func:`init_pair` and :func:`alloc_pair`.
+
+ This function is only available if Python was built against a wide-character
+ version of the underlying curses library with extended-color support (see
+ :func:`has_extended_color_support`).
+
+ .. versionadded:: next
+
+
.. function:: reset_prog_mode()
Restore the terminal to "program" mode, as previously saved by
* Add :func:`curses.nofilter`, which undoes the effect of :func:`curses.filter`.
(Contributed by Serhiy Storchaka in :gh:`151744`.)
+* Add the :mod:`curses` functions :func:`curses.alloc_pair`,
+ :func:`curses.find_pair`, :func:`curses.free_pair` and
+ :func:`curses.reset_color_pairs` for dynamic color-pair management,
+ available when built against a wide-character ncurses with extended-color
+ support.
+ (Contributed by Serhiy Storchaka in :gh:`151774`.)
+
gzip
----
self.assertRaises(ValueError, curses.init_pair, 1, color, 0)
self.assertRaises(ValueError, curses.init_pair, 1, 0, color)
+ @requires_curses_func('alloc_pair')
+ @requires_colors
+ def test_dynamic_color_pairs(self):
+ # alloc_pair()/find_pair()/free_pair() (extended-color extension).
+ fg = bg = curses.COLORS - 1
+ pair = curses.alloc_pair(fg, bg)
+ self.assertGreater(pair, 0)
+ self.assertEqual(curses.pair_content(pair), (fg, bg))
+ # The same combination of colors reuses the same pair.
+ self.assertEqual(curses.alloc_pair(fg, bg), pair)
+ self.assertEqual(curses.find_pair(fg, bg), pair)
+ # Once freed, the pair is no longer found.
+ self.assertIsNone(curses.free_pair(pair))
+ self.assertEqual(curses.find_pair(fg, bg), -1)
+
+ # Error paths.
+ for color in self.bad_colors2():
+ self.assertRaises(ValueError, curses.alloc_pair, color, 0)
+ self.assertRaises(ValueError, curses.alloc_pair, 0, color)
+ self.assertRaises(ValueError, curses.find_pair, color, 0)
+ self.assertRaises(ValueError, curses.find_pair, 0, color)
+ for pair in self.bad_pairs():
+ self.assertRaises(ValueError, curses.free_pair, pair)
+ # Color pair 0 is reserved and cannot be freed.
+ self.assertRaises(curses.error, curses.free_pair, 0)
+
+ # Invalid number or type of arguments.
+ self.assertRaises(TypeError, curses.alloc_pair)
+ self.assertRaises(TypeError, curses.alloc_pair, 0)
+ self.assertRaises(TypeError, curses.alloc_pair, 0, 0, 0)
+ self.assertRaises(TypeError, curses.alloc_pair, 'red', 0)
+ self.assertRaises(TypeError, curses.alloc_pair, 0, 'red')
+ self.assertRaises(TypeError, curses.alloc_pair, fg=0, bg=0)
+ self.assertRaises(TypeError, curses.find_pair)
+ self.assertRaises(TypeError, curses.find_pair, 0)
+ self.assertRaises(TypeError, curses.find_pair, 0, 0, 0)
+ self.assertRaises(TypeError, curses.find_pair, 'red', 0)
+ self.assertRaises(TypeError, curses.find_pair, 0, 'red')
+ self.assertRaises(TypeError, curses.free_pair)
+ self.assertRaises(TypeError, curses.free_pair, 1, 2)
+ self.assertRaises(TypeError, curses.free_pair, 'red')
+
+ @requires_curses_func('reset_color_pairs')
+ @requires_colors
+ def test_reset_color_pairs(self):
+ self.assertIsNone(curses.reset_color_pairs())
+ self.assertRaises(TypeError, curses.reset_color_pairs, 0)
+
@requires_colors
def test_color_attrs(self):
for pair in 0, 1, 255:
--- /dev/null
+Add the :mod:`curses` functions :func:`curses.alloc_pair`,
+:func:`curses.find_pair`, :func:`curses.free_pair` and
+:func:`curses.reset_color_pairs` for dynamic color-pair management. They are
+only available when Python is built against a wide-character version of the
+underlying curses library with extended-color support.
Py_RETURN_NONE;
}
+#if _NCURSES_EXTENDED_COLOR_FUNCS
+/*[clinic input]
+_curses.alloc_pair
+
+ fg: color_allow_default
+ Foreground color number.
+ bg: color_allow_default
+ Background color number.
+ /
+
+Allocate a color pair for the given foreground and background colors.
+
+If a color pair for the same colors already exists, return its number.
+Otherwise allocate a new color pair and return its number.
+[clinic start generated code]*/
+
+static PyObject *
+_curses_alloc_pair_impl(PyObject *module, int fg, int bg)
+/*[clinic end generated code: output=6eb08cb643d4b5a2 input=b29bafd7b360fa35]*/
+{
+ PyCursesStatefulInitialised(module);
+ PyCursesStatefulInitialisedColor(module);
+
+ int pair = alloc_pair(fg, bg);
+ if (pair < 0) {
+ curses_set_error(module, "alloc_pair", NULL);
+ return NULL;
+ }
+ return PyLong_FromLong(pair);
+}
+
+/*[clinic input]
+_curses.find_pair
+
+ fg: color_allow_default
+ Foreground color number.
+ bg: color_allow_default
+ Background color number.
+ /
+
+Return the number of a color pair for the given colors, or -1.
+
+Return -1 if no color pair for this combination of foreground and
+background colors has been allocated.
+[clinic start generated code]*/
+
+static PyObject *
+_curses_find_pair_impl(PyObject *module, int fg, int bg)
+/*[clinic end generated code: output=376026c2a3ac4a9b input=930feac14892c251]*/
+{
+ PyCursesStatefulInitialised(module);
+ PyCursesStatefulInitialisedColor(module);
+
+ return PyLong_FromLong(find_pair(fg, bg));
+}
+
+/*[clinic input]
+_curses.free_pair
+
+ pair: pair
+ The number of the color pair to free.
+ /
+
+Free a color pair allocated by alloc_pair().
+[clinic start generated code]*/
+
+static PyObject *
+_curses_free_pair_impl(PyObject *module, int pair)
+/*[clinic end generated code: output=61be0fb2e4bb4e4a input=d24df62feb4161c6]*/
+{
+ PyCursesStatefulInitialised(module);
+ PyCursesStatefulInitialisedColor(module);
+
+ return curses_check_err(module, free_pair(pair), "free_pair", NULL);
+}
+
+/*[clinic input]
+_curses.reset_color_pairs
+
+Discard all color-pair definitions.
+[clinic start generated code]*/
+
+static PyObject *
+_curses_reset_color_pairs_impl(PyObject *module)
+/*[clinic end generated code: output=117e68c6614e1d06 input=57c1cf7e5447e1ac]*/
+{
+ PyCursesStatefulInitialised(module);
+ PyCursesStatefulInitialisedColor(module);
+
+ reset_color_pairs();
+ Py_RETURN_NONE;
+}
+#endif /* _NCURSES_EXTENDED_COLOR_FUNCS */
+
/* Refresh the private copy of the screen encoding from a freshly created
stdscr window object. Returns 0 on success, -1 with an exception set. */
static int
/* List of functions defined in the module */
static PyMethodDef cursesmodule_methods[] = {
+ _CURSES_ALLOC_PAIR_METHODDEF
_CURSES_BAUDRATE_METHODDEF
_CURSES_BEEP_METHODDEF
_CURSES_CAN_CHANGE_COLOR_METHODDEF
_CURSES_ERASEWCHAR_METHODDEF
_CURSES_FILTER_METHODDEF
_CURSES_NOFILTER_METHODDEF
+ _CURSES_FIND_PAIR_METHODDEF
_CURSES_FLASH_METHODDEF
_CURSES_FLUSHINP_METHODDEF
+ _CURSES_FREE_PAIR_METHODDEF
_CURSES_GETMOUSE_METHODDEF
_CURSES_UNGETMOUSE_METHODDEF
_CURSES_GETSYX_METHODDEF
_CURSES_PUTP_METHODDEF
_CURSES_QIFLUSH_METHODDEF
_CURSES_RAW_METHODDEF
+ _CURSES_RESET_COLOR_PAIRS_METHODDEF
_CURSES_RESET_PROG_MODE_METHODDEF
_CURSES_RESET_SHELL_MODE_METHODDEF
_CURSES_RESETTY_METHODDEF
return return_value;
}
+#if (_NCURSES_EXTENDED_COLOR_FUNCS)
+
+PyDoc_STRVAR(_curses_alloc_pair__doc__,
+"alloc_pair($module, fg, bg, /)\n"
+"--\n"
+"\n"
+"Allocate a color pair for the given foreground and background colors.\n"
+"\n"
+" fg\n"
+" Foreground color number.\n"
+" bg\n"
+" Background color number.\n"
+"\n"
+"If a color pair for the same colors already exists, return its number.\n"
+"Otherwise allocate a new color pair and return its number.");
+
+#define _CURSES_ALLOC_PAIR_METHODDEF \
+ {"alloc_pair", _PyCFunction_CAST(_curses_alloc_pair), METH_FASTCALL, _curses_alloc_pair__doc__},
+
+static PyObject *
+_curses_alloc_pair_impl(PyObject *module, int fg, int bg);
+
+static PyObject *
+_curses_alloc_pair(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ int fg;
+ int bg;
+
+ if (!_PyArg_CheckPositional("alloc_pair", nargs, 2, 2)) {
+ goto exit;
+ }
+ if (!color_allow_default_converter(args[0], &fg)) {
+ goto exit;
+ }
+ if (!color_allow_default_converter(args[1], &bg)) {
+ goto exit;
+ }
+ return_value = _curses_alloc_pair_impl(module, fg, bg);
+
+exit:
+ return return_value;
+}
+
+#endif /* (_NCURSES_EXTENDED_COLOR_FUNCS) */
+
+#if (_NCURSES_EXTENDED_COLOR_FUNCS)
+
+PyDoc_STRVAR(_curses_find_pair__doc__,
+"find_pair($module, fg, bg, /)\n"
+"--\n"
+"\n"
+"Return the number of a color pair for the given colors, or -1.\n"
+"\n"
+" fg\n"
+" Foreground color number.\n"
+" bg\n"
+" Background color number.\n"
+"\n"
+"Return -1 if no color pair for this combination of foreground and\n"
+"background colors has been allocated.");
+
+#define _CURSES_FIND_PAIR_METHODDEF \
+ {"find_pair", _PyCFunction_CAST(_curses_find_pair), METH_FASTCALL, _curses_find_pair__doc__},
+
+static PyObject *
+_curses_find_pair_impl(PyObject *module, int fg, int bg);
+
+static PyObject *
+_curses_find_pair(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ int fg;
+ int bg;
+
+ if (!_PyArg_CheckPositional("find_pair", nargs, 2, 2)) {
+ goto exit;
+ }
+ if (!color_allow_default_converter(args[0], &fg)) {
+ goto exit;
+ }
+ if (!color_allow_default_converter(args[1], &bg)) {
+ goto exit;
+ }
+ return_value = _curses_find_pair_impl(module, fg, bg);
+
+exit:
+ return return_value;
+}
+
+#endif /* (_NCURSES_EXTENDED_COLOR_FUNCS) */
+
+#if (_NCURSES_EXTENDED_COLOR_FUNCS)
+
+PyDoc_STRVAR(_curses_free_pair__doc__,
+"free_pair($module, pair, /)\n"
+"--\n"
+"\n"
+"Free a color pair allocated by alloc_pair().\n"
+"\n"
+" pair\n"
+" The number of the color pair to free.");
+
+#define _CURSES_FREE_PAIR_METHODDEF \
+ {"free_pair", (PyCFunction)_curses_free_pair, METH_O, _curses_free_pair__doc__},
+
+static PyObject *
+_curses_free_pair_impl(PyObject *module, int pair);
+
+static PyObject *
+_curses_free_pair(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ int pair;
+
+ if (!pair_converter(arg, &pair)) {
+ goto exit;
+ }
+ return_value = _curses_free_pair_impl(module, pair);
+
+exit:
+ return return_value;
+}
+
+#endif /* (_NCURSES_EXTENDED_COLOR_FUNCS) */
+
+#if (_NCURSES_EXTENDED_COLOR_FUNCS)
+
+PyDoc_STRVAR(_curses_reset_color_pairs__doc__,
+"reset_color_pairs($module, /)\n"
+"--\n"
+"\n"
+"Discard all color-pair definitions.");
+
+#define _CURSES_RESET_COLOR_PAIRS_METHODDEF \
+ {"reset_color_pairs", (PyCFunction)_curses_reset_color_pairs, METH_NOARGS, _curses_reset_color_pairs__doc__},
+
+static PyObject *
+_curses_reset_color_pairs_impl(PyObject *module);
+
+static PyObject *
+_curses_reset_color_pairs(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _curses_reset_color_pairs_impl(module);
+}
+
+#endif /* (_NCURSES_EXTENDED_COLOR_FUNCS) */
+
PyDoc_STRVAR(_curses_initscr__doc__,
"initscr($module, /)\n"
"--\n"
#define _CURSES_HAS_KEY_METHODDEF
#endif /* !defined(_CURSES_HAS_KEY_METHODDEF) */
+#ifndef _CURSES_ALLOC_PAIR_METHODDEF
+ #define _CURSES_ALLOC_PAIR_METHODDEF
+#endif /* !defined(_CURSES_ALLOC_PAIR_METHODDEF) */
+
+#ifndef _CURSES_FIND_PAIR_METHODDEF
+ #define _CURSES_FIND_PAIR_METHODDEF
+#endif /* !defined(_CURSES_FIND_PAIR_METHODDEF) */
+
+#ifndef _CURSES_FREE_PAIR_METHODDEF
+ #define _CURSES_FREE_PAIR_METHODDEF
+#endif /* !defined(_CURSES_FREE_PAIR_METHODDEF) */
+
+#ifndef _CURSES_RESET_COLOR_PAIRS_METHODDEF
+ #define _CURSES_RESET_COLOR_PAIRS_METHODDEF
+#endif /* !defined(_CURSES_RESET_COLOR_PAIRS_METHODDEF) */
+
#ifndef _CURSES_NEW_PRESCR_METHODDEF
#define _CURSES_NEW_PRESCR_METHODDEF
#endif /* !defined(_CURSES_NEW_PRESCR_METHODDEF) */
#ifndef _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
#define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
#endif /* !defined(_CURSES_ASSUME_DEFAULT_COLORS_METHODDEF) */
-/*[clinic end generated code: output=8188ebf7404d028a input=a9049054013a1b77]*/
+/*[clinic end generated code: output=35a3d93708112587 input=a9049054013a1b77]*/