From 089e6f622b19fe2e3da2e97f0af96fad4a448e85 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 29 Jun 2026 20:57:56 +0300 Subject: [PATCH] gh-152263: Add curses soft-label-key functions (GH-152264) Wrap the X/Open Curses soft-label-key functions: slk_init, slk_set, slk_label, slk_refresh, slk_noutrefresh, slk_clear, slk_restore, slk_touch, the chtype attribute functions slk_attron, slk_attroff, slk_attrset and slk_attr, and the attr_t functions slk_attr_on, slk_attr_off, slk_attr_set and slk_color. Co-Authored-By: Claude Opus 4.8 --- Doc/library/curses.rst | 125 +++++ Doc/whatsnew/3.16.rst | 12 + Lib/test/test_curses.py | 119 ++++- ...-06-26-14-34-28.gh-issue-152263.5PHQP4.rst | 9 + Modules/_cursesmodule.c | 319 ++++++++++++- Modules/clinic/_cursesmodule.c.h | 447 +++++++++++++++++- 6 files changed, 1015 insertions(+), 16 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-06-26-14-34-28.gh-issue-152263.5PHQP4.rst diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst index 76967b88482c..b3341fb8629f 100644 --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -653,6 +653,131 @@ Windows and pads is to be displayed. +Soft labels +~~~~~~~~~~~ + +.. _curses-slk: + +The following functions manage *soft-label keys*, a row of labels displayed +along the bottom line of the screen, typically used to label a row of function +keys. :func:`slk_init` must be called before :func:`initscr` or +:func:`newterm`; it takes one screen line away from the standard window for the +labels. + + +.. function:: slk_init(fmt=0) + + Reserve a screen line for the soft labels and choose their layout. *fmt* + selects the arrangement: ``0`` for 3-2-3 (eight labels), ``1`` for 4-4 + (eight labels). Where the underlying curses library supports them, ``2`` + gives 4-4-4 (twelve labels) and ``3`` gives 4-4-4 with an index line. + + Must be called before :func:`initscr` or :func:`newterm`. + + .. versionadded:: next + + +.. function:: slk_set(labnum, label, justify) + + Set the text of soft label number *labnum*, in the range ``1`` through ``8`` + (or ``12`` in a twelve-label layout). *justify* controls how *label* is + placed within the label: ``0`` for left, ``1`` for centered, ``2`` for right. + + .. versionadded:: next + + +.. function:: slk_label(labnum) + + Return the current text of soft label number *labnum*, justified as it was + set, or an empty string if it has no label. + + .. versionadded:: next + + +.. function:: slk_refresh() + + Update the soft labels on the physical screen, like + :meth:`~curses.window.refresh` for a window. + + .. versionadded:: next + + +.. function:: slk_noutrefresh() + + Update the soft labels on the virtual screen, like + :meth:`window.noutrefresh`. Use it together with :func:`doupdate` to batch + screen updates. + + .. versionadded:: next + + +.. function:: slk_clear() + + Remove the soft labels from the screen. + + .. versionadded:: next + + +.. function:: slk_restore() + + Restore the soft labels to the screen after a :func:`slk_clear`. + + .. versionadded:: next + + +.. function:: slk_touch() + + Force all the soft labels to be redrawn by the next :func:`slk_refresh` or + :func:`slk_noutrefresh`. + + .. versionadded:: next + + +.. function:: slk_attron(attr) + slk_attroff(attr) + slk_attrset(attr) + + Add, remove, or set the attributes used to display the soft labels, given as + packed ``A_*`` attributes. + + .. versionadded:: next + + +.. function:: slk_attr() + + Return the current attributes of the soft labels as packed ``A_*`` + attributes. Availability depends on the underlying curses library. + + .. versionadded:: next + + +.. function:: slk_attr_on(attr) + slk_attr_off(attr) + + Turn the given attributes on or off without affecting any others. Like the + ``attr_*`` window methods, these work with the + :ref:`WA_* attributes ` rather than packed ``A_*`` + attributes. + + .. versionadded:: next + + +.. function:: slk_attr_set(attr, pair=0) + + Set the attributes and color pair of the soft labels. *attr* is given as + :ref:`WA_* attributes ` and *pair* as a color pair + number. + + .. versionadded:: next + + +.. function:: slk_color(pair) + + Set the color pair of the soft labels to color pair number *pair*. + + .. versionadded:: next + + Saving and restoring ~~~~~~~~~~~~~~~~~~~~ diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 8407d0df3256..e215d4ddfdf4 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -182,6 +182,18 @@ curses :func:`~curses.scr_set`, which dump the whole screen to a file and restore it. (Contributed by Serhiy Storchaka in :gh:`152260`.) +* Add the soft-label-key functions to the :mod:`curses` module, which manage a + row of labels along the bottom line of the screen: + :func:`~curses.slk_init`, :func:`~curses.slk_set`, :func:`~curses.slk_label`, + :func:`~curses.slk_refresh`, :func:`~curses.slk_noutrefresh`, + :func:`~curses.slk_clear`, :func:`~curses.slk_restore`, + :func:`~curses.slk_touch`, the attribute functions + :func:`~curses.slk_attron`, :func:`~curses.slk_attroff`, + :func:`~curses.slk_attrset`, :func:`~curses.slk_attr`, + :func:`~curses.slk_attr_on`, :func:`~curses.slk_attr_off`, + :func:`~curses.slk_attr_set`, and :func:`~curses.slk_color`. + (Contributed by Serhiy Storchaka in :gh:`152263`.) + * Add the :func:`curses.term_attrs` function, which returns the supported video attributes as :ref:`WA_* ` values, the counterpart of :func:`curses.termattrs`. diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index 17b31e4c7c80..a18f83e23908 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -2843,16 +2843,12 @@ class TextboxTest(unittest.TestCase): self.mock_win.reset_mock() -@unittest.skipUnless(hasattr(curses, 'newterm'), 'requires curses.newterm()') -@unittest.skipIf(not term or term == 'unknown', - "$TERM=%r, newterm() may not work" % term) -@unittest.skipIf(sys.platform == "cygwin", - "cygwin's curses mostly just hangs") -class ScreenTests(unittest.TestCase): - # newterm()/set_term() mutate global curses state, but each test drives its - # own pseudo-terminal(s) and never touches the screen shared by TestCurses, - # whose setUp() makes that screen current again. So these can run in this - # process, without a real terminal and without a subprocess. +class NewtermTestBase(unittest.TestCase): + # Shared plumbing for tests that drive newterm() over their own + # pseudo-terminal(s). newterm()/set_term() mutate global curses state, but + # each test never touches the screen shared by TestCurses, whose setUp() + # makes that screen current again. So these can run in this process, + # without a real terminal and without a subprocess. def setUp(self): # newterm() may install signal handlers; restore them afterwards. @@ -2906,6 +2902,14 @@ class ScreenTests(unittest.TestCase): self.addCleanup(stop_reader) return slave + +@unittest.skipUnless(hasattr(curses, 'newterm'), 'requires curses.newterm()') +@unittest.skipIf(not term or term == 'unknown', + f"$TERM={term!r}, newterm() may not work") +@unittest.skipIf(sys.platform == "cygwin", + "cygwin's curses mostly just hangs") +class ScreenTests(NewtermTestBase): + def test_newterm(self): s = self.make_pty() screen = curses.newterm('xterm', s, s) @@ -2979,5 +2983,100 @@ class ScreenTests(unittest.TestCase): check_disallow_instantiation(self, curses.screen) +@unittest.skipUnless(hasattr(curses, 'slk_init'), 'requires curses.slk_init()') +@unittest.skipUnless(hasattr(curses, 'newterm'), 'requires curses.newterm()') +@unittest.skipIf(not term or term == 'unknown', + f"$TERM={term!r}, newterm() may not work") +@unittest.skipIf(sys.platform == "cygwin", + "cygwin's curses mostly just hangs") +class SLKTests(NewtermTestBase): + # Soft-label keys reserve the bottom screen line for a row of labels. + # slk_init() must run before newterm()/initscr(), so each test sets up its + # own screen rather than reusing the one TestCurses builds in setUp(). + + def make_slk_screen(self, fmt=0): + s = self.make_pty() + curses.slk_init(fmt) + return curses.newterm('xterm', s, s) + + def test_init_reserves_a_line(self): + # Every layout takes the bottom line for the labels; the index-line + # layout (3) takes a second line for the index. Layouts 0 and 1 are + # standard; 2 and 3 are ncurses extensions that other curses + # implementations reject (slk_init() then returns an error). + ncurses = hasattr(curses, 'ncurses_version') + for fmt, lines in [(0, 23), (1, 23), (2, 23), (3, 22)]: + with self.subTest(fmt=fmt): + try: + screen = self.make_slk_screen(fmt) + except curses.error: + if ncurses or fmt < 2: + raise + continue + self.assertEqual(screen.stdscr.getmaxyx()[0], lines) + curses.endwin() + + def test_init_bad_format(self): + for fmt in (-1, 4): + self.assertRaises(ValueError, curses.slk_init, fmt) + + def test_set_and_label(self): + self.make_slk_screen() + curses.slk_set(1, 'Help', 0) + curses.slk_set(2, 'Save', 1) + curses.slk_set(3, 'Quit', 2) + self.assertEqual(curses.slk_label(1), 'Help') + self.assertEqual(curses.slk_label(2), 'Save') + self.assertEqual(curses.slk_label(3), 'Quit') + + def test_set_wide(self): + screen = self.make_slk_screen() + label = 'Ångström' + try: + label.encode(screen.stdscr.encoding) + except UnicodeEncodeError: + self.skipTest('the locale cannot encode %r' % label) + curses.slk_set(1, label, 0) + self.assertEqual(curses.slk_label(1), label) + + def test_set_bad_justify(self): + self.make_slk_screen() + for justify in (-1, 3): + self.assertRaises(ValueError, curses.slk_set, 1, 'x', justify) + + def test_refresh(self): + self.make_slk_screen() + curses.slk_set(1, 'Help', 0) + curses.slk_noutrefresh() + curses.slk_refresh() + curses.slk_clear() + curses.slk_restore() + curses.slk_touch() + + def test_attributes(self): + self.make_slk_screen() + curses.slk_attron(curses.A_BOLD) + curses.slk_attrset(curses.A_UNDERLINE) + curses.slk_attroff(curses.A_BOLD) + if hasattr(curses, 'slk_attr'): + self.assertIsInstance(curses.slk_attr(), int) + + def test_attr_on_off(self): + self.make_slk_screen() + curses.slk_attr_on(curses.A_BOLD) + curses.slk_attr_off(curses.A_BOLD) + + def test_color(self): + # slk_attr_set() and slk_color() act on a color pair, so the color + # subsystem must be started first. + self.make_slk_screen() + if not curses.has_colors(): + self.skipTest('requires colors support') + curses.start_color() + curses.slk_attr_set(curses.A_BOLD) + curses.slk_attr_set(curses.A_BOLD, 0) + curses.slk_color(0) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2026-06-26-14-34-28.gh-issue-152263.5PHQP4.rst b/Misc/NEWS.d/next/Library/2026-06-26-14-34-28.gh-issue-152263.5PHQP4.rst new file mode 100644 index 000000000000..7367f84c6f47 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-26-14-34-28.gh-issue-152263.5PHQP4.rst @@ -0,0 +1,9 @@ +Add the soft-label-key functions to the :mod:`curses` module: +:func:`~curses.slk_init`, :func:`~curses.slk_set`, :func:`~curses.slk_label`, +:func:`~curses.slk_refresh`, :func:`~curses.slk_noutrefresh`, +:func:`~curses.slk_clear`, :func:`~curses.slk_restore`, +:func:`~curses.slk_touch`, :func:`~curses.slk_attron`, +:func:`~curses.slk_attroff`, :func:`~curses.slk_attrset`, +:func:`~curses.slk_attr`, :func:`~curses.slk_attr_on`, +:func:`~curses.slk_attr_off`, :func:`~curses.slk_attr_set` and +:func:`~curses.slk_color`. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 07883848992a..cbd452169684 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -45,11 +45,6 @@ tgetent tgetflag tgetnum tgetstr tgoto tputs vidattr vidputs - Low-priority: - slk_attr slk_attr_off slk_attr_on slk_attr_set slk_attroff - slk_attron slk_attrset slk_clear slk_color slk_init slk_label - slk_noutrefresh slk_refresh slk_restore slk_set slk_touch - Menu extension (ncurses and probably SYSV): current_item free_item free_menu item_count item_description item_index item_init item_name item_opts item_opts_off @@ -8088,6 +8083,304 @@ _curses_unget_wch(PyObject *module, PyObject *ch) #endif } +/* ------------------------------------------------------------------------ */ +/* Soft-label keys: a row of labels along the bottom line of the screen. */ +/* All slk_* functions are module-level and act on one global label area. */ +/* ------------------------------------------------------------------------ */ + +/*[clinic input] +_curses.slk_init + + fmt: int = 0 + Label layout: 0 = 3-2-3, 1 = 4-4 (8 labels each); 2 = 4-4-4, + 3 = 4-4-4 with an index line (12 labels each, ncurses extensions). + / + +Reserve a line for soft labels and choose their layout. + +Must be called before initscr() or newterm(). +[clinic start generated code]*/ + +static PyObject * +_curses_slk_init_impl(PyObject *module, int fmt) +/*[clinic end generated code: output=8d3da3609be1a133 input=b9fec1776f56772a]*/ +{ + if (fmt < 0 || fmt > 3) { + PyErr_SetString(PyExc_ValueError, + "format must be an integer from 0 to 3"); + return NULL; + } + return curses_check_err(module, slk_init(fmt), "slk_init", NULL); +} + +/*[clinic input] +_curses.slk_set + + labnum: int + The label number (1 to 8, or 1 to 12 in a 12-label layout). + label: unicode + The text to display. + justify: int = 0 + 0 = left, 1 = center, 2 = right. + / + +Set the text of a soft label. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_set_impl(PyObject *module, int labnum, PyObject *label, + int justify) +/*[clinic end generated code: output=fc0f6b7af5acf32d input=1ce82b6cf23504d1]*/ +{ + PyCursesStatefulInitialised(module); + if (justify < 0 || justify > 2) { + PyErr_SetString(PyExc_ValueError, + "justification must be an integer from 0 to 2"); + return NULL; + } + int rtn; +#ifdef HAVE_NCURSESW + wchar_t *wstr = PyUnicode_AsWideCharString(label, NULL); + if (wstr == NULL) { + return NULL; + } + rtn = slk_wset(labnum, wstr, justify); + PyMem_Free(wstr); +#else + PyObject *bytes = PyUnicode_EncodeLocale(label, NULL); + if (bytes == NULL) { + return NULL; + } + rtn = slk_set(labnum, PyBytes_AS_STRING(bytes), justify); + Py_DECREF(bytes); +#endif + return curses_check_err(module, rtn, "slk_set", NULL); +} + +/*[clinic input] +_curses.slk_label + + labnum: int + The label number. + / + +Return the current text of a soft label. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_label_impl(PyObject *module, int labnum) +/*[clinic end generated code: output=4f4945ceaa0db758 input=ad9c26a136555ea0]*/ +{ + PyCursesStatefulInitialised(module); + char *label = slk_label(labnum); + if (label == NULL) { + return Py_GetConstant(Py_CONSTANT_EMPTY_STR); + } + return PyUnicode_DecodeLocale(label, NULL); +} + +/*[clinic input] +_curses.slk_refresh + +Update the soft labels on the screen. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_refresh_impl(PyObject *module) +/*[clinic end generated code: output=93183b9300e29cfe input=c668ee5b14ecb802]*/ +NoArgNoReturnFunctionBody(slk_refresh) + +/*[clinic input] +_curses.slk_noutrefresh + +Update the soft labels on the virtual screen only. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_noutrefresh_impl(PyObject *module) +/*[clinic end generated code: output=043d1d0021331e48 input=cabc0f5e37aac369]*/ +NoArgNoReturnFunctionBody(slk_noutrefresh) + +/*[clinic input] +_curses.slk_clear + +Erase the soft labels from the screen. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_clear_impl(PyObject *module) +/*[clinic end generated code: output=acf24fa9b130c8c6 input=38644dc752e4372b]*/ +NoArgNoReturnFunctionBody(slk_clear) + +/*[clinic input] +_curses.slk_restore + +Restore the soft labels after a preceding slk_clear(). +[clinic start generated code]*/ + +static PyObject * +_curses_slk_restore_impl(PyObject *module) +/*[clinic end generated code: output=fe9a518a013a00de input=97346ac473b0f9d7]*/ +NoArgNoReturnFunctionBody(slk_restore) + +/*[clinic input] +_curses.slk_touch + +Force the soft labels to be redrawn by the next slk_refresh(). +[clinic start generated code]*/ + +static PyObject * +_curses_slk_touch_impl(PyObject *module) +/*[clinic end generated code: output=6135e95a69687969 input=ff45098b9d8c9417]*/ +NoArgNoReturnFunctionBody(slk_touch) + +/*[clinic input] +_curses.slk_attron + + attr: long + / + +Add the given chtype attributes to the soft labels. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_attron_impl(PyObject *module, long attr) +/*[clinic end generated code: output=01aa29848a58ab50 input=fa198a604e3eec04]*/ +{ + PyCursesStatefulInitialised(module); + return curses_check_err(module, slk_attron((chtype)attr), + "slk_attron", NULL); +} + +/*[clinic input] +_curses.slk_attroff + + attr: long + / + +Remove the given chtype attributes from the soft labels. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_attroff_impl(PyObject *module, long attr) +/*[clinic end generated code: output=7b172cc37a17811f input=21dab55d43d30b8f]*/ +{ + PyCursesStatefulInitialised(module); + return curses_check_err(module, slk_attroff((chtype)attr), + "slk_attroff", NULL); +} + +/*[clinic input] +_curses.slk_attrset + + attr: long + / + +Set the chtype attributes of the soft labels. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_attrset_impl(PyObject *module, long attr) +/*[clinic end generated code: output=1139e2b0f757edfd input=d5c798956a5f046a]*/ +{ + PyCursesStatefulInitialised(module); + return curses_check_err(module, slk_attrset((chtype)attr), + "slk_attrset", NULL); +} + +#ifdef NCURSES_EXT_FUNCS +/*[clinic input] +_curses.slk_attr + +Return the current chtype attributes of the soft labels. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_attr_impl(PyObject *module) +/*[clinic end generated code: output=6d47752f82bdc29f input=be38805fdec52149]*/ +{ + PyCursesStatefulInitialised(module); + return PyLong_FromUnsignedLong((unsigned long)slk_attr()); +} +#endif + +/*[clinic input] +_curses.slk_attr_on + + attr: attr + / + +Turn on attributes of the soft labels without affecting others. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_attr_on_impl(PyObject *module, attr_t attr) +/*[clinic end generated code: output=32419d75e53e01c1 input=1087c3c4ecf21080]*/ +{ + PyCursesStatefulInitialised(module); + return curses_check_err(module, slk_attr_on(attr, NULL), + "slk_attr_on", NULL); +} + +/*[clinic input] +_curses.slk_attr_off + + attr: attr + / + +Turn off attributes of the soft labels without affecting others. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_attr_off_impl(PyObject *module, attr_t attr) +/*[clinic end generated code: output=28c6235ac6bc923c input=02b472ca7c772a66]*/ +{ + PyCursesStatefulInitialised(module); + return curses_check_err(module, slk_attr_off(attr, NULL), + "slk_attr_off", NULL); +} + +/*[clinic input] +_curses.slk_attr_set + + attr: attr + pair: pair = 0 + / + +Set the attributes and color pair of the soft labels. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_attr_set_impl(PyObject *module, attr_t attr, int pair) +/*[clinic end generated code: output=b93f23465e232597 input=4502a201917e4bf4]*/ +{ + PyCursesStatefulInitialised(module); + int rtn; +#if _NCURSES_EXTENDED_COLOR_FUNCS + rtn = slk_attr_set(attr, 0, &pair); +#else + rtn = slk_attr_set(attr, (short)pair, NULL); +#endif + return curses_check_err(module, rtn, "slk_attr_set", NULL); +} + +/*[clinic input] +_curses.slk_color + + pair: pair + / + +Set the color pair of the soft labels. +[clinic start generated code]*/ + +static PyObject * +_curses_slk_color_impl(PyObject *module, int pair) +/*[clinic end generated code: output=ffe4de805f9c65f5 input=b1e691a9cc6177ee]*/ +{ + PyCursesStatefulInitialised(module); + return curses_check_err(module, slk_color((short)pair), "slk_color", NULL); +} + #ifdef HAVE_CURSES_USE_ENV /*[clinic input] _curses.use_env @@ -8330,6 +8623,22 @@ static PyMethodDef cursesmodule_methods[] = { _CURSES_SET_TERM_METHODDEF _CURSES_SETSYX_METHODDEF _CURSES_SETUPTERM_METHODDEF + _CURSES_SLK_INIT_METHODDEF + _CURSES_SLK_SET_METHODDEF + _CURSES_SLK_LABEL_METHODDEF + _CURSES_SLK_REFRESH_METHODDEF + _CURSES_SLK_NOUTREFRESH_METHODDEF + _CURSES_SLK_CLEAR_METHODDEF + _CURSES_SLK_RESTORE_METHODDEF + _CURSES_SLK_TOUCH_METHODDEF + _CURSES_SLK_ATTRON_METHODDEF + _CURSES_SLK_ATTROFF_METHODDEF + _CURSES_SLK_ATTRSET_METHODDEF + _CURSES_SLK_ATTR_METHODDEF + _CURSES_SLK_ATTR_ON_METHODDEF + _CURSES_SLK_ATTR_OFF_METHODDEF + _CURSES_SLK_ATTR_SET_METHODDEF + _CURSES_SLK_COLOR_METHODDEF _CURSES_START_COLOR_METHODDEF _CURSES_TERMATTRS_METHODDEF _CURSES_TERM_ATTRS_METHODDEF diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index 1bd1e9b2554b..78619842f97f 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -5433,6 +5433,447 @@ PyDoc_STRVAR(_curses_unget_wch__doc__, #define _CURSES_UNGET_WCH_METHODDEF \ {"unget_wch", (PyCFunction)_curses_unget_wch, METH_O, _curses_unget_wch__doc__}, +PyDoc_STRVAR(_curses_slk_init__doc__, +"slk_init($module, fmt=0, /)\n" +"--\n" +"\n" +"Reserve a line for soft labels and choose their layout.\n" +"\n" +" fmt\n" +" Label layout: 0 = 3-2-3, 1 = 4-4 (8 labels each); 2 = 4-4-4,\n" +" 3 = 4-4-4 with an index line (12 labels each, ncurses extensions).\n" +"\n" +"Must be called before initscr() or newterm()."); + +#define _CURSES_SLK_INIT_METHODDEF \ + {"slk_init", _PyCFunction_CAST(_curses_slk_init), METH_FASTCALL, _curses_slk_init__doc__}, + +static PyObject * +_curses_slk_init_impl(PyObject *module, int fmt); + +static PyObject * +_curses_slk_init(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fmt = 0; + + if (!_PyArg_CheckPositional("slk_init", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + fmt = PyLong_AsInt(args[0]); + if (fmt == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _curses_slk_init_impl(module, fmt); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_slk_set__doc__, +"slk_set($module, labnum, label, justify=0, /)\n" +"--\n" +"\n" +"Set the text of a soft label.\n" +"\n" +" labnum\n" +" The label number (1 to 8, or 1 to 12 in a 12-label layout).\n" +" label\n" +" The text to display.\n" +" justify\n" +" 0 = left, 1 = center, 2 = right."); + +#define _CURSES_SLK_SET_METHODDEF \ + {"slk_set", _PyCFunction_CAST(_curses_slk_set), METH_FASTCALL, _curses_slk_set__doc__}, + +static PyObject * +_curses_slk_set_impl(PyObject *module, int labnum, PyObject *label, + int justify); + +static PyObject * +_curses_slk_set(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int labnum; + PyObject *label; + int justify = 0; + + if (!_PyArg_CheckPositional("slk_set", nargs, 2, 3)) { + goto exit; + } + labnum = PyLong_AsInt(args[0]); + if (labnum == -1 && PyErr_Occurred()) { + goto exit; + } + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("slk_set", "argument 2", "str", args[1]); + goto exit; + } + label = args[1]; + if (nargs < 3) { + goto skip_optional; + } + justify = PyLong_AsInt(args[2]); + if (justify == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _curses_slk_set_impl(module, labnum, label, justify); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_slk_label__doc__, +"slk_label($module, labnum, /)\n" +"--\n" +"\n" +"Return the current text of a soft label.\n" +"\n" +" labnum\n" +" The label number."); + +#define _CURSES_SLK_LABEL_METHODDEF \ + {"slk_label", (PyCFunction)_curses_slk_label, METH_O, _curses_slk_label__doc__}, + +static PyObject * +_curses_slk_label_impl(PyObject *module, int labnum); + +static PyObject * +_curses_slk_label(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int labnum; + + labnum = PyLong_AsInt(arg); + if (labnum == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_slk_label_impl(module, labnum); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_slk_refresh__doc__, +"slk_refresh($module, /)\n" +"--\n" +"\n" +"Update the soft labels on the screen."); + +#define _CURSES_SLK_REFRESH_METHODDEF \ + {"slk_refresh", (PyCFunction)_curses_slk_refresh, METH_NOARGS, _curses_slk_refresh__doc__}, + +static PyObject * +_curses_slk_refresh_impl(PyObject *module); + +static PyObject * +_curses_slk_refresh(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_slk_refresh_impl(module); +} + +PyDoc_STRVAR(_curses_slk_noutrefresh__doc__, +"slk_noutrefresh($module, /)\n" +"--\n" +"\n" +"Update the soft labels on the virtual screen only."); + +#define _CURSES_SLK_NOUTREFRESH_METHODDEF \ + {"slk_noutrefresh", (PyCFunction)_curses_slk_noutrefresh, METH_NOARGS, _curses_slk_noutrefresh__doc__}, + +static PyObject * +_curses_slk_noutrefresh_impl(PyObject *module); + +static PyObject * +_curses_slk_noutrefresh(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_slk_noutrefresh_impl(module); +} + +PyDoc_STRVAR(_curses_slk_clear__doc__, +"slk_clear($module, /)\n" +"--\n" +"\n" +"Erase the soft labels from the screen."); + +#define _CURSES_SLK_CLEAR_METHODDEF \ + {"slk_clear", (PyCFunction)_curses_slk_clear, METH_NOARGS, _curses_slk_clear__doc__}, + +static PyObject * +_curses_slk_clear_impl(PyObject *module); + +static PyObject * +_curses_slk_clear(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_slk_clear_impl(module); +} + +PyDoc_STRVAR(_curses_slk_restore__doc__, +"slk_restore($module, /)\n" +"--\n" +"\n" +"Restore the soft labels after a preceding slk_clear()."); + +#define _CURSES_SLK_RESTORE_METHODDEF \ + {"slk_restore", (PyCFunction)_curses_slk_restore, METH_NOARGS, _curses_slk_restore__doc__}, + +static PyObject * +_curses_slk_restore_impl(PyObject *module); + +static PyObject * +_curses_slk_restore(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_slk_restore_impl(module); +} + +PyDoc_STRVAR(_curses_slk_touch__doc__, +"slk_touch($module, /)\n" +"--\n" +"\n" +"Force the soft labels to be redrawn by the next slk_refresh()."); + +#define _CURSES_SLK_TOUCH_METHODDEF \ + {"slk_touch", (PyCFunction)_curses_slk_touch, METH_NOARGS, _curses_slk_touch__doc__}, + +static PyObject * +_curses_slk_touch_impl(PyObject *module); + +static PyObject * +_curses_slk_touch(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_slk_touch_impl(module); +} + +PyDoc_STRVAR(_curses_slk_attron__doc__, +"slk_attron($module, attr, /)\n" +"--\n" +"\n" +"Add the given chtype attributes to the soft labels."); + +#define _CURSES_SLK_ATTRON_METHODDEF \ + {"slk_attron", (PyCFunction)_curses_slk_attron, METH_O, _curses_slk_attron__doc__}, + +static PyObject * +_curses_slk_attron_impl(PyObject *module, long attr); + +static PyObject * +_curses_slk_attron(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + long attr; + + attr = PyLong_AsLong(arg); + if (attr == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_slk_attron_impl(module, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_slk_attroff__doc__, +"slk_attroff($module, attr, /)\n" +"--\n" +"\n" +"Remove the given chtype attributes from the soft labels."); + +#define _CURSES_SLK_ATTROFF_METHODDEF \ + {"slk_attroff", (PyCFunction)_curses_slk_attroff, METH_O, _curses_slk_attroff__doc__}, + +static PyObject * +_curses_slk_attroff_impl(PyObject *module, long attr); + +static PyObject * +_curses_slk_attroff(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + long attr; + + attr = PyLong_AsLong(arg); + if (attr == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_slk_attroff_impl(module, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_slk_attrset__doc__, +"slk_attrset($module, attr, /)\n" +"--\n" +"\n" +"Set the chtype attributes of the soft labels."); + +#define _CURSES_SLK_ATTRSET_METHODDEF \ + {"slk_attrset", (PyCFunction)_curses_slk_attrset, METH_O, _curses_slk_attrset__doc__}, + +static PyObject * +_curses_slk_attrset_impl(PyObject *module, long attr); + +static PyObject * +_curses_slk_attrset(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + long attr; + + attr = PyLong_AsLong(arg); + if (attr == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_slk_attrset_impl(module, attr); + +exit: + return return_value; +} + +#if defined(NCURSES_EXT_FUNCS) + +PyDoc_STRVAR(_curses_slk_attr__doc__, +"slk_attr($module, /)\n" +"--\n" +"\n" +"Return the current chtype attributes of the soft labels."); + +#define _CURSES_SLK_ATTR_METHODDEF \ + {"slk_attr", (PyCFunction)_curses_slk_attr, METH_NOARGS, _curses_slk_attr__doc__}, + +static PyObject * +_curses_slk_attr_impl(PyObject *module); + +static PyObject * +_curses_slk_attr(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_slk_attr_impl(module); +} + +#endif /* defined(NCURSES_EXT_FUNCS) */ + +PyDoc_STRVAR(_curses_slk_attr_on__doc__, +"slk_attr_on($module, attr, /)\n" +"--\n" +"\n" +"Turn on attributes of the soft labels without affecting others."); + +#define _CURSES_SLK_ATTR_ON_METHODDEF \ + {"slk_attr_on", (PyCFunction)_curses_slk_attr_on, METH_O, _curses_slk_attr_on__doc__}, + +static PyObject * +_curses_slk_attr_on_impl(PyObject *module, attr_t attr); + +static PyObject * +_curses_slk_attr_on(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + attr_t attr; + + if (!attr_converter(arg, &attr)) { + goto exit; + } + return_value = _curses_slk_attr_on_impl(module, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_slk_attr_off__doc__, +"slk_attr_off($module, attr, /)\n" +"--\n" +"\n" +"Turn off attributes of the soft labels without affecting others."); + +#define _CURSES_SLK_ATTR_OFF_METHODDEF \ + {"slk_attr_off", (PyCFunction)_curses_slk_attr_off, METH_O, _curses_slk_attr_off__doc__}, + +static PyObject * +_curses_slk_attr_off_impl(PyObject *module, attr_t attr); + +static PyObject * +_curses_slk_attr_off(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + attr_t attr; + + if (!attr_converter(arg, &attr)) { + goto exit; + } + return_value = _curses_slk_attr_off_impl(module, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_slk_attr_set__doc__, +"slk_attr_set($module, attr, pair=0, /)\n" +"--\n" +"\n" +"Set the attributes and color pair of the soft labels."); + +#define _CURSES_SLK_ATTR_SET_METHODDEF \ + {"slk_attr_set", _PyCFunction_CAST(_curses_slk_attr_set), METH_FASTCALL, _curses_slk_attr_set__doc__}, + +static PyObject * +_curses_slk_attr_set_impl(PyObject *module, attr_t attr, int pair); + +static PyObject * +_curses_slk_attr_set(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + attr_t attr; + int pair = 0; + + if (!_PyArg_CheckPositional("slk_attr_set", nargs, 1, 2)) { + goto exit; + } + if (!attr_converter(args[0], &attr)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!pair_converter(args[1], &pair)) { + goto exit; + } +skip_optional: + return_value = _curses_slk_attr_set_impl(module, attr, pair); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_slk_color__doc__, +"slk_color($module, pair, /)\n" +"--\n" +"\n" +"Set the color pair of the soft labels."); + +#define _CURSES_SLK_COLOR_METHODDEF \ + {"slk_color", (PyCFunction)_curses_slk_color, METH_O, _curses_slk_color__doc__}, + +static PyObject * +_curses_slk_color_impl(PyObject *module, int pair); + +static PyObject * +_curses_slk_color(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int pair; + + if (!pair_converter(arg, &pair)) { + goto exit; + } + return_value = _curses_slk_color_impl(module, pair); + +exit: + return return_value; +} + #if defined(HAVE_CURSES_USE_ENV) PyDoc_STRVAR(_curses_use_env__doc__, @@ -5718,6 +6159,10 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored #define _CURSES_TYPEAHEAD_METHODDEF #endif /* !defined(_CURSES_TYPEAHEAD_METHODDEF) */ +#ifndef _CURSES_SLK_ATTR_METHODDEF + #define _CURSES_SLK_ATTR_METHODDEF +#endif /* !defined(_CURSES_SLK_ATTR_METHODDEF) */ + #ifndef _CURSES_USE_ENV_METHODDEF #define _CURSES_USE_ENV_METHODDEF #endif /* !defined(_CURSES_USE_ENV_METHODDEF) */ @@ -5729,4 +6174,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored #ifndef _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF #define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_ASSUME_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=0cf212f804ab3d85 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=55829d2ef2b559a0 input=a9049054013a1b77]*/ -- 2.47.3