From 66a825a3ebad060ef679845cb31a85b3acf904bd Mon Sep 17 00:00:00 2001 From: Imre Eilertsen Date: Mon, 1 Dec 2025 17:09:39 +0100 Subject: [PATCH 1/6] Add files via upload --- py314/_curses_panel.c | 871 +++++++ py314/_cursesmodule.c | 5648 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 6519 insertions(+) create mode 100644 py314/_curses_panel.c create mode 100644 py314/_cursesmodule.c diff --git a/py314/_curses_panel.c b/py314/_curses_panel.c new file mode 100644 index 0000000..3b46fdf --- /dev/null +++ b/py314/_curses_panel.c @@ -0,0 +1,871 @@ +/* + * Interface to the ncurses panel library + * + * Original version by Thomas Gellekum + */ + +/* Release Number */ + +static const char PyCursesVersion[] = "2.1"; + +/* Includes */ + +// clinic/_curses_panel.c.h uses internal pycore_modsupport.h API +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + +#include "Python.h" + +#define CURSES_PANEL_MODULE +#include "py_curses.h" + +#if defined(HAVE_NCURSESW_PANEL_H) +# include +#elif defined(HAVE_NCURSES_PANEL_H) +# include +#elif defined(HAVE_PANEL_H) +# include +#endif + +typedef struct { + PyObject *error; + PyTypeObject *PyCursesPanel_Type; +} _curses_panel_state; + +typedef struct PyCursesPanelObject PyCursesPanelObject; + +static inline _curses_panel_state * +get_curses_panel_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (_curses_panel_state *)state; +} + +static inline _curses_panel_state * +get_curses_panel_state_by_panel(PyCursesPanelObject *panel) +{ + /* + * Note: 'state' may be NULL if Py_TYPE(panel) is not a heap + * type associated with this module, but the compiler would + * have likely already complained with an "invalid pointer + * type" at compile-time. + * + * To make it more robust, all functions recovering a module's + * state from an object should expect to return NULL with an + * exception set (in contrast to functions recovering a module's + * state from a module itself). + */ + void *state = PyType_GetModuleState(Py_TYPE(panel)); + assert(state != NULL); + return (_curses_panel_state *)state; +} + +static int +_curses_panel_clear(PyObject *mod) +{ + _curses_panel_state *state = get_curses_panel_state(mod); + Py_CLEAR(state->error); + Py_CLEAR(state->PyCursesPanel_Type); + return 0; +} + +static int +_curses_panel_traverse(PyObject *mod, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(mod)); + _curses_panel_state *state = get_curses_panel_state(mod); + Py_VISIT(state->error); + Py_VISIT(state->PyCursesPanel_Type); + return 0; +} + +static void +_curses_panel_free(void *mod) +{ + (void)_curses_panel_clear((PyObject *)mod); +} + +/* Utility Error Procedures + * + * The naming and implementations are identical to those in _cursesmodule.c. + * Functions that are not yet needed (for instance, reporting an ERR value + * from a module-wide function, namely curses_panel_set_error()) are + * omitted and should only be added if needed. + */ + +static void +_curses_panel_format_error(_curses_panel_state *state, + const char *curses_funcname, + const char *python_funcname, + const char *return_value, + const char *default_message) +{ + assert(!PyErr_Occurred()); + if (python_funcname == NULL && curses_funcname == NULL) { + PyErr_SetString(state->error, default_message); + } + else if (python_funcname == NULL) { + (void)PyErr_Format(state->error, CURSES_ERROR_FORMAT, + curses_funcname, return_value); + } + else { + assert(python_funcname != NULL); + (void)PyErr_Format(state->error, CURSES_ERROR_VERBOSE_FORMAT, + curses_funcname, python_funcname, return_value); + } +} + +/* + * Format a curses error for a function that returned ERR. + * + * Specify a non-NULL 'python_funcname' when the latter differs from + * 'curses_funcname'. If both names are NULL, uses the 'catchall_ERR' + * message instead. + */ +static void +_curses_panel_set_error(_curses_panel_state *state, + const char *curses_funcname, + const char *python_funcname) +{ + _curses_panel_format_error(state, curses_funcname, python_funcname, + "ERR", catchall_ERR); +} + +/* + * Format a curses error for a function that returned NULL. + * + * Specify a non-NULL 'python_funcname' when the latter differs from + * 'curses_funcname'. If both names are NULL, uses the 'catchall_NULL' + * message instead. + */ +static void +_curses_panel_set_null_error(_curses_panel_state *state, + const char *curses_funcname, + const char *python_funcname) +{ + _curses_panel_format_error(state, curses_funcname, python_funcname, + "NULL", catchall_NULL); +} + +/* Same as _curses_panel_set_null_error() for a module object. */ +static void +curses_panel_set_null_error(PyObject *module, + const char *curses_funcname, + const char *python_funcname) +{ + _curses_panel_state *state = get_curses_panel_state(module); + _curses_panel_set_null_error(state, curses_funcname, python_funcname); +} + +/* Same as _curses_panel_set_error() for a panel object. */ +static void +curses_panel_panel_set_error(PyCursesPanelObject *panel, + const char *curses_funcname, + const char *python_funcname) +{ + _curses_panel_state *state = get_curses_panel_state_by_panel(panel); + _curses_panel_set_error(state, curses_funcname, python_funcname); +} + +/* Same as _curses_panel_set_null_error() for a panel object. */ +static void +curses_panel_panel_set_null_error(PyCursesPanelObject *panel, + const char *curses_funcname, + const char *python_funcname) +{ + _curses_panel_state *state = get_curses_panel_state_by_panel(panel); + _curses_panel_set_null_error(state, curses_funcname, python_funcname); +} + +/* + * Indicate that a panel object couldn't be found. + * + * Use it for the following constructions: + * + * PROC caller_funcname: + * pan = called_funcname() + * find_po(panel) + * + * PROC caller_funcname: + * find_po(self->pan) +*/ +static void +curses_panel_notfound_error(const char *called_funcname, + const char *caller_funcname) +{ + assert(!(called_funcname == NULL && caller_funcname == NULL)); + if (caller_funcname == NULL) { + (void)PyErr_Format(PyExc_RuntimeError, + "%s(): cannot find panel object", + called_funcname); + } + else { + (void)PyErr_Format(PyExc_RuntimeError, + "%s() (called by %s()): cannot find panel object", + called_funcname, caller_funcname); + } +} + +/* Utility Functions */ + +/* + * Check the return code from a curses function, returning None + * on success and setting an exception on error. + */ + +/* + * Return None if 'code' is different from ERR (implementation-defined). + * Otherwise, set an exception using curses_panel_panel_set_error() and + * the remaining arguments, and return NULL. + */ +static PyObject * +curses_panel_panel_check_err(PyCursesPanelObject *panel, int code, + const char *curses_funcname, + const char *python_funcname) +{ + if (code != ERR) { + Py_RETURN_NONE; + } + curses_panel_panel_set_error(panel, curses_funcname, python_funcname); + return NULL; +} + +/***************************************************************************** + The Panel Object +******************************************************************************/ + +/* Definition of the panel object and panel type */ + +typedef struct PyCursesPanelObject { + PyObject_HEAD + PANEL *pan; + PyCursesWindowObject *wo; /* for reference counts */ +} PyCursesPanelObject; + +#define _PyCursesPanelObject_CAST(op) ((PyCursesPanelObject *)(op)) + +/* Some helper functions. The problem is that there's always a window + associated with a panel. To ensure that Python's GC doesn't pull + this window from under our feet we need to keep track of references + to the corresponding window object within Python. We can't use + dupwin(oldwin) to keep a copy of the curses WINDOW because the + contents of oldwin is copied only once; code like + + win = newwin(...) + pan = win.panel() + win.addstr(some_string) + pan.window().addstr(other_string) + + will fail. */ + +/* We keep a linked list of PyCursesPanelObjects, lop. A list should + suffice, I don't expect more than a handful or at most a few + dozens of panel objects within a typical program. */ +typedef struct _list_of_panels { + PyCursesPanelObject *po; + struct _list_of_panels *next; +} list_of_panels; + +/* list anchor */ +static list_of_panels *lop; + +/* Insert a new panel object into lop */ +static int +insert_lop(PyCursesPanelObject *po) +{ + list_of_panels *new; + + if ((new = (list_of_panels *)PyMem_Malloc(sizeof(list_of_panels))) == NULL) { + PyErr_NoMemory(); + return -1; + } + new->po = po; + new->next = lop; + lop = new; + return 0; +} + +/* Remove the panel object from lop. + * + * Return -1 on error but do NOT set an exception; otherwise return 0. + */ +static int +remove_lop(PyCursesPanelObject *po) +{ + list_of_panels *temp, *n; + + temp = lop; + if (temp->po == po) { + lop = temp->next; + PyMem_Free(temp); + return 0; + } + while (temp->next == NULL || temp->next->po != po) { + if (temp->next == NULL) { + return -1; + } + temp = temp->next; + } + n = temp->next->next; + PyMem_Free(temp->next); + temp->next = n; + return 0; +} + +/* Return the panel object that corresponds to pan */ +static PyCursesPanelObject * +find_po_impl(PANEL *pan) +{ + list_of_panels *temp; + for (temp = lop; temp->po->pan != pan; temp = temp->next) + if (temp->next == NULL) return NULL; /* not found!? */ + return temp->po; +} + +/* Same as find_po_impl() but with caller context information. */ +static PyCursesPanelObject * +find_po(PANEL *pan, const char *called_funcname, const char *caller_funcname) +{ + PyCursesPanelObject *res = find_po_impl(pan); + if (res == NULL) { + curses_panel_notfound_error(called_funcname, caller_funcname); + } + return res; +} + +/*[clinic input] +module _curses_panel +class _curses_panel.panel "PyCursesPanelObject *" "&PyCursesPanel_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2f4ef263ca850a31]*/ + +#include "clinic/_curses_panel.c.h" + +/* ------------- PANEL routines --------------- */ + +/*[clinic input] +_curses_panel.panel.bottom + +Push the panel to the bottom of the stack. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_bottom_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=7aa7d14d7e1d1ce6 input=b6c920c071b61e2e]*/ +{ + int rtn = bottom_panel(self->pan); + return curses_panel_panel_check_err(self, rtn, "bottom_panel", "bottom"); +} + +/*[clinic input] +@permit_long_docstring_body +_curses_panel.panel.hide + +Hide the panel. + +This does not delete the object, it just makes the window on screen invisible. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_hide_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=a7bbbd523e1eab49 input=9071b463a39a1a6a]*/ +{ + int rtn = hide_panel(self->pan); + return curses_panel_panel_check_err(self, rtn, "hide_panel", "hide"); +} + +/*[clinic input] +_curses_panel.panel.show + +Display the panel (which might have been hidden). +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_show_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=6b4553ab45c97769 input=57b167bbefaa3755]*/ +{ + int rtn = show_panel(self->pan); + return curses_panel_panel_check_err(self, rtn, "show_panel", "show"); +} + +/*[clinic input] +_curses_panel.panel.top + +Push panel to the top of the stack. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_top_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=0f5f2f8cdd2d1777 input=be33975ec3ca0e9a]*/ +{ + int rtn = top_panel(self->pan); + return curses_panel_panel_check_err(self, rtn, "top_panel", "top"); +} + +/* Allocation and deallocation of Panel Objects */ + +static PyObject * +PyCursesPanel_New(_curses_panel_state *state, PANEL *pan, + PyCursesWindowObject *wo) +{ + assert(state != NULL); + PyTypeObject *type = state->PyCursesPanel_Type; + assert(type != NULL); + assert(type->tp_alloc != NULL); + PyCursesPanelObject *po = (PyCursesPanelObject *)type->tp_alloc(type, 0); + if (po == NULL) { + return NULL; + } + + po->pan = pan; + if (insert_lop(po) < 0) { + po->wo = NULL; + Py_DECREF(po); + return NULL; + } + po->wo = (PyCursesWindowObject*)Py_NewRef(wo); + return (PyObject *)po; +} + +static int +PyCursesPanel_Clear(PyObject *op) +{ + PyCursesPanelObject *self = _PyCursesPanelObject_CAST(op); + PyObject *extra = (PyObject *)panel_userptr(self->pan); + if (extra != NULL) { + Py_DECREF(extra); + if (set_panel_userptr(self->pan, NULL) == ERR) { + curses_panel_panel_set_error(self, "set_panel_userptr", NULL); + return -1; + } + } + // self->wo should not be cleared because an associated WINDOW may exist + return 0; +} + +static void +PyCursesPanel_Dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + + PyCursesPanelObject *po = _PyCursesPanelObject_CAST(self); + if (PyCursesPanel_Clear(self) < 0) { + PyErr_FormatUnraisable("Exception ignored in PyCursesPanel_Dealloc()"); + } + if (del_panel(po->pan) == ERR && !PyErr_Occurred()) { + curses_panel_panel_set_error(po, "del_panel", "__del__"); + PyErr_FormatUnraisable("Exception ignored in PyCursesPanel_Dealloc()"); + } + if (po->wo != NULL) { + Py_DECREF(po->wo); + if (remove_lop(po) < 0) { + PyErr_SetString(PyExc_RuntimeError, "__del__: no panel object to delete"); + PyErr_FormatUnraisable("Exception ignored in PyCursesPanel_Dealloc()"); + } + } + tp->tp_free(po); + Py_DECREF(tp); +} + +static int +PyCursesPanel_Traverse(PyObject *op, visitproc visit, void *arg) +{ + PyCursesPanelObject *self = _PyCursesPanelObject_CAST(op); + Py_VISIT(Py_TYPE(op)); + Py_VISIT(panel_userptr(self->pan)); + Py_VISIT(self->wo); + return 0; +} + +/* panel_above(NULL) returns the bottom panel in the stack. To get + this behaviour we use curses.panel.bottom_panel(). */ +/*[clinic input] +_curses_panel.panel.above + +Return the panel above the current panel. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_above_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=70ac06d25fd3b4da input=c059994022976788]*/ +{ + PANEL *pan; + PyCursesPanelObject *po; + + pan = panel_above(self->pan); + if (pan == NULL) { /* valid output: it means no panel exists yet */ + Py_RETURN_NONE; + } + po = find_po(pan, "panel_above", "above"); + return Py_XNewRef(po); +} + +/* panel_below(NULL) returns the top panel in the stack. To get + this behaviour we use curses.panel.top_panel(). */ +/*[clinic input] +_curses_panel.panel.below + +Return the panel below the current panel. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_below_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=282861122e06e3de input=cc08f61936d297c6]*/ +{ + PANEL *pan; + PyCursesPanelObject *po; + + pan = panel_below(self->pan); + if (pan == NULL) { /* valid output: it means no panel exists yet */ + Py_RETURN_NONE; + } + po = find_po(pan, "panel_below", "below"); + return Py_XNewRef(po); +} + +/*[clinic input] +_curses_panel.panel.hidden + +Return True if the panel is hidden (not visible), False otherwise. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_hidden_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=66eebd1ab4501a71 input=453d4b4fce25e21a]*/ +{ + if (panel_hidden(self->pan)) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +/*[clinic input] +_curses_panel.panel.move + + y: int + x: int + / + +Move the panel to the screen coordinates (y, x). +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_move_impl(PyCursesPanelObject *self, int y, int x) +/*[clinic end generated code: output=d867535a89777415 input=e0b36b78acc03fba]*/ +{ + int rtn = move_panel(self->pan, y, x); + return curses_panel_panel_check_err(self, rtn, "move_panel", "move"); +} + +/*[clinic input] +_curses_panel.panel.window + +Return the window object associated with the panel. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_window_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=5f05940d4106b4cb input=6067353d2c307901]*/ +{ + return Py_NewRef(self->wo); +} + +/*[clinic input] +_curses_panel.panel.replace + + win: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + / + +Change the window associated with the panel to the window win. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_replace_impl(PyCursesPanelObject *self, + PyCursesWindowObject *win) +/*[clinic end generated code: output=2253a95f7b287255 input=4b1c4283987d9dfa]*/ +{ + PyCursesPanelObject *po = find_po(self->pan, "replace", NULL); + if (po == NULL) { + return NULL; + } + + int rtn = replace_panel(self->pan, win->win); + if (rtn == ERR) { + curses_panel_panel_set_error(self, "replace_panel", "replace"); + return NULL; + } + Py_SETREF(po->wo, (PyCursesWindowObject*)Py_NewRef(win)); + Py_RETURN_NONE; +} + +/*[clinic input] +_curses_panel.panel.set_userptr + + obj: object + / + +Set the panel's user pointer to obj. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_set_userptr_impl(PyCursesPanelObject *self, + PyObject *obj) +/*[clinic end generated code: output=7fa1fd23f69db71e input=d2c6a9dbefabbf39]*/ +{ + PyCursesInitialised; + Py_INCREF(obj); + PyObject *oldobj = (PyObject *) panel_userptr(self->pan); + int rc = set_panel_userptr(self->pan, (void*)obj); + if (rc == ERR) { + /* In case of an ncurses error, decref the new object again */ + Py_DECREF(obj); + curses_panel_panel_set_error(self, "set_panel_userptr", "set_userptr"); + return NULL; + } + Py_XDECREF(oldobj); + Py_RETURN_NONE; +} + +/*[clinic input] +_curses_panel.panel.userptr + +Return the user pointer for the panel. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_userptr_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=e849c307b5dc9237 input=f78b7a47aef0fd50]*/ +{ + PyCursesInitialised; + PyObject *obj = (PyObject *) panel_userptr(self->pan); + if (obj == NULL) { + curses_panel_panel_set_null_error(self, "panel_userptr", "userptr"); + return NULL; + } + + return Py_NewRef(obj); +} + + +/* Module interface */ + +static PyMethodDef PyCursesPanel_Methods[] = { + _CURSES_PANEL_PANEL_ABOVE_METHODDEF + _CURSES_PANEL_PANEL_BELOW_METHODDEF + _CURSES_PANEL_PANEL_BOTTOM_METHODDEF + _CURSES_PANEL_PANEL_HIDDEN_METHODDEF + _CURSES_PANEL_PANEL_HIDE_METHODDEF + _CURSES_PANEL_PANEL_MOVE_METHODDEF + _CURSES_PANEL_PANEL_REPLACE_METHODDEF + _CURSES_PANEL_PANEL_SET_USERPTR_METHODDEF + _CURSES_PANEL_PANEL_SHOW_METHODDEF + _CURSES_PANEL_PANEL_TOP_METHODDEF + _CURSES_PANEL_PANEL_USERPTR_METHODDEF + _CURSES_PANEL_PANEL_WINDOW_METHODDEF + {NULL, NULL} /* sentinel */ +}; + +/* -------------------------------------------------------*/ + +static PyType_Slot PyCursesPanel_Type_slots[] = { + {Py_tp_clear, PyCursesPanel_Clear}, + {Py_tp_dealloc, PyCursesPanel_Dealloc}, + {Py_tp_traverse, PyCursesPanel_Traverse}, + {Py_tp_methods, PyCursesPanel_Methods}, + {0, 0}, +}; + +static PyType_Spec PyCursesPanel_Type_spec = { + .name = "_curses_panel.panel", + .basicsize = sizeof(PyCursesPanelObject), + .flags = ( + Py_TPFLAGS_DEFAULT + | Py_TPFLAGS_DISALLOW_INSTANTIATION + | Py_TPFLAGS_IMMUTABLETYPE + | Py_TPFLAGS_HAVE_GC + ), + .slots = PyCursesPanel_Type_slots +}; + +/* Wrapper for panel_above(NULL). This function returns the bottom + panel of the stack, so it's renamed to bottom_panel(). + panel.above() *requires* a panel object in the first place which + may be undesirable. */ +/*[clinic input] +_curses_panel.bottom_panel + +Return the bottom panel in the panel stack. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_bottom_panel_impl(PyObject *module) +/*[clinic end generated code: output=3aba9f985f4c2bd0 input=634c2a8078b3d7e4]*/ +{ + PANEL *pan; + PyCursesPanelObject *po; + + PyCursesInitialised; + + pan = panel_above(NULL); + if (pan == NULL) { /* valid output: it means no panel exists yet */ + Py_RETURN_NONE; + } + po = find_po(pan, "panel_above", "bottom_panel"); + return Py_XNewRef(po); +} + +/*[clinic input] +_curses_panel.new_panel + + win: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + / + +Return a panel object, associating it with the given window win. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_new_panel_impl(PyObject *module, PyCursesWindowObject *win) +/*[clinic end generated code: output=45e948e0176a9bd2 input=74d4754e0ebe4800]*/ +{ + PANEL *pan = new_panel(win->win); + if (pan == NULL) { + curses_panel_set_null_error(module, "new_panel", NULL); + return NULL; + } + _curses_panel_state *state = get_curses_panel_state(module); + return PyCursesPanel_New(state, pan, win); +} + + +/* Wrapper for panel_below(NULL). This function returns the top panel + of the stack, so it's renamed to top_panel(). panel.below() + *requires* a panel object in the first place which may be + undesirable. */ +/*[clinic input] +_curses_panel.top_panel + +Return the top panel in the panel stack. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_top_panel_impl(PyObject *module) +/*[clinic end generated code: output=86704988bea8508e input=e62d6278dba39e79]*/ +{ + PANEL *pan; + PyCursesPanelObject *po; + + PyCursesInitialised; + + pan = panel_below(NULL); + if (pan == NULL) { /* valid output: it means no panel exists yet */ + Py_RETURN_NONE; + } + po = find_po(pan, "panel_below", "top_panel"); + return Py_XNewRef(po); +} + +/*[clinic input] +_curses_panel.update_panels + +Updates the virtual screen after changes in the panel stack. + +This does not call curses.doupdate(), so you'll have to do this yourself. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_update_panels_impl(PyObject *module) +/*[clinic end generated code: output=2f3b4c2e03d90ded input=5299624c9a708621]*/ +{ + PyCursesInitialised; + update_panels(); + Py_RETURN_NONE; +} + +/* List of functions defined in the module */ + +static PyMethodDef PyCurses_methods[] = { + _CURSES_PANEL_BOTTOM_PANEL_METHODDEF + _CURSES_PANEL_NEW_PANEL_METHODDEF + _CURSES_PANEL_TOP_PANEL_METHODDEF + _CURSES_PANEL_UPDATE_PANELS_METHODDEF + {NULL, NULL} /* sentinel */ +}; + +/* Initialization function for the module */ +static int +_curses_panel_exec(PyObject *mod) +{ + _curses_panel_state *state = get_curses_panel_state(mod); + /* Initialize object type */ + state->PyCursesPanel_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + mod, &PyCursesPanel_Type_spec, NULL); + if (state->PyCursesPanel_Type == NULL) { + return -1; + } + + if (PyModule_AddType(mod, state->PyCursesPanel_Type) < 0) { + return -1; + } + + import_curses(); + if (PyErr_Occurred()) { + return -1; + } + + /* For exception _curses_panel.error */ + state->error = PyErr_NewException( + "_curses_panel.error", NULL, NULL); + + if (PyModule_AddObjectRef(mod, "error", state->error) < 0) { + return -1; + } + + /* Make the version available */ + PyObject *v = PyUnicode_FromString(PyCursesVersion); + if (v == NULL) { + return -1; + } + + PyObject *d = PyModule_GetDict(mod); + if (PyDict_SetItemString(d, "version", v) < 0) { + Py_DECREF(v); + return -1; + } + if (PyDict_SetItemString(d, "__version__", v) < 0) { + Py_DECREF(v); + return -1; + } + + Py_DECREF(v); + + return 0; +} + +static PyModuleDef_Slot _curses_slots[] = { + {Py_mod_exec, _curses_panel_exec}, + // XXX gh-103092: fix isolation. + {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, + //{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, + {0, NULL} +}; + +static struct PyModuleDef _curses_panelmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_curses_panel", + .m_size = sizeof(_curses_panel_state), + .m_methods = PyCurses_methods, + .m_slots = _curses_slots, + .m_traverse = _curses_panel_traverse, + .m_clear = _curses_panel_clear, + .m_free = _curses_panel_free +}; + +PyMODINIT_FUNC +PyInit__curses_panel(void) +{ + return PyModuleDef_Init(&_curses_panelmodule); +} diff --git a/py314/_cursesmodule.c b/py314/_cursesmodule.c new file mode 100644 index 0000000..6146434 --- /dev/null +++ b/py314/_cursesmodule.c @@ -0,0 +1,5648 @@ +/* + * This is a curses module for Python. + * + * Based on prior work by Lance Ellinghaus and Oliver Andrich + * Version 1.2 of this module: Copyright 1994 by Lance Ellinghouse, + * Cathedral City, California Republic, United States of America. + * + * Version 1.5b1, heavily extended for ncurses by Oliver Andrich: + * Copyright 1996,1997 by Oliver Andrich, Koblenz, Germany. + * + * Tidied for Python 1.6, and currently maintained by . + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this source file to use, copy, modify, merge, or publish it + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or in any new file that contains a substantial portion of + * this file. + * + * THE AUTHOR MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF + * THE SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT + * EXPRESS OR IMPLIED WARRANTY. THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE, STRICT LIABILITY OR + * ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + + A number of SysV or ncurses functions don't have wrappers yet; if you + need a given function, add it and send a patch. See + https://www.python.org/dev/patches/ for instructions on how to submit + patches to Python. + + Here's a list of currently unsupported functions: + + addchnstr addchstr color_set define_key + del_curterm delscreen dupwin inchnstr inchstr innstr keyok + mcprint mvaddchnstr mvaddchstr mvcur mvinchnstr + mvinchstr mvinnstr mmvwaddchnstr mvwaddchstr + mvwinchnstr mvwinchstr mvwinnstr newterm + restartterm ripoffline scr_dump + scr_init scr_restore scr_set scrl set_curterm set_term setterm + tgetent tgetflag tgetnum tgetstr tgoto timeout tputs + vidattr vidputs waddchnstr waddchstr + wcolor_set winchnstr winchstr winnstr wmouse_trafo wscrl + + 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 + item_opts_on item_term item_userptr item_value item_visible + menu_back menu_driver menu_fore menu_format menu_grey + menu_init menu_items menu_mark menu_opts menu_opts_off + menu_opts_on menu_pad menu_pattern menu_request_by_name + menu_request_name menu_spacing menu_sub menu_term menu_userptr + menu_win new_item new_menu pos_menu_cursor post_menu + scale_menu set_current_item set_item_init set_item_opts + set_item_term set_item_userptr set_item_value set_menu_back + set_menu_fore set_menu_format set_menu_grey set_menu_init + set_menu_items set_menu_mark set_menu_opts set_menu_pad + set_menu_pattern set_menu_spacing set_menu_sub set_menu_term + set_menu_userptr set_menu_win set_top_row top_row unpost_menu + + Form extension (ncurses and probably SYSV): + current_field data_ahead data_behind dup_field + dynamic_fieldinfo field_arg field_back field_buffer + field_count field_fore field_index field_info field_init + field_just field_opts field_opts_off field_opts_on field_pad + field_status field_term field_type field_userptr form_driver + form_fields form_init form_opts form_opts_off form_opts_on + form_page form_request_by_name form_request_name form_sub + form_term form_userptr form_win free_field free_form + link_field link_fieldtype move_field new_field new_form + new_page pos_form_cursor post_form scale_form + set_current_field set_field_back set_field_buffer + set_field_fore set_field_init set_field_just set_field_opts + set_field_pad set_field_status set_field_term set_field_type + set_field_userptr set_fieldtype_arg set_fieldtype_choice + set_form_fields set_form_init set_form_opts set_form_page + set_form_sub set_form_term set_form_userptr set_form_win + set_max_field set_new_page unpost_form + + +*/ + +/* Release Number */ + +static const char PyCursesVersion[] = "2.2"; + +/* Includes */ + +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + +#include "Python.h" +#include "pycore_capsule.h" // _PyCapsule_SetTraverse() +#include "pycore_long.h" // _PyLong_GetZero() +#include "pycore_structseq.h" // _PyStructSequence_NewType() +#include "pycore_fileutils.h" // _Py_set_inheritable + +#ifdef __hpux +#define STRICT_SYSV_CURSES +#endif + +#define CURSES_MODULE +#include "py_curses.h" + +#if defined(HAVE_TERM_H) || defined(__sgi) +/* For termname, longname, putp, tigetflag, tigetnum, tigetstr, tparm + which are not declared in SysV curses and for setupterm. */ +#include +/* Including #defines many common symbols. */ +#undef lines +#undef columns +#endif + +#ifdef HAVE_LANGINFO_H +#include +#endif + +#if !defined(NCURSES_VERSION) && (defined(sgi) || defined(__sun) || defined(SCO5)) +#define STRICT_SYSV_CURSES /* Don't use ncurses extensions */ +typedef chtype attr_t; /* No attr_t type is available */ +#endif + +#if defined(_AIX) +#define STRICT_SYSV_CURSES +#endif + +#if defined(HAVE_NCURSESW) && NCURSES_EXT_FUNCS+0 >= 20170401 && NCURSES_EXT_COLORS+0 >= 20170401 +#define _NCURSES_EXTENDED_COLOR_FUNCS 1 +#else +#define _NCURSES_EXTENDED_COLOR_FUNCS 0 +#endif + +#if _NCURSES_EXTENDED_COLOR_FUNCS +#define _CURSES_COLOR_VAL_TYPE int +#define _CURSES_COLOR_NUM_TYPE int +#define _CURSES_INIT_COLOR_FUNC init_extended_color +#define _CURSES_INIT_PAIR_FUNC init_extended_pair +#define _COLOR_CONTENT_FUNC extended_color_content +#define _CURSES_PAIR_CONTENT_FUNC extended_pair_content +#else +#define _CURSES_COLOR_VAL_TYPE short +#define _CURSES_COLOR_NUM_TYPE short +#define _CURSES_INIT_COLOR_FUNC init_color +#define _CURSES_INIT_PAIR_FUNC init_pair +#define _COLOR_CONTENT_FUNC color_content +#define _CURSES_PAIR_CONTENT_FUNC pair_content +#endif /* _NCURSES_EXTENDED_COLOR_FUNCS */ + +typedef struct { + PyObject *error; // curses exception type + PyTypeObject *window_type; // exposed by PyCursesWindow_Type +} cursesmodule_state; + +static inline cursesmodule_state * +get_cursesmodule_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (cursesmodule_state *)state; +} + +static inline cursesmodule_state * +get_cursesmodule_state_by_cls(PyTypeObject *cls) +{ + void *state = PyType_GetModuleState(cls); + assert(state != NULL); + return (cursesmodule_state *)state; +} + +static inline cursesmodule_state * +get_cursesmodule_state_by_win(PyCursesWindowObject *win) +{ + return get_cursesmodule_state_by_cls(Py_TYPE(win)); +} + +#define _PyCursesWindowObject_CAST(op) ((PyCursesWindowObject *)(op)) + +/*[clinic input] +module _curses +class _curses.window "PyCursesWindowObject *" "clinic_state()->window_type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ae6cb623018f2cbc]*/ + +/* Indicate whether the module has already been loaded or not. */ +static int curses_module_loaded = 0; + +/* Tells whether setupterm() has been called to initialise terminfo. */ +static int curses_setupterm_called = FALSE; + +/* Tells whether initscr() has been called to initialise curses. */ +static int curses_initscr_called = FALSE; + +/* Tells whether start_color() has been called to initialise color usage. */ +static int curses_start_color_called = FALSE; + +static const char *curses_screen_encoding = NULL; + +/* Utility Error Procedures */ + +static void +_curses_format_error(cursesmodule_state *state, + const char *curses_funcname, + const char *python_funcname, + const char *return_value, + const char *default_message) +{ + assert(!PyErr_Occurred()); + if (python_funcname == NULL && curses_funcname == NULL) { + PyErr_SetString(state->error, default_message); + } + else if (python_funcname == NULL) { + (void)PyErr_Format(state->error, CURSES_ERROR_FORMAT, + curses_funcname, return_value); + } + else { + assert(python_funcname != NULL); + (void)PyErr_Format(state->error, CURSES_ERROR_VERBOSE_FORMAT, + curses_funcname, python_funcname, return_value); + } +} + +/* + * Format a curses error for a function that returned ERR. + * + * Specify a non-NULL 'python_funcname' when the latter differs from + * 'curses_funcname'. If both names are NULL, uses the 'catchall_ERR' + * message instead. + */ +static void +_curses_set_error(cursesmodule_state *state, + const char *curses_funcname, + const char *python_funcname) +{ + _curses_format_error(state, curses_funcname, python_funcname, + "ERR", catchall_ERR); +} + +/* + * Format a curses error for a function that returned NULL. + * + * Specify a non-NULL 'python_funcname' when the latter differs from + * 'curses_funcname'. If both names are NULL, uses the 'catchall_NULL' + * message instead. + */ +static inline void +_curses_set_null_error(cursesmodule_state *state, + const char *curses_funcname, + const char *python_funcname) +{ + _curses_format_error(state, curses_funcname, python_funcname, + "NULL", catchall_NULL); +} + +/* Same as _curses_set_error() for a module object. */ +static void +curses_set_error(PyObject *module, + const char *curses_funcname, + const char *python_funcname) +{ + cursesmodule_state *state = get_cursesmodule_state(module); + _curses_set_error(state, curses_funcname, python_funcname); +} + +/* Same as _curses_set_null_error() for a module object. */ +static void +curses_set_null_error(PyObject *module, + const char *curses_funcname, + const char *python_funcname) +{ + cursesmodule_state *state = get_cursesmodule_state(module); + _curses_set_null_error(state, curses_funcname, python_funcname); +} + +/* Same as _curses_set_error() for a Window object. */ +static void +curses_window_set_error(PyCursesWindowObject *win, + const char *curses_funcname, + const char *python_funcname) +{ + cursesmodule_state *state = get_cursesmodule_state_by_win(win); + _curses_set_error(state, curses_funcname, python_funcname); +} + +/* Same as _curses_set_null_error() for a Window object. */ +static void +curses_window_set_null_error(PyCursesWindowObject *win, + const char *curses_funcname, + const char *python_funcname) +{ + cursesmodule_state *state = get_cursesmodule_state_by_win(win); + _curses_set_null_error(state, curses_funcname, python_funcname); +} + +/* Utility Checking Procedures */ + +/* + * Function to check that 'funcname' has been called by testing + * the 'called' boolean. If an error occurs, an exception is + * set and this returns 0. Otherwise, this returns 1. + * + * Since this function can be called in functions that do not + * have a direct access to the module's state, '_curses.error' + * is imported on demand. + * + * Use _PyCursesStatefulCheckFunction() if the module is given. + */ +static int +_PyCursesCheckFunction(int called, const char *funcname) +{ + if (called == TRUE) { + return 1; + } + PyObject *exc = PyImport_ImportModuleAttrString("_curses", "error"); + if (exc != NULL) { + PyErr_Format(exc, CURSES_ERROR_MUST_CALL_FORMAT, funcname); + Py_DECREF(exc); + } + assert(PyErr_Occurred()); + return 0; +} + +/* + * Function to check that 'funcname' has been called by testing + * the 'called'' boolean. If an error occurs, a PyCursesError is + * set and this returns 0. Otherwise this returns 1. + * + * The exception type is obtained from the 'module' state. + */ +static int +_PyCursesStatefulCheckFunction(PyObject *module, + int called, const char *funcname) +{ + if (called == TRUE) { + return 1; + } + cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_Format(state->error, CURSES_ERROR_MUST_CALL_FORMAT, funcname); + return 0; +} + +#define PyCursesStatefulSetupTermCalled(MODULE) \ + do { \ + if (!_PyCursesStatefulCheckFunction(MODULE, \ + curses_setupterm_called, \ + "setupterm")) \ + { \ + return 0; \ + } \ + } while (0) + +#define PyCursesStatefulInitialised(MODULE) \ + do { \ + if (!_PyCursesStatefulCheckFunction(MODULE, \ + curses_initscr_called, \ + "initscr")) \ + { \ + return 0; \ + } \ + } while (0) + +#define PyCursesStatefulInitialisedColor(MODULE) \ + do { \ + if (!_PyCursesStatefulCheckFunction(MODULE, \ + curses_start_color_called, \ + "start_color")) \ + { \ + return 0; \ + } \ + } while (0) + +/* Utility Functions */ + +/* + * Check the return code from a curses function, returning None + * on success and setting an exception on error. + */ + +/* + * Return None if 'code' is different from ERR (implementation-defined). + * Otherwise, set an exception using curses_set_error() and the remaining + * arguments, and return NULL. + */ +static PyObject * +curses_check_err(PyObject *module, int code, + const char *curses_funcname, + const char *python_funcname) +{ + if (code != ERR) { + Py_RETURN_NONE; + } + curses_set_error(module, curses_funcname, python_funcname); + return NULL; +} + +/* Same as curses_check_err() for a Window object. */ +static PyObject * +curses_window_check_err(PyCursesWindowObject *win, int code, + const char *curses_funcname, + const char *python_funcname) +{ + if (code != ERR) { + Py_RETURN_NONE; + } + curses_window_set_error(win, curses_funcname, python_funcname); + return NULL; +} + +/* Convert an object to a byte (an integer of type chtype): + + - int + - bytes of length 1 + - str of length 1 + + Return 1 on success, 0 on error (invalid type or integer overflow). */ +static int +PyCurses_ConvertToChtype(PyCursesWindowObject *win, PyObject *obj, chtype *ch) +{ + long value; + if (PyBytes_Check(obj)) { + if (PyBytes_GET_SIZE(obj) != 1) { + PyErr_Format(PyExc_TypeError, + "expect int or bytes or str of length 1, " + "got a bytes of length %zd", + PyBytes_GET_SIZE(obj)); + return 0; + } + value = (unsigned char)PyBytes_AsString(obj)[0]; + } + else if (PyUnicode_Check(obj)) { + if (PyUnicode_GET_LENGTH(obj) != 1) { + PyErr_Format(PyExc_TypeError, + "expect int or bytes or str of length 1, " + "got a str of length %zi", + PyUnicode_GET_LENGTH(obj)); + return 0; + } + value = PyUnicode_READ_CHAR(obj, 0); + if (128 < value) { + PyObject *bytes; + const char *encoding; + if (win) + encoding = win->encoding; + else + encoding = curses_screen_encoding; + bytes = PyUnicode_AsEncodedString(obj, encoding, NULL); + if (bytes == NULL) + return 0; + if (PyBytes_GET_SIZE(bytes) == 1) + value = (unsigned char)PyBytes_AS_STRING(bytes)[0]; + else + value = -1; + Py_DECREF(bytes); + if (value < 0) + goto overflow; + } + } + else if (PyLong_CheckExact(obj)) { + int long_overflow; + value = PyLong_AsLongAndOverflow(obj, &long_overflow); + if (long_overflow) + goto overflow; + } + else { + PyErr_Format(PyExc_TypeError, + "expect int or bytes or str of length 1, got %s", + Py_TYPE(obj)->tp_name); + return 0; + } + *ch = (chtype)value; + if ((long)*ch != value) + goto overflow; + return 1; + +overflow: + PyErr_SetString(PyExc_OverflowError, + "byte doesn't fit in chtype"); + return 0; +} + +/* Convert an object to a byte (chtype) or a character (cchar_t): + + - int + - bytes of length 1 + - str of length 1 + + Return: + + - 2 if obj is a character (written into *wch) + - 1 if obj is a byte (written into *ch) + - 0 on error: raise an exception */ +static int +PyCurses_ConvertToCchar_t(PyCursesWindowObject *win, PyObject *obj, + chtype *ch +#ifdef HAVE_NCURSESW + , wchar_t *wch +#endif + ) +{ + long value; +#ifdef HAVE_NCURSESW + wchar_t buffer[2]; +#endif + + if (PyUnicode_Check(obj)) { +#ifdef HAVE_NCURSESW + if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) { + PyErr_Format(PyExc_TypeError, + "expect int or bytes or str of length 1, " + "got a str of length %zi", + PyUnicode_GET_LENGTH(obj)); + return 0; + } + *wch = buffer[0]; + return 2; +#else + return PyCurses_ConvertToChtype(win, obj, ch); +#endif + } + else if (PyBytes_Check(obj)) { + if (PyBytes_GET_SIZE(obj) != 1) { + PyErr_Format(PyExc_TypeError, + "expect int or bytes or str of length 1, " + "got a bytes of length %zd", + PyBytes_GET_SIZE(obj)); + return 0; + } + value = (unsigned char)PyBytes_AsString(obj)[0]; + } + else if (PyLong_CheckExact(obj)) { + int overflow; + value = PyLong_AsLongAndOverflow(obj, &overflow); + if (overflow) { + PyErr_SetString(PyExc_OverflowError, + "int doesn't fit in long"); + return 0; + } + } + else { + PyErr_Format(PyExc_TypeError, + "expect int or bytes or str of length 1, got %s", + Py_TYPE(obj)->tp_name); + return 0; + } + + *ch = (chtype)value; + if ((long)*ch != value) { + PyErr_Format(PyExc_OverflowError, + "byte doesn't fit in chtype"); + return 0; + } + return 1; +} + +/* Convert an object to a byte string (char*) or a wide character string + (wchar_t*). Return: + + - 2 if obj is a character string (written into *wch) + - 1 if obj is a byte string (written into *bytes) + - 0 on error: raise an exception */ +static int +PyCurses_ConvertToString(PyCursesWindowObject *win, PyObject *obj, + PyObject **bytes, wchar_t **wstr) +{ + char *str; + if (PyUnicode_Check(obj)) { +#ifdef HAVE_NCURSESW + assert (wstr != NULL); + + *wstr = PyUnicode_AsWideCharString(obj, NULL); + if (*wstr == NULL) + return 0; + return 2; +#else + assert (wstr == NULL); + *bytes = PyUnicode_AsEncodedString(obj, win->encoding, NULL); + if (*bytes == NULL) + return 0; + /* check for embedded null bytes */ + if (PyBytes_AsStringAndSize(*bytes, &str, NULL) < 0) { + Py_CLEAR(*bytes); + return 0; + } + return 1; +#endif + } + else if (PyBytes_Check(obj)) { + *bytes = Py_NewRef(obj); + /* check for embedded null bytes */ + if (PyBytes_AsStringAndSize(*bytes, &str, NULL) < 0) { + Py_DECREF(obj); + return 0; + } + return 1; + } + + PyErr_Format(PyExc_TypeError, "expect bytes or str, got %s", + Py_TYPE(obj)->tp_name); + return 0; +} + +static int +color_allow_default_converter(PyObject *arg, void *ptr) +{ + long color_number; + int overflow; + + color_number = PyLong_AsLongAndOverflow(arg, &overflow); + if (color_number == -1 && PyErr_Occurred()) + return 0; + + if (overflow > 0 || color_number >= COLORS) { + PyErr_Format(PyExc_ValueError, + "Color number is greater than COLORS-1 (%d).", + COLORS - 1); + return 0; + } + else if (overflow < 0 || color_number < 0) { + color_number = -1; + } + + *(int *)ptr = (int)color_number; + return 1; +} + +static int +color_converter(PyObject *arg, void *ptr) +{ + if (!color_allow_default_converter(arg, ptr)) { + return 0; + } + if (*(int *)ptr < 0) { + PyErr_SetString(PyExc_ValueError, + "Color number is less than 0."); + return 0; + } + return 1; +} + +/*[python input] +class color_converter(CConverter): + type = 'int' + converter = 'color_converter' +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=4260d2b6e66b3709]*/ + +/*[python input] +class color_allow_default_converter(CConverter): + type = 'int' + converter = 'color_allow_default_converter' +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=975602bc058a872d]*/ + +static int +pair_converter(PyObject *arg, void *ptr) +{ + long pair_number; + int overflow; + + pair_number = PyLong_AsLongAndOverflow(arg, &overflow); + if (pair_number == -1 && PyErr_Occurred()) + return 0; + +#if _NCURSES_EXTENDED_COLOR_FUNCS + if (overflow > 0 || pair_number > INT_MAX) { + PyErr_Format(PyExc_ValueError, + "Color pair is greater than maximum (%d).", + INT_MAX); + return 0; + } +#else + if (overflow > 0 || pair_number >= COLOR_PAIRS) { + PyErr_Format(PyExc_ValueError, + "Color pair is greater than COLOR_PAIRS-1 (%d).", + COLOR_PAIRS - 1); + return 0; + } +#endif + else if (overflow < 0 || pair_number < 0) { + PyErr_SetString(PyExc_ValueError, + "Color pair is less than 0."); + return 0; + } + + *(int *)ptr = (int)pair_number; + return 1; +} + +/*[python input] +class pair_converter(CConverter): + type = 'int' + converter = 'pair_converter' +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=1a918ae6a1b32af7]*/ + +static int +component_converter(PyObject *arg, void *ptr) +{ + long component; + int overflow; + + component = PyLong_AsLongAndOverflow(arg, &overflow); + if (component == -1 && PyErr_Occurred()) + return 0; + + if (overflow > 0 || component > 1000) { + PyErr_SetString(PyExc_ValueError, + "Color component is greater than 1000"); + return 0; + } + else if (overflow < 0 || component < 0) { + PyErr_SetString(PyExc_ValueError, + "Color component is less than 0"); + return 0; + } + + *(short *)ptr = (short)component; + return 1; +} + +/*[python input] +class component_converter(CConverter): + type = 'short' + converter = 'component_converter' +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=38e9be01d33927fb]*/ + +/***************************************************************************** + The Window Object +******************************************************************************/ + +/* + * Macros for creating a PyCursesWindowObject object's method. + * + * Parameters + * + * X The name of the curses C function or macro to invoke. + * TYPE The function parameter(s) type. + * ERGSTR The format string for construction of the return value. + * PARSESTR The format string for argument parsing. + */ + +#define Window_NoArgNoReturnFunction(X) \ + static PyObject *PyCursesWindow_ ## X \ + (PyObject *op, PyObject *Py_UNUSED(ignored)) \ + { \ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \ + int code = X(self->win); \ + return curses_window_check_err(self, code, # X, NULL); \ + } + +#define Window_NoArgTrueFalseFunction(X) \ + static PyObject * PyCursesWindow_ ## X \ + (PyObject *op, PyObject *Py_UNUSED(ignored)) \ + { \ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \ + return PyBool_FromLong(X(self->win)); \ + } + +#define Window_NoArgNoReturnVoidFunction(X) \ + static PyObject * PyCursesWindow_ ## X \ + (PyObject *op, PyObject *Py_UNUSED(ignored)) \ + { \ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \ + X(self->win); \ + Py_RETURN_NONE; \ + } + +#define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyObject *op, PyObject *Py_UNUSED(ignored)) \ + { \ + TYPE arg1, arg2; \ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \ + X(self->win, arg1, arg2); \ + return Py_BuildValue(ERGSTR, arg1, arg2); \ + } + +#define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyObject *op, PyObject *args) \ + { \ + TYPE arg1; \ + if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) { \ + return NULL; \ + } \ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \ + X(self->win, arg1); \ + Py_RETURN_NONE; \ + } + +#define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyObject *op, PyObject *args) \ + { \ + TYPE arg1; \ + if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) { \ + return NULL; \ + } \ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \ + int code = X(self->win, arg1); \ + return curses_window_check_err(self, code, # X, NULL); \ + } + +#define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyObject *op, PyObject *args) \ + { \ + TYPE arg1, arg2; \ + if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) { \ + return NULL; \ + } \ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \ + int code = X(self->win, arg1, arg2); \ + return curses_window_check_err(self, code, # X, NULL); \ + } + +/* ------------- WINDOW routines --------------- */ + +Window_NoArgNoReturnFunction(untouchwin) +Window_NoArgNoReturnFunction(touchwin) +Window_NoArgNoReturnFunction(redrawwin) +Window_NoArgNoReturnFunction(winsertln) +Window_NoArgNoReturnFunction(werase) +Window_NoArgNoReturnFunction(wdeleteln) + +Window_NoArgTrueFalseFunction(is_wintouched) + +Window_NoArgNoReturnVoidFunction(wsyncup) +Window_NoArgNoReturnVoidFunction(wsyncdown) +Window_NoArgNoReturnVoidFunction(wstandend) +Window_NoArgNoReturnVoidFunction(wstandout) +Window_NoArgNoReturnVoidFunction(wcursyncup) +Window_NoArgNoReturnVoidFunction(wclrtoeol) +Window_NoArgNoReturnVoidFunction(wclrtobot) +Window_NoArgNoReturnVoidFunction(wclear) + +Window_OneArgNoReturnVoidFunction(idcok, int, "i;True(1) or False(0)") +#ifdef HAVE_CURSES_IMMEDOK +Window_OneArgNoReturnVoidFunction(immedok, int, "i;True(1) or False(0)") +#endif +Window_OneArgNoReturnVoidFunction(wtimeout, int, "i;delay") + +Window_NoArg2TupleReturnFunction(getyx, int, "ii") +Window_NoArg2TupleReturnFunction(getbegyx, int, "ii") +Window_NoArg2TupleReturnFunction(getmaxyx, int, "ii") +Window_NoArg2TupleReturnFunction(getparyx, int, "ii") + +Window_OneArgNoReturnFunction(clearok, int, "i;True(1) or False(0)") +Window_OneArgNoReturnFunction(idlok, int, "i;True(1) or False(0)") +Window_OneArgNoReturnFunction(keypad, int, "i;True(1) or False(0)") +Window_OneArgNoReturnFunction(leaveok, int, "i;True(1) or False(0)") +Window_OneArgNoReturnFunction(nodelay, int, "i;True(1) or False(0)") +Window_OneArgNoReturnFunction(notimeout, int, "i;True(1) or False(0)") +Window_OneArgNoReturnFunction(scrollok, int, "i;True(1) or False(0)") +Window_OneArgNoReturnFunction(winsdelln, int, "i;nlines") +#ifdef HAVE_CURSES_SYNCOK +Window_OneArgNoReturnFunction(syncok, int, "i;True(1) or False(0)") +#endif + +Window_TwoArgNoReturnFunction(mvwin, int, "ii;y,x") +Window_TwoArgNoReturnFunction(mvderwin, int, "ii;y,x") +Window_TwoArgNoReturnFunction(wmove, int, "ii;y,x") +#ifndef STRICT_SYSV_CURSES +Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns") +#endif + +/* Allocation and deallocation of Window Objects */ + +static PyObject * +PyCursesWindow_New(cursesmodule_state *state, + WINDOW *win, const char *encoding, + PyCursesWindowObject *orig) +{ + if (encoding == NULL) { +#if defined(MS_WINDOWS) + char *buffer[100]; + UINT cp; + cp = GetConsoleOutputCP(); + if (cp != 0) { + PyOS_snprintf(buffer, sizeof(buffer), "cp%u", cp); + encoding = buffer; + } +#elif defined(CODESET) + const char *codeset = nl_langinfo(CODESET); + if (codeset != NULL && codeset[0] != 0) { + encoding = codeset; + } +#endif + if (encoding == NULL) { + encoding = "utf-8"; + } + } + + PyCursesWindowObject *wo = PyObject_GC_New(PyCursesWindowObject, + state->window_type); + if (wo == NULL) { + return NULL; + } + wo->win = win; + wo->encoding = _PyMem_Strdup(encoding); + if (wo->encoding == NULL) { + Py_DECREF(wo); + PyErr_NoMemory(); + return NULL; + } + wo->orig = orig; + Py_XINCREF(orig); + PyObject_GC_Track((PyObject *)wo); + return (PyObject *)wo; +} + +static void +PyCursesWindow_dealloc(PyObject *self) +{ + PyTypeObject *window_type = Py_TYPE(self); + PyObject_GC_UnTrack(self); + PyCursesWindowObject *wo = (PyCursesWindowObject *)self; + if (wo->win != stdscr && wo->win != NULL) { + if (delwin(wo->win) == ERR) { + curses_window_set_error(wo, "delwin", "__del__"); + PyErr_FormatUnraisable("Exception ignored in delwin()"); + } + } + if (wo->encoding != NULL) { + PyMem_Free(wo->encoding); + } + Py_XDECREF(wo->orig); + window_type->tp_free(self); + Py_DECREF(window_type); +} + +static int +PyCursesWindow_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + PyCursesWindowObject *wo = (PyCursesWindowObject *)self; + Py_VISIT(wo->orig); + return 0; +} + +/* Addch, Addstr, Addnstr */ + +/*[clinic input] +_curses.window.addch + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + ch: object + Character to add. + + [ + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Attributes for the character. + ] + / + +Paint the character. + +Paint character ch at (y, x) with attributes attr, +overwriting any character previously painted at that location. +By default, the character position and attributes are the +current settings for the window object. +[clinic start generated code]*/ + +static PyObject * +_curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int group_right_1, + long attr) +/*[clinic end generated code: output=00f4c37af3378f45 input=95ce131578458196]*/ +{ + int coordinates_group = group_left_1; + int rtn; + int type; + chtype cch = 0; +#ifdef HAVE_NCURSESW + wchar_t wstr[2]; + cchar_t wcval; +#endif + const char *funcname; + +#ifdef HAVE_NCURSESW + type = PyCurses_ConvertToCchar_t(self, ch, &cch, wstr); + if (type == 2) { + wstr[1] = L'\0'; + rtn = setcchar(&wcval, wstr, attr, PAIR_NUMBER(attr), NULL); + if (rtn == ERR) { + curses_window_set_error(self, "setcchar", "addch"); + return NULL; + } + if (coordinates_group) { + rtn = mvwadd_wch(self->win,y,x, &wcval); + funcname = "mvwadd_wch"; + } + else { + rtn = wadd_wch(self->win, &wcval); + funcname = "wadd_wch"; + } + } + else +#else + type = PyCurses_ConvertToCchar_t(self, ch, &cch); +#endif + if (type == 1) { + if (coordinates_group) { + rtn = mvwaddch(self->win,y,x, cch | (attr_t) attr); + funcname = "mvwaddch"; + } + else { + rtn = waddch(self->win, cch | (attr_t) attr); + funcname = "waddch"; + } + } + else { + return NULL; + } + return curses_window_check_err(self, rtn, funcname, "addch"); +} + +#ifdef HAVE_NCURSESW +#define curses_release_wstr(STRTYPE, WSTR) \ + do { \ + if ((STRTYPE) == 2) { \ + PyMem_Free((WSTR)); \ + } \ + } while (0) +#else +#define curses_release_wstr(_STRTYPE, _WSTR) +#endif + +static int +curses_wattrset(PyCursesWindowObject *self, long attr, const char *funcname) +{ + if (wattrset(self->win, attr) == ERR) { + curses_window_set_error(self, "wattrset", funcname); + return -1; + } + return 0; +} + +/*[clinic input] +_curses.window.addstr + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + str: object + String to add. + + [ + attr: long + Attributes for characters. + ] + / + +Paint the string. + +Paint the string str at (y, x) with attributes attr, +overwriting anything previously on the display. +By default, the character position and attributes are the +current settings for the window object. +[clinic start generated code]*/ + +static PyObject * +_curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int group_right_1, + long attr) +/*[clinic end generated code: output=65a928ea85ff3115 input=ff6cbb91448a22a3]*/ +{ + int rtn; + int strtype; + PyObject *bytesobj = NULL; +#ifdef HAVE_NCURSESW + wchar_t *wstr = NULL; +#endif + attr_t attr_old = A_NORMAL; + int use_xy = group_left_1, use_attr = group_right_1; + const char *funcname; + +#ifdef HAVE_NCURSESW + strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr); +#else + strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL); +#endif + if (strtype == 0) { + return NULL; + } + if (use_attr) { + attr_old = getattrs(self->win); + if (curses_wattrset(self, attr, "addstr") < 0) { + curses_release_wstr(strtype, wstr); + return NULL; + } + } +#ifdef HAVE_NCURSESW + if (strtype == 2) { + if (use_xy) { + rtn = mvwaddwstr(self->win,y,x,wstr); + funcname = "mvwaddwstr"; + } + else { + rtn = waddwstr(self->win,wstr); + funcname = "waddwstr"; + } + PyMem_Free(wstr); + } + else +#endif + { + const char *str = PyBytes_AS_STRING(bytesobj); + if (use_xy) { + rtn = mvwaddstr(self->win,y,x,str); + funcname = "mvwaddstr"; + } + else { + rtn = waddstr(self->win,str); + funcname = "waddstr"; + } + Py_DECREF(bytesobj); + } + if (rtn == ERR) { + curses_window_set_error(self, funcname, "addstr"); + return NULL; + } + if (use_attr) { + rtn = wattrset(self->win, attr_old); + return curses_window_check_err(self, rtn, "wattrset", "addstr"); + } + Py_RETURN_NONE; +} + +/*[clinic input] +_curses.window.addnstr + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + str: object + String to add. + + n: int + Maximal number of characters. + + [ + attr: long + Attributes for characters. + ] + / + +Paint at most n characters of the string. + +Paint at most n characters of the string str at (y, x) with +attributes attr, overwriting anything previously on the display. +By default, the character position and attributes are the +current settings for the window object. +[clinic start generated code]*/ + +static PyObject * +_curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int n, + int group_right_1, long attr) +/*[clinic end generated code: output=6d21cee2ce6876d9 input=72718415c2744a2a]*/ +{ + int rtn; + int strtype; + PyObject *bytesobj = NULL; +#ifdef HAVE_NCURSESW + wchar_t *wstr = NULL; +#endif + attr_t attr_old = A_NORMAL; + int use_xy = group_left_1, use_attr = group_right_1; + const char *funcname; + +#ifdef HAVE_NCURSESW + strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr); +#else + strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL); +#endif + if (strtype == 0) + return NULL; + + if (use_attr) { + attr_old = getattrs(self->win); + if (curses_wattrset(self, attr, "addnstr") < 0) { + curses_release_wstr(strtype, wstr); + return NULL; + } + } +#ifdef HAVE_NCURSESW + if (strtype == 2) { + if (use_xy) { + rtn = mvwaddnwstr(self->win,y,x,wstr,n); + funcname = "mvwaddnwstr"; + } + else { + rtn = waddnwstr(self->win,wstr,n); + funcname = "waddnwstr"; + } + PyMem_Free(wstr); + } + else +#endif + { + const char *str = PyBytes_AS_STRING(bytesobj); + if (use_xy) { + rtn = mvwaddnstr(self->win,y,x,str,n); + funcname = "mvwaddnstr"; + } + else { + rtn = waddnstr(self->win,str,n); + funcname = "waddnstr"; + } + Py_DECREF(bytesobj); + } + if (rtn == ERR) { + curses_window_set_error(self, funcname, "addnstr"); + return NULL; + } + if (use_attr) { + rtn = wattrset(self->win, attr_old); + return curses_window_check_err(self, rtn, "wattrset", "addnstr"); + } + Py_RETURN_NONE; +} + +/*[clinic input] +_curses.window.bkgd + + ch: object + Background character. + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Background attributes. + / + +Set the background property of the window. +[clinic start generated code]*/ + +static PyObject * +_curses_window_bkgd_impl(PyCursesWindowObject *self, PyObject *ch, long attr) +/*[clinic end generated code: output=058290afb2cf4034 input=634015bcb339283d]*/ +{ + chtype bkgd; + + if (!PyCurses_ConvertToChtype(self, ch, &bkgd)) + return NULL; + + int rtn = wbkgd(self->win, bkgd | attr); + return curses_window_check_err(self, rtn, "wbkgd", "bkgd"); +} + +/*[clinic input] +_curses.window.attroff + + attr: long + / + +Remove attribute attr from the "background" set. +[clinic start generated code]*/ + +static PyObject * +_curses_window_attroff_impl(PyCursesWindowObject *self, long attr) +/*[clinic end generated code: output=8a2fcd4df682fc64 input=786beedf06a7befe]*/ +{ + int rtn = wattroff(self->win, (attr_t)attr); + return curses_window_check_err(self, rtn, "wattroff", "attroff"); +} + +/*[clinic input] +_curses.window.attron + + attr: long + / + +Add attribute attr to the "background" set. +[clinic start generated code]*/ + +static PyObject * +_curses_window_attron_impl(PyCursesWindowObject *self, long attr) +/*[clinic end generated code: output=7afea43b237fa870 input=b57f824e1bf58326]*/ +{ + int rtn = wattron(self->win, (attr_t)attr); + return curses_window_check_err(self, rtn, "wattron", "attron"); +} + +/*[clinic input] +_curses.window.attrset + + attr: long + / + +Set the "background" set of attributes. +[clinic start generated code]*/ + +static PyObject * +_curses_window_attrset_impl(PyCursesWindowObject *self, long attr) +/*[clinic end generated code: output=84e379bff20c0433 input=42e400c0d0154ab5]*/ +{ + int rtn = wattrset(self->win, (attr_t)attr); + return curses_window_check_err(self, rtn, "wattrset", "attrset"); +} + +/*[clinic input] +_curses.window.bkgdset + + ch: object + Background character. + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Background attributes. + / + +Set the window's background. +[clinic start generated code]*/ + +static PyObject * +_curses_window_bkgdset_impl(PyCursesWindowObject *self, PyObject *ch, + long attr) +/*[clinic end generated code: output=8cb994fc4d7e2496 input=e09c682425c9e45b]*/ +{ + chtype bkgd; + + if (!PyCurses_ConvertToChtype(self, ch, &bkgd)) + return NULL; + + wbkgdset(self->win, bkgd | attr); + Py_RETURN_NONE; +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.border + + ls: object(c_default="NULL") = _curses.ACS_VLINE + Left side. + rs: object(c_default="NULL") = _curses.ACS_VLINE + Right side. + ts: object(c_default="NULL") = _curses.ACS_HLINE + Top side. + bs: object(c_default="NULL") = _curses.ACS_HLINE + Bottom side. + tl: object(c_default="NULL") = _curses.ACS_ULCORNER + Upper-left corner. + tr: object(c_default="NULL") = _curses.ACS_URCORNER + Upper-right corner. + bl: object(c_default="NULL") = _curses.ACS_LLCORNER + Bottom-left corner. + br: object(c_default="NULL") = _curses.ACS_LRCORNER + Bottom-right corner. + / + +Draw a border around the edges of the window. + +Each parameter specifies the character to use for a specific part of the +border. The characters can be specified as integers or as one-character +strings. A 0 value for any parameter will cause the default character to be +used for that parameter. +[clinic start generated code]*/ + +static PyObject * +_curses_window_border_impl(PyCursesWindowObject *self, PyObject *ls, + PyObject *rs, PyObject *ts, PyObject *bs, + PyObject *tl, PyObject *tr, PyObject *bl, + PyObject *br) +/*[clinic end generated code: output=670ef38d3d7c2aa3 input=adaafca87488ee35]*/ +{ + chtype ch[8]; + int i, rtn; + + /* Clear the array of parameters */ + for(i=0; i<8; i++) + ch[i] = 0; + +#define CONVERTTOCHTYPE(obj, i) \ + if ((obj) != NULL && !PyCurses_ConvertToChtype(self, (obj), &ch[(i)])) \ + return NULL; + + CONVERTTOCHTYPE(ls, 0); + CONVERTTOCHTYPE(rs, 1); + CONVERTTOCHTYPE(ts, 2); + CONVERTTOCHTYPE(bs, 3); + CONVERTTOCHTYPE(tl, 4); + CONVERTTOCHTYPE(tr, 5); + CONVERTTOCHTYPE(bl, 6); + CONVERTTOCHTYPE(br, 7); + +#undef CONVERTTOCHTYPE + + rtn = wborder(self->win, + ch[0], ch[1], ch[2], ch[3], + ch[4], ch[5], ch[6], ch[7]); + return curses_window_check_err(self, rtn, "wborder", "border"); +} + +/*[clinic input] +_curses.window.box + + [ + verch: object(c_default="_PyLong_GetZero()") = 0 + Left and right side. + horch: object(c_default="_PyLong_GetZero()") = 0 + Top and bottom side. + ] + / + +Draw a border around the edges of the window. + +Similar to border(), but both ls and rs are verch and both ts and bs are +horch. The default corner characters are always used by this function. +[clinic start generated code]*/ + +static PyObject * +_curses_window_box_impl(PyCursesWindowObject *self, int group_right_1, + PyObject *verch, PyObject *horch) +/*[clinic end generated code: output=f3fcb038bb287192 input=f00435f9c8c98f60]*/ +{ + chtype ch1 = 0, ch2 = 0; + if (group_right_1) { + if (!PyCurses_ConvertToChtype(self, verch, &ch1)) { + return NULL; + } + if (!PyCurses_ConvertToChtype(self, horch, &ch2)) { + return NULL; + } + } + return curses_window_check_err(self, box(self->win, ch1, ch2), "box", NULL); +} + +#if defined(HAVE_NCURSES_H) || defined(MVWDELCH_IS_EXPRESSION) +#define py_mvwdelch mvwdelch +#else +int py_mvwdelch(WINDOW *w, int y, int x) +{ + mvwdelch(w,y,x); + /* On HP/UX, mvwdelch already returns. On other systems, + we may well run into this return statement. */ + return 0; +} +#endif + +#if defined(HAVE_CURSES_IS_PAD) +// is_pad() is defined, either as a macro or as a function +#define py_is_pad(win) is_pad(win) +#elif defined(WINDOW_HAS_FLAGS) +// is_pad() is not defined, but we can inspect WINDOW structure members +#define py_is_pad(win) ((win) ? ((win)->_flags & _ISPAD) != 0 : FALSE) +#endif + +/* chgat, added by Fabian Kreutz */ +#ifdef HAVE_CURSES_WCHGAT + +PyDoc_STRVAR(_curses_window_chgat__doc__, +"chgat([y, x,] [n=-1,] attr)\n" +"Set the attributes of characters.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" n\n" +" Number of characters.\n" +" attr\n" +" Attributes for characters.\n" +"\n" +"Set the attributes of num characters at the current cursor position, or at\n" +"position (y, x) if supplied. If no value of num is given or num = -1, the\n" +"attribute will be set on all the characters to the end of the line. This\n" +"function does not move the cursor. The changed line will be touched using\n" +"the touchline() method so that the contents will be redisplayed by the next\n" +"window refresh."); + +static PyObject * +PyCursesWindow_ChgAt(PyObject *op, PyObject *args) +{ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); + + int rtn; + const char *funcname; + int x, y; + int num = -1; + short color; + attr_t attr = A_NORMAL; + long lattr; + int use_xy = FALSE; + + switch (PyTuple_Size(args)) { + case 1: + if (!PyArg_ParseTuple(args,"l;attr", &lattr)) + return NULL; + attr = lattr; + break; + case 2: + if (!PyArg_ParseTuple(args,"il;n,attr", &num, &lattr)) + return NULL; + attr = lattr; + break; + case 3: + if (!PyArg_ParseTuple(args,"iil;y,x,attr", &y, &x, &lattr)) + return NULL; + attr = lattr; + use_xy = TRUE; + break; + case 4: + if (!PyArg_ParseTuple(args,"iiil;y,x,n,attr", &y, &x, &num, &lattr)) + return NULL; + attr = lattr; + use_xy = TRUE; + break; + default: + PyErr_SetString(PyExc_TypeError, + "_curses.window.chgat requires 1 to 4 arguments"); + return NULL; + } + + color = (short) PAIR_NUMBER(attr); + attr = attr & A_ATTRIBUTES; + + if (use_xy) { + rtn = mvwchgat(self->win,y,x,num,attr,color,NULL); + funcname = "mvwchgat"; + } else { + getyx(self->win,y,x); + rtn = wchgat(self->win,num,attr,color,NULL); + funcname = "wchgat"; + } + if (rtn == ERR) { + curses_window_set_error(self, funcname, "chgat"); + return NULL; + } + rtn = touchline(self->win,y,1); + return curses_window_check_err(self, rtn, "touchline", "chgat"); +} +#endif + +/*[clinic input] +_curses.window.delch + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + / + +Delete any character at (y, x). +[clinic start generated code]*/ + +static PyObject * +_curses_window_delch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x) +/*[clinic end generated code: output=22e77bb9fa11b461 input=d2f79e630a4fc6d0]*/ +{ + int rtn; + const char *funcname; + if (!group_right_1) { + rtn = wdelch(self->win); + funcname = "wdelch"; + } + else { + rtn = py_mvwdelch(self->win, y, x); + funcname = "mvwdelch"; + } + return curses_window_check_err(self, rtn, funcname, "delch"); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.derwin + + [ + nlines: int = 0 + Height. + ncols: int = 0 + Width. + ] + begin_y: int + Top side y-coordinate. + begin_x: int + Left side x-coordinate. + / + +Create a sub-window (window-relative coordinates). + +derwin() is the same as calling subwin(), except that begin_y and begin_x +are relative to the origin of the window, rather than relative to the entire +screen. +[clinic start generated code]*/ + +static PyObject * +_curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, + int nlines, int ncols, int begin_y, int begin_x) +/*[clinic end generated code: output=7924b112d9f70d6e input=ebe95ded1c284c8e]*/ +{ + WINDOW *win; + + win = derwin(self->win,nlines,ncols,begin_y,begin_x); + + if (win == NULL) { + curses_window_set_null_error(self, "derwin", NULL); + return NULL; + } + + cursesmodule_state *state = get_cursesmodule_state_by_win(self); + return PyCursesWindow_New(state, win, NULL, self); +} + +/*[clinic input] +_curses.window.echochar + + ch: object + Character to add. + + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Attributes for the character. + / + +Add character ch with attribute attr, and refresh. +[clinic start generated code]*/ + +static PyObject * +_curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch, + long attr) +/*[clinic end generated code: output=13e7dd875d4b9642 input=e7f34b964e92b156]*/ +{ + chtype ch_; + + if (!PyCurses_ConvertToChtype(self, ch, &ch_)) + return NULL; + + int rtn; + const char *funcname; +#ifdef py_is_pad + if (py_is_pad(self->win)) { + rtn = pechochar(self->win, ch_ | (attr_t)attr); + funcname = "pechochar"; + } + else +#endif + { + rtn = wechochar(self->win, ch_ | (attr_t)attr); + funcname = "wechochar"; + } + return curses_window_check_err(self, rtn, funcname, "echochar"); +} + +#ifdef NCURSES_MOUSE_VERSION +/*[clinic input] +@permit_long_summary +_curses.window.enclose + + y: int + Y-coordinate. + x: int + X-coordinate. + / + +Return True if the screen-relative coordinates are enclosed by the window. +[clinic start generated code]*/ + +static PyObject * +_curses_window_enclose_impl(PyCursesWindowObject *self, int y, int x) +/*[clinic end generated code: output=8679beef50502648 input=9ba7c894cffe5507]*/ +{ + return PyBool_FromLong(wenclose(self->win, y, x)); +} +#endif + +/*[clinic input] +_curses.window.getbkgd + +Return the window's current background character/attribute pair. +[clinic start generated code]*/ + +static PyObject * +_curses_window_getbkgd_impl(PyCursesWindowObject *self) +/*[clinic end generated code: output=3ff953412b0e6028 input=7cf1f59a31f89df4]*/ +{ + chtype rtn = getbkgd(self->win); + if (rtn == (chtype)ERR) { + curses_window_set_error(self, "getbkgd", NULL); + return NULL; + } + return PyLong_FromLong(rtn); +} + +static PyObject * +curses_check_signals_on_input_error(PyCursesWindowObject *self, + const char *curses_funcname, + const char *python_funcname) +{ + assert(!PyErr_Occurred()); + if (PyErr_CheckSignals()) { + return NULL; + } + cursesmodule_state *state = get_cursesmodule_state_by_win(self); + PyErr_Format(state->error, "%s() (called by %s()): no input", + curses_funcname, python_funcname); + return NULL; +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.getch + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + / + +Get a character code from terminal keyboard. + +The integer returned does not have to be in ASCII range: function keys, +keypad keys and so on return numbers higher than 256. In no-delay mode, -1 +is returned if there is no input, else getch() waits until a key is pressed. +[clinic start generated code]*/ + +static PyObject * +_curses_window_getch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x) +/*[clinic end generated code: output=e1639e87d545e676 input=9a053077373e2a30]*/ +{ + int rtn; + + Py_BEGIN_ALLOW_THREADS + if (!group_right_1) { + rtn = wgetch(self->win); + } + else { + rtn = mvwgetch(self->win, y, x); + } + Py_END_ALLOW_THREADS + + if (rtn == ERR) { + // We suppress ERR returned by wgetch() in nodelay mode + // after we handled possible interruption signals. + if (PyErr_CheckSignals()) { + return NULL; + } + // ERR is an implementation detail, so to be on the safe side, + // we forcibly set the return value to -1 as documented above. + rtn = -1; + } + return PyLong_FromLong(rtn); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.getkey + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + / + +Get a character (string) from terminal keyboard. + +Returning a string instead of an integer, as getch() does. Function keys, +keypad keys and other special keys return a multibyte string containing the +key name. In no-delay mode, an exception is raised if there is no input. +[clinic start generated code]*/ + +static PyObject * +_curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x) +/*[clinic end generated code: output=8490a182db46b10f input=5177f03fb6c31ea6]*/ +{ + int rtn; + + Py_BEGIN_ALLOW_THREADS + if (!group_right_1) { + rtn = wgetch(self->win); + } + else { + rtn = mvwgetch(self->win, y, x); + } + Py_END_ALLOW_THREADS + + if (rtn == ERR) { + /* wgetch() returns ERR in nodelay mode */ + const char *funcname = group_right_1 ? "mvwgetch" : "wgetch"; + return curses_check_signals_on_input_error(self, funcname, "getkey"); + } else if (rtn <= 255) { +#ifdef NCURSES_VERSION_MAJOR +#if NCURSES_VERSION_MAJOR*100+NCURSES_VERSION_MINOR <= 507 + /* Work around a bug in ncurses 5.7 and earlier */ + if (rtn < 0) { + rtn += 256; + } +#endif +#endif + return PyUnicode_FromOrdinal(rtn); + } else { + const char *knp = keyname(rtn); + return PyUnicode_FromString((knp == NULL) ? "" : knp); + } +} + +#ifdef HAVE_NCURSESW +/*[clinic input] +_curses.window.get_wch + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + / + +Get a wide character from terminal keyboard. + +Return a character for most keys, or an integer for function keys, +keypad keys, and other special keys. +[clinic start generated code]*/ + +static PyObject * +_curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x) +/*[clinic end generated code: output=9f4f86e91fe50ef3 input=dd7e5367fb49dc48]*/ +{ + int ct; + wint_t rtn; + + Py_BEGIN_ALLOW_THREADS + if (!group_right_1) { + ct = wget_wch(self->win ,&rtn); + } + else { + ct = mvwget_wch(self->win, y, x, &rtn); + } + Py_END_ALLOW_THREADS + + if (ct == ERR) { + /* wget_wch() returns ERR in nodelay mode */ + const char *funcname = group_right_1 ? "mvwget_wch" : "wget_wch"; + return curses_check_signals_on_input_error(self, funcname, "get_wch"); + } + if (ct == KEY_CODE_YES) + return PyLong_FromLong(rtn); + else + return PyUnicode_FromOrdinal(rtn); +} +#endif + +/* + * Helper function for parsing parameters from getstr() and instr(). + * This function is necessary because Argument Clinic does not know + * how to handle nested optional groups with default values inside. + * + * Return 1 on success and 0 on failure, similar to PyArg_ParseTuple(). + */ +static int +curses_clinic_parse_optional_xy_n(PyObject *args, + int *y, int *x, unsigned int *n, int *use_xy, + const char *qualname) +{ + switch (PyTuple_GET_SIZE(args)) { + case 0: { + *use_xy = 0; + return 1; + } + case 1: { + *use_xy = 0; + return PyArg_ParseTuple(args, "O&;n", + _PyLong_UnsignedInt_Converter, n); + } + case 2: { + *use_xy = 1; + return PyArg_ParseTuple(args, "ii;y,x", y, x); + } + case 3: { + *use_xy = 1; + return PyArg_ParseTuple(args, "iiO&;y,x,n", y, x, + _PyLong_UnsignedInt_Converter, n); + } + default: { + *use_xy = 0; + PyErr_Format(PyExc_TypeError, "%s requires 0 to 3 arguments", + qualname); + return 0; + } + } +} + +PyDoc_STRVAR(_curses_window_getstr__doc__, +"getstr([[y, x,] n=2047])\n" +"Read a string from the user, with primitive line editing capacity.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" n\n" +" Maximal number of characters."); + +static PyObject * +PyCursesWindow_getstr(PyObject *op, PyObject *args) +{ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); + int rtn, use_xy = 0, y = 0, x = 0; + unsigned int max_buf_size = 2048; + unsigned int n = max_buf_size - 1; + + if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy, + "_curses.window.instr")) + { + return NULL; + } + + n = Py_MIN(n, max_buf_size - 1); + PyBytesWriter *writer = PyBytesWriter_Create(n + 1); + if (writer == NULL) { + return NULL; + } + char *buf = PyBytesWriter_GetData(writer); + + if (use_xy) { + Py_BEGIN_ALLOW_THREADS +#ifdef STRICT_SYSV_CURSES + rtn = wmove(self->win, y, x) == ERR + ? ERR + : wgetnstr(self->win, buf, n); +#else + rtn = mvwgetnstr(self->win, y, x, buf, n); +#endif + Py_END_ALLOW_THREADS + } + else { + Py_BEGIN_ALLOW_THREADS + rtn = wgetnstr(self->win, buf, n); + Py_END_ALLOW_THREADS + } + + if (rtn == ERR) { + PyBytesWriter_Discard(writer); + return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES); + } + return PyBytesWriter_FinishWithSize(writer, strlen(buf)); +} + +/*[clinic input] +_curses.window.hline + + [ + y: int + Starting Y-coordinate. + x: int + Starting X-coordinate. + ] + + ch: object + Character to draw. + n: int + Line length. + + [ + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Attributes for the characters. + ] + / + +Display a horizontal line. +[clinic start generated code]*/ + +static PyObject * +_curses_window_hline_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int n, + int group_right_1, long attr) +/*[clinic end generated code: output=c00d489d61fc9eef input=81a4dea47268163e]*/ +{ + chtype ch_; + + if (!PyCurses_ConvertToChtype(self, ch, &ch_)) + return NULL; + if (group_left_1) { + if (wmove(self->win, y, x) == ERR) { + curses_window_set_error(self, "wmove", "hline"); + return NULL; + } + } + int rtn = whline(self->win, ch_ | (attr_t)attr, n); + return curses_window_check_err(self, rtn, "whline", "hline"); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.insch + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + ch: object + Character to insert. + + [ + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Attributes for the character. + ] + / + +Insert a character before the current or specified position. + +All characters to the right of the cursor are shifted one position right, with +the rightmost characters on the line being lost. +[clinic start generated code]*/ + +static PyObject * +_curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int group_right_1, + long attr) +/*[clinic end generated code: output=ade8cfe3a3bf3e34 input=3f2a230cb09fed5a]*/ +{ + int rtn; + chtype ch_ = 0; + + if (!PyCurses_ConvertToChtype(self, ch, &ch_)) + return NULL; + + const char *funcname; + if (!group_left_1) { + rtn = winsch(self->win, ch_ | (attr_t)attr); + funcname = "winsch"; + } + else { + rtn = mvwinsch(self->win, y, x, ch_ | (attr_t)attr); + funcname = "mvwwinsch"; + } + + return curses_window_check_err(self, rtn, funcname, "insch"); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.inch + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + / + +Return the character at the given position in the window. + +The bottom 8 bits are the character proper, and upper bits are the attributes. +[clinic start generated code]*/ + +static PyObject * +_curses_window_inch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x) +/*[clinic end generated code: output=97ca8581baaafd06 input=a5846f315464dc86]*/ +{ + chtype rtn; + const char *funcname; + + if (!group_right_1) { + rtn = winch(self->win); + funcname = "winch"; + } + else { + rtn = mvwinch(self->win, y, x); + funcname = "mvwinch"; + } + if (rtn == (chtype)ERR) { + curses_window_set_error(self, funcname, "inch"); + return NULL; + } + return PyLong_FromUnsignedLong(rtn); +} + +PyDoc_STRVAR(_curses_window_instr__doc__, +"instr([y, x,] n=2047)\n" +"Return a string of characters, extracted from the window.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" n\n" +" Maximal number of characters.\n" +"\n" +"Return a string of characters, extracted from the window starting at the\n" +"current cursor position, or at y, x if specified. Attributes are stripped\n" +"from the characters. If n is specified, instr() returns a string at most\n" +"n characters long (exclusive of the trailing NUL)."); + +static PyObject * +PyCursesWindow_instr(PyObject *op, PyObject *args) +{ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); + int rtn, use_xy = 0, y = 0, x = 0; + unsigned int max_buf_size = 2048; + unsigned int n = max_buf_size - 1; + + if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy, + "_curses.window.instr")) + { + return NULL; + } + + n = Py_MIN(n, max_buf_size - 1); + PyBytesWriter *writer = PyBytesWriter_Create(n + 1); + if (writer == NULL) { + return NULL; + } + char *buf = PyBytesWriter_GetData(writer); + + if (use_xy) { + rtn = mvwinnstr(self->win, y, x, buf, n); + } + else { + rtn = winnstr(self->win, buf, n); + } + + if (rtn == ERR) { + PyBytesWriter_Discard(writer); + return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES); + } + return PyBytesWriter_FinishWithSize(writer, strlen(buf)); +} + +/*[clinic input] +_curses.window.insstr + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + str: object + String to insert. + + [ + attr: long + Attributes for characters. + ] + / + +Insert the string before the current or specified position. + +Insert a character string (as many characters as will fit on the line) +before the character under the cursor. All characters to the right of +the cursor are shifted right, with the rightmost characters on the line +being lost. The cursor position does not change (after moving to y, x, +if specified). +[clinic start generated code]*/ + +static PyObject * +_curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int group_right_1, + long attr) +/*[clinic end generated code: output=c259a5265ad0b777 input=6827cddc6340a7f3]*/ +{ + int rtn; + int strtype; + PyObject *bytesobj = NULL; +#ifdef HAVE_NCURSESW + wchar_t *wstr = NULL; +#endif + attr_t attr_old = A_NORMAL; + int use_xy = group_left_1, use_attr = group_right_1; + const char *funcname; + +#ifdef HAVE_NCURSESW + strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr); +#else + strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL); +#endif + if (strtype == 0) + return NULL; + + if (use_attr) { + attr_old = getattrs(self->win); + if (curses_wattrset(self, attr, "insstr") < 0) { + curses_release_wstr(strtype, wstr); + return NULL; + } + } +#ifdef HAVE_NCURSESW + if (strtype == 2) { + if (use_xy) { + rtn = mvwins_wstr(self->win,y,x,wstr); + funcname = "mvwins_wstr"; + } + else { + rtn = wins_wstr(self->win,wstr); + funcname = "wins_wstr"; + } + PyMem_Free(wstr); + } + else +#endif + { + const char *str = PyBytes_AS_STRING(bytesobj); + if (use_xy) { + rtn = mvwinsstr(self->win,y,x,str); + funcname = "mvwinsstr"; + } + else { + rtn = winsstr(self->win,str); + funcname = "winsstr"; + } + Py_DECREF(bytesobj); + } + if (rtn == ERR) { + curses_window_set_error(self, funcname, "insstr"); + return NULL; + } + if (use_attr) { + rtn = wattrset(self->win, attr_old); + return curses_window_check_err(self, rtn, "wattrset", "insstr"); + } + Py_RETURN_NONE; +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.insnstr + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + str: object + String to insert. + + n: int + Maximal number of characters. + + [ + attr: long + Attributes for characters. + ] + / + +Insert at most n characters of the string. + +Insert a character string (as many characters as will fit on the line) +before the character under the cursor, up to n characters. If n is zero +or negative, the entire string is inserted. All characters to the right +of the cursor are shifted right, with the rightmost characters on the line +being lost. The cursor position does not change (after moving to y, x, if +specified). +[clinic start generated code]*/ + +static PyObject * +_curses_window_insnstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int n, + int group_right_1, long attr) +/*[clinic end generated code: output=971a32ea6328ec8b input=dcdc554102fbcd5d]*/ +{ + int rtn; + int strtype; + PyObject *bytesobj = NULL; +#ifdef HAVE_NCURSESW + wchar_t *wstr = NULL; +#endif + attr_t attr_old = A_NORMAL; + int use_xy = group_left_1, use_attr = group_right_1; + const char *funcname; + +#ifdef HAVE_NCURSESW + strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr); +#else + strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL); +#endif + if (strtype == 0) + return NULL; + + if (use_attr) { + attr_old = getattrs(self->win); + if (curses_wattrset(self, attr, "insnstr") < 0) { + curses_release_wstr(strtype, wstr); + return NULL; + } + } +#ifdef HAVE_NCURSESW + if (strtype == 2) { + if (use_xy) { + rtn = mvwins_nwstr(self->win,y,x,wstr,n); + funcname = "mvwins_nwstr"; + } + else { + rtn = wins_nwstr(self->win,wstr,n); + funcname = "wins_nwstr"; + } + PyMem_Free(wstr); + } + else +#endif + { + const char *str = PyBytes_AS_STRING(bytesobj); + if (use_xy) { + rtn = mvwinsnstr(self->win,y,x,str,n); + funcname = "mvwinsnstr"; + } + else { + rtn = winsnstr(self->win,str,n); + funcname = "winsnstr"; + } + Py_DECREF(bytesobj); + } + if (rtn == ERR) { + curses_window_set_error(self, funcname, "insnstr"); + return NULL; + } + if (use_attr) { + rtn = wattrset(self->win, attr_old); + return curses_window_check_err(self, rtn, "wattrset", "insnstr"); + } + Py_RETURN_NONE; +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.is_linetouched + + line: int + Line number. + / + +Return True if the specified line was modified, otherwise return False. + +Raise a curses.error exception if line is not valid for the given window. +[clinic start generated code]*/ + +static PyObject * +_curses_window_is_linetouched_impl(PyCursesWindowObject *self, int line) +/*[clinic end generated code: output=ad4a4edfee2db08c input=af71c040b951c467]*/ +{ + int erg; + erg = is_linetouched(self->win, line); + if (erg == ERR) { + curses_window_set_error(self, "is_linetouched", NULL); + return NULL; + } + return PyBool_FromLong(erg); +} + +#ifdef py_is_pad +/*[clinic input] +@permit_long_docstring_body +_curses.window.noutrefresh + + [ + pminrow: int + pmincol: int + sminrow: int + smincol: int + smaxrow: int + smaxcol: int + ] + / + +Mark for refresh but wait. + +This function updates the data structure representing the desired state of the +window, but does not force an update of the physical screen. To accomplish +that, call doupdate(). +[clinic start generated code]*/ + +static PyObject * +_curses_window_noutrefresh_impl(PyCursesWindowObject *self, + int group_right_1, int pminrow, int pmincol, + int sminrow, int smincol, int smaxrow, + int smaxcol) +/*[clinic end generated code: output=809a1f3c6a03e23e input=b39fe8fc79b9980b]*/ +#else +/*[clinic input] +@permit_long_docstring_body +_curses.window.noutrefresh + +Mark for refresh but wait. + +This function updates the data structure representing the desired state of the +window, but does not force an update of the physical screen. To accomplish +that, call doupdate(). +[clinic start generated code]*/ + +static PyObject * +_curses_window_noutrefresh_impl(PyCursesWindowObject *self) +/*[clinic end generated code: output=6ef6dec666643fee input=6a9f59ae5e4c139e]*/ +#endif +{ + int rtn; + +#ifdef py_is_pad + if (py_is_pad(self->win)) { + if (!group_right_1) { + PyErr_SetString(PyExc_TypeError, + "noutrefresh() called for a pad " + "requires 6 arguments"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS + rtn = pnoutrefresh(self->win, pminrow, pmincol, + sminrow, smincol, smaxrow, smaxcol); + Py_END_ALLOW_THREADS + return curses_window_check_err(self, rtn, + "pnoutrefresh", "noutrefresh"); + } + if (group_right_1) { + PyErr_SetString(PyExc_TypeError, + "noutrefresh() takes no arguments (6 given)"); + return NULL; + } +#endif + Py_BEGIN_ALLOW_THREADS + rtn = wnoutrefresh(self->win); + Py_END_ALLOW_THREADS + return curses_window_check_err(self, rtn, "wnoutrefresh", "noutrefresh"); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.overlay + + destwin: object(type="PyCursesWindowObject *", subclass_of="clinic_state()->window_type") + + [ + sminrow: int + smincol: int + dminrow: int + dmincol: int + dmaxrow: int + dmaxcol: int + ] + / + +Overlay the window on top of destwin. + +The windows need not be the same size, only the overlapping region is copied. +This copy is non-destructive, which means that the current background +character does not overwrite the old contents of destwin. + +To get fine-grained control over the copied region, the second form of +overlay() can be used. sminrow and smincol are the upper-left coordinates +of the source window, and the other variables mark a rectangle in the +destination window. +[clinic start generated code]*/ + +static PyObject * +_curses_window_overlay_impl(PyCursesWindowObject *self, + PyCursesWindowObject *destwin, int group_right_1, + int sminrow, int smincol, int dminrow, + int dmincol, int dmaxrow, int dmaxcol) +/*[clinic end generated code: output=82bb2c4cb443ca58 input=dd6af34deb892a65]*/ +{ + int rtn; + + if (group_right_1) { + rtn = copywin(self->win, destwin->win, sminrow, smincol, + dminrow, dmincol, dmaxrow, dmaxcol, TRUE); + return curses_window_check_err(self, rtn, "copywin", "overlay"); + } + else { + rtn = overlay(self->win, destwin->win); + return curses_window_check_err(self, rtn, "overlay", NULL); + } +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.overwrite + + destwin: object(type="PyCursesWindowObject *", subclass_of="clinic_state()->window_type") + + [ + sminrow: int + smincol: int + dminrow: int + dmincol: int + dmaxrow: int + dmaxcol: int + ] + / + +Overwrite the window on top of destwin. + +The windows need not be the same size, in which case only the overlapping +region is copied. This copy is destructive, which means that the current +background character overwrites the old contents of destwin. + +To get fine-grained control over the copied region, the second form of +overwrite() can be used. sminrow and smincol are the upper-left coordinates +of the source window, the other variables mark a rectangle in the destination +window. +[clinic start generated code]*/ + +static PyObject * +_curses_window_overwrite_impl(PyCursesWindowObject *self, + PyCursesWindowObject *destwin, + int group_right_1, int sminrow, int smincol, + int dminrow, int dmincol, int dmaxrow, + int dmaxcol) +/*[clinic end generated code: output=12ae007d1681be28 input=e84d8ebdf1c09596]*/ +{ + int rtn; + + if (group_right_1) { + rtn = copywin(self->win, destwin->win, sminrow, smincol, + dminrow, dmincol, dmaxrow, dmaxcol, FALSE); + return curses_window_check_err(self, rtn, "copywin", "overwrite"); + } + else { + rtn = overwrite(self->win, destwin->win); + return curses_window_check_err(self, rtn, "overwrite", NULL); + } +} + +/*[clinic input] +_curses.window.putwin + + file: object + / + +Write all data associated with the window into the provided file object. + +This information can be later retrieved using the getwin() function. +[clinic start generated code]*/ + +static PyObject * +_curses_window_putwin_impl(PyCursesWindowObject *self, PyObject *file) +/*[clinic end generated code: output=fdae68ac59b0281b input=0608648e09c8ea0a]*/ +{ + /* We have to simulate this by writing to a temporary FILE*, + then reading back, then writing to the argument file. */ + FILE *fp; + PyObject *res = NULL; + + fp = tmpfile(); + if (fp == NULL) + return PyErr_SetFromErrno(PyExc_OSError); + if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0) + goto exit; + res = curses_window_check_err(self, putwin(self->win, fp), "putwin", NULL); + if (res == NULL) + goto exit; + fseek(fp, 0, 0); + while (1) { + char buf[BUFSIZ]; + Py_ssize_t n = fread(buf, 1, BUFSIZ, fp); + + if (n <= 0) + break; + Py_DECREF(res); + res = PyObject_CallMethod(file, "write", "y#", buf, n); + if (res == NULL) + break; + } + +exit: + fclose(fp); + return res; +} + +/*[clinic input] +_curses.window.redrawln + + beg: int + Starting line number. + num: int + The number of lines. + / + +Mark the specified lines corrupted. + +They should be completely redrawn on the next refresh() call. +[clinic start generated code]*/ + +static PyObject * +_curses_window_redrawln_impl(PyCursesWindowObject *self, int beg, int num) +/*[clinic end generated code: output=ea216e334f9ce1b4 input=152155e258a77a7a]*/ +{ + int rtn = wredrawln(self->win,beg, num); + return curses_window_check_err(self, rtn, "wredrawln", "redrawln"); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.refresh + + [ + pminrow: int + pmincol: int + sminrow: int + smincol: int + smaxrow: int + smaxcol: int + ] + / + +Update the display immediately. + +Synchronize actual screen with previous drawing/deleting methods. +The 6 optional arguments can only be specified when the window is a pad +created with newpad(). The additional parameters are needed to indicate +what part of the pad and screen are involved. pminrow and pmincol specify +the upper left-hand corner of the rectangle to be displayed in the pad. +sminrow, smincol, smaxrow, and smaxcol specify the edges of the rectangle to +be displayed on the screen. The lower right-hand corner of the rectangle to +be displayed in the pad is calculated from the screen coordinates, since the +rectangles must be the same size. Both rectangles must be entirely contained +within their respective structures. Negative values of pminrow, pmincol, +sminrow, or smincol are treated as if they were zero. +[clinic start generated code]*/ + +static PyObject * +_curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, + int pminrow, int pmincol, int sminrow, + int smincol, int smaxrow, int smaxcol) +/*[clinic end generated code: output=42199543115e6e63 input=65405c03290496a6]*/ +{ + int rtn; + +#ifdef py_is_pad + if (py_is_pad(self->win)) { + if (!group_right_1) { + PyErr_SetString(PyExc_TypeError, + "refresh() for a pad requires 6 arguments"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS + rtn = prefresh(self->win, pminrow, pmincol, + sminrow, smincol, smaxrow, smaxcol); + Py_END_ALLOW_THREADS + return curses_window_check_err(self, rtn, "prefresh", "refresh"); + } +#endif + if (group_right_1) { + PyErr_SetString(PyExc_TypeError, + "refresh() takes no arguments (6 given)"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS + rtn = wrefresh(self->win); + Py_END_ALLOW_THREADS + return curses_window_check_err(self, rtn, "wrefresh", "refresh"); +} + +/*[clinic input] +_curses.window.setscrreg + + top: int + First line number. + bottom: int + Last line number. + / + +Define a software scrolling region. + +All scrolling actions will take place in this region. +[clinic start generated code]*/ + +static PyObject * +_curses_window_setscrreg_impl(PyCursesWindowObject *self, int top, + int bottom) +/*[clinic end generated code: output=486ab5db218d2b1a input=1b517b986838bf0e]*/ +{ + int rtn = wsetscrreg(self->win, top, bottom); + return curses_window_check_err(self, rtn, "wsetscrreg", "setscrreg"); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.subwin + + [ + nlines: int = 0 + Height. + ncols: int = 0 + Width. + ] + begin_y: int + Top side y-coordinate. + begin_x: int + Left side x-coordinate. + / + +Create a sub-window (screen-relative coordinates). + +By default, the sub-window will extend from the specified position to the +lower right corner of the window. +[clinic start generated code]*/ + +static PyObject * +_curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, + int nlines, int ncols, int begin_y, int begin_x) +/*[clinic end generated code: output=93e898afc348f59a input=5292cf610e2f3585]*/ +{ + WINDOW *win; + const char *funcname; + + /* printf("Subwin: %i %i %i %i \n", nlines, ncols, begin_y, begin_x); */ +#ifdef py_is_pad + if (py_is_pad(self->win)) { + win = subpad(self->win, nlines, ncols, begin_y, begin_x); + funcname = "subpad"; + } + else +#endif + { + win = subwin(self->win, nlines, ncols, begin_y, begin_x); + funcname = "subwin"; + } + + if (win == NULL) { + curses_window_set_null_error(self, funcname, "subwin"); + return NULL; + } + + cursesmodule_state *state = get_cursesmodule_state_by_win(self); + return PyCursesWindow_New(state, win, self->encoding, self); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.scroll + + [ + lines: int = 1 + Number of lines to scroll. + ] + / + +Scroll the screen or scrolling region. + +Scroll upward if the argument is positive and downward if it is negative. +[clinic start generated code]*/ + +static PyObject * +_curses_window_scroll_impl(PyCursesWindowObject *self, int group_right_1, + int lines) +/*[clinic end generated code: output=4541a8a11852d360 input=386456524c550113]*/ +{ + int rtn; + const char *funcname; + if (!group_right_1) { + rtn = scroll(self->win); + funcname = "scroll"; + } + else { + rtn = wscrl(self->win, lines); + funcname = "wscrl"; + } + return curses_window_check_err(self, rtn, funcname, "scroll"); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.window.touchline + + start: int + count: int + [ + changed: bool = True + ] + / + +Pretend count lines have been changed, starting with line start. + +If changed is supplied, it specifies whether the affected lines are marked +as having been changed (changed=True) or unchanged (changed=False). +[clinic start generated code]*/ + +static PyObject * +_curses_window_touchline_impl(PyCursesWindowObject *self, int start, + int count, int group_right_1, int changed) +/*[clinic end generated code: output=65d05b3f7438c61d input=36e13b6f5eb591f5]*/ +{ + int rtn; + const char *funcname; + if (!group_right_1) { + rtn = touchline(self->win, start, count); + funcname = "touchline"; + } + else { + rtn = wtouchln(self->win, start, count, changed); + funcname = "wtouchln"; + } + return curses_window_check_err(self, rtn, funcname, "touchline"); +} + +/*[clinic input] +_curses.window.vline + + [ + y: int + Starting Y-coordinate. + x: int + Starting X-coordinate. + ] + + ch: object + Character to draw. + n: int + Line length. + + [ + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Attributes for the character. + ] + / + +Display a vertical line. +[clinic start generated code]*/ + +static PyObject * +_curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int n, + int group_right_1, long attr) +/*[clinic end generated code: output=287ad1cc8982217f input=a6f2dc86a4648b32]*/ +{ + chtype ch_; + + if (!PyCurses_ConvertToChtype(self, ch, &ch_)) + return NULL; + if (group_left_1) { + if (wmove(self->win, y, x) == ERR) { + curses_window_set_error(self, "wmove", "vline"); + return NULL; + } + } + int rtn = wvline(self->win, ch_ | (attr_t)attr, n); + return curses_window_check_err(self, rtn, "wvline", "vline"); +} + +static PyObject * +PyCursesWindow_get_encoding(PyObject *op, void *closure) +{ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); + return PyUnicode_FromString(self->encoding); +} + +static int +PyCursesWindow_set_encoding(PyObject *op, PyObject *value, void *Py_UNUSED(ignored)) +{ + PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); + + PyObject *ascii; + char *encoding; + + /* It is illegal to del win.encoding */ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, + "encoding may not be deleted"); + return -1; + } + + if (!PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "setting encoding to a non-string"); + return -1; + } + ascii = PyUnicode_AsASCIIString(value); + if (ascii == NULL) + return -1; + encoding = _PyMem_Strdup(PyBytes_AS_STRING(ascii)); + Py_DECREF(ascii); + if (encoding == NULL) { + PyErr_NoMemory(); + return -1; + } + PyMem_Free(self->encoding); + self->encoding = encoding; + return 0; +} + +#define clinic_state() (get_cursesmodule_state_by_cls(Py_TYPE(self))) +#include "clinic/_cursesmodule.c.h" +#undef clinic_state + +static PyMethodDef PyCursesWindow_methods[] = { + _CURSES_WINDOW_ADDCH_METHODDEF + _CURSES_WINDOW_ADDNSTR_METHODDEF + _CURSES_WINDOW_ADDSTR_METHODDEF + _CURSES_WINDOW_ATTROFF_METHODDEF + _CURSES_WINDOW_ATTRON_METHODDEF + _CURSES_WINDOW_ATTRSET_METHODDEF + _CURSES_WINDOW_BKGD_METHODDEF +#ifdef HAVE_CURSES_WCHGAT + { + "chgat", PyCursesWindow_ChgAt, METH_VARARGS, + _curses_window_chgat__doc__ + }, +#endif + _CURSES_WINDOW_BKGDSET_METHODDEF + _CURSES_WINDOW_BORDER_METHODDEF + _CURSES_WINDOW_BOX_METHODDEF + {"clear", PyCursesWindow_wclear, METH_NOARGS}, + {"clearok", PyCursesWindow_clearok, METH_VARARGS}, + {"clrtobot", PyCursesWindow_wclrtobot, METH_NOARGS}, + {"clrtoeol", PyCursesWindow_wclrtoeol, METH_NOARGS}, + {"cursyncup", PyCursesWindow_wcursyncup, METH_NOARGS}, + _CURSES_WINDOW_DELCH_METHODDEF + {"deleteln", PyCursesWindow_wdeleteln, METH_NOARGS}, + _CURSES_WINDOW_DERWIN_METHODDEF + _CURSES_WINDOW_ECHOCHAR_METHODDEF + _CURSES_WINDOW_ENCLOSE_METHODDEF + {"erase", PyCursesWindow_werase, METH_NOARGS}, + {"getbegyx", PyCursesWindow_getbegyx, METH_NOARGS}, + _CURSES_WINDOW_GETBKGD_METHODDEF + _CURSES_WINDOW_GETCH_METHODDEF + _CURSES_WINDOW_GETKEY_METHODDEF + _CURSES_WINDOW_GET_WCH_METHODDEF + {"getmaxyx", PyCursesWindow_getmaxyx, METH_NOARGS}, + {"getparyx", PyCursesWindow_getparyx, METH_NOARGS}, + { + "getstr", PyCursesWindow_getstr, METH_VARARGS, + _curses_window_getstr__doc__ + }, + {"getyx", PyCursesWindow_getyx, METH_NOARGS}, + _CURSES_WINDOW_HLINE_METHODDEF + {"idcok", PyCursesWindow_idcok, METH_VARARGS}, + {"idlok", PyCursesWindow_idlok, METH_VARARGS}, +#ifdef HAVE_CURSES_IMMEDOK + {"immedok", PyCursesWindow_immedok, METH_VARARGS}, +#endif + _CURSES_WINDOW_INCH_METHODDEF + _CURSES_WINDOW_INSCH_METHODDEF + {"insdelln", PyCursesWindow_winsdelln, METH_VARARGS}, + {"insertln", PyCursesWindow_winsertln, METH_NOARGS}, + _CURSES_WINDOW_INSNSTR_METHODDEF + _CURSES_WINDOW_INSSTR_METHODDEF + { + "instr", PyCursesWindow_instr, METH_VARARGS, + _curses_window_instr__doc__ + }, + _CURSES_WINDOW_IS_LINETOUCHED_METHODDEF + {"is_wintouched", PyCursesWindow_is_wintouched, METH_NOARGS}, + {"keypad", PyCursesWindow_keypad, METH_VARARGS}, + {"leaveok", PyCursesWindow_leaveok, METH_VARARGS}, + {"move", PyCursesWindow_wmove, METH_VARARGS}, + {"mvderwin", PyCursesWindow_mvderwin, METH_VARARGS}, + {"mvwin", PyCursesWindow_mvwin, METH_VARARGS}, + {"nodelay", PyCursesWindow_nodelay, METH_VARARGS}, + {"notimeout", PyCursesWindow_notimeout, METH_VARARGS}, + _CURSES_WINDOW_NOUTREFRESH_METHODDEF + _CURSES_WINDOW_OVERLAY_METHODDEF + _CURSES_WINDOW_OVERWRITE_METHODDEF + _CURSES_WINDOW_PUTWIN_METHODDEF + _CURSES_WINDOW_REDRAWLN_METHODDEF + {"redrawwin", PyCursesWindow_redrawwin, METH_NOARGS}, + _CURSES_WINDOW_REFRESH_METHODDEF +#ifndef STRICT_SYSV_CURSES + {"resize", PyCursesWindow_wresize, METH_VARARGS}, +#endif + _CURSES_WINDOW_SCROLL_METHODDEF + {"scrollok", PyCursesWindow_scrollok, METH_VARARGS}, + _CURSES_WINDOW_SETSCRREG_METHODDEF + {"standend", PyCursesWindow_wstandend, METH_NOARGS}, + {"standout", PyCursesWindow_wstandout, METH_NOARGS}, + {"subpad", _curses_window_subwin, METH_VARARGS, _curses_window_subwin__doc__}, + _CURSES_WINDOW_SUBWIN_METHODDEF + {"syncdown", PyCursesWindow_wsyncdown, METH_NOARGS}, +#ifdef HAVE_CURSES_SYNCOK + {"syncok", PyCursesWindow_syncok, METH_VARARGS}, +#endif + {"syncup", PyCursesWindow_wsyncup, METH_NOARGS}, + {"timeout", PyCursesWindow_wtimeout, METH_VARARGS}, + _CURSES_WINDOW_TOUCHLINE_METHODDEF + {"touchwin", PyCursesWindow_touchwin, METH_NOARGS}, + {"untouchwin", PyCursesWindow_untouchwin, METH_NOARGS}, + _CURSES_WINDOW_VLINE_METHODDEF + {NULL, NULL} /* sentinel */ +}; + +static PyGetSetDef PyCursesWindow_getsets[] = { + { + "encoding", + PyCursesWindow_get_encoding, + PyCursesWindow_set_encoding, + "the typecode character used to create the array" + }, + {NULL, NULL, NULL, NULL } /* sentinel */ +}; + +static PyType_Slot PyCursesWindow_Type_slots[] = { + {Py_tp_methods, PyCursesWindow_methods}, + {Py_tp_getset, PyCursesWindow_getsets}, + {Py_tp_dealloc, PyCursesWindow_dealloc}, + {Py_tp_traverse, PyCursesWindow_traverse}, + {0, NULL} +}; + +static PyType_Spec PyCursesWindow_Type_spec = { + .name = "_curses.window", + .basicsize = sizeof(PyCursesWindowObject), + .flags = Py_TPFLAGS_DEFAULT + | Py_TPFLAGS_DISALLOW_INSTANTIATION + | Py_TPFLAGS_IMMUTABLETYPE + | Py_TPFLAGS_HEAPTYPE + | Py_TPFLAGS_HAVE_GC, + .slots = PyCursesWindow_Type_slots +}; + +/* -------------------------------------------------------*/ + +/* + * Macros for implementing simple module's methods. + * + * Parameters + * + * X The name of the curses C function or macro to invoke. + * FLAG When false, prefixes the function name with 'no' at runtime, + * This parameter is present in the signature and auto-generated + * by Argument Clinic. + * + * These macros should only be used for generating the body of + * the module's methods since they need a module reference. + * + * The Python function name must be the same as the curses function name (X). + */ + +#define NoArgNoReturnFunctionBody(X) \ +{ \ + PyCursesStatefulInitialised(module); \ + return curses_check_err(module, X(), # X, NULL); \ +} + +#define NoArgOrFlagNoReturnFunctionBody(X, FLAG) \ +{ \ + PyCursesStatefulInitialised(module); \ + int rtn; \ + const char *funcname; \ + if (FLAG) { \ + rtn = X(); \ + funcname = # X; \ + } \ + else { \ + rtn = no ## X(); \ + funcname = "no" # X; \ + } \ + return curses_check_err(module, rtn, funcname, # X); \ +} + +#define NoArgReturnIntFunctionBody(X) \ +{ \ + PyCursesStatefulInitialised(module); \ + int rtn = X(); \ + if (rtn == ERR) { \ + curses_set_error(module, # X, NULL); \ + return NULL; \ + } \ + return PyLong_FromLong(rtn); \ +} + +#define NoArgReturnStringFunctionBody(X) \ +{ \ + PyCursesStatefulInitialised(module); \ + const char *res = X(); \ + if (res == NULL) { \ + curses_set_null_error(module, # X, NULL); \ + return NULL; \ + } \ + return PyBytes_FromString(res); \ +} + +#define NoArgTrueFalseFunctionBody(X) \ +{ \ + PyCursesStatefulInitialised(module); \ + return PyBool_FromLong(X()); \ +} + +#define NoArgNoReturnVoidFunctionBody(X) \ +{ \ + PyCursesStatefulInitialised(module); \ + X(); \ + Py_RETURN_NONE; \ +} + +/********************************************************************* + Global Functions +**********************************************************************/ + +#ifdef HAVE_CURSES_FILTER +/*[clinic input] +_curses.filter + +[clinic start generated code]*/ + +static PyObject * +_curses_filter_impl(PyObject *module) +/*[clinic end generated code: output=fb5b8a3642eb70b5 input=668c75a6992d3624]*/ +{ + /* not checking for PyCursesInitialised here since filter() must + be called before initscr() */ + filter(); + Py_RETURN_NONE; +} +#endif + +/*[clinic input] +_curses.baudrate + +Return the output speed of the terminal in bits per second. +[clinic start generated code]*/ + +static PyObject * +_curses_baudrate_impl(PyObject *module) +/*[clinic end generated code: output=3c63c6c401d7d9c0 input=921f022ed04a0fd9]*/ +NoArgReturnIntFunctionBody(baudrate) + +/*[clinic input] +_curses.beep + +Emit a short attention sound. +[clinic start generated code]*/ + +static PyObject * +_curses_beep_impl(PyObject *module) +/*[clinic end generated code: output=425274962abe49a2 input=a35698ca7d0162bc]*/ +NoArgNoReturnFunctionBody(beep) + +/*[clinic input] +@permit_long_summary +_curses.can_change_color + +Return True if the programmer can change the colors displayed by the terminal. +[clinic start generated code]*/ + +static PyObject * +_curses_can_change_color_impl(PyObject *module) +/*[clinic end generated code: output=359df8c3c77d8bf1 input=8315c364ba1e5b4c]*/ +NoArgTrueFalseFunctionBody(can_change_color) + +/*[clinic input] +_curses.cbreak + + flag: bool = True + If false, the effect is the same as calling nocbreak(). + / + +Enter cbreak mode. + +In cbreak mode (sometimes called "rare" mode) normal tty line buffering is +turned off and characters are available to be read one by one. However, +unlike raw mode, special characters (interrupt, quit, suspend, and flow +control) retain their effects on the tty driver and calling program. +Calling first raw() then cbreak() leaves the terminal in cbreak mode. +[clinic start generated code]*/ + +static PyObject * +_curses_cbreak_impl(PyObject *module, int flag) +/*[clinic end generated code: output=9f9dee9664769751 input=c7d0bddda93016c1]*/ +NoArgOrFlagNoReturnFunctionBody(cbreak, flag) + +/*[clinic input] +@permit_long_docstring_body +_curses.color_content + + color_number: color + The number of the color (0 - (COLORS-1)). + / + +Return the red, green, and blue (RGB) components of the specified color. + +A 3-tuple is returned, containing the R, G, B values for the given color, +which will be between 0 (no component) and 1000 (maximum amount of component). +[clinic start generated code]*/ + +static PyObject * +_curses_color_content_impl(PyObject *module, int color_number) +/*[clinic end generated code: output=17b466df7054e0de input=baffe25b351eb916]*/ +{ + _CURSES_COLOR_VAL_TYPE r,g,b; + + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); + + if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) { + const char *funcname = Py_STRINGIFY(_COLOR_CONTENT_FUNC); + curses_set_error(module, funcname, "color_content"); + return NULL; + } + + return Py_BuildValue("(iii)", r, g, b); +} + +/*[clinic input] +_curses.color_pair + + pair_number: int + The number of the color pair. + / + +Return the attribute value for displaying text in the specified color. + +This attribute value can be combined with A_STANDOUT, A_REVERSE, and the +other A_* attributes. pair_number() is the counterpart to this function. +[clinic start generated code]*/ + +static PyObject * +_curses_color_pair_impl(PyObject *module, int pair_number) +/*[clinic end generated code: output=60718abb10ce9feb input=6034e9146f343802]*/ +{ + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); + + return PyLong_FromLong(COLOR_PAIR(pair_number)); +} + +/*[clinic input] +_curses.curs_set + + visibility: int + 0 for invisible, 1 for normal visible, or 2 for very visible. + / + +Set the cursor state. + +If the terminal supports the visibility requested, the previous cursor +state is returned; otherwise, an exception is raised. On many terminals, +the "visible" mode is an underline cursor and the "very visible" mode is +a block cursor. +[clinic start generated code]*/ + +static PyObject * +_curses_curs_set_impl(PyObject *module, int visibility) +/*[clinic end generated code: output=ee8e62483b1d6cd4 input=81a7924a65d29504]*/ +{ + int erg; + + PyCursesStatefulInitialised(module); + + erg = curs_set(visibility); + if (erg == ERR) { + curses_set_error(module, "curs_set", NULL); + return NULL; + } + + return PyLong_FromLong((long) erg); +} + +/*[clinic input] +_curses.def_prog_mode + +Save the current terminal mode as the "program" mode. + +The "program" mode is the mode when the running program is using curses. + +Subsequent calls to reset_prog_mode() will restore this mode. +[clinic start generated code]*/ + +static PyObject * +_curses_def_prog_mode_impl(PyObject *module) +/*[clinic end generated code: output=05d5a351fff874aa input=768b9cace620dda5]*/ +NoArgNoReturnFunctionBody(def_prog_mode) + +/*[clinic input] +_curses.def_shell_mode + +Save the current terminal mode as the "shell" mode. + +The "shell" mode is the mode when the running program is not using curses. + +Subsequent calls to reset_shell_mode() will restore this mode. +[clinic start generated code]*/ + +static PyObject * +_curses_def_shell_mode_impl(PyObject *module) +/*[clinic end generated code: output=d6e42f5c768f860f input=5ead21f6f0baa894]*/ +NoArgNoReturnFunctionBody(def_shell_mode) + +/*[clinic input] +_curses.delay_output + + ms: int + Duration in milliseconds. + / + +Insert a pause in output. +[clinic start generated code]*/ + +static PyObject * +_curses_delay_output_impl(PyObject *module, int ms) +/*[clinic end generated code: output=b6613a67f17fa4f4 input=5316457f5f59196c]*/ +{ + PyCursesStatefulInitialised(module); + + return curses_check_err(module, delay_output(ms), "delay_output", NULL); +} + +/*[clinic input] +_curses.doupdate + +Update the physical screen to match the virtual screen. +[clinic start generated code]*/ + +static PyObject * +_curses_doupdate_impl(PyObject *module) +/*[clinic end generated code: output=f34536975a75680c input=8da80914432a6489]*/ +NoArgNoReturnFunctionBody(doupdate) + +/*[clinic input] +_curses.echo + + flag: bool = True + If false, the effect is the same as calling noecho(). + / + +Enter echo mode. + +In echo mode, each character input is echoed to the screen as it is entered. +[clinic start generated code]*/ + +static PyObject * +_curses_echo_impl(PyObject *module, int flag) +/*[clinic end generated code: output=03acb2ddfa6c8729 input=86cd4d5bb1d569c0]*/ +NoArgOrFlagNoReturnFunctionBody(echo, flag) + +/*[clinic input] +_curses.endwin + +De-initialize the library, and return terminal to normal status. +[clinic start generated code]*/ + +static PyObject * +_curses_endwin_impl(PyObject *module) +/*[clinic end generated code: output=c0150cd96d2f4128 input=e172cfa43062f3fa]*/ +NoArgNoReturnFunctionBody(endwin) + +/*[clinic input] +_curses.erasechar + +Return the user's current erase character. +[clinic start generated code]*/ + +static PyObject * +_curses_erasechar_impl(PyObject *module) +/*[clinic end generated code: output=3df305dc6b926b3f input=628c136c3c5758d3]*/ +{ + char ch; + + PyCursesStatefulInitialised(module); + + ch = erasechar(); + + return PyBytes_FromStringAndSize(&ch, 1); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.flash + +Flash the screen. + +That is, change it to reverse-video and then change it back in a short interval. +[clinic start generated code]*/ + +static PyObject * +_curses_flash_impl(PyObject *module) +/*[clinic end generated code: output=488b8a0ebd9ea9b8 input=dd33d718e6edf436]*/ +NoArgNoReturnFunctionBody(flash) + +/*[clinic input] +_curses.flushinp + +Flush all input buffers. + +This throws away any typeahead that has been typed by the user and has not +yet been processed by the program. +[clinic start generated code]*/ + +static PyObject * +_curses_flushinp_impl(PyObject *module) +/*[clinic end generated code: output=7e7a1fc1473960f5 input=59d042e705cef5ec]*/ +NoArgNoReturnVoidFunctionBody(flushinp) + +#ifdef getsyx +/*[clinic input] +_curses.getsyx + +Return the current coordinates of the virtual screen cursor. + +Return a (y, x) tuple. If leaveok is currently true, return (-1, -1). +[clinic start generated code]*/ + +static PyObject * +_curses_getsyx_impl(PyObject *module) +/*[clinic end generated code: output=c8e6c3f42349a038 input=9e1f862f3b4f7cba]*/ +{ + int x = 0; + int y = 0; + + PyCursesStatefulInitialised(module); + + getsyx(y, x); + + return Py_BuildValue("(ii)", y, x); +} +#endif + +#ifdef NCURSES_MOUSE_VERSION +/*[clinic input] +_curses.getmouse + +Retrieve the queued mouse event. + +After getch() returns KEY_MOUSE to signal a mouse event, this function +returns a 5-tuple (id, x, y, z, bstate). +[clinic start generated code]*/ + +static PyObject * +_curses_getmouse_impl(PyObject *module) +/*[clinic end generated code: output=ccf4242546b9cfa8 input=5b756ee6f5b481b1]*/ +{ + int rtn; + MEVENT event; + + PyCursesStatefulInitialised(module); + + rtn = getmouse( &event ); + if (rtn == ERR) { + curses_set_error(module, "getmouse", NULL); + return NULL; + } + return Py_BuildValue("(hiiik)", + (short)event.id, + (int)event.x, (int)event.y, (int)event.z, + (unsigned long) event.bstate); +} + +/*[clinic input] +_curses.ungetmouse + + id: short + x: int + y: int + z: int + bstate: unsigned_long(bitwise=True) + / + +Push a KEY_MOUSE event onto the input queue. + +The following getmouse() will return the given state data. +[clinic start generated code]*/ + +static PyObject * +_curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, + unsigned long bstate) +/*[clinic end generated code: output=3430c9b0fc5c4341 input=fd650b2ca5a01e8f]*/ +{ + MEVENT event; + + PyCursesStatefulInitialised(module); + + event.id = id; + event.x = x; + event.y = y; + event.z = z; + event.bstate = bstate; + return curses_check_err(module, ungetmouse(&event), "ungetmouse", NULL); +} +#endif + +/*[clinic input] +_curses.getwin + + file: object + / + +Read window related data stored in the file by an earlier putwin() call. + +The routine then creates and initializes a new window using that data, +returning the new window object. +[clinic start generated code]*/ + +static PyObject * +_curses_getwin(PyObject *module, PyObject *file) +/*[clinic end generated code: output=a79e0df3379af756 input=f713d2bba0e4c929]*/ +{ + FILE *fp; + PyObject *data; + size_t datalen; + WINDOW *win; + PyObject *res = NULL; + + PyCursesStatefulInitialised(module); + + fp = tmpfile(); + if (fp == NULL) + return PyErr_SetFromErrno(PyExc_OSError); + + if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0) + goto error; + + data = PyObject_CallMethod(file, "read", NULL); + if (data == NULL) + goto error; + if (!PyBytes_Check(data)) { + PyErr_Format(PyExc_TypeError, + "f.read() returned %.100s instead of bytes", + Py_TYPE(data)->tp_name); + Py_DECREF(data); + goto error; + } + datalen = PyBytes_GET_SIZE(data); + if (fwrite(PyBytes_AS_STRING(data), 1, datalen, fp) != datalen) { + PyErr_SetFromErrno(PyExc_OSError); + Py_DECREF(data); + goto error; + } + Py_DECREF(data); + + fseek(fp, 0, 0); + win = getwin(fp); + if (win == NULL) { + curses_set_null_error(module, "getwin", NULL); + goto error; + } + cursesmodule_state *state = get_cursesmodule_state(module); + res = PyCursesWindow_New(state, win, NULL, NULL); + +error: + fclose(fp); + return res; +} + +/*[clinic input] +_curses.halfdelay + + tenths: byte + Maximal blocking delay in tenths of seconds (1 - 255). + / + +Enter half-delay mode. + +Use nocbreak() to leave half-delay mode. +[clinic start generated code]*/ + +static PyObject * +_curses_halfdelay_impl(PyObject *module, unsigned char tenths) +/*[clinic end generated code: output=e92cdf0ef33c0663 input=e42dce7259c15100]*/ +{ + PyCursesStatefulInitialised(module); + + return curses_check_err(module, halfdelay(tenths), "halfdelay", NULL); +} + +/*[clinic input] +_curses.has_colors + +Return True if the terminal can display colors; otherwise, return False. +[clinic start generated code]*/ + +static PyObject * +_curses_has_colors_impl(PyObject *module) +/*[clinic end generated code: output=db5667483139e3e2 input=b2ec41b739d896c6]*/ +NoArgTrueFalseFunctionBody(has_colors) + +/*[clinic input] +_curses.has_ic + +Return True if the terminal has insert- and delete-character capabilities. +[clinic start generated code]*/ + +static PyObject * +_curses_has_ic_impl(PyObject *module) +/*[clinic end generated code: output=6be24da9cb1268fe input=9bc2d3a797cc7324]*/ +NoArgTrueFalseFunctionBody(has_ic) + +/*[clinic input] +_curses.has_il + +Return True if the terminal has insert- and delete-line capabilities. +[clinic start generated code]*/ + +static PyObject * +_curses_has_il_impl(PyObject *module) +/*[clinic end generated code: output=d45bd7788ff9f5f4 input=cd939d5607ee5427]*/ +NoArgTrueFalseFunctionBody(has_il) + +#ifdef HAVE_CURSES_HAS_KEY +/*[clinic input] +_curses.has_key + + key: int + Key number. + / + +Return True if the current terminal type recognizes a key with that value. +[clinic start generated code]*/ + +static PyObject * +_curses_has_key_impl(PyObject *module, int key) +/*[clinic end generated code: output=19ad48319414d0b1 input=78bd44acf1a4997c]*/ +{ + PyCursesStatefulInitialised(module); + + return PyBool_FromLong(has_key(key)); +} +#endif + +/*[clinic input] +_curses.init_color + + color_number: color + The number of the color to be changed (0 - (COLORS-1)). + r: component + Red component (0 - 1000). + g: component + Green component (0 - 1000). + b: component + Blue component (0 - 1000). + / + +Change the definition of a color. + +When init_color() is used, all occurrences of that color on the screen +immediately change to the new definition. This function is a no-op on +most terminals; it is active only if can_change_color() returns true. +[clinic start generated code]*/ + +static PyObject * +_curses_init_color_impl(PyObject *module, int color_number, short r, short g, + short b) +/*[clinic end generated code: output=d7ed71b2d818cdf2 input=ae2b8bea0f152c80]*/ +{ + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); + + return curses_check_err(module, + _CURSES_INIT_COLOR_FUNC(color_number, r, g, b), + Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC), + NULL); +} + +/*[clinic input] +_curses.init_pair + + pair_number: pair + The number of the color-pair to be changed (1 - (COLOR_PAIRS-1)). + fg: color_allow_default + Foreground color number (-1 - (COLORS-1)). + bg: color_allow_default + Background color number (-1 - (COLORS-1)). + / + +Change the definition of a color-pair. + +If the color-pair was previously initialized, the screen is refreshed and +all occurrences of that color-pair are changed to the new definition. +[clinic start generated code]*/ + +static PyObject * +_curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) +/*[clinic end generated code: output=a0bba03d2bbc3ee6 input=54b421b44c12c389]*/ +{ + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); + + if (_CURSES_INIT_PAIR_FUNC(pair_number, fg, bg) == ERR) { + if (pair_number >= COLOR_PAIRS) { + PyErr_Format(PyExc_ValueError, + "Color pair is greater than COLOR_PAIRS-1 (%d).", + COLOR_PAIRS - 1); + } + else { + const char *funcname = Py_STRINGIFY(_CURSES_INIT_PAIR_FUNC); + curses_set_error(module, funcname, "init_pair"); + } + return NULL; + } + + Py_RETURN_NONE; +} + +/*[clinic input] +_curses.initscr + +Initialize the library. + +Return a WindowObject which represents the whole screen. +[clinic start generated code]*/ + +static PyObject * +_curses_initscr_impl(PyObject *module) +/*[clinic end generated code: output=619fb68443810b7b input=514f4bce1821f6b5]*/ +{ + WINDOW *win; + + if (curses_initscr_called) { + cursesmodule_state *state = get_cursesmodule_state(module); + int code = wrefresh(stdscr); + if (code == ERR) { + _curses_set_null_error(state, "wrefresh", "initscr"); + return NULL; + } + return PyCursesWindow_New(state, stdscr, NULL, NULL); + } + + win = initscr(); + + if (win == NULL) { + curses_set_null_error(module, "initscr", NULL); + return NULL; + } + + curses_initscr_called = curses_setupterm_called = TRUE; + + PyObject *module_dict = PyModule_GetDict(module); // borrowed + if (module_dict == NULL) { + return NULL; + } + /* This was moved from initcurses() because it core dumped on SGI, + where they're not defined until you've called initscr() */ +#define SetDictInt(NAME, VALUE) \ + do { \ + PyObject *value = PyLong_FromLong((long)(VALUE)); \ + if (value == NULL) { \ + return NULL; \ + } \ + int rc = PyDict_SetItemString(module_dict, (NAME), value); \ + Py_DECREF(value); \ + if (rc < 0) { \ + return NULL; \ + } \ + } while (0) + + /* Here are some graphic symbols you can use */ + SetDictInt("ACS_ULCORNER", (ACS_ULCORNER)); + SetDictInt("ACS_LLCORNER", (ACS_LLCORNER)); + SetDictInt("ACS_URCORNER", (ACS_URCORNER)); + SetDictInt("ACS_LRCORNER", (ACS_LRCORNER)); + SetDictInt("ACS_LTEE", (ACS_LTEE)); + SetDictInt("ACS_RTEE", (ACS_RTEE)); + SetDictInt("ACS_BTEE", (ACS_BTEE)); + SetDictInt("ACS_TTEE", (ACS_TTEE)); + SetDictInt("ACS_HLINE", (ACS_HLINE)); + SetDictInt("ACS_VLINE", (ACS_VLINE)); + SetDictInt("ACS_PLUS", (ACS_PLUS)); +#if !defined(__hpux) || defined(HAVE_NCURSES_H) + /* On HP/UX 11, these are of type cchar_t, which is not an + integral type. If this is a problem on more platforms, a + configure test should be added to determine whether ACS_S1 + is of integral type. */ + SetDictInt("ACS_S1", (ACS_S1)); + SetDictInt("ACS_S9", (ACS_S9)); + SetDictInt("ACS_DIAMOND", (ACS_DIAMOND)); + SetDictInt("ACS_CKBOARD", (ACS_CKBOARD)); + SetDictInt("ACS_DEGREE", (ACS_DEGREE)); + SetDictInt("ACS_PLMINUS", (ACS_PLMINUS)); + SetDictInt("ACS_BULLET", (ACS_BULLET)); + SetDictInt("ACS_LARROW", (ACS_LARROW)); + SetDictInt("ACS_RARROW", (ACS_RARROW)); + SetDictInt("ACS_DARROW", (ACS_DARROW)); + SetDictInt("ACS_UARROW", (ACS_UARROW)); + SetDictInt("ACS_BOARD", (ACS_BOARD)); + SetDictInt("ACS_LANTERN", (ACS_LANTERN)); + SetDictInt("ACS_BLOCK", (ACS_BLOCK)); +#endif + SetDictInt("ACS_BSSB", (ACS_ULCORNER)); + SetDictInt("ACS_SSBB", (ACS_LLCORNER)); + SetDictInt("ACS_BBSS", (ACS_URCORNER)); + SetDictInt("ACS_SBBS", (ACS_LRCORNER)); + SetDictInt("ACS_SBSS", (ACS_RTEE)); + SetDictInt("ACS_SSSB", (ACS_LTEE)); + SetDictInt("ACS_SSBS", (ACS_BTEE)); + SetDictInt("ACS_BSSS", (ACS_TTEE)); + SetDictInt("ACS_BSBS", (ACS_HLINE)); + SetDictInt("ACS_SBSB", (ACS_VLINE)); + SetDictInt("ACS_SSSS", (ACS_PLUS)); + + /* The following are never available with strict SYSV curses */ +#ifdef ACS_S3 + SetDictInt("ACS_S3", (ACS_S3)); +#endif +#ifdef ACS_S7 + SetDictInt("ACS_S7", (ACS_S7)); +#endif +#ifdef ACS_LEQUAL + SetDictInt("ACS_LEQUAL", (ACS_LEQUAL)); +#endif +#ifdef ACS_GEQUAL + SetDictInt("ACS_GEQUAL", (ACS_GEQUAL)); +#endif +#ifdef ACS_PI + SetDictInt("ACS_PI", (ACS_PI)); +#endif +#ifdef ACS_NEQUAL + SetDictInt("ACS_NEQUAL", (ACS_NEQUAL)); +#endif +#ifdef ACS_STERLING + SetDictInt("ACS_STERLING", (ACS_STERLING)); +#endif + + SetDictInt("LINES", LINES); + SetDictInt("COLS", COLS); +#undef SetDictInt + + cursesmodule_state *state = get_cursesmodule_state(module); + PyObject *winobj = PyCursesWindow_New(state, win, NULL, NULL); + if (winobj == NULL) { + return NULL; + } + curses_screen_encoding = ((PyCursesWindowObject *)winobj)->encoding; + return winobj; +} + +/*[clinic input] +_curses.setupterm + + term: str(accept={str, NoneType}) = None + Terminal name. + If omitted, the value of the TERM environment variable will be used. + fd: int = -1 + File descriptor to which any initialization sequences will be sent. + If not supplied, the file descriptor for sys.stdout will be used. + +Initialize the terminal. +[clinic start generated code]*/ + +static PyObject * +_curses_setupterm_impl(PyObject *module, const char *term, int fd) +/*[clinic end generated code: output=4584e587350f2848 input=4511472766af0c12]*/ +{ + int err; + + if (fd == -1) { + PyObject* sys_stdout; + + if (PySys_GetOptionalAttrString("stdout", &sys_stdout) < 0) { + return NULL; + } + + if (sys_stdout == NULL || sys_stdout == Py_None) { + cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, "lost sys.stdout"); + Py_XDECREF(sys_stdout); + return NULL; + } + + fd = PyObject_AsFileDescriptor(sys_stdout); + Py_DECREF(sys_stdout); + if (fd == -1) { + return NULL; + } + } + + if (!curses_setupterm_called && setupterm((char *)term, fd, &err) == ERR) { + const char* s = "setupterm: unknown error"; + + if (err == 0) { + s = "setupterm: could not find terminal"; + } else if (err == -1) { + s = "setupterm: could not find terminfo database"; + } + + cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, s); + return NULL; + } + + curses_setupterm_called = TRUE; + + Py_RETURN_NONE; +} + +#if defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102 +// https://invisible-island.net/ncurses/NEWS.html#index-t20080119 + +/*[clinic input] +_curses.get_escdelay + +Gets the curses ESCDELAY setting. + +Gets the number of milliseconds to wait after reading an escape character, +to distinguish between an individual escape character entered on the +keyboard from escape sequences sent by cursor and function keys. +[clinic start generated code]*/ + +static PyObject * +_curses_get_escdelay_impl(PyObject *module) +/*[clinic end generated code: output=222fa1a822555d60 input=be2d5b3dd974d0a4]*/ +{ + return PyLong_FromLong(ESCDELAY); +} +/*[clinic input] +_curses.set_escdelay + ms: int + length of the delay in milliseconds. + / + +Sets the curses ESCDELAY setting. + +Sets the number of milliseconds to wait after reading an escape character, +to distinguish between an individual escape character entered on the +keyboard from escape sequences sent by cursor and function keys. +[clinic start generated code]*/ + +static PyObject * +_curses_set_escdelay_impl(PyObject *module, int ms) +/*[clinic end generated code: output=43818efbf7980ac4 input=7796fe19f111e250]*/ +{ + if (ms <= 0) { + PyErr_SetString(PyExc_ValueError, "ms must be > 0"); + return NULL; + } + + return curses_check_err(module, set_escdelay(ms), "set_escdelay", NULL); +} + +/*[clinic input] +_curses.get_tabsize + +Gets the curses TABSIZE setting. + +Gets the number of columns used by the curses library when converting a tab +character to spaces as it adds the tab to a window. +[clinic start generated code]*/ + +static PyObject * +_curses_get_tabsize_impl(PyObject *module) +/*[clinic end generated code: output=7e9e51fb6126fbdf input=74af86bf6c9f5d7e]*/ +{ + return PyLong_FromLong(TABSIZE); +} +/*[clinic input] +_curses.set_tabsize + size: int + rendered cell width of a tab character. + / + +Sets the curses TABSIZE setting. + +Sets the number of columns used by the curses library when converting a tab +character to spaces as it adds the tab to a window. +[clinic start generated code]*/ + +static PyObject * +_curses_set_tabsize_impl(PyObject *module, int size) +/*[clinic end generated code: output=c1de5a76c0daab1e input=78cba6a3021ad061]*/ +{ + if (size <= 0) { + PyErr_SetString(PyExc_ValueError, "size must be > 0"); + return NULL; + } + + return curses_check_err(module, set_tabsize(size), "set_tabsize", NULL); +} +#endif + +/*[clinic input] +_curses.intrflush + + flag: bool + / + +[clinic start generated code]*/ + +static PyObject * +_curses_intrflush_impl(PyObject *module, int flag) +/*[clinic end generated code: output=c1986df35e999a0f input=c65fe2ef973fe40a]*/ +{ + PyCursesStatefulInitialised(module); + + return curses_check_err(module, intrflush(NULL, flag), "intrflush", NULL); +} + +/*[clinic input] +_curses.isendwin + +Return True if endwin() has been called. +[clinic start generated code]*/ + +static PyObject * +_curses_isendwin_impl(PyObject *module) +/*[clinic end generated code: output=d73179e4a7e1eb8c input=6cdb01a7ebf71397]*/ +NoArgTrueFalseFunctionBody(isendwin) + +#ifdef HAVE_CURSES_IS_TERM_RESIZED +/*[clinic input] +@permit_long_summary +_curses.is_term_resized + + nlines: int + Height. + ncols: int + Width. + / + +Return True if resize_term() would modify the window structure, False otherwise. +[clinic start generated code]*/ + +static PyObject * +_curses_is_term_resized_impl(PyObject *module, int nlines, int ncols) +/*[clinic end generated code: output=aafe04afe50f1288 input=5792a3f40cecb010]*/ +{ + PyCursesStatefulInitialised(module); + + return PyBool_FromLong(is_term_resized(nlines, ncols)); +} +#endif /* HAVE_CURSES_IS_TERM_RESIZED */ + +/*[clinic input] +_curses.keyname + + key: int + Key number. + / + +Return the name of specified key. +[clinic start generated code]*/ + +static PyObject * +_curses_keyname_impl(PyObject *module, int key) +/*[clinic end generated code: output=fa2675ab3f4e056b input=ee4b1d0f243a2a2b]*/ +{ + const char *knp; + + PyCursesStatefulInitialised(module); + + if (key < 0) { + PyErr_SetString(PyExc_ValueError, "invalid key number"); + return NULL; + } + knp = keyname(key); + + return PyBytes_FromString((knp == NULL) ? "" : knp); +} + +/*[clinic input] +_curses.killchar + +Return the user's current line kill character. +[clinic start generated code]*/ + +static PyObject * +_curses_killchar_impl(PyObject *module) +/*[clinic end generated code: output=31c3a45b2c528269 input=1ff171c38df5ccad]*/ +{ + char ch; + + ch = killchar(); + + return PyBytes_FromStringAndSize(&ch, 1); +} + +/*[clinic input] +@permit_long_docstring_body +_curses.longname + +Return the terminfo long name field describing the current terminal. + +The maximum length of a verbose description is 128 characters. It is defined +only after the call to initscr(). +[clinic start generated code]*/ + +static PyObject * +_curses_longname_impl(PyObject *module) +/*[clinic end generated code: output=fdf30433727ef568 input=5de06852f2230ddb]*/ +NoArgReturnStringFunctionBody(longname) + +/*[clinic input] +_curses.meta + + yes: bool + / + +Enable/disable meta keys. + +If yes is True, allow 8-bit characters to be input. If yes is False, +allow only 7-bit characters. +[clinic start generated code]*/ + +static PyObject * +_curses_meta_impl(PyObject *module, int yes) +/*[clinic end generated code: output=22f5abda46a605d8 input=cfe7da79f51d0e30]*/ +{ + PyCursesStatefulInitialised(module); + + return curses_check_err(module, meta(stdscr, yes), "meta", NULL); +} + +#ifdef NCURSES_MOUSE_VERSION +/*[clinic input] +_curses.mouseinterval + + interval: int + Time in milliseconds. + / + +Set and retrieve the maximum time between press and release in a click. + +Set the maximum time that can elapse between press and release events in +order for them to be recognized as a click, and return the previous interval +value. +[clinic start generated code]*/ + +static PyObject * +_curses_mouseinterval_impl(PyObject *module, int interval) +/*[clinic end generated code: output=c4f5ff04354634c5 input=75aaa3f0db10ac4e]*/ +{ + PyCursesStatefulInitialised(module); + int value = mouseinterval(interval); + if (value == ERR) { + curses_set_error(module, "mouseinterval", NULL); + return NULL; + } + return PyLong_FromLong(value); +} + +/*[clinic input] +@permit_long_summary +_curses.mousemask + + newmask: unsigned_long(bitwise=True) + / + +Set the mouse events to be reported, and return a tuple (availmask, oldmask). + +Return a tuple (availmask, oldmask). availmask indicates which of the +specified mouse events can be reported; on complete failure it returns 0. +oldmask is the previous value of the given window's mouse event mask. +If this function is never called, no mouse events are ever reported. +[clinic start generated code]*/ + +static PyObject * +_curses_mousemask_impl(PyObject *module, unsigned long newmask) +/*[clinic end generated code: output=9406cf1b8a36e485 input=b92ff4fbe5ce61b1]*/ +{ + mmask_t oldmask, availmask; + + PyCursesStatefulInitialised(module); + availmask = mousemask((mmask_t)newmask, &oldmask); + return Py_BuildValue("(kk)", + (unsigned long)availmask, (unsigned long)oldmask); +} +#endif + +/*[clinic input] +_curses.napms -> int + + ms: int + Duration in milliseconds. + / + +Sleep for specified time. +[clinic start generated code]*/ + +static int +_curses_napms_impl(PyObject *module, int ms) +/*[clinic end generated code: output=5f292a6a724491bd input=c6d6e01f2f1df9f7]*/ +{ + if (!_PyCursesStatefulCheckFunction(module, + curses_initscr_called, + "initscr")) { + return -1; + } + return napms(ms); +} + + +/*[clinic input] +_curses.newpad + + nlines: int + Height. + ncols: int + Width. + / + +Create and return a pointer to a new pad data structure. +[clinic start generated code]*/ + +static PyObject * +_curses_newpad_impl(PyObject *module, int nlines, int ncols) +/*[clinic end generated code: output=de52a56eb1098ec9 input=93f1272f240d8894]*/ +{ + WINDOW *win; + + PyCursesStatefulInitialised(module); + + win = newpad(nlines, ncols); + + if (win == NULL) { + curses_set_null_error(module, "newpad", NULL); + return NULL; + } + + cursesmodule_state *state = get_cursesmodule_state(module); + return PyCursesWindow_New(state, win, NULL, NULL); +} + +/*[clinic input] +_curses.newwin + + nlines: int + Height. + ncols: int + Width. + [ + begin_y: int = 0 + Top side y-coordinate. + begin_x: int = 0 + Left side x-coordinate. + ] + / + +Return a new window. + +By default, the window will extend from the specified position to the lower +right corner of the screen. +[clinic start generated code]*/ + +static PyObject * +_curses_newwin_impl(PyObject *module, int nlines, int ncols, + int group_right_1, int begin_y, int begin_x) +/*[clinic end generated code: output=c1e0a8dc8ac2826c input=29312c15a72a003d]*/ +{ + WINDOW *win; + + PyCursesStatefulInitialised(module); + + win = newwin(nlines,ncols,begin_y,begin_x); + if (win == NULL) { + curses_set_null_error(module, "newwin", NULL); + return NULL; + } + + cursesmodule_state *state = get_cursesmodule_state(module); + return PyCursesWindow_New(state, win, NULL, NULL); +} + +/*[clinic input] +_curses.nl + + flag: bool = True + If false, the effect is the same as calling nonl(). + / + +Enter newline mode. + +This mode translates the return key into newline on input, and translates +newline into return and line-feed on output. Newline mode is initially on. +[clinic start generated code]*/ + +static PyObject * +_curses_nl_impl(PyObject *module, int flag) +/*[clinic end generated code: output=b39cc0ffc9015003 input=18e3e9c6e8cfcf6f]*/ +NoArgOrFlagNoReturnFunctionBody(nl, flag) + +/*[clinic input] +_curses.nocbreak + +Leave cbreak mode. + +Return to normal "cooked" mode with line buffering. +[clinic start generated code]*/ + +static PyObject * +_curses_nocbreak_impl(PyObject *module) +/*[clinic end generated code: output=eabf3833a4fbf620 input=e4b65f7d734af400]*/ +NoArgNoReturnFunctionBody(nocbreak) + +/*[clinic input] +_curses.noecho + +Leave echo mode. + +Echoing of input characters is turned off. +[clinic start generated code]*/ + +static PyObject * +_curses_noecho_impl(PyObject *module) +/*[clinic end generated code: output=cc95ab45bc98f41b input=76714df529e614c3]*/ +NoArgNoReturnFunctionBody(noecho) + +/*[clinic input] +_curses.nonl + +Leave newline mode. + +Disable translation of return into newline on input, and disable low-level +translation of newline into newline/return on output. +[clinic start generated code]*/ + +static PyObject * +_curses_nonl_impl(PyObject *module) +/*[clinic end generated code: output=99e917e9715770c6 input=9d37dd122d3022fc]*/ +NoArgNoReturnFunctionBody(nonl) + +/*[clinic input] +_curses.noqiflush + +Disable queue flushing. + +When queue flushing is disabled, normal flush of input and output queues +associated with the INTR, QUIT and SUSP characters will not be done. +[clinic start generated code]*/ + +static PyObject * +_curses_noqiflush_impl(PyObject *module) +/*[clinic end generated code: output=8b95a4229bbf0877 input=ba3e6b2e3e54c4df]*/ +NoArgNoReturnVoidFunctionBody(noqiflush) + +/*[clinic input] +_curses.noraw + +Leave raw mode. + +Return to normal "cooked" mode with line buffering. +[clinic start generated code]*/ + +static PyObject * +_curses_noraw_impl(PyObject *module) +/*[clinic end generated code: output=39894e5524c430cc input=6ec86692096dffb5]*/ +NoArgNoReturnFunctionBody(noraw) + +/*[clinic input] +_curses.pair_content + + pair_number: pair + The number of the color pair (0 - (COLOR_PAIRS-1)). + / + +Return a tuple (fg, bg) containing the colors for the requested color pair. +[clinic start generated code]*/ + +static PyObject * +_curses_pair_content_impl(PyObject *module, int pair_number) +/*[clinic end generated code: output=4a726dd0e6885f3f input=03970f840fc7b739]*/ +{ + _CURSES_COLOR_NUM_TYPE f, b; + + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); + + if (_CURSES_PAIR_CONTENT_FUNC(pair_number, &f, &b) == ERR) { + if (pair_number >= COLOR_PAIRS) { + PyErr_Format(PyExc_ValueError, + "Color pair is greater than COLOR_PAIRS-1 (%d).", + COLOR_PAIRS - 1); + } + else { + const char *funcname = Py_STRINGIFY(_CURSES_PAIR_CONTENT_FUNC); + curses_set_error(module, funcname, "pair_content"); + } + return NULL; + } + + return Py_BuildValue("(ii)", f, b); +} + +/*[clinic input] +_curses.pair_number + + attr: int + / + +Return the number of the color-pair set by the specified attribute value. + +color_pair() is the counterpart to this function. +[clinic start generated code]*/ + +static PyObject * +_curses_pair_number_impl(PyObject *module, int attr) +/*[clinic end generated code: output=85bce7d65c0aa3f4 input=d478548e33f5e61a]*/ +{ + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); + + return PyLong_FromLong(PAIR_NUMBER(attr)); +} + +/*[clinic input] +_curses.putp + + string: str(accept={robuffer}) + / + +Emit the value of a specified terminfo capability for the current terminal. + +Note that the output of putp() always goes to standard output. +[clinic start generated code]*/ + +static PyObject * +_curses_putp_impl(PyObject *module, const char *string) +/*[clinic end generated code: output=e98081d1b8eb5816 input=1601faa828b44cb3]*/ +{ + return curses_check_err(module, putp(string), "putp", NULL); +} + +/*[clinic input] +_curses.qiflush + + flag: bool = True + If false, the effect is the same as calling noqiflush(). + / + +Enable queue flushing. + +If queue flushing is enabled, all output in the display driver queue +will be flushed when the INTR, QUIT and SUSP characters are read. +[clinic start generated code]*/ + +static PyObject * +_curses_qiflush_impl(PyObject *module, int flag) +/*[clinic end generated code: output=9167e862f760ea30 input=6ec8b3e2b717ec40]*/ +{ + PyCursesStatefulInitialised(module); + + if (flag) { + qiflush(); + } + else { + noqiflush(); + } + Py_RETURN_NONE; +} + +#if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM) +/* Internal helper used for updating curses.LINES, curses.COLS, _curses.LINES + * and _curses.COLS. Returns 1 on success and 0 on failure. */ +static int +update_lines_cols(PyObject *private_module) +{ + PyObject *exposed_module = NULL, *o = NULL; + + exposed_module = PyImport_ImportModule("curses"); + if (exposed_module == NULL) { + goto error; + } + PyObject *exposed_module_dict = PyModule_GetDict(exposed_module); // borrowed + if (exposed_module_dict == NULL) { + goto error; + } + PyObject *private_module_dict = PyModule_GetDict(private_module); // borrowed + if (private_module_dict == NULL) { + goto error; + } + + o = PyLong_FromLong(LINES); + if (o == NULL) { + goto error; + } + if (PyDict_SetItemString(exposed_module_dict, "LINES", o) < 0) { + goto error; + } + if (PyDict_SetItemString(private_module_dict, "LINES", o) < 0) { + goto error; + } + Py_DECREF(o); + + o = PyLong_FromLong(COLS); + if (o == NULL) { + goto error; + } + if (PyDict_SetItemString(exposed_module_dict, "COLS", o) < 0) { + goto error; + } + if (PyDict_SetItemString(private_module_dict, "COLS", o) < 0) { + goto error; + } + Py_DECREF(o); + Py_DECREF(exposed_module); + return 1; + +error: + Py_XDECREF(o); + Py_XDECREF(exposed_module); + return 0; +} + +/*[clinic input] +_curses.update_lines_cols + +[clinic start generated code]*/ + +static PyObject * +_curses_update_lines_cols_impl(PyObject *module) +/*[clinic end generated code: output=423f2b1e63ed0f75 input=5f065ab7a28a5d90]*/ +{ + if (!update_lines_cols(module)) { + return NULL; + } + Py_RETURN_NONE; +} + +#endif + +/*[clinic input] +_curses.raw + + flag: bool = True + If false, the effect is the same as calling noraw(). + / + +Enter raw mode. + +In raw mode, normal line buffering and processing of interrupt, quit, +suspend, and flow control keys are turned off; characters are presented to +curses input functions one by one. +[clinic start generated code]*/ + +static PyObject * +_curses_raw_impl(PyObject *module, int flag) +/*[clinic end generated code: output=a750e4b342be015b input=4b447701389fb4df]*/ +NoArgOrFlagNoReturnFunctionBody(raw, flag) + +/*[clinic input] +@permit_long_summary +_curses.reset_prog_mode + +Restore the terminal to "program" mode, as previously saved by def_prog_mode(). +[clinic start generated code]*/ + +static PyObject * +_curses_reset_prog_mode_impl(PyObject *module) +/*[clinic end generated code: output=15eb765abf0b6575 input=a8b44b5261c8cf3a]*/ +NoArgNoReturnFunctionBody(reset_prog_mode) + +/*[clinic input] +@permit_long_summary +_curses.reset_shell_mode + +Restore the terminal to "shell" mode, as previously saved by def_shell_mode(). +[clinic start generated code]*/ + +static PyObject * +_curses_reset_shell_mode_impl(PyObject *module) +/*[clinic end generated code: output=0238de2962090d33 input=f5224034a2c95931]*/ +NoArgNoReturnFunctionBody(reset_shell_mode) + +/*[clinic input] +_curses.resetty + +Restore terminal mode. +[clinic start generated code]*/ + +static PyObject * +_curses_resetty_impl(PyObject *module) +/*[clinic end generated code: output=ff4b448e80a7cd63 input=940493de03624bb0]*/ +NoArgNoReturnFunctionBody(resetty) + +#ifdef HAVE_CURSES_RESIZETERM +/*[clinic input] +_curses.resizeterm + + nlines: short + Height. + ncols: short + Width. + / + +Resize the standard and current windows to the specified dimensions. + +Adjusts other bookkeeping data used by the curses library that record the +window dimensions (in particular the SIGWINCH handler). +[clinic start generated code]*/ + +static PyObject * +_curses_resizeterm_impl(PyObject *module, short nlines, short ncols) +/*[clinic end generated code: output=4de3abab50c67f02 input=414e92a63e3e9899]*/ +{ + PyObject *result; + int code; + + PyCursesStatefulInitialised(module); + + code = resizeterm(nlines, ncols); + result = curses_check_err(module, code, "resizeterm", NULL); + if (!result) + return NULL; + if (!update_lines_cols(module)) { + Py_DECREF(result); + return NULL; + } + return result; +} + +#endif + +#ifdef HAVE_CURSES_RESIZE_TERM +/*[clinic input] +@permit_long_docstring_body +_curses.resize_term + + nlines: short + Height. + ncols: short + Width. + / + +Backend function used by resizeterm(), performing most of the work. + +When resizing the windows, resize_term() blank-fills the areas that are +extended. The calling application should fill in these areas with appropriate +data. The resize_term() function attempts to resize all windows. However, +due to the calling convention of pads, it is not possible to resize these +without additional interaction with the application. +[clinic start generated code]*/ + +static PyObject * +_curses_resize_term_impl(PyObject *module, short nlines, short ncols) +/*[clinic end generated code: output=46c6d749fa291dbd input=ebfa840f6b5f03fa]*/ +{ + PyObject *result; + int code; + + PyCursesStatefulInitialised(module); + + code = resize_term(nlines, ncols); + result = curses_check_err(module, code, "resize_term", NULL); + if (!result) + return NULL; + if (!update_lines_cols(module)) { + Py_DECREF(result); + return NULL; + } + return result; +} +#endif /* HAVE_CURSES_RESIZE_TERM */ + +/*[clinic input] +_curses.savetty + +Save terminal mode. +[clinic start generated code]*/ + +static PyObject * +_curses_savetty_impl(PyObject *module) +/*[clinic end generated code: output=6babc49f12b42199 input=fce6b2b7d2200102]*/ +NoArgNoReturnFunctionBody(savetty) + +#ifdef getsyx +/*[clinic input] +_curses.setsyx + + y: int + Y-coordinate. + x: int + X-coordinate. + / + +Set the virtual screen cursor. + +If y and x are both -1, then leaveok is set. +[clinic start generated code]*/ + +static PyObject * +_curses_setsyx_impl(PyObject *module, int y, int x) +/*[clinic end generated code: output=23dcf753511a2464 input=fa7f2b208e10a557]*/ +{ + PyCursesStatefulInitialised(module); + + setsyx(y,x); + + Py_RETURN_NONE; +} +#endif + +/*[clinic input] +_curses.start_color + +Initializes eight basic colors and global variables COLORS and COLOR_PAIRS. + +Must be called if the programmer wants to use colors, and before any other +color manipulation routine is called. It is good practice to call this +routine right after initscr(). + +It also restores the colors on the terminal to the values they had when the +terminal was just turned on. +[clinic start generated code]*/ + +static PyObject * +_curses_start_color_impl(PyObject *module) +/*[clinic end generated code: output=8b772b41d8090ede input=0ca0ecb2b77e1a12]*/ +{ + PyCursesStatefulInitialised(module); + + if (start_color() == ERR) { + curses_set_error(module, "start_color", NULL); + return NULL; + } + + curses_start_color_called = TRUE; + + PyObject *module_dict = PyModule_GetDict(module); // borrowed + if (module_dict == NULL) { + return NULL; + } +#define DICT_ADD_INT_VALUE(NAME, VALUE) \ + do { \ + PyObject *value = PyLong_FromLong((long)(VALUE)); \ + if (value == NULL) { \ + return NULL; \ + } \ + int rc = PyDict_SetItemString(module_dict, (NAME), value); \ + Py_DECREF(value); \ + if (rc < 0) { \ + return NULL; \ + } \ + } while (0) + + DICT_ADD_INT_VALUE("COLORS", COLORS); + DICT_ADD_INT_VALUE("COLOR_PAIRS", COLOR_PAIRS); +#undef DICT_ADD_INT_VALUE + + Py_RETURN_NONE; +} + +/*[clinic input] +_curses.termattrs + +Return a logical OR of all video attributes supported by the terminal. +[clinic start generated code]*/ + +static PyObject * +_curses_termattrs_impl(PyObject *module) +/*[clinic end generated code: output=b06f437fce1b6fc4 input=0559882a04f84d1d]*/ +NoArgReturnIntFunctionBody(termattrs) + +/*[clinic input] +@permit_long_summary +_curses.termname + +Return the value of the environment variable TERM, truncated to 14 characters. +[clinic start generated code]*/ + +static PyObject * +_curses_termname_impl(PyObject *module) +/*[clinic end generated code: output=96375577ebbd67fd input=c34f724d8ce8fc4e]*/ +NoArgReturnStringFunctionBody(termname) + +/*[clinic input] +_curses.tigetflag + + capname: str + The terminfo capability name. + / + +Return the value of the Boolean capability. + +The value -1 is returned if capname is not a Boolean capability, or 0 if +it is canceled or absent from the terminal description. +[clinic start generated code]*/ + +static PyObject * +_curses_tigetflag_impl(PyObject *module, const char *capname) +/*[clinic end generated code: output=8853c0e55542195b input=b0787af9e3e9a6ce]*/ +{ + PyCursesStatefulSetupTermCalled(module); + + return PyLong_FromLong( (long) tigetflag( (char *)capname ) ); +} + +/*[clinic input] +_curses.tigetnum + + capname: str + The terminfo capability name. + / + +Return the value of the numeric capability. + +The value -2 is returned if capname is not a numeric capability, or -1 if +it is canceled or absent from the terminal description. +[clinic start generated code]*/ + +static PyObject * +_curses_tigetnum_impl(PyObject *module, const char *capname) +/*[clinic end generated code: output=46f8b0a1b5dff42f input=5cdf2f410b109720]*/ +{ + PyCursesStatefulSetupTermCalled(module); + + return PyLong_FromLong( (long) tigetnum( (char *)capname ) ); +} + +/*[clinic input] +_curses.tigetstr + + capname: str + The terminfo capability name. + / + +Return the value of the string capability. + +None is returned if capname is not a string capability, or is canceled or +absent from the terminal description. +[clinic start generated code]*/ + +static PyObject * +_curses_tigetstr_impl(PyObject *module, const char *capname) +/*[clinic end generated code: output=f22b576ad60248f3 input=36644df25c73c0a7]*/ +{ + PyCursesStatefulSetupTermCalled(module); + + capname = tigetstr( (char *)capname ); + if (capname == NULL || capname == (char*) -1) { + Py_RETURN_NONE; + } + return PyBytes_FromString( capname ); +} + +/*[clinic input] +_curses.tparm + + str: str(accept={robuffer}) + Parameterized byte string obtained from the terminfo database. + i1: int = 0 + i2: int = 0 + i3: int = 0 + i4: int = 0 + i5: int = 0 + i6: int = 0 + i7: int = 0 + i8: int = 0 + i9: int = 0 + / + +Instantiate the specified byte string with the supplied parameters. +[clinic start generated code]*/ + +static PyObject * +_curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, + int i4, int i5, int i6, int i7, int i8, int i9) +/*[clinic end generated code: output=599f62b615c667ff input=5e30b15786f032aa]*/ +{ + char* result = NULL; + + PyCursesStatefulSetupTermCalled(module); + + result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9); + if (!result) { + curses_set_null_error(module, "tparm", NULL); + return NULL; + } + + return PyBytes_FromString(result); +} + +#ifdef HAVE_CURSES_TYPEAHEAD +/*[clinic input] +_curses.typeahead + + fd: int + File descriptor. + / + +Specify that the file descriptor fd be used for typeahead checking. + +If fd is -1, then no typeahead checking is done. +[clinic start generated code]*/ + +static PyObject * +_curses_typeahead_impl(PyObject *module, int fd) +/*[clinic end generated code: output=084bb649d7066583 input=f2968d8e1805051b]*/ +{ + PyCursesStatefulInitialised(module); + + return curses_check_err(module, typeahead(fd), "typeahead", NULL); +} +#endif + +/*[clinic input] +_curses.unctrl + + ch: object + / + +Return a string which is a printable representation of the character ch. + +Control characters are displayed as a caret followed by the character, +for example as ^C. Printing characters are left as they are. +[clinic start generated code]*/ + +static PyObject * +_curses_unctrl(PyObject *module, PyObject *ch) +/*[clinic end generated code: output=8e07fafc430c9434 input=cd1e35e16cd1ace4]*/ +{ + chtype ch_; + + PyCursesStatefulInitialised(module); + + if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) + return NULL; + + const char *res = unctrl(ch_); + if (res == NULL) { + curses_set_null_error(module, "unctrl", NULL); + return NULL; + } + return PyBytes_FromString(res); +} + +/*[clinic input] +_curses.ungetch + + ch: object + / + +Push ch so the next getch() will return it. +[clinic start generated code]*/ + +static PyObject * +_curses_ungetch(PyObject *module, PyObject *ch) +/*[clinic end generated code: output=9b19d8268376d887 input=6681e6ae4c42e5eb]*/ +{ + chtype ch_; + + PyCursesStatefulInitialised(module); + + if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) + return NULL; + + return curses_check_err(module, ungetch(ch_), "ungetch", NULL); +} + +#ifdef HAVE_NCURSESW +/* Convert an object to a character (wchar_t): + + - int + - str of length 1 + + Return 1 on success, 0 on error. */ +static int +PyCurses_ConvertToWchar_t(PyObject *obj, + wchar_t *wch) +{ + if (PyUnicode_Check(obj)) { + wchar_t buffer[2]; + if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) { + PyErr_Format(PyExc_TypeError, + "expect int or str of length 1, " + "got a str of length %zi", + PyUnicode_GET_LENGTH(obj)); + return 0; + } + *wch = buffer[0]; + return 2; + } + else if (PyLong_CheckExact(obj)) { + long value; + int overflow; + value = PyLong_AsLongAndOverflow(obj, &overflow); + if (overflow) { + PyErr_SetString(PyExc_OverflowError, + "int doesn't fit in long"); + return 0; + } + *wch = (wchar_t)value; + if ((long)*wch != value) { + PyErr_Format(PyExc_OverflowError, + "character doesn't fit in wchar_t"); + return 0; + } + return 1; + } + else { + PyErr_Format(PyExc_TypeError, + "expect int or str of length 1, got %s", + Py_TYPE(obj)->tp_name); + return 0; + } +} + +/*[clinic input] +_curses.unget_wch + + ch: object + / + +Push ch so the next get_wch() will return it. +[clinic start generated code]*/ + +static PyObject * +_curses_unget_wch(PyObject *module, PyObject *ch) +/*[clinic end generated code: output=1974c9fb01d37863 input=0d56dc65a46feebb]*/ +{ + wchar_t wch; + + PyCursesStatefulInitialised(module); + + if (!PyCurses_ConvertToWchar_t(ch, &wch)) + return NULL; + return curses_check_err(module, unget_wch(wch), "unget_wch", NULL); +} +#endif + +#ifdef HAVE_CURSES_USE_ENV +/*[clinic input] +@permit_long_docstring_body +_curses.use_env + + flag: bool + / + +Use environment variables LINES and COLUMNS. + +If used, this function should be called before initscr() or newterm() are +called. + +When flag is False, the values of lines and columns specified in the terminfo +database will be used, even if environment variables LINES and COLUMNS (used +by default) are set, or if curses is running in a window (in which case +default behavior would be to use the window size if LINES and COLUMNS are +not set). +[clinic start generated code]*/ + +static PyObject * +_curses_use_env_impl(PyObject *module, int flag) +/*[clinic end generated code: output=b2c445e435c0b164 input=eaa9047ec73c27d3]*/ +{ + use_env(flag); + Py_RETURN_NONE; +} +#endif + +#ifndef STRICT_SYSV_CURSES +/*[clinic input] +_curses.use_default_colors + +Equivalent to assume_default_colors(-1, -1). +[clinic start generated code]*/ + +static PyObject * +_curses_use_default_colors_impl(PyObject *module) +/*[clinic end generated code: output=a3b81ff71dd901be input=99ff0b7c69834d1f]*/ +{ + int code; + + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); + + code = use_default_colors(); + return curses_check_err(module, code, "use_default_colors", NULL); +} + +/*[clinic input] +_curses.assume_default_colors + fg: int + bg: int + / + +Allow use of default values for colors on terminals supporting this feature. + +Assign terminal default foreground/background colors to color number -1. +Change the definition of the color-pair 0 to (fg, bg). + +Use this to support transparency in your application. +[clinic start generated code]*/ + +static PyObject * +_curses_assume_default_colors_impl(PyObject *module, int fg, int bg) +/*[clinic end generated code: output=54985397a7d2b3a5 input=7fe301712ef3e9fb]*/ +{ + int code; + + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); + + code = assume_default_colors(fg, bg); + return curses_check_err(module, code, "assume_default_colors", NULL); +} +#endif /* STRICT_SYSV_CURSES */ + + +#ifdef NCURSES_VERSION + +PyDoc_STRVAR(ncurses_version__doc__, +"curses.ncurses_version\n\ +\n\ +Ncurses version information as a named tuple."); + +static PyStructSequence_Field ncurses_version_fields[] = { + {"major", "Major release number"}, + {"minor", "Minor release number"}, + {"patch", "Patch release number"}, + {0} +}; + +static PyStructSequence_Desc ncurses_version_desc = { + "curses.ncurses_version", /* name */ + ncurses_version__doc__, /* doc */ + ncurses_version_fields, /* fields */ + 3 +}; + +static PyObject * +make_ncurses_version(PyTypeObject *type) +{ + PyObject *ncurses_version = PyStructSequence_New(type); + if (ncurses_version == NULL) { + return NULL; + } + const char *str = curses_version(); + unsigned long major = 0, minor = 0, patch = 0; + if (!str || sscanf(str, "%*[^0-9]%lu.%lu.%lu", &major, &minor, &patch) < 3) { + // Fallback to header version, which cannot be that wrong + major = NCURSES_VERSION_MAJOR; + minor = NCURSES_VERSION_MINOR; + patch = NCURSES_VERSION_PATCH; + } +#define SET_VERSION_COMPONENT(INDEX, VALUE) \ + do { \ + PyObject *o = PyLong_FromLong(VALUE); \ + if (o == NULL) { \ + Py_DECREF(ncurses_version); \ + return NULL; \ + } \ + PyStructSequence_SET_ITEM(ncurses_version, INDEX, o); \ + } while (0) + + SET_VERSION_COMPONENT(0, major); + SET_VERSION_COMPONENT(1, minor); + SET_VERSION_COMPONENT(2, patch); +#undef SET_VERSION_COMPONENT + return ncurses_version; +} + +#endif /* NCURSES_VERSION */ + +/*[clinic input] +_curses.has_extended_color_support + +Return True if the module supports extended colors; otherwise, return False. + +Extended color support allows more than 256 color-pairs for terminals +that support more than 16 colors (e.g. xterm-256color). +[clinic start generated code]*/ + +static PyObject * +_curses_has_extended_color_support_impl(PyObject *module) +/*[clinic end generated code: output=68f1be2b57d92e22 input=4b905f046e35ee9f]*/ +{ + return PyBool_FromLong(_NCURSES_EXTENDED_COLOR_FUNCS); +} + +/* List of functions defined in the module */ + +static PyMethodDef cursesmodule_methods[] = { + _CURSES_BAUDRATE_METHODDEF + _CURSES_BEEP_METHODDEF + _CURSES_CAN_CHANGE_COLOR_METHODDEF + _CURSES_CBREAK_METHODDEF + _CURSES_COLOR_CONTENT_METHODDEF + _CURSES_COLOR_PAIR_METHODDEF + _CURSES_CURS_SET_METHODDEF + _CURSES_DEF_PROG_MODE_METHODDEF + _CURSES_DEF_SHELL_MODE_METHODDEF + _CURSES_DELAY_OUTPUT_METHODDEF + _CURSES_DOUPDATE_METHODDEF + _CURSES_ECHO_METHODDEF + _CURSES_ENDWIN_METHODDEF + _CURSES_ERASECHAR_METHODDEF + _CURSES_FILTER_METHODDEF + _CURSES_FLASH_METHODDEF + _CURSES_FLUSHINP_METHODDEF + _CURSES_GETMOUSE_METHODDEF + _CURSES_UNGETMOUSE_METHODDEF + _CURSES_GETSYX_METHODDEF + _CURSES_GETWIN_METHODDEF + _CURSES_HAS_COLORS_METHODDEF + _CURSES_HAS_EXTENDED_COLOR_SUPPORT_METHODDEF + _CURSES_HAS_IC_METHODDEF + _CURSES_HAS_IL_METHODDEF + _CURSES_HAS_KEY_METHODDEF + _CURSES_HALFDELAY_METHODDEF + _CURSES_INIT_COLOR_METHODDEF + _CURSES_INIT_PAIR_METHODDEF + _CURSES_INITSCR_METHODDEF + _CURSES_INTRFLUSH_METHODDEF + _CURSES_ISENDWIN_METHODDEF + _CURSES_IS_TERM_RESIZED_METHODDEF + _CURSES_KEYNAME_METHODDEF + _CURSES_KILLCHAR_METHODDEF + _CURSES_LONGNAME_METHODDEF + _CURSES_META_METHODDEF + _CURSES_MOUSEINTERVAL_METHODDEF + _CURSES_MOUSEMASK_METHODDEF + _CURSES_NAPMS_METHODDEF + _CURSES_NEWPAD_METHODDEF + _CURSES_NEWWIN_METHODDEF + _CURSES_NL_METHODDEF + _CURSES_NOCBREAK_METHODDEF + _CURSES_NOECHO_METHODDEF + _CURSES_NONL_METHODDEF + _CURSES_NOQIFLUSH_METHODDEF + _CURSES_NORAW_METHODDEF + _CURSES_PAIR_CONTENT_METHODDEF + _CURSES_PAIR_NUMBER_METHODDEF + _CURSES_PUTP_METHODDEF + _CURSES_QIFLUSH_METHODDEF + _CURSES_RAW_METHODDEF + _CURSES_RESET_PROG_MODE_METHODDEF + _CURSES_RESET_SHELL_MODE_METHODDEF + _CURSES_RESETTY_METHODDEF + _CURSES_RESIZETERM_METHODDEF + _CURSES_RESIZE_TERM_METHODDEF + _CURSES_SAVETTY_METHODDEF +#if defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102 + _CURSES_GET_ESCDELAY_METHODDEF + _CURSES_SET_ESCDELAY_METHODDEF +#endif + _CURSES_GET_TABSIZE_METHODDEF + _CURSES_SET_TABSIZE_METHODDEF + _CURSES_SETSYX_METHODDEF + _CURSES_SETUPTERM_METHODDEF + _CURSES_START_COLOR_METHODDEF + _CURSES_TERMATTRS_METHODDEF + _CURSES_TERMNAME_METHODDEF + _CURSES_TIGETFLAG_METHODDEF + _CURSES_TIGETNUM_METHODDEF + _CURSES_TIGETSTR_METHODDEF + _CURSES_TPARM_METHODDEF + _CURSES_TYPEAHEAD_METHODDEF + _CURSES_UNCTRL_METHODDEF + _CURSES_UNGETCH_METHODDEF + _CURSES_UPDATE_LINES_COLS_METHODDEF + _CURSES_UNGET_WCH_METHODDEF + _CURSES_USE_ENV_METHODDEF + _CURSES_USE_DEFAULT_COLORS_METHODDEF + _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF + {NULL, NULL} /* sentinel */ +}; + +/* Module C API */ + +/* Function versions of the 3 functions for testing whether curses has been + initialised or not. */ + +static inline int +curses_capi_setupterm_called(void) +{ + return _PyCursesCheckFunction(curses_setupterm_called, "setupterm"); +} + +static inline int +curses_capi_initscr_called(void) +{ + return _PyCursesCheckFunction(curses_initscr_called, "initscr"); +} + +static inline int +curses_capi_start_color_called(void) +{ + return _PyCursesCheckFunction(curses_start_color_called, "start_color"); +} + +static void * +curses_capi_new(cursesmodule_state *state) +{ + assert(state->window_type != NULL); + void **capi = (void **)PyMem_Calloc(PyCurses_API_pointers, sizeof(void *)); + if (capi == NULL) { + PyErr_NoMemory(); + return NULL; + } + capi[0] = (void *)Py_NewRef(state->window_type); + capi[1] = curses_capi_setupterm_called; + capi[2] = curses_capi_initscr_called; + capi[3] = curses_capi_start_color_called; + return (void *)capi; +} + +static void +curses_capi_free(void *capi) +{ + assert(capi != NULL); + void **capi_ptr = (void **)capi; + // In free-threaded builds, capi_ptr[0] may have been already cleared + // by curses_capi_capsule_destructor(), hence the use of Py_XDECREF(). + Py_XDECREF(capi_ptr[0]); // decref curses window type + PyMem_Free(capi_ptr); +} + +/* Module C API Capsule */ + +static void +curses_capi_capsule_destructor(PyObject *op) +{ + void *capi = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME); + curses_capi_free(capi); +} + +static int +curses_capi_capsule_traverse(PyObject *op, visitproc visit, void *arg) +{ + void **capi_ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME); + assert(capi_ptr != NULL); + Py_VISIT(capi_ptr[0]); // visit curses window type + return 0; +} + +static int +curses_capi_capsule_clear(PyObject *op) +{ + void **capi_ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME); + assert(capi_ptr != NULL); + Py_CLEAR(capi_ptr[0]); // clear curses window type + return 0; +} + +static PyObject * +curses_capi_capsule_new(void *capi) +{ + PyObject *capsule = PyCapsule_New(capi, PyCurses_CAPSULE_NAME, + curses_capi_capsule_destructor); + if (capsule == NULL) { + return NULL; + } + if (_PyCapsule_SetTraverse(capsule, + curses_capi_capsule_traverse, + curses_capi_capsule_clear) < 0) + { + Py_DECREF(capsule); + return NULL; + } + return capsule; +} + +/* Module initialization and cleanup functions */ + +static int +cursesmodule_traverse(PyObject *mod, visitproc visit, void *arg) +{ + cursesmodule_state *state = get_cursesmodule_state(mod); + Py_VISIT(state->error); + Py_VISIT(state->window_type); + return 0; +} + +static int +cursesmodule_clear(PyObject *mod) +{ + cursesmodule_state *state = get_cursesmodule_state(mod); + Py_CLEAR(state->error); + Py_CLEAR(state->window_type); + return 0; +} + +static void +cursesmodule_free(void *mod) +{ + (void)cursesmodule_clear((PyObject *)mod); + curses_module_loaded = 0; // allow reloading once garbage-collected +} + +static int +cursesmodule_exec(PyObject *module) +{ + if (curses_module_loaded) { + PyErr_SetString(PyExc_ImportError, + "module 'curses' can only be loaded once per process"); + return -1; + } + curses_module_loaded = 1; + + cursesmodule_state *state = get_cursesmodule_state(module); + /* Initialize object type */ + state->window_type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &PyCursesWindow_Type_spec, NULL); + if (state->window_type == NULL) { + return -1; + } + if (PyModule_AddType(module, state->window_type) < 0) { + return -1; + } + + /* Add some symbolic constants to the module */ + PyObject *module_dict = PyModule_GetDict(module); + if (module_dict == NULL) { + return -1; + } + + /* Create the C API object */ + void *capi = curses_capi_new(state); + if (capi == NULL) { + return -1; + } + /* Add a capsule for the C API */ + PyObject *capi_capsule = curses_capi_capsule_new(capi); + if (capi_capsule == NULL) { + curses_capi_free(capi); + return -1; + } + int rc = PyDict_SetItemString(module_dict, "_C_API", capi_capsule); + Py_DECREF(capi_capsule); + if (rc < 0) { + return -1; + } + + /* For exception curses.error */ + state->error = PyErr_NewException("_curses.error", NULL, NULL); + if (state->error == NULL) { + return -1; + } + rc = PyDict_SetItemString(module_dict, "error", state->error); + if (rc < 0) { + return -1; + } + + /* Make the version available */ + PyObject *curses_version = PyBytes_FromString(PyCursesVersion); + if (curses_version == NULL) { + return -1; + } + rc = PyDict_SetItemString(module_dict, "version", curses_version); + if (rc < 0) { + Py_DECREF(curses_version); + return -1; + } + rc = PyDict_SetItemString(module_dict, "__version__", curses_version); + Py_CLEAR(curses_version); + if (rc < 0) { + return -1; + } + +#ifdef NCURSES_VERSION + /* ncurses_version */ + PyTypeObject *version_type; + version_type = _PyStructSequence_NewType(&ncurses_version_desc, + Py_TPFLAGS_DISALLOW_INSTANTIATION); + if (version_type == NULL) { + return -1; + } + PyObject *ncurses_version = make_ncurses_version(version_type); + Py_DECREF(version_type); + if (ncurses_version == NULL) { + return -1; + } + rc = PyDict_SetItemString(module_dict, "ncurses_version", ncurses_version); + Py_CLEAR(ncurses_version); + if (rc < 0) { + return -1; + } +#endif /* NCURSES_VERSION */ + +#define SetDictInt(NAME, VALUE) \ + do { \ + PyObject *value = PyLong_FromLong((long)(VALUE)); \ + if (value == NULL) { \ + return -1; \ + } \ + int rc = PyDict_SetItemString(module_dict, (NAME), value); \ + Py_DECREF(value); \ + if (rc < 0) { \ + return -1; \ + } \ + } while (0) + + SetDictInt("ERR", ERR); + SetDictInt("OK", OK); + + /* Here are some attributes you can add to chars to print */ + + SetDictInt("A_ATTRIBUTES", A_ATTRIBUTES); + SetDictInt("A_NORMAL", A_NORMAL); + SetDictInt("A_STANDOUT", A_STANDOUT); + SetDictInt("A_UNDERLINE", A_UNDERLINE); + SetDictInt("A_REVERSE", A_REVERSE); + SetDictInt("A_BLINK", A_BLINK); + SetDictInt("A_DIM", A_DIM); + SetDictInt("A_BOLD", A_BOLD); + SetDictInt("A_ALTCHARSET", A_ALTCHARSET); + SetDictInt("A_INVIS", A_INVIS); + SetDictInt("A_PROTECT", A_PROTECT); + SetDictInt("A_CHARTEXT", A_CHARTEXT); + SetDictInt("A_COLOR", A_COLOR); + + /* The following are never available with strict SYSV curses */ +#ifdef A_HORIZONTAL + SetDictInt("A_HORIZONTAL", A_HORIZONTAL); +#endif +#ifdef A_LEFT + SetDictInt("A_LEFT", A_LEFT); +#endif +#ifdef A_LOW + SetDictInt("A_LOW", A_LOW); +#endif +#ifdef A_RIGHT + SetDictInt("A_RIGHT", A_RIGHT); +#endif +#ifdef A_TOP + SetDictInt("A_TOP", A_TOP); +#endif +#ifdef A_VERTICAL + SetDictInt("A_VERTICAL", A_VERTICAL); +#endif + + /* ncurses extension */ +#ifdef A_ITALIC + SetDictInt("A_ITALIC", A_ITALIC); +#endif + + SetDictInt("COLOR_BLACK", COLOR_BLACK); + SetDictInt("COLOR_RED", COLOR_RED); + SetDictInt("COLOR_GREEN", COLOR_GREEN); + SetDictInt("COLOR_YELLOW", COLOR_YELLOW); + SetDictInt("COLOR_BLUE", COLOR_BLUE); + SetDictInt("COLOR_MAGENTA", COLOR_MAGENTA); + SetDictInt("COLOR_CYAN", COLOR_CYAN); + SetDictInt("COLOR_WHITE", COLOR_WHITE); + +#ifdef NCURSES_MOUSE_VERSION + /* Mouse-related constants */ + SetDictInt("BUTTON1_PRESSED", BUTTON1_PRESSED); + SetDictInt("BUTTON1_RELEASED", BUTTON1_RELEASED); + SetDictInt("BUTTON1_CLICKED", BUTTON1_CLICKED); + SetDictInt("BUTTON1_DOUBLE_CLICKED", BUTTON1_DOUBLE_CLICKED); + SetDictInt("BUTTON1_TRIPLE_CLICKED", BUTTON1_TRIPLE_CLICKED); + + SetDictInt("BUTTON2_PRESSED", BUTTON2_PRESSED); + SetDictInt("BUTTON2_RELEASED", BUTTON2_RELEASED); + SetDictInt("BUTTON2_CLICKED", BUTTON2_CLICKED); + SetDictInt("BUTTON2_DOUBLE_CLICKED", BUTTON2_DOUBLE_CLICKED); + SetDictInt("BUTTON2_TRIPLE_CLICKED", BUTTON2_TRIPLE_CLICKED); + + SetDictInt("BUTTON3_PRESSED", BUTTON3_PRESSED); + SetDictInt("BUTTON3_RELEASED", BUTTON3_RELEASED); + SetDictInt("BUTTON3_CLICKED", BUTTON3_CLICKED); + SetDictInt("BUTTON3_DOUBLE_CLICKED", BUTTON3_DOUBLE_CLICKED); + SetDictInt("BUTTON3_TRIPLE_CLICKED", BUTTON3_TRIPLE_CLICKED); + + SetDictInt("BUTTON4_PRESSED", BUTTON4_PRESSED); + SetDictInt("BUTTON4_RELEASED", BUTTON4_RELEASED); + SetDictInt("BUTTON4_CLICKED", BUTTON4_CLICKED); + SetDictInt("BUTTON4_DOUBLE_CLICKED", BUTTON4_DOUBLE_CLICKED); + SetDictInt("BUTTON4_TRIPLE_CLICKED", BUTTON4_TRIPLE_CLICKED); + +#if NCURSES_MOUSE_VERSION > 1 + SetDictInt("BUTTON5_PRESSED", BUTTON5_PRESSED); + SetDictInt("BUTTON5_RELEASED", BUTTON5_RELEASED); + SetDictInt("BUTTON5_CLICKED", BUTTON5_CLICKED); + SetDictInt("BUTTON5_DOUBLE_CLICKED", BUTTON5_DOUBLE_CLICKED); + SetDictInt("BUTTON5_TRIPLE_CLICKED", BUTTON5_TRIPLE_CLICKED); +#endif + + SetDictInt("BUTTON_SHIFT", BUTTON_SHIFT); + SetDictInt("BUTTON_CTRL", BUTTON_CTRL); + SetDictInt("BUTTON_ALT", BUTTON_ALT); + + SetDictInt("ALL_MOUSE_EVENTS", ALL_MOUSE_EVENTS); + SetDictInt("REPORT_MOUSE_POSITION", REPORT_MOUSE_POSITION); +#endif + /* Now set everything up for KEY_ variables */ + for (int keycode = KEY_MIN; keycode < KEY_MAX; keycode++) { + const char *key_name = keyname(keycode); + if (key_name == NULL || strcmp(key_name, "UNKNOWN KEY") == 0) { + continue; + } + if (strncmp(key_name, "KEY_F(", 6) == 0) { + char *fn_key_name = PyMem_Malloc(strlen(key_name) + 1); + if (!fn_key_name) { + PyErr_NoMemory(); + return -1; + } + const char *p1 = key_name; + char *p2 = fn_key_name; + while (*p1) { + if (*p1 != '(' && *p1 != ')') { + *p2 = *p1; + p2++; + } + p1++; + } + *p2 = (char)0; + PyObject *p_keycode = PyLong_FromLong((long)keycode); + if (p_keycode == NULL) { + PyMem_Free(fn_key_name); + return -1; + } + int rc = PyDict_SetItemString(module_dict, fn_key_name, p_keycode); + Py_DECREF(p_keycode); + PyMem_Free(fn_key_name); + if (rc < 0) { + return -1; + } + } + else { + SetDictInt(key_name, keycode); + } + } + SetDictInt("KEY_MIN", KEY_MIN); + SetDictInt("KEY_MAX", KEY_MAX); +#undef SetDictInt + return 0; +} + +/* Initialization function for the module */ + +static PyModuleDef_Slot cursesmodule_slots[] = { + {Py_mod_exec, cursesmodule_exec}, + {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, + {0, NULL} +}; + +static struct PyModuleDef cursesmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_curses", + .m_size = sizeof(cursesmodule_state), + .m_methods = cursesmodule_methods, + .m_slots = cursesmodule_slots, + .m_traverse = cursesmodule_traverse, + .m_clear = cursesmodule_clear, + .m_free = cursesmodule_free +}; + +PyMODINIT_FUNC +PyInit__curses(void) +{ + return PyModuleDef_Init(&cursesmodule); +} From 347cc425d9f06495885bc782c39240cc27d8a8d6 Mon Sep 17 00:00:00 2001 From: Imre Eilertsen Date: Mon, 1 Dec 2025 17:18:02 +0100 Subject: [PATCH 2/6] Applied the patches. --- py314/_cursesmodule.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/py314/_cursesmodule.c b/py314/_cursesmodule.c index 6146434..711753e 100644 --- a/py314/_cursesmodule.c +++ b/py314/_cursesmodule.c @@ -114,6 +114,10 @@ static const char PyCursesVersion[] = "2.2"; #define STRICT_SYSV_CURSES #endif +#ifdef _WIN32 +#include +#endif + #define CURSES_MODULE #include "py_curses.h" @@ -1757,6 +1761,12 @@ _curses_window_getch_impl(PyCursesWindowObject *self, int group_right_1, else { rtn = mvwgetch(self->win, y, x); } + + // windows-curses hack to make resizing work the same as in ncurses. See + // PDCurses' documentation for resize_term(). + if (rtn == KEY_RESIZE) + resize_term(0, 0); + Py_END_ALLOW_THREADS if (rtn == ERR) { @@ -1805,6 +1815,12 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, else { rtn = mvwgetch(self->win, y, x); } + + // windows-curses hack to make resizing work the same as in ncurses. See + // PDCurses' documentation for resize_term(). + if (rtn == KEY_RESIZE) + resize_term(0, 0); + Py_END_ALLOW_THREADS if (rtn == ERR) { @@ -3857,7 +3873,9 @@ static PyObject * _curses_setupterm_impl(PyObject *module, const char *term, int fd) /*[clinic end generated code: output=4584e587350f2848 input=4511472766af0c12]*/ { +#ifndef _WIN32 int err; +#endif if (fd == -1) { PyObject* sys_stdout; @@ -4031,7 +4049,7 @@ _curses_is_term_resized_impl(PyObject *module, int nlines, int ncols) { PyCursesStatefulInitialised(module); - return PyBool_FromLong(is_term_resized(nlines, ncols)); + return PyBool_FromLong(is_term_resized()); } #endif /* HAVE_CURSES_IS_TERM_RESIZED */ From 3f0287d775fa3df4f44102e704393266c4866e1f Mon Sep 17 00:00:00 2001 From: Imre Eilertsen Date: Mon, 1 Dec 2025 17:33:18 +0100 Subject: [PATCH 3/6] Add files via upload --- py314/clinic/_curses_panel.c.h | 344 +++ py314/clinic/_cursesmodule.c.h | 4453 ++++++++++++++++++++++++++++++++ 2 files changed, 4797 insertions(+) create mode 100644 py314/clinic/_curses_panel.c.h create mode 100644 py314/clinic/_cursesmodule.c.h diff --git a/py314/clinic/_curses_panel.c.h b/py314/clinic/_curses_panel.c.h new file mode 100644 index 0000000..0f29f6b --- /dev/null +++ b/py314/clinic/_curses_panel.c.h @@ -0,0 +1,344 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#include "pycore_modsupport.h" // _PyArg_CheckPositional() + +PyDoc_STRVAR(_curses_panel_panel_bottom__doc__, +"bottom($self, /)\n" +"--\n" +"\n" +"Push the panel to the bottom of the stack."); + +#define _CURSES_PANEL_PANEL_BOTTOM_METHODDEF \ + {"bottom", (PyCFunction)_curses_panel_panel_bottom, METH_NOARGS, _curses_panel_panel_bottom__doc__}, + +static PyObject * +_curses_panel_panel_bottom_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_bottom(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_bottom_impl((PyCursesPanelObject *)self); +} + +PyDoc_STRVAR(_curses_panel_panel_hide__doc__, +"hide($self, /)\n" +"--\n" +"\n" +"Hide the panel.\n" +"\n" +"This does not delete the object, it just makes the window on screen invisible."); + +#define _CURSES_PANEL_PANEL_HIDE_METHODDEF \ + {"hide", (PyCFunction)_curses_panel_panel_hide, METH_NOARGS, _curses_panel_panel_hide__doc__}, + +static PyObject * +_curses_panel_panel_hide_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_hide(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_hide_impl((PyCursesPanelObject *)self); +} + +PyDoc_STRVAR(_curses_panel_panel_show__doc__, +"show($self, /)\n" +"--\n" +"\n" +"Display the panel (which might have been hidden)."); + +#define _CURSES_PANEL_PANEL_SHOW_METHODDEF \ + {"show", (PyCFunction)_curses_panel_panel_show, METH_NOARGS, _curses_panel_panel_show__doc__}, + +static PyObject * +_curses_panel_panel_show_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_show(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_show_impl((PyCursesPanelObject *)self); +} + +PyDoc_STRVAR(_curses_panel_panel_top__doc__, +"top($self, /)\n" +"--\n" +"\n" +"Push panel to the top of the stack."); + +#define _CURSES_PANEL_PANEL_TOP_METHODDEF \ + {"top", (PyCFunction)_curses_panel_panel_top, METH_NOARGS, _curses_panel_panel_top__doc__}, + +static PyObject * +_curses_panel_panel_top_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_top(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_top_impl((PyCursesPanelObject *)self); +} + +PyDoc_STRVAR(_curses_panel_panel_above__doc__, +"above($self, /)\n" +"--\n" +"\n" +"Return the panel above the current panel."); + +#define _CURSES_PANEL_PANEL_ABOVE_METHODDEF \ + {"above", (PyCFunction)_curses_panel_panel_above, METH_NOARGS, _curses_panel_panel_above__doc__}, + +static PyObject * +_curses_panel_panel_above_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_above(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_above_impl((PyCursesPanelObject *)self); +} + +PyDoc_STRVAR(_curses_panel_panel_below__doc__, +"below($self, /)\n" +"--\n" +"\n" +"Return the panel below the current panel."); + +#define _CURSES_PANEL_PANEL_BELOW_METHODDEF \ + {"below", (PyCFunction)_curses_panel_panel_below, METH_NOARGS, _curses_panel_panel_below__doc__}, + +static PyObject * +_curses_panel_panel_below_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_below(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_below_impl((PyCursesPanelObject *)self); +} + +PyDoc_STRVAR(_curses_panel_panel_hidden__doc__, +"hidden($self, /)\n" +"--\n" +"\n" +"Return True if the panel is hidden (not visible), False otherwise."); + +#define _CURSES_PANEL_PANEL_HIDDEN_METHODDEF \ + {"hidden", (PyCFunction)_curses_panel_panel_hidden, METH_NOARGS, _curses_panel_panel_hidden__doc__}, + +static PyObject * +_curses_panel_panel_hidden_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_hidden(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_hidden_impl((PyCursesPanelObject *)self); +} + +PyDoc_STRVAR(_curses_panel_panel_move__doc__, +"move($self, y, x, /)\n" +"--\n" +"\n" +"Move the panel to the screen coordinates (y, x)."); + +#define _CURSES_PANEL_PANEL_MOVE_METHODDEF \ + {"move", _PyCFunction_CAST(_curses_panel_panel_move), METH_FASTCALL, _curses_panel_panel_move__doc__}, + +static PyObject * +_curses_panel_panel_move_impl(PyCursesPanelObject *self, int y, int x); + +static PyObject * +_curses_panel_panel_move(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int y; + int x; + + if (!_PyArg_CheckPositional("move", nargs, 2, 2)) { + goto exit; + } + y = PyLong_AsInt(args[0]); + if (y == -1 && PyErr_Occurred()) { + goto exit; + } + x = PyLong_AsInt(args[1]); + if (x == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_panel_panel_move_impl((PyCursesPanelObject *)self, y, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_panel_panel_window__doc__, +"window($self, /)\n" +"--\n" +"\n" +"Return the window object associated with the panel."); + +#define _CURSES_PANEL_PANEL_WINDOW_METHODDEF \ + {"window", (PyCFunction)_curses_panel_panel_window, METH_NOARGS, _curses_panel_panel_window__doc__}, + +static PyObject * +_curses_panel_panel_window_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_window(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_window_impl((PyCursesPanelObject *)self); +} + +PyDoc_STRVAR(_curses_panel_panel_replace__doc__, +"replace($self, win, /)\n" +"--\n" +"\n" +"Change the window associated with the panel to the window win."); + +#define _CURSES_PANEL_PANEL_REPLACE_METHODDEF \ + {"replace", (PyCFunction)_curses_panel_panel_replace, METH_O, _curses_panel_panel_replace__doc__}, + +static PyObject * +_curses_panel_panel_replace_impl(PyCursesPanelObject *self, + PyCursesWindowObject *win); + +static PyObject * +_curses_panel_panel_replace(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + PyCursesWindowObject *win; + + if (!PyObject_TypeCheck(arg, &PyCursesWindow_Type)) { + _PyArg_BadArgument("replace", "argument", (&PyCursesWindow_Type)->tp_name, arg); + goto exit; + } + win = (PyCursesWindowObject *)arg; + return_value = _curses_panel_panel_replace_impl((PyCursesPanelObject *)self, win); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_panel_panel_set_userptr__doc__, +"set_userptr($self, obj, /)\n" +"--\n" +"\n" +"Set the panel\'s user pointer to obj."); + +#define _CURSES_PANEL_PANEL_SET_USERPTR_METHODDEF \ + {"set_userptr", (PyCFunction)_curses_panel_panel_set_userptr, METH_O, _curses_panel_panel_set_userptr__doc__}, + +static PyObject * +_curses_panel_panel_set_userptr_impl(PyCursesPanelObject *self, + PyObject *obj); + +static PyObject * +_curses_panel_panel_set_userptr(PyObject *self, PyObject *obj) +{ + PyObject *return_value = NULL; + + return_value = _curses_panel_panel_set_userptr_impl((PyCursesPanelObject *)self, obj); + + return return_value; +} + +PyDoc_STRVAR(_curses_panel_panel_userptr__doc__, +"userptr($self, /)\n" +"--\n" +"\n" +"Return the user pointer for the panel."); + +#define _CURSES_PANEL_PANEL_USERPTR_METHODDEF \ + {"userptr", (PyCFunction)_curses_panel_panel_userptr, METH_NOARGS, _curses_panel_panel_userptr__doc__}, + +static PyObject * +_curses_panel_panel_userptr_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_userptr(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_userptr_impl((PyCursesPanelObject *)self); +} + +PyDoc_STRVAR(_curses_panel_bottom_panel__doc__, +"bottom_panel($module, /)\n" +"--\n" +"\n" +"Return the bottom panel in the panel stack."); + +#define _CURSES_PANEL_BOTTOM_PANEL_METHODDEF \ + {"bottom_panel", (PyCFunction)_curses_panel_bottom_panel, METH_NOARGS, _curses_panel_bottom_panel__doc__}, + +static PyObject * +_curses_panel_bottom_panel_impl(PyObject *module); + +static PyObject * +_curses_panel_bottom_panel(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_bottom_panel_impl(module); +} + +PyDoc_STRVAR(_curses_panel_new_panel__doc__, +"new_panel($module, win, /)\n" +"--\n" +"\n" +"Return a panel object, associating it with the given window win."); + +#define _CURSES_PANEL_NEW_PANEL_METHODDEF \ + {"new_panel", (PyCFunction)_curses_panel_new_panel, METH_O, _curses_panel_new_panel__doc__}, + +static PyObject * +_curses_panel_new_panel_impl(PyObject *module, PyCursesWindowObject *win); + +static PyObject * +_curses_panel_new_panel(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyCursesWindowObject *win; + + if (!PyObject_TypeCheck(arg, &PyCursesWindow_Type)) { + _PyArg_BadArgument("new_panel", "argument", (&PyCursesWindow_Type)->tp_name, arg); + goto exit; + } + win = (PyCursesWindowObject *)arg; + return_value = _curses_panel_new_panel_impl(module, win); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_panel_top_panel__doc__, +"top_panel($module, /)\n" +"--\n" +"\n" +"Return the top panel in the panel stack."); + +#define _CURSES_PANEL_TOP_PANEL_METHODDEF \ + {"top_panel", (PyCFunction)_curses_panel_top_panel, METH_NOARGS, _curses_panel_top_panel__doc__}, + +static PyObject * +_curses_panel_top_panel_impl(PyObject *module); + +static PyObject * +_curses_panel_top_panel(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_top_panel_impl(module); +} + +PyDoc_STRVAR(_curses_panel_update_panels__doc__, +"update_panels($module, /)\n" +"--\n" +"\n" +"Updates the virtual screen after changes in the panel stack.\n" +"\n" +"This does not call curses.doupdate(), so you\'ll have to do this yourself."); + +#define _CURSES_PANEL_UPDATE_PANELS_METHODDEF \ + {"update_panels", (PyCFunction)_curses_panel_update_panels, METH_NOARGS, _curses_panel_update_panels__doc__}, + +static PyObject * +_curses_panel_update_panels_impl(PyObject *module); + +static PyObject * +_curses_panel_update_panels(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_update_panels_impl(module); +} +/*[clinic end generated code: output=db2fe491582784aa input=a9049054013a1b77]*/ diff --git a/py314/clinic/_cursesmodule.c.h b/py314/clinic/_cursesmodule.c.h new file mode 100644 index 0000000..2bc98b2 --- /dev/null +++ b/py314/clinic/_cursesmodule.c.h @@ -0,0 +1,4453 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif +#include "pycore_modsupport.h" // _PyArg_CheckPositional() + +PyDoc_STRVAR(_curses_window_addch__doc__, +"addch([y, x,] ch, [attr=_curses.A_NORMAL])\n" +"Paint the character.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" ch\n" +" Character to add.\n" +" attr\n" +" Attributes for the character.\n" +"\n" +"Paint character ch at (y, x) with attributes attr,\n" +"overwriting any character previously painted at that location.\n" +"By default, the character position and attributes are the\n" +"current settings for the window object."); + +#define _CURSES_WINDOW_ADDCH_METHODDEF \ + {"addch", (PyCFunction)_curses_window_addch, METH_VARARGS, _curses_window_addch__doc__}, + +static PyObject * +_curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int group_right_1, + long attr); + +static PyObject * +_curses_window_addch(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *ch; + int group_right_1 = 0; + long attr = A_NORMAL; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:addch", &ch)) { + goto exit; + } + break; + case 2: + if (!PyArg_ParseTuple(args, "Ol:addch", &ch, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 3: + if (!PyArg_ParseTuple(args, "iiO:addch", &y, &x, &ch)) { + goto exit; + } + group_left_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOl:addch", &y, &x, &ch, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.addch requires 1 to 4 arguments"); + goto exit; + } + return_value = _curses_window_addch_impl((PyCursesWindowObject *)self, group_left_1, y, x, ch, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_addstr__doc__, +"addstr([y, x,] str, [attr])\n" +"Paint the string.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" str\n" +" String to add.\n" +" attr\n" +" Attributes for characters.\n" +"\n" +"Paint the string str at (y, x) with attributes attr,\n" +"overwriting anything previously on the display.\n" +"By default, the character position and attributes are the\n" +"current settings for the window object."); + +#define _CURSES_WINDOW_ADDSTR_METHODDEF \ + {"addstr", (PyCFunction)_curses_window_addstr, METH_VARARGS, _curses_window_addstr__doc__}, + +static PyObject * +_curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int group_right_1, + long attr); + +static PyObject * +_curses_window_addstr(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *str; + int group_right_1 = 0; + long attr = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:addstr", &str)) { + goto exit; + } + break; + case 2: + if (!PyArg_ParseTuple(args, "Ol:addstr", &str, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 3: + if (!PyArg_ParseTuple(args, "iiO:addstr", &y, &x, &str)) { + goto exit; + } + group_left_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOl:addstr", &y, &x, &str, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.addstr requires 1 to 4 arguments"); + goto exit; + } + return_value = _curses_window_addstr_impl((PyCursesWindowObject *)self, group_left_1, y, x, str, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_addnstr__doc__, +"addnstr([y, x,] str, n, [attr])\n" +"Paint at most n characters of the string.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" str\n" +" String to add.\n" +" n\n" +" Maximal number of characters.\n" +" attr\n" +" Attributes for characters.\n" +"\n" +"Paint at most n characters of the string str at (y, x) with\n" +"attributes attr, overwriting anything previously on the display.\n" +"By default, the character position and attributes are the\n" +"current settings for the window object."); + +#define _CURSES_WINDOW_ADDNSTR_METHODDEF \ + {"addnstr", (PyCFunction)_curses_window_addnstr, METH_VARARGS, _curses_window_addnstr__doc__}, + +static PyObject * +_curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int n, + int group_right_1, long attr); + +static PyObject * +_curses_window_addnstr(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *str; + int n; + int group_right_1 = 0; + long attr = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "Oi:addnstr", &str, &n)) { + goto exit; + } + break; + case 3: + if (!PyArg_ParseTuple(args, "Oil:addnstr", &str, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOi:addnstr", &y, &x, &str, &n)) { + goto exit; + } + group_left_1 = 1; + break; + case 5: + if (!PyArg_ParseTuple(args, "iiOil:addnstr", &y, &x, &str, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.addnstr requires 2 to 5 arguments"); + goto exit; + } + return_value = _curses_window_addnstr_impl((PyCursesWindowObject *)self, group_left_1, y, x, str, n, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_bkgd__doc__, +"bkgd($self, ch, attr=_curses.A_NORMAL, /)\n" +"--\n" +"\n" +"Set the background property of the window.\n" +"\n" +" ch\n" +" Background character.\n" +" attr\n" +" Background attributes."); + +#define _CURSES_WINDOW_BKGD_METHODDEF \ + {"bkgd", _PyCFunction_CAST(_curses_window_bkgd), METH_FASTCALL, _curses_window_bkgd__doc__}, + +static PyObject * +_curses_window_bkgd_impl(PyCursesWindowObject *self, PyObject *ch, long attr); + +static PyObject * +_curses_window_bkgd(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *ch; + long attr = A_NORMAL; + + if (!_PyArg_CheckPositional("bkgd", nargs, 1, 2)) { + goto exit; + } + ch = args[0]; + if (nargs < 2) { + goto skip_optional; + } + attr = PyLong_AsLong(args[1]); + if (attr == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _curses_window_bkgd_impl((PyCursesWindowObject *)self, ch, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_attroff__doc__, +"attroff($self, attr, /)\n" +"--\n" +"\n" +"Remove attribute attr from the \"background\" set."); + +#define _CURSES_WINDOW_ATTROFF_METHODDEF \ + {"attroff", (PyCFunction)_curses_window_attroff, METH_O, _curses_window_attroff__doc__}, + +static PyObject * +_curses_window_attroff_impl(PyCursesWindowObject *self, long attr); + +static PyObject * +_curses_window_attroff(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + long attr; + + attr = PyLong_AsLong(arg); + if (attr == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_window_attroff_impl((PyCursesWindowObject *)self, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_attron__doc__, +"attron($self, attr, /)\n" +"--\n" +"\n" +"Add attribute attr to the \"background\" set."); + +#define _CURSES_WINDOW_ATTRON_METHODDEF \ + {"attron", (PyCFunction)_curses_window_attron, METH_O, _curses_window_attron__doc__}, + +static PyObject * +_curses_window_attron_impl(PyCursesWindowObject *self, long attr); + +static PyObject * +_curses_window_attron(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + long attr; + + attr = PyLong_AsLong(arg); + if (attr == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_window_attron_impl((PyCursesWindowObject *)self, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_attrset__doc__, +"attrset($self, attr, /)\n" +"--\n" +"\n" +"Set the \"background\" set of attributes."); + +#define _CURSES_WINDOW_ATTRSET_METHODDEF \ + {"attrset", (PyCFunction)_curses_window_attrset, METH_O, _curses_window_attrset__doc__}, + +static PyObject * +_curses_window_attrset_impl(PyCursesWindowObject *self, long attr); + +static PyObject * +_curses_window_attrset(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + long attr; + + attr = PyLong_AsLong(arg); + if (attr == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_window_attrset_impl((PyCursesWindowObject *)self, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_bkgdset__doc__, +"bkgdset($self, ch, attr=_curses.A_NORMAL, /)\n" +"--\n" +"\n" +"Set the window\'s background.\n" +"\n" +" ch\n" +" Background character.\n" +" attr\n" +" Background attributes."); + +#define _CURSES_WINDOW_BKGDSET_METHODDEF \ + {"bkgdset", _PyCFunction_CAST(_curses_window_bkgdset), METH_FASTCALL, _curses_window_bkgdset__doc__}, + +static PyObject * +_curses_window_bkgdset_impl(PyCursesWindowObject *self, PyObject *ch, + long attr); + +static PyObject * +_curses_window_bkgdset(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *ch; + long attr = A_NORMAL; + + if (!_PyArg_CheckPositional("bkgdset", nargs, 1, 2)) { + goto exit; + } + ch = args[0]; + if (nargs < 2) { + goto skip_optional; + } + attr = PyLong_AsLong(args[1]); + if (attr == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _curses_window_bkgdset_impl((PyCursesWindowObject *)self, ch, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_border__doc__, +"border($self, ls=_curses.ACS_VLINE, rs=_curses.ACS_VLINE,\n" +" ts=_curses.ACS_HLINE, bs=_curses.ACS_HLINE,\n" +" tl=_curses.ACS_ULCORNER, tr=_curses.ACS_URCORNER,\n" +" bl=_curses.ACS_LLCORNER, br=_curses.ACS_LRCORNER, /)\n" +"--\n" +"\n" +"Draw a border around the edges of the window.\n" +"\n" +" ls\n" +" Left side.\n" +" rs\n" +" Right side.\n" +" ts\n" +" Top side.\n" +" bs\n" +" Bottom side.\n" +" tl\n" +" Upper-left corner.\n" +" tr\n" +" Upper-right corner.\n" +" bl\n" +" Bottom-left corner.\n" +" br\n" +" Bottom-right corner.\n" +"\n" +"Each parameter specifies the character to use for a specific part of the\n" +"border. The characters can be specified as integers or as one-character\n" +"strings. A 0 value for any parameter will cause the default character to be\n" +"used for that parameter."); + +#define _CURSES_WINDOW_BORDER_METHODDEF \ + {"border", _PyCFunction_CAST(_curses_window_border), METH_FASTCALL, _curses_window_border__doc__}, + +static PyObject * +_curses_window_border_impl(PyCursesWindowObject *self, PyObject *ls, + PyObject *rs, PyObject *ts, PyObject *bs, + PyObject *tl, PyObject *tr, PyObject *bl, + PyObject *br); + +static PyObject * +_curses_window_border(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *ls = NULL; + PyObject *rs = NULL; + PyObject *ts = NULL; + PyObject *bs = NULL; + PyObject *tl = NULL; + PyObject *tr = NULL; + PyObject *bl = NULL; + PyObject *br = NULL; + + if (!_PyArg_CheckPositional("border", nargs, 0, 8)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + ls = args[0]; + if (nargs < 2) { + goto skip_optional; + } + rs = args[1]; + if (nargs < 3) { + goto skip_optional; + } + ts = args[2]; + if (nargs < 4) { + goto skip_optional; + } + bs = args[3]; + if (nargs < 5) { + goto skip_optional; + } + tl = args[4]; + if (nargs < 6) { + goto skip_optional; + } + tr = args[5]; + if (nargs < 7) { + goto skip_optional; + } + bl = args[6]; + if (nargs < 8) { + goto skip_optional; + } + br = args[7]; +skip_optional: + return_value = _curses_window_border_impl((PyCursesWindowObject *)self, ls, rs, ts, bs, tl, tr, bl, br); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_box__doc__, +"box([verch=0, horch=0])\n" +"Draw a border around the edges of the window.\n" +"\n" +" verch\n" +" Left and right side.\n" +" horch\n" +" Top and bottom side.\n" +"\n" +"Similar to border(), but both ls and rs are verch and both ts and bs are\n" +"horch. The default corner characters are always used by this function."); + +#define _CURSES_WINDOW_BOX_METHODDEF \ + {"box", (PyCFunction)_curses_window_box, METH_VARARGS, _curses_window_box__doc__}, + +static PyObject * +_curses_window_box_impl(PyCursesWindowObject *self, int group_right_1, + PyObject *verch, PyObject *horch); + +static PyObject * +_curses_window_box(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + PyObject *verch = _PyLong_GetZero(); + PyObject *horch = _PyLong_GetZero(); + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "OO:box", &verch, &horch)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.box requires 0 to 2 arguments"); + goto exit; + } + return_value = _curses_window_box_impl((PyCursesWindowObject *)self, group_right_1, verch, horch); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_delch__doc__, +"delch([y, x])\n" +"Delete any character at (y, x).\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate."); + +#define _CURSES_WINDOW_DELCH_METHODDEF \ + {"delch", (PyCFunction)_curses_window_delch, METH_VARARGS, _curses_window_delch__doc__}, + +static PyObject * +_curses_window_delch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x); + +static PyObject * +_curses_window_delch(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int y = 0; + int x = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:delch", &y, &x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.delch requires 0 to 2 arguments"); + goto exit; + } + return_value = _curses_window_delch_impl((PyCursesWindowObject *)self, group_right_1, y, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_derwin__doc__, +"derwin([nlines=0, ncols=0,] begin_y, begin_x)\n" +"Create a sub-window (window-relative coordinates).\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width.\n" +" begin_y\n" +" Top side y-coordinate.\n" +" begin_x\n" +" Left side x-coordinate.\n" +"\n" +"derwin() is the same as calling subwin(), except that begin_y and begin_x\n" +"are relative to the origin of the window, rather than relative to the entire\n" +"screen."); + +#define _CURSES_WINDOW_DERWIN_METHODDEF \ + {"derwin", (PyCFunction)_curses_window_derwin, METH_VARARGS, _curses_window_derwin__doc__}, + +static PyObject * +_curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, + int nlines, int ncols, int begin_y, int begin_x); + +static PyObject * +_curses_window_derwin(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int nlines = 0; + int ncols = 0; + int begin_y; + int begin_x; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "ii:derwin", &begin_y, &begin_x)) { + goto exit; + } + break; + case 4: + if (!PyArg_ParseTuple(args, "iiii:derwin", &nlines, &ncols, &begin_y, &begin_x)) { + goto exit; + } + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.derwin requires 2 to 4 arguments"); + goto exit; + } + return_value = _curses_window_derwin_impl((PyCursesWindowObject *)self, group_left_1, nlines, ncols, begin_y, begin_x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_echochar__doc__, +"echochar($self, ch, attr=_curses.A_NORMAL, /)\n" +"--\n" +"\n" +"Add character ch with attribute attr, and refresh.\n" +"\n" +" ch\n" +" Character to add.\n" +" attr\n" +" Attributes for the character."); + +#define _CURSES_WINDOW_ECHOCHAR_METHODDEF \ + {"echochar", _PyCFunction_CAST(_curses_window_echochar), METH_FASTCALL, _curses_window_echochar__doc__}, + +static PyObject * +_curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch, + long attr); + +static PyObject * +_curses_window_echochar(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *ch; + long attr = A_NORMAL; + + if (!_PyArg_CheckPositional("echochar", nargs, 1, 2)) { + goto exit; + } + ch = args[0]; + if (nargs < 2) { + goto skip_optional; + } + attr = PyLong_AsLong(args[1]); + if (attr == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _curses_window_echochar_impl((PyCursesWindowObject *)self, ch, attr); + +exit: + return return_value; +} + +#if defined(NCURSES_MOUSE_VERSION) + +PyDoc_STRVAR(_curses_window_enclose__doc__, +"enclose($self, y, x, /)\n" +"--\n" +"\n" +"Return True if the screen-relative coordinates are enclosed by the window.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate."); + +#define _CURSES_WINDOW_ENCLOSE_METHODDEF \ + {"enclose", _PyCFunction_CAST(_curses_window_enclose), METH_FASTCALL, _curses_window_enclose__doc__}, + +static PyObject * +_curses_window_enclose_impl(PyCursesWindowObject *self, int y, int x); + +static PyObject * +_curses_window_enclose(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int y; + int x; + + if (!_PyArg_CheckPositional("enclose", nargs, 2, 2)) { + goto exit; + } + y = PyLong_AsInt(args[0]); + if (y == -1 && PyErr_Occurred()) { + goto exit; + } + x = PyLong_AsInt(args[1]); + if (x == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_window_enclose_impl((PyCursesWindowObject *)self, y, x); + +exit: + return return_value; +} + +#endif /* defined(NCURSES_MOUSE_VERSION) */ + +PyDoc_STRVAR(_curses_window_getbkgd__doc__, +"getbkgd($self, /)\n" +"--\n" +"\n" +"Return the window\'s current background character/attribute pair."); + +#define _CURSES_WINDOW_GETBKGD_METHODDEF \ + {"getbkgd", (PyCFunction)_curses_window_getbkgd, METH_NOARGS, _curses_window_getbkgd__doc__}, + +static PyObject * +_curses_window_getbkgd_impl(PyCursesWindowObject *self); + +static PyObject * +_curses_window_getbkgd(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_window_getbkgd_impl((PyCursesWindowObject *)self); +} + +PyDoc_STRVAR(_curses_window_getch__doc__, +"getch([y, x])\n" +"Get a character code from terminal keyboard.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +"\n" +"The integer returned does not have to be in ASCII range: function keys,\n" +"keypad keys and so on return numbers higher than 256. In no-delay mode, -1\n" +"is returned if there is no input, else getch() waits until a key is pressed."); + +#define _CURSES_WINDOW_GETCH_METHODDEF \ + {"getch", (PyCFunction)_curses_window_getch, METH_VARARGS, _curses_window_getch__doc__}, + +static PyObject * +_curses_window_getch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x); + +static PyObject * +_curses_window_getch(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int y = 0; + int x = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:getch", &y, &x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.getch requires 0 to 2 arguments"); + goto exit; + } + return_value = _curses_window_getch_impl((PyCursesWindowObject *)self, group_right_1, y, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_getkey__doc__, +"getkey([y, x])\n" +"Get a character (string) from terminal keyboard.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +"\n" +"Returning a string instead of an integer, as getch() does. Function keys,\n" +"keypad keys and other special keys return a multibyte string containing the\n" +"key name. In no-delay mode, an exception is raised if there is no input."); + +#define _CURSES_WINDOW_GETKEY_METHODDEF \ + {"getkey", (PyCFunction)_curses_window_getkey, METH_VARARGS, _curses_window_getkey__doc__}, + +static PyObject * +_curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x); + +static PyObject * +_curses_window_getkey(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int y = 0; + int x = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:getkey", &y, &x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.getkey requires 0 to 2 arguments"); + goto exit; + } + return_value = _curses_window_getkey_impl((PyCursesWindowObject *)self, group_right_1, y, x); + +exit: + return return_value; +} + +#if defined(HAVE_NCURSESW) + +PyDoc_STRVAR(_curses_window_get_wch__doc__, +"get_wch([y, x])\n" +"Get a wide character from terminal keyboard.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +"\n" +"Return a character for most keys, or an integer for function keys,\n" +"keypad keys, and other special keys."); + +#define _CURSES_WINDOW_GET_WCH_METHODDEF \ + {"get_wch", (PyCFunction)_curses_window_get_wch, METH_VARARGS, _curses_window_get_wch__doc__}, + +static PyObject * +_curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x); + +static PyObject * +_curses_window_get_wch(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int y = 0; + int x = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:get_wch", &y, &x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.get_wch requires 0 to 2 arguments"); + goto exit; + } + return_value = _curses_window_get_wch_impl((PyCursesWindowObject *)self, group_right_1, y, x); + +exit: + return return_value; +} + +#endif /* defined(HAVE_NCURSESW) */ + +PyDoc_STRVAR(_curses_window_hline__doc__, +"hline([y, x,] ch, n, [attr=_curses.A_NORMAL])\n" +"Display a horizontal line.\n" +"\n" +" y\n" +" Starting Y-coordinate.\n" +" x\n" +" Starting X-coordinate.\n" +" ch\n" +" Character to draw.\n" +" n\n" +" Line length.\n" +" attr\n" +" Attributes for the characters."); + +#define _CURSES_WINDOW_HLINE_METHODDEF \ + {"hline", (PyCFunction)_curses_window_hline, METH_VARARGS, _curses_window_hline__doc__}, + +static PyObject * +_curses_window_hline_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int n, + int group_right_1, long attr); + +static PyObject * +_curses_window_hline(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *ch; + int n; + int group_right_1 = 0; + long attr = A_NORMAL; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "Oi:hline", &ch, &n)) { + goto exit; + } + break; + case 3: + if (!PyArg_ParseTuple(args, "Oil:hline", &ch, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOi:hline", &y, &x, &ch, &n)) { + goto exit; + } + group_left_1 = 1; + break; + case 5: + if (!PyArg_ParseTuple(args, "iiOil:hline", &y, &x, &ch, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.hline requires 2 to 5 arguments"); + goto exit; + } + return_value = _curses_window_hline_impl((PyCursesWindowObject *)self, group_left_1, y, x, ch, n, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_insch__doc__, +"insch([y, x,] ch, [attr=_curses.A_NORMAL])\n" +"Insert a character before the current or specified position.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" ch\n" +" Character to insert.\n" +" attr\n" +" Attributes for the character.\n" +"\n" +"All characters to the right of the cursor are shifted one position right, with\n" +"the rightmost characters on the line being lost."); + +#define _CURSES_WINDOW_INSCH_METHODDEF \ + {"insch", (PyCFunction)_curses_window_insch, METH_VARARGS, _curses_window_insch__doc__}, + +static PyObject * +_curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int group_right_1, + long attr); + +static PyObject * +_curses_window_insch(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *ch; + int group_right_1 = 0; + long attr = A_NORMAL; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:insch", &ch)) { + goto exit; + } + break; + case 2: + if (!PyArg_ParseTuple(args, "Ol:insch", &ch, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 3: + if (!PyArg_ParseTuple(args, "iiO:insch", &y, &x, &ch)) { + goto exit; + } + group_left_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOl:insch", &y, &x, &ch, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.insch requires 1 to 4 arguments"); + goto exit; + } + return_value = _curses_window_insch_impl((PyCursesWindowObject *)self, group_left_1, y, x, ch, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_inch__doc__, +"inch([y, x])\n" +"Return the character at the given position in the window.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +"\n" +"The bottom 8 bits are the character proper, and upper bits are the attributes."); + +#define _CURSES_WINDOW_INCH_METHODDEF \ + {"inch", (PyCFunction)_curses_window_inch, METH_VARARGS, _curses_window_inch__doc__}, + +static PyObject * +_curses_window_inch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x); + +static PyObject * +_curses_window_inch(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int y = 0; + int x = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:inch", &y, &x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.inch requires 0 to 2 arguments"); + goto exit; + } + return_value = _curses_window_inch_impl((PyCursesWindowObject *)self, group_right_1, y, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_insstr__doc__, +"insstr([y, x,] str, [attr])\n" +"Insert the string before the current or specified position.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" str\n" +" String to insert.\n" +" attr\n" +" Attributes for characters.\n" +"\n" +"Insert a character string (as many characters as will fit on the line)\n" +"before the character under the cursor. All characters to the right of\n" +"the cursor are shifted right, with the rightmost characters on the line\n" +"being lost. The cursor position does not change (after moving to y, x,\n" +"if specified)."); + +#define _CURSES_WINDOW_INSSTR_METHODDEF \ + {"insstr", (PyCFunction)_curses_window_insstr, METH_VARARGS, _curses_window_insstr__doc__}, + +static PyObject * +_curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int group_right_1, + long attr); + +static PyObject * +_curses_window_insstr(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *str; + int group_right_1 = 0; + long attr = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:insstr", &str)) { + goto exit; + } + break; + case 2: + if (!PyArg_ParseTuple(args, "Ol:insstr", &str, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 3: + if (!PyArg_ParseTuple(args, "iiO:insstr", &y, &x, &str)) { + goto exit; + } + group_left_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOl:insstr", &y, &x, &str, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.insstr requires 1 to 4 arguments"); + goto exit; + } + return_value = _curses_window_insstr_impl((PyCursesWindowObject *)self, group_left_1, y, x, str, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_insnstr__doc__, +"insnstr([y, x,] str, n, [attr])\n" +"Insert at most n characters of the string.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" str\n" +" String to insert.\n" +" n\n" +" Maximal number of characters.\n" +" attr\n" +" Attributes for characters.\n" +"\n" +"Insert a character string (as many characters as will fit on the line)\n" +"before the character under the cursor, up to n characters. If n is zero\n" +"or negative, the entire string is inserted. All characters to the right\n" +"of the cursor are shifted right, with the rightmost characters on the line\n" +"being lost. The cursor position does not change (after moving to y, x, if\n" +"specified)."); + +#define _CURSES_WINDOW_INSNSTR_METHODDEF \ + {"insnstr", (PyCFunction)_curses_window_insnstr, METH_VARARGS, _curses_window_insnstr__doc__}, + +static PyObject * +_curses_window_insnstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int n, + int group_right_1, long attr); + +static PyObject * +_curses_window_insnstr(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *str; + int n; + int group_right_1 = 0; + long attr = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "Oi:insnstr", &str, &n)) { + goto exit; + } + break; + case 3: + if (!PyArg_ParseTuple(args, "Oil:insnstr", &str, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOi:insnstr", &y, &x, &str, &n)) { + goto exit; + } + group_left_1 = 1; + break; + case 5: + if (!PyArg_ParseTuple(args, "iiOil:insnstr", &y, &x, &str, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.insnstr requires 2 to 5 arguments"); + goto exit; + } + return_value = _curses_window_insnstr_impl((PyCursesWindowObject *)self, group_left_1, y, x, str, n, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_is_linetouched__doc__, +"is_linetouched($self, line, /)\n" +"--\n" +"\n" +"Return True if the specified line was modified, otherwise return False.\n" +"\n" +" line\n" +" Line number.\n" +"\n" +"Raise a curses.error exception if line is not valid for the given window."); + +#define _CURSES_WINDOW_IS_LINETOUCHED_METHODDEF \ + {"is_linetouched", (PyCFunction)_curses_window_is_linetouched, METH_O, _curses_window_is_linetouched__doc__}, + +static PyObject * +_curses_window_is_linetouched_impl(PyCursesWindowObject *self, int line); + +static PyObject * +_curses_window_is_linetouched(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int line; + + line = PyLong_AsInt(arg); + if (line == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_window_is_linetouched_impl((PyCursesWindowObject *)self, line); + +exit: + return return_value; +} + +#if defined(py_is_pad) + +PyDoc_STRVAR(_curses_window_noutrefresh__doc__, +"noutrefresh([pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol])\n" +"Mark for refresh but wait.\n" +"\n" +"This function updates the data structure representing the desired state of the\n" +"window, but does not force an update of the physical screen. To accomplish\n" +"that, call doupdate()."); + +#define _CURSES_WINDOW_NOUTREFRESH_METHODDEF \ + {"noutrefresh", (PyCFunction)_curses_window_noutrefresh, METH_VARARGS, _curses_window_noutrefresh__doc__}, + +static PyObject * +_curses_window_noutrefresh_impl(PyCursesWindowObject *self, + int group_right_1, int pminrow, int pmincol, + int sminrow, int smincol, int smaxrow, + int smaxcol); + +static PyObject * +_curses_window_noutrefresh(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int pminrow = 0; + int pmincol = 0; + int sminrow = 0; + int smincol = 0; + int smaxrow = 0; + int smaxcol = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 6: + if (!PyArg_ParseTuple(args, "iiiiii:noutrefresh", &pminrow, &pmincol, &sminrow, &smincol, &smaxrow, &smaxcol)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.noutrefresh requires 0 to 6 arguments"); + goto exit; + } + return_value = _curses_window_noutrefresh_impl((PyCursesWindowObject *)self, group_right_1, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); + +exit: + return return_value; +} + +#endif /* defined(py_is_pad) */ + +#if !defined(py_is_pad) + +PyDoc_STRVAR(_curses_window_noutrefresh__doc__, +"noutrefresh($self, /)\n" +"--\n" +"\n" +"Mark for refresh but wait.\n" +"\n" +"This function updates the data structure representing the desired state of the\n" +"window, but does not force an update of the physical screen. To accomplish\n" +"that, call doupdate()."); + +#define _CURSES_WINDOW_NOUTREFRESH_METHODDEF \ + {"noutrefresh", (PyCFunction)_curses_window_noutrefresh, METH_NOARGS, _curses_window_noutrefresh__doc__}, + +static PyObject * +_curses_window_noutrefresh_impl(PyCursesWindowObject *self); + +static PyObject * +_curses_window_noutrefresh(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_window_noutrefresh_impl((PyCursesWindowObject *)self); +} + +#endif /* !defined(py_is_pad) */ + +PyDoc_STRVAR(_curses_window_overlay__doc__, +"overlay(destwin, [sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol])\n" +"Overlay the window on top of destwin.\n" +"\n" +"The windows need not be the same size, only the overlapping region is copied.\n" +"This copy is non-destructive, which means that the current background\n" +"character does not overwrite the old contents of destwin.\n" +"\n" +"To get fine-grained control over the copied region, the second form of\n" +"overlay() can be used. sminrow and smincol are the upper-left coordinates\n" +"of the source window, and the other variables mark a rectangle in the\n" +"destination window."); + +#define _CURSES_WINDOW_OVERLAY_METHODDEF \ + {"overlay", (PyCFunction)_curses_window_overlay, METH_VARARGS, _curses_window_overlay__doc__}, + +static PyObject * +_curses_window_overlay_impl(PyCursesWindowObject *self, + PyCursesWindowObject *destwin, int group_right_1, + int sminrow, int smincol, int dminrow, + int dmincol, int dmaxrow, int dmaxcol); + +static PyObject * +_curses_window_overlay(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyCursesWindowObject *destwin; + int group_right_1 = 0; + int sminrow = 0; + int smincol = 0; + int dminrow = 0; + int dmincol = 0; + int dmaxrow = 0; + int dmaxcol = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O!:overlay", clinic_state()->window_type, &destwin)) { + goto exit; + } + break; + case 7: + if (!PyArg_ParseTuple(args, "O!iiiiii:overlay", clinic_state()->window_type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.overlay requires 1 to 7 arguments"); + goto exit; + } + return_value = _curses_window_overlay_impl((PyCursesWindowObject *)self, destwin, group_right_1, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_overwrite__doc__, +"overwrite(destwin, [sminrow, smincol, dminrow, dmincol, dmaxrow,\n" +" dmaxcol])\n" +"Overwrite the window on top of destwin.\n" +"\n" +"The windows need not be the same size, in which case only the overlapping\n" +"region is copied. This copy is destructive, which means that the current\n" +"background character overwrites the old contents of destwin.\n" +"\n" +"To get fine-grained control over the copied region, the second form of\n" +"overwrite() can be used. sminrow and smincol are the upper-left coordinates\n" +"of the source window, the other variables mark a rectangle in the destination\n" +"window."); + +#define _CURSES_WINDOW_OVERWRITE_METHODDEF \ + {"overwrite", (PyCFunction)_curses_window_overwrite, METH_VARARGS, _curses_window_overwrite__doc__}, + +static PyObject * +_curses_window_overwrite_impl(PyCursesWindowObject *self, + PyCursesWindowObject *destwin, + int group_right_1, int sminrow, int smincol, + int dminrow, int dmincol, int dmaxrow, + int dmaxcol); + +static PyObject * +_curses_window_overwrite(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyCursesWindowObject *destwin; + int group_right_1 = 0; + int sminrow = 0; + int smincol = 0; + int dminrow = 0; + int dmincol = 0; + int dmaxrow = 0; + int dmaxcol = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O!:overwrite", clinic_state()->window_type, &destwin)) { + goto exit; + } + break; + case 7: + if (!PyArg_ParseTuple(args, "O!iiiiii:overwrite", clinic_state()->window_type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.overwrite requires 1 to 7 arguments"); + goto exit; + } + return_value = _curses_window_overwrite_impl((PyCursesWindowObject *)self, destwin, group_right_1, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_putwin__doc__, +"putwin($self, file, /)\n" +"--\n" +"\n" +"Write all data associated with the window into the provided file object.\n" +"\n" +"This information can be later retrieved using the getwin() function."); + +#define _CURSES_WINDOW_PUTWIN_METHODDEF \ + {"putwin", (PyCFunction)_curses_window_putwin, METH_O, _curses_window_putwin__doc__}, + +static PyObject * +_curses_window_putwin_impl(PyCursesWindowObject *self, PyObject *file); + +static PyObject * +_curses_window_putwin(PyObject *self, PyObject *file) +{ + PyObject *return_value = NULL; + + return_value = _curses_window_putwin_impl((PyCursesWindowObject *)self, file); + + return return_value; +} + +PyDoc_STRVAR(_curses_window_redrawln__doc__, +"redrawln($self, beg, num, /)\n" +"--\n" +"\n" +"Mark the specified lines corrupted.\n" +"\n" +" beg\n" +" Starting line number.\n" +" num\n" +" The number of lines.\n" +"\n" +"They should be completely redrawn on the next refresh() call."); + +#define _CURSES_WINDOW_REDRAWLN_METHODDEF \ + {"redrawln", _PyCFunction_CAST(_curses_window_redrawln), METH_FASTCALL, _curses_window_redrawln__doc__}, + +static PyObject * +_curses_window_redrawln_impl(PyCursesWindowObject *self, int beg, int num); + +static PyObject * +_curses_window_redrawln(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int beg; + int num; + + if (!_PyArg_CheckPositional("redrawln", nargs, 2, 2)) { + goto exit; + } + beg = PyLong_AsInt(args[0]); + if (beg == -1 && PyErr_Occurred()) { + goto exit; + } + num = PyLong_AsInt(args[1]); + if (num == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_window_redrawln_impl((PyCursesWindowObject *)self, beg, num); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_refresh__doc__, +"refresh([pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol])\n" +"Update the display immediately.\n" +"\n" +"Synchronize actual screen with previous drawing/deleting methods.\n" +"The 6 optional arguments can only be specified when the window is a pad\n" +"created with newpad(). The additional parameters are needed to indicate\n" +"what part of the pad and screen are involved. pminrow and pmincol specify\n" +"the upper left-hand corner of the rectangle to be displayed in the pad.\n" +"sminrow, smincol, smaxrow, and smaxcol specify the edges of the rectangle to\n" +"be displayed on the screen. The lower right-hand corner of the rectangle to\n" +"be displayed in the pad is calculated from the screen coordinates, since the\n" +"rectangles must be the same size. Both rectangles must be entirely contained\n" +"within their respective structures. Negative values of pminrow, pmincol,\n" +"sminrow, or smincol are treated as if they were zero."); + +#define _CURSES_WINDOW_REFRESH_METHODDEF \ + {"refresh", (PyCFunction)_curses_window_refresh, METH_VARARGS, _curses_window_refresh__doc__}, + +static PyObject * +_curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, + int pminrow, int pmincol, int sminrow, + int smincol, int smaxrow, int smaxcol); + +static PyObject * +_curses_window_refresh(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int pminrow = 0; + int pmincol = 0; + int sminrow = 0; + int smincol = 0; + int smaxrow = 0; + int smaxcol = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 6: + if (!PyArg_ParseTuple(args, "iiiiii:refresh", &pminrow, &pmincol, &sminrow, &smincol, &smaxrow, &smaxcol)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.refresh requires 0 to 6 arguments"); + goto exit; + } + return_value = _curses_window_refresh_impl((PyCursesWindowObject *)self, group_right_1, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_setscrreg__doc__, +"setscrreg($self, top, bottom, /)\n" +"--\n" +"\n" +"Define a software scrolling region.\n" +"\n" +" top\n" +" First line number.\n" +" bottom\n" +" Last line number.\n" +"\n" +"All scrolling actions will take place in this region."); + +#define _CURSES_WINDOW_SETSCRREG_METHODDEF \ + {"setscrreg", _PyCFunction_CAST(_curses_window_setscrreg), METH_FASTCALL, _curses_window_setscrreg__doc__}, + +static PyObject * +_curses_window_setscrreg_impl(PyCursesWindowObject *self, int top, + int bottom); + +static PyObject * +_curses_window_setscrreg(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int top; + int bottom; + + if (!_PyArg_CheckPositional("setscrreg", nargs, 2, 2)) { + goto exit; + } + top = PyLong_AsInt(args[0]); + if (top == -1 && PyErr_Occurred()) { + goto exit; + } + bottom = PyLong_AsInt(args[1]); + if (bottom == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_window_setscrreg_impl((PyCursesWindowObject *)self, top, bottom); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_subwin__doc__, +"subwin([nlines=0, ncols=0,] begin_y, begin_x)\n" +"Create a sub-window (screen-relative coordinates).\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width.\n" +" begin_y\n" +" Top side y-coordinate.\n" +" begin_x\n" +" Left side x-coordinate.\n" +"\n" +"By default, the sub-window will extend from the specified position to the\n" +"lower right corner of the window."); + +#define _CURSES_WINDOW_SUBWIN_METHODDEF \ + {"subwin", (PyCFunction)_curses_window_subwin, METH_VARARGS, _curses_window_subwin__doc__}, + +static PyObject * +_curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, + int nlines, int ncols, int begin_y, int begin_x); + +static PyObject * +_curses_window_subwin(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int nlines = 0; + int ncols = 0; + int begin_y; + int begin_x; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "ii:subwin", &begin_y, &begin_x)) { + goto exit; + } + break; + case 4: + if (!PyArg_ParseTuple(args, "iiii:subwin", &nlines, &ncols, &begin_y, &begin_x)) { + goto exit; + } + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.subwin requires 2 to 4 arguments"); + goto exit; + } + return_value = _curses_window_subwin_impl((PyCursesWindowObject *)self, group_left_1, nlines, ncols, begin_y, begin_x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_scroll__doc__, +"scroll([lines=1])\n" +"Scroll the screen or scrolling region.\n" +"\n" +" lines\n" +" Number of lines to scroll.\n" +"\n" +"Scroll upward if the argument is positive and downward if it is negative."); + +#define _CURSES_WINDOW_SCROLL_METHODDEF \ + {"scroll", (PyCFunction)_curses_window_scroll, METH_VARARGS, _curses_window_scroll__doc__}, + +static PyObject * +_curses_window_scroll_impl(PyCursesWindowObject *self, int group_right_1, + int lines); + +static PyObject * +_curses_window_scroll(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int lines = 1; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 1: + if (!PyArg_ParseTuple(args, "i:scroll", &lines)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.scroll requires 0 to 1 arguments"); + goto exit; + } + return_value = _curses_window_scroll_impl((PyCursesWindowObject *)self, group_right_1, lines); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_touchline__doc__, +"touchline(start, count, [changed=True])\n" +"Pretend count lines have been changed, starting with line start.\n" +"\n" +"If changed is supplied, it specifies whether the affected lines are marked\n" +"as having been changed (changed=True) or unchanged (changed=False)."); + +#define _CURSES_WINDOW_TOUCHLINE_METHODDEF \ + {"touchline", (PyCFunction)_curses_window_touchline, METH_VARARGS, _curses_window_touchline__doc__}, + +static PyObject * +_curses_window_touchline_impl(PyCursesWindowObject *self, int start, + int count, int group_right_1, int changed); + +static PyObject * +_curses_window_touchline(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int start; + int count; + int group_right_1 = 0; + int changed = 1; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "ii:touchline", &start, &count)) { + goto exit; + } + break; + case 3: + if (!PyArg_ParseTuple(args, "iip:touchline", &start, &count, &changed)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.touchline requires 2 to 3 arguments"); + goto exit; + } + return_value = _curses_window_touchline_impl((PyCursesWindowObject *)self, start, count, group_right_1, changed); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_vline__doc__, +"vline([y, x,] ch, n, [attr=_curses.A_NORMAL])\n" +"Display a vertical line.\n" +"\n" +" y\n" +" Starting Y-coordinate.\n" +" x\n" +" Starting X-coordinate.\n" +" ch\n" +" Character to draw.\n" +" n\n" +" Line length.\n" +" attr\n" +" Attributes for the character."); + +#define _CURSES_WINDOW_VLINE_METHODDEF \ + {"vline", (PyCFunction)_curses_window_vline, METH_VARARGS, _curses_window_vline__doc__}, + +static PyObject * +_curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int n, + int group_right_1, long attr); + +static PyObject * +_curses_window_vline(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *ch; + int n; + int group_right_1 = 0; + long attr = A_NORMAL; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "Oi:vline", &ch, &n)) { + goto exit; + } + break; + case 3: + if (!PyArg_ParseTuple(args, "Oil:vline", &ch, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOi:vline", &y, &x, &ch, &n)) { + goto exit; + } + group_left_1 = 1; + break; + case 5: + if (!PyArg_ParseTuple(args, "iiOil:vline", &y, &x, &ch, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.vline requires 2 to 5 arguments"); + goto exit; + } + return_value = _curses_window_vline_impl((PyCursesWindowObject *)self, group_left_1, y, x, ch, n, group_right_1, attr); + +exit: + return return_value; +} + +#if defined(HAVE_CURSES_FILTER) + +PyDoc_STRVAR(_curses_filter__doc__, +"filter($module, /)\n" +"--\n" +"\n"); + +#define _CURSES_FILTER_METHODDEF \ + {"filter", (PyCFunction)_curses_filter, METH_NOARGS, _curses_filter__doc__}, + +static PyObject * +_curses_filter_impl(PyObject *module); + +static PyObject * +_curses_filter(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_filter_impl(module); +} + +#endif /* defined(HAVE_CURSES_FILTER) */ + +PyDoc_STRVAR(_curses_baudrate__doc__, +"baudrate($module, /)\n" +"--\n" +"\n" +"Return the output speed of the terminal in bits per second."); + +#define _CURSES_BAUDRATE_METHODDEF \ + {"baudrate", (PyCFunction)_curses_baudrate, METH_NOARGS, _curses_baudrate__doc__}, + +static PyObject * +_curses_baudrate_impl(PyObject *module); + +static PyObject * +_curses_baudrate(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_baudrate_impl(module); +} + +PyDoc_STRVAR(_curses_beep__doc__, +"beep($module, /)\n" +"--\n" +"\n" +"Emit a short attention sound."); + +#define _CURSES_BEEP_METHODDEF \ + {"beep", (PyCFunction)_curses_beep, METH_NOARGS, _curses_beep__doc__}, + +static PyObject * +_curses_beep_impl(PyObject *module); + +static PyObject * +_curses_beep(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_beep_impl(module); +} + +PyDoc_STRVAR(_curses_can_change_color__doc__, +"can_change_color($module, /)\n" +"--\n" +"\n" +"Return True if the programmer can change the colors displayed by the terminal."); + +#define _CURSES_CAN_CHANGE_COLOR_METHODDEF \ + {"can_change_color", (PyCFunction)_curses_can_change_color, METH_NOARGS, _curses_can_change_color__doc__}, + +static PyObject * +_curses_can_change_color_impl(PyObject *module); + +static PyObject * +_curses_can_change_color(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_can_change_color_impl(module); +} + +PyDoc_STRVAR(_curses_cbreak__doc__, +"cbreak($module, flag=True, /)\n" +"--\n" +"\n" +"Enter cbreak mode.\n" +"\n" +" flag\n" +" If false, the effect is the same as calling nocbreak().\n" +"\n" +"In cbreak mode (sometimes called \"rare\" mode) normal tty line buffering is\n" +"turned off and characters are available to be read one by one. However,\n" +"unlike raw mode, special characters (interrupt, quit, suspend, and flow\n" +"control) retain their effects on the tty driver and calling program.\n" +"Calling first raw() then cbreak() leaves the terminal in cbreak mode."); + +#define _CURSES_CBREAK_METHODDEF \ + {"cbreak", _PyCFunction_CAST(_curses_cbreak), METH_FASTCALL, _curses_cbreak__doc__}, + +static PyObject * +_curses_cbreak_impl(PyObject *module, int flag); + +static PyObject * +_curses_cbreak(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int flag = 1; + + if (!_PyArg_CheckPositional("cbreak", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + flag = PyObject_IsTrue(args[0]); + if (flag < 0) { + goto exit; + } +skip_optional: + return_value = _curses_cbreak_impl(module, flag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_color_content__doc__, +"color_content($module, color_number, /)\n" +"--\n" +"\n" +"Return the red, green, and blue (RGB) components of the specified color.\n" +"\n" +" color_number\n" +" The number of the color (0 - (COLORS-1)).\n" +"\n" +"A 3-tuple is returned, containing the R, G, B values for the given color,\n" +"which will be between 0 (no component) and 1000 (maximum amount of component)."); + +#define _CURSES_COLOR_CONTENT_METHODDEF \ + {"color_content", (PyCFunction)_curses_color_content, METH_O, _curses_color_content__doc__}, + +static PyObject * +_curses_color_content_impl(PyObject *module, int color_number); + +static PyObject * +_curses_color_content(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int color_number; + + if (!color_converter(arg, &color_number)) { + goto exit; + } + return_value = _curses_color_content_impl(module, color_number); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_color_pair__doc__, +"color_pair($module, pair_number, /)\n" +"--\n" +"\n" +"Return the attribute value for displaying text in the specified color.\n" +"\n" +" pair_number\n" +" The number of the color pair.\n" +"\n" +"This attribute value can be combined with A_STANDOUT, A_REVERSE, and the\n" +"other A_* attributes. pair_number() is the counterpart to this function."); + +#define _CURSES_COLOR_PAIR_METHODDEF \ + {"color_pair", (PyCFunction)_curses_color_pair, METH_O, _curses_color_pair__doc__}, + +static PyObject * +_curses_color_pair_impl(PyObject *module, int pair_number); + +static PyObject * +_curses_color_pair(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int pair_number; + + pair_number = PyLong_AsInt(arg); + if (pair_number == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_color_pair_impl(module, pair_number); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_curs_set__doc__, +"curs_set($module, visibility, /)\n" +"--\n" +"\n" +"Set the cursor state.\n" +"\n" +" visibility\n" +" 0 for invisible, 1 for normal visible, or 2 for very visible.\n" +"\n" +"If the terminal supports the visibility requested, the previous cursor\n" +"state is returned; otherwise, an exception is raised. On many terminals,\n" +"the \"visible\" mode is an underline cursor and the \"very visible\" mode is\n" +"a block cursor."); + +#define _CURSES_CURS_SET_METHODDEF \ + {"curs_set", (PyCFunction)_curses_curs_set, METH_O, _curses_curs_set__doc__}, + +static PyObject * +_curses_curs_set_impl(PyObject *module, int visibility); + +static PyObject * +_curses_curs_set(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int visibility; + + visibility = PyLong_AsInt(arg); + if (visibility == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_curs_set_impl(module, visibility); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_def_prog_mode__doc__, +"def_prog_mode($module, /)\n" +"--\n" +"\n" +"Save the current terminal mode as the \"program\" mode.\n" +"\n" +"The \"program\" mode is the mode when the running program is using curses.\n" +"\n" +"Subsequent calls to reset_prog_mode() will restore this mode."); + +#define _CURSES_DEF_PROG_MODE_METHODDEF \ + {"def_prog_mode", (PyCFunction)_curses_def_prog_mode, METH_NOARGS, _curses_def_prog_mode__doc__}, + +static PyObject * +_curses_def_prog_mode_impl(PyObject *module); + +static PyObject * +_curses_def_prog_mode(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_def_prog_mode_impl(module); +} + +PyDoc_STRVAR(_curses_def_shell_mode__doc__, +"def_shell_mode($module, /)\n" +"--\n" +"\n" +"Save the current terminal mode as the \"shell\" mode.\n" +"\n" +"The \"shell\" mode is the mode when the running program is not using curses.\n" +"\n" +"Subsequent calls to reset_shell_mode() will restore this mode."); + +#define _CURSES_DEF_SHELL_MODE_METHODDEF \ + {"def_shell_mode", (PyCFunction)_curses_def_shell_mode, METH_NOARGS, _curses_def_shell_mode__doc__}, + +static PyObject * +_curses_def_shell_mode_impl(PyObject *module); + +static PyObject * +_curses_def_shell_mode(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_def_shell_mode_impl(module); +} + +PyDoc_STRVAR(_curses_delay_output__doc__, +"delay_output($module, ms, /)\n" +"--\n" +"\n" +"Insert a pause in output.\n" +"\n" +" ms\n" +" Duration in milliseconds."); + +#define _CURSES_DELAY_OUTPUT_METHODDEF \ + {"delay_output", (PyCFunction)_curses_delay_output, METH_O, _curses_delay_output__doc__}, + +static PyObject * +_curses_delay_output_impl(PyObject *module, int ms); + +static PyObject * +_curses_delay_output(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int ms; + + ms = PyLong_AsInt(arg); + if (ms == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_delay_output_impl(module, ms); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_doupdate__doc__, +"doupdate($module, /)\n" +"--\n" +"\n" +"Update the physical screen to match the virtual screen."); + +#define _CURSES_DOUPDATE_METHODDEF \ + {"doupdate", (PyCFunction)_curses_doupdate, METH_NOARGS, _curses_doupdate__doc__}, + +static PyObject * +_curses_doupdate_impl(PyObject *module); + +static PyObject * +_curses_doupdate(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_doupdate_impl(module); +} + +PyDoc_STRVAR(_curses_echo__doc__, +"echo($module, flag=True, /)\n" +"--\n" +"\n" +"Enter echo mode.\n" +"\n" +" flag\n" +" If false, the effect is the same as calling noecho().\n" +"\n" +"In echo mode, each character input is echoed to the screen as it is entered."); + +#define _CURSES_ECHO_METHODDEF \ + {"echo", _PyCFunction_CAST(_curses_echo), METH_FASTCALL, _curses_echo__doc__}, + +static PyObject * +_curses_echo_impl(PyObject *module, int flag); + +static PyObject * +_curses_echo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int flag = 1; + + if (!_PyArg_CheckPositional("echo", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + flag = PyObject_IsTrue(args[0]); + if (flag < 0) { + goto exit; + } +skip_optional: + return_value = _curses_echo_impl(module, flag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_endwin__doc__, +"endwin($module, /)\n" +"--\n" +"\n" +"De-initialize the library, and return terminal to normal status."); + +#define _CURSES_ENDWIN_METHODDEF \ + {"endwin", (PyCFunction)_curses_endwin, METH_NOARGS, _curses_endwin__doc__}, + +static PyObject * +_curses_endwin_impl(PyObject *module); + +static PyObject * +_curses_endwin(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_endwin_impl(module); +} + +PyDoc_STRVAR(_curses_erasechar__doc__, +"erasechar($module, /)\n" +"--\n" +"\n" +"Return the user\'s current erase character."); + +#define _CURSES_ERASECHAR_METHODDEF \ + {"erasechar", (PyCFunction)_curses_erasechar, METH_NOARGS, _curses_erasechar__doc__}, + +static PyObject * +_curses_erasechar_impl(PyObject *module); + +static PyObject * +_curses_erasechar(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_erasechar_impl(module); +} + +PyDoc_STRVAR(_curses_flash__doc__, +"flash($module, /)\n" +"--\n" +"\n" +"Flash the screen.\n" +"\n" +"That is, change it to reverse-video and then change it back in a short interval."); + +#define _CURSES_FLASH_METHODDEF \ + {"flash", (PyCFunction)_curses_flash, METH_NOARGS, _curses_flash__doc__}, + +static PyObject * +_curses_flash_impl(PyObject *module); + +static PyObject * +_curses_flash(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_flash_impl(module); +} + +PyDoc_STRVAR(_curses_flushinp__doc__, +"flushinp($module, /)\n" +"--\n" +"\n" +"Flush all input buffers.\n" +"\n" +"This throws away any typeahead that has been typed by the user and has not\n" +"yet been processed by the program."); + +#define _CURSES_FLUSHINP_METHODDEF \ + {"flushinp", (PyCFunction)_curses_flushinp, METH_NOARGS, _curses_flushinp__doc__}, + +static PyObject * +_curses_flushinp_impl(PyObject *module); + +static PyObject * +_curses_flushinp(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_flushinp_impl(module); +} + +#if defined(getsyx) + +PyDoc_STRVAR(_curses_getsyx__doc__, +"getsyx($module, /)\n" +"--\n" +"\n" +"Return the current coordinates of the virtual screen cursor.\n" +"\n" +"Return a (y, x) tuple. If leaveok is currently true, return (-1, -1)."); + +#define _CURSES_GETSYX_METHODDEF \ + {"getsyx", (PyCFunction)_curses_getsyx, METH_NOARGS, _curses_getsyx__doc__}, + +static PyObject * +_curses_getsyx_impl(PyObject *module); + +static PyObject * +_curses_getsyx(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_getsyx_impl(module); +} + +#endif /* defined(getsyx) */ + +#if defined(NCURSES_MOUSE_VERSION) + +PyDoc_STRVAR(_curses_getmouse__doc__, +"getmouse($module, /)\n" +"--\n" +"\n" +"Retrieve the queued mouse event.\n" +"\n" +"After getch() returns KEY_MOUSE to signal a mouse event, this function\n" +"returns a 5-tuple (id, x, y, z, bstate)."); + +#define _CURSES_GETMOUSE_METHODDEF \ + {"getmouse", (PyCFunction)_curses_getmouse, METH_NOARGS, _curses_getmouse__doc__}, + +static PyObject * +_curses_getmouse_impl(PyObject *module); + +static PyObject * +_curses_getmouse(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_getmouse_impl(module); +} + +#endif /* defined(NCURSES_MOUSE_VERSION) */ + +#if defined(NCURSES_MOUSE_VERSION) + +PyDoc_STRVAR(_curses_ungetmouse__doc__, +"ungetmouse($module, id, x, y, z, bstate, /)\n" +"--\n" +"\n" +"Push a KEY_MOUSE event onto the input queue.\n" +"\n" +"The following getmouse() will return the given state data."); + +#define _CURSES_UNGETMOUSE_METHODDEF \ + {"ungetmouse", _PyCFunction_CAST(_curses_ungetmouse), METH_FASTCALL, _curses_ungetmouse__doc__}, + +static PyObject * +_curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, + unsigned long bstate); + +static PyObject * +_curses_ungetmouse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + short id; + int x; + int y; + int z; + unsigned long bstate; + + if (!_PyArg_CheckPositional("ungetmouse", nargs, 5, 5)) { + goto exit; + } + { + long ival = PyLong_AsLong(args[0]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + id = (short) ival; + } + } + x = PyLong_AsInt(args[1]); + if (x == -1 && PyErr_Occurred()) { + goto exit; + } + y = PyLong_AsInt(args[2]); + if (y == -1 && PyErr_Occurred()) { + goto exit; + } + z = PyLong_AsInt(args[3]); + if (z == -1 && PyErr_Occurred()) { + goto exit; + } + if (!PyIndex_Check(args[4])) { + _PyArg_BadArgument("ungetmouse", "argument 5", "int", args[4]); + goto exit; + } + { + Py_ssize_t _bytes = PyLong_AsNativeBytes(args[4], &bstate, sizeof(unsigned long), + Py_ASNATIVEBYTES_NATIVE_ENDIAN | + Py_ASNATIVEBYTES_ALLOW_INDEX | + Py_ASNATIVEBYTES_UNSIGNED_BUFFER); + if (_bytes < 0) { + goto exit; + } + if ((size_t)_bytes > sizeof(unsigned long)) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "integer value out of range", 1) < 0) + { + goto exit; + } + } + } + return_value = _curses_ungetmouse_impl(module, id, x, y, z, bstate); + +exit: + return return_value; +} + +#endif /* defined(NCURSES_MOUSE_VERSION) */ + +PyDoc_STRVAR(_curses_getwin__doc__, +"getwin($module, file, /)\n" +"--\n" +"\n" +"Read window related data stored in the file by an earlier putwin() call.\n" +"\n" +"The routine then creates and initializes a new window using that data,\n" +"returning the new window object."); + +#define _CURSES_GETWIN_METHODDEF \ + {"getwin", (PyCFunction)_curses_getwin, METH_O, _curses_getwin__doc__}, + +PyDoc_STRVAR(_curses_halfdelay__doc__, +"halfdelay($module, tenths, /)\n" +"--\n" +"\n" +"Enter half-delay mode.\n" +"\n" +" tenths\n" +" Maximal blocking delay in tenths of seconds (1 - 255).\n" +"\n" +"Use nocbreak() to leave half-delay mode."); + +#define _CURSES_HALFDELAY_METHODDEF \ + {"halfdelay", (PyCFunction)_curses_halfdelay, METH_O, _curses_halfdelay__doc__}, + +static PyObject * +_curses_halfdelay_impl(PyObject *module, unsigned char tenths); + +static PyObject * +_curses_halfdelay(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + unsigned char tenths; + + { + long ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < 0) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is less than minimum"); + goto exit; + } + else if (ival > UCHAR_MAX) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is greater than maximum"); + goto exit; + } + else { + tenths = (unsigned char) ival; + } + } + return_value = _curses_halfdelay_impl(module, tenths); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_has_colors__doc__, +"has_colors($module, /)\n" +"--\n" +"\n" +"Return True if the terminal can display colors; otherwise, return False."); + +#define _CURSES_HAS_COLORS_METHODDEF \ + {"has_colors", (PyCFunction)_curses_has_colors, METH_NOARGS, _curses_has_colors__doc__}, + +static PyObject * +_curses_has_colors_impl(PyObject *module); + +static PyObject * +_curses_has_colors(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_has_colors_impl(module); +} + +PyDoc_STRVAR(_curses_has_ic__doc__, +"has_ic($module, /)\n" +"--\n" +"\n" +"Return True if the terminal has insert- and delete-character capabilities."); + +#define _CURSES_HAS_IC_METHODDEF \ + {"has_ic", (PyCFunction)_curses_has_ic, METH_NOARGS, _curses_has_ic__doc__}, + +static PyObject * +_curses_has_ic_impl(PyObject *module); + +static PyObject * +_curses_has_ic(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_has_ic_impl(module); +} + +PyDoc_STRVAR(_curses_has_il__doc__, +"has_il($module, /)\n" +"--\n" +"\n" +"Return True if the terminal has insert- and delete-line capabilities."); + +#define _CURSES_HAS_IL_METHODDEF \ + {"has_il", (PyCFunction)_curses_has_il, METH_NOARGS, _curses_has_il__doc__}, + +static PyObject * +_curses_has_il_impl(PyObject *module); + +static PyObject * +_curses_has_il(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_has_il_impl(module); +} + +#if defined(HAVE_CURSES_HAS_KEY) + +PyDoc_STRVAR(_curses_has_key__doc__, +"has_key($module, key, /)\n" +"--\n" +"\n" +"Return True if the current terminal type recognizes a key with that value.\n" +"\n" +" key\n" +" Key number."); + +#define _CURSES_HAS_KEY_METHODDEF \ + {"has_key", (PyCFunction)_curses_has_key, METH_O, _curses_has_key__doc__}, + +static PyObject * +_curses_has_key_impl(PyObject *module, int key); + +static PyObject * +_curses_has_key(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int key; + + key = PyLong_AsInt(arg); + if (key == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_has_key_impl(module, key); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_HAS_KEY) */ + +PyDoc_STRVAR(_curses_init_color__doc__, +"init_color($module, color_number, r, g, b, /)\n" +"--\n" +"\n" +"Change the definition of a color.\n" +"\n" +" color_number\n" +" The number of the color to be changed (0 - (COLORS-1)).\n" +" r\n" +" Red component (0 - 1000).\n" +" g\n" +" Green component (0 - 1000).\n" +" b\n" +" Blue component (0 - 1000).\n" +"\n" +"When init_color() is used, all occurrences of that color on the screen\n" +"immediately change to the new definition. This function is a no-op on\n" +"most terminals; it is active only if can_change_color() returns true."); + +#define _CURSES_INIT_COLOR_METHODDEF \ + {"init_color", _PyCFunction_CAST(_curses_init_color), METH_FASTCALL, _curses_init_color__doc__}, + +static PyObject * +_curses_init_color_impl(PyObject *module, int color_number, short r, short g, + short b); + +static PyObject * +_curses_init_color(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int color_number; + short r; + short g; + short b; + + if (!_PyArg_CheckPositional("init_color", nargs, 4, 4)) { + goto exit; + } + if (!color_converter(args[0], &color_number)) { + goto exit; + } + if (!component_converter(args[1], &r)) { + goto exit; + } + if (!component_converter(args[2], &g)) { + goto exit; + } + if (!component_converter(args[3], &b)) { + goto exit; + } + return_value = _curses_init_color_impl(module, color_number, r, g, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_init_pair__doc__, +"init_pair($module, pair_number, fg, bg, /)\n" +"--\n" +"\n" +"Change the definition of a color-pair.\n" +"\n" +" pair_number\n" +" The number of the color-pair to be changed (1 - (COLOR_PAIRS-1)).\n" +" fg\n" +" Foreground color number (-1 - (COLORS-1)).\n" +" bg\n" +" Background color number (-1 - (COLORS-1)).\n" +"\n" +"If the color-pair was previously initialized, the screen is refreshed and\n" +"all occurrences of that color-pair are changed to the new definition."); + +#define _CURSES_INIT_PAIR_METHODDEF \ + {"init_pair", _PyCFunction_CAST(_curses_init_pair), METH_FASTCALL, _curses_init_pair__doc__}, + +static PyObject * +_curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg); + +static PyObject * +_curses_init_pair(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int pair_number; + int fg; + int bg; + + if (!_PyArg_CheckPositional("init_pair", nargs, 3, 3)) { + goto exit; + } + if (!pair_converter(args[0], &pair_number)) { + goto exit; + } + if (!color_allow_default_converter(args[1], &fg)) { + goto exit; + } + if (!color_allow_default_converter(args[2], &bg)) { + goto exit; + } + return_value = _curses_init_pair_impl(module, pair_number, fg, bg); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_initscr__doc__, +"initscr($module, /)\n" +"--\n" +"\n" +"Initialize the library.\n" +"\n" +"Return a WindowObject which represents the whole screen."); + +#define _CURSES_INITSCR_METHODDEF \ + {"initscr", (PyCFunction)_curses_initscr, METH_NOARGS, _curses_initscr__doc__}, + +static PyObject * +_curses_initscr_impl(PyObject *module); + +static PyObject * +_curses_initscr(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_initscr_impl(module); +} + +PyDoc_STRVAR(_curses_setupterm__doc__, +"setupterm($module, /, term=None, fd=-1)\n" +"--\n" +"\n" +"Initialize the terminal.\n" +"\n" +" term\n" +" Terminal name.\n" +" If omitted, the value of the TERM environment variable will be used.\n" +" fd\n" +" File descriptor to which any initialization sequences will be sent.\n" +" If not supplied, the file descriptor for sys.stdout will be used."); + +#define _CURSES_SETUPTERM_METHODDEF \ + {"setupterm", _PyCFunction_CAST(_curses_setupterm), METH_FASTCALL|METH_KEYWORDS, _curses_setupterm__doc__}, + +static PyObject * +_curses_setupterm_impl(PyObject *module, const char *term, int fd); + +static PyObject * +_curses_setupterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(term), &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"term", "fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "setupterm", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + const char *term = NULL; + int fd = -1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + if (args[0] == Py_None) { + term = NULL; + } + else if (PyUnicode_Check(args[0])) { + Py_ssize_t term_length; + term = PyUnicode_AsUTF8AndSize(args[0], &term_length); + if (term == NULL) { + goto exit; + } + if (strlen(term) != (size_t)term_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + } + else { + _PyArg_BadArgument("setupterm", "argument 'term'", "str or None", args[0]); + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + fd = PyLong_AsInt(args[1]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = _curses_setupterm_impl(module, term, fd); + +exit: + return return_value; +} + +#if (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) + +PyDoc_STRVAR(_curses_get_escdelay__doc__, +"get_escdelay($module, /)\n" +"--\n" +"\n" +"Gets the curses ESCDELAY setting.\n" +"\n" +"Gets the number of milliseconds to wait after reading an escape character,\n" +"to distinguish between an individual escape character entered on the\n" +"keyboard from escape sequences sent by cursor and function keys."); + +#define _CURSES_GET_ESCDELAY_METHODDEF \ + {"get_escdelay", (PyCFunction)_curses_get_escdelay, METH_NOARGS, _curses_get_escdelay__doc__}, + +static PyObject * +_curses_get_escdelay_impl(PyObject *module); + +static PyObject * +_curses_get_escdelay(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_get_escdelay_impl(module); +} + +#endif /* (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) */ + +#if (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) + +PyDoc_STRVAR(_curses_set_escdelay__doc__, +"set_escdelay($module, ms, /)\n" +"--\n" +"\n" +"Sets the curses ESCDELAY setting.\n" +"\n" +" ms\n" +" length of the delay in milliseconds.\n" +"\n" +"Sets the number of milliseconds to wait after reading an escape character,\n" +"to distinguish between an individual escape character entered on the\n" +"keyboard from escape sequences sent by cursor and function keys."); + +#define _CURSES_SET_ESCDELAY_METHODDEF \ + {"set_escdelay", (PyCFunction)_curses_set_escdelay, METH_O, _curses_set_escdelay__doc__}, + +static PyObject * +_curses_set_escdelay_impl(PyObject *module, int ms); + +static PyObject * +_curses_set_escdelay(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int ms; + + ms = PyLong_AsInt(arg); + if (ms == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_set_escdelay_impl(module, ms); + +exit: + return return_value; +} + +#endif /* (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) */ + +#if (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) + +PyDoc_STRVAR(_curses_get_tabsize__doc__, +"get_tabsize($module, /)\n" +"--\n" +"\n" +"Gets the curses TABSIZE setting.\n" +"\n" +"Gets the number of columns used by the curses library when converting a tab\n" +"character to spaces as it adds the tab to a window."); + +#define _CURSES_GET_TABSIZE_METHODDEF \ + {"get_tabsize", (PyCFunction)_curses_get_tabsize, METH_NOARGS, _curses_get_tabsize__doc__}, + +static PyObject * +_curses_get_tabsize_impl(PyObject *module); + +static PyObject * +_curses_get_tabsize(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_get_tabsize_impl(module); +} + +#endif /* (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) */ + +#if (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) + +PyDoc_STRVAR(_curses_set_tabsize__doc__, +"set_tabsize($module, size, /)\n" +"--\n" +"\n" +"Sets the curses TABSIZE setting.\n" +"\n" +" size\n" +" rendered cell width of a tab character.\n" +"\n" +"Sets the number of columns used by the curses library when converting a tab\n" +"character to spaces as it adds the tab to a window."); + +#define _CURSES_SET_TABSIZE_METHODDEF \ + {"set_tabsize", (PyCFunction)_curses_set_tabsize, METH_O, _curses_set_tabsize__doc__}, + +static PyObject * +_curses_set_tabsize_impl(PyObject *module, int size); + +static PyObject * +_curses_set_tabsize(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int size; + + size = PyLong_AsInt(arg); + if (size == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_set_tabsize_impl(module, size); + +exit: + return return_value; +} + +#endif /* (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) */ + +PyDoc_STRVAR(_curses_intrflush__doc__, +"intrflush($module, flag, /)\n" +"--\n" +"\n"); + +#define _CURSES_INTRFLUSH_METHODDEF \ + {"intrflush", (PyCFunction)_curses_intrflush, METH_O, _curses_intrflush__doc__}, + +static PyObject * +_curses_intrflush_impl(PyObject *module, int flag); + +static PyObject * +_curses_intrflush(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int flag; + + flag = PyObject_IsTrue(arg); + if (flag < 0) { + goto exit; + } + return_value = _curses_intrflush_impl(module, flag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_isendwin__doc__, +"isendwin($module, /)\n" +"--\n" +"\n" +"Return True if endwin() has been called."); + +#define _CURSES_ISENDWIN_METHODDEF \ + {"isendwin", (PyCFunction)_curses_isendwin, METH_NOARGS, _curses_isendwin__doc__}, + +static PyObject * +_curses_isendwin_impl(PyObject *module); + +static PyObject * +_curses_isendwin(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_isendwin_impl(module); +} + +#if defined(HAVE_CURSES_IS_TERM_RESIZED) + +PyDoc_STRVAR(_curses_is_term_resized__doc__, +"is_term_resized($module, nlines, ncols, /)\n" +"--\n" +"\n" +"Return True if resize_term() would modify the window structure, False otherwise.\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width."); + +#define _CURSES_IS_TERM_RESIZED_METHODDEF \ + {"is_term_resized", _PyCFunction_CAST(_curses_is_term_resized), METH_FASTCALL, _curses_is_term_resized__doc__}, + +static PyObject * +_curses_is_term_resized_impl(PyObject *module, int nlines, int ncols); + +static PyObject * +_curses_is_term_resized(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int nlines; + int ncols; + + if (!_PyArg_CheckPositional("is_term_resized", nargs, 2, 2)) { + goto exit; + } + nlines = PyLong_AsInt(args[0]); + if (nlines == -1 && PyErr_Occurred()) { + goto exit; + } + ncols = PyLong_AsInt(args[1]); + if (ncols == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_is_term_resized_impl(module, nlines, ncols); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_IS_TERM_RESIZED) */ + +PyDoc_STRVAR(_curses_keyname__doc__, +"keyname($module, key, /)\n" +"--\n" +"\n" +"Return the name of specified key.\n" +"\n" +" key\n" +" Key number."); + +#define _CURSES_KEYNAME_METHODDEF \ + {"keyname", (PyCFunction)_curses_keyname, METH_O, _curses_keyname__doc__}, + +static PyObject * +_curses_keyname_impl(PyObject *module, int key); + +static PyObject * +_curses_keyname(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int key; + + key = PyLong_AsInt(arg); + if (key == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_keyname_impl(module, key); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_killchar__doc__, +"killchar($module, /)\n" +"--\n" +"\n" +"Return the user\'s current line kill character."); + +#define _CURSES_KILLCHAR_METHODDEF \ + {"killchar", (PyCFunction)_curses_killchar, METH_NOARGS, _curses_killchar__doc__}, + +static PyObject * +_curses_killchar_impl(PyObject *module); + +static PyObject * +_curses_killchar(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_killchar_impl(module); +} + +PyDoc_STRVAR(_curses_longname__doc__, +"longname($module, /)\n" +"--\n" +"\n" +"Return the terminfo long name field describing the current terminal.\n" +"\n" +"The maximum length of a verbose description is 128 characters. It is defined\n" +"only after the call to initscr()."); + +#define _CURSES_LONGNAME_METHODDEF \ + {"longname", (PyCFunction)_curses_longname, METH_NOARGS, _curses_longname__doc__}, + +static PyObject * +_curses_longname_impl(PyObject *module); + +static PyObject * +_curses_longname(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_longname_impl(module); +} + +PyDoc_STRVAR(_curses_meta__doc__, +"meta($module, yes, /)\n" +"--\n" +"\n" +"Enable/disable meta keys.\n" +"\n" +"If yes is True, allow 8-bit characters to be input. If yes is False,\n" +"allow only 7-bit characters."); + +#define _CURSES_META_METHODDEF \ + {"meta", (PyCFunction)_curses_meta, METH_O, _curses_meta__doc__}, + +static PyObject * +_curses_meta_impl(PyObject *module, int yes); + +static PyObject * +_curses_meta(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int yes; + + yes = PyObject_IsTrue(arg); + if (yes < 0) { + goto exit; + } + return_value = _curses_meta_impl(module, yes); + +exit: + return return_value; +} + +#if defined(NCURSES_MOUSE_VERSION) + +PyDoc_STRVAR(_curses_mouseinterval__doc__, +"mouseinterval($module, interval, /)\n" +"--\n" +"\n" +"Set and retrieve the maximum time between press and release in a click.\n" +"\n" +" interval\n" +" Time in milliseconds.\n" +"\n" +"Set the maximum time that can elapse between press and release events in\n" +"order for them to be recognized as a click, and return the previous interval\n" +"value."); + +#define _CURSES_MOUSEINTERVAL_METHODDEF \ + {"mouseinterval", (PyCFunction)_curses_mouseinterval, METH_O, _curses_mouseinterval__doc__}, + +static PyObject * +_curses_mouseinterval_impl(PyObject *module, int interval); + +static PyObject * +_curses_mouseinterval(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int interval; + + interval = PyLong_AsInt(arg); + if (interval == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_mouseinterval_impl(module, interval); + +exit: + return return_value; +} + +#endif /* defined(NCURSES_MOUSE_VERSION) */ + +#if defined(NCURSES_MOUSE_VERSION) + +PyDoc_STRVAR(_curses_mousemask__doc__, +"mousemask($module, newmask, /)\n" +"--\n" +"\n" +"Set the mouse events to be reported, and return a tuple (availmask, oldmask).\n" +"\n" +"Return a tuple (availmask, oldmask). availmask indicates which of the\n" +"specified mouse events can be reported; on complete failure it returns 0.\n" +"oldmask is the previous value of the given window\'s mouse event mask.\n" +"If this function is never called, no mouse events are ever reported."); + +#define _CURSES_MOUSEMASK_METHODDEF \ + {"mousemask", (PyCFunction)_curses_mousemask, METH_O, _curses_mousemask__doc__}, + +static PyObject * +_curses_mousemask_impl(PyObject *module, unsigned long newmask); + +static PyObject * +_curses_mousemask(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + unsigned long newmask; + + if (!PyIndex_Check(arg)) { + _PyArg_BadArgument("mousemask", "argument", "int", arg); + goto exit; + } + { + Py_ssize_t _bytes = PyLong_AsNativeBytes(arg, &newmask, sizeof(unsigned long), + Py_ASNATIVEBYTES_NATIVE_ENDIAN | + Py_ASNATIVEBYTES_ALLOW_INDEX | + Py_ASNATIVEBYTES_UNSIGNED_BUFFER); + if (_bytes < 0) { + goto exit; + } + if ((size_t)_bytes > sizeof(unsigned long)) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "integer value out of range", 1) < 0) + { + goto exit; + } + } + } + return_value = _curses_mousemask_impl(module, newmask); + +exit: + return return_value; +} + +#endif /* defined(NCURSES_MOUSE_VERSION) */ + +PyDoc_STRVAR(_curses_napms__doc__, +"napms($module, ms, /)\n" +"--\n" +"\n" +"Sleep for specified time.\n" +"\n" +" ms\n" +" Duration in milliseconds."); + +#define _CURSES_NAPMS_METHODDEF \ + {"napms", (PyCFunction)_curses_napms, METH_O, _curses_napms__doc__}, + +static int +_curses_napms_impl(PyObject *module, int ms); + +static PyObject * +_curses_napms(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int ms; + int _return_value; + + ms = PyLong_AsInt(arg); + if (ms == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = _curses_napms_impl(module, ms); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_newpad__doc__, +"newpad($module, nlines, ncols, /)\n" +"--\n" +"\n" +"Create and return a pointer to a new pad data structure.\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width."); + +#define _CURSES_NEWPAD_METHODDEF \ + {"newpad", _PyCFunction_CAST(_curses_newpad), METH_FASTCALL, _curses_newpad__doc__}, + +static PyObject * +_curses_newpad_impl(PyObject *module, int nlines, int ncols); + +static PyObject * +_curses_newpad(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int nlines; + int ncols; + + if (!_PyArg_CheckPositional("newpad", nargs, 2, 2)) { + goto exit; + } + nlines = PyLong_AsInt(args[0]); + if (nlines == -1 && PyErr_Occurred()) { + goto exit; + } + ncols = PyLong_AsInt(args[1]); + if (ncols == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_newpad_impl(module, nlines, ncols); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_newwin__doc__, +"newwin(nlines, ncols, [begin_y=0, begin_x=0])\n" +"Return a new window.\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width.\n" +" begin_y\n" +" Top side y-coordinate.\n" +" begin_x\n" +" Left side x-coordinate.\n" +"\n" +"By default, the window will extend from the specified position to the lower\n" +"right corner of the screen."); + +#define _CURSES_NEWWIN_METHODDEF \ + {"newwin", (PyCFunction)_curses_newwin, METH_VARARGS, _curses_newwin__doc__}, + +static PyObject * +_curses_newwin_impl(PyObject *module, int nlines, int ncols, + int group_right_1, int begin_y, int begin_x); + +static PyObject * +_curses_newwin(PyObject *module, PyObject *args) +{ + PyObject *return_value = NULL; + int nlines; + int ncols; + int group_right_1 = 0; + int begin_y = 0; + int begin_x = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "ii:newwin", &nlines, &ncols)) { + goto exit; + } + break; + case 4: + if (!PyArg_ParseTuple(args, "iiii:newwin", &nlines, &ncols, &begin_y, &begin_x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.newwin requires 2 to 4 arguments"); + goto exit; + } + return_value = _curses_newwin_impl(module, nlines, ncols, group_right_1, begin_y, begin_x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_nl__doc__, +"nl($module, flag=True, /)\n" +"--\n" +"\n" +"Enter newline mode.\n" +"\n" +" flag\n" +" If false, the effect is the same as calling nonl().\n" +"\n" +"This mode translates the return key into newline on input, and translates\n" +"newline into return and line-feed on output. Newline mode is initially on."); + +#define _CURSES_NL_METHODDEF \ + {"nl", _PyCFunction_CAST(_curses_nl), METH_FASTCALL, _curses_nl__doc__}, + +static PyObject * +_curses_nl_impl(PyObject *module, int flag); + +static PyObject * +_curses_nl(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int flag = 1; + + if (!_PyArg_CheckPositional("nl", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + flag = PyObject_IsTrue(args[0]); + if (flag < 0) { + goto exit; + } +skip_optional: + return_value = _curses_nl_impl(module, flag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_nocbreak__doc__, +"nocbreak($module, /)\n" +"--\n" +"\n" +"Leave cbreak mode.\n" +"\n" +"Return to normal \"cooked\" mode with line buffering."); + +#define _CURSES_NOCBREAK_METHODDEF \ + {"nocbreak", (PyCFunction)_curses_nocbreak, METH_NOARGS, _curses_nocbreak__doc__}, + +static PyObject * +_curses_nocbreak_impl(PyObject *module); + +static PyObject * +_curses_nocbreak(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_nocbreak_impl(module); +} + +PyDoc_STRVAR(_curses_noecho__doc__, +"noecho($module, /)\n" +"--\n" +"\n" +"Leave echo mode.\n" +"\n" +"Echoing of input characters is turned off."); + +#define _CURSES_NOECHO_METHODDEF \ + {"noecho", (PyCFunction)_curses_noecho, METH_NOARGS, _curses_noecho__doc__}, + +static PyObject * +_curses_noecho_impl(PyObject *module); + +static PyObject * +_curses_noecho(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_noecho_impl(module); +} + +PyDoc_STRVAR(_curses_nonl__doc__, +"nonl($module, /)\n" +"--\n" +"\n" +"Leave newline mode.\n" +"\n" +"Disable translation of return into newline on input, and disable low-level\n" +"translation of newline into newline/return on output."); + +#define _CURSES_NONL_METHODDEF \ + {"nonl", (PyCFunction)_curses_nonl, METH_NOARGS, _curses_nonl__doc__}, + +static PyObject * +_curses_nonl_impl(PyObject *module); + +static PyObject * +_curses_nonl(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_nonl_impl(module); +} + +PyDoc_STRVAR(_curses_noqiflush__doc__, +"noqiflush($module, /)\n" +"--\n" +"\n" +"Disable queue flushing.\n" +"\n" +"When queue flushing is disabled, normal flush of input and output queues\n" +"associated with the INTR, QUIT and SUSP characters will not be done."); + +#define _CURSES_NOQIFLUSH_METHODDEF \ + {"noqiflush", (PyCFunction)_curses_noqiflush, METH_NOARGS, _curses_noqiflush__doc__}, + +static PyObject * +_curses_noqiflush_impl(PyObject *module); + +static PyObject * +_curses_noqiflush(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_noqiflush_impl(module); +} + +PyDoc_STRVAR(_curses_noraw__doc__, +"noraw($module, /)\n" +"--\n" +"\n" +"Leave raw mode.\n" +"\n" +"Return to normal \"cooked\" mode with line buffering."); + +#define _CURSES_NORAW_METHODDEF \ + {"noraw", (PyCFunction)_curses_noraw, METH_NOARGS, _curses_noraw__doc__}, + +static PyObject * +_curses_noraw_impl(PyObject *module); + +static PyObject * +_curses_noraw(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_noraw_impl(module); +} + +PyDoc_STRVAR(_curses_pair_content__doc__, +"pair_content($module, pair_number, /)\n" +"--\n" +"\n" +"Return a tuple (fg, bg) containing the colors for the requested color pair.\n" +"\n" +" pair_number\n" +" The number of the color pair (0 - (COLOR_PAIRS-1))."); + +#define _CURSES_PAIR_CONTENT_METHODDEF \ + {"pair_content", (PyCFunction)_curses_pair_content, METH_O, _curses_pair_content__doc__}, + +static PyObject * +_curses_pair_content_impl(PyObject *module, int pair_number); + +static PyObject * +_curses_pair_content(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int pair_number; + + if (!pair_converter(arg, &pair_number)) { + goto exit; + } + return_value = _curses_pair_content_impl(module, pair_number); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_pair_number__doc__, +"pair_number($module, attr, /)\n" +"--\n" +"\n" +"Return the number of the color-pair set by the specified attribute value.\n" +"\n" +"color_pair() is the counterpart to this function."); + +#define _CURSES_PAIR_NUMBER_METHODDEF \ + {"pair_number", (PyCFunction)_curses_pair_number, METH_O, _curses_pair_number__doc__}, + +static PyObject * +_curses_pair_number_impl(PyObject *module, int attr); + +static PyObject * +_curses_pair_number(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int attr; + + attr = PyLong_AsInt(arg); + if (attr == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_pair_number_impl(module, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_putp__doc__, +"putp($module, string, /)\n" +"--\n" +"\n" +"Emit the value of a specified terminfo capability for the current terminal.\n" +"\n" +"Note that the output of putp() always goes to standard output."); + +#define _CURSES_PUTP_METHODDEF \ + {"putp", (PyCFunction)_curses_putp, METH_O, _curses_putp__doc__}, + +static PyObject * +_curses_putp_impl(PyObject *module, const char *string); + +static PyObject * +_curses_putp(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *string; + + if (!PyArg_Parse(arg, "y:putp", &string)) { + goto exit; + } + return_value = _curses_putp_impl(module, string); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_qiflush__doc__, +"qiflush($module, flag=True, /)\n" +"--\n" +"\n" +"Enable queue flushing.\n" +"\n" +" flag\n" +" If false, the effect is the same as calling noqiflush().\n" +"\n" +"If queue flushing is enabled, all output in the display driver queue\n" +"will be flushed when the INTR, QUIT and SUSP characters are read."); + +#define _CURSES_QIFLUSH_METHODDEF \ + {"qiflush", _PyCFunction_CAST(_curses_qiflush), METH_FASTCALL, _curses_qiflush__doc__}, + +static PyObject * +_curses_qiflush_impl(PyObject *module, int flag); + +static PyObject * +_curses_qiflush(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int flag = 1; + + if (!_PyArg_CheckPositional("qiflush", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + flag = PyObject_IsTrue(args[0]); + if (flag < 0) { + goto exit; + } +skip_optional: + return_value = _curses_qiflush_impl(module, flag); + +exit: + return return_value; +} + +#if (defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)) + +PyDoc_STRVAR(_curses_update_lines_cols__doc__, +"update_lines_cols($module, /)\n" +"--\n" +"\n"); + +#define _CURSES_UPDATE_LINES_COLS_METHODDEF \ + {"update_lines_cols", (PyCFunction)_curses_update_lines_cols, METH_NOARGS, _curses_update_lines_cols__doc__}, + +static PyObject * +_curses_update_lines_cols_impl(PyObject *module); + +static PyObject * +_curses_update_lines_cols(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_update_lines_cols_impl(module); +} + +#endif /* (defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)) */ + +PyDoc_STRVAR(_curses_raw__doc__, +"raw($module, flag=True, /)\n" +"--\n" +"\n" +"Enter raw mode.\n" +"\n" +" flag\n" +" If false, the effect is the same as calling noraw().\n" +"\n" +"In raw mode, normal line buffering and processing of interrupt, quit,\n" +"suspend, and flow control keys are turned off; characters are presented to\n" +"curses input functions one by one."); + +#define _CURSES_RAW_METHODDEF \ + {"raw", _PyCFunction_CAST(_curses_raw), METH_FASTCALL, _curses_raw__doc__}, + +static PyObject * +_curses_raw_impl(PyObject *module, int flag); + +static PyObject * +_curses_raw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int flag = 1; + + if (!_PyArg_CheckPositional("raw", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + flag = PyObject_IsTrue(args[0]); + if (flag < 0) { + goto exit; + } +skip_optional: + return_value = _curses_raw_impl(module, flag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_reset_prog_mode__doc__, +"reset_prog_mode($module, /)\n" +"--\n" +"\n" +"Restore the terminal to \"program\" mode, as previously saved by def_prog_mode()."); + +#define _CURSES_RESET_PROG_MODE_METHODDEF \ + {"reset_prog_mode", (PyCFunction)_curses_reset_prog_mode, METH_NOARGS, _curses_reset_prog_mode__doc__}, + +static PyObject * +_curses_reset_prog_mode_impl(PyObject *module); + +static PyObject * +_curses_reset_prog_mode(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_reset_prog_mode_impl(module); +} + +PyDoc_STRVAR(_curses_reset_shell_mode__doc__, +"reset_shell_mode($module, /)\n" +"--\n" +"\n" +"Restore the terminal to \"shell\" mode, as previously saved by def_shell_mode()."); + +#define _CURSES_RESET_SHELL_MODE_METHODDEF \ + {"reset_shell_mode", (PyCFunction)_curses_reset_shell_mode, METH_NOARGS, _curses_reset_shell_mode__doc__}, + +static PyObject * +_curses_reset_shell_mode_impl(PyObject *module); + +static PyObject * +_curses_reset_shell_mode(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_reset_shell_mode_impl(module); +} + +PyDoc_STRVAR(_curses_resetty__doc__, +"resetty($module, /)\n" +"--\n" +"\n" +"Restore terminal mode."); + +#define _CURSES_RESETTY_METHODDEF \ + {"resetty", (PyCFunction)_curses_resetty, METH_NOARGS, _curses_resetty__doc__}, + +static PyObject * +_curses_resetty_impl(PyObject *module); + +static PyObject * +_curses_resetty(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_resetty_impl(module); +} + +#if defined(HAVE_CURSES_RESIZETERM) + +PyDoc_STRVAR(_curses_resizeterm__doc__, +"resizeterm($module, nlines, ncols, /)\n" +"--\n" +"\n" +"Resize the standard and current windows to the specified dimensions.\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width.\n" +"\n" +"Adjusts other bookkeeping data used by the curses library that record the\n" +"window dimensions (in particular the SIGWINCH handler)."); + +#define _CURSES_RESIZETERM_METHODDEF \ + {"resizeterm", _PyCFunction_CAST(_curses_resizeterm), METH_FASTCALL, _curses_resizeterm__doc__}, + +static PyObject * +_curses_resizeterm_impl(PyObject *module, short nlines, short ncols); + +static PyObject * +_curses_resizeterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + short nlines; + short ncols; + + if (!_PyArg_CheckPositional("resizeterm", nargs, 2, 2)) { + goto exit; + } + { + long ival = PyLong_AsLong(args[0]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + nlines = (short) ival; + } + } + { + long ival = PyLong_AsLong(args[1]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + ncols = (short) ival; + } + } + return_value = _curses_resizeterm_impl(module, nlines, ncols); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_RESIZETERM) */ + +#if defined(HAVE_CURSES_RESIZE_TERM) + +PyDoc_STRVAR(_curses_resize_term__doc__, +"resize_term($module, nlines, ncols, /)\n" +"--\n" +"\n" +"Backend function used by resizeterm(), performing most of the work.\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width.\n" +"\n" +"When resizing the windows, resize_term() blank-fills the areas that are\n" +"extended. The calling application should fill in these areas with appropriate\n" +"data. The resize_term() function attempts to resize all windows. However,\n" +"due to the calling convention of pads, it is not possible to resize these\n" +"without additional interaction with the application."); + +#define _CURSES_RESIZE_TERM_METHODDEF \ + {"resize_term", _PyCFunction_CAST(_curses_resize_term), METH_FASTCALL, _curses_resize_term__doc__}, + +static PyObject * +_curses_resize_term_impl(PyObject *module, short nlines, short ncols); + +static PyObject * +_curses_resize_term(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + short nlines; + short ncols; + + if (!_PyArg_CheckPositional("resize_term", nargs, 2, 2)) { + goto exit; + } + { + long ival = PyLong_AsLong(args[0]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + nlines = (short) ival; + } + } + { + long ival = PyLong_AsLong(args[1]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + ncols = (short) ival; + } + } + return_value = _curses_resize_term_impl(module, nlines, ncols); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_RESIZE_TERM) */ + +PyDoc_STRVAR(_curses_savetty__doc__, +"savetty($module, /)\n" +"--\n" +"\n" +"Save terminal mode."); + +#define _CURSES_SAVETTY_METHODDEF \ + {"savetty", (PyCFunction)_curses_savetty, METH_NOARGS, _curses_savetty__doc__}, + +static PyObject * +_curses_savetty_impl(PyObject *module); + +static PyObject * +_curses_savetty(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_savetty_impl(module); +} + +#if defined(getsyx) + +PyDoc_STRVAR(_curses_setsyx__doc__, +"setsyx($module, y, x, /)\n" +"--\n" +"\n" +"Set the virtual screen cursor.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +"\n" +"If y and x are both -1, then leaveok is set."); + +#define _CURSES_SETSYX_METHODDEF \ + {"setsyx", _PyCFunction_CAST(_curses_setsyx), METH_FASTCALL, _curses_setsyx__doc__}, + +static PyObject * +_curses_setsyx_impl(PyObject *module, int y, int x); + +static PyObject * +_curses_setsyx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int y; + int x; + + if (!_PyArg_CheckPositional("setsyx", nargs, 2, 2)) { + goto exit; + } + y = PyLong_AsInt(args[0]); + if (y == -1 && PyErr_Occurred()) { + goto exit; + } + x = PyLong_AsInt(args[1]); + if (x == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_setsyx_impl(module, y, x); + +exit: + return return_value; +} + +#endif /* defined(getsyx) */ + +PyDoc_STRVAR(_curses_start_color__doc__, +"start_color($module, /)\n" +"--\n" +"\n" +"Initializes eight basic colors and global variables COLORS and COLOR_PAIRS.\n" +"\n" +"Must be called if the programmer wants to use colors, and before any other\n" +"color manipulation routine is called. It is good practice to call this\n" +"routine right after initscr().\n" +"\n" +"It also restores the colors on the terminal to the values they had when the\n" +"terminal was just turned on."); + +#define _CURSES_START_COLOR_METHODDEF \ + {"start_color", (PyCFunction)_curses_start_color, METH_NOARGS, _curses_start_color__doc__}, + +static PyObject * +_curses_start_color_impl(PyObject *module); + +static PyObject * +_curses_start_color(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_start_color_impl(module); +} + +PyDoc_STRVAR(_curses_termattrs__doc__, +"termattrs($module, /)\n" +"--\n" +"\n" +"Return a logical OR of all video attributes supported by the terminal."); + +#define _CURSES_TERMATTRS_METHODDEF \ + {"termattrs", (PyCFunction)_curses_termattrs, METH_NOARGS, _curses_termattrs__doc__}, + +static PyObject * +_curses_termattrs_impl(PyObject *module); + +static PyObject * +_curses_termattrs(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_termattrs_impl(module); +} + +PyDoc_STRVAR(_curses_termname__doc__, +"termname($module, /)\n" +"--\n" +"\n" +"Return the value of the environment variable TERM, truncated to 14 characters."); + +#define _CURSES_TERMNAME_METHODDEF \ + {"termname", (PyCFunction)_curses_termname, METH_NOARGS, _curses_termname__doc__}, + +static PyObject * +_curses_termname_impl(PyObject *module); + +static PyObject * +_curses_termname(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_termname_impl(module); +} + +PyDoc_STRVAR(_curses_tigetflag__doc__, +"tigetflag($module, capname, /)\n" +"--\n" +"\n" +"Return the value of the Boolean capability.\n" +"\n" +" capname\n" +" The terminfo capability name.\n" +"\n" +"The value -1 is returned if capname is not a Boolean capability, or 0 if\n" +"it is canceled or absent from the terminal description."); + +#define _CURSES_TIGETFLAG_METHODDEF \ + {"tigetflag", (PyCFunction)_curses_tigetflag, METH_O, _curses_tigetflag__doc__}, + +static PyObject * +_curses_tigetflag_impl(PyObject *module, const char *capname); + +static PyObject * +_curses_tigetflag(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *capname; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("tigetflag", "argument", "str", arg); + goto exit; + } + Py_ssize_t capname_length; + capname = PyUnicode_AsUTF8AndSize(arg, &capname_length); + if (capname == NULL) { + goto exit; + } + if (strlen(capname) != (size_t)capname_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = _curses_tigetflag_impl(module, capname); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_tigetnum__doc__, +"tigetnum($module, capname, /)\n" +"--\n" +"\n" +"Return the value of the numeric capability.\n" +"\n" +" capname\n" +" The terminfo capability name.\n" +"\n" +"The value -2 is returned if capname is not a numeric capability, or -1 if\n" +"it is canceled or absent from the terminal description."); + +#define _CURSES_TIGETNUM_METHODDEF \ + {"tigetnum", (PyCFunction)_curses_tigetnum, METH_O, _curses_tigetnum__doc__}, + +static PyObject * +_curses_tigetnum_impl(PyObject *module, const char *capname); + +static PyObject * +_curses_tigetnum(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *capname; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("tigetnum", "argument", "str", arg); + goto exit; + } + Py_ssize_t capname_length; + capname = PyUnicode_AsUTF8AndSize(arg, &capname_length); + if (capname == NULL) { + goto exit; + } + if (strlen(capname) != (size_t)capname_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = _curses_tigetnum_impl(module, capname); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_tigetstr__doc__, +"tigetstr($module, capname, /)\n" +"--\n" +"\n" +"Return the value of the string capability.\n" +"\n" +" capname\n" +" The terminfo capability name.\n" +"\n" +"None is returned if capname is not a string capability, or is canceled or\n" +"absent from the terminal description."); + +#define _CURSES_TIGETSTR_METHODDEF \ + {"tigetstr", (PyCFunction)_curses_tigetstr, METH_O, _curses_tigetstr__doc__}, + +static PyObject * +_curses_tigetstr_impl(PyObject *module, const char *capname); + +static PyObject * +_curses_tigetstr(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *capname; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("tigetstr", "argument", "str", arg); + goto exit; + } + Py_ssize_t capname_length; + capname = PyUnicode_AsUTF8AndSize(arg, &capname_length); + if (capname == NULL) { + goto exit; + } + if (strlen(capname) != (size_t)capname_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = _curses_tigetstr_impl(module, capname); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_tparm__doc__, +"tparm($module, str, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0,\n" +" i9=0, /)\n" +"--\n" +"\n" +"Instantiate the specified byte string with the supplied parameters.\n" +"\n" +" str\n" +" Parameterized byte string obtained from the terminfo database."); + +#define _CURSES_TPARM_METHODDEF \ + {"tparm", _PyCFunction_CAST(_curses_tparm), METH_FASTCALL, _curses_tparm__doc__}, + +static PyObject * +_curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, + int i4, int i5, int i6, int i7, int i8, int i9); + +static PyObject * +_curses_tparm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *str; + int i1 = 0; + int i2 = 0; + int i3 = 0; + int i4 = 0; + int i5 = 0; + int i6 = 0; + int i7 = 0; + int i8 = 0; + int i9 = 0; + + if (!_PyArg_ParseStack(args, nargs, "y|iiiiiiiii:tparm", + &str, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8, &i9)) { + goto exit; + } + return_value = _curses_tparm_impl(module, str, i1, i2, i3, i4, i5, i6, i7, i8, i9); + +exit: + return return_value; +} + +#if defined(HAVE_CURSES_TYPEAHEAD) + +PyDoc_STRVAR(_curses_typeahead__doc__, +"typeahead($module, fd, /)\n" +"--\n" +"\n" +"Specify that the file descriptor fd be used for typeahead checking.\n" +"\n" +" fd\n" +" File descriptor.\n" +"\n" +"If fd is -1, then no typeahead checking is done."); + +#define _CURSES_TYPEAHEAD_METHODDEF \ + {"typeahead", (PyCFunction)_curses_typeahead, METH_O, _curses_typeahead__doc__}, + +static PyObject * +_curses_typeahead_impl(PyObject *module, int fd); + +static PyObject * +_curses_typeahead(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + fd = PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_typeahead_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_TYPEAHEAD) */ + +PyDoc_STRVAR(_curses_unctrl__doc__, +"unctrl($module, ch, /)\n" +"--\n" +"\n" +"Return a string which is a printable representation of the character ch.\n" +"\n" +"Control characters are displayed as a caret followed by the character,\n" +"for example as ^C. Printing characters are left as they are."); + +#define _CURSES_UNCTRL_METHODDEF \ + {"unctrl", (PyCFunction)_curses_unctrl, METH_O, _curses_unctrl__doc__}, + +PyDoc_STRVAR(_curses_ungetch__doc__, +"ungetch($module, ch, /)\n" +"--\n" +"\n" +"Push ch so the next getch() will return it."); + +#define _CURSES_UNGETCH_METHODDEF \ + {"ungetch", (PyCFunction)_curses_ungetch, METH_O, _curses_ungetch__doc__}, + +#if defined(HAVE_NCURSESW) + +PyDoc_STRVAR(_curses_unget_wch__doc__, +"unget_wch($module, ch, /)\n" +"--\n" +"\n" +"Push ch so the next get_wch() will return it."); + +#define _CURSES_UNGET_WCH_METHODDEF \ + {"unget_wch", (PyCFunction)_curses_unget_wch, METH_O, _curses_unget_wch__doc__}, + +#endif /* defined(HAVE_NCURSESW) */ + +#if defined(HAVE_CURSES_USE_ENV) + +PyDoc_STRVAR(_curses_use_env__doc__, +"use_env($module, flag, /)\n" +"--\n" +"\n" +"Use environment variables LINES and COLUMNS.\n" +"\n" +"If used, this function should be called before initscr() or newterm() are\n" +"called.\n" +"\n" +"When flag is False, the values of lines and columns specified in the terminfo\n" +"database will be used, even if environment variables LINES and COLUMNS (used\n" +"by default) are set, or if curses is running in a window (in which case\n" +"default behavior would be to use the window size if LINES and COLUMNS are\n" +"not set)."); + +#define _CURSES_USE_ENV_METHODDEF \ + {"use_env", (PyCFunction)_curses_use_env, METH_O, _curses_use_env__doc__}, + +static PyObject * +_curses_use_env_impl(PyObject *module, int flag); + +static PyObject * +_curses_use_env(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int flag; + + flag = PyObject_IsTrue(arg); + if (flag < 0) { + goto exit; + } + return_value = _curses_use_env_impl(module, flag); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_USE_ENV) */ + +#if !defined(STRICT_SYSV_CURSES) + +PyDoc_STRVAR(_curses_use_default_colors__doc__, +"use_default_colors($module, /)\n" +"--\n" +"\n" +"Equivalent to assume_default_colors(-1, -1)."); + +#define _CURSES_USE_DEFAULT_COLORS_METHODDEF \ + {"use_default_colors", (PyCFunction)_curses_use_default_colors, METH_NOARGS, _curses_use_default_colors__doc__}, + +static PyObject * +_curses_use_default_colors_impl(PyObject *module); + +static PyObject * +_curses_use_default_colors(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_use_default_colors_impl(module); +} + +#endif /* !defined(STRICT_SYSV_CURSES) */ + +#if !defined(STRICT_SYSV_CURSES) + +PyDoc_STRVAR(_curses_assume_default_colors__doc__, +"assume_default_colors($module, fg, bg, /)\n" +"--\n" +"\n" +"Allow use of default values for colors on terminals supporting this feature.\n" +"\n" +"Assign terminal default foreground/background colors to color number -1.\n" +"Change the definition of the color-pair 0 to (fg, bg).\n" +"\n" +"Use this to support transparency in your application."); + +#define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF \ + {"assume_default_colors", _PyCFunction_CAST(_curses_assume_default_colors), METH_FASTCALL, _curses_assume_default_colors__doc__}, + +static PyObject * +_curses_assume_default_colors_impl(PyObject *module, int fg, int bg); + +static PyObject * +_curses_assume_default_colors(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fg; + int bg; + + if (!_PyArg_CheckPositional("assume_default_colors", nargs, 2, 2)) { + goto exit; + } + fg = PyLong_AsInt(args[0]); + if (fg == -1 && PyErr_Occurred()) { + goto exit; + } + bg = PyLong_AsInt(args[1]); + if (bg == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_assume_default_colors_impl(module, fg, bg); + +exit: + return return_value; +} + +#endif /* !defined(STRICT_SYSV_CURSES) */ + +PyDoc_STRVAR(_curses_has_extended_color_support__doc__, +"has_extended_color_support($module, /)\n" +"--\n" +"\n" +"Return True if the module supports extended colors; otherwise, return False.\n" +"\n" +"Extended color support allows more than 256 color-pairs for terminals\n" +"that support more than 16 colors (e.g. xterm-256color)."); + +#define _CURSES_HAS_EXTENDED_COLOR_SUPPORT_METHODDEF \ + {"has_extended_color_support", (PyCFunction)_curses_has_extended_color_support, METH_NOARGS, _curses_has_extended_color_support__doc__}, + +static PyObject * +_curses_has_extended_color_support_impl(PyObject *module); + +static PyObject * +_curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_has_extended_color_support_impl(module); +} + +#ifndef _CURSES_WINDOW_ENCLOSE_METHODDEF + #define _CURSES_WINDOW_ENCLOSE_METHODDEF +#endif /* !defined(_CURSES_WINDOW_ENCLOSE_METHODDEF) */ + +#ifndef _CURSES_WINDOW_GET_WCH_METHODDEF + #define _CURSES_WINDOW_GET_WCH_METHODDEF +#endif /* !defined(_CURSES_WINDOW_GET_WCH_METHODDEF) */ + +#ifndef _CURSES_WINDOW_NOUTREFRESH_METHODDEF + #define _CURSES_WINDOW_NOUTREFRESH_METHODDEF +#endif /* !defined(_CURSES_WINDOW_NOUTREFRESH_METHODDEF) */ + +#ifndef _CURSES_FILTER_METHODDEF + #define _CURSES_FILTER_METHODDEF +#endif /* !defined(_CURSES_FILTER_METHODDEF) */ + +#ifndef _CURSES_GETSYX_METHODDEF + #define _CURSES_GETSYX_METHODDEF +#endif /* !defined(_CURSES_GETSYX_METHODDEF) */ + +#ifndef _CURSES_GETMOUSE_METHODDEF + #define _CURSES_GETMOUSE_METHODDEF +#endif /* !defined(_CURSES_GETMOUSE_METHODDEF) */ + +#ifndef _CURSES_UNGETMOUSE_METHODDEF + #define _CURSES_UNGETMOUSE_METHODDEF +#endif /* !defined(_CURSES_UNGETMOUSE_METHODDEF) */ + +#ifndef _CURSES_HAS_KEY_METHODDEF + #define _CURSES_HAS_KEY_METHODDEF +#endif /* !defined(_CURSES_HAS_KEY_METHODDEF) */ + +#ifndef _CURSES_GET_ESCDELAY_METHODDEF + #define _CURSES_GET_ESCDELAY_METHODDEF +#endif /* !defined(_CURSES_GET_ESCDELAY_METHODDEF) */ + +#ifndef _CURSES_SET_ESCDELAY_METHODDEF + #define _CURSES_SET_ESCDELAY_METHODDEF +#endif /* !defined(_CURSES_SET_ESCDELAY_METHODDEF) */ + +#ifndef _CURSES_GET_TABSIZE_METHODDEF + #define _CURSES_GET_TABSIZE_METHODDEF +#endif /* !defined(_CURSES_GET_TABSIZE_METHODDEF) */ + +#ifndef _CURSES_SET_TABSIZE_METHODDEF + #define _CURSES_SET_TABSIZE_METHODDEF +#endif /* !defined(_CURSES_SET_TABSIZE_METHODDEF) */ + +#ifndef _CURSES_IS_TERM_RESIZED_METHODDEF + #define _CURSES_IS_TERM_RESIZED_METHODDEF +#endif /* !defined(_CURSES_IS_TERM_RESIZED_METHODDEF) */ + +#ifndef _CURSES_MOUSEINTERVAL_METHODDEF + #define _CURSES_MOUSEINTERVAL_METHODDEF +#endif /* !defined(_CURSES_MOUSEINTERVAL_METHODDEF) */ + +#ifndef _CURSES_MOUSEMASK_METHODDEF + #define _CURSES_MOUSEMASK_METHODDEF +#endif /* !defined(_CURSES_MOUSEMASK_METHODDEF) */ + +#ifndef _CURSES_UPDATE_LINES_COLS_METHODDEF + #define _CURSES_UPDATE_LINES_COLS_METHODDEF +#endif /* !defined(_CURSES_UPDATE_LINES_COLS_METHODDEF) */ + +#ifndef _CURSES_RESIZETERM_METHODDEF + #define _CURSES_RESIZETERM_METHODDEF +#endif /* !defined(_CURSES_RESIZETERM_METHODDEF) */ + +#ifndef _CURSES_RESIZE_TERM_METHODDEF + #define _CURSES_RESIZE_TERM_METHODDEF +#endif /* !defined(_CURSES_RESIZE_TERM_METHODDEF) */ + +#ifndef _CURSES_SETSYX_METHODDEF + #define _CURSES_SETSYX_METHODDEF +#endif /* !defined(_CURSES_SETSYX_METHODDEF) */ + +#ifndef _CURSES_TYPEAHEAD_METHODDEF + #define _CURSES_TYPEAHEAD_METHODDEF +#endif /* !defined(_CURSES_TYPEAHEAD_METHODDEF) */ + +#ifndef _CURSES_UNGET_WCH_METHODDEF + #define _CURSES_UNGET_WCH_METHODDEF +#endif /* !defined(_CURSES_UNGET_WCH_METHODDEF) */ + +#ifndef _CURSES_USE_ENV_METHODDEF + #define _CURSES_USE_ENV_METHODDEF +#endif /* !defined(_CURSES_USE_ENV_METHODDEF) */ + +#ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF + #define _CURSES_USE_DEFAULT_COLORS_METHODDEF +#endif /* !defined(_CURSES_USE_DEFAULT_COLORS_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=135246e29163510c input=a9049054013a1b77]*/ From 269b95e0709eabc3520f4b28fc8b63fbaaffeef6 Mon Sep 17 00:00:00 2001 From: Imre Eilertsen Date: Mon, 1 Dec 2025 17:35:25 +0100 Subject: [PATCH 4/6] Update ci.yml --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbf2226..c5ca261 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,9 +68,15 @@ jobs: builder: windows-2022 toolset: '14.42' # Visual Studio 2022 winsdk: '10.0.17763.0' # Windows 10 1809 + # Python 3.14 + - python: '3.14' + builder: windows-2022 + toolset: '14.42' # Visual Studio 2022 + winsdk: '10.0.17763.0' # Windows 10 1809 arch: - x86 - x64 + - arm64 steps: - name: Set up Python @@ -105,7 +111,7 @@ jobs: - name: Build wheel id: build-wheel run: | - ./build-wheels.bat ${{ matrix.target.python }}${{ matrix.arch == 'x86' && '-32' || '' }} + ./build-wheels.bat ${{ matrix.target.python }}${{ matrix.arch == 'x86' && '-32' && 'arm64 || '' }} ls -l dist files=(dist/*.whl) filename=$(basename ${files[0]}) From e1bcf99565bbd498a626fad0826987472dda79d3 Mon Sep 17 00:00:00 2001 From: Imre Eilertsen Date: Mon, 1 Dec 2025 17:37:01 +0100 Subject: [PATCH 5/6] Update setup.py --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b982c97..d4067f0 100644 --- a/setup.py +++ b/setup.py @@ -62,7 +62,7 @@ setup( name='windows-curses', - version='2.4.1', + version='2.5.0', description="Support for the standard curses module on Windows", long_description=LONG_DESCRIPTION, long_description_content_type="text/markdown", @@ -108,6 +108,7 @@ 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'Programming Language :: Python :: Implementation :: CPython', 'Topic :: Software Development', 'Topic :: Software Development :: Libraries :: Python Modules', From 4e7e0bfa0eec47d83ac4e820fc1be63409116028 Mon Sep 17 00:00:00 2001 From: Imre Eilertsen Date: Mon, 1 Dec 2025 17:41:48 +0100 Subject: [PATCH 6/6] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c5ca261..2192be4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,7 +111,7 @@ jobs: - name: Build wheel id: build-wheel run: | - ./build-wheels.bat ${{ matrix.target.python }}${{ matrix.arch == 'x86' && '-32' && 'arm64 || '' }} + ./build-wheels.bat ${{ matrix.target.python }}${{ matrix.arch == 'x86' && '-32' && 'arm64' || '' }} ls -l dist files=(dist/*.whl) filename=$(basename ${files[0]})