From b29c1e9f23396109acf62f8a6fd354f3894f9351 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Mon, 22 May 2023 02:37:15 +0300 Subject: [PATCH 01/12] Isolate _curses module * converted `PyCursesWindowObject` to heap type * added module state containing previously global `PyCursesWindow_Type`, `PyCursesError` and `screen_encoding`; added `get__curses_state` and `find__curses_state_by_type` functions; changed functions and methods to access members of state or take state as a parameter * got rid of `ModDict` global variable, made functions/methods access it through `PyModule_GetDict` call; changed `SetDictInt` to accept dict as parameter * converted module to multi-phase init * changed signatures of functions used by C API in order to make exception stored in module state accessible by API users; reworked macros in Include/py_curses.h to reflect these changes * added `clinic_state()` macro for access to `PyCursesWindow_Type` in AC-generated code --- Include/py_curses.h | 9 +- Modules/_cursesmodule.c | 867 +++++++++++++++++-------------- Modules/clinic/_cursesmodule.c.h | 10 +- 3 files changed, 498 insertions(+), 388 deletions(-) diff --git a/Include/py_curses.h b/Include/py_curses.h index e46b08e9cc414e..089bae4f4abf20 100644 --- a/Include/py_curses.h +++ b/Include/py_curses.h @@ -54,7 +54,7 @@ extern "C" { #endif -#define PyCurses_API_pointers 4 +#define PyCurses_API_pointers 5 /* Type declarations */ @@ -62,6 +62,7 @@ typedef struct { PyObject_HEAD WINDOW *win; char *encoding; + struct _curses_state *state; } PyCursesWindowObject; #define PyCursesWindow_Check(v) Py_IS_TYPE((v), &PyCursesWindow_Type) @@ -78,9 +79,9 @@ typedef struct { static void **PyCurses_API; #define PyCursesWindow_Type (*_PyType_CAST(PyCurses_API[0])) -#define PyCursesSetupTermCalled {if (! ((int (*)(void))PyCurses_API[1]) () ) return NULL;} -#define PyCursesInitialised {if (! ((int (*)(void))PyCurses_API[2]) () ) return NULL;} -#define PyCursesInitialisedColor {if (! ((int (*)(void))PyCurses_API[3]) () ) return NULL;} +#define PyCursesSetupTermCalled {if (! ((int (*)(void **))PyCurses_API[1]) (PyCurses_API) ) return NULL;} +#define PyCursesInitialised {if (! ((int (*)(void **))PyCurses_API[2]) (PyCurses_API) ) return NULL;} +#define PyCursesInitialisedColor {if (! ((int (*)(void **))PyCurses_API[3]) (PyCurses_API) ) return NULL;} #define import_curses() \ PyCurses_API = (void **)PyCapsule_Import(PyCurses_CAPSULE_NAME, 1); diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 5691a419a32f8e..2d9a15ef95d735 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -163,13 +163,9 @@ typedef chtype attr_t; /* No attr_t type is available */ /*[clinic input] module _curses -class _curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type" +class _curses.window "PyCursesWindowObject *" "clinic_state()->PyCursesWindow_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=43265c372c2887d6]*/ - -/* Definition of exception curses.error */ - -static PyObject *PyCursesError; +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=83369be6e20ef0da]*/ /* Tells whether setupterm() has been called to initialise terminfo. */ static int initialised_setupterm = FALSE; @@ -180,24 +176,74 @@ static int initialised = FALSE; /* Tells whether start_color() has been called to initialise color usage. */ static int initialisedcolors = FALSE; -static char *screen_encoding = NULL; + +typedef struct _curses_state { + PyTypeObject *PyCursesWindow_Type; + PyObject *PyCursesError; + char *screen_encoding; +} _curses_state; + + +static struct PyModuleDef _curses_module; + + +static inline _curses_state * +get__curses_state(PyObject *mod) +{ + void *state = PyModule_GetState(mod); + assert (state != NULL); + return (_curses_state *)state; +} + +static inline _curses_state * +find__curses_state_by_type(PyTypeObject *type) +{ + PyObject *mod = PyType_GetModuleByDef(type, &_curses_module); + assert(mod != NULL); + return get__curses_state(mod); +} + + +static int +_curses_clear(PyObject *mod) +{ + _curses_state *state = get__curses_state(mod); + Py_CLEAR(state->PyCursesWindow_Type); + Py_CLEAR(state->PyCursesError); + return 0; +} + +static int +_curses_traverse(PyObject *mod, visitproc visit, void *arg) +{ + _curses_state *state = get__curses_state(mod); + Py_VISIT(state->PyCursesWindow_Type); + Py_VISIT(state->PyCursesError); + return 0; +} + +static void +_curses_free(void *mod) +{ + _curses_clear((PyObject *)mod); +} /* Utility Macros */ -#define PyCursesSetupTermCalled \ +#define PyCursesSetupTermCalled(state) \ if (initialised_setupterm != TRUE) { \ - PyErr_SetString(PyCursesError, \ + PyErr_SetString(state->PyCursesError, \ "must call (at least) setupterm() first"); \ return 0; } -#define PyCursesInitialised \ +#define PyCursesInitialised(state) \ if (initialised != TRUE) { \ - PyErr_SetString(PyCursesError, \ + PyErr_SetString(state->PyCursesError, \ "must call initscr() first"); \ return 0; } -#define PyCursesInitialisedColor \ +#define PyCursesInitialisedColor(state) \ if (initialisedcolors != TRUE) { \ - PyErr_SetString(PyCursesError, \ + PyErr_SetString(state->PyCursesError, \ "must call start_color() first"); \ return 0; } @@ -210,15 +256,15 @@ static char *screen_encoding = NULL; */ static PyObject * -PyCursesCheckERR(int code, const char *fname) +PyCursesCheckERR(_curses_state *state, int code, const char *fname) { if (code != ERR) { Py_RETURN_NONE; } else { if (fname == NULL) { - PyErr_SetString(PyCursesError, catchall_ERR); + PyErr_SetString(state->PyCursesError, catchall_ERR); } else { - PyErr_Format(PyCursesError, "%s() returned ERR", fname); + PyErr_Format(state->PyCursesError, "%s() returned ERR", fname); } return NULL; } @@ -253,7 +299,7 @@ PyCurses_ConvertToChtype(PyCursesWindowObject *win, PyObject *obj, chtype *ch) if (win) encoding = win->encoding; else - encoding = screen_encoding; + encoding = win->state->screen_encoding; bytes = PyUnicode_AsEncodedString(obj, encoding, NULL); if (bytes == NULL) return 0; @@ -532,21 +578,34 @@ class component_converter(CConverter): /* Function versions of the 3 functions for testing whether curses has been initialised or not. */ -static int func_PyCursesSetupTermCalled(void) + +static int func_PyCursesSetupTermCalled(void **api) { - PyCursesSetupTermCalled; + if (initialised_setupterm != TRUE) { + PyErr_SetString(api[4], + "must call (at least) setupterm() first"); + return 0; + } return 1; } -static int func_PyCursesInitialised(void) +static int func_PyCursesInitialised(void **api) { - PyCursesInitialised; + if (initialised != TRUE) { + PyErr_SetString(api[4], + "must call initscr() first"); + return 0; + } return 1; } -static int func_PyCursesInitialisedColor(void) +static int func_PyCursesInitialisedColor(void **api) { - PyCursesInitialisedColor; + if (initialisedcolors != TRUE) { + PyErr_SetString(api[4], + "must call start_color() first"); + return 0; + } return 1; } @@ -556,8 +615,6 @@ static int func_PyCursesInitialisedColor(void) /* Definition of the window type */ -PyTypeObject PyCursesWindow_Type; - /* Function prototype macros for Window object X - function name @@ -569,7 +626,7 @@ PyTypeObject PyCursesWindow_Type; #define Window_NoArgNoReturnFunction(X) \ static PyObject *PyCursesWindow_ ## X \ (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ - { return PyCursesCheckERR(X(self->win), # X); } + { return PyCursesCheckERR(self->state, X(self->win), # X); } #define Window_NoArgTrueFalseFunction(X) \ static PyObject * PyCursesWindow_ ## X \ @@ -604,7 +661,7 @@ PyTypeObject PyCursesWindow_Type; { \ TYPE arg1; \ if (!PyArg_ParseTuple(args,PARSESTR, &arg1)) return NULL; \ - return PyCursesCheckERR(X(self->win, arg1), # X); } + return PyCursesCheckERR(self->state, X(self->win, arg1), # X); } #define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \ static PyObject * PyCursesWindow_ ## X \ @@ -612,7 +669,7 @@ PyTypeObject PyCursesWindow_Type; { \ TYPE arg1, arg2; \ if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) return NULL; \ - return PyCursesCheckERR(X(self->win, arg1, arg2), # X); } + return PyCursesCheckERR(self->state, X(self->win, arg1, arg2), # X); } /* ------------- WINDOW routines --------------- */ @@ -667,7 +724,7 @@ Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns") /* Allocation and deallocation of Window Objects */ static PyObject * -PyCursesWindow_New(WINDOW *win, const char *encoding) +PyCursesWindow_New(_curses_state *state, WINDOW *win, const char *encoding) { PyCursesWindowObject *wo; @@ -689,7 +746,7 @@ PyCursesWindow_New(WINDOW *win, const char *encoding) encoding = "utf-8"; } - wo = PyObject_New(PyCursesWindowObject, &PyCursesWindow_Type); + wo = PyObject_New(PyCursesWindowObject, state->PyCursesWindow_Type); if (wo == NULL) return NULL; wo->win = win; wo->encoding = _PyMem_Strdup(encoding); @@ -698,6 +755,7 @@ PyCursesWindow_New(WINDOW *win, const char *encoding) PyErr_NoMemory(); return NULL; } + wo->state = state; return (PyObject *)wo; } @@ -707,9 +765,12 @@ PyCursesWindow_Dealloc(PyCursesWindowObject *wo) if (wo->win != stdscr) delwin(wo->win); if (wo->encoding != NULL) PyMem_Free(wo->encoding); - PyObject_Free(wo); + PyTypeObject *tp = Py_TYPE(wo); + tp->tp_free((PyObject *)wo); + Py_DECREF(tp); } + /* Addch, Addstr, Addnstr */ /*[clinic input] @@ -782,7 +843,7 @@ _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, else { return NULL; } - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR(self->state, rtn, funcname); } /*[clinic input] @@ -862,7 +923,7 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR(self->state, rtn, funcname); } /*[clinic input] @@ -945,7 +1006,7 @@ _curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR(self->state, rtn, funcname); } /*[clinic input] @@ -969,7 +1030,7 @@ _curses_window_bkgd_impl(PyCursesWindowObject *self, PyObject *ch, long attr) if (!PyCurses_ConvertToChtype(self, ch, &bkgd)) return NULL; - return PyCursesCheckERR(wbkgd(self->win, bkgd | attr), "bkgd"); + return PyCursesCheckERR(self->state, wbkgd(self->win, bkgd | attr), "bkgd"); } /*[clinic input] @@ -985,7 +1046,7 @@ static PyObject * _curses_window_attroff_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=8a2fcd4df682fc64 input=786beedf06a7befe]*/ { - return PyCursesCheckERR(wattroff(self->win, (attr_t)attr), "attroff"); + return PyCursesCheckERR(self->state, wattroff(self->win, (attr_t)attr), "attroff"); } /*[clinic input] @@ -1001,7 +1062,7 @@ static PyObject * _curses_window_attron_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=7afea43b237fa870 input=5a88fba7b1524f32]*/ { - return PyCursesCheckERR(wattron(self->win, (attr_t)attr), "attron"); + return PyCursesCheckERR(self->state, wattron(self->win, (attr_t)attr), "attron"); } /*[clinic input] @@ -1017,7 +1078,7 @@ static PyObject * _curses_window_attrset_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=84e379bff20c0433 input=42e400c0d0154ab5]*/ { - return PyCursesCheckERR(wattrset(self->win, (attr_t)attr), "attrset"); + return PyCursesCheckERR(self->state, wattrset(self->win, (attr_t)attr), "attrset"); } /*[clinic input] @@ -1043,7 +1104,7 @@ _curses_window_bkgdset_impl(PyCursesWindowObject *self, PyObject *ch, return NULL; wbkgdset(self->win, bkgd | attr); - return PyCursesCheckERR(0, "bkgdset"); + return PyCursesCheckERR(self->state, 0, "bkgdset"); } /*[clinic input] @@ -1241,7 +1302,7 @@ PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) rtn = wchgat(self->win,num,attr,color,NULL); touchline(self->win,y,1); } - return PyCursesCheckERR(rtn, "chgat"); + return PyCursesCheckERR(self->state, rtn, "chgat"); } #endif @@ -1265,10 +1326,10 @@ _curses_window_delch_impl(PyCursesWindowObject *self, int group_right_1, /*[clinic end generated code: output=22e77bb9fa11b461 input=d2f79e630a4fc6d0]*/ { if (!group_right_1) { - return PyCursesCheckERR(wdelch(self->win), "wdelch"); + return PyCursesCheckERR(self->state, wdelch(self->win), "wdelch"); } else { - return PyCursesCheckERR(py_mvwdelch(self->win, y, x), "mvwdelch"); + return PyCursesCheckERR(self->state, py_mvwdelch(self->win, y, x), "mvwdelch"); } } @@ -1304,11 +1365,11 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, win = derwin(self->win,nlines,ncols,begin_y,begin_x); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + PyErr_SetString(self->state->PyCursesError, catchall_NULL); return NULL; } - return (PyObject *)PyCursesWindow_New(win, NULL); + return (PyObject *)PyCursesWindow_New(self->state, win, NULL); } /*[clinic input] @@ -1336,12 +1397,12 @@ _curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch, #ifdef py_is_pad if (py_is_pad(self->win)) { - return PyCursesCheckERR(pechochar(self->win, ch_ | (attr_t)attr), + return PyCursesCheckERR(self->state, pechochar(self->win, ch_ | (attr_t)attr), "echochar"); } else #endif - return PyCursesCheckERR(wechochar(self->win, ch_ | (attr_t)attr), + return PyCursesCheckERR(self->state, wechochar(self->win, ch_ | (attr_t)attr), "echochar"); } @@ -1454,7 +1515,7 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, /* getch() returns ERR in nodelay mode */ PyErr_CheckSignals(); if (!PyErr_Occurred()) - PyErr_SetString(PyCursesError, "no input"); + PyErr_SetString(self->state->PyCursesError, "no input"); return NULL; } else if (rtn <= 255) { #ifdef NCURSES_VERSION_MAJOR @@ -1512,7 +1573,7 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, return NULL; /* get_wch() returns ERR in nodelay mode */ - PyErr_SetString(PyCursesError, "no input"); + PyErr_SetString(self->state->PyCursesError, "no input"); return NULL; } if (ct == KEY_CODE_YES) @@ -1636,10 +1697,10 @@ _curses_window_hline_impl(PyCursesWindowObject *self, int group_left_1, return NULL; if (group_left_1) { if (wmove(self->win, y, x) == ERR) { - return PyCursesCheckERR(ERR, "wmove"); + return PyCursesCheckERR(self->state, ERR, "wmove"); } } - return PyCursesCheckERR(whline(self->win, ch_ | (attr_t)attr, n), "hline"); + return PyCursesCheckERR(self->state, whline(self->win, ch_ | (attr_t)attr, n), "hline"); } /*[clinic input] @@ -1686,7 +1747,7 @@ _curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1, rtn = mvwinsch(self->win, y, x, ch_ | (attr_t)attr); } - return PyCursesCheckERR(rtn, "insch"); + return PyCursesCheckERR(self->state, rtn, "insch"); } /*[clinic input] @@ -1863,7 +1924,7 @@ _curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR(self->state, rtn, funcname); } /*[clinic input] @@ -1948,7 +2009,7 @@ _curses_window_insnstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR(self->state, rtn, funcname); } /*[clinic input] @@ -2025,7 +2086,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - PyErr_SetString(PyCursesError, + PyErr_SetString(self->state->PyCursesError, "noutrefresh() called for a pad " "requires 6 arguments"); return NULL; @@ -2034,7 +2095,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) rtn = pnoutrefresh(self->win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "pnoutrefresh"); + return PyCursesCheckERR(self->state, rtn, "pnoutrefresh"); } if (group_right_1) { PyErr_SetString(PyExc_TypeError, @@ -2045,13 +2106,13 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) Py_BEGIN_ALLOW_THREADS rtn = wnoutrefresh(self->win); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "wnoutrefresh"); + return PyCursesCheckERR(self->state, rtn, "wnoutrefresh"); } /*[clinic input] _curses.window.overlay - destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + destwin: object(type="PyCursesWindowObject *", subclass_of="clinic_state()->PyCursesWindow_Type") [ sminrow: int @@ -2080,25 +2141,25 @@ _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=7edd23ad22cc1984]*/ +/*[clinic end generated code: output=82bb2c4cb443ca58 input=2b1427dce85d2869]*/ { int rtn; if (group_right_1) { rtn = copywin(self->win, destwin->win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, TRUE); - return PyCursesCheckERR(rtn, "copywin"); + return PyCursesCheckERR(self->state, rtn, "copywin"); } else { rtn = overlay(self->win, destwin->win); - return PyCursesCheckERR(rtn, "overlay"); + return PyCursesCheckERR(self->state, rtn, "overlay"); } } /*[clinic input] _curses.window.overwrite - destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + destwin: object(type="PyCursesWindowObject *", subclass_of="clinic_state()->PyCursesWindow_Type") [ sminrow: int @@ -2128,18 +2189,18 @@ _curses_window_overwrite_impl(PyCursesWindowObject *self, int group_right_1, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol) -/*[clinic end generated code: output=12ae007d1681be28 input=ea5de1b35cd948e0]*/ +/*[clinic end generated code: output=12ae007d1681be28 input=ea0f756c3487e4de]*/ { int rtn; if (group_right_1) { rtn = copywin(self->win, destwin->win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, FALSE); - return PyCursesCheckERR(rtn, "copywin"); + return PyCursesCheckERR(self->state, rtn, "copywin"); } else { rtn = overwrite(self->win, destwin->win); - return PyCursesCheckERR(rtn, "overwrite"); + return PyCursesCheckERR(self->state, rtn, "overwrite"); } } @@ -2168,7 +2229,7 @@ _curses_window_putwin(PyCursesWindowObject *self, PyObject *file) return PyErr_SetFromErrno(PyExc_OSError); if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0) goto exit; - res = PyCursesCheckERR(putwin(self->win, fp), "putwin"); + res = PyCursesCheckERR(self->state, putwin(self->win, fp), "putwin"); if (res == NULL) goto exit; fseek(fp, 0, 0); @@ -2207,7 +2268,7 @@ static PyObject * _curses_window_redrawln_impl(PyCursesWindowObject *self, int beg, int num) /*[clinic end generated code: output=ea216e334f9ce1b4 input=152155e258a77a7a]*/ { - return PyCursesCheckERR(wredrawln(self->win,beg,num), "redrawln"); + return PyCursesCheckERR(self->state, wredrawln(self->win,beg,num), "redrawln"); } /*[clinic input] @@ -2249,7 +2310,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - PyErr_SetString(PyCursesError, + PyErr_SetString(self->state->PyCursesError, "refresh() for a pad requires 6 arguments"); return NULL; } @@ -2257,7 +2318,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, rtn = prefresh(self->win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); + return PyCursesCheckERR(self->state, rtn, "prefresh"); } #endif if (group_right_1) { @@ -2268,7 +2329,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, Py_BEGIN_ALLOW_THREADS rtn = wrefresh(self->win); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); + return PyCursesCheckERR(self->state, rtn, "prefresh"); } /*[clinic input] @@ -2290,7 +2351,7 @@ _curses_window_setscrreg_impl(PyCursesWindowObject *self, int top, int bottom) /*[clinic end generated code: output=486ab5db218d2b1a input=1b517b986838bf0e]*/ { - return PyCursesCheckERR(wsetscrreg(self->win, top, bottom), "wsetscrreg"); + return PyCursesCheckERR(self->state, wsetscrreg(self->win, top, bottom), "wsetscrreg"); } /*[clinic input] @@ -2331,11 +2392,11 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, win = subwin(self->win, nlines, ncols, begin_y, begin_x); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + PyErr_SetString(self->state->PyCursesError, catchall_NULL); return NULL; } - return (PyObject *)PyCursesWindow_New(win, self->encoding); + return (PyObject *)PyCursesWindow_New(self->state, win, self->encoding); } /*[clinic input] @@ -2358,10 +2419,10 @@ _curses_window_scroll_impl(PyCursesWindowObject *self, int group_right_1, /*[clinic end generated code: output=4541a8a11852d360 input=c969ca0cfabbdbec]*/ { if (!group_right_1) { - return PyCursesCheckERR(scroll(self->win), "scroll"); + return PyCursesCheckERR(self->state, scroll(self->win), "scroll"); } else { - return PyCursesCheckERR(wscrl(self->win, lines), "scroll"); + return PyCursesCheckERR(self->state, wscrl(self->win, lines), "scroll"); } } @@ -2387,10 +2448,10 @@ _curses_window_touchline_impl(PyCursesWindowObject *self, int start, /*[clinic end generated code: output=65d05b3f7438c61d input=a98aa4f79b6be845]*/ { if (!group_right_1) { - return PyCursesCheckERR(touchline(self->win, start, count), "touchline"); + return PyCursesCheckERR(self->state, touchline(self->win, start, count), "touchline"); } else { - return PyCursesCheckERR(wtouchln(self->win, start, count, changed), "touchline"); + return PyCursesCheckERR(self->state, wtouchln(self->win, start, count, changed), "touchline"); } } @@ -2430,9 +2491,9 @@ _curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1, return NULL; if (group_left_1) { if (wmove(self->win, y, x) == ERR) - return PyCursesCheckERR(ERR, "wmove"); + return PyCursesCheckERR(self->state, ERR, "wmove"); } - return PyCursesCheckERR(wvline(self->win, ch_ | (attr_t)attr, n), "vline"); + return PyCursesCheckERR(self->state, wvline(self->win, ch_ | (attr_t)attr, n), "vline"); } static PyObject * @@ -2473,7 +2534,9 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value, void *P return 0; } +#define clinic_state() (find__curses_state_by_type(Py_TYPE(self))) #include "clinic/_cursesmodule.c.h" +#undef clinic_state static PyMethodDef PyCursesWindow_Methods[] = { _CURSES_WINDOW_ADDCH_METHODDEF @@ -2569,42 +2632,23 @@ static PyGetSetDef PyCursesWindow_getsets[] = { {NULL, NULL, NULL, NULL } /* sentinel */ }; -/* -------------------------------------------------------*/ - -PyTypeObject PyCursesWindow_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_curses.window", /*tp_name*/ - sizeof(PyCursesWindowObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PyCursesWindow_Dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - PyCursesWindow_Methods, /*tp_methods*/ - 0, /* tp_members */ - PyCursesWindow_getsets, /* tp_getset */ + +static PyType_Slot PyCursesWindow_slots[] = { + {Py_tp_dealloc, PyCursesWindow_Dealloc}, + {Py_tp_methods, PyCursesWindow_Methods}, + {Py_tp_getset, PyCursesWindow_getsets}, + {0, NULL} +}; + + +static PyType_Spec PyCursesWindow_spec = { + .name = "_curses.window", + .basicsize = sizeof(PyCursesWindowObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .slots = PyCursesWindow_slots }; + /* Function Prototype Macros - They are ugly but very, very useful. ;-) X - function name @@ -2615,37 +2659,43 @@ PyTypeObject PyCursesWindow_Type = { #define NoArgNoReturnFunctionBody(X) \ { \ - PyCursesInitialised \ - return PyCursesCheckERR(X(), # X); } + _curses_state *state = get__curses_state(module); \ + PyCursesInitialised(state) \ + return PyCursesCheckERR(state, X(), # X); } #define NoArgOrFlagNoReturnFunctionBody(X, flag) \ { \ - PyCursesInitialised \ + _curses_state *state = get__curses_state(module); \ + PyCursesInitialised(state) \ if (flag) \ - return PyCursesCheckERR(X(), # X); \ + return PyCursesCheckERR(state, X(), # X); \ else \ - return PyCursesCheckERR(no ## X(), # X); \ + return PyCursesCheckERR(state, no ## X(), # X); \ } #define NoArgReturnIntFunctionBody(X) \ { \ - PyCursesInitialised \ + _curses_state *state = get__curses_state(module); \ + PyCursesInitialised(state) \ return PyLong_FromLong((long) X()); } #define NoArgReturnStringFunctionBody(X) \ { \ - PyCursesInitialised \ + _curses_state *state = get__curses_state(module); \ + PyCursesInitialised(state) \ return PyBytes_FromString(X()); } #define NoArgTrueFalseFunctionBody(X) \ { \ - PyCursesInitialised \ + _curses_state *state = get__curses_state(module); \ + PyCursesInitialised(state) \ return PyBool_FromLong(X()); } #define NoArgNoReturnVoidFunctionBody(X) \ { \ - PyCursesInitialised \ + _curses_state *state = get__curses_state(module); \ + PyCursesInitialised(state) \ X(); \ Py_RETURN_NONE; } @@ -2743,11 +2793,13 @@ _curses_color_content_impl(PyObject *module, int color_number) { _CURSES_COLOR_VAL_TYPE r,g,b; - PyCursesInitialised; - PyCursesInitialisedColor; + _curses_state *state = get__curses_state(module); + + PyCursesInitialised(state); + PyCursesInitialisedColor(state); if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) { - PyErr_Format(PyCursesError, "%s() returned ERR", + PyErr_Format(state->PyCursesError, "%s() returned ERR", Py_STRINGIFY(_COLOR_CONTENT_FUNC)); return NULL; } @@ -2772,10 +2824,11 @@ static PyObject * _curses_color_pair_impl(PyObject *module, int pair_number) /*[clinic end generated code: output=60718abb10ce9feb input=6034e9146f343802]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); + PyCursesInitialisedColor(state); - return PyLong_FromLong(COLOR_PAIR(pair_number)); + return PyLong_FromLong(COLOR_PAIR(pair_number)); } /*[clinic input] @@ -2799,10 +2852,11 @@ _curses_curs_set_impl(PyObject *module, int visibility) { int erg; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); erg = curs_set(visibility); - if (erg == ERR) return PyCursesCheckERR(erg, "curs_set"); + if (erg == ERR) return PyCursesCheckERR(state, erg, "curs_set"); return PyLong_FromLong((long) erg); } @@ -2851,9 +2905,10 @@ static PyObject * _curses_delay_output_impl(PyObject *module, int ms) /*[clinic end generated code: output=b6613a67f17fa4f4 input=5316457f5f59196c]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); - return PyCursesCheckERR(delay_output(ms), "delay_output"); + return PyCursesCheckERR(state, delay_output(ms), "delay_output"); } /*[clinic input] @@ -2907,7 +2962,8 @@ _curses_erasechar_impl(PyObject *module) { char ch; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); ch = erasechar(); @@ -2957,7 +3013,8 @@ _curses_getsyx_impl(PyObject *module) int x = 0; int y = 0; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); getsyx(y, x); @@ -2982,11 +3039,12 @@ _curses_getmouse_impl(PyObject *module) int rtn; MEVENT event; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); rtn = getmouse( &event ); if (rtn == ERR) { - PyErr_SetString(PyCursesError, "getmouse() returned ERR"); + PyErr_SetString(state->PyCursesError, "getmouse() returned ERR"); return NULL; } return Py_BuildValue("(hiiik)", @@ -3017,14 +3075,15 @@ _curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, { MEVENT event; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); event.id = id; event.x = x; event.y = y; event.z = z; event.bstate = bstate; - return PyCursesCheckERR(ungetmouse(&event), "ungetmouse"); + return PyCursesCheckERR(state, ungetmouse(&event), "ungetmouse"); } #endif @@ -3050,7 +3109,8 @@ _curses_getwin(PyObject *module, PyObject *file) WINDOW *win; PyObject *res = NULL; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); fp = tmpfile(); if (fp == NULL) @@ -3080,10 +3140,10 @@ _curses_getwin(PyObject *module, PyObject *file) fseek(fp, 0, 0); win = getwin(fp); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + PyErr_SetString(state->PyCursesError, catchall_NULL); goto error; } - res = PyCursesWindow_New(win, NULL); + res = PyCursesWindow_New(state, win, NULL); error: fclose(fp); @@ -3106,9 +3166,10 @@ static PyObject * _curses_halfdelay_impl(PyObject *module, unsigned char tenths) /*[clinic end generated code: output=e92cdf0ef33c0663 input=e42dce7259c15100]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); - return PyCursesCheckERR(halfdelay(tenths), "halfdelay"); + return PyCursesCheckERR(state, halfdelay(tenths), "halfdelay"); } /*[clinic input] @@ -3159,7 +3220,8 @@ static PyObject * _curses_has_key_impl(PyObject *module, int key) /*[clinic end generated code: output=19ad48319414d0b1 input=78bd44acf1a4997c]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); return PyBool_FromLong(has_key(key)); } @@ -3190,10 +3252,11 @@ _curses_init_color_impl(PyObject *module, int color_number, short r, short g, short b) /*[clinic end generated code: output=d7ed71b2d818cdf2 input=ae2b8bea0f152c80]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); + PyCursesInitialisedColor(state); - return PyCursesCheckERR(_CURSES_INIT_COLOR_FUNC(color_number, r, g, b), + return PyCursesCheckERR(state, _CURSES_INIT_COLOR_FUNC(color_number, r, g, b), Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC)); } @@ -3218,8 +3281,9 @@ static PyObject * _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) /*[clinic end generated code: output=a0bba03d2bbc3ee6 input=54b421b44c12c389]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); + PyCursesInitialisedColor(state); if (_CURSES_INIT_PAIR_FUNC(pair_number, fg, bg) == ERR) { if (pair_number >= COLOR_PAIRS) { @@ -3228,7 +3292,7 @@ _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) COLOR_PAIRS - 1); } else { - PyErr_Format(PyCursesError, "%s() returned ERR", + PyErr_Format(state->PyCursesError, "%s() returned ERR", Py_STRINGIFY(_CURSES_INIT_PAIR_FUNC)); } return NULL; @@ -3237,8 +3301,6 @@ _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) Py_RETURN_NONE; } -static PyObject *ModDict; - /*[clinic input] _curses.initscr @@ -3254,15 +3316,17 @@ _curses_initscr_impl(PyObject *module) WINDOW *win; PyCursesWindowObject *winobj; + _curses_state *state = get__curses_state(module); + if (initialised) { wrefresh(stdscr); - return (PyObject *)PyCursesWindow_New(stdscr, NULL); + return (PyObject *)PyCursesWindow_New(state, stdscr, NULL); } win = initscr(); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + PyErr_SetString(state->PyCursesError, catchall_NULL); return NULL; } @@ -3270,86 +3334,87 @@ _curses_initscr_impl(PyObject *module) /* This was moved from initcurses() because it core dumped on SGI, where they're not defined until you've called initscr() */ -#define SetDictInt(string,ch) \ +#define SetDictInt(dict, string,ch) \ do { \ PyObject *o = PyLong_FromLong((long) (ch)); \ - if (o && PyDict_SetItemString(ModDict, string, o) == 0) { \ + if (o && PyDict_SetItemString(dict, string, o) == 0) { \ Py_DECREF(o); \ } \ } while (0) + PyObject *d = PyModule_GetDict(module); /* 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)); + SetDictInt(d, "ACS_ULCORNER", (ACS_ULCORNER)); + SetDictInt(d, "ACS_LLCORNER", (ACS_LLCORNER)); + SetDictInt(d, "ACS_URCORNER", (ACS_URCORNER)); + SetDictInt(d, "ACS_LRCORNER", (ACS_LRCORNER)); + SetDictInt(d, "ACS_LTEE", (ACS_LTEE)); + SetDictInt(d, "ACS_RTEE", (ACS_RTEE)); + SetDictInt(d, "ACS_BTEE", (ACS_BTEE)); + SetDictInt(d, "ACS_TTEE", (ACS_TTEE)); + SetDictInt(d, "ACS_HLINE", (ACS_HLINE)); + SetDictInt(d, "ACS_VLINE", (ACS_VLINE)); + SetDictInt(d, "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)); + SetDictInt(d, "ACS_S1", (ACS_S1)); + SetDictInt(d, "ACS_S9", (ACS_S9)); + SetDictInt(d, "ACS_DIAMOND", (ACS_DIAMOND)); + SetDictInt(d, "ACS_CKBOARD", (ACS_CKBOARD)); + SetDictInt(d, "ACS_DEGREE", (ACS_DEGREE)); + SetDictInt(d, "ACS_PLMINUS", (ACS_PLMINUS)); + SetDictInt(d, "ACS_BULLET", (ACS_BULLET)); + SetDictInt(d, "ACS_LARROW", (ACS_LARROW)); + SetDictInt(d, "ACS_RARROW", (ACS_RARROW)); + SetDictInt(d, "ACS_DARROW", (ACS_DARROW)); + SetDictInt(d, "ACS_UARROW", (ACS_UARROW)); + SetDictInt(d, "ACS_BOARD", (ACS_BOARD)); + SetDictInt(d, "ACS_LANTERN", (ACS_LANTERN)); + SetDictInt(d, "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)); + SetDictInt(d, "ACS_BSSB", (ACS_ULCORNER)); + SetDictInt(d, "ACS_SSBB", (ACS_LLCORNER)); + SetDictInt(d, "ACS_BBSS", (ACS_URCORNER)); + SetDictInt(d, "ACS_SBBS", (ACS_LRCORNER)); + SetDictInt(d, "ACS_SBSS", (ACS_RTEE)); + SetDictInt(d, "ACS_SSSB", (ACS_LTEE)); + SetDictInt(d, "ACS_SSBS", (ACS_BTEE)); + SetDictInt(d, "ACS_BSSS", (ACS_TTEE)); + SetDictInt(d, "ACS_BSBS", (ACS_HLINE)); + SetDictInt(d, "ACS_SBSB", (ACS_VLINE)); + SetDictInt(d, "ACS_SSSS", (ACS_PLUS)); /* The following are never available with strict SYSV curses */ #ifdef ACS_S3 - SetDictInt("ACS_S3", (ACS_S3)); + SetDictInt(d, "ACS_S3", (ACS_S3)); #endif #ifdef ACS_S7 - SetDictInt("ACS_S7", (ACS_S7)); + SetDictInt(d, "ACS_S7", (ACS_S7)); #endif #ifdef ACS_LEQUAL - SetDictInt("ACS_LEQUAL", (ACS_LEQUAL)); + SetDictInt(d, "ACS_LEQUAL", (ACS_LEQUAL)); #endif #ifdef ACS_GEQUAL - SetDictInt("ACS_GEQUAL", (ACS_GEQUAL)); + SetDictInt(d, "ACS_GEQUAL", (ACS_GEQUAL)); #endif #ifdef ACS_PI - SetDictInt("ACS_PI", (ACS_PI)); + SetDictInt(d, "ACS_PI", (ACS_PI)); #endif #ifdef ACS_NEQUAL - SetDictInt("ACS_NEQUAL", (ACS_NEQUAL)); + SetDictInt(d, "ACS_NEQUAL", (ACS_NEQUAL)); #endif #ifdef ACS_STERLING - SetDictInt("ACS_STERLING", (ACS_STERLING)); + SetDictInt(d, "ACS_STERLING", (ACS_STERLING)); #endif - SetDictInt("LINES", LINES); - SetDictInt("COLS", COLS); + SetDictInt(d, "LINES", LINES); + SetDictInt(d, "COLS", COLS); - winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL); - screen_encoding = winobj->encoding; + winobj = (PyCursesWindowObject *)PyCursesWindow_New(state, win, NULL); + state->screen_encoding = winobj->encoding; return (PyObject *)winobj; } @@ -3372,6 +3437,8 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) { int err; + _curses_state *state = get__curses_state(module); + if (fd == -1) { PyObject* sys_stdout; @@ -3379,7 +3446,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) if (sys_stdout == NULL || sys_stdout == Py_None) { PyErr_SetString( - PyCursesError, + state->PyCursesError, "lost sys.stdout"); return NULL; } @@ -3400,7 +3467,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) s = "setupterm: could not find terminfo database"; } - PyErr_SetString(PyCursesError,s); + PyErr_SetString(state->PyCursesError, s); return NULL; } @@ -3450,7 +3517,9 @@ _curses_set_escdelay_impl(PyObject *module, int ms) return NULL; } - return PyCursesCheckERR(set_escdelay(ms), "set_escdelay"); + _curses_state *state = get__curses_state(module); + + return PyCursesCheckERR(state, set_escdelay(ms), "set_escdelay"); } /*[clinic input] @@ -3489,7 +3558,9 @@ _curses_set_tabsize_impl(PyObject *module, int size) return NULL; } - return PyCursesCheckERR(set_tabsize(size), "set_tabsize"); + _curses_state *state = get__curses_state(module); + + return PyCursesCheckERR(state, set_tabsize(size), "set_tabsize"); } #endif @@ -3505,9 +3576,10 @@ static PyObject * _curses_intrflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=c1986df35e999a0f input=c65fe2ef973fe40a]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); - return PyCursesCheckERR(intrflush(NULL, flag), "intrflush"); + return PyCursesCheckERR(state, intrflush(NULL, flag), "intrflush"); } /*[clinic input] @@ -3538,7 +3610,8 @@ static PyObject * _curses_is_term_resized_impl(PyObject *module, int nlines, int ncols) /*[clinic end generated code: output=aafe04afe50f1288 input=ca9c0bd0fb8ab444]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); return PyBool_FromLong(is_term_resized(nlines, ncols)); } @@ -3560,7 +3633,8 @@ _curses_keyname_impl(PyObject *module, int key) { const char *knp; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); if (key < 0) { PyErr_SetString(PyExc_ValueError, "invalid key number"); @@ -3618,9 +3692,10 @@ static PyObject * _curses_meta_impl(PyObject *module, int yes) /*[clinic end generated code: output=22f5abda46a605d8 input=cfe7da79f51d0e30]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); - return PyCursesCheckERR(meta(stdscr, yes), "meta"); + return PyCursesCheckERR(state, meta(stdscr, yes), "meta"); } #ifdef NCURSES_MOUSE_VERSION @@ -3642,9 +3717,10 @@ static PyObject * _curses_mouseinterval_impl(PyObject *module, int interval) /*[clinic end generated code: output=c4f5ff04354634c5 input=75aaa3f0db10ac4e]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); - return PyCursesCheckERR(mouseinterval(interval), "mouseinterval"); + return PyCursesCheckERR(state, mouseinterval(interval), "mouseinterval"); } /*[clinic input] @@ -3667,7 +3743,8 @@ _curses_mousemask_impl(PyObject *module, unsigned long newmask) { mmask_t oldmask, availmask; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); availmask = mousemask((mmask_t)newmask, &oldmask); return Py_BuildValue("(kk)", (unsigned long)availmask, (unsigned long)oldmask); @@ -3688,7 +3765,8 @@ static PyObject * _curses_napms_impl(PyObject *module, int ms) /*[clinic end generated code: output=a40a1da2e39ea438 input=20cd3af2b6900f56]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); return Py_BuildValue("i", napms(ms)); } @@ -3712,16 +3790,17 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) { WINDOW *win; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); win = newpad(nlines, ncols); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + PyErr_SetString(state->PyCursesError, catchall_NULL); return NULL; } - return (PyObject *)PyCursesWindow_New(win, NULL); + return (PyObject *)PyCursesWindow_New(state, win, NULL); } /*[clinic input] @@ -3752,15 +3831,16 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, { WINDOW *win; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); win = newwin(nlines,ncols,begin_y,begin_x); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + PyErr_SetString(state->PyCursesError, catchall_NULL); return NULL; } - return (PyObject *)PyCursesWindow_New(win, NULL); + return (PyObject *)PyCursesWindow_New(state, win, NULL); } /*[clinic input] @@ -3864,8 +3944,9 @@ _curses_pair_content_impl(PyObject *module, int pair_number) { _CURSES_COLOR_NUM_TYPE f, b; - PyCursesInitialised; - PyCursesInitialisedColor; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); + PyCursesInitialisedColor(state); if (_CURSES_PAIR_CONTENT_FUNC(pair_number, &f, &b) == ERR) { if (pair_number >= COLOR_PAIRS) { @@ -3874,7 +3955,7 @@ _curses_pair_content_impl(PyObject *module, int pair_number) COLOR_PAIRS - 1); } else { - PyErr_Format(PyCursesError, "%s() returned ERR", + PyErr_Format(state->PyCursesError, "%s() returned ERR", Py_STRINGIFY(_CURSES_PAIR_CONTENT_FUNC)); } return NULL; @@ -3898,8 +3979,9 @@ static PyObject * _curses_pair_number_impl(PyObject *module, int attr) /*[clinic end generated code: output=85bce7d65c0aa3f4 input=d478548e33f5e61a]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); + PyCursesInitialisedColor(state); return PyLong_FromLong(PAIR_NUMBER(attr)); } @@ -3919,7 +4001,8 @@ static PyObject * _curses_putp_impl(PyObject *module, const char *string) /*[clinic end generated code: output=e98081d1b8eb5816 input=1601faa828b44cb3]*/ { - return PyCursesCheckERR(putp(string), "putp"); + _curses_state *state = get__curses_state(module); + return PyCursesCheckERR(state, putp(string), "putp"); } /*[clinic input] @@ -3939,7 +4022,8 @@ static PyObject * _curses_qiflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=9167e862f760ea30 input=6ec8b3e2b717ec40]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); if (flag) { qiflush(); @@ -3954,10 +4038,11 @@ _curses_qiflush_impl(PyObject *module, int flag) * and _curses.COLS */ #if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM) static int -update_lines_cols(void) +update_lines_cols(PyObject *mod) { PyObject *o; PyObject *m = PyImport_ImportModule("curses"); + PyObject *d = PyModule_GetDict(mod); if (!m) return 0; @@ -3972,7 +4057,7 @@ update_lines_cols(void) Py_DECREF(o); return 0; } - if (PyDict_SetItemString(ModDict, "LINES", o)) { + if (PyDict_SetItemString(d, "LINES", o)) { Py_DECREF(m); Py_DECREF(o); return 0; @@ -3988,7 +4073,7 @@ update_lines_cols(void) Py_DECREF(o); return 0; } - if (PyDict_SetItemString(ModDict, "COLS", o)) { + if (PyDict_SetItemString(d, "COLS", o)) { Py_DECREF(m); Py_DECREF(o); return 0; @@ -4007,7 +4092,7 @@ static PyObject * _curses_update_lines_cols_impl(PyObject *module) /*[clinic end generated code: output=423f2b1e63ed0f75 input=5f065ab7a28a5d90]*/ { - if (!update_lines_cols()) { + if (!update_lines_cols(module)) { return NULL; } Py_RETURN_NONE; @@ -4089,12 +4174,13 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols) { PyObject *result; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); - result = PyCursesCheckERR(resizeterm(nlines, ncols), "resizeterm"); + result = PyCursesCheckERR(state, resizeterm(nlines, ncols), "resizeterm"); if (!result) return NULL; - if (!update_lines_cols()) { + if (!update_lines_cols(module)) { Py_DECREF(result); return NULL; } @@ -4128,12 +4214,13 @@ _curses_resize_term_impl(PyObject *module, int nlines, int ncols) { PyObject *result; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); - result = PyCursesCheckERR(resize_term(nlines, ncols), "resize_term"); + result = PyCursesCheckERR(state, resize_term(nlines, ncols), "resize_term"); if (!result) return NULL; - if (!update_lines_cols()) { + if (!update_lines_cols(module)) { Py_DECREF(result); return NULL; } @@ -4171,7 +4258,8 @@ static PyObject * _curses_setsyx_impl(PyObject *module, int y, int x) /*[clinic end generated code: output=23dcf753511a2464 input=fa7f2b208e10a557]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); setsyx(y,x); @@ -4199,7 +4287,8 @@ _curses_start_color_impl(PyObject *module) int code; PyObject *c, *cp; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); code = start_color(); if (code != ERR) { @@ -4207,7 +4296,7 @@ _curses_start_color_impl(PyObject *module) c = PyLong_FromLong((long) COLORS); if (c == NULL) return NULL; - if (PyDict_SetItemString(ModDict, "COLORS", c) < 0) { + if (PyModule_AddObjectRef(module, "COLORS", c) < 0) { Py_DECREF(c); return NULL; } @@ -4215,14 +4304,14 @@ _curses_start_color_impl(PyObject *module) cp = PyLong_FromLong((long) COLOR_PAIRS); if (cp == NULL) return NULL; - if (PyDict_SetItemString(ModDict, "COLOR_PAIRS", cp) < 0) { + if (PyModule_AddObjectRef(module, "COLOR_PAIRS", cp) < 0) { Py_DECREF(cp); return NULL; } Py_DECREF(cp); Py_RETURN_NONE; } else { - PyErr_SetString(PyCursesError, "start_color() returned ERR"); + PyErr_SetString(state->PyCursesError, "start_color() returned ERR"); return NULL; } } @@ -4266,7 +4355,8 @@ static PyObject * _curses_tigetflag_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=8853c0e55542195b input=b0787af9e3e9a6ce]*/ { - PyCursesSetupTermCalled; + _curses_state *state = get__curses_state(module); + PyCursesSetupTermCalled(state); return PyLong_FromLong( (long) tigetflag( (char *)capname ) ); } @@ -4288,7 +4378,8 @@ static PyObject * _curses_tigetnum_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=46f8b0a1b5dff42f input=5cdf2f410b109720]*/ { - PyCursesSetupTermCalled; + _curses_state *state = get__curses_state(module); + PyCursesSetupTermCalled(state); return PyLong_FromLong( (long) tigetnum( (char *)capname ) ); } @@ -4310,7 +4401,8 @@ static PyObject * _curses_tigetstr_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=f22b576ad60248f3 input=36644df25c73c0a7]*/ { - PyCursesSetupTermCalled; + _curses_state *state = get__curses_state(module); + PyCursesSetupTermCalled(state); capname = tigetstr( (char *)capname ); if (capname == NULL || capname == (char*) -1) { @@ -4345,11 +4437,12 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, { char* result = NULL; - PyCursesSetupTermCalled; + _curses_state *state = get__curses_state(module); + PyCursesSetupTermCalled(state); result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9); if (!result) { - PyErr_SetString(PyCursesError, "tparm() returned NULL"); + PyErr_SetString(state->PyCursesError, "tparm() returned NULL"); return NULL; } @@ -4373,9 +4466,10 @@ static PyObject * _curses_typeahead_impl(PyObject *module, int fd) /*[clinic end generated code: output=084bb649d7066583 input=f2968d8e1805051b]*/ { - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); - return PyCursesCheckERR(typeahead( fd ), "typeahead"); + return PyCursesCheckERR(state, typeahead( fd ), "typeahead"); } #endif @@ -4397,7 +4491,8 @@ _curses_unctrl(PyObject *module, PyObject *ch) { chtype ch_; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; @@ -4420,12 +4515,13 @@ _curses_ungetch(PyObject *module, PyObject *ch) { chtype ch_; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; - return PyCursesCheckERR(ungetch(ch_), "ungetch"); + return PyCursesCheckERR(state, ungetch(ch_), "ungetch"); } #ifdef HAVE_NCURSESW @@ -4491,11 +4587,12 @@ _curses_unget_wch(PyObject *module, PyObject *ch) { wchar_t wch; - PyCursesInitialised; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); if (!PyCurses_ConvertToWchar_t(ch, &wch)) return NULL; - return PyCursesCheckERR(unget_wch(wch), "unget_wch"); + return PyCursesCheckERR(state, unget_wch(wch), "unget_wch"); } #endif @@ -4543,14 +4640,15 @@ _curses_use_default_colors_impl(PyObject *module) { int code; - PyCursesInitialised; - PyCursesInitialisedColor; + _curses_state *state = get__curses_state(module); + PyCursesInitialised(state); + PyCursesInitialisedColor(state); code = use_default_colors(); if (code != ERR) { Py_RETURN_NONE; } else { - PyErr_SetString(PyCursesError, "use_default_colors() returned ERR"); + PyErr_SetString(state->PyCursesError, "use_default_colors() returned ERR"); return NULL; } } @@ -4709,83 +4807,72 @@ static PyMethodDef PyCurses_methods[] = { {NULL, NULL} /* sentinel */ }; -/* Initialization function for the module */ - - -static struct PyModuleDef _cursesmodule = { - PyModuleDef_HEAD_INIT, - "_curses", - NULL, - -1, - PyCurses_methods, - NULL, - NULL, - NULL, - NULL -}; - static void -curses_destructor(PyObject *op) +curses_capi_destructor(PyObject *op) { void *ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME); Py_DECREF(*(void **)ptr); PyMem_Free(ptr); } -PyMODINIT_FUNC -PyInit__curses(void) +static int +_curses_exec(PyObject *module) { - PyObject *m, *d, *v, *c_api_object; + PyObject *v, *error, *c_api_object; + PyTypeObject *win_tp; + + _curses_state *state = get__curses_state(module); /* Initialize object type */ - if (PyType_Ready(&PyCursesWindow_Type) < 0) - return NULL; + win_tp = (PyTypeObject *)PyType_FromModuleAndSpec(module, &PyCursesWindow_spec, NULL); + if (win_tp == NULL) + return -1; + if (PyModule_AddType(module, win_tp) < 0) + return -1; + state->PyCursesWindow_Type = win_tp; - /* Create the module and add the functions */ - m = PyModule_Create(&_cursesmodule); - if (m == NULL) - return NULL; + PyObject *d = PyModule_GetDict(module); - /* Add some symbolic constants to the module */ - d = PyModule_GetDict(m); - if (d == NULL) - return NULL; - ModDict = d; /* For PyCurses_InitScr to use later */ + /* For exception curses.error */ + error = PyErr_NewException("_curses.error", NULL, NULL); + if (PyDict_SetItemString(d, "error", error) < 0) { + return -1; + } + state->PyCursesError = error; + state->screen_encoding = NULL; + /* Allocate C API pointer array */ void **PyCurses_API = PyMem_Calloc(PyCurses_API_pointers, sizeof(void *)); if (PyCurses_API == NULL) { PyErr_NoMemory(); - return NULL; + return -1; } /* Initialize the C API pointer array */ - PyCurses_API[0] = (void *)Py_NewRef(&PyCursesWindow_Type); + PyCurses_API[0] = (void *)Py_NewRef(state->PyCursesWindow_Type); PyCurses_API[1] = (void *)func_PyCursesSetupTermCalled; PyCurses_API[2] = (void *)func_PyCursesInitialised; PyCurses_API[3] = (void *)func_PyCursesInitialisedColor; + PyCurses_API[4] = (void *)Py_NewRef(state->PyCursesError); /* Add a capsule for the C API */ - c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, - curses_destructor); + c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, curses_capi_destructor); if (c_api_object == NULL) { Py_DECREF(PyCurses_API[0]); PyMem_Free(PyCurses_API); - return NULL; + return -1; } if (PyDict_SetItemString(d, "_C_API", c_api_object) < 0) { - Py_DECREF(c_api_object); - return NULL; + return -1; } - Py_DECREF(c_api_object); - - /* For exception curses.error */ - PyCursesError = PyErr_NewException("_curses.error", NULL, NULL); - PyDict_SetItemString(d, "error", PyCursesError); /* Make the version available */ v = PyBytes_FromString(PyCursesVersion); - PyDict_SetItemString(d, "version", v); - PyDict_SetItemString(d, "__version__", v); - Py_DECREF(v); + if (PyDict_SetItemString(d, "version", v) < 0) { + return -1; + } + if (PyDict_SetItemString(d, "__version__", v) < 0) { + return -1; + } #ifdef NCURSES_VERSION /* ncurses_version */ @@ -4793,110 +4880,110 @@ PyInit__curses(void) version_type = _PyStructSequence_NewType(&ncurses_version_desc, Py_TPFLAGS_DISALLOW_INSTANTIATION); if (version_type == NULL) { - return NULL; + return -1; } v = make_ncurses_version(version_type); - Py_DECREF(version_type); if (v == NULL) { - return NULL; + return -1; + } + if (PyDict_SetItemString(d, "ncurses_version", v) < 0) { + return -1; } - PyDict_SetItemString(d, "ncurses_version", v); - Py_DECREF(v); #endif /* NCURSES_VERSION */ - SetDictInt("ERR", ERR); - SetDictInt("OK", OK); + SetDictInt(d, "ERR", ERR); + SetDictInt(d, "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); + SetDictInt(d, "A_ATTRIBUTES", A_ATTRIBUTES); + SetDictInt(d, "A_NORMAL", A_NORMAL); + SetDictInt(d, "A_STANDOUT", A_STANDOUT); + SetDictInt(d, "A_UNDERLINE", A_UNDERLINE); + SetDictInt(d, "A_REVERSE", A_REVERSE); + SetDictInt(d, "A_BLINK", A_BLINK); + SetDictInt(d, "A_DIM", A_DIM); + SetDictInt(d, "A_BOLD", A_BOLD); + SetDictInt(d, "A_ALTCHARSET", A_ALTCHARSET); + SetDictInt(d, "A_INVIS", A_INVIS); + SetDictInt(d, "A_PROTECT", A_PROTECT); + SetDictInt(d, "A_CHARTEXT", A_CHARTEXT); + SetDictInt(d, "A_COLOR", A_COLOR); /* The following are never available with strict SYSV curses */ #ifdef A_HORIZONTAL - SetDictInt("A_HORIZONTAL", A_HORIZONTAL); + SetDictInt(d, "A_HORIZONTAL", A_HORIZONTAL); #endif #ifdef A_LEFT - SetDictInt("A_LEFT", A_LEFT); + SetDictInt(d, "A_LEFT", A_LEFT); #endif #ifdef A_LOW - SetDictInt("A_LOW", A_LOW); + SetDictInt(d, "A_LOW", A_LOW); #endif #ifdef A_RIGHT - SetDictInt("A_RIGHT", A_RIGHT); + SetDictInt(d, "A_RIGHT", A_RIGHT); #endif #ifdef A_TOP - SetDictInt("A_TOP", A_TOP); + SetDictInt(d, "A_TOP", A_TOP); #endif #ifdef A_VERTICAL - SetDictInt("A_VERTICAL", A_VERTICAL); + SetDictInt(d, "A_VERTICAL", A_VERTICAL); #endif /* ncurses extension */ #ifdef A_ITALIC - SetDictInt("A_ITALIC", A_ITALIC); + SetDictInt(d, "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); + SetDictInt(d, "COLOR_BLACK", COLOR_BLACK); + SetDictInt(d, "COLOR_RED", COLOR_RED); + SetDictInt(d, "COLOR_GREEN", COLOR_GREEN); + SetDictInt(d, "COLOR_YELLOW", COLOR_YELLOW); + SetDictInt(d, "COLOR_BLUE", COLOR_BLUE); + SetDictInt(d, "COLOR_MAGENTA", COLOR_MAGENTA); + SetDictInt(d, "COLOR_CYAN", COLOR_CYAN); + SetDictInt(d, "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); + SetDictInt(d, "BUTTON1_PRESSED", BUTTON1_PRESSED); + SetDictInt(d, "BUTTON1_RELEASED", BUTTON1_RELEASED); + SetDictInt(d, "BUTTON1_CLICKED", BUTTON1_CLICKED); + SetDictInt(d, "BUTTON1_DOUBLE_CLICKED", BUTTON1_DOUBLE_CLICKED); + SetDictInt(d, "BUTTON1_TRIPLE_CLICKED", BUTTON1_TRIPLE_CLICKED); + + SetDictInt(d, "BUTTON2_PRESSED", BUTTON2_PRESSED); + SetDictInt(d, "BUTTON2_RELEASED", BUTTON2_RELEASED); + SetDictInt(d, "BUTTON2_CLICKED", BUTTON2_CLICKED); + SetDictInt(d, "BUTTON2_DOUBLE_CLICKED", BUTTON2_DOUBLE_CLICKED); + SetDictInt(d, "BUTTON2_TRIPLE_CLICKED", BUTTON2_TRIPLE_CLICKED); + + SetDictInt(d, "BUTTON3_PRESSED", BUTTON3_PRESSED); + SetDictInt(d, "BUTTON3_RELEASED", BUTTON3_RELEASED); + SetDictInt(d, "BUTTON3_CLICKED", BUTTON3_CLICKED); + SetDictInt(d, "BUTTON3_DOUBLE_CLICKED", BUTTON3_DOUBLE_CLICKED); + SetDictInt(d, "BUTTON3_TRIPLE_CLICKED", BUTTON3_TRIPLE_CLICKED); + + SetDictInt(d, "BUTTON4_PRESSED", BUTTON4_PRESSED); + SetDictInt(d, "BUTTON4_RELEASED", BUTTON4_RELEASED); + SetDictInt(d, "BUTTON4_CLICKED", BUTTON4_CLICKED); + SetDictInt(d, "BUTTON4_DOUBLE_CLICKED", BUTTON4_DOUBLE_CLICKED); + SetDictInt(d, "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); + SetDictInt(d, "BUTTON5_PRESSED", BUTTON5_PRESSED); + SetDictInt(d, "BUTTON5_RELEASED", BUTTON5_RELEASED); + SetDictInt(d, "BUTTON5_CLICKED", BUTTON5_CLICKED); + SetDictInt(d, "BUTTON5_DOUBLE_CLICKED", BUTTON5_DOUBLE_CLICKED); + SetDictInt(d, "BUTTON5_TRIPLE_CLICKED", BUTTON5_TRIPLE_CLICKED); #endif - SetDictInt("BUTTON_SHIFT", BUTTON_SHIFT); - SetDictInt("BUTTON_CTRL", BUTTON_CTRL); - SetDictInt("BUTTON_ALT", BUTTON_ALT); + SetDictInt(d, "BUTTON_SHIFT", BUTTON_SHIFT); + SetDictInt(d, "BUTTON_CTRL", BUTTON_CTRL); + SetDictInt(d, "BUTTON_ALT", BUTTON_ALT); - SetDictInt("ALL_MOUSE_EVENTS", ALL_MOUSE_EVENTS); - SetDictInt("REPORT_MOUSE_POSITION", REPORT_MOUSE_POSITION); + SetDictInt(d, "ALL_MOUSE_EVENTS", ALL_MOUSE_EVENTS); + SetDictInt(d, "REPORT_MOUSE_POSITION", REPORT_MOUSE_POSITION); #endif /* Now set everything up for KEY_ variables */ { @@ -4926,16 +5013,38 @@ PyInit__curses(void) *p2 = (char)0; } else key_n2 = key_n; - SetDictInt(key_n2,key); + SetDictInt(d, key_n2,key); if (key_n2 != key_n) PyMem_Free(key_n2); } - SetDictInt("KEY_MIN", KEY_MIN); - SetDictInt("KEY_MAX", KEY_MAX); + SetDictInt(d, "KEY_MIN", KEY_MIN); + SetDictInt(d, "KEY_MAX", KEY_MAX); } - if (PyModule_AddType(m, &PyCursesWindow_Type) < 0) { - return NULL; - } - return m; + return 0; +} + + +static struct PyModuleDef_Slot _curses_slots[] = { + {Py_mod_exec, _curses_exec}, + {0, NULL} +}; + + +static struct PyModuleDef _curses_module = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_curses", + .m_size = sizeof(_curses_state), + .m_methods = PyCurses_methods, + .m_slots = _curses_slots, + .m_traverse = _curses_traverse, + .m_clear = _curses_clear, + .m_free = _curses_free +}; + + +PyMODINIT_FUNC +PyInit__curses(void) +{ + return PyModuleDef_Init(&_curses_module); } diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index 9d99d41af5d2d9..cab222fea0c311 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -1389,12 +1389,12 @@ _curses_window_overlay(PyCursesWindowObject *self, PyObject *args) switch (PyTuple_GET_SIZE(args)) { case 1: - if (!PyArg_ParseTuple(args, "O!:overlay", &PyCursesWindow_Type, &destwin)) { + if (!PyArg_ParseTuple(args, "O!:overlay", clinic_state()->PyCursesWindow_Type, &destwin)) { goto exit; } break; case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii:overlay", &PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + if (!PyArg_ParseTuple(args, "O!iiiiii:overlay", clinic_state()->PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { goto exit; } group_right_1 = 1; @@ -1448,12 +1448,12 @@ _curses_window_overwrite(PyCursesWindowObject *self, PyObject *args) switch (PyTuple_GET_SIZE(args)) { case 1: - if (!PyArg_ParseTuple(args, "O!:overwrite", &PyCursesWindow_Type, &destwin)) { + if (!PyArg_ParseTuple(args, "O!:overwrite", clinic_state()->PyCursesWindow_Type, &destwin)) { goto exit; } break; case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii:overwrite", &PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + if (!PyArg_ParseTuple(args, "O!iiiiii:overwrite", clinic_state()->PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { goto exit; } group_right_1 = 1; @@ -4313,4 +4313,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored #ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF #define _CURSES_USE_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=27a2364193b503c1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=eac5ea1b55606da0 input=a9049054013a1b77]*/ From aad895f47a087461637e3b1f2a9132a47415e6e5 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Mon, 22 May 2023 03:10:02 +0300 Subject: [PATCH 02/12] changed C API funcs to accept pointer to exception, removed excess decref in _curses_exec --- Include/py_curses.h | 6 +++--- Modules/_cursesmodule.c | 13 ++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Include/py_curses.h b/Include/py_curses.h index 089bae4f4abf20..0ef4b545119bf6 100644 --- a/Include/py_curses.h +++ b/Include/py_curses.h @@ -79,9 +79,9 @@ typedef struct { static void **PyCurses_API; #define PyCursesWindow_Type (*_PyType_CAST(PyCurses_API[0])) -#define PyCursesSetupTermCalled {if (! ((int (*)(void **))PyCurses_API[1]) (PyCurses_API) ) return NULL;} -#define PyCursesInitialised {if (! ((int (*)(void **))PyCurses_API[2]) (PyCurses_API) ) return NULL;} -#define PyCursesInitialisedColor {if (! ((int (*)(void **))PyCurses_API[3]) (PyCurses_API) ) return NULL;} +#define PyCursesSetupTermCalled {if (! ((int (*)(void *))PyCurses_API[1]) (PyCurses_API[4]) ) return NULL;} +#define PyCursesInitialised {if (! ((int (*)(void *))PyCurses_API[2]) (PyCurses_API[4]) ) return NULL;} +#define PyCursesInitialisedColor {if (! ((int (*)(void *))PyCurses_API[3]) (PyCurses_API[4]) ) return NULL;} #define import_curses() \ PyCurses_API = (void **)PyCapsule_Import(PyCurses_CAPSULE_NAME, 1); diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 2d9a15ef95d735..cc4f5db449adfa 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -579,30 +579,30 @@ class component_converter(CConverter): initialised or not. */ -static int func_PyCursesSetupTermCalled(void **api) +static int func_PyCursesSetupTermCalled(void *exc) { if (initialised_setupterm != TRUE) { - PyErr_SetString(api[4], + PyErr_SetString((PyObject *)exc, "must call (at least) setupterm() first"); return 0; } return 1; } -static int func_PyCursesInitialised(void **api) +static int func_PyCursesInitialised(void *exc) { if (initialised != TRUE) { - PyErr_SetString(api[4], + PyErr_SetString((PyObject *)exc, "must call initscr() first"); return 0; } return 1; } -static int func_PyCursesInitialisedColor(void **api) +static int func_PyCursesInitialisedColor(void *exc) { if (initialisedcolors != TRUE) { - PyErr_SetString(api[4], + PyErr_SetString((PyObject *)exc, "must call start_color() first"); return 0; } @@ -4857,7 +4857,6 @@ _curses_exec(PyObject *module) /* Add a capsule for the C API */ c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, curses_capi_destructor); if (c_api_object == NULL) { - Py_DECREF(PyCurses_API[0]); PyMem_Free(PyCurses_API); return -1; } From 9d5e52e9639e8ddcc57a73d74bb763cd22cf2684 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Tue, 23 May 2023 02:23:07 +0300 Subject: [PATCH 03/12] * made `_curses.window` type immutable * added `__reduce__` method to `_curses.window` type to make it non-pickable, as its static version was * added tests to check if `_curses.window` is non-instantiable/non-picklable/immutable * moved `SetDictInt` macro from function body * added NULL check for value returned by `PyCursesWindow_New` in `_curses_initscr_impl` --- Lib/test/test_curses.py | 14 ++++++++++++ Modules/_cursesmodule.c | 39 ++++++++++++++++++++++++-------- Modules/clinic/_cursesmodule.c.h | 19 +++++++++++++++- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index 3ab837e4f95681..b6923a35252e24 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -1,6 +1,7 @@ import functools import inspect import os +import pickle import string import sys import tempfile @@ -1179,6 +1180,19 @@ def test_issue13051(self): # this may cause infinite recursion, leading to a RuntimeError box._insert_printable_char('a') + def test_window_non_instantiable(self): + # Ensure that '_curses.window' type in not directly instantiable + check_disallow_instantiation(self, curses.window) + + def test_window_immutable(self): + with self.assertRaisesRegex(TypeError, "immutable"): + curses.window.foo = 123 + + def test_window_non_picklable(self): + win = curses.newwin(10, 10) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + self.assertRaises(TypeError, pickle.dumps, win, proto) + class MiscTests(unittest.TestCase): diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index cc4f5db449adfa..30d7b48e02b432 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -2534,6 +2534,21 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value, void *P return 0; } +/*[clinic input] +_curses.window.__reduce__ +[clinic start generated code]*/ + +static PyObject * +_curses_window___reduce___impl(PyCursesWindowObject *self) +/*[clinic end generated code: output=5d438a482619b25a input=cc7e2066b8e918b9]*/ +{ + PyErr_Format(PyExc_TypeError, + "cannot pickle %s object", + Py_TYPE(self)->tp_name); + return NULL; +} + + #define clinic_state() (find__curses_state_by_type(Py_TYPE(self))) #include "clinic/_cursesmodule.c.h" #undef clinic_state @@ -2621,6 +2636,7 @@ static PyMethodDef PyCursesWindow_Methods[] = { {"touchwin", (PyCFunction)PyCursesWindow_touchwin, METH_NOARGS}, {"untouchwin", (PyCFunction)PyCursesWindow_untouchwin, METH_NOARGS}, _CURSES_WINDOW_VLINE_METHODDEF + _CURSES_WINDOW___REDUCE___METHODDEF {NULL, NULL} /* sentinel */ }; @@ -2644,7 +2660,8 @@ static PyType_Slot PyCursesWindow_slots[] = { static PyType_Spec PyCursesWindow_spec = { .name = "_curses.window", .basicsize = sizeof(PyCursesWindowObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE + | Py_TPFLAGS_DISALLOW_INSTANTIATION, .slots = PyCursesWindow_slots }; @@ -2794,7 +2811,6 @@ _curses_color_content_impl(PyObject *module, int color_number) _CURSES_COLOR_VAL_TYPE r,g,b; _curses_state *state = get__curses_state(module); - PyCursesInitialised(state); PyCursesInitialisedColor(state); @@ -3301,6 +3317,14 @@ _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) Py_RETURN_NONE; } +#define SetDictInt(dict, string,ch) \ + do { \ + PyObject *o = PyLong_FromLong((long) (ch)); \ + if (o && PyDict_SetItemString(dict, string, o) == 0) { \ + Py_DECREF(o); \ + } \ + } while (0) + /*[clinic input] _curses.initscr @@ -3334,14 +3358,6 @@ _curses_initscr_impl(PyObject *module) /* This was moved from initcurses() because it core dumped on SGI, where they're not defined until you've called initscr() */ -#define SetDictInt(dict, string,ch) \ - do { \ - PyObject *o = PyLong_FromLong((long) (ch)); \ - if (o && PyDict_SetItemString(dict, string, o) == 0) { \ - Py_DECREF(o); \ - } \ - } while (0) - PyObject *d = PyModule_GetDict(module); /* Here are some graphic symbols you can use */ SetDictInt(d, "ACS_ULCORNER", (ACS_ULCORNER)); @@ -3414,6 +3430,9 @@ _curses_initscr_impl(PyObject *module) SetDictInt(d, "COLS", COLS); winobj = (PyCursesWindowObject *)PyCursesWindow_New(state, win, NULL); + if (winobj == NULL) { + return NULL; + } state->screen_encoding = winobj->encoding; return (PyObject *)winobj; } diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index cab222fea0c311..3e660ed546cf17 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -1833,6 +1833,23 @@ _curses_window_vline(PyCursesWindowObject *self, PyObject *args) return return_value; } +PyDoc_STRVAR(_curses_window___reduce____doc__, +"__reduce__($self, /)\n" +"--\n" +"\n"); + +#define _CURSES_WINDOW___REDUCE___METHODDEF \ + {"__reduce__", (PyCFunction)_curses_window___reduce__, METH_NOARGS, _curses_window___reduce____doc__}, + +static PyObject * +_curses_window___reduce___impl(PyCursesWindowObject *self); + +static PyObject * +_curses_window___reduce__(PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_window___reduce___impl(self); +} + #if defined(HAVE_CURSES_FILTER) PyDoc_STRVAR(_curses_filter__doc__, @@ -4313,4 +4330,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored #ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF #define _CURSES_USE_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=eac5ea1b55606da0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7a49be78fe2f4adc input=a9049054013a1b77]*/ From d3bcb2ba9831b15a83a5b5e81c3188b0c97e0da4 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 23:25:01 +0000 Subject: [PATCH 04/12] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2023-05-22-23-24-58.gh-issue-101714.iw8L88.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2023-05-22-23-24-58.gh-issue-101714.iw8L88.rst diff --git a/Misc/NEWS.d/next/Library/2023-05-22-23-24-58.gh-issue-101714.iw8L88.rst b/Misc/NEWS.d/next/Library/2023-05-22-23-24-58.gh-issue-101714.iw8L88.rst new file mode 100644 index 00000000000000..465052db941021 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-22-23-24-58.gh-issue-101714.iw8L88.rst @@ -0,0 +1 @@ +Isolate :mod:`!_curses` (apply :pep:`687`). Patch by Radislav Chugunov. From a27c444ee37ddd0a81f167661b558848731a7d2a Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Tue, 23 May 2023 03:51:40 +0300 Subject: [PATCH 05/12] cosmetic change in _curses_exec --- Modules/_cursesmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 30d7b48e02b432..d59eeaf45ed32b 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -4837,7 +4837,7 @@ curses_capi_destructor(PyObject *op) static int _curses_exec(PyObject *module) { - PyObject *v, *error, *c_api_object; + PyObject *d, *v, *error, *c_api_object; PyTypeObject *win_tp; _curses_state *state = get__curses_state(module); @@ -4850,7 +4850,7 @@ _curses_exec(PyObject *module) return -1; state->PyCursesWindow_Type = win_tp; - PyObject *d = PyModule_GetDict(module); + d = PyModule_GetDict(module); /* For exception curses.error */ error = PyErr_NewException("_curses.error", NULL, NULL); From ebda40d80b437ae17af579541940ad987af9e7cc Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Wed, 24 May 2023 20:37:57 +0300 Subject: [PATCH 06/12] * added Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED flag to module def slots for a while * removed excess newline characters --- Modules/_cursesmodule.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index d59eeaf45ed32b..8d34f06ad5b16f 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -183,10 +183,8 @@ typedef struct _curses_state { char *screen_encoding; } _curses_state; - static struct PyModuleDef _curses_module; - static inline _curses_state * get__curses_state(PyObject *mod) { @@ -203,7 +201,6 @@ find__curses_state_by_type(PyTypeObject *type) return get__curses_state(mod); } - static int _curses_clear(PyObject *mod) { @@ -2548,7 +2545,6 @@ _curses_window___reduce___impl(PyCursesWindowObject *self) return NULL; } - #define clinic_state() (find__curses_state_by_type(Py_TYPE(self))) #include "clinic/_cursesmodule.c.h" #undef clinic_state @@ -5042,13 +5038,12 @@ _curses_exec(PyObject *module) return 0; } - static struct PyModuleDef_Slot _curses_slots[] = { {Py_mod_exec, _curses_exec}, + {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, {0, NULL} }; - static struct PyModuleDef _curses_module = { .m_base = PyModuleDef_HEAD_INIT, .m_name = "_curses", @@ -5060,7 +5055,6 @@ static struct PyModuleDef _curses_module = { .m_free = _curses_free }; - PyMODINIT_FUNC PyInit__curses(void) { From 64852b32697c7aad9bcb2367f5b42c436fda49e7 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Mon, 29 May 2023 15:06:56 +0300 Subject: [PATCH 07/12] removed useless underscore --- Modules/_cursesmodule.c | 112 ++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 8d34f06ad5b16f..57cd90446bc03b 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -186,7 +186,7 @@ typedef struct _curses_state { static struct PyModuleDef _curses_module; static inline _curses_state * -get__curses_state(PyObject *mod) +get_curses_state(PyObject *mod) { void *state = PyModule_GetState(mod); assert (state != NULL); @@ -194,17 +194,17 @@ get__curses_state(PyObject *mod) } static inline _curses_state * -find__curses_state_by_type(PyTypeObject *type) +find_curses_state_by_type(PyTypeObject *type) { PyObject *mod = PyType_GetModuleByDef(type, &_curses_module); assert(mod != NULL); - return get__curses_state(mod); + return get_curses_state(mod); } static int _curses_clear(PyObject *mod) { - _curses_state *state = get__curses_state(mod); + _curses_state *state = get_curses_state(mod); Py_CLEAR(state->PyCursesWindow_Type); Py_CLEAR(state->PyCursesError); return 0; @@ -213,7 +213,7 @@ _curses_clear(PyObject *mod) static int _curses_traverse(PyObject *mod, visitproc visit, void *arg) { - _curses_state *state = get__curses_state(mod); + _curses_state *state = get_curses_state(mod); Py_VISIT(state->PyCursesWindow_Type); Py_VISIT(state->PyCursesError); return 0; @@ -2545,7 +2545,7 @@ _curses_window___reduce___impl(PyCursesWindowObject *self) return NULL; } -#define clinic_state() (find__curses_state_by_type(Py_TYPE(self))) +#define clinic_state() (find_curses_state_by_type(Py_TYPE(self))) #include "clinic/_cursesmodule.c.h" #undef clinic_state @@ -2672,13 +2672,13 @@ static PyType_Spec PyCursesWindow_spec = { #define NoArgNoReturnFunctionBody(X) \ { \ - _curses_state *state = get__curses_state(module); \ + _curses_state *state = get_curses_state(module); \ PyCursesInitialised(state) \ return PyCursesCheckERR(state, X(), # X); } #define NoArgOrFlagNoReturnFunctionBody(X, flag) \ { \ - _curses_state *state = get__curses_state(module); \ + _curses_state *state = get_curses_state(module); \ PyCursesInitialised(state) \ if (flag) \ return PyCursesCheckERR(state, X(), # X); \ @@ -2688,26 +2688,26 @@ static PyType_Spec PyCursesWindow_spec = { #define NoArgReturnIntFunctionBody(X) \ { \ - _curses_state *state = get__curses_state(module); \ + _curses_state *state = get_curses_state(module); \ PyCursesInitialised(state) \ return PyLong_FromLong((long) X()); } #define NoArgReturnStringFunctionBody(X) \ { \ - _curses_state *state = get__curses_state(module); \ + _curses_state *state = get_curses_state(module); \ PyCursesInitialised(state) \ return PyBytes_FromString(X()); } #define NoArgTrueFalseFunctionBody(X) \ { \ - _curses_state *state = get__curses_state(module); \ + _curses_state *state = get_curses_state(module); \ PyCursesInitialised(state) \ return PyBool_FromLong(X()); } #define NoArgNoReturnVoidFunctionBody(X) \ { \ - _curses_state *state = get__curses_state(module); \ + _curses_state *state = get_curses_state(module); \ PyCursesInitialised(state) \ X(); \ Py_RETURN_NONE; } @@ -2806,7 +2806,7 @@ _curses_color_content_impl(PyObject *module, int color_number) { _CURSES_COLOR_VAL_TYPE r,g,b; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); PyCursesInitialisedColor(state); @@ -2836,7 +2836,7 @@ static PyObject * _curses_color_pair_impl(PyObject *module, int pair_number) /*[clinic end generated code: output=60718abb10ce9feb input=6034e9146f343802]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); PyCursesInitialisedColor(state); @@ -2864,7 +2864,7 @@ _curses_curs_set_impl(PyObject *module, int visibility) { int erg; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); erg = curs_set(visibility); @@ -2917,7 +2917,7 @@ static PyObject * _curses_delay_output_impl(PyObject *module, int ms) /*[clinic end generated code: output=b6613a67f17fa4f4 input=5316457f5f59196c]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); return PyCursesCheckERR(state, delay_output(ms), "delay_output"); @@ -2974,7 +2974,7 @@ _curses_erasechar_impl(PyObject *module) { char ch; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); ch = erasechar(); @@ -3025,7 +3025,7 @@ _curses_getsyx_impl(PyObject *module) int x = 0; int y = 0; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); getsyx(y, x); @@ -3051,7 +3051,7 @@ _curses_getmouse_impl(PyObject *module) int rtn; MEVENT event; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); rtn = getmouse( &event ); @@ -3087,7 +3087,7 @@ _curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, { MEVENT event; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); event.id = id; @@ -3121,7 +3121,7 @@ _curses_getwin(PyObject *module, PyObject *file) WINDOW *win; PyObject *res = NULL; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); fp = tmpfile(); @@ -3178,7 +3178,7 @@ static PyObject * _curses_halfdelay_impl(PyObject *module, unsigned char tenths) /*[clinic end generated code: output=e92cdf0ef33c0663 input=e42dce7259c15100]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); return PyCursesCheckERR(state, halfdelay(tenths), "halfdelay"); @@ -3232,7 +3232,7 @@ static PyObject * _curses_has_key_impl(PyObject *module, int key) /*[clinic end generated code: output=19ad48319414d0b1 input=78bd44acf1a4997c]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); return PyBool_FromLong(has_key(key)); @@ -3264,7 +3264,7 @@ _curses_init_color_impl(PyObject *module, int color_number, short r, short g, short b) /*[clinic end generated code: output=d7ed71b2d818cdf2 input=ae2b8bea0f152c80]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); PyCursesInitialisedColor(state); @@ -3293,7 +3293,7 @@ static PyObject * _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) /*[clinic end generated code: output=a0bba03d2bbc3ee6 input=54b421b44c12c389]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); PyCursesInitialisedColor(state); @@ -3336,7 +3336,7 @@ _curses_initscr_impl(PyObject *module) WINDOW *win; PyCursesWindowObject *winobj; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); if (initialised) { wrefresh(stdscr); @@ -3452,7 +3452,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) { int err; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); if (fd == -1) { PyObject* sys_stdout; @@ -3532,7 +3532,7 @@ _curses_set_escdelay_impl(PyObject *module, int ms) return NULL; } - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); return PyCursesCheckERR(state, set_escdelay(ms), "set_escdelay"); } @@ -3573,7 +3573,7 @@ _curses_set_tabsize_impl(PyObject *module, int size) return NULL; } - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); return PyCursesCheckERR(state, set_tabsize(size), "set_tabsize"); } @@ -3591,7 +3591,7 @@ static PyObject * _curses_intrflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=c1986df35e999a0f input=c65fe2ef973fe40a]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); return PyCursesCheckERR(state, intrflush(NULL, flag), "intrflush"); @@ -3625,7 +3625,7 @@ static PyObject * _curses_is_term_resized_impl(PyObject *module, int nlines, int ncols) /*[clinic end generated code: output=aafe04afe50f1288 input=ca9c0bd0fb8ab444]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); return PyBool_FromLong(is_term_resized(nlines, ncols)); @@ -3648,7 +3648,7 @@ _curses_keyname_impl(PyObject *module, int key) { const char *knp; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); if (key < 0) { @@ -3707,7 +3707,7 @@ static PyObject * _curses_meta_impl(PyObject *module, int yes) /*[clinic end generated code: output=22f5abda46a605d8 input=cfe7da79f51d0e30]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); return PyCursesCheckERR(state, meta(stdscr, yes), "meta"); @@ -3732,7 +3732,7 @@ static PyObject * _curses_mouseinterval_impl(PyObject *module, int interval) /*[clinic end generated code: output=c4f5ff04354634c5 input=75aaa3f0db10ac4e]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); return PyCursesCheckERR(state, mouseinterval(interval), "mouseinterval"); @@ -3758,7 +3758,7 @@ _curses_mousemask_impl(PyObject *module, unsigned long newmask) { mmask_t oldmask, availmask; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); availmask = mousemask((mmask_t)newmask, &oldmask); return Py_BuildValue("(kk)", @@ -3780,7 +3780,7 @@ static PyObject * _curses_napms_impl(PyObject *module, int ms) /*[clinic end generated code: output=a40a1da2e39ea438 input=20cd3af2b6900f56]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); return Py_BuildValue("i", napms(ms)); @@ -3805,7 +3805,7 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) { WINDOW *win; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); win = newpad(nlines, ncols); @@ -3846,7 +3846,7 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, { WINDOW *win; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); win = newwin(nlines,ncols,begin_y,begin_x); @@ -3959,7 +3959,7 @@ _curses_pair_content_impl(PyObject *module, int pair_number) { _CURSES_COLOR_NUM_TYPE f, b; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); PyCursesInitialisedColor(state); @@ -3994,7 +3994,7 @@ static PyObject * _curses_pair_number_impl(PyObject *module, int attr) /*[clinic end generated code: output=85bce7d65c0aa3f4 input=d478548e33f5e61a]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); PyCursesInitialisedColor(state); @@ -4016,7 +4016,7 @@ static PyObject * _curses_putp_impl(PyObject *module, const char *string) /*[clinic end generated code: output=e98081d1b8eb5816 input=1601faa828b44cb3]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); return PyCursesCheckERR(state, putp(string), "putp"); } @@ -4037,7 +4037,7 @@ static PyObject * _curses_qiflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=9167e862f760ea30 input=6ec8b3e2b717ec40]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); if (flag) { @@ -4189,7 +4189,7 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols) { PyObject *result; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); result = PyCursesCheckERR(state, resizeterm(nlines, ncols), "resizeterm"); @@ -4229,7 +4229,7 @@ _curses_resize_term_impl(PyObject *module, int nlines, int ncols) { PyObject *result; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); result = PyCursesCheckERR(state, resize_term(nlines, ncols), "resize_term"); @@ -4273,7 +4273,7 @@ static PyObject * _curses_setsyx_impl(PyObject *module, int y, int x) /*[clinic end generated code: output=23dcf753511a2464 input=fa7f2b208e10a557]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); setsyx(y,x); @@ -4302,7 +4302,7 @@ _curses_start_color_impl(PyObject *module) int code; PyObject *c, *cp; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); code = start_color(); @@ -4370,7 +4370,7 @@ static PyObject * _curses_tigetflag_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=8853c0e55542195b input=b0787af9e3e9a6ce]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesSetupTermCalled(state); return PyLong_FromLong( (long) tigetflag( (char *)capname ) ); @@ -4393,7 +4393,7 @@ static PyObject * _curses_tigetnum_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=46f8b0a1b5dff42f input=5cdf2f410b109720]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesSetupTermCalled(state); return PyLong_FromLong( (long) tigetnum( (char *)capname ) ); @@ -4416,7 +4416,7 @@ static PyObject * _curses_tigetstr_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=f22b576ad60248f3 input=36644df25c73c0a7]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesSetupTermCalled(state); capname = tigetstr( (char *)capname ); @@ -4452,7 +4452,7 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, { char* result = NULL; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesSetupTermCalled(state); result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9); @@ -4481,7 +4481,7 @@ static PyObject * _curses_typeahead_impl(PyObject *module, int fd) /*[clinic end generated code: output=084bb649d7066583 input=f2968d8e1805051b]*/ { - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); return PyCursesCheckERR(state, typeahead( fd ), "typeahead"); @@ -4506,7 +4506,7 @@ _curses_unctrl(PyObject *module, PyObject *ch) { chtype ch_; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) @@ -4530,7 +4530,7 @@ _curses_ungetch(PyObject *module, PyObject *ch) { chtype ch_; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) @@ -4602,7 +4602,7 @@ _curses_unget_wch(PyObject *module, PyObject *ch) { wchar_t wch; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); if (!PyCurses_ConvertToWchar_t(ch, &wch)) @@ -4655,7 +4655,7 @@ _curses_use_default_colors_impl(PyObject *module) { int code; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); PyCursesInitialised(state); PyCursesInitialisedColor(state); @@ -4836,7 +4836,7 @@ _curses_exec(PyObject *module) PyObject *d, *v, *error, *c_api_object; PyTypeObject *win_tp; - _curses_state *state = get__curses_state(module); + _curses_state *state = get_curses_state(module); /* Initialize object type */ win_tp = (PyTypeObject *)PyType_FromModuleAndSpec(module, &PyCursesWindow_spec, NULL); From 75a1c2f4a67f00cf97d50e43f6931d1c5918d2c5 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Fri, 2 Jun 2023 22:28:30 +0300 Subject: [PATCH 08/12] omitted state value assignments when state value is used just once --- Modules/_cursesmodule.c | 62 +++++++++++++---------------------------- 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 57cd90446bc03b..0a3ad5a69f2924 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -2688,27 +2688,23 @@ static PyType_Spec PyCursesWindow_spec = { #define NoArgReturnIntFunctionBody(X) \ { \ - _curses_state *state = get_curses_state(module); \ - PyCursesInitialised(state) \ + PyCursesInitialised(get_curses_state(module)) \ return PyLong_FromLong((long) X()); } #define NoArgReturnStringFunctionBody(X) \ { \ - _curses_state *state = get_curses_state(module); \ - PyCursesInitialised(state) \ + PyCursesInitialised(get_curses_state(module)) \ return PyBytes_FromString(X()); } #define NoArgTrueFalseFunctionBody(X) \ { \ - _curses_state *state = get_curses_state(module); \ - PyCursesInitialised(state) \ + PyCursesInitialised(get_curses_state(module)) \ return PyBool_FromLong(X()); } #define NoArgNoReturnVoidFunctionBody(X) \ { \ - _curses_state *state = get_curses_state(module); \ - PyCursesInitialised(state) \ + PyCursesInitialised(get_curses_state(module)) \ X(); \ Py_RETURN_NONE; } @@ -2974,8 +2970,7 @@ _curses_erasechar_impl(PyObject *module) { char ch; - _curses_state *state = get_curses_state(module); - PyCursesInitialised(state); + PyCursesInitialised(get_curses_state(module)); ch = erasechar(); @@ -3025,8 +3020,7 @@ _curses_getsyx_impl(PyObject *module) int x = 0; int y = 0; - _curses_state *state = get_curses_state(module); - PyCursesInitialised(state); + PyCursesInitialised(get_curses_state(module)); getsyx(y, x); @@ -3232,8 +3226,7 @@ static PyObject * _curses_has_key_impl(PyObject *module, int key) /*[clinic end generated code: output=19ad48319414d0b1 input=78bd44acf1a4997c]*/ { - _curses_state *state = get_curses_state(module); - PyCursesInitialised(state); + PyCursesInitialised(get_curses_state(module)); return PyBool_FromLong(has_key(key)); } @@ -3532,9 +3525,7 @@ _curses_set_escdelay_impl(PyObject *module, int ms) return NULL; } - _curses_state *state = get_curses_state(module); - - return PyCursesCheckERR(state, set_escdelay(ms), "set_escdelay"); + return PyCursesCheckERR(get_curses_state(module), set_escdelay(ms), "set_escdelay"); } /*[clinic input] @@ -3573,9 +3564,7 @@ _curses_set_tabsize_impl(PyObject *module, int size) return NULL; } - _curses_state *state = get_curses_state(module); - - return PyCursesCheckERR(state, set_tabsize(size), "set_tabsize"); + return PyCursesCheckERR(get_curses_state(module), set_tabsize(size), "set_tabsize"); } #endif @@ -3625,8 +3614,7 @@ static PyObject * _curses_is_term_resized_impl(PyObject *module, int nlines, int ncols) /*[clinic end generated code: output=aafe04afe50f1288 input=ca9c0bd0fb8ab444]*/ { - _curses_state *state = get_curses_state(module); - PyCursesInitialised(state); + PyCursesInitialised(get_curses_state(module)); return PyBool_FromLong(is_term_resized(nlines, ncols)); } @@ -3648,8 +3636,7 @@ _curses_keyname_impl(PyObject *module, int key) { const char *knp; - _curses_state *state = get_curses_state(module); - PyCursesInitialised(state); + PyCursesInitialised(get_curses_state(module)); if (key < 0) { PyErr_SetString(PyExc_ValueError, "invalid key number"); @@ -3758,8 +3745,7 @@ _curses_mousemask_impl(PyObject *module, unsigned long newmask) { mmask_t oldmask, availmask; - _curses_state *state = get_curses_state(module); - PyCursesInitialised(state); + PyCursesInitialised(get_curses_state(module)); availmask = mousemask((mmask_t)newmask, &oldmask); return Py_BuildValue("(kk)", (unsigned long)availmask, (unsigned long)oldmask); @@ -3780,8 +3766,7 @@ static PyObject * _curses_napms_impl(PyObject *module, int ms) /*[clinic end generated code: output=a40a1da2e39ea438 input=20cd3af2b6900f56]*/ { - _curses_state *state = get_curses_state(module); - PyCursesInitialised(state); + PyCursesInitialised(get_curses_state(module)); return Py_BuildValue("i", napms(ms)); } @@ -4016,8 +4001,7 @@ static PyObject * _curses_putp_impl(PyObject *module, const char *string) /*[clinic end generated code: output=e98081d1b8eb5816 input=1601faa828b44cb3]*/ { - _curses_state *state = get_curses_state(module); - return PyCursesCheckERR(state, putp(string), "putp"); + return PyCursesCheckERR(get_curses_state(module), putp(string), "putp"); } /*[clinic input] @@ -4037,8 +4021,7 @@ static PyObject * _curses_qiflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=9167e862f760ea30 input=6ec8b3e2b717ec40]*/ { - _curses_state *state = get_curses_state(module); - PyCursesInitialised(state); + PyCursesInitialised(get_curses_state(module)); if (flag) { qiflush(); @@ -4273,8 +4256,7 @@ static PyObject * _curses_setsyx_impl(PyObject *module, int y, int x) /*[clinic end generated code: output=23dcf753511a2464 input=fa7f2b208e10a557]*/ { - _curses_state *state = get_curses_state(module); - PyCursesInitialised(state); + PyCursesInitialised(get_curses_state(module)); setsyx(y,x); @@ -4370,8 +4352,7 @@ static PyObject * _curses_tigetflag_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=8853c0e55542195b input=b0787af9e3e9a6ce]*/ { - _curses_state *state = get_curses_state(module); - PyCursesSetupTermCalled(state); + PyCursesSetupTermCalled(get_curses_state(module)); return PyLong_FromLong( (long) tigetflag( (char *)capname ) ); } @@ -4393,8 +4374,7 @@ static PyObject * _curses_tigetnum_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=46f8b0a1b5dff42f input=5cdf2f410b109720]*/ { - _curses_state *state = get_curses_state(module); - PyCursesSetupTermCalled(state); + PyCursesSetupTermCalled(get_curses_state(module)); return PyLong_FromLong( (long) tigetnum( (char *)capname ) ); } @@ -4416,8 +4396,7 @@ static PyObject * _curses_tigetstr_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=f22b576ad60248f3 input=36644df25c73c0a7]*/ { - _curses_state *state = get_curses_state(module); - PyCursesSetupTermCalled(state); + PyCursesSetupTermCalled(get_curses_state(module)); capname = tigetstr( (char *)capname ); if (capname == NULL || capname == (char*) -1) { @@ -4506,8 +4485,7 @@ _curses_unctrl(PyObject *module, PyObject *ch) { chtype ch_; - _curses_state *state = get_curses_state(module); - PyCursesInitialised(state); + PyCursesInitialised(get_curses_state(module)); if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; From 146971fba653a9802402e02ea132adbcd486aaa8 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Fri, 2 Jun 2023 22:55:24 +0300 Subject: [PATCH 09/12] reverted SetDictInt macro changes --- Modules/_cursesmodule.c | 229 ++++++++++++++++++++-------------------- 1 file changed, 115 insertions(+), 114 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 0a3ad5a69f2924..49be7baadd42e6 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -3306,10 +3306,10 @@ _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) Py_RETURN_NONE; } -#define SetDictInt(dict, string,ch) \ +#define SetDictInt(string,ch) \ do { \ PyObject *o = PyLong_FromLong((long) (ch)); \ - if (o && PyDict_SetItemString(dict, string, o) == 0) { \ + if (o && PyDict_SetItemString(d, string, o) == 0) { \ Py_DECREF(o); \ } \ } while (0) @@ -3349,74 +3349,74 @@ _curses_initscr_impl(PyObject *module) where they're not defined until you've called initscr() */ PyObject *d = PyModule_GetDict(module); /* Here are some graphic symbols you can use */ - SetDictInt(d, "ACS_ULCORNER", (ACS_ULCORNER)); - SetDictInt(d, "ACS_LLCORNER", (ACS_LLCORNER)); - SetDictInt(d, "ACS_URCORNER", (ACS_URCORNER)); - SetDictInt(d, "ACS_LRCORNER", (ACS_LRCORNER)); - SetDictInt(d, "ACS_LTEE", (ACS_LTEE)); - SetDictInt(d, "ACS_RTEE", (ACS_RTEE)); - SetDictInt(d, "ACS_BTEE", (ACS_BTEE)); - SetDictInt(d, "ACS_TTEE", (ACS_TTEE)); - SetDictInt(d, "ACS_HLINE", (ACS_HLINE)); - SetDictInt(d, "ACS_VLINE", (ACS_VLINE)); - SetDictInt(d, "ACS_PLUS", (ACS_PLUS)); + 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(d, "ACS_S1", (ACS_S1)); - SetDictInt(d, "ACS_S9", (ACS_S9)); - SetDictInt(d, "ACS_DIAMOND", (ACS_DIAMOND)); - SetDictInt(d, "ACS_CKBOARD", (ACS_CKBOARD)); - SetDictInt(d, "ACS_DEGREE", (ACS_DEGREE)); - SetDictInt(d, "ACS_PLMINUS", (ACS_PLMINUS)); - SetDictInt(d, "ACS_BULLET", (ACS_BULLET)); - SetDictInt(d, "ACS_LARROW", (ACS_LARROW)); - SetDictInt(d, "ACS_RARROW", (ACS_RARROW)); - SetDictInt(d, "ACS_DARROW", (ACS_DARROW)); - SetDictInt(d, "ACS_UARROW", (ACS_UARROW)); - SetDictInt(d, "ACS_BOARD", (ACS_BOARD)); - SetDictInt(d, "ACS_LANTERN", (ACS_LANTERN)); - SetDictInt(d, "ACS_BLOCK", (ACS_BLOCK)); + 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(d, "ACS_BSSB", (ACS_ULCORNER)); - SetDictInt(d, "ACS_SSBB", (ACS_LLCORNER)); - SetDictInt(d, "ACS_BBSS", (ACS_URCORNER)); - SetDictInt(d, "ACS_SBBS", (ACS_LRCORNER)); - SetDictInt(d, "ACS_SBSS", (ACS_RTEE)); - SetDictInt(d, "ACS_SSSB", (ACS_LTEE)); - SetDictInt(d, "ACS_SSBS", (ACS_BTEE)); - SetDictInt(d, "ACS_BSSS", (ACS_TTEE)); - SetDictInt(d, "ACS_BSBS", (ACS_HLINE)); - SetDictInt(d, "ACS_SBSB", (ACS_VLINE)); - SetDictInt(d, "ACS_SSSS", (ACS_PLUS)); + 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(d, "ACS_S3", (ACS_S3)); + SetDictInt("ACS_S3", (ACS_S3)); #endif #ifdef ACS_S7 - SetDictInt(d, "ACS_S7", (ACS_S7)); + SetDictInt("ACS_S7", (ACS_S7)); #endif #ifdef ACS_LEQUAL - SetDictInt(d, "ACS_LEQUAL", (ACS_LEQUAL)); + SetDictInt("ACS_LEQUAL", (ACS_LEQUAL)); #endif #ifdef ACS_GEQUAL - SetDictInt(d, "ACS_GEQUAL", (ACS_GEQUAL)); + SetDictInt("ACS_GEQUAL", (ACS_GEQUAL)); #endif #ifdef ACS_PI - SetDictInt(d, "ACS_PI", (ACS_PI)); + SetDictInt("ACS_PI", (ACS_PI)); #endif #ifdef ACS_NEQUAL - SetDictInt(d, "ACS_NEQUAL", (ACS_NEQUAL)); + SetDictInt("ACS_NEQUAL", (ACS_NEQUAL)); #endif #ifdef ACS_STERLING - SetDictInt(d, "ACS_STERLING", (ACS_STERLING)); + SetDictInt("ACS_STERLING", (ACS_STERLING)); #endif - SetDictInt(d, "LINES", LINES); - SetDictInt(d, "COLS", COLS); + SetDictInt("LINES", LINES); + SetDictInt("COLS", COLS); winobj = (PyCursesWindowObject *)PyCursesWindow_New(state, win, NULL); if (winobj == NULL) { @@ -4848,7 +4848,8 @@ _curses_exec(PyObject *module) PyCurses_API[4] = (void *)Py_NewRef(state->PyCursesError); /* Add a capsule for the C API */ - c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, curses_capi_destructor); + c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, + curses_capi_destructor); if (c_api_object == NULL) { PyMem_Free(PyCurses_API); return -1; @@ -4883,99 +4884,99 @@ _curses_exec(PyObject *module) } #endif /* NCURSES_VERSION */ - SetDictInt(d, "ERR", ERR); - SetDictInt(d, "OK", OK); + SetDictInt("ERR", ERR); + SetDictInt("OK", OK); /* Here are some attributes you can add to chars to print */ - SetDictInt(d, "A_ATTRIBUTES", A_ATTRIBUTES); - SetDictInt(d, "A_NORMAL", A_NORMAL); - SetDictInt(d, "A_STANDOUT", A_STANDOUT); - SetDictInt(d, "A_UNDERLINE", A_UNDERLINE); - SetDictInt(d, "A_REVERSE", A_REVERSE); - SetDictInt(d, "A_BLINK", A_BLINK); - SetDictInt(d, "A_DIM", A_DIM); - SetDictInt(d, "A_BOLD", A_BOLD); - SetDictInt(d, "A_ALTCHARSET", A_ALTCHARSET); - SetDictInt(d, "A_INVIS", A_INVIS); - SetDictInt(d, "A_PROTECT", A_PROTECT); - SetDictInt(d, "A_CHARTEXT", A_CHARTEXT); - SetDictInt(d, "A_COLOR", A_COLOR); + 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(d, "A_HORIZONTAL", A_HORIZONTAL); + SetDictInt("A_HORIZONTAL", A_HORIZONTAL); #endif #ifdef A_LEFT - SetDictInt(d, "A_LEFT", A_LEFT); + SetDictInt("A_LEFT", A_LEFT); #endif #ifdef A_LOW - SetDictInt(d, "A_LOW", A_LOW); + SetDictInt("A_LOW", A_LOW); #endif #ifdef A_RIGHT - SetDictInt(d, "A_RIGHT", A_RIGHT); + SetDictInt("A_RIGHT", A_RIGHT); #endif #ifdef A_TOP - SetDictInt(d, "A_TOP", A_TOP); + SetDictInt("A_TOP", A_TOP); #endif #ifdef A_VERTICAL - SetDictInt(d, "A_VERTICAL", A_VERTICAL); + SetDictInt("A_VERTICAL", A_VERTICAL); #endif /* ncurses extension */ #ifdef A_ITALIC - SetDictInt(d, "A_ITALIC", A_ITALIC); + SetDictInt("A_ITALIC", A_ITALIC); #endif - SetDictInt(d, "COLOR_BLACK", COLOR_BLACK); - SetDictInt(d, "COLOR_RED", COLOR_RED); - SetDictInt(d, "COLOR_GREEN", COLOR_GREEN); - SetDictInt(d, "COLOR_YELLOW", COLOR_YELLOW); - SetDictInt(d, "COLOR_BLUE", COLOR_BLUE); - SetDictInt(d, "COLOR_MAGENTA", COLOR_MAGENTA); - SetDictInt(d, "COLOR_CYAN", COLOR_CYAN); - SetDictInt(d, "COLOR_WHITE", COLOR_WHITE); + 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(d, "BUTTON1_PRESSED", BUTTON1_PRESSED); - SetDictInt(d, "BUTTON1_RELEASED", BUTTON1_RELEASED); - SetDictInt(d, "BUTTON1_CLICKED", BUTTON1_CLICKED); - SetDictInt(d, "BUTTON1_DOUBLE_CLICKED", BUTTON1_DOUBLE_CLICKED); - SetDictInt(d, "BUTTON1_TRIPLE_CLICKED", BUTTON1_TRIPLE_CLICKED); - - SetDictInt(d, "BUTTON2_PRESSED", BUTTON2_PRESSED); - SetDictInt(d, "BUTTON2_RELEASED", BUTTON2_RELEASED); - SetDictInt(d, "BUTTON2_CLICKED", BUTTON2_CLICKED); - SetDictInt(d, "BUTTON2_DOUBLE_CLICKED", BUTTON2_DOUBLE_CLICKED); - SetDictInt(d, "BUTTON2_TRIPLE_CLICKED", BUTTON2_TRIPLE_CLICKED); - - SetDictInt(d, "BUTTON3_PRESSED", BUTTON3_PRESSED); - SetDictInt(d, "BUTTON3_RELEASED", BUTTON3_RELEASED); - SetDictInt(d, "BUTTON3_CLICKED", BUTTON3_CLICKED); - SetDictInt(d, "BUTTON3_DOUBLE_CLICKED", BUTTON3_DOUBLE_CLICKED); - SetDictInt(d, "BUTTON3_TRIPLE_CLICKED", BUTTON3_TRIPLE_CLICKED); - - SetDictInt(d, "BUTTON4_PRESSED", BUTTON4_PRESSED); - SetDictInt(d, "BUTTON4_RELEASED", BUTTON4_RELEASED); - SetDictInt(d, "BUTTON4_CLICKED", BUTTON4_CLICKED); - SetDictInt(d, "BUTTON4_DOUBLE_CLICKED", BUTTON4_DOUBLE_CLICKED); - SetDictInt(d, "BUTTON4_TRIPLE_CLICKED", BUTTON4_TRIPLE_CLICKED); + 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(d, "BUTTON5_PRESSED", BUTTON5_PRESSED); - SetDictInt(d, "BUTTON5_RELEASED", BUTTON5_RELEASED); - SetDictInt(d, "BUTTON5_CLICKED", BUTTON5_CLICKED); - SetDictInt(d, "BUTTON5_DOUBLE_CLICKED", BUTTON5_DOUBLE_CLICKED); - SetDictInt(d, "BUTTON5_TRIPLE_CLICKED", BUTTON5_TRIPLE_CLICKED); + 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(d, "BUTTON_SHIFT", BUTTON_SHIFT); - SetDictInt(d, "BUTTON_CTRL", BUTTON_CTRL); - SetDictInt(d, "BUTTON_ALT", BUTTON_ALT); + SetDictInt("BUTTON_SHIFT", BUTTON_SHIFT); + SetDictInt("BUTTON_CTRL", BUTTON_CTRL); + SetDictInt("BUTTON_ALT", BUTTON_ALT); - SetDictInt(d, "ALL_MOUSE_EVENTS", ALL_MOUSE_EVENTS); - SetDictInt(d, "REPORT_MOUSE_POSITION", REPORT_MOUSE_POSITION); + SetDictInt("ALL_MOUSE_EVENTS", ALL_MOUSE_EVENTS); + SetDictInt("REPORT_MOUSE_POSITION", REPORT_MOUSE_POSITION); #endif /* Now set everything up for KEY_ variables */ { @@ -5005,12 +5006,12 @@ _curses_exec(PyObject *module) *p2 = (char)0; } else key_n2 = key_n; - SetDictInt(d, key_n2,key); + SetDictInt(key_n2,key); if (key_n2 != key_n) PyMem_Free(key_n2); } - SetDictInt(d, "KEY_MIN", KEY_MIN); - SetDictInt(d, "KEY_MAX", KEY_MAX); + SetDictInt("KEY_MIN", KEY_MIN); + SetDictInt("KEY_MAX", KEY_MAX); } return 0; From 7a8f6dc5c95cdc2230666ae37976aba2f704be0b Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Fri, 2 Jun 2023 22:59:29 +0300 Subject: [PATCH 10/12] reverted SetDictInt macro change --- Modules/_cursesmodule.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 49be7baadd42e6..6f59f99a3ea125 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -3306,14 +3306,6 @@ _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) Py_RETURN_NONE; } -#define SetDictInt(string,ch) \ - do { \ - PyObject *o = PyLong_FromLong((long) (ch)); \ - if (o && PyDict_SetItemString(d, string, o) == 0) { \ - Py_DECREF(o); \ - } \ - } while (0) - /*[clinic input] _curses.initscr @@ -3347,6 +3339,14 @@ _curses_initscr_impl(PyObject *module) /* This was moved from initcurses() because it core dumped on SGI, where they're not defined until you've called initscr() */ +#define SetDictInt(string,ch) \ + do { \ + PyObject *o = PyLong_FromLong((long) (ch)); \ + if (o && PyDict_SetItemString(d, string, o) == 0) { \ + Py_DECREF(o); \ + } \ + } while (0) + PyObject *d = PyModule_GetDict(module); /* Here are some graphic symbols you can use */ SetDictInt("ACS_ULCORNER", (ACS_ULCORNER)); From 8173984666f95b17105358f8d70a8f98499df607 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Fri, 16 Jun 2023 20:46:21 +0300 Subject: [PATCH 11/12] * moved remaining global vars, which indicate that `setupterm`/`initscr`/`start_color` funcs were called, to module state * removed funcs that were exposed to curses C API and used vars mentioned above * made C API use pointers to corresponding fields in curses state --- Include/py_curses.h | 24 ++++++++++++-- Modules/_cursesmodule.c | 73 +++++++++++++---------------------------- 2 files changed, 44 insertions(+), 53 deletions(-) diff --git a/Include/py_curses.h b/Include/py_curses.h index 0ef4b545119bf6..55224a8e30b73b 100644 --- a/Include/py_curses.h +++ b/Include/py_curses.h @@ -79,9 +79,27 @@ typedef struct { static void **PyCurses_API; #define PyCursesWindow_Type (*_PyType_CAST(PyCurses_API[0])) -#define PyCursesSetupTermCalled {if (! ((int (*)(void *))PyCurses_API[1]) (PyCurses_API[4]) ) return NULL;} -#define PyCursesInitialised {if (! ((int (*)(void *))PyCurses_API[2]) (PyCurses_API[4]) ) return NULL;} -#define PyCursesInitialisedColor {if (! ((int (*)(void *))PyCurses_API[3]) (PyCurses_API[4]) ) return NULL;} + +#define PyCursesSetupTermCalled \ + if (!(*(int *)PyCurses_API[1])) { \ + PyErr_SetString(PyCurses_API[4], \ + "must call (at least) setupterm() first"); \ + return NULL; \ + } + +#define PyCursesInitialised \ + if (!(*(int *)PyCurses_API[2])) { \ + PyErr_SetString(PyCurses_API[4], \ + "must call initscr() first"); \ + return NULL; \ + } + +#define PyCursesInitialisedColor \ + if (!(*(int *)PyCurses_API[3])) { \ + PyErr_SetString(PyCurses_API[4], \ + "must call start_color() first"); \ + return NULL; \ + } #define import_curses() \ PyCurses_API = (void **)PyCapsule_Import(PyCurses_CAPSULE_NAME, 1); diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 6f59f99a3ea125..b88a949aab0d92 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -167,20 +167,18 @@ class _curses.window "PyCursesWindowObject *" "clinic_state()->PyCursesWindow_Ty [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=83369be6e20ef0da]*/ -/* Tells whether setupterm() has been called to initialise terminfo. */ -static int initialised_setupterm = FALSE; - -/* Tells whether initscr() has been called to initialise curses. */ -static int initialised = FALSE; - -/* Tells whether start_color() has been called to initialise color usage. */ -static int initialisedcolors = FALSE; - typedef struct _curses_state { PyTypeObject *PyCursesWindow_Type; PyObject *PyCursesError; char *screen_encoding; + + /* Tells whether setupterm() has been called to initialise terminfo. */ + int initialised_setupterm; + /* Tells whether initscr() has been called to initialise curses. */ + int initialised; + /* Tells whether start_color() has been called to initialise color usage. */ + int initialisedcolors; } _curses_state; static struct PyModuleDef _curses_module; @@ -227,19 +225,19 @@ _curses_free(void *mod) /* Utility Macros */ #define PyCursesSetupTermCalled(state) \ - if (initialised_setupterm != TRUE) { \ + if (state->initialised_setupterm != TRUE) { \ PyErr_SetString(state->PyCursesError, \ "must call (at least) setupterm() first"); \ return 0; } #define PyCursesInitialised(state) \ - if (initialised != TRUE) { \ + if (state->initialised != TRUE) { \ PyErr_SetString(state->PyCursesError, \ "must call initscr() first"); \ return 0; } #define PyCursesInitialisedColor(state) \ - if (initialisedcolors != TRUE) { \ + if (state->initialisedcolors != TRUE) { \ PyErr_SetString(state->PyCursesError, \ "must call start_color() first"); \ return 0; } @@ -576,36 +574,6 @@ class component_converter(CConverter): initialised or not. */ -static int func_PyCursesSetupTermCalled(void *exc) -{ - if (initialised_setupterm != TRUE) { - PyErr_SetString((PyObject *)exc, - "must call (at least) setupterm() first"); - return 0; - } - return 1; -} - -static int func_PyCursesInitialised(void *exc) -{ - if (initialised != TRUE) { - PyErr_SetString((PyObject *)exc, - "must call initscr() first"); - return 0; - } - return 1; -} - -static int func_PyCursesInitialisedColor(void *exc) -{ - if (initialisedcolors != TRUE) { - PyErr_SetString((PyObject *)exc, - "must call start_color() first"); - return 0; - } - return 1; -} - /***************************************************************************** The Window Object ******************************************************************************/ @@ -3323,7 +3291,7 @@ _curses_initscr_impl(PyObject *module) _curses_state *state = get_curses_state(module); - if (initialised) { + if (state->initialised) { wrefresh(stdscr); return (PyObject *)PyCursesWindow_New(state, stdscr, NULL); } @@ -3335,7 +3303,8 @@ _curses_initscr_impl(PyObject *module) return NULL; } - initialised = initialised_setupterm = TRUE; + state->initialised = TRUE; + state->initialised_setupterm = TRUE; /* This was moved from initcurses() because it core dumped on SGI, where they're not defined until you've called initscr() */ @@ -3466,7 +3435,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) } } - if (!initialised_setupterm && setupterm((char *)term, fd, &err) == ERR) { + if (!state->initialised_setupterm && setupterm((char *)term, fd, &err) == ERR) { const char* s = "setupterm: unknown error"; if (err == 0) { @@ -3479,7 +3448,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) return NULL; } - initialised_setupterm = TRUE; + state->initialised_setupterm = TRUE; Py_RETURN_NONE; } @@ -4289,7 +4258,7 @@ _curses_start_color_impl(PyObject *module) code = start_color(); if (code != ERR) { - initialisedcolors = TRUE; + state->initialisedcolors = TRUE; c = PyLong_FromLong((long) COLORS); if (c == NULL) return NULL; @@ -4834,6 +4803,10 @@ _curses_exec(PyObject *module) state->PyCursesError = error; state->screen_encoding = NULL; + state->initialised = FALSE; + state->initialised_setupterm = FALSE; + state->initialisedcolors = FALSE; + /* Allocate C API pointer array */ void **PyCurses_API = PyMem_Calloc(PyCurses_API_pointers, sizeof(void *)); if (PyCurses_API == NULL) { @@ -4842,9 +4815,9 @@ _curses_exec(PyObject *module) } /* Initialize the C API pointer array */ PyCurses_API[0] = (void *)Py_NewRef(state->PyCursesWindow_Type); - PyCurses_API[1] = (void *)func_PyCursesSetupTermCalled; - PyCurses_API[2] = (void *)func_PyCursesInitialised; - PyCurses_API[3] = (void *)func_PyCursesInitialisedColor; + PyCurses_API[1] = (void *)&state->initialised; + PyCurses_API[2] = (void *)&state->initialised_setupterm; + PyCurses_API[3] = (void *)&state->initialisedcolors; PyCurses_API[4] = (void *)Py_NewRef(state->PyCursesError); /* Add a capsule for the C API */ From cd13eaf0fbbbefce15640a879bed43bf33f81176 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Fri, 16 Jun 2023 20:59:57 +0300 Subject: [PATCH 12/12] applied suggestion --- Modules/_cursesmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index b88a949aab0d92..2197ae02d91c31 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -220,7 +220,7 @@ _curses_traverse(PyObject *mod, visitproc visit, void *arg) static void _curses_free(void *mod) { - _curses_clear((PyObject *)mod); + (void)_curses_clear((PyObject *)mod); } /* Utility Macros */