1 /*
2  *   This is a curses module for Python.
3  *
4  *   Based on prior work by Lance Ellinghaus and Oliver Andrich
5  *   Version 1.2 of this module: Copyright 1994 by Lance Ellinghouse,
6  *    Cathedral City, California Republic, United States of America.
7  *
8  *   Version 1.5b1, heavily extended for ncurses by Oliver Andrich:
9  *   Copyright 1996,1997 by Oliver Andrich, Koblenz, Germany.
10  *
11  *   Tidied for Python 1.6, and currently maintained by <amk@amk.ca>.
12  *
13  *   Permission is hereby granted, free of charge, to any person obtaining
14  *   a copy of this source file to use, copy, modify, merge, or publish it
15  *   subject to the following conditions:
16  *
17  *   The above copyright notice and this permission notice shall be included
18  *   in all copies or in any new file that contains a substantial portion of
19  *   this file.
20  *
21  *   THE  AUTHOR  MAKES  NO  REPRESENTATIONS ABOUT  THE  SUITABILITY  OF
22  *   THE  SOFTWARE FOR  ANY  PURPOSE.  IT IS  PROVIDED  "AS IS"  WITHOUT
23  *   EXPRESS OR  IMPLIED WARRANTY.  THE AUTHOR DISCLAIMS  ALL WARRANTIES
24  *   WITH  REGARD TO  THIS  SOFTWARE, INCLUDING  ALL IMPLIED  WARRANTIES
25  *   OF   MERCHANTABILITY,  FITNESS   FOR  A   PARTICULAR  PURPOSE   AND
26  *   NON-INFRINGEMENT  OF THIRD  PARTY  RIGHTS. IN  NO  EVENT SHALL  THE
27  *   AUTHOR  BE LIABLE  TO  YOU  OR ANY  OTHER  PARTY  FOR ANY  SPECIAL,
28  *   INDIRECT,  OR  CONSEQUENTIAL  DAMAGES  OR  ANY  DAMAGES  WHATSOEVER
29  *   WHETHER IN AN  ACTION OF CONTRACT, NEGLIGENCE,  STRICT LIABILITY OR
30  *   ANY OTHER  ACTION ARISING OUT OF  OR IN CONNECTION WITH  THE USE OR
31  *   PERFORMANCE OF THIS SOFTWARE.
32  */
33 
34 /*
35 
36   A number of SysV or ncurses functions don't have wrappers yet; if you
37   need a given function, add it and send a patch.  See
38   https://www.python.org/dev/patches/ for instructions on how to submit
39   patches to Python.
40 
41   Here's a list of currently unsupported functions:
42 
43   addchnstr addchstr color_set define_key
44   del_curterm delscreen dupwin inchnstr inchstr innstr keyok
45   mcprint mvaddchnstr mvaddchstr mvcur mvinchnstr
46   mvinchstr mvinnstr mmvwaddchnstr mvwaddchstr
47   mvwinchnstr mvwinchstr mvwinnstr newterm
48   restartterm ripoffline scr_dump
49   scr_init scr_restore scr_set scrl set_curterm set_term setterm
50   tgetent tgetflag tgetnum tgetstr tgoto timeout tputs
51   vidattr vidputs waddchnstr waddchstr
52   wcolor_set winchnstr winchstr winnstr wmouse_trafo wscrl
53 
54   Low-priority:
55   slk_attr slk_attr_off slk_attr_on slk_attr_set slk_attroff
56   slk_attron slk_attrset slk_clear slk_color slk_init slk_label
57   slk_noutrefresh slk_refresh slk_restore slk_set slk_touch
58 
59   Menu extension (ncurses and probably SYSV):
60   current_item free_item free_menu item_count item_description
61   item_index item_init item_name item_opts item_opts_off
62   item_opts_on item_term item_userptr item_value item_visible
63   menu_back menu_driver menu_fore menu_format menu_grey
64   menu_init menu_items menu_mark menu_opts menu_opts_off
65   menu_opts_on menu_pad menu_pattern menu_request_by_name
66   menu_request_name menu_spacing menu_sub menu_term menu_userptr
67   menu_win new_item new_menu pos_menu_cursor post_menu
68   scale_menu set_current_item set_item_init set_item_opts
69   set_item_term set_item_userptr set_item_value set_menu_back
70   set_menu_fore set_menu_format set_menu_grey set_menu_init
71   set_menu_items set_menu_mark set_menu_opts set_menu_pad
72   set_menu_pattern set_menu_spacing set_menu_sub set_menu_term
73   set_menu_userptr set_menu_win set_top_row top_row unpost_menu
74 
75   Form extension (ncurses and probably SYSV):
76   current_field data_ahead data_behind dup_field
77   dynamic_fieldinfo field_arg field_back field_buffer
78   field_count field_fore field_index field_info field_init
79   field_just field_opts field_opts_off field_opts_on field_pad
80   field_status field_term field_type field_userptr form_driver
81   form_fields form_init form_opts form_opts_off form_opts_on
82   form_page form_request_by_name form_request_name form_sub
83   form_term form_userptr form_win free_field free_form
84   link_field link_fieldtype move_field new_field new_form
85   new_page pos_form_cursor post_form scale_form
86   set_current_field set_field_back set_field_buffer
87   set_field_fore set_field_init set_field_just set_field_opts
88   set_field_pad set_field_status set_field_term set_field_type
89   set_field_userptr set_fieldtype_arg set_fieldtype_choice
90   set_form_fields set_form_init set_form_opts set_form_page
91   set_form_sub set_form_term set_form_userptr set_form_win
92   set_max_field set_new_page unpost_form
93 
94 
95 */
96 
97 /* Release Number */
98 
99 static const char PyCursesVersion[] = "2.2";
100 
101 /* Includes */
102 
103 #ifndef Py_BUILD_CORE_BUILTIN
104 #  define Py_BUILD_CORE_MODULE 1
105 #endif
106 
107 #define PY_SSIZE_T_CLEAN
108 
109 #include "Python.h"
110 #include "pycore_long.h"          // _PyLong_GetZero()
111 #include "pycore_structseq.h"     // PyStructSequence_InitType()
112 
113 #ifdef __hpux
114 #define STRICT_SYSV_CURSES
115 #endif
116 
117 #define CURSES_MODULE
118 #include "py_curses.h"
119 
120 #if defined(HAVE_TERM_H) || defined(__sgi)
121 /* For termname, longname, putp, tigetflag, tigetnum, tigetstr, tparm
122    which are not declared in SysV curses and for setupterm. */
123 #include <term.h>
124 /* Including <term.h> #defines many common symbols. */
125 #undef lines
126 #undef columns
127 #endif
128 
129 #ifdef HAVE_LANGINFO_H
130 #include <langinfo.h>
131 #endif
132 
133 #if !defined(HAVE_NCURSES_H) && (defined(sgi) || defined(__sun) || defined(SCO5))
134 #define STRICT_SYSV_CURSES       /* Don't use ncurses extensions */
135 typedef chtype attr_t;           /* No attr_t type is available */
136 #endif
137 
138 #if defined(_AIX)
139 #define STRICT_SYSV_CURSES
140 #endif
141 
142 #if NCURSES_EXT_FUNCS+0 >= 20170401 && NCURSES_EXT_COLORS+0 >= 20170401
143 #define _NCURSES_EXTENDED_COLOR_FUNCS   1
144 #else
145 #define _NCURSES_EXTENDED_COLOR_FUNCS   0
146 #endif
147 
148 #if _NCURSES_EXTENDED_COLOR_FUNCS
149 #define _CURSES_COLOR_VAL_TYPE          int
150 #define _CURSES_COLOR_NUM_TYPE          int
151 #define _CURSES_INIT_COLOR_FUNC         init_extended_color
152 #define _CURSES_INIT_PAIR_FUNC          init_extended_pair
153 #define _COLOR_CONTENT_FUNC             extended_color_content
154 #define _CURSES_PAIR_CONTENT_FUNC       extended_pair_content
155 #else
156 #define _CURSES_COLOR_VAL_TYPE          short
157 #define _CURSES_COLOR_NUM_TYPE          short
158 #define _CURSES_INIT_COLOR_FUNC         init_color
159 #define _CURSES_INIT_PAIR_FUNC          init_pair
160 #define _COLOR_CONTENT_FUNC             color_content
161 #define _CURSES_PAIR_CONTENT_FUNC       pair_content
162 #endif  /* _NCURSES_EXTENDED_COLOR_FUNCS */
163 
164 /*[clinic input]
165 module _curses
166 class _curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type"
167 [clinic start generated code]*/
168 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=43265c372c2887d6]*/
169 
170 /* Definition of exception curses.error */
171 
172 static PyObject *PyCursesError;
173 
174 /* Tells whether setupterm() has been called to initialise terminfo.  */
175 static int initialised_setupterm = FALSE;
176 
177 /* Tells whether initscr() has been called to initialise curses.  */
178 static int initialised = FALSE;
179 
180 /* Tells whether start_color() has been called to initialise color usage. */
181 static int initialisedcolors = FALSE;
182 
183 static char *screen_encoding = NULL;
184 
185 /* Utility Macros */
186 #define PyCursesSetupTermCalled                                         \
187     if (initialised_setupterm != TRUE) {                                \
188         PyErr_SetString(PyCursesError,                                  \
189                         "must call (at least) setupterm() first");      \
190         return 0; }
191 
192 #define PyCursesInitialised                             \
193     if (initialised != TRUE) {                          \
194         PyErr_SetString(PyCursesError,                  \
195                         "must call initscr() first");   \
196         return 0; }
197 
198 #define PyCursesInitialisedColor                                \
199     if (initialisedcolors != TRUE) {                            \
200         PyErr_SetString(PyCursesError,                          \
201                         "must call start_color() first");       \
202         return 0; }
203 
204 /* Utility Functions */
205 
206 /*
207  * Check the return code from a curses function and return None
208  * or raise an exception as appropriate.  These are exported using the
209  * capsule API.
210  */
211 
212 static PyObject *
PyCursesCheckERR(int code,const char * fname)213 PyCursesCheckERR(int code, const char *fname)
214 {
215     if (code != ERR) {
216         Py_RETURN_NONE;
217     } else {
218         if (fname == NULL) {
219             PyErr_SetString(PyCursesError, catchall_ERR);
220         } else {
221             PyErr_Format(PyCursesError, "%s() returned ERR", fname);
222         }
223         return NULL;
224     }
225 }
226 
227 /* Convert an object to a byte (an integer of type chtype):
228 
229    - int
230    - bytes of length 1
231    - str of length 1
232 
233    Return 1 on success, 0 on error (invalid type or integer overflow). */
234 static int
PyCurses_ConvertToChtype(PyCursesWindowObject * win,PyObject * obj,chtype * ch)235 PyCurses_ConvertToChtype(PyCursesWindowObject *win, PyObject *obj, chtype *ch)
236 {
237     long value;
238     if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) {
239         value = (unsigned char)PyBytes_AsString(obj)[0];
240     }
241     else if (PyUnicode_Check(obj)) {
242         if (PyUnicode_GetLength(obj) != 1) {
243             PyErr_Format(PyExc_TypeError,
244                          "expect bytes or str of length 1, or int, "
245                          "got a str of length %zi",
246                          PyUnicode_GET_LENGTH(obj));
247             return 0;
248         }
249         value = PyUnicode_READ_CHAR(obj, 0);
250         if (128 < value) {
251             PyObject *bytes;
252             const char *encoding;
253             if (win)
254                 encoding = win->encoding;
255             else
256                 encoding = screen_encoding;
257             bytes = PyUnicode_AsEncodedString(obj, encoding, NULL);
258             if (bytes == NULL)
259                 return 0;
260             if (PyBytes_GET_SIZE(bytes) == 1)
261                 value = (unsigned char)PyBytes_AS_STRING(bytes)[0];
262             else
263                 value = -1;
264             Py_DECREF(bytes);
265             if (value < 0)
266                 goto overflow;
267         }
268     }
269     else if (PyLong_CheckExact(obj)) {
270         int long_overflow;
271         value = PyLong_AsLongAndOverflow(obj, &long_overflow);
272         if (long_overflow)
273             goto overflow;
274     }
275     else {
276         PyErr_Format(PyExc_TypeError,
277                      "expect bytes or str of length 1, or int, got %s",
278                      Py_TYPE(obj)->tp_name);
279         return 0;
280     }
281     *ch = (chtype)value;
282     if ((long)*ch != value)
283         goto overflow;
284     return 1;
285 
286 overflow:
287     PyErr_SetString(PyExc_OverflowError,
288                     "byte doesn't fit in chtype");
289     return 0;
290 }
291 
292 /* Convert an object to a byte (chtype) or a character (cchar_t):
293 
294     - int
295     - bytes of length 1
296     - str of length 1
297 
298    Return:
299 
300     - 2 if obj is a character (written into *wch)
301     - 1 if obj is a byte (written into *ch)
302     - 0 on error: raise an exception */
303 static int
PyCurses_ConvertToCchar_t(PyCursesWindowObject * win,PyObject * obj,chtype * ch,wchar_t * wch)304 PyCurses_ConvertToCchar_t(PyCursesWindowObject *win, PyObject *obj,
305                           chtype *ch
306 #ifdef HAVE_NCURSESW
307                           , wchar_t *wch
308 #endif
309                           )
310 {
311     long value;
312 #ifdef HAVE_NCURSESW
313     wchar_t buffer[2];
314 #endif
315 
316     if (PyUnicode_Check(obj)) {
317 #ifdef HAVE_NCURSESW
318         if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) {
319             PyErr_Format(PyExc_TypeError,
320                          "expect bytes or str of length 1, or int, "
321                          "got a str of length %zi",
322                          PyUnicode_GET_LENGTH(obj));
323             return 0;
324         }
325         *wch = buffer[0];
326         return 2;
327 #else
328         return PyCurses_ConvertToChtype(win, obj, ch);
329 #endif
330     }
331     else if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) {
332         value = (unsigned char)PyBytes_AsString(obj)[0];
333     }
334     else if (PyLong_CheckExact(obj)) {
335         int overflow;
336         value = PyLong_AsLongAndOverflow(obj, &overflow);
337         if (overflow) {
338             PyErr_SetString(PyExc_OverflowError,
339                             "int doesn't fit in long");
340             return 0;
341         }
342     }
343     else {
344         PyErr_Format(PyExc_TypeError,
345                      "expect bytes or str of length 1, or int, got %s",
346                      Py_TYPE(obj)->tp_name);
347         return 0;
348     }
349 
350     *ch = (chtype)value;
351     if ((long)*ch != value) {
352         PyErr_Format(PyExc_OverflowError,
353                      "byte doesn't fit in chtype");
354         return 0;
355     }
356     return 1;
357 }
358 
359 /* Convert an object to a byte string (char*) or a wide character string
360    (wchar_t*). Return:
361 
362     - 2 if obj is a character string (written into *wch)
363     - 1 if obj is a byte string (written into *bytes)
364     - 0 on error: raise an exception */
365 static int
PyCurses_ConvertToString(PyCursesWindowObject * win,PyObject * obj,PyObject ** bytes,wchar_t ** wstr)366 PyCurses_ConvertToString(PyCursesWindowObject *win, PyObject *obj,
367                          PyObject **bytes, wchar_t **wstr)
368 {
369     char *str;
370     if (PyUnicode_Check(obj)) {
371 #ifdef HAVE_NCURSESW
372         assert (wstr != NULL);
373 
374         *wstr = PyUnicode_AsWideCharString(obj, NULL);
375         if (*wstr == NULL)
376             return 0;
377         return 2;
378 #else
379         assert (wstr == NULL);
380         *bytes = PyUnicode_AsEncodedString(obj, win->encoding, NULL);
381         if (*bytes == NULL)
382             return 0;
383         /* check for embedded null bytes */
384         if (PyBytes_AsStringAndSize(*bytes, &str, NULL) < 0) {
385             return 0;
386         }
387         return 1;
388 #endif
389     }
390     else if (PyBytes_Check(obj)) {
391         Py_INCREF(obj);
392         *bytes = obj;
393         /* check for embedded null bytes */
394         if (PyBytes_AsStringAndSize(*bytes, &str, NULL) < 0) {
395             Py_DECREF(obj);
396             return 0;
397         }
398         return 1;
399     }
400 
401     PyErr_Format(PyExc_TypeError, "expect bytes or str, got %s",
402                  Py_TYPE(obj)->tp_name);
403     return 0;
404 }
405 
406 static int
color_allow_default_converter(PyObject * arg,void * ptr)407 color_allow_default_converter(PyObject *arg, void *ptr)
408 {
409     long color_number;
410     int overflow;
411 
412     color_number = PyLong_AsLongAndOverflow(arg, &overflow);
413     if (color_number == -1 && PyErr_Occurred())
414         return 0;
415 
416     if (overflow > 0 || color_number >= COLORS) {
417         PyErr_Format(PyExc_ValueError,
418                      "Color number is greater than COLORS-1 (%d).",
419                      COLORS - 1);
420         return 0;
421     }
422     else if (overflow < 0 || color_number < 0) {
423         color_number = -1;
424     }
425 
426     *(int *)ptr = (int)color_number;
427     return 1;
428 }
429 
430 static int
color_converter(PyObject * arg,void * ptr)431 color_converter(PyObject *arg, void *ptr)
432 {
433     if (!color_allow_default_converter(arg, ptr)) {
434         return 0;
435     }
436     if (*(int *)ptr < 0) {
437         PyErr_SetString(PyExc_ValueError,
438                         "Color number is less than 0.");
439         return 0;
440     }
441     return 1;
442 }
443 
444 /*[python input]
445 class color_converter(CConverter):
446     type = 'int'
447     converter = 'color_converter'
448 [python start generated code]*/
449 /*[python end generated code: output=da39a3ee5e6b4b0d input=4260d2b6e66b3709]*/
450 
451 /*[python input]
452 class color_allow_default_converter(CConverter):
453     type = 'int'
454     converter = 'color_allow_default_converter'
455 [python start generated code]*/
456 /*[python end generated code: output=da39a3ee5e6b4b0d input=975602bc058a872d]*/
457 
458 static int
pair_converter(PyObject * arg,void * ptr)459 pair_converter(PyObject *arg, void *ptr)
460 {
461     long pair_number;
462     int overflow;
463 
464     pair_number = PyLong_AsLongAndOverflow(arg, &overflow);
465     if (pair_number == -1 && PyErr_Occurred())
466         return 0;
467 
468 #if _NCURSES_EXTENDED_COLOR_FUNCS
469     if (overflow > 0 || pair_number > INT_MAX) {
470         PyErr_Format(PyExc_ValueError,
471                      "Color pair is greater than maximum (%d).",
472                      INT_MAX);
473         return 0;
474     }
475 #else
476     if (overflow > 0 || pair_number >= COLOR_PAIRS) {
477         PyErr_Format(PyExc_ValueError,
478                      "Color pair is greater than COLOR_PAIRS-1 (%d).",
479                      COLOR_PAIRS - 1);
480         return 0;
481     }
482 #endif
483     else if (overflow < 0 || pair_number < 0) {
484         PyErr_SetString(PyExc_ValueError,
485                         "Color pair is less than 0.");
486         return 0;
487     }
488 
489     *(int *)ptr = (int)pair_number;
490     return 1;
491 }
492 
493 /*[python input]
494 class pair_converter(CConverter):
495     type = 'int'
496     converter = 'pair_converter'
497 [python start generated code]*/
498 /*[python end generated code: output=da39a3ee5e6b4b0d input=1a918ae6a1b32af7]*/
499 
500 static int
component_converter(PyObject * arg,void * ptr)501 component_converter(PyObject *arg, void *ptr)
502 {
503     long component;
504     int overflow;
505 
506     component = PyLong_AsLongAndOverflow(arg, &overflow);
507     if (component == -1 && PyErr_Occurred())
508         return 0;
509 
510     if (overflow > 0 || component > 1000) {
511         PyErr_SetString(PyExc_ValueError,
512                         "Color component is greater than 1000");
513         return 0;
514     }
515     else if (overflow < 0 || component < 0) {
516         PyErr_SetString(PyExc_ValueError,
517                         "Color component is less than 0");
518         return 0;
519     }
520 
521     *(short *)ptr = (short)component;
522     return 1;
523 }
524 
525 /*[python input]
526 class component_converter(CConverter):
527     type = 'short'
528     converter = 'component_converter'
529 [python start generated code]*/
530 /*[python end generated code: output=da39a3ee5e6b4b0d input=38e9be01d33927fb]*/
531 
532 /* Function versions of the 3 functions for testing whether curses has been
533    initialised or not. */
534 
func_PyCursesSetupTermCalled(void)535 static int func_PyCursesSetupTermCalled(void)
536 {
537     PyCursesSetupTermCalled;
538     return 1;
539 }
540 
func_PyCursesInitialised(void)541 static int func_PyCursesInitialised(void)
542 {
543     PyCursesInitialised;
544     return 1;
545 }
546 
func_PyCursesInitialisedColor(void)547 static int func_PyCursesInitialisedColor(void)
548 {
549     PyCursesInitialisedColor;
550     return 1;
551 }
552 
553 /*****************************************************************************
554  The Window Object
555 ******************************************************************************/
556 
557 /* Definition of the window type */
558 
559 PyTypeObject PyCursesWindow_Type;
560 
561 /* Function prototype macros for Window object
562 
563    X - function name
564    TYPE - parameter Type
565    ERGSTR - format string for construction of the return value
566    PARSESTR - format string for argument parsing
567 */
568 
569 #define Window_NoArgNoReturnFunction(X)                         \
570     static PyObject *PyCursesWindow_ ## X                       \
571     (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored))  \
572     { return PyCursesCheckERR(X(self->win), # X); }
573 
574 #define Window_NoArgTrueFalseFunction(X)                                \
575     static PyObject * PyCursesWindow_ ## X                              \
576     (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored))          \
577     {                                                                   \
578         return PyBool_FromLong(X(self->win)); }
579 
580 #define Window_NoArgNoReturnVoidFunction(X)                     \
581     static PyObject * PyCursesWindow_ ## X                      \
582     (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored))  \
583     {                                                           \
584         X(self->win); Py_RETURN_NONE; }
585 
586 #define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR)               \
587     static PyObject * PyCursesWindow_ ## X                              \
588     (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored))          \
589     {                                                                   \
590         TYPE arg1, arg2;                                                \
591         X(self->win,arg1,arg2); return Py_BuildValue(ERGSTR, arg1, arg2); }
592 
593 #define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR)            \
594     static PyObject * PyCursesWindow_ ## X                              \
595     (PyCursesWindowObject *self, PyObject *args)                        \
596     {                                                                   \
597         TYPE arg1;                                                      \
598         if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) return NULL;      \
599         X(self->win,arg1); Py_RETURN_NONE; }
600 
601 #define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR)                \
602     static PyObject * PyCursesWindow_ ## X                              \
603     (PyCursesWindowObject *self, PyObject *args)                        \
604     {                                                                   \
605         TYPE arg1;                                                      \
606         if (!PyArg_ParseTuple(args,PARSESTR, &arg1)) return NULL;       \
607         return PyCursesCheckERR(X(self->win, arg1), # X); }
608 
609 #define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR)                \
610     static PyObject * PyCursesWindow_ ## X                              \
611     (PyCursesWindowObject *self, PyObject *args)                        \
612     {                                                                   \
613         TYPE arg1, arg2;                                                \
614         if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) return NULL; \
615         return PyCursesCheckERR(X(self->win, arg1, arg2), # X); }
616 
617 /* ------------- WINDOW routines --------------- */
618 
619 Window_NoArgNoReturnFunction(untouchwin)
Window_NoArgNoReturnFunction(touchwin)620 Window_NoArgNoReturnFunction(touchwin)
621 Window_NoArgNoReturnFunction(redrawwin)
622 Window_NoArgNoReturnFunction(winsertln)
623 Window_NoArgNoReturnFunction(werase)
624 Window_NoArgNoReturnFunction(wdeleteln)
625 
626 Window_NoArgTrueFalseFunction(is_wintouched)
627 
628 Window_NoArgNoReturnVoidFunction(wsyncup)
629 Window_NoArgNoReturnVoidFunction(wsyncdown)
630 Window_NoArgNoReturnVoidFunction(wstandend)
631 Window_NoArgNoReturnVoidFunction(wstandout)
632 Window_NoArgNoReturnVoidFunction(wcursyncup)
633 Window_NoArgNoReturnVoidFunction(wclrtoeol)
634 Window_NoArgNoReturnVoidFunction(wclrtobot)
635 Window_NoArgNoReturnVoidFunction(wclear)
636 
637 Window_OneArgNoReturnVoidFunction(idcok, int, "i;True(1) or False(0)")
638 #ifdef HAVE_CURSES_IMMEDOK
639 Window_OneArgNoReturnVoidFunction(immedok, int, "i;True(1) or False(0)")
640 #endif
641 Window_OneArgNoReturnVoidFunction(wtimeout, int, "i;delay")
642 
643 Window_NoArg2TupleReturnFunction(getyx, int, "ii")
644 Window_NoArg2TupleReturnFunction(getbegyx, int, "ii")
645 Window_NoArg2TupleReturnFunction(getmaxyx, int, "ii")
646 Window_NoArg2TupleReturnFunction(getparyx, int, "ii")
647 
648 Window_OneArgNoReturnFunction(clearok, int, "i;True(1) or False(0)")
649 Window_OneArgNoReturnFunction(idlok, int, "i;True(1) or False(0)")
650 Window_OneArgNoReturnFunction(keypad, int, "i;True(1) or False(0)")
651 Window_OneArgNoReturnFunction(leaveok, int, "i;True(1) or False(0)")
652 Window_OneArgNoReturnFunction(nodelay, int, "i;True(1) or False(0)")
653 Window_OneArgNoReturnFunction(notimeout, int, "i;True(1) or False(0)")
654 Window_OneArgNoReturnFunction(scrollok, int, "i;True(1) or False(0)")
655 Window_OneArgNoReturnFunction(winsdelln, int, "i;nlines")
656 #ifdef HAVE_CURSES_SYNCOK
657 Window_OneArgNoReturnFunction(syncok, int, "i;True(1) or False(0)")
658 #endif
659 
660 Window_TwoArgNoReturnFunction(mvwin, int, "ii;y,x")
661 Window_TwoArgNoReturnFunction(mvderwin, int, "ii;y,x")
662 Window_TwoArgNoReturnFunction(wmove, int, "ii;y,x")
663 #ifndef STRICT_SYSV_CURSES
664 Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns")
665 #endif
666 
667 /* Allocation and deallocation of Window Objects */
668 
669 static PyObject *
670 PyCursesWindow_New(WINDOW *win, const char *encoding)
671 {
672     PyCursesWindowObject *wo;
673 
674     if (encoding == NULL) {
675 #if defined(MS_WINDOWS)
676         char *buffer[100];
677         UINT cp;
678         cp = GetConsoleOutputCP();
679         if (cp != 0) {
680             PyOS_snprintf(buffer, sizeof(buffer), "cp%u", cp);
681             encoding = buffer;
682         }
683 #elif defined(CODESET)
684         const char *codeset = nl_langinfo(CODESET);
685         if (codeset != NULL && codeset[0] != 0)
686             encoding = codeset;
687 #endif
688         if (encoding == NULL)
689             encoding = "utf-8";
690     }
691 
692     wo = PyObject_New(PyCursesWindowObject, &PyCursesWindow_Type);
693     if (wo == NULL) return NULL;
694     wo->win = win;
695     wo->encoding = _PyMem_Strdup(encoding);
696     if (wo->encoding == NULL) {
697         Py_DECREF(wo);
698         PyErr_NoMemory();
699         return NULL;
700     }
701     return (PyObject *)wo;
702 }
703 
704 static void
PyCursesWindow_Dealloc(PyCursesWindowObject * wo)705 PyCursesWindow_Dealloc(PyCursesWindowObject *wo)
706 {
707     if (wo->win != stdscr) delwin(wo->win);
708     if (wo->encoding != NULL)
709         PyMem_Free(wo->encoding);
710     PyObject_Free(wo);
711 }
712 
713 /* Addch, Addstr, Addnstr */
714 
715 /*[clinic input]
716 _curses.window.addch
717 
718     [
719     y: int
720         Y-coordinate.
721     x: int
722         X-coordinate.
723     ]
724 
725     ch: object
726         Character to add.
727 
728     [
729     attr: long(c_default="A_NORMAL") = _curses.A_NORMAL
730         Attributes for the character.
731     ]
732     /
733 
734 Paint the character.
735 
736 Paint character ch at (y, x) with attributes attr,
737 overwriting any character previously painted at that location.
738 By default, the character position and attributes are the
739 current settings for the window object.
740 [clinic start generated code]*/
741 
742 static PyObject *
_curses_window_addch_impl(PyCursesWindowObject * self,int group_left_1,int y,int x,PyObject * ch,int group_right_1,long attr)743 _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1,
744                           int y, int x, PyObject *ch, int group_right_1,
745                           long attr)
746 /*[clinic end generated code: output=00f4c37af3378f45 input=95ce131578458196]*/
747 {
748     int coordinates_group = group_left_1;
749     int rtn;
750     int type;
751     chtype cch = 0;
752 #ifdef HAVE_NCURSESW
753     wchar_t wstr[2];
754     cchar_t wcval;
755 #endif
756     const char *funcname;
757 
758 #ifdef HAVE_NCURSESW
759     type = PyCurses_ConvertToCchar_t(self, ch, &cch, wstr);
760     if (type == 2) {
761         funcname = "add_wch";
762         wstr[1] = L'\0';
763         setcchar(&wcval, wstr, attr, PAIR_NUMBER(attr), NULL);
764         if (coordinates_group)
765             rtn = mvwadd_wch(self->win,y,x, &wcval);
766         else {
767             rtn = wadd_wch(self->win, &wcval);
768         }
769     }
770     else
771 #else
772     type = PyCurses_ConvertToCchar_t(self, ch, &cch);
773 #endif
774     if (type == 1) {
775         funcname = "addch";
776         if (coordinates_group)
777             rtn = mvwaddch(self->win,y,x, cch | (attr_t) attr);
778         else {
779             rtn = waddch(self->win, cch | (attr_t) attr);
780         }
781     }
782     else {
783         return NULL;
784     }
785     return PyCursesCheckERR(rtn, funcname);
786 }
787 
788 /*[clinic input]
789 _curses.window.addstr
790 
791     [
792     y: int
793         Y-coordinate.
794     x: int
795         X-coordinate.
796     ]
797 
798     str: object
799         String to add.
800 
801     [
802     attr: long
803         Attributes for characters.
804     ]
805     /
806 
807 Paint the string.
808 
809 Paint the string str at (y, x) with attributes attr,
810 overwriting anything previously on the display.
811 By default, the character position and attributes are the
812 current settings for the window object.
813 [clinic start generated code]*/
814 
815 static PyObject *
_curses_window_addstr_impl(PyCursesWindowObject * self,int group_left_1,int y,int x,PyObject * str,int group_right_1,long attr)816 _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1,
817                            int y, int x, PyObject *str, int group_right_1,
818                            long attr)
819 /*[clinic end generated code: output=65a928ea85ff3115 input=ff6cbb91448a22a3]*/
820 {
821     int rtn;
822     int strtype;
823     PyObject *bytesobj = NULL;
824 #ifdef HAVE_NCURSESW
825     wchar_t *wstr = NULL;
826 #endif
827     attr_t attr_old = A_NORMAL;
828     int use_xy = group_left_1, use_attr = group_right_1;
829     const char *funcname;
830 
831 #ifdef HAVE_NCURSESW
832     strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr);
833 #else
834     strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL);
835 #endif
836     if (strtype == 0) {
837         return NULL;
838     }
839     if (use_attr) {
840         attr_old = getattrs(self->win);
841         (void)wattrset(self->win,attr);
842     }
843 #ifdef HAVE_NCURSESW
844     if (strtype == 2) {
845         funcname = "addwstr";
846         if (use_xy)
847             rtn = mvwaddwstr(self->win,y,x,wstr);
848         else
849             rtn = waddwstr(self->win,wstr);
850         PyMem_Free(wstr);
851     }
852     else
853 #endif
854     {
855         const char *str = PyBytes_AS_STRING(bytesobj);
856         funcname = "addstr";
857         if (use_xy)
858             rtn = mvwaddstr(self->win,y,x,str);
859         else
860             rtn = waddstr(self->win,str);
861         Py_DECREF(bytesobj);
862     }
863     if (use_attr)
864         (void)wattrset(self->win,attr_old);
865     return PyCursesCheckERR(rtn, funcname);
866 }
867 
868 /*[clinic input]
869 _curses.window.addnstr
870 
871     [
872     y: int
873         Y-coordinate.
874     x: int
875         X-coordinate.
876     ]
877 
878     str: object
879         String to add.
880 
881     n: int
882         Maximal number of characters.
883 
884     [
885     attr: long
886         Attributes for characters.
887     ]
888     /
889 
890 Paint at most n characters of the string.
891 
892 Paint at most n characters of the string str at (y, x) with
893 attributes attr, overwriting anything previously on the display.
894 By default, the character position and attributes are the
895 current settings for the window object.
896 [clinic start generated code]*/
897 
898 static PyObject *
_curses_window_addnstr_impl(PyCursesWindowObject * self,int group_left_1,int y,int x,PyObject * str,int n,int group_right_1,long attr)899 _curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1,
900                             int y, int x, PyObject *str, int n,
901                             int group_right_1, long attr)
902 /*[clinic end generated code: output=6d21cee2ce6876d9 input=72718415c2744a2a]*/
903 {
904     int rtn;
905     int strtype;
906     PyObject *bytesobj = NULL;
907 #ifdef HAVE_NCURSESW
908     wchar_t *wstr = NULL;
909 #endif
910     attr_t attr_old = A_NORMAL;
911     int use_xy = group_left_1, use_attr = group_right_1;
912     const char *funcname;
913 
914 #ifdef HAVE_NCURSESW
915     strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr);
916 #else
917     strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL);
918 #endif
919     if (strtype == 0)
920         return NULL;
921 
922     if (use_attr) {
923         attr_old = getattrs(self->win);
924         (void)wattrset(self->win,attr);
925     }
926 #ifdef HAVE_NCURSESW
927     if (strtype == 2) {
928         funcname = "addnwstr";
929         if (use_xy)
930             rtn = mvwaddnwstr(self->win,y,x,wstr,n);
931         else
932             rtn = waddnwstr(self->win,wstr,n);
933         PyMem_Free(wstr);
934     }
935     else
936 #endif
937     {
938         const char *str = PyBytes_AS_STRING(bytesobj);
939         funcname = "addnstr";
940         if (use_xy)
941             rtn = mvwaddnstr(self->win,y,x,str,n);
942         else
943             rtn = waddnstr(self->win,str,n);
944         Py_DECREF(bytesobj);
945     }
946     if (use_attr)
947         (void)wattrset(self->win,attr_old);
948     return PyCursesCheckERR(rtn, funcname);
949 }
950 
951 /*[clinic input]
952 _curses.window.bkgd
953 
954     ch: object
955         Background character.
956     attr: long(c_default="A_NORMAL") = _curses.A_NORMAL
957         Background attributes.
958     /
959 
960 Set the background property of the window.
961 [clinic start generated code]*/
962 
963 static PyObject *
_curses_window_bkgd_impl(PyCursesWindowObject * self,PyObject * ch,long attr)964 _curses_window_bkgd_impl(PyCursesWindowObject *self, PyObject *ch, long attr)
965 /*[clinic end generated code: output=058290afb2cf4034 input=634015bcb339283d]*/
966 {
967     chtype bkgd;
968 
969     if (!PyCurses_ConvertToChtype(self, ch, &bkgd))
970         return NULL;
971 
972     return PyCursesCheckERR(wbkgd(self->win, bkgd | attr), "bkgd");
973 }
974 
975 /*[clinic input]
976 _curses.window.attroff
977 
978     attr: long
979     /
980 
981 Remove attribute attr from the "background" set.
982 [clinic start generated code]*/
983 
984 static PyObject *
_curses_window_attroff_impl(PyCursesWindowObject * self,long attr)985 _curses_window_attroff_impl(PyCursesWindowObject *self, long attr)
986 /*[clinic end generated code: output=8a2fcd4df682fc64 input=786beedf06a7befe]*/
987 {
988     return PyCursesCheckERR(wattroff(self->win, (attr_t)attr), "attroff");
989 }
990 
991 /*[clinic input]
992 _curses.window.attron
993 
994     attr: long
995     /
996 
997 Add attribute attr from the "background" set.
998 [clinic start generated code]*/
999 
1000 static PyObject *
_curses_window_attron_impl(PyCursesWindowObject * self,long attr)1001 _curses_window_attron_impl(PyCursesWindowObject *self, long attr)
1002 /*[clinic end generated code: output=7afea43b237fa870 input=5a88fba7b1524f32]*/
1003 {
1004     return PyCursesCheckERR(wattron(self->win, (attr_t)attr), "attron");
1005 }
1006 
1007 /*[clinic input]
1008 _curses.window.attrset
1009 
1010     attr: long
1011     /
1012 
1013 Set the "background" set of attributes.
1014 [clinic start generated code]*/
1015 
1016 static PyObject *
_curses_window_attrset_impl(PyCursesWindowObject * self,long attr)1017 _curses_window_attrset_impl(PyCursesWindowObject *self, long attr)
1018 /*[clinic end generated code: output=84e379bff20c0433 input=42e400c0d0154ab5]*/
1019 {
1020     return PyCursesCheckERR(wattrset(self->win, (attr_t)attr), "attrset");
1021 }
1022 
1023 /*[clinic input]
1024 _curses.window.bkgdset
1025 
1026     ch: object
1027         Background character.
1028     attr: long(c_default="A_NORMAL") = _curses.A_NORMAL
1029         Background attributes.
1030     /
1031 
1032 Set the window's background.
1033 [clinic start generated code]*/
1034 
1035 static PyObject *
_curses_window_bkgdset_impl(PyCursesWindowObject * self,PyObject * ch,long attr)1036 _curses_window_bkgdset_impl(PyCursesWindowObject *self, PyObject *ch,
1037                             long attr)
1038 /*[clinic end generated code: output=8cb994fc4d7e2496 input=e09c682425c9e45b]*/
1039 {
1040     chtype bkgd;
1041 
1042     if (!PyCurses_ConvertToChtype(self, ch, &bkgd))
1043         return NULL;
1044 
1045     wbkgdset(self->win, bkgd | attr);
1046     return PyCursesCheckERR(0, "bkgdset");
1047 }
1048 
1049 /*[clinic input]
1050 _curses.window.border
1051 
1052     ls: object(c_default="NULL") = _curses.ACS_VLINE
1053         Left side.
1054     rs: object(c_default="NULL") = _curses.ACS_VLINE
1055         Right side.
1056     ts: object(c_default="NULL") = _curses.ACS_HLINE
1057         Top side.
1058     bs: object(c_default="NULL") = _curses.ACS_HLINE
1059         Bottom side.
1060     tl: object(c_default="NULL") = _curses.ACS_ULCORNER
1061         Upper-left corner.
1062     tr: object(c_default="NULL") = _curses.ACS_URCORNER
1063         Upper-right corner.
1064     bl: object(c_default="NULL") = _curses.ACS_LLCORNER
1065         Bottom-left corner.
1066     br: object(c_default="NULL") = _curses.ACS_LRCORNER
1067         Bottom-right corner.
1068     /
1069 
1070 Draw a border around the edges of the window.
1071 
1072 Each parameter specifies the character to use for a specific part of the
1073 border.  The characters can be specified as integers or as one-character
1074 strings.  A 0 value for any parameter will cause the default character to be
1075 used for that parameter.
1076 [clinic start generated code]*/
1077 
1078 static PyObject *
_curses_window_border_impl(PyCursesWindowObject * self,PyObject * ls,PyObject * rs,PyObject * ts,PyObject * bs,PyObject * tl,PyObject * tr,PyObject * bl,PyObject * br)1079 _curses_window_border_impl(PyCursesWindowObject *self, PyObject *ls,
1080                            PyObject *rs, PyObject *ts, PyObject *bs,
1081                            PyObject *tl, PyObject *tr, PyObject *bl,
1082                            PyObject *br)
1083 /*[clinic end generated code: output=670ef38d3d7c2aa3 input=e015f735d67a240b]*/
1084 {
1085     chtype ch[8];
1086     int i;
1087 
1088     /* Clear the array of parameters */
1089     for(i=0; i<8; i++)
1090         ch[i] = 0;
1091 
1092 #define CONVERTTOCHTYPE(obj, i) \
1093     if ((obj) != NULL && !PyCurses_ConvertToChtype(self, (obj), &ch[(i)])) \
1094         return NULL;
1095 
1096     CONVERTTOCHTYPE(ls, 0);
1097     CONVERTTOCHTYPE(rs, 1);
1098     CONVERTTOCHTYPE(ts, 2);
1099     CONVERTTOCHTYPE(bs, 3);
1100     CONVERTTOCHTYPE(tl, 4);
1101     CONVERTTOCHTYPE(tr, 5);
1102     CONVERTTOCHTYPE(bl, 6);
1103     CONVERTTOCHTYPE(br, 7);
1104 
1105 #undef CONVERTTOCHTYPE
1106 
1107     wborder(self->win,
1108             ch[0], ch[1], ch[2], ch[3],
1109             ch[4], ch[5], ch[6], ch[7]);
1110     Py_RETURN_NONE;
1111 }
1112 
1113 /*[clinic input]
1114 _curses.window.box
1115 
1116     [
1117     verch: object(c_default="_PyLong_GetZero()") = 0
1118         Left and right side.
1119     horch: object(c_default="_PyLong_GetZero()") = 0
1120         Top and bottom side.
1121     ]
1122     /
1123 
1124 Draw a border around the edges of the window.
1125 
1126 Similar to border(), but both ls and rs are verch and both ts and bs are
1127 horch.  The default corner characters are always used by this function.
1128 [clinic start generated code]*/
1129 
1130 static PyObject *
_curses_window_box_impl(PyCursesWindowObject * self,int group_right_1,PyObject * verch,PyObject * horch)1131 _curses_window_box_impl(PyCursesWindowObject *self, int group_right_1,
1132                         PyObject *verch, PyObject *horch)
1133 /*[clinic end generated code: output=f3fcb038bb287192 input=f00435f9c8c98f60]*/
1134 {
1135     chtype ch1 = 0, ch2 = 0;
1136     if (group_right_1) {
1137         if (!PyCurses_ConvertToChtype(self, verch, &ch1)) {
1138             return NULL;
1139         }
1140         if (!PyCurses_ConvertToChtype(self, horch, &ch2)) {
1141             return NULL;
1142         }
1143     }
1144     box(self->win,ch1,ch2);
1145     Py_RETURN_NONE;
1146 }
1147 
1148 #if defined(HAVE_NCURSES_H) || defined(MVWDELCH_IS_EXPRESSION)
1149 #define py_mvwdelch mvwdelch
1150 #else
py_mvwdelch(WINDOW * w,int y,int x)1151 int py_mvwdelch(WINDOW *w, int y, int x)
1152 {
1153     mvwdelch(w,y,x);
1154     /* On HP/UX, mvwdelch already returns. On other systems,
1155        we may well run into this return statement. */
1156     return 0;
1157 }
1158 #endif
1159 
1160 #if defined(HAVE_CURSES_IS_PAD)
1161 #define py_is_pad(win)      is_pad(win)
1162 #elif defined(WINDOW_HAS_FLAGS)
1163 #define py_is_pad(win)      ((win) ? ((win)->_flags & _ISPAD) != 0 : FALSE)
1164 #endif
1165 
1166 /* chgat, added by Fabian Kreutz <fabian.kreutz at gmx.net> */
1167 #ifdef HAVE_CURSES_WCHGAT
1168 /*[-clinic input]
1169 _curses.window.chgat
1170 
1171     [
1172     y: int
1173         Y-coordinate.
1174     x: int
1175         X-coordinate.
1176     ]
1177 
1178     n: int = -1
1179         Number of characters.
1180 
1181     attr: long
1182         Attributes for characters.
1183     /
1184 
1185 Set the attributes of characters.
1186 
1187 Set the attributes of num characters at the current cursor position, or at
1188 position (y, x) if supplied.  If no value of num is given or num = -1, the
1189 attribute will be set on all the characters to the end of the line.  This
1190 function does not move the cursor.  The changed line will be touched using
1191 the touchline() method so that the contents will be redisplayed by the next
1192 window refresh.
1193 [-clinic start generated code]*/
1194 static PyObject *
PyCursesWindow_ChgAt(PyCursesWindowObject * self,PyObject * args)1195 PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args)
1196 {
1197     int rtn;
1198     int x, y;
1199     int num = -1;
1200     short color;
1201     attr_t attr = A_NORMAL;
1202     long lattr;
1203     int use_xy = FALSE;
1204 
1205     switch (PyTuple_Size(args)) {
1206     case 1:
1207         if (!PyArg_ParseTuple(args,"l;attr", &lattr))
1208             return NULL;
1209         attr = lattr;
1210         break;
1211     case 2:
1212         if (!PyArg_ParseTuple(args,"il;n,attr", &num, &lattr))
1213             return NULL;
1214         attr = lattr;
1215         break;
1216     case 3:
1217         if (!PyArg_ParseTuple(args,"iil;int,int,attr", &y, &x, &lattr))
1218             return NULL;
1219         attr = lattr;
1220         use_xy = TRUE;
1221         break;
1222     case 4:
1223         if (!PyArg_ParseTuple(args,"iiil;int,int,n,attr", &y, &x, &num, &lattr))
1224             return NULL;
1225         attr = lattr;
1226         use_xy = TRUE;
1227         break;
1228     default:
1229         PyErr_SetString(PyExc_TypeError, "chgat requires 1 to 4 arguments");
1230         return NULL;
1231     }
1232 
1233     color = (short)((attr >> 8) & 0xff);
1234     attr = attr - (color << 8);
1235 
1236     if (use_xy) {
1237         rtn = mvwchgat(self->win,y,x,num,attr,color,NULL);
1238         touchline(self->win,y,1);
1239     } else {
1240         getyx(self->win,y,x);
1241         rtn = wchgat(self->win,num,attr,color,NULL);
1242         touchline(self->win,y,1);
1243     }
1244     return PyCursesCheckERR(rtn, "chgat");
1245 }
1246 #endif
1247 
1248 /*[clinic input]
1249 _curses.window.delch
1250 
1251     [
1252     y: int
1253         Y-coordinate.
1254     x: int
1255         X-coordinate.
1256     ]
1257     /
1258 
1259 Delete any character at (y, x).
1260 [clinic start generated code]*/
1261 
1262 static PyObject *
_curses_window_delch_impl(PyCursesWindowObject * self,int group_right_1,int y,int x)1263 _curses_window_delch_impl(PyCursesWindowObject *self, int group_right_1,
1264                           int y, int x)
1265 /*[clinic end generated code: output=22e77bb9fa11b461 input=d2f79e630a4fc6d0]*/
1266 {
1267     if (!group_right_1) {
1268         return PyCursesCheckERR(wdelch(self->win), "wdelch");
1269     }
1270     else {
1271         return PyCursesCheckERR(py_mvwdelch(self->win, y, x), "mvwdelch");
1272     }
1273 }
1274 
1275 /*[clinic input]
1276 _curses.window.derwin
1277 
1278     [
1279     nlines: int = 0
1280         Height.
1281     ncols: int = 0
1282         Width.
1283     ]
1284     begin_y: int
1285         Top side y-coordinate.
1286     begin_x: int
1287         Left side x-coordinate.
1288     /
1289 
1290 Create a sub-window (window-relative coordinates).
1291 
1292 derwin() is the same as calling subwin(), except that begin_y and begin_x
1293 are relative to the origin of the window, rather than relative to the entire
1294 screen.
1295 [clinic start generated code]*/
1296 
1297 static PyObject *
_curses_window_derwin_impl(PyCursesWindowObject * self,int group_left_1,int nlines,int ncols,int begin_y,int begin_x)1298 _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1,
1299                            int nlines, int ncols, int begin_y, int begin_x)
1300 /*[clinic end generated code: output=7924b112d9f70d6e input=966d9481f7f5022e]*/
1301 {
1302     WINDOW *win;
1303 
1304     win = derwin(self->win,nlines,ncols,begin_y,begin_x);
1305 
1306     if (win == NULL) {
1307         PyErr_SetString(PyCursesError, catchall_NULL);
1308         return NULL;
1309     }
1310 
1311     return (PyObject *)PyCursesWindow_New(win, NULL);
1312 }
1313 
1314 /*[clinic input]
1315 _curses.window.echochar
1316 
1317     ch: object
1318         Character to add.
1319 
1320     attr: long(c_default="A_NORMAL") = _curses.A_NORMAL
1321         Attributes for the character.
1322     /
1323 
1324 Add character ch with attribute attr, and refresh.
1325 [clinic start generated code]*/
1326 
1327 static PyObject *
_curses_window_echochar_impl(PyCursesWindowObject * self,PyObject * ch,long attr)1328 _curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch,
1329                              long attr)
1330 /*[clinic end generated code: output=13e7dd875d4b9642 input=e7f34b964e92b156]*/
1331 {
1332     chtype ch_;
1333 
1334     if (!PyCurses_ConvertToChtype(self, ch, &ch_))
1335         return NULL;
1336 
1337 #ifdef py_is_pad
1338     if (py_is_pad(self->win)) {
1339         return PyCursesCheckERR(pechochar(self->win, ch_ | (attr_t)attr),
1340                                 "echochar");
1341     }
1342     else
1343 #endif
1344         return PyCursesCheckERR(wechochar(self->win, ch_ | (attr_t)attr),
1345                                 "echochar");
1346 }
1347 
1348 #ifdef NCURSES_MOUSE_VERSION
1349 /*[clinic input]
1350 _curses.window.enclose
1351 
1352     y: int
1353         Y-coordinate.
1354     x: int
1355         X-coordinate.
1356     /
1357 
1358 Return True if the screen-relative coordinates are enclosed by the window.
1359 [clinic start generated code]*/
1360 
1361 static PyObject *
_curses_window_enclose_impl(PyCursesWindowObject * self,int y,int x)1362 _curses_window_enclose_impl(PyCursesWindowObject *self, int y, int x)
1363 /*[clinic end generated code: output=8679beef50502648 input=4fd3355d723f7bc9]*/
1364 {
1365     return PyBool_FromLong(wenclose(self->win, y, x));
1366 }
1367 #endif
1368 
1369 /*[clinic input]
1370 _curses.window.getbkgd -> long
1371 
1372 Return the window's current background character/attribute pair.
1373 [clinic start generated code]*/
1374 
1375 static long
_curses_window_getbkgd_impl(PyCursesWindowObject * self)1376 _curses_window_getbkgd_impl(PyCursesWindowObject *self)
1377 /*[clinic end generated code: output=c52b25dc16b215c3 input=a69db882fa35426c]*/
1378 {
1379     return (long) getbkgd(self->win);
1380 }
1381 
1382 /*[clinic input]
1383 _curses.window.getch -> int
1384 
1385     [
1386     y: int
1387         Y-coordinate.
1388     x: int
1389         X-coordinate.
1390     ]
1391     /
1392 
1393 Get a character code from terminal keyboard.
1394 
1395 The integer returned does not have to be in ASCII range: function keys,
1396 keypad keys and so on return numbers higher than 256.  In no-delay mode, -1
1397 is returned if there is no input, else getch() waits until a key is pressed.
1398 [clinic start generated code]*/
1399 
1400 static int
_curses_window_getch_impl(PyCursesWindowObject * self,int group_right_1,int y,int x)1401 _curses_window_getch_impl(PyCursesWindowObject *self, int group_right_1,
1402                           int y, int x)
1403 /*[clinic end generated code: output=980aa6af0c0ca387 input=bb24ebfb379f991f]*/
1404 {
1405     int rtn;
1406 
1407     Py_BEGIN_ALLOW_THREADS
1408     if (!group_right_1) {
1409         rtn = wgetch(self->win);
1410     }
1411     else {
1412         rtn = mvwgetch(self->win, y, x);
1413     }
1414     Py_END_ALLOW_THREADS
1415 
1416     return rtn;
1417 }
1418 
1419 /*[clinic input]
1420 _curses.window.getkey
1421 
1422     [
1423     y: int
1424         Y-coordinate.
1425     x: int
1426         X-coordinate.
1427     ]
1428     /
1429 
1430 Get a character (string) from terminal keyboard.
1431 
1432 Returning a string instead of an integer, as getch() does.  Function keys,
1433 keypad keys and other special keys return a multibyte string containing the
1434 key name.  In no-delay mode, an exception is raised if there is no input.
1435 [clinic start generated code]*/
1436 
1437 static PyObject *
_curses_window_getkey_impl(PyCursesWindowObject * self,int group_right_1,int y,int x)1438 _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1,
1439                            int y, int x)
1440 /*[clinic end generated code: output=8490a182db46b10f input=be2dee34f5cf57f8]*/
1441 {
1442     int rtn;
1443 
1444     Py_BEGIN_ALLOW_THREADS
1445     if (!group_right_1) {
1446         rtn = wgetch(self->win);
1447     }
1448     else {
1449         rtn = mvwgetch(self->win, y, x);
1450     }
1451     Py_END_ALLOW_THREADS
1452 
1453     if (rtn == ERR) {
1454         /* getch() returns ERR in nodelay mode */
1455         PyErr_CheckSignals();
1456         if (!PyErr_Occurred())
1457             PyErr_SetString(PyCursesError, "no input");
1458         return NULL;
1459     } else if (rtn <= 255) {
1460 #ifdef NCURSES_VERSION_MAJOR
1461 #if NCURSES_VERSION_MAJOR*100+NCURSES_VERSION_MINOR <= 507
1462         /* Work around a bug in ncurses 5.7 and earlier */
1463         if (rtn < 0) {
1464             rtn += 256;
1465         }
1466 #endif
1467 #endif
1468         return PyUnicode_FromOrdinal(rtn);
1469     } else {
1470         const char *knp = keyname(rtn);
1471         return PyUnicode_FromString((knp == NULL) ? "" : knp);
1472     }
1473 }
1474 
1475 #ifdef HAVE_NCURSESW
1476 /*[clinic input]
1477 _curses.window.get_wch
1478 
1479     [
1480     y: int
1481         Y-coordinate.
1482     x: int
1483         X-coordinate.
1484     ]
1485     /
1486 
1487 Get a wide character from terminal keyboard.
1488 
1489 Return a character for most keys, or an integer for function keys,
1490 keypad keys, and other special keys.
1491 [clinic start generated code]*/
1492 
1493 static PyObject *
_curses_window_get_wch_impl(PyCursesWindowObject * self,int group_right_1,int y,int x)1494 _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1,
1495                             int y, int x)
1496 /*[clinic end generated code: output=9f4f86e91fe50ef3 input=dd7e5367fb49dc48]*/
1497 {
1498     int ct;
1499     wint_t rtn;
1500 
1501     Py_BEGIN_ALLOW_THREADS
1502     if (!group_right_1) {
1503         ct = wget_wch(self->win ,&rtn);
1504     }
1505     else {
1506         ct = mvwget_wch(self->win, y, x, &rtn);
1507     }
1508     Py_END_ALLOW_THREADS
1509 
1510     if (ct == ERR) {
1511         if (PyErr_CheckSignals())
1512             return NULL;
1513 
1514         /* get_wch() returns ERR in nodelay mode */
1515         PyErr_SetString(PyCursesError, "no input");
1516         return NULL;
1517     }
1518     if (ct == KEY_CODE_YES)
1519         return PyLong_FromLong(rtn);
1520     else
1521         return PyUnicode_FromOrdinal(rtn);
1522 }
1523 #endif
1524 
1525 /*[-clinic input]
1526 _curses.window.getstr
1527 
1528     [
1529     y: int
1530         Y-coordinate.
1531     x: int
1532         X-coordinate.
1533     ]
1534     n: int = 1023
1535         Maximal number of characters.
1536     /
1537 
1538 Read a string from the user, with primitive line editing capacity.
1539 [-clinic start generated code]*/
1540 
1541 static PyObject *
PyCursesWindow_GetStr(PyCursesWindowObject * self,PyObject * args)1542 PyCursesWindow_GetStr(PyCursesWindowObject *self, PyObject *args)
1543 {
1544     int x, y, n;
1545     char rtn[1024]; /* This should be big enough.. I hope */
1546     int rtn2;
1547 
1548     switch (PyTuple_Size(args)) {
1549     case 0:
1550         Py_BEGIN_ALLOW_THREADS
1551         rtn2 = wgetnstr(self->win,rtn, 1023);
1552         Py_END_ALLOW_THREADS
1553         break;
1554     case 1:
1555         if (!PyArg_ParseTuple(args,"i;n", &n))
1556             return NULL;
1557         if (n < 0) {
1558             PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
1559             return NULL;
1560         }
1561         Py_BEGIN_ALLOW_THREADS
1562         rtn2 = wgetnstr(self->win, rtn, Py_MIN(n, 1023));
1563         Py_END_ALLOW_THREADS
1564         break;
1565     case 2:
1566         if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
1567             return NULL;
1568         Py_BEGIN_ALLOW_THREADS
1569 #ifdef STRICT_SYSV_CURSES
1570         rtn2 = wmove(self->win,y,x)==ERR ? ERR : wgetnstr(self->win, rtn, 1023);
1571 #else
1572         rtn2 = mvwgetnstr(self->win,y,x,rtn, 1023);
1573 #endif
1574         Py_END_ALLOW_THREADS
1575         break;
1576     case 3:
1577         if (!PyArg_ParseTuple(args,"iii;y,x,n", &y, &x, &n))
1578             return NULL;
1579         if (n < 0) {
1580             PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
1581             return NULL;
1582         }
1583 #ifdef STRICT_SYSV_CURSES
1584         Py_BEGIN_ALLOW_THREADS
1585         rtn2 = wmove(self->win,y,x)==ERR ? ERR :
1586         wgetnstr(self->win, rtn, Py_MIN(n, 1023));
1587         Py_END_ALLOW_THREADS
1588 #else
1589         Py_BEGIN_ALLOW_THREADS
1590         rtn2 = mvwgetnstr(self->win, y, x, rtn, Py_MIN(n, 1023));
1591         Py_END_ALLOW_THREADS
1592 #endif
1593         break;
1594     default:
1595         PyErr_SetString(PyExc_TypeError, "getstr requires 0 to 3 arguments");
1596         return NULL;
1597     }
1598     if (rtn2 == ERR)
1599         rtn[0] = 0;
1600     return PyBytes_FromString(rtn);
1601 }
1602 
1603 /*[clinic input]
1604 _curses.window.hline
1605 
1606     [
1607     y: int
1608         Starting Y-coordinate.
1609     x: int
1610         Starting X-coordinate.
1611     ]
1612 
1613     ch: object
1614         Character to draw.
1615     n: int
1616         Line length.
1617 
1618     [
1619     attr: long(c_default="A_NORMAL") = _curses.A_NORMAL
1620         Attributes for the characters.
1621     ]
1622     /
1623 
1624 Display a horizontal line.
1625 [clinic start generated code]*/
1626 
1627 static PyObject *
_curses_window_hline_impl(PyCursesWindowObject * self,int group_left_1,int y,int x,PyObject * ch,int n,int group_right_1,long attr)1628 _curses_window_hline_impl(PyCursesWindowObject *self, int group_left_1,
1629                           int y, int x, PyObject *ch, int n,
1630                           int group_right_1, long attr)
1631 /*[clinic end generated code: output=c00d489d61fc9eef input=81a4dea47268163e]*/
1632 {
1633     chtype ch_;
1634 
1635     if (!PyCurses_ConvertToChtype(self, ch, &ch_))
1636         return NULL;
1637     if (group_left_1) {
1638         if (wmove(self->win, y, x) == ERR) {
1639             return PyCursesCheckERR(ERR, "wmove");
1640         }
1641     }
1642     return PyCursesCheckERR(whline(self->win, ch_ | (attr_t)attr, n), "hline");
1643 }
1644 
1645 /*[clinic input]
1646 _curses.window.insch
1647 
1648     [
1649     y: int
1650         Y-coordinate.
1651     x: int
1652         X-coordinate.
1653     ]
1654 
1655     ch: object
1656         Character to insert.
1657 
1658     [
1659     attr: long(c_default="A_NORMAL") = _curses.A_NORMAL
1660         Attributes for the character.
1661     ]
1662     /
1663 
1664 Insert a character before the current or specified position.
1665 
1666 All characters to the right of the cursor are shifted one position right, with
1667 the rightmost characters on the line being lost.
1668 [clinic start generated code]*/
1669 
1670 static PyObject *
_curses_window_insch_impl(PyCursesWindowObject * self,int group_left_1,int y,int x,PyObject * ch,int group_right_1,long attr)1671 _curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1,
1672                           int y, int x, PyObject *ch, int group_right_1,
1673                           long attr)
1674 /*[clinic end generated code: output=ade8cfe3a3bf3e34 input=336342756ee19812]*/
1675 {
1676     int rtn;
1677     chtype ch_ = 0;
1678 
1679     if (!PyCurses_ConvertToChtype(self, ch, &ch_))
1680         return NULL;
1681 
1682     if (!group_left_1) {
1683         rtn = winsch(self->win, ch_ | (attr_t)attr);
1684     }
1685     else {
1686         rtn = mvwinsch(self->win, y, x, ch_ | (attr_t)attr);
1687     }
1688 
1689     return PyCursesCheckERR(rtn, "insch");
1690 }
1691 
1692 /*[clinic input]
1693 _curses.window.inch -> unsigned_long
1694 
1695     [
1696     y: int
1697         Y-coordinate.
1698     x: int
1699         X-coordinate.
1700     ]
1701     /
1702 
1703 Return the character at the given position in the window.
1704 
1705 The bottom 8 bits are the character proper, and upper bits are the attributes.
1706 [clinic start generated code]*/
1707 
1708 static unsigned long
_curses_window_inch_impl(PyCursesWindowObject * self,int group_right_1,int y,int x)1709 _curses_window_inch_impl(PyCursesWindowObject *self, int group_right_1,
1710                          int y, int x)
1711 /*[clinic end generated code: output=6c4719fe978fe86a input=fac23ee11e3b3a66]*/
1712 {
1713     unsigned long rtn;
1714 
1715     if (!group_right_1) {
1716         rtn = winch(self->win);
1717     }
1718     else {
1719         rtn = mvwinch(self->win, y, x);
1720     }
1721 
1722     return rtn;
1723 }
1724 
1725 /*[-clinic input]
1726 _curses.window.instr
1727 
1728     [
1729     y: int
1730         Y-coordinate.
1731     x: int
1732         X-coordinate.
1733     ]
1734     n: int = 1023
1735         Maximal number of characters.
1736     /
1737 
1738 Return a string of characters, extracted from the window.
1739 
1740 Return a string of characters, extracted from the window starting at the
1741 current cursor position, or at y, x if specified.  Attributes are stripped
1742 from the characters.  If n is specified, instr() returns a string at most
1743 n characters long (exclusive of the trailing NUL).
1744 [-clinic start generated code]*/
1745 static PyObject *
PyCursesWindow_InStr(PyCursesWindowObject * self,PyObject * args)1746 PyCursesWindow_InStr(PyCursesWindowObject *self, PyObject *args)
1747 {
1748     int x, y, n;
1749     char rtn[1024]; /* This should be big enough.. I hope */
1750     int rtn2;
1751 
1752     switch (PyTuple_Size(args)) {
1753     case 0:
1754         rtn2 = winnstr(self->win,rtn, 1023);
1755         break;
1756     case 1:
1757         if (!PyArg_ParseTuple(args,"i;n", &n))
1758             return NULL;
1759         if (n < 0) {
1760             PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
1761             return NULL;
1762         }
1763         rtn2 = winnstr(self->win, rtn, Py_MIN(n, 1023));
1764         break;
1765     case 2:
1766         if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
1767             return NULL;
1768         rtn2 = mvwinnstr(self->win,y,x,rtn,1023);
1769         break;
1770     case 3:
1771         if (!PyArg_ParseTuple(args, "iii;y,x,n", &y, &x, &n))
1772             return NULL;
1773         if (n < 0) {
1774             PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
1775             return NULL;
1776         }
1777         rtn2 = mvwinnstr(self->win, y, x, rtn, Py_MIN(n,1023));
1778         break;
1779     default:
1780         PyErr_SetString(PyExc_TypeError, "instr requires 0 or 3 arguments");
1781         return NULL;
1782     }
1783     if (rtn2 == ERR)
1784         rtn[0] = 0;
1785     return PyBytes_FromString(rtn);
1786 }
1787 
1788 /*[clinic input]
1789 _curses.window.insstr
1790 
1791     [
1792     y: int
1793         Y-coordinate.
1794     x: int
1795         X-coordinate.
1796     ]
1797 
1798     str: object
1799         String to insert.
1800 
1801     [
1802     attr: long
1803         Attributes for characters.
1804     ]
1805     /
1806 
1807 Insert the string before the current or specified position.
1808 
1809 Insert a character string (as many characters as will fit on the line)
1810 before the character under the cursor.  All characters to the right of
1811 the cursor are shifted right, with the rightmost characters on the line
1812 being lost.  The cursor position does not change (after moving to y, x,
1813 if specified).
1814 [clinic start generated code]*/
1815 
1816 static PyObject *
_curses_window_insstr_impl(PyCursesWindowObject * self,int group_left_1,int y,int x,PyObject * str,int group_right_1,long attr)1817 _curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1,
1818                            int y, int x, PyObject *str, int group_right_1,
1819                            long attr)
1820 /*[clinic end generated code: output=c259a5265ad0b777 input=6827cddc6340a7f3]*/
1821 {
1822     int rtn;
1823     int strtype;
1824     PyObject *bytesobj = NULL;
1825 #ifdef HAVE_NCURSESW
1826     wchar_t *wstr = NULL;
1827 #endif
1828     attr_t attr_old = A_NORMAL;
1829     int use_xy = group_left_1, use_attr = group_right_1;
1830     const char *funcname;
1831 
1832 #ifdef HAVE_NCURSESW
1833     strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr);
1834 #else
1835     strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL);
1836 #endif
1837     if (strtype == 0)
1838         return NULL;
1839 
1840     if (use_attr) {
1841         attr_old = getattrs(self->win);
1842         (void)wattrset(self->win, (attr_t)attr);
1843     }
1844 #ifdef HAVE_NCURSESW
1845     if (strtype == 2) {
1846         funcname = "inswstr";
1847         if (use_xy)
1848             rtn = mvwins_wstr(self->win,y,x,wstr);
1849         else
1850             rtn = wins_wstr(self->win,wstr);
1851         PyMem_Free(wstr);
1852     }
1853     else
1854 #endif
1855     {
1856         const char *str = PyBytes_AS_STRING(bytesobj);
1857         funcname = "insstr";
1858         if (use_xy)
1859             rtn = mvwinsstr(self->win,y,x,str);
1860         else
1861             rtn = winsstr(self->win,str);
1862         Py_DECREF(bytesobj);
1863     }
1864     if (use_attr)
1865         (void)wattrset(self->win,attr_old);
1866     return PyCursesCheckERR(rtn, funcname);
1867 }
1868 
1869 /*[clinic input]
1870 _curses.window.insnstr
1871 
1872     [
1873     y: int
1874         Y-coordinate.
1875     x: int
1876         X-coordinate.
1877     ]
1878 
1879     str: object
1880         String to insert.
1881 
1882     n: int
1883         Maximal number of characters.
1884 
1885     [
1886     attr: long
1887         Attributes for characters.
1888     ]
1889     /
1890 
1891 Insert at most n characters of the string.
1892 
1893 Insert a character string (as many characters as will fit on the line)
1894 before the character under the cursor, up to n characters.  If n is zero
1895 or negative, the entire string is inserted.  All characters to the right
1896 of the cursor are shifted right, with the rightmost characters on the line
1897 being lost.  The cursor position does not change (after moving to y, x, if
1898 specified).
1899 [clinic start generated code]*/
1900 
1901 static PyObject *
_curses_window_insnstr_impl(PyCursesWindowObject * self,int group_left_1,int y,int x,PyObject * str,int n,int group_right_1,long attr)1902 _curses_window_insnstr_impl(PyCursesWindowObject *self, int group_left_1,
1903                             int y, int x, PyObject *str, int n,
1904                             int group_right_1, long attr)
1905 /*[clinic end generated code: output=971a32ea6328ec8b input=70fa0cd543901a4c]*/
1906 {
1907     int rtn;
1908     int strtype;
1909     PyObject *bytesobj = NULL;
1910 #ifdef HAVE_NCURSESW
1911     wchar_t *wstr = NULL;
1912 #endif
1913     attr_t attr_old = A_NORMAL;
1914     int use_xy = group_left_1, use_attr = group_right_1;
1915     const char *funcname;
1916 
1917 #ifdef HAVE_NCURSESW
1918     strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr);
1919 #else
1920     strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL);
1921 #endif
1922     if (strtype == 0)
1923         return NULL;
1924 
1925     if (use_attr) {
1926         attr_old = getattrs(self->win);
1927         (void)wattrset(self->win, (attr_t)attr);
1928     }
1929 #ifdef HAVE_NCURSESW
1930     if (strtype == 2) {
1931         funcname = "insn_wstr";
1932         if (use_xy)
1933             rtn = mvwins_nwstr(self->win,y,x,wstr,n);
1934         else
1935             rtn = wins_nwstr(self->win,wstr,n);
1936         PyMem_Free(wstr);
1937     }
1938     else
1939 #endif
1940     {
1941         const char *str = PyBytes_AS_STRING(bytesobj);
1942         funcname = "insnstr";
1943         if (use_xy)
1944             rtn = mvwinsnstr(self->win,y,x,str,n);
1945         else
1946             rtn = winsnstr(self->win,str,n);
1947         Py_DECREF(bytesobj);
1948     }
1949     if (use_attr)
1950         (void)wattrset(self->win,attr_old);
1951     return PyCursesCheckERR(rtn, funcname);
1952 }
1953 
1954 /*[clinic input]
1955 _curses.window.is_linetouched
1956 
1957     line: int
1958         Line number.
1959     /
1960 
1961 Return True if the specified line was modified, otherwise return False.
1962 
1963 Raise a curses.error exception if line is not valid for the given window.
1964 [clinic start generated code]*/
1965 
1966 static PyObject *
_curses_window_is_linetouched_impl(PyCursesWindowObject * self,int line)1967 _curses_window_is_linetouched_impl(PyCursesWindowObject *self, int line)
1968 /*[clinic end generated code: output=ad4a4edfee2db08c input=a7be0c189f243914]*/
1969 {
1970     int erg;
1971     erg = is_linetouched(self->win, line);
1972     if (erg == ERR) {
1973         PyErr_SetString(PyExc_TypeError,
1974                         "is_linetouched: line number outside of boundaries");
1975         return NULL;
1976     }
1977     return PyBool_FromLong(erg);
1978 }
1979 
1980 #ifdef py_is_pad
1981 /*[clinic input]
1982 _curses.window.noutrefresh
1983 
1984     [
1985     pminrow: int
1986     pmincol: int
1987     sminrow: int
1988     smincol: int
1989     smaxrow: int
1990     smaxcol: int
1991     ]
1992     /
1993 
1994 Mark for refresh but wait.
1995 
1996 This function updates the data structure representing the desired state of the
1997 window, but does not force an update of the physical screen.  To accomplish
1998 that, call doupdate().
1999 [clinic start generated code]*/
2000 
2001 static PyObject *
_curses_window_noutrefresh_impl(PyCursesWindowObject * self,int group_right_1,int pminrow,int pmincol,int sminrow,int smincol,int smaxrow,int smaxcol)2002 _curses_window_noutrefresh_impl(PyCursesWindowObject *self,
2003                                 int group_right_1, int pminrow, int pmincol,
2004                                 int sminrow, int smincol, int smaxrow,
2005                                 int smaxcol)
2006 /*[clinic end generated code: output=809a1f3c6a03e23e input=3e56898388cd739e]*/
2007 #else
2008 /*[clinic input]
2009 _curses.window.noutrefresh
2010 
2011 Mark for refresh but wait.
2012 
2013 This function updates the data structure representing the desired state of the
2014 window, but does not force an update of the physical screen.  To accomplish
2015 that, call doupdate().
2016 [clinic start generated code]*/
2017 
2018 static PyObject *
2019 _curses_window_noutrefresh_impl(PyCursesWindowObject *self)
2020 /*[clinic end generated code: output=6ef6dec666643fee input=876902e3fa431dbd]*/
2021 #endif
2022 {
2023     int rtn;
2024 
2025 #ifdef py_is_pad
2026     if (py_is_pad(self->win)) {
2027         if (!group_right_1) {
2028             PyErr_SetString(PyCursesError,
2029                             "noutrefresh() called for a pad "
2030                             "requires 6 arguments");
2031             return NULL;
2032         }
2033         Py_BEGIN_ALLOW_THREADS
2034         rtn = pnoutrefresh(self->win, pminrow, pmincol,
2035                            sminrow, smincol, smaxrow, smaxcol);
2036         Py_END_ALLOW_THREADS
2037         return PyCursesCheckERR(rtn, "pnoutrefresh");
2038     }
2039     if (group_right_1) {
2040         PyErr_SetString(PyExc_TypeError,
2041                         "noutrefresh() takes no arguments (6 given)");
2042         return NULL;
2043     }
2044 #endif
2045     Py_BEGIN_ALLOW_THREADS
2046     rtn = wnoutrefresh(self->win);
2047     Py_END_ALLOW_THREADS
2048     return PyCursesCheckERR(rtn, "wnoutrefresh");
2049 }
2050 
2051 /*[clinic input]
2052 _curses.window.overlay
2053 
2054     destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type")
2055 
2056     [
2057     sminrow: int
2058     smincol: int
2059     dminrow: int
2060     dmincol: int
2061     dmaxrow: int
2062     dmaxcol: int
2063     ]
2064     /
2065 
2066 Overlay the window on top of destwin.
2067 
2068 The windows need not be the same size, only the overlapping region is copied.
2069 This copy is non-destructive, which means that the current background
2070 character does not overwrite the old contents of destwin.
2071 
2072 To get fine-grained control over the copied region, the second form of
2073 overlay() can be used.  sminrow and smincol are the upper-left coordinates
2074 of the source window, and the other variables mark a rectangle in the
2075 destination window.
2076 [clinic start generated code]*/
2077 
2078 static PyObject *
_curses_window_overlay_impl(PyCursesWindowObject * self,PyCursesWindowObject * destwin,int group_right_1,int sminrow,int smincol,int dminrow,int dmincol,int dmaxrow,int dmaxcol)2079 _curses_window_overlay_impl(PyCursesWindowObject *self,
2080                             PyCursesWindowObject *destwin, int group_right_1,
2081                             int sminrow, int smincol, int dminrow,
2082                             int dmincol, int dmaxrow, int dmaxcol)
2083 /*[clinic end generated code: output=82bb2c4cb443ca58 input=7edd23ad22cc1984]*/
2084 {
2085     int rtn;
2086 
2087     if (group_right_1) {
2088         rtn = copywin(self->win, destwin->win, sminrow, smincol,
2089                       dminrow, dmincol, dmaxrow, dmaxcol, TRUE);
2090         return PyCursesCheckERR(rtn, "copywin");
2091     }
2092     else {
2093         rtn = overlay(self->win, destwin->win);
2094         return PyCursesCheckERR(rtn, "overlay");
2095     }
2096 }
2097 
2098 /*[clinic input]
2099 _curses.window.overwrite
2100 
2101     destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type")
2102 
2103     [
2104     sminrow: int
2105     smincol: int
2106     dminrow: int
2107     dmincol: int
2108     dmaxrow: int
2109     dmaxcol: int
2110     ]
2111     /
2112 
2113 Overwrite the window on top of destwin.
2114 
2115 The windows need not be the same size, in which case only the overlapping
2116 region is copied.  This copy is destructive, which means that the current
2117 background character overwrites the old contents of destwin.
2118 
2119 To get fine-grained control over the copied region, the second form of
2120 overwrite() can be used. sminrow and smincol are the upper-left coordinates
2121 of the source window, the other variables mark a rectangle in the destination
2122 window.
2123 [clinic start generated code]*/
2124 
2125 static PyObject *
_curses_window_overwrite_impl(PyCursesWindowObject * self,PyCursesWindowObject * destwin,int group_right_1,int sminrow,int smincol,int dminrow,int dmincol,int dmaxrow,int dmaxcol)2126 _curses_window_overwrite_impl(PyCursesWindowObject *self,
2127                               PyCursesWindowObject *destwin,
2128                               int group_right_1, int sminrow, int smincol,
2129                               int dminrow, int dmincol, int dmaxrow,
2130                               int dmaxcol)
2131 /*[clinic end generated code: output=12ae007d1681be28 input=ea5de1b35cd948e0]*/
2132 {
2133     int rtn;
2134 
2135     if (group_right_1) {
2136         rtn = copywin(self->win, destwin->win, sminrow, smincol,
2137                       dminrow, dmincol, dmaxrow, dmaxcol, FALSE);
2138         return PyCursesCheckERR(rtn, "copywin");
2139     }
2140     else {
2141         rtn = overwrite(self->win, destwin->win);
2142         return PyCursesCheckERR(rtn, "overwrite");
2143     }
2144 }
2145 
2146 /*[clinic input]
2147 _curses.window.putwin
2148 
2149     file: object
2150     /
2151 
2152 Write all data associated with the window into the provided file object.
2153 
2154 This information can be later retrieved using the getwin() function.
2155 [clinic start generated code]*/
2156 
2157 static PyObject *
_curses_window_putwin(PyCursesWindowObject * self,PyObject * file)2158 _curses_window_putwin(PyCursesWindowObject *self, PyObject *file)
2159 /*[clinic end generated code: output=3a25e2a5e7a040ac input=0608648e09c8ea0a]*/
2160 {
2161     /* We have to simulate this by writing to a temporary FILE*,
2162        then reading back, then writing to the argument file. */
2163     FILE *fp;
2164     PyObject *res = NULL;
2165 
2166     fp = tmpfile();
2167     if (fp == NULL)
2168         return PyErr_SetFromErrno(PyExc_OSError);
2169     if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0)
2170         goto exit;
2171     res = PyCursesCheckERR(putwin(self->win, fp), "putwin");
2172     if (res == NULL)
2173         goto exit;
2174     fseek(fp, 0, 0);
2175     while (1) {
2176         char buf[BUFSIZ];
2177         Py_ssize_t n = fread(buf, 1, BUFSIZ, fp);
2178         _Py_IDENTIFIER(write);
2179 
2180         if (n <= 0)
2181             break;
2182         Py_DECREF(res);
2183         res = _PyObject_CallMethodId(file, &PyId_write, "y#", buf, n);
2184         if (res == NULL)
2185             break;
2186     }
2187 
2188 exit:
2189     fclose(fp);
2190     return res;
2191 }
2192 
2193 /*[clinic input]
2194 _curses.window.redrawln
2195 
2196     beg: int
2197         Starting line number.
2198     num: int
2199         The number of lines.
2200     /
2201 
2202 Mark the specified lines corrupted.
2203 
2204 They should be completely redrawn on the next refresh() call.
2205 [clinic start generated code]*/
2206 
2207 static PyObject *
_curses_window_redrawln_impl(PyCursesWindowObject * self,int beg,int num)2208 _curses_window_redrawln_impl(PyCursesWindowObject *self, int beg, int num)
2209 /*[clinic end generated code: output=ea216e334f9ce1b4 input=152155e258a77a7a]*/
2210 {
2211     return PyCursesCheckERR(wredrawln(self->win,beg,num), "redrawln");
2212 }
2213 
2214 /*[clinic input]
2215 _curses.window.refresh
2216 
2217     [
2218     pminrow: int
2219     pmincol: int
2220     sminrow: int
2221     smincol: int
2222     smaxrow: int
2223     smaxcol: int
2224     ]
2225     /
2226 
2227 Update the display immediately.
2228 
2229 Synchronize actual screen with previous drawing/deleting methods.
2230 The 6 optional arguments can only be specified when the window is a pad
2231 created with newpad().  The additional parameters are needed to indicate
2232 what part of the pad and screen are involved.  pminrow and pmincol specify
2233 the upper left-hand corner of the rectangle to be displayed in the pad.
2234 sminrow, smincol, smaxrow, and smaxcol specify the edges of the rectangle to
2235 be displayed on the screen.  The lower right-hand corner of the rectangle to
2236 be displayed in the pad is calculated from the screen coordinates, since the
2237 rectangles must be the same size.  Both rectangles must be entirely contained
2238 within their respective structures.  Negative values of pminrow, pmincol,
2239 sminrow, or smincol are treated as if they were zero.
2240 [clinic start generated code]*/
2241 
2242 static PyObject *
_curses_window_refresh_impl(PyCursesWindowObject * self,int group_right_1,int pminrow,int pmincol,int sminrow,int smincol,int smaxrow,int smaxcol)2243 _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1,
2244                             int pminrow, int pmincol, int sminrow,
2245                             int smincol, int smaxrow, int smaxcol)
2246 /*[clinic end generated code: output=42199543115e6e63 input=95e01cb5ffc635d0]*/
2247 {
2248     int rtn;
2249 
2250 #ifdef py_is_pad
2251     if (py_is_pad(self->win)) {
2252         if (!group_right_1) {
2253             PyErr_SetString(PyCursesError,
2254                             "refresh() for a pad requires 6 arguments");
2255             return NULL;
2256         }
2257         Py_BEGIN_ALLOW_THREADS
2258         rtn = prefresh(self->win, pminrow, pmincol,
2259                        sminrow, smincol, smaxrow, smaxcol);
2260         Py_END_ALLOW_THREADS
2261         return PyCursesCheckERR(rtn, "prefresh");
2262     }
2263 #endif
2264     if (group_right_1) {
2265         PyErr_SetString(PyExc_TypeError,
2266                         "refresh() takes no arguments (6 given)");
2267         return NULL;
2268     }
2269     Py_BEGIN_ALLOW_THREADS
2270     rtn = wrefresh(self->win);
2271     Py_END_ALLOW_THREADS
2272     return PyCursesCheckERR(rtn, "prefresh");
2273 }
2274 
2275 /*[clinic input]
2276 _curses.window.setscrreg
2277 
2278     top: int
2279         First line number.
2280     bottom: int
2281         Last line number.
2282     /
2283 
2284 Define a software scrolling region.
2285 
2286 All scrolling actions will take place in this region.
2287 [clinic start generated code]*/
2288 
2289 static PyObject *
_curses_window_setscrreg_impl(PyCursesWindowObject * self,int top,int bottom)2290 _curses_window_setscrreg_impl(PyCursesWindowObject *self, int top,
2291                               int bottom)
2292 /*[clinic end generated code: output=486ab5db218d2b1a input=1b517b986838bf0e]*/
2293 {
2294     return PyCursesCheckERR(wsetscrreg(self->win, top, bottom), "wsetscrreg");
2295 }
2296 
2297 /*[clinic input]
2298 _curses.window.subwin
2299 
2300     [
2301     nlines: int = 0
2302         Height.
2303     ncols: int = 0
2304         Width.
2305     ]
2306     begin_y: int
2307         Top side y-coordinate.
2308     begin_x: int
2309         Left side x-coordinate.
2310     /
2311 
2312 Create a sub-window (screen-relative coordinates).
2313 
2314 By default, the sub-window will extend from the specified position to the
2315 lower right corner of the window.
2316 [clinic start generated code]*/
2317 
2318 static PyObject *
_curses_window_subwin_impl(PyCursesWindowObject * self,int group_left_1,int nlines,int ncols,int begin_y,int begin_x)2319 _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1,
2320                            int nlines, int ncols, int begin_y, int begin_x)
2321 /*[clinic end generated code: output=93e898afc348f59a input=2129fa47fd57721c]*/
2322 {
2323     WINDOW *win;
2324 
2325     /* printf("Subwin: %i %i %i %i   \n", nlines, ncols, begin_y, begin_x); */
2326 #ifdef py_is_pad
2327     if (py_is_pad(self->win)) {
2328         win = subpad(self->win, nlines, ncols, begin_y, begin_x);
2329     }
2330     else
2331 #endif
2332         win = subwin(self->win, nlines, ncols, begin_y, begin_x);
2333 
2334     if (win == NULL) {
2335         PyErr_SetString(PyCursesError, catchall_NULL);
2336         return NULL;
2337     }
2338 
2339     return (PyObject *)PyCursesWindow_New(win, self->encoding);
2340 }
2341 
2342 /*[clinic input]
2343 _curses.window.scroll
2344 
2345     [
2346     lines: int = 1
2347         Number of lines to scroll.
2348     ]
2349     /
2350 
2351 Scroll the screen or scrolling region.
2352 
2353 Scroll upward if the argument is positive and downward if it is negative.
2354 [clinic start generated code]*/
2355 
2356 static PyObject *
_curses_window_scroll_impl(PyCursesWindowObject * self,int group_right_1,int lines)2357 _curses_window_scroll_impl(PyCursesWindowObject *self, int group_right_1,
2358                            int lines)
2359 /*[clinic end generated code: output=4541a8a11852d360 input=c969ca0cfabbdbec]*/
2360 {
2361     if (!group_right_1) {
2362         return PyCursesCheckERR(scroll(self->win), "scroll");
2363     }
2364     else {
2365         return PyCursesCheckERR(wscrl(self->win, lines), "scroll");
2366     }
2367 }
2368 
2369 /*[clinic input]
2370 _curses.window.touchline
2371 
2372     start: int
2373     count: int
2374     [
2375     changed: bool(accept={int}) = True
2376     ]
2377     /
2378 
2379 Pretend count lines have been changed, starting with line start.
2380 
2381 If changed is supplied, it specifies whether the affected lines are marked
2382 as having been changed (changed=True) or unchanged (changed=False).
2383 [clinic start generated code]*/
2384 
2385 static PyObject *
_curses_window_touchline_impl(PyCursesWindowObject * self,int start,int count,int group_right_1,int changed)2386 _curses_window_touchline_impl(PyCursesWindowObject *self, int start,
2387                               int count, int group_right_1, int changed)
2388 /*[clinic end generated code: output=65d05b3f7438c61d input=918ad1cbdadf93ea]*/
2389 {
2390     if (!group_right_1) {
2391         return PyCursesCheckERR(touchline(self->win, start, count), "touchline");
2392     }
2393     else {
2394         return PyCursesCheckERR(wtouchln(self->win, start, count, changed), "touchline");
2395     }
2396 }
2397 
2398 /*[clinic input]
2399 _curses.window.vline
2400 
2401     [
2402     y: int
2403         Starting Y-coordinate.
2404     x: int
2405         Starting X-coordinate.
2406     ]
2407 
2408     ch: object
2409         Character to draw.
2410     n: int
2411         Line length.
2412 
2413     [
2414     attr: long(c_default="A_NORMAL") = _curses.A_NORMAL
2415         Attributes for the character.
2416     ]
2417     /
2418 
2419 Display a vertical line.
2420 [clinic start generated code]*/
2421 
2422 static PyObject *
_curses_window_vline_impl(PyCursesWindowObject * self,int group_left_1,int y,int x,PyObject * ch,int n,int group_right_1,long attr)2423 _curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1,
2424                           int y, int x, PyObject *ch, int n,
2425                           int group_right_1, long attr)
2426 /*[clinic end generated code: output=287ad1cc8982217f input=a6f2dc86a4648b32]*/
2427 {
2428     chtype ch_;
2429 
2430     if (!PyCurses_ConvertToChtype(self, ch, &ch_))
2431         return NULL;
2432     if (group_left_1) {
2433         if (wmove(self->win, y, x) == ERR)
2434             return PyCursesCheckERR(ERR, "wmove");
2435     }
2436     return PyCursesCheckERR(wvline(self->win, ch_ | (attr_t)attr, n), "vline");
2437 }
2438 
2439 static PyObject *
PyCursesWindow_get_encoding(PyCursesWindowObject * self,void * closure)2440 PyCursesWindow_get_encoding(PyCursesWindowObject *self, void *closure)
2441 {
2442     return PyUnicode_FromString(self->encoding);
2443 }
2444 
2445 static int
PyCursesWindow_set_encoding(PyCursesWindowObject * self,PyObject * value,void * Py_UNUSED (ignored))2446 PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value, void *Py_UNUSED(ignored))
2447 {
2448     PyObject *ascii;
2449     char *encoding;
2450 
2451     /* It is illegal to del win.encoding */
2452     if (value == NULL) {
2453         PyErr_SetString(PyExc_TypeError,
2454                         "encoding may not be deleted");
2455         return -1;
2456     }
2457 
2458     if (!PyUnicode_Check(value)) {
2459         PyErr_SetString(PyExc_TypeError,
2460                         "setting encoding to a non-string");
2461         return -1;
2462     }
2463     ascii = PyUnicode_AsASCIIString(value);
2464     if (ascii == NULL)
2465         return -1;
2466     encoding = _PyMem_Strdup(PyBytes_AS_STRING(ascii));
2467     Py_DECREF(ascii);
2468     if (encoding == NULL) {
2469         PyErr_NoMemory();
2470         return -1;
2471     }
2472     PyMem_Free(self->encoding);
2473     self->encoding = encoding;
2474     return 0;
2475 }
2476 
2477 #include "clinic/_cursesmodule.c.h"
2478 
2479 static PyMethodDef PyCursesWindow_Methods[] = {
2480     _CURSES_WINDOW_ADDCH_METHODDEF
2481     _CURSES_WINDOW_ADDNSTR_METHODDEF
2482     _CURSES_WINDOW_ADDSTR_METHODDEF
2483     _CURSES_WINDOW_ATTROFF_METHODDEF
2484     _CURSES_WINDOW_ATTRON_METHODDEF
2485     _CURSES_WINDOW_ATTRSET_METHODDEF
2486     _CURSES_WINDOW_BKGD_METHODDEF
2487 #ifdef HAVE_CURSES_WCHGAT
2488     {"chgat",           (PyCFunction)PyCursesWindow_ChgAt, METH_VARARGS},
2489 #endif
2490     _CURSES_WINDOW_BKGDSET_METHODDEF
2491     _CURSES_WINDOW_BORDER_METHODDEF
2492     _CURSES_WINDOW_BOX_METHODDEF
2493     {"clear",           (PyCFunction)PyCursesWindow_wclear, METH_NOARGS},
2494     {"clearok",         (PyCFunction)PyCursesWindow_clearok, METH_VARARGS},
2495     {"clrtobot",        (PyCFunction)PyCursesWindow_wclrtobot, METH_NOARGS},
2496     {"clrtoeol",        (PyCFunction)PyCursesWindow_wclrtoeol, METH_NOARGS},
2497     {"cursyncup",       (PyCFunction)PyCursesWindow_wcursyncup, METH_NOARGS},
2498     _CURSES_WINDOW_DELCH_METHODDEF
2499     {"deleteln",        (PyCFunction)PyCursesWindow_wdeleteln, METH_NOARGS},
2500     _CURSES_WINDOW_DERWIN_METHODDEF
2501     _CURSES_WINDOW_ECHOCHAR_METHODDEF
2502     _CURSES_WINDOW_ENCLOSE_METHODDEF
2503     {"erase",           (PyCFunction)PyCursesWindow_werase, METH_NOARGS},
2504     {"getbegyx",        (PyCFunction)PyCursesWindow_getbegyx, METH_NOARGS},
2505     _CURSES_WINDOW_GETBKGD_METHODDEF
2506     _CURSES_WINDOW_GETCH_METHODDEF
2507     _CURSES_WINDOW_GETKEY_METHODDEF
2508     _CURSES_WINDOW_GET_WCH_METHODDEF
2509     {"getmaxyx",        (PyCFunction)PyCursesWindow_getmaxyx, METH_NOARGS},
2510     {"getparyx",        (PyCFunction)PyCursesWindow_getparyx, METH_NOARGS},
2511     {"getstr",          (PyCFunction)PyCursesWindow_GetStr, METH_VARARGS},
2512     {"getyx",           (PyCFunction)PyCursesWindow_getyx, METH_NOARGS},
2513     _CURSES_WINDOW_HLINE_METHODDEF
2514     {"idcok",           (PyCFunction)PyCursesWindow_idcok, METH_VARARGS},
2515     {"idlok",           (PyCFunction)PyCursesWindow_idlok, METH_VARARGS},
2516 #ifdef HAVE_CURSES_IMMEDOK
2517     {"immedok",         (PyCFunction)PyCursesWindow_immedok, METH_VARARGS},
2518 #endif
2519     _CURSES_WINDOW_INCH_METHODDEF
2520     _CURSES_WINDOW_INSCH_METHODDEF
2521     {"insdelln",        (PyCFunction)PyCursesWindow_winsdelln, METH_VARARGS},
2522     {"insertln",        (PyCFunction)PyCursesWindow_winsertln, METH_NOARGS},
2523     _CURSES_WINDOW_INSNSTR_METHODDEF
2524     _CURSES_WINDOW_INSSTR_METHODDEF
2525     {"instr",           (PyCFunction)PyCursesWindow_InStr, METH_VARARGS},
2526     _CURSES_WINDOW_IS_LINETOUCHED_METHODDEF
2527     {"is_wintouched",   (PyCFunction)PyCursesWindow_is_wintouched, METH_NOARGS},
2528     {"keypad",          (PyCFunction)PyCursesWindow_keypad, METH_VARARGS},
2529     {"leaveok",         (PyCFunction)PyCursesWindow_leaveok, METH_VARARGS},
2530     {"move",            (PyCFunction)PyCursesWindow_wmove, METH_VARARGS},
2531     {"mvderwin",        (PyCFunction)PyCursesWindow_mvderwin, METH_VARARGS},
2532     {"mvwin",           (PyCFunction)PyCursesWindow_mvwin, METH_VARARGS},
2533     {"nodelay",         (PyCFunction)PyCursesWindow_nodelay, METH_VARARGS},
2534     {"notimeout",       (PyCFunction)PyCursesWindow_notimeout, METH_VARARGS},
2535     _CURSES_WINDOW_NOUTREFRESH_METHODDEF
2536     _CURSES_WINDOW_OVERLAY_METHODDEF
2537     _CURSES_WINDOW_OVERWRITE_METHODDEF
2538     _CURSES_WINDOW_PUTWIN_METHODDEF
2539     _CURSES_WINDOW_REDRAWLN_METHODDEF
2540     {"redrawwin",       (PyCFunction)PyCursesWindow_redrawwin, METH_NOARGS},
2541     _CURSES_WINDOW_REFRESH_METHODDEF
2542 #ifndef STRICT_SYSV_CURSES
2543     {"resize",          (PyCFunction)PyCursesWindow_wresize, METH_VARARGS},
2544 #endif
2545     _CURSES_WINDOW_SCROLL_METHODDEF
2546     {"scrollok",        (PyCFunction)PyCursesWindow_scrollok, METH_VARARGS},
2547     _CURSES_WINDOW_SETSCRREG_METHODDEF
2548     {"standend",        (PyCFunction)PyCursesWindow_wstandend, METH_NOARGS},
2549     {"standout",        (PyCFunction)PyCursesWindow_wstandout, METH_NOARGS},
2550     {"subpad", (PyCFunction)_curses_window_subwin, METH_VARARGS, _curses_window_subwin__doc__},
2551     _CURSES_WINDOW_SUBWIN_METHODDEF
2552     {"syncdown",        (PyCFunction)PyCursesWindow_wsyncdown, METH_NOARGS},
2553 #ifdef HAVE_CURSES_SYNCOK
2554     {"syncok",          (PyCFunction)PyCursesWindow_syncok, METH_VARARGS},
2555 #endif
2556     {"syncup",          (PyCFunction)PyCursesWindow_wsyncup, METH_NOARGS},
2557     {"timeout",         (PyCFunction)PyCursesWindow_wtimeout, METH_VARARGS},
2558     _CURSES_WINDOW_TOUCHLINE_METHODDEF
2559     {"touchwin",        (PyCFunction)PyCursesWindow_touchwin, METH_NOARGS},
2560     {"untouchwin",      (PyCFunction)PyCursesWindow_untouchwin, METH_NOARGS},
2561     _CURSES_WINDOW_VLINE_METHODDEF
2562     {NULL,                  NULL}   /* sentinel */
2563 };
2564 
2565 static PyGetSetDef PyCursesWindow_getsets[] = {
2566     {"encoding",
2567      (getter)PyCursesWindow_get_encoding,
2568      (setter)PyCursesWindow_set_encoding,
2569      "the typecode character used to create the array"},
2570     {NULL, NULL, NULL, NULL }  /* sentinel */
2571 };
2572 
2573 /* -------------------------------------------------------*/
2574 
2575 PyTypeObject PyCursesWindow_Type = {
2576     PyVarObject_HEAD_INIT(NULL, 0)
2577     "_curses.window",           /*tp_name*/
2578     sizeof(PyCursesWindowObject),       /*tp_basicsize*/
2579     0,                          /*tp_itemsize*/
2580     /* methods */
2581     (destructor)PyCursesWindow_Dealloc, /*tp_dealloc*/
2582     0,                          /*tp_vectorcall_offset*/
2583     (getattrfunc)0,             /*tp_getattr*/
2584     (setattrfunc)0,             /*tp_setattr*/
2585     0,                          /*tp_as_async*/
2586     0,                          /*tp_repr*/
2587     0,                          /*tp_as_number*/
2588     0,                          /*tp_as_sequence*/
2589     0,                          /*tp_as_mapping*/
2590     0,                          /*tp_hash*/
2591     0,                          /*tp_call*/
2592     0,                          /*tp_str*/
2593     0,                          /*tp_getattro*/
2594     0,                          /*tp_setattro*/
2595     0,                          /*tp_as_buffer*/
2596     Py_TPFLAGS_DEFAULT,         /*tp_flags*/
2597     0,                          /*tp_doc*/
2598     0,                          /*tp_traverse*/
2599     0,                          /*tp_clear*/
2600     0,                          /*tp_richcompare*/
2601     0,                          /*tp_weaklistoffset*/
2602     0,                          /*tp_iter*/
2603     0,                          /*tp_iternext*/
2604     PyCursesWindow_Methods,     /*tp_methods*/
2605     0,                          /* tp_members */
2606     PyCursesWindow_getsets,     /* tp_getset */
2607 };
2608 
2609 /* Function Prototype Macros - They are ugly but very, very useful. ;-)
2610 
2611    X - function name
2612    TYPE - parameter Type
2613    ERGSTR - format string for construction of the return value
2614    PARSESTR - format string for argument parsing
2615    */
2616 
2617 #define NoArgNoReturnFunctionBody(X) \
2618 { \
2619   PyCursesInitialised \
2620   return PyCursesCheckERR(X(), # X); }
2621 
2622 #define NoArgOrFlagNoReturnFunctionBody(X, flag) \
2623 { \
2624     PyCursesInitialised \
2625     if (flag) \
2626         return PyCursesCheckERR(X(), # X); \
2627     else \
2628         return PyCursesCheckERR(no ## X(), # X); \
2629 }
2630 
2631 #define NoArgReturnIntFunctionBody(X) \
2632 { \
2633  PyCursesInitialised \
2634  return PyLong_FromLong((long) X()); }
2635 
2636 
2637 #define NoArgReturnStringFunctionBody(X) \
2638 { \
2639   PyCursesInitialised \
2640   return PyBytes_FromString(X()); }
2641 
2642 #define NoArgTrueFalseFunctionBody(X) \
2643 { \
2644   PyCursesInitialised \
2645   return PyBool_FromLong(X()); }
2646 
2647 #define NoArgNoReturnVoidFunctionBody(X) \
2648 { \
2649   PyCursesInitialised \
2650   X(); \
2651   Py_RETURN_NONE; }
2652 
2653 /*********************************************************************
2654  Global Functions
2655 **********************************************************************/
2656 
2657 #ifdef HAVE_CURSES_FILTER
2658 /*[clinic input]
2659 _curses.filter
2660 
2661 [clinic start generated code]*/
2662 
2663 static PyObject *
_curses_filter_impl(PyObject * module)2664 _curses_filter_impl(PyObject *module)
2665 /*[clinic end generated code: output=fb5b8a3642eb70b5 input=668c75a6992d3624]*/
2666 {
2667     /* not checking for PyCursesInitialised here since filter() must
2668        be called before initscr() */
2669     filter();
2670     Py_RETURN_NONE;
2671 }
2672 #endif
2673 
2674 /*[clinic input]
2675 _curses.baudrate
2676 
2677 Return the output speed of the terminal in bits per second.
2678 [clinic start generated code]*/
2679 
2680 static PyObject *
_curses_baudrate_impl(PyObject * module)2681 _curses_baudrate_impl(PyObject *module)
2682 /*[clinic end generated code: output=3c63c6c401d7d9c0 input=921f022ed04a0fd9]*/
2683 NoArgReturnIntFunctionBody(baudrate)
2684 
2685 /*[clinic input]
2686 _curses.beep
2687 
2688 Emit a short attention sound.
2689 [clinic start generated code]*/
2690 
2691 static PyObject *
2692 _curses_beep_impl(PyObject *module)
2693 /*[clinic end generated code: output=425274962abe49a2 input=a35698ca7d0162bc]*/
2694 NoArgNoReturnFunctionBody(beep)
2695 
2696 /*[clinic input]
2697 _curses.can_change_color
2698 
2699 Return True if the programmer can change the colors displayed by the terminal.
2700 [clinic start generated code]*/
2701 
2702 static PyObject *
2703 _curses_can_change_color_impl(PyObject *module)
2704 /*[clinic end generated code: output=359df8c3c77d8bf1 input=d7718884de0092f2]*/
2705 NoArgTrueFalseFunctionBody(can_change_color)
2706 
2707 /*[clinic input]
2708 _curses.cbreak
2709 
2710     flag: bool(accept={int}) = True
2711         If false, the effect is the same as calling nocbreak().
2712     /
2713 
2714 Enter cbreak mode.
2715 
2716 In cbreak mode (sometimes called "rare" mode) normal tty line buffering is
2717 turned off and characters are available to be read one by one.  However,
2718 unlike raw mode, special characters (interrupt, quit, suspend, and flow
2719 control) retain their effects on the tty driver and calling program.
2720 Calling first raw() then cbreak() leaves the terminal in cbreak mode.
2721 [clinic start generated code]*/
2722 
2723 static PyObject *
2724 _curses_cbreak_impl(PyObject *module, int flag)
2725 /*[clinic end generated code: output=9f9dee9664769751 input=150be619eb1f1458]*/
2726 NoArgOrFlagNoReturnFunctionBody(cbreak, flag)
2727 
2728 /*[clinic input]
2729 _curses.color_content
2730 
2731     color_number: color
2732         The number of the color (0 - (COLORS-1)).
2733     /
2734 
2735 Return the red, green, and blue (RGB) components of the specified color.
2736 
2737 A 3-tuple is returned, containing the R, G, B values for the given color,
2738 which will be between 0 (no component) and 1000 (maximum amount of component).
2739 [clinic start generated code]*/
2740 
2741 static PyObject *
2742 _curses_color_content_impl(PyObject *module, int color_number)
2743 /*[clinic end generated code: output=17b466df7054e0de input=03b5ed0472662aea]*/
2744 {
2745     _CURSES_COLOR_VAL_TYPE r,g,b;
2746 
2747     PyCursesInitialised;
2748     PyCursesInitialisedColor;
2749 
2750     if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) {
2751         PyErr_Format(PyCursesError, "%s() returned ERR",
2752                         Py_STRINGIFY(_COLOR_CONTENT_FUNC));
2753         return NULL;
2754     }
2755 
2756     return Py_BuildValue("(iii)", r, g, b);
2757 }
2758 
2759 /*[clinic input]
2760 _curses.color_pair
2761 
2762     pair_number: int
2763         The number of the color pair.
2764     /
2765 
2766 Return the attribute value for displaying text in the specified color.
2767 
2768 This attribute value can be combined with A_STANDOUT, A_REVERSE, and the
2769 other A_* attributes.  pair_number() is the counterpart to this function.
2770 [clinic start generated code]*/
2771 
2772 static PyObject *
_curses_color_pair_impl(PyObject * module,int pair_number)2773 _curses_color_pair_impl(PyObject *module, int pair_number)
2774 /*[clinic end generated code: output=60718abb10ce9feb input=6034e9146f343802]*/
2775 {
2776     PyCursesInitialised;
2777     PyCursesInitialisedColor;
2778 
2779     return  PyLong_FromLong(COLOR_PAIR(pair_number));
2780 }
2781 
2782 /*[clinic input]
2783 _curses.curs_set
2784 
2785     visibility: int
2786         0 for invisible, 1 for normal visible, or 2 for very visible.
2787     /
2788 
2789 Set the cursor state.
2790 
2791 If the terminal supports the visibility requested, the previous cursor
2792 state is returned; otherwise, an exception is raised.  On many terminals,
2793 the "visible" mode is an underline cursor and the "very visible" mode is
2794 a block cursor.
2795 [clinic start generated code]*/
2796 
2797 static PyObject *
_curses_curs_set_impl(PyObject * module,int visibility)2798 _curses_curs_set_impl(PyObject *module, int visibility)
2799 /*[clinic end generated code: output=ee8e62483b1d6cd4 input=81a7924a65d29504]*/
2800 {
2801     int erg;
2802 
2803     PyCursesInitialised;
2804 
2805     erg = curs_set(visibility);
2806     if (erg == ERR) return PyCursesCheckERR(erg, "curs_set");
2807 
2808     return PyLong_FromLong((long) erg);
2809 }
2810 
2811 /*[clinic input]
2812 _curses.def_prog_mode
2813 
2814 Save the current terminal mode as the "program" mode.
2815 
2816 The "program" mode is the mode when the running program is using curses.
2817 
2818 Subsequent calls to reset_prog_mode() will restore this mode.
2819 [clinic start generated code]*/
2820 
2821 static PyObject *
_curses_def_prog_mode_impl(PyObject * module)2822 _curses_def_prog_mode_impl(PyObject *module)
2823 /*[clinic end generated code: output=05d5a351fff874aa input=768b9cace620dda5]*/
2824 NoArgNoReturnFunctionBody(def_prog_mode)
2825 
2826 /*[clinic input]
2827 _curses.def_shell_mode
2828 
2829 Save the current terminal mode as the "shell" mode.
2830 
2831 The "shell" mode is the mode when the running program is not using curses.
2832 
2833 Subsequent calls to reset_shell_mode() will restore this mode.
2834 [clinic start generated code]*/
2835 
2836 static PyObject *
2837 _curses_def_shell_mode_impl(PyObject *module)
2838 /*[clinic end generated code: output=d6e42f5c768f860f input=5ead21f6f0baa894]*/
2839 NoArgNoReturnFunctionBody(def_shell_mode)
2840 
2841 /*[clinic input]
2842 _curses.delay_output
2843 
2844     ms: int
2845         Duration in milliseconds.
2846     /
2847 
2848 Insert a pause in output.
2849 [clinic start generated code]*/
2850 
2851 static PyObject *
2852 _curses_delay_output_impl(PyObject *module, int ms)
2853 /*[clinic end generated code: output=b6613a67f17fa4f4 input=5316457f5f59196c]*/
2854 {
2855     PyCursesInitialised;
2856 
2857     return PyCursesCheckERR(delay_output(ms), "delay_output");
2858 }
2859 
2860 /*[clinic input]
2861 _curses.doupdate
2862 
2863 Update the physical screen to match the virtual screen.
2864 [clinic start generated code]*/
2865 
2866 static PyObject *
_curses_doupdate_impl(PyObject * module)2867 _curses_doupdate_impl(PyObject *module)
2868 /*[clinic end generated code: output=f34536975a75680c input=8da80914432a6489]*/
2869 NoArgNoReturnFunctionBody(doupdate)
2870 
2871 /*[clinic input]
2872 _curses.echo
2873 
2874     flag: bool(accept={int}) = True
2875         If false, the effect is the same as calling noecho().
2876     /
2877 
2878 Enter echo mode.
2879 
2880 In echo mode, each character input is echoed to the screen as it is entered.
2881 [clinic start generated code]*/
2882 
2883 static PyObject *
2884 _curses_echo_impl(PyObject *module, int flag)
2885 /*[clinic end generated code: output=03acb2ddfa6c8729 input=2e9e891d637eac5d]*/
2886 NoArgOrFlagNoReturnFunctionBody(echo, flag)
2887 
2888 /*[clinic input]
2889 _curses.endwin
2890 
2891 De-initialize the library, and return terminal to normal status.
2892 [clinic start generated code]*/
2893 
2894 static PyObject *
2895 _curses_endwin_impl(PyObject *module)
2896 /*[clinic end generated code: output=c0150cd96d2f4128 input=e172cfa43062f3fa]*/
2897 NoArgNoReturnFunctionBody(endwin)
2898 
2899 /*[clinic input]
2900 _curses.erasechar
2901 
2902 Return the user's current erase character.
2903 [clinic start generated code]*/
2904 
2905 static PyObject *
2906 _curses_erasechar_impl(PyObject *module)
2907 /*[clinic end generated code: output=3df305dc6b926b3f input=628c136c3c5758d3]*/
2908 {
2909     char ch;
2910 
2911     PyCursesInitialised;
2912 
2913     ch = erasechar();
2914 
2915     return PyBytes_FromStringAndSize(&ch, 1);
2916 }
2917 
2918 /*[clinic input]
2919 _curses.flash
2920 
2921 Flash the screen.
2922 
2923 That is, change it to reverse-video and then change it back in a short interval.
2924 [clinic start generated code]*/
2925 
2926 static PyObject *
_curses_flash_impl(PyObject * module)2927 _curses_flash_impl(PyObject *module)
2928 /*[clinic end generated code: output=488b8a0ebd9ea9b8 input=02fdfb06c8fc3171]*/
2929 NoArgNoReturnFunctionBody(flash)
2930 
2931 /*[clinic input]
2932 _curses.flushinp
2933 
2934 Flush all input buffers.
2935 
2936 This throws away any typeahead that has been typed by the user and has not
2937 yet been processed by the program.
2938 [clinic start generated code]*/
2939 
2940 static PyObject *
2941 _curses_flushinp_impl(PyObject *module)
2942 /*[clinic end generated code: output=7e7a1fc1473960f5 input=59d042e705cef5ec]*/
2943 NoArgNoReturnVoidFunctionBody(flushinp)
2944 
2945 #ifdef getsyx
2946 /*[clinic input]
2947 _curses.getsyx
2948 
2949 Return the current coordinates of the virtual screen cursor.
2950 
2951 Return a (y, x) tuple.  If leaveok is currently true, return (-1, -1).
2952 [clinic start generated code]*/
2953 
2954 static PyObject *
2955 _curses_getsyx_impl(PyObject *module)
2956 /*[clinic end generated code: output=c8e6c3f42349a038 input=9e1f862f3b4f7cba]*/
2957 {
2958     int x = 0;
2959     int y = 0;
2960 
2961     PyCursesInitialised;
2962 
2963     getsyx(y, x);
2964 
2965     return Py_BuildValue("(ii)", y, x);
2966 }
2967 #endif
2968 
2969 #ifdef NCURSES_MOUSE_VERSION
2970 /*[clinic input]
2971 _curses.getmouse
2972 
2973 Retrieve the queued mouse event.
2974 
2975 After getch() returns KEY_MOUSE to signal a mouse event, this function
2976 returns a 5-tuple (id, x, y, z, bstate).
2977 [clinic start generated code]*/
2978 
2979 static PyObject *
_curses_getmouse_impl(PyObject * module)2980 _curses_getmouse_impl(PyObject *module)
2981 /*[clinic end generated code: output=ccf4242546b9cfa8 input=5b756ee6f5b481b1]*/
2982 {
2983     int rtn;
2984     MEVENT event;
2985 
2986     PyCursesInitialised;
2987 
2988     rtn = getmouse( &event );
2989     if (rtn == ERR) {
2990         PyErr_SetString(PyCursesError, "getmouse() returned ERR");
2991         return NULL;
2992     }
2993     return Py_BuildValue("(hiiik)",
2994                          (short)event.id,
2995                          (int)event.x, (int)event.y, (int)event.z,
2996                          (unsigned long) event.bstate);
2997 }
2998 
2999 /*[clinic input]
3000 _curses.ungetmouse
3001 
3002     id: short
3003     x: int
3004     y: int
3005     z: int
3006     bstate: unsigned_long(bitwise=True)
3007     /
3008 
3009 Push a KEY_MOUSE event onto the input queue.
3010 
3011 The following getmouse() will return the given state data.
3012 [clinic start generated code]*/
3013 
3014 static PyObject *
_curses_ungetmouse_impl(PyObject * module,short id,int x,int y,int z,unsigned long bstate)3015 _curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z,
3016                         unsigned long bstate)
3017 /*[clinic end generated code: output=3430c9b0fc5c4341 input=fd650b2ca5a01e8f]*/
3018 {
3019     MEVENT event;
3020 
3021     PyCursesInitialised;
3022 
3023     event.id = id;
3024     event.x = x;
3025     event.y = y;
3026     event.z = z;
3027     event.bstate = bstate;
3028     return PyCursesCheckERR(ungetmouse(&event), "ungetmouse");
3029 }
3030 #endif
3031 
3032 /*[clinic input]
3033 _curses.getwin
3034 
3035     file: object
3036     /
3037 
3038 Read window related data stored in the file by an earlier putwin() call.
3039 
3040 The routine then creates and initializes a new window using that data,
3041 returning the new window object.
3042 [clinic start generated code]*/
3043 
3044 static PyObject *
_curses_getwin(PyObject * module,PyObject * file)3045 _curses_getwin(PyObject *module, PyObject *file)
3046 /*[clinic end generated code: output=a79e0df3379af756 input=f713d2bba0e4c929]*/
3047 {
3048     FILE *fp;
3049     PyObject *data;
3050     size_t datalen;
3051     WINDOW *win;
3052     _Py_IDENTIFIER(read);
3053     PyObject *res = NULL;
3054 
3055     PyCursesInitialised;
3056 
3057     fp = tmpfile();
3058     if (fp == NULL)
3059         return PyErr_SetFromErrno(PyExc_OSError);
3060 
3061     if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0)
3062         goto error;
3063 
3064     data = _PyObject_CallMethodIdNoArgs(file, &PyId_read);
3065     if (data == NULL)
3066         goto error;
3067     if (!PyBytes_Check(data)) {
3068         PyErr_Format(PyExc_TypeError,
3069                      "f.read() returned %.100s instead of bytes",
3070                      Py_TYPE(data)->tp_name);
3071         Py_DECREF(data);
3072         goto error;
3073     }
3074     datalen = PyBytes_GET_SIZE(data);
3075     if (fwrite(PyBytes_AS_STRING(data), 1, datalen, fp) != datalen) {
3076         Py_DECREF(data);
3077         PyErr_SetFromErrno(PyExc_OSError);
3078         goto error;
3079     }
3080     Py_DECREF(data);
3081 
3082     fseek(fp, 0, 0);
3083     win = getwin(fp);
3084     if (win == NULL) {
3085         PyErr_SetString(PyCursesError, catchall_NULL);
3086         goto error;
3087     }
3088     res = PyCursesWindow_New(win, NULL);
3089 
3090 error:
3091     fclose(fp);
3092     return res;
3093 }
3094 
3095 /*[clinic input]
3096 _curses.halfdelay
3097 
3098     tenths: byte
3099         Maximal blocking delay in tenths of seconds (1 - 255).
3100     /
3101 
3102 Enter half-delay mode.
3103 
3104 Use nocbreak() to leave half-delay mode.
3105 [clinic start generated code]*/
3106 
3107 static PyObject *
_curses_halfdelay_impl(PyObject * module,unsigned char tenths)3108 _curses_halfdelay_impl(PyObject *module, unsigned char tenths)
3109 /*[clinic end generated code: output=e92cdf0ef33c0663 input=e42dce7259c15100]*/
3110 {
3111     PyCursesInitialised;
3112 
3113     return PyCursesCheckERR(halfdelay(tenths), "halfdelay");
3114 }
3115 
3116 /*[clinic input]
3117 _curses.has_colors
3118 
3119 Return True if the terminal can display colors; otherwise, return False.
3120 [clinic start generated code]*/
3121 
3122 static PyObject *
_curses_has_colors_impl(PyObject * module)3123 _curses_has_colors_impl(PyObject *module)
3124 /*[clinic end generated code: output=db5667483139e3e2 input=b2ec41b739d896c6]*/
3125 NoArgTrueFalseFunctionBody(has_colors)
3126 
3127 /*[clinic input]
3128 _curses.has_ic
3129 
3130 Return True if the terminal has insert- and delete-character capabilities.
3131 [clinic start generated code]*/
3132 
3133 static PyObject *
3134 _curses_has_ic_impl(PyObject *module)
3135 /*[clinic end generated code: output=6be24da9cb1268fe input=9bc2d3a797cc7324]*/
3136 NoArgTrueFalseFunctionBody(has_ic)
3137 
3138 /*[clinic input]
3139 _curses.has_il
3140 
3141 Return True if the terminal has insert- and delete-line capabilities.
3142 [clinic start generated code]*/
3143 
3144 static PyObject *
3145 _curses_has_il_impl(PyObject *module)
3146 /*[clinic end generated code: output=d45bd7788ff9f5f4 input=cd939d5607ee5427]*/
3147 NoArgTrueFalseFunctionBody(has_il)
3148 
3149 #ifdef HAVE_CURSES_HAS_KEY
3150 /*[clinic input]
3151 _curses.has_key
3152 
3153     key: int
3154         Key number.
3155     /
3156 
3157 Return True if the current terminal type recognizes a key with that value.
3158 [clinic start generated code]*/
3159 
3160 static PyObject *
3161 _curses_has_key_impl(PyObject *module, int key)
3162 /*[clinic end generated code: output=19ad48319414d0b1 input=78bd44acf1a4997c]*/
3163 {
3164     PyCursesInitialised;
3165 
3166     return PyBool_FromLong(has_key(key));
3167 }
3168 #endif
3169 
3170 /*[clinic input]
3171 _curses.init_color
3172 
3173     color_number: color
3174         The number of the color to be changed (0 - (COLORS-1)).
3175     r: component
3176         Red component (0 - 1000).
3177     g: component
3178         Green component (0 - 1000).
3179     b: component
3180         Blue component (0 - 1000).
3181     /
3182 
3183 Change the definition of a color.
3184 
3185 When init_color() is used, all occurrences of that color on the screen
3186 immediately change to the new definition.  This function is a no-op on
3187 most terminals; it is active only if can_change_color() returns true.
3188 [clinic start generated code]*/
3189 
3190 static PyObject *
_curses_init_color_impl(PyObject * module,int color_number,short r,short g,short b)3191 _curses_init_color_impl(PyObject *module, int color_number, short r, short g,
3192                         short b)
3193 /*[clinic end generated code: output=d7ed71b2d818cdf2 input=ae2b8bea0f152c80]*/
3194 {
3195     PyCursesInitialised;
3196     PyCursesInitialisedColor;
3197 
3198     return PyCursesCheckERR(_CURSES_INIT_COLOR_FUNC(color_number, r, g, b),
3199                             Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC));
3200 }
3201 
3202 /*[clinic input]
3203 _curses.init_pair
3204 
3205     pair_number: pair
3206         The number of the color-pair to be changed (1 - (COLOR_PAIRS-1)).
3207     fg: color_allow_default
3208         Foreground color number (-1 - (COLORS-1)).
3209     bg: color_allow_default
3210         Background color number (-1 - (COLORS-1)).
3211     /
3212 
3213 Change the definition of a color-pair.
3214 
3215 If the color-pair was previously initialized, the screen is refreshed and
3216 all occurrences of that color-pair are changed to the new definition.
3217 [clinic start generated code]*/
3218 
3219 static PyObject *
_curses_init_pair_impl(PyObject * module,int pair_number,int fg,int bg)3220 _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg)
3221 /*[clinic end generated code: output=a0bba03d2bbc3ee6 input=54b421b44c12c389]*/
3222 {
3223     PyCursesInitialised;
3224     PyCursesInitialisedColor;
3225 
3226     if (_CURSES_INIT_PAIR_FUNC(pair_number, fg, bg) == ERR) {
3227         if (pair_number >= COLOR_PAIRS) {
3228             PyErr_Format(PyExc_ValueError,
3229                          "Color pair is greater than COLOR_PAIRS-1 (%d).",
3230                          COLOR_PAIRS - 1);
3231         }
3232         else {
3233             PyErr_Format(PyCursesError, "%s() returned ERR",
3234                          Py_STRINGIFY(_CURSES_INIT_PAIR_FUNC));
3235         }
3236         return NULL;
3237     }
3238 
3239     Py_RETURN_NONE;
3240 }
3241 
3242 static PyObject *ModDict;
3243 
3244 /*[clinic input]
3245 _curses.initscr
3246 
3247 Initialize the library.
3248 
3249 Return a WindowObject which represents the whole screen.
3250 [clinic start generated code]*/
3251 
3252 static PyObject *
_curses_initscr_impl(PyObject * module)3253 _curses_initscr_impl(PyObject *module)
3254 /*[clinic end generated code: output=619fb68443810b7b input=514f4bce1821f6b5]*/
3255 {
3256     WINDOW *win;
3257     PyCursesWindowObject *winobj;
3258 
3259     if (initialised) {
3260         wrefresh(stdscr);
3261         return (PyObject *)PyCursesWindow_New(stdscr, NULL);
3262     }
3263 
3264     win = initscr();
3265 
3266     if (win == NULL) {
3267         PyErr_SetString(PyCursesError, catchall_NULL);
3268         return NULL;
3269     }
3270 
3271     initialised = initialised_setupterm = TRUE;
3272 
3273 /* This was moved from initcurses() because it core dumped on SGI,
3274    where they're not defined until you've called initscr() */
3275 #define SetDictInt(string,ch)                                           \
3276     do {                                                                \
3277         PyObject *o = PyLong_FromLong((long) (ch));                     \
3278         if (o && PyDict_SetItemString(ModDict, string, o) == 0)     {   \
3279             Py_DECREF(o);                                               \
3280         }                                                               \
3281     } while (0)
3282 
3283     /* Here are some graphic symbols you can use */
3284     SetDictInt("ACS_ULCORNER",      (ACS_ULCORNER));
3285     SetDictInt("ACS_LLCORNER",      (ACS_LLCORNER));
3286     SetDictInt("ACS_URCORNER",      (ACS_URCORNER));
3287     SetDictInt("ACS_LRCORNER",      (ACS_LRCORNER));
3288     SetDictInt("ACS_LTEE",          (ACS_LTEE));
3289     SetDictInt("ACS_RTEE",          (ACS_RTEE));
3290     SetDictInt("ACS_BTEE",          (ACS_BTEE));
3291     SetDictInt("ACS_TTEE",          (ACS_TTEE));
3292     SetDictInt("ACS_HLINE",         (ACS_HLINE));
3293     SetDictInt("ACS_VLINE",         (ACS_VLINE));
3294     SetDictInt("ACS_PLUS",          (ACS_PLUS));
3295 #if !defined(__hpux) || defined(HAVE_NCURSES_H)
3296     /* On HP/UX 11, these are of type cchar_t, which is not an
3297        integral type. If this is a problem on more platforms, a
3298        configure test should be added to determine whether ACS_S1
3299        is of integral type. */
3300     SetDictInt("ACS_S1",            (ACS_S1));
3301     SetDictInt("ACS_S9",            (ACS_S9));
3302     SetDictInt("ACS_DIAMOND",       (ACS_DIAMOND));
3303     SetDictInt("ACS_CKBOARD",       (ACS_CKBOARD));
3304     SetDictInt("ACS_DEGREE",        (ACS_DEGREE));
3305     SetDictInt("ACS_PLMINUS",       (ACS_PLMINUS));
3306     SetDictInt("ACS_BULLET",        (ACS_BULLET));
3307     SetDictInt("ACS_LARROW",        (ACS_LARROW));
3308     SetDictInt("ACS_RARROW",        (ACS_RARROW));
3309     SetDictInt("ACS_DARROW",        (ACS_DARROW));
3310     SetDictInt("ACS_UARROW",        (ACS_UARROW));
3311     SetDictInt("ACS_BOARD",         (ACS_BOARD));
3312     SetDictInt("ACS_LANTERN",       (ACS_LANTERN));
3313     SetDictInt("ACS_BLOCK",         (ACS_BLOCK));
3314 #endif
3315     SetDictInt("ACS_BSSB",          (ACS_ULCORNER));
3316     SetDictInt("ACS_SSBB",          (ACS_LLCORNER));
3317     SetDictInt("ACS_BBSS",          (ACS_URCORNER));
3318     SetDictInt("ACS_SBBS",          (ACS_LRCORNER));
3319     SetDictInt("ACS_SBSS",          (ACS_RTEE));
3320     SetDictInt("ACS_SSSB",          (ACS_LTEE));
3321     SetDictInt("ACS_SSBS",          (ACS_BTEE));
3322     SetDictInt("ACS_BSSS",          (ACS_TTEE));
3323     SetDictInt("ACS_BSBS",          (ACS_HLINE));
3324     SetDictInt("ACS_SBSB",          (ACS_VLINE));
3325     SetDictInt("ACS_SSSS",          (ACS_PLUS));
3326 
3327     /* The following are never available with strict SYSV curses */
3328 #ifdef ACS_S3
3329     SetDictInt("ACS_S3",            (ACS_S3));
3330 #endif
3331 #ifdef ACS_S7
3332     SetDictInt("ACS_S7",            (ACS_S7));
3333 #endif
3334 #ifdef ACS_LEQUAL
3335     SetDictInt("ACS_LEQUAL",        (ACS_LEQUAL));
3336 #endif
3337 #ifdef ACS_GEQUAL
3338     SetDictInt("ACS_GEQUAL",        (ACS_GEQUAL));
3339 #endif
3340 #ifdef ACS_PI
3341     SetDictInt("ACS_PI",            (ACS_PI));
3342 #endif
3343 #ifdef ACS_NEQUAL
3344     SetDictInt("ACS_NEQUAL",        (ACS_NEQUAL));
3345 #endif
3346 #ifdef ACS_STERLING
3347     SetDictInt("ACS_STERLING",      (ACS_STERLING));
3348 #endif
3349 
3350     SetDictInt("LINES", LINES);
3351     SetDictInt("COLS", COLS);
3352 
3353     winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL);
3354     screen_encoding = winobj->encoding;
3355     return (PyObject *)winobj;
3356 }
3357 
3358 /*[clinic input]
3359 _curses.setupterm
3360 
3361     term: str(accept={str, NoneType}) = None
3362         Terminal name.
3363         If omitted, the value of the TERM environment variable will be used.
3364     fd: int = -1
3365         File descriptor to which any initialization sequences will be sent.
3366         If not supplied, the file descriptor for sys.stdout will be used.
3367 
3368 Initialize the terminal.
3369 [clinic start generated code]*/
3370 
3371 static PyObject *
_curses_setupterm_impl(PyObject * module,const char * term,int fd)3372 _curses_setupterm_impl(PyObject *module, const char *term, int fd)
3373 /*[clinic end generated code: output=4584e587350f2848 input=4511472766af0c12]*/
3374 {
3375     int err;
3376 
3377     if (fd == -1) {
3378         PyObject* sys_stdout;
3379 
3380         sys_stdout = PySys_GetObject("stdout");
3381 
3382         if (sys_stdout == NULL || sys_stdout == Py_None) {
3383             PyErr_SetString(
3384                 PyCursesError,
3385                 "lost sys.stdout");
3386             return NULL;
3387         }
3388 
3389         fd = PyObject_AsFileDescriptor(sys_stdout);
3390 
3391         if (fd == -1) {
3392             return NULL;
3393         }
3394     }
3395 
3396     if (!initialised_setupterm && setupterm((char *)term, fd, &err) == ERR) {
3397         const char* s = "setupterm: unknown error";
3398 
3399         if (err == 0) {
3400             s = "setupterm: could not find terminal";
3401         } else if (err == -1) {
3402             s = "setupterm: could not find terminfo database";
3403         }
3404 
3405         PyErr_SetString(PyCursesError,s);
3406         return NULL;
3407     }
3408 
3409     initialised_setupterm = TRUE;
3410 
3411     Py_RETURN_NONE;
3412 }
3413 
3414 #if defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102
3415 // https://invisible-island.net/ncurses/NEWS.html#index-t20080119
3416 
3417 /*[clinic input]
3418 _curses.get_escdelay
3419 
3420 Gets the curses ESCDELAY setting.
3421 
3422 Gets the number of milliseconds to wait after reading an escape character,
3423 to distinguish between an individual escape character entered on the
3424 keyboard from escape sequences sent by cursor and function keys.
3425 [clinic start generated code]*/
3426 
3427 static PyObject *
_curses_get_escdelay_impl(PyObject * module)3428 _curses_get_escdelay_impl(PyObject *module)
3429 /*[clinic end generated code: output=222fa1a822555d60 input=be2d5b3dd974d0a4]*/
3430 {
3431     return PyLong_FromLong(ESCDELAY);
3432 }
3433 /*[clinic input]
3434 _curses.set_escdelay
3435     ms: int
3436         length of the delay in milliseconds.
3437     /
3438 
3439 Sets the curses ESCDELAY setting.
3440 
3441 Sets the number of milliseconds to wait after reading an escape character,
3442 to distinguish between an individual escape character entered on the
3443 keyboard from escape sequences sent by cursor and function keys.
3444 [clinic start generated code]*/
3445 
3446 static PyObject *
_curses_set_escdelay_impl(PyObject * module,int ms)3447 _curses_set_escdelay_impl(PyObject *module, int ms)
3448 /*[clinic end generated code: output=43818efbf7980ac4 input=7796fe19f111e250]*/
3449 {
3450     if (ms <= 0) {
3451         PyErr_SetString(PyExc_ValueError, "ms must be > 0");
3452         return NULL;
3453     }
3454 
3455     return PyCursesCheckERR(set_escdelay(ms), "set_escdelay");
3456 }
3457 
3458 /*[clinic input]
3459 _curses.get_tabsize
3460 
3461 Gets the curses TABSIZE setting.
3462 
3463 Gets the number of columns used by the curses library when converting a tab
3464 character to spaces as it adds the tab to a window.
3465 [clinic start generated code]*/
3466 
3467 static PyObject *
_curses_get_tabsize_impl(PyObject * module)3468 _curses_get_tabsize_impl(PyObject *module)
3469 /*[clinic end generated code: output=7e9e51fb6126fbdf input=74af86bf6c9f5d7e]*/
3470 {
3471     return PyLong_FromLong(TABSIZE);
3472 }
3473 /*[clinic input]
3474 _curses.set_tabsize
3475     size: int
3476         rendered cell width of a tab character.
3477     /
3478 
3479 Sets the curses TABSIZE setting.
3480 
3481 Sets the number of columns used by the curses library when converting a tab
3482 character to spaces as it adds the tab to a window.
3483 [clinic start generated code]*/
3484 
3485 static PyObject *
_curses_set_tabsize_impl(PyObject * module,int size)3486 _curses_set_tabsize_impl(PyObject *module, int size)
3487 /*[clinic end generated code: output=c1de5a76c0daab1e input=78cba6a3021ad061]*/
3488 {
3489     if (size <= 0) {
3490         PyErr_SetString(PyExc_ValueError, "size must be > 0");
3491         return NULL;
3492     }
3493 
3494     return PyCursesCheckERR(set_tabsize(size), "set_tabsize");
3495 }
3496 #endif
3497 
3498 /*[clinic input]
3499 _curses.intrflush
3500 
3501     flag: bool(accept={int})
3502     /
3503 
3504 [clinic start generated code]*/
3505 
3506 static PyObject *
_curses_intrflush_impl(PyObject * module,int flag)3507 _curses_intrflush_impl(PyObject *module, int flag)
3508 /*[clinic end generated code: output=c1986df35e999a0f input=fcba57bb28dfd795]*/
3509 {
3510     PyCursesInitialised;
3511 
3512     return PyCursesCheckERR(intrflush(NULL, flag), "intrflush");
3513 }
3514 
3515 /*[clinic input]
3516 _curses.isendwin
3517 
3518 Return True if endwin() has been called.
3519 [clinic start generated code]*/
3520 
3521 static PyObject *
_curses_isendwin_impl(PyObject * module)3522 _curses_isendwin_impl(PyObject *module)
3523 /*[clinic end generated code: output=d73179e4a7e1eb8c input=6cdb01a7ebf71397]*/
3524 NoArgTrueFalseFunctionBody(isendwin)
3525 
3526 #ifdef HAVE_CURSES_IS_TERM_RESIZED
3527 /*[clinic input]
3528 _curses.is_term_resized
3529 
3530     nlines: int
3531         Height.
3532     ncols: int
3533         Width.
3534     /
3535 
3536 Return True if resize_term() would modify the window structure, False otherwise.
3537 [clinic start generated code]*/
3538 
3539 static PyObject *
3540 _curses_is_term_resized_impl(PyObject *module, int nlines, int ncols)
3541 /*[clinic end generated code: output=aafe04afe50f1288 input=ca9c0bd0fb8ab444]*/
3542 {
3543     PyCursesInitialised;
3544 
3545     return PyBool_FromLong(is_term_resized(nlines, ncols));
3546 }
3547 #endif /* HAVE_CURSES_IS_TERM_RESIZED */
3548 
3549 /*[clinic input]
3550 _curses.keyname
3551 
3552     key: int
3553         Key number.
3554     /
3555 
3556 Return the name of specified key.
3557 [clinic start generated code]*/
3558 
3559 static PyObject *
_curses_keyname_impl(PyObject * module,int key)3560 _curses_keyname_impl(PyObject *module, int key)
3561 /*[clinic end generated code: output=fa2675ab3f4e056b input=ee4b1d0f243a2a2b]*/
3562 {
3563     const char *knp;
3564 
3565     PyCursesInitialised;
3566 
3567     if (key < 0) {
3568         PyErr_SetString(PyExc_ValueError, "invalid key number");
3569         return NULL;
3570     }
3571     knp = keyname(key);
3572 
3573     return PyBytes_FromString((knp == NULL) ? "" : knp);
3574 }
3575 
3576 /*[clinic input]
3577 _curses.killchar
3578 
3579 Return the user's current line kill character.
3580 [clinic start generated code]*/
3581 
3582 static PyObject *
_curses_killchar_impl(PyObject * module)3583 _curses_killchar_impl(PyObject *module)
3584 /*[clinic end generated code: output=31c3a45b2c528269 input=1ff171c38df5ccad]*/
3585 {
3586     char ch;
3587 
3588     ch = killchar();
3589 
3590     return PyBytes_FromStringAndSize(&ch, 1);
3591 }
3592 
3593 /*[clinic input]
3594 _curses.longname
3595 
3596 Return the terminfo long name field describing the current terminal.
3597 
3598 The maximum length of a verbose description is 128 characters.  It is defined
3599 only after the call to initscr().
3600 [clinic start generated code]*/
3601 
3602 static PyObject *
_curses_longname_impl(PyObject * module)3603 _curses_longname_impl(PyObject *module)
3604 /*[clinic end generated code: output=fdf30433727ef568 input=84c3f20201b1098e]*/
3605 NoArgReturnStringFunctionBody(longname)
3606 
3607 /*[clinic input]
3608 _curses.meta
3609 
3610     yes: bool(accept={int})
3611     /
3612 
3613 Enable/disable meta keys.
3614 
3615 If yes is True, allow 8-bit characters to be input.  If yes is False,
3616 allow only 7-bit characters.
3617 [clinic start generated code]*/
3618 
3619 static PyObject *
3620 _curses_meta_impl(PyObject *module, int yes)
3621 /*[clinic end generated code: output=22f5abda46a605d8 input=af9892e3a74f35db]*/
3622 {
3623     PyCursesInitialised;
3624 
3625     return PyCursesCheckERR(meta(stdscr, yes), "meta");
3626 }
3627 
3628 #ifdef NCURSES_MOUSE_VERSION
3629 /*[clinic input]
3630 _curses.mouseinterval
3631 
3632     interval: int
3633         Time in milliseconds.
3634     /
3635 
3636 Set and retrieve the maximum time between press and release in a click.
3637 
3638 Set the maximum time that can elapse between press and release events in
3639 order for them to be recognized as a click, and return the previous interval
3640 value.
3641 [clinic start generated code]*/
3642 
3643 static PyObject *
_curses_mouseinterval_impl(PyObject * module,int interval)3644 _curses_mouseinterval_impl(PyObject *module, int interval)
3645 /*[clinic end generated code: output=c4f5ff04354634c5 input=75aaa3f0db10ac4e]*/
3646 {
3647     PyCursesInitialised;
3648 
3649     return PyCursesCheckERR(mouseinterval(interval), "mouseinterval");
3650 }
3651 
3652 /*[clinic input]
3653 _curses.mousemask
3654 
3655     newmask: unsigned_long(bitwise=True)
3656     /
3657 
3658 Set the mouse events to be reported, and return a tuple (availmask, oldmask).
3659 
3660 Return a tuple (availmask, oldmask).  availmask indicates which of the
3661 specified mouse events can be reported; on complete failure it returns 0.
3662 oldmask is the previous value of the given window's mouse event mask.
3663 If this function is never called, no mouse events are ever reported.
3664 [clinic start generated code]*/
3665 
3666 static PyObject *
_curses_mousemask_impl(PyObject * module,unsigned long newmask)3667 _curses_mousemask_impl(PyObject *module, unsigned long newmask)
3668 /*[clinic end generated code: output=9406cf1b8a36e485 input=bdf76b7568a3c541]*/
3669 {
3670     mmask_t oldmask, availmask;
3671 
3672     PyCursesInitialised;
3673     availmask = mousemask((mmask_t)newmask, &oldmask);
3674     return Py_BuildValue("(kk)",
3675                          (unsigned long)availmask, (unsigned long)oldmask);
3676 }
3677 #endif
3678 
3679 /*[clinic input]
3680 _curses.napms
3681 
3682     ms: int
3683         Duration in milliseconds.
3684     /
3685 
3686 Sleep for specified time.
3687 [clinic start generated code]*/
3688 
3689 static PyObject *
_curses_napms_impl(PyObject * module,int ms)3690 _curses_napms_impl(PyObject *module, int ms)
3691 /*[clinic end generated code: output=a40a1da2e39ea438 input=20cd3af2b6900f56]*/
3692 {
3693     PyCursesInitialised;
3694 
3695     return Py_BuildValue("i", napms(ms));
3696 }
3697 
3698 
3699 /*[clinic input]
3700 _curses.newpad
3701 
3702     nlines: int
3703         Height.
3704     ncols: int
3705         Width.
3706     /
3707 
3708 Create and return a pointer to a new pad data structure.
3709 [clinic start generated code]*/
3710 
3711 static PyObject *
_curses_newpad_impl(PyObject * module,int nlines,int ncols)3712 _curses_newpad_impl(PyObject *module, int nlines, int ncols)
3713 /*[clinic end generated code: output=de52a56eb1098ec9 input=93f1272f240d8894]*/
3714 {
3715     WINDOW *win;
3716 
3717     PyCursesInitialised;
3718 
3719     win = newpad(nlines, ncols);
3720 
3721     if (win == NULL) {
3722         PyErr_SetString(PyCursesError, catchall_NULL);
3723         return NULL;
3724     }
3725 
3726     return (PyObject *)PyCursesWindow_New(win, NULL);
3727 }
3728 
3729 /*[clinic input]
3730 _curses.newwin
3731 
3732     nlines: int
3733         Height.
3734     ncols: int
3735         Width.
3736     [
3737     begin_y: int = 0
3738         Top side y-coordinate.
3739     begin_x: int = 0
3740         Left side x-coordinate.
3741     ]
3742     /
3743 
3744 Return a new window.
3745 
3746 By default, the window will extend from the specified position to the lower
3747 right corner of the screen.
3748 [clinic start generated code]*/
3749 
3750 static PyObject *
_curses_newwin_impl(PyObject * module,int nlines,int ncols,int group_right_1,int begin_y,int begin_x)3751 _curses_newwin_impl(PyObject *module, int nlines, int ncols,
3752                     int group_right_1, int begin_y, int begin_x)
3753 /*[clinic end generated code: output=c1e0a8dc8ac2826c input=29312c15a72a003d]*/
3754 {
3755     WINDOW *win;
3756 
3757     PyCursesInitialised;
3758 
3759     win = newwin(nlines,ncols,begin_y,begin_x);
3760     if (win == NULL) {
3761         PyErr_SetString(PyCursesError, catchall_NULL);
3762         return NULL;
3763     }
3764 
3765     return (PyObject *)PyCursesWindow_New(win, NULL);
3766 }
3767 
3768 /*[clinic input]
3769 _curses.nl
3770 
3771     flag: bool(accept={int}) = True
3772         If false, the effect is the same as calling nonl().
3773     /
3774 
3775 Enter newline mode.
3776 
3777 This mode translates the return key into newline on input, and translates
3778 newline into return and line-feed on output.  Newline mode is initially on.
3779 [clinic start generated code]*/
3780 
3781 static PyObject *
_curses_nl_impl(PyObject * module,int flag)3782 _curses_nl_impl(PyObject *module, int flag)
3783 /*[clinic end generated code: output=b39cc0ffc9015003 input=cf36a63f7b86e28a]*/
3784 NoArgOrFlagNoReturnFunctionBody(nl, flag)
3785 
3786 /*[clinic input]
3787 _curses.nocbreak
3788 
3789 Leave cbreak mode.
3790 
3791 Return to normal "cooked" mode with line buffering.
3792 [clinic start generated code]*/
3793 
3794 static PyObject *
3795 _curses_nocbreak_impl(PyObject *module)
3796 /*[clinic end generated code: output=eabf3833a4fbf620 input=e4b65f7d734af400]*/
3797 NoArgNoReturnFunctionBody(nocbreak)
3798 
3799 /*[clinic input]
3800 _curses.noecho
3801 
3802 Leave echo mode.
3803 
3804 Echoing of input characters is turned off.
3805 [clinic start generated code]*/
3806 
3807 static PyObject *
3808 _curses_noecho_impl(PyObject *module)
3809 /*[clinic end generated code: output=cc95ab45bc98f41b input=76714df529e614c3]*/
3810 NoArgNoReturnFunctionBody(noecho)
3811 
3812 /*[clinic input]
3813 _curses.nonl
3814 
3815 Leave newline mode.
3816 
3817 Disable translation of return into newline on input, and disable low-level
3818 translation of newline into newline/return on output.
3819 [clinic start generated code]*/
3820 
3821 static PyObject *
3822 _curses_nonl_impl(PyObject *module)
3823 /*[clinic end generated code: output=99e917e9715770c6 input=9d37dd122d3022fc]*/
3824 NoArgNoReturnFunctionBody(nonl)
3825 
3826 /*[clinic input]
3827 _curses.noqiflush
3828 
3829 Disable queue flushing.
3830 
3831 When queue flushing is disabled, normal flush of input and output queues
3832 associated with the INTR, QUIT and SUSP characters will not be done.
3833 [clinic start generated code]*/
3834 
3835 static PyObject *
3836 _curses_noqiflush_impl(PyObject *module)
3837 /*[clinic end generated code: output=8b95a4229bbf0877 input=ba3e6b2e3e54c4df]*/
3838 NoArgNoReturnVoidFunctionBody(noqiflush)
3839 
3840 /*[clinic input]
3841 _curses.noraw
3842 
3843 Leave raw mode.
3844 
3845 Return to normal "cooked" mode with line buffering.
3846 [clinic start generated code]*/
3847 
3848 static PyObject *
3849 _curses_noraw_impl(PyObject *module)
3850 /*[clinic end generated code: output=39894e5524c430cc input=6ec86692096dffb5]*/
3851 NoArgNoReturnFunctionBody(noraw)
3852 
3853 /*[clinic input]
3854 _curses.pair_content
3855 
3856     pair_number: pair
3857         The number of the color pair (0 - (COLOR_PAIRS-1)).
3858     /
3859 
3860 Return a tuple (fg, bg) containing the colors for the requested color pair.
3861 [clinic start generated code]*/
3862 
3863 static PyObject *
3864 _curses_pair_content_impl(PyObject *module, int pair_number)
3865 /*[clinic end generated code: output=4a726dd0e6885f3f input=03970f840fc7b739]*/
3866 {
3867     _CURSES_COLOR_NUM_TYPE f, b;
3868 
3869     PyCursesInitialised;
3870     PyCursesInitialisedColor;
3871 
3872     if (_CURSES_PAIR_CONTENT_FUNC(pair_number, &f, &b) == ERR) {
3873         if (pair_number >= COLOR_PAIRS) {
3874             PyErr_Format(PyExc_ValueError,
3875                          "Color pair is greater than COLOR_PAIRS-1 (%d).",
3876                          COLOR_PAIRS - 1);
3877         }
3878         else {
3879             PyErr_Format(PyCursesError, "%s() returned ERR",
3880                          Py_STRINGIFY(_CURSES_PAIR_CONTENT_FUNC));
3881         }
3882         return NULL;
3883     }
3884 
3885     return Py_BuildValue("(ii)", f, b);
3886 }
3887 
3888 /*[clinic input]
3889 _curses.pair_number
3890 
3891     attr: int
3892     /
3893 
3894 Return the number of the color-pair set by the specified attribute value.
3895 
3896 color_pair() is the counterpart to this function.
3897 [clinic start generated code]*/
3898 
3899 static PyObject *
_curses_pair_number_impl(PyObject * module,int attr)3900 _curses_pair_number_impl(PyObject *module, int attr)
3901 /*[clinic end generated code: output=85bce7d65c0aa3f4 input=d478548e33f5e61a]*/
3902 {
3903     PyCursesInitialised;
3904     PyCursesInitialisedColor;
3905 
3906     return PyLong_FromLong(PAIR_NUMBER(attr));
3907 }
3908 
3909 /*[clinic input]
3910 _curses.putp
3911 
3912     string: str(accept={robuffer})
3913     /
3914 
3915 Emit the value of a specified terminfo capability for the current terminal.
3916 
3917 Note that the output of putp() always goes to standard output.
3918 [clinic start generated code]*/
3919 
3920 static PyObject *
_curses_putp_impl(PyObject * module,const char * string)3921 _curses_putp_impl(PyObject *module, const char *string)
3922 /*[clinic end generated code: output=e98081d1b8eb5816 input=1601faa828b44cb3]*/
3923 {
3924     return PyCursesCheckERR(putp(string), "putp");
3925 }
3926 
3927 /*[clinic input]
3928 _curses.qiflush
3929 
3930     flag: bool(accept={int}) = True
3931         If false, the effect is the same as calling noqiflush().
3932     /
3933 
3934 Enable queue flushing.
3935 
3936 If queue flushing is enabled, all output in the display driver queue
3937 will be flushed when the INTR, QUIT and SUSP characters are read.
3938 [clinic start generated code]*/
3939 
3940 static PyObject *
_curses_qiflush_impl(PyObject * module,int flag)3941 _curses_qiflush_impl(PyObject *module, int flag)
3942 /*[clinic end generated code: output=9167e862f760ea30 input=e9e4a389946a0dbc]*/
3943 {
3944     PyCursesInitialised;
3945 
3946     if (flag) {
3947         qiflush();
3948     }
3949     else {
3950         noqiflush();
3951     }
3952     Py_RETURN_NONE;
3953 }
3954 
3955 /* Internal helper used for updating curses.LINES, curses.COLS, _curses.LINES
3956  * and _curses.COLS */
3957 #if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)
3958 static int
update_lines_cols(void)3959 update_lines_cols(void)
3960 {
3961     PyObject *o;
3962     PyObject *m = PyImport_ImportModuleNoBlock("curses");
3963     _Py_IDENTIFIER(LINES);
3964     _Py_IDENTIFIER(COLS);
3965 
3966     if (!m)
3967         return 0;
3968 
3969     o = PyLong_FromLong(LINES);
3970     if (!o) {
3971         Py_DECREF(m);
3972         return 0;
3973     }
3974     if (_PyObject_SetAttrId(m, &PyId_LINES, o)) {
3975         Py_DECREF(m);
3976         Py_DECREF(o);
3977         return 0;
3978     }
3979     /* PyId_LINES.object will be initialized here. */
3980     if (PyDict_SetItem(ModDict, _PyUnicode_FromId(&PyId_LINES), o)) {
3981         Py_DECREF(m);
3982         Py_DECREF(o);
3983         return 0;
3984     }
3985     Py_DECREF(o);
3986     o = PyLong_FromLong(COLS);
3987     if (!o) {
3988         Py_DECREF(m);
3989         return 0;
3990     }
3991     if (_PyObject_SetAttrId(m, &PyId_COLS, o)) {
3992         Py_DECREF(m);
3993         Py_DECREF(o);
3994         return 0;
3995     }
3996     if (PyDict_SetItem(ModDict, _PyUnicode_FromId(&PyId_COLS), o)) {
3997         Py_DECREF(m);
3998         Py_DECREF(o);
3999         return 0;
4000     }
4001     Py_DECREF(o);
4002     Py_DECREF(m);
4003     return 1;
4004 }
4005 
4006 /*[clinic input]
4007 _curses.update_lines_cols
4008 
4009 [clinic start generated code]*/
4010 
4011 static PyObject *
_curses_update_lines_cols_impl(PyObject * module)4012 _curses_update_lines_cols_impl(PyObject *module)
4013 /*[clinic end generated code: output=423f2b1e63ed0f75 input=5f065ab7a28a5d90]*/
4014 {
4015     if (!update_lines_cols()) {
4016         return NULL;
4017     }
4018     Py_RETURN_NONE;
4019 }
4020 
4021 #endif
4022 
4023 /*[clinic input]
4024 _curses.raw
4025 
4026     flag: bool(accept={int}) = True
4027         If false, the effect is the same as calling noraw().
4028     /
4029 
4030 Enter raw mode.
4031 
4032 In raw mode, normal line buffering and processing of interrupt, quit,
4033 suspend, and flow control keys are turned off; characters are presented to
4034 curses input functions one by one.
4035 [clinic start generated code]*/
4036 
4037 static PyObject *
_curses_raw_impl(PyObject * module,int flag)4038 _curses_raw_impl(PyObject *module, int flag)
4039 /*[clinic end generated code: output=a750e4b342be015b input=e36d8db27832b848]*/
4040 NoArgOrFlagNoReturnFunctionBody(raw, flag)
4041 
4042 /*[clinic input]
4043 _curses.reset_prog_mode
4044 
4045 Restore the terminal to "program" mode, as previously saved by def_prog_mode().
4046 [clinic start generated code]*/
4047 
4048 static PyObject *
4049 _curses_reset_prog_mode_impl(PyObject *module)
4050 /*[clinic end generated code: output=15eb765abf0b6575 input=3d82bea2b3243471]*/
4051 NoArgNoReturnFunctionBody(reset_prog_mode)
4052 
4053 /*[clinic input]
4054 _curses.reset_shell_mode
4055 
4056 Restore the terminal to "shell" mode, as previously saved by def_shell_mode().
4057 [clinic start generated code]*/
4058 
4059 static PyObject *
4060 _curses_reset_shell_mode_impl(PyObject *module)
4061 /*[clinic end generated code: output=0238de2962090d33 input=1c738fa64bd1a24f]*/
4062 NoArgNoReturnFunctionBody(reset_shell_mode)
4063 
4064 /*[clinic input]
4065 _curses.resetty
4066 
4067 Restore terminal mode.
4068 [clinic start generated code]*/
4069 
4070 static PyObject *
4071 _curses_resetty_impl(PyObject *module)
4072 /*[clinic end generated code: output=ff4b448e80a7cd63 input=940493de03624bb0]*/
4073 NoArgNoReturnFunctionBody(resetty)
4074 
4075 #ifdef HAVE_CURSES_RESIZETERM
4076 /*[clinic input]
4077 _curses.resizeterm
4078 
4079     nlines: int
4080         Height.
4081     ncols: int
4082         Width.
4083     /
4084 
4085 Resize the standard and current windows to the specified dimensions.
4086 
4087 Adjusts other bookkeeping data used by the curses library that record the
4088 window dimensions (in particular the SIGWINCH handler).
4089 [clinic start generated code]*/
4090 
4091 static PyObject *
4092 _curses_resizeterm_impl(PyObject *module, int nlines, int ncols)
4093 /*[clinic end generated code: output=56d6bcc5194ad055 input=0fca02ebad5ffa82]*/
4094 {
4095     PyObject *result;
4096 
4097     PyCursesInitialised;
4098 
4099     result = PyCursesCheckERR(resizeterm(nlines, ncols), "resizeterm");
4100     if (!result)
4101         return NULL;
4102     if (!update_lines_cols()) {
4103         Py_DECREF(result);
4104         return NULL;
4105     }
4106     return result;
4107 }
4108 
4109 #endif
4110 
4111 #ifdef HAVE_CURSES_RESIZE_TERM
4112 /*[clinic input]
4113 _curses.resize_term
4114 
4115     nlines: int
4116         Height.
4117     ncols: int
4118         Width.
4119     /
4120 
4121 Backend function used by resizeterm(), performing most of the work.
4122 
4123 When resizing the windows, resize_term() blank-fills the areas that are
4124 extended.  The calling application should fill in these areas with appropriate
4125 data.  The resize_term() function attempts to resize all windows.  However,
4126 due to the calling convention of pads, it is not possible to resize these
4127 without additional interaction with the application.
4128 [clinic start generated code]*/
4129 
4130 static PyObject *
_curses_resize_term_impl(PyObject * module,int nlines,int ncols)4131 _curses_resize_term_impl(PyObject *module, int nlines, int ncols)
4132 /*[clinic end generated code: output=9e26d8b9ea311ed2 input=2197edd05b049ed4]*/
4133 {
4134     PyObject *result;
4135 
4136     PyCursesInitialised;
4137 
4138     result = PyCursesCheckERR(resize_term(nlines, ncols), "resize_term");
4139     if (!result)
4140         return NULL;
4141     if (!update_lines_cols()) {
4142         Py_DECREF(result);
4143         return NULL;
4144     }
4145     return result;
4146 }
4147 #endif /* HAVE_CURSES_RESIZE_TERM */
4148 
4149 /*[clinic input]
4150 _curses.savetty
4151 
4152 Save terminal mode.
4153 [clinic start generated code]*/
4154 
4155 static PyObject *
_curses_savetty_impl(PyObject * module)4156 _curses_savetty_impl(PyObject *module)
4157 /*[clinic end generated code: output=6babc49f12b42199 input=fce6b2b7d2200102]*/
4158 NoArgNoReturnFunctionBody(savetty)
4159 
4160 #ifdef getsyx
4161 /*[clinic input]
4162 _curses.setsyx
4163 
4164     y: int
4165         Y-coordinate.
4166     x: int
4167         X-coordinate.
4168     /
4169 
4170 Set the virtual screen cursor.
4171 
4172 If y and x are both -1, then leaveok is set.
4173 [clinic start generated code]*/
4174 
4175 static PyObject *
4176 _curses_setsyx_impl(PyObject *module, int y, int x)
4177 /*[clinic end generated code: output=23dcf753511a2464 input=fa7f2b208e10a557]*/
4178 {
4179     PyCursesInitialised;
4180 
4181     setsyx(y,x);
4182 
4183     Py_RETURN_NONE;
4184 }
4185 #endif
4186 
4187 /*[clinic input]
4188 _curses.start_color
4189 
4190 Initializes eight basic colors and global variables COLORS and COLOR_PAIRS.
4191 
4192 Must be called if the programmer wants to use colors, and before any other
4193 color manipulation routine is called.  It is good practice to call this
4194 routine right after initscr().
4195 
4196 It also restores the colors on the terminal to the values they had when the
4197 terminal was just turned on.
4198 [clinic start generated code]*/
4199 
4200 static PyObject *
_curses_start_color_impl(PyObject * module)4201 _curses_start_color_impl(PyObject *module)
4202 /*[clinic end generated code: output=8b772b41d8090ede input=0ca0ecb2b77e1a12]*/
4203 {
4204     int code;
4205     PyObject *c, *cp;
4206 
4207     PyCursesInitialised;
4208 
4209     code = start_color();
4210     if (code != ERR) {
4211         initialisedcolors = TRUE;
4212         c = PyLong_FromLong((long) COLORS);
4213         if (c == NULL)
4214             return NULL;
4215         if (PyDict_SetItemString(ModDict, "COLORS", c) < 0) {
4216             Py_DECREF(c);
4217             return NULL;
4218         }
4219         Py_DECREF(c);
4220         cp = PyLong_FromLong((long) COLOR_PAIRS);
4221         if (cp == NULL)
4222             return NULL;
4223         if (PyDict_SetItemString(ModDict, "COLOR_PAIRS", cp) < 0) {
4224             Py_DECREF(cp);
4225             return NULL;
4226         }
4227         Py_DECREF(cp);
4228         Py_RETURN_NONE;
4229     } else {
4230         PyErr_SetString(PyCursesError, "start_color() returned ERR");
4231         return NULL;
4232     }
4233 }
4234 
4235 /*[clinic input]
4236 _curses.termattrs
4237 
4238 Return a logical OR of all video attributes supported by the terminal.
4239 [clinic start generated code]*/
4240 
4241 static PyObject *
_curses_termattrs_impl(PyObject * module)4242 _curses_termattrs_impl(PyObject *module)
4243 /*[clinic end generated code: output=b06f437fce1b6fc4 input=0559882a04f84d1d]*/
4244 NoArgReturnIntFunctionBody(termattrs)
4245 
4246 /*[clinic input]
4247 _curses.termname
4248 
4249 Return the value of the environment variable TERM, truncated to 14 characters.
4250 [clinic start generated code]*/
4251 
4252 static PyObject *
4253 _curses_termname_impl(PyObject *module)
4254 /*[clinic end generated code: output=96375577ebbd67fd input=33c08d000944f33f]*/
4255 NoArgReturnStringFunctionBody(termname)
4256 
4257 /*[clinic input]
4258 _curses.tigetflag
4259 
4260     capname: str
4261         The terminfo capability name.
4262     /
4263 
4264 Return the value of the Boolean capability.
4265 
4266 The value -1 is returned if capname is not a Boolean capability, or 0 if
4267 it is canceled or absent from the terminal description.
4268 [clinic start generated code]*/
4269 
4270 static PyObject *
4271 _curses_tigetflag_impl(PyObject *module, const char *capname)
4272 /*[clinic end generated code: output=8853c0e55542195b input=b0787af9e3e9a6ce]*/
4273 {
4274     PyCursesSetupTermCalled;
4275 
4276     return PyLong_FromLong( (long) tigetflag( (char *)capname ) );
4277 }
4278 
4279 /*[clinic input]
4280 _curses.tigetnum
4281 
4282     capname: str
4283         The terminfo capability name.
4284     /
4285 
4286 Return the value of the numeric capability.
4287 
4288 The value -2 is returned if capname is not a numeric capability, or -1 if
4289 it is canceled or absent from the terminal description.
4290 [clinic start generated code]*/
4291 
4292 static PyObject *
_curses_tigetnum_impl(PyObject * module,const char * capname)4293 _curses_tigetnum_impl(PyObject *module, const char *capname)
4294 /*[clinic end generated code: output=46f8b0a1b5dff42f input=5cdf2f410b109720]*/
4295 {
4296     PyCursesSetupTermCalled;
4297 
4298     return PyLong_FromLong( (long) tigetnum( (char *)capname ) );
4299 }
4300 
4301 /*[clinic input]
4302 _curses.tigetstr
4303 
4304     capname: str
4305         The terminfo capability name.
4306     /
4307 
4308 Return the value of the string capability.
4309 
4310 None is returned if capname is not a string capability, or is canceled or
4311 absent from the terminal description.
4312 [clinic start generated code]*/
4313 
4314 static PyObject *
_curses_tigetstr_impl(PyObject * module,const char * capname)4315 _curses_tigetstr_impl(PyObject *module, const char *capname)
4316 /*[clinic end generated code: output=f22b576ad60248f3 input=36644df25c73c0a7]*/
4317 {
4318     PyCursesSetupTermCalled;
4319 
4320     capname = tigetstr( (char *)capname );
4321     if (capname == NULL || capname == (char*) -1) {
4322         Py_RETURN_NONE;
4323     }
4324     return PyBytes_FromString( capname );
4325 }
4326 
4327 /*[clinic input]
4328 _curses.tparm
4329 
4330     str: str(accept={robuffer})
4331         Parameterized byte string obtained from the terminfo database.
4332     i1: int = 0
4333     i2: int = 0
4334     i3: int = 0
4335     i4: int = 0
4336     i5: int = 0
4337     i6: int = 0
4338     i7: int = 0
4339     i8: int = 0
4340     i9: int = 0
4341     /
4342 
4343 Instantiate the specified byte string with the supplied parameters.
4344 [clinic start generated code]*/
4345 
4346 static PyObject *
_curses_tparm_impl(PyObject * module,const char * str,int i1,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9)4347 _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3,
4348                    int i4, int i5, int i6, int i7, int i8, int i9)
4349 /*[clinic end generated code: output=599f62b615c667ff input=5e30b15786f032aa]*/
4350 {
4351     char* result = NULL;
4352 
4353     PyCursesSetupTermCalled;
4354 
4355     result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9);
4356     if (!result) {
4357         PyErr_SetString(PyCursesError, "tparm() returned NULL");
4358         return NULL;
4359     }
4360 
4361     return PyBytes_FromString(result);
4362 }
4363 
4364 #ifdef HAVE_CURSES_TYPEAHEAD
4365 /*[clinic input]
4366 _curses.typeahead
4367 
4368     fd: int
4369         File descriptor.
4370     /
4371 
4372 Specify that the file descriptor fd be used for typeahead checking.
4373 
4374 If fd is -1, then no typeahead checking is done.
4375 [clinic start generated code]*/
4376 
4377 static PyObject *
_curses_typeahead_impl(PyObject * module,int fd)4378 _curses_typeahead_impl(PyObject *module, int fd)
4379 /*[clinic end generated code: output=084bb649d7066583 input=f2968d8e1805051b]*/
4380 {
4381     PyCursesInitialised;
4382 
4383     return PyCursesCheckERR(typeahead( fd ), "typeahead");
4384 }
4385 #endif
4386 
4387 /*[clinic input]
4388 _curses.unctrl
4389 
4390     ch: object
4391     /
4392 
4393 Return a string which is a printable representation of the character ch.
4394 
4395 Control characters are displayed as a caret followed by the character,
4396 for example as ^C.  Printing characters are left as they are.
4397 [clinic start generated code]*/
4398 
4399 static PyObject *
_curses_unctrl(PyObject * module,PyObject * ch)4400 _curses_unctrl(PyObject *module, PyObject *ch)
4401 /*[clinic end generated code: output=8e07fafc430c9434 input=cd1e35e16cd1ace4]*/
4402 {
4403     chtype ch_;
4404 
4405     PyCursesInitialised;
4406 
4407     if (!PyCurses_ConvertToChtype(NULL, ch, &ch_))
4408         return NULL;
4409 
4410     return PyBytes_FromString(unctrl(ch_));
4411 }
4412 
4413 /*[clinic input]
4414 _curses.ungetch
4415 
4416     ch: object
4417     /
4418 
4419 Push ch so the next getch() will return it.
4420 [clinic start generated code]*/
4421 
4422 static PyObject *
_curses_ungetch(PyObject * module,PyObject * ch)4423 _curses_ungetch(PyObject *module, PyObject *ch)
4424 /*[clinic end generated code: output=9b19d8268376d887 input=6681e6ae4c42e5eb]*/
4425 {
4426     chtype ch_;
4427 
4428     PyCursesInitialised;
4429 
4430     if (!PyCurses_ConvertToChtype(NULL, ch, &ch_))
4431         return NULL;
4432 
4433     return PyCursesCheckERR(ungetch(ch_), "ungetch");
4434 }
4435 
4436 #ifdef HAVE_NCURSESW
4437 /* Convert an object to a character (wchar_t):
4438 
4439     - int
4440     - str of length 1
4441 
4442    Return 1 on success, 0 on error. */
4443 static int
PyCurses_ConvertToWchar_t(PyObject * obj,wchar_t * wch)4444 PyCurses_ConvertToWchar_t(PyObject *obj,
4445                           wchar_t *wch)
4446 {
4447     if (PyUnicode_Check(obj)) {
4448         wchar_t buffer[2];
4449         if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) {
4450             PyErr_Format(PyExc_TypeError,
4451                          "expect str of length 1 or int, "
4452                          "got a str of length %zi",
4453                          PyUnicode_GET_LENGTH(obj));
4454             return 0;
4455         }
4456         *wch = buffer[0];
4457         return 2;
4458     }
4459     else if (PyLong_CheckExact(obj)) {
4460         long value;
4461         int overflow;
4462         value = PyLong_AsLongAndOverflow(obj, &overflow);
4463         if (overflow) {
4464             PyErr_SetString(PyExc_OverflowError,
4465                             "int doesn't fit in long");
4466             return 0;
4467         }
4468         *wch = (wchar_t)value;
4469         if ((long)*wch != value) {
4470             PyErr_Format(PyExc_OverflowError,
4471                          "character doesn't fit in wchar_t");
4472             return 0;
4473         }
4474         return 1;
4475     }
4476     else {
4477         PyErr_Format(PyExc_TypeError,
4478                      "expect str of length 1 or int, got %s",
4479                      Py_TYPE(obj)->tp_name);
4480         return 0;
4481     }
4482 }
4483 
4484 /*[clinic input]
4485 _curses.unget_wch
4486 
4487     ch: object
4488     /
4489 
4490 Push ch so the next get_wch() will return it.
4491 [clinic start generated code]*/
4492 
4493 static PyObject *
_curses_unget_wch(PyObject * module,PyObject * ch)4494 _curses_unget_wch(PyObject *module, PyObject *ch)
4495 /*[clinic end generated code: output=1974c9fb01d37863 input=0d56dc65a46feebb]*/
4496 {
4497     wchar_t wch;
4498 
4499     PyCursesInitialised;
4500 
4501     if (!PyCurses_ConvertToWchar_t(ch, &wch))
4502         return NULL;
4503     return PyCursesCheckERR(unget_wch(wch), "unget_wch");
4504 }
4505 #endif
4506 
4507 #ifdef HAVE_CURSES_USE_ENV
4508 /*[clinic input]
4509 _curses.use_env
4510 
4511     flag: bool(accept={int})
4512     /
4513 
4514 Use environment variables LINES and COLUMNS.
4515 
4516 If used, this function should be called before initscr() or newterm() are
4517 called.
4518 
4519 When flag is False, the values of lines and columns specified in the terminfo
4520 database will be used, even if environment variables LINES and COLUMNS (used
4521 by default) are set, or if curses is running in a window (in which case
4522 default behavior would be to use the window size if LINES and COLUMNS are
4523 not set).
4524 [clinic start generated code]*/
4525 
4526 static PyObject *
_curses_use_env_impl(PyObject * module,int flag)4527 _curses_use_env_impl(PyObject *module, int flag)
4528 /*[clinic end generated code: output=b2c445e435c0b164 input=1778eb1e9151ea37]*/
4529 {
4530     use_env(flag);
4531     Py_RETURN_NONE;
4532 }
4533 #endif
4534 
4535 #ifndef STRICT_SYSV_CURSES
4536 /*[clinic input]
4537 _curses.use_default_colors
4538 
4539 Allow use of default values for colors on terminals supporting this feature.
4540 
4541 Use this to support transparency in your application.  The default color
4542 is assigned to the color number -1.
4543 [clinic start generated code]*/
4544 
4545 static PyObject *
_curses_use_default_colors_impl(PyObject * module)4546 _curses_use_default_colors_impl(PyObject *module)
4547 /*[clinic end generated code: output=a3b81ff71dd901be input=656844367470e8fc]*/
4548 {
4549     int code;
4550 
4551     PyCursesInitialised;
4552     PyCursesInitialisedColor;
4553 
4554     code = use_default_colors();
4555     if (code != ERR) {
4556         Py_RETURN_NONE;
4557     } else {
4558         PyErr_SetString(PyCursesError, "use_default_colors() returned ERR");
4559         return NULL;
4560     }
4561 }
4562 #endif /* STRICT_SYSV_CURSES */
4563 
4564 
4565 #ifdef NCURSES_VERSION
4566 
4567 PyDoc_STRVAR(ncurses_version__doc__,
4568 "curses.ncurses_version\n\
4569 \n\
4570 Ncurses version information as a named tuple.");
4571 
4572 static PyTypeObject NcursesVersionType;
4573 
4574 static PyStructSequence_Field ncurses_version_fields[] = {
4575     {"major", "Major release number"},
4576     {"minor", "Minor release number"},
4577     {"patch", "Patch release number"},
4578     {0}
4579 };
4580 
4581 static PyStructSequence_Desc ncurses_version_desc = {
4582     "curses.ncurses_version",  /* name */
4583     ncurses_version__doc__,    /* doc */
4584     ncurses_version_fields,    /* fields */
4585     3
4586 };
4587 
4588 static PyObject *
make_ncurses_version(void)4589 make_ncurses_version(void)
4590 {
4591     PyObject *ncurses_version;
4592     int pos = 0;
4593 
4594     ncurses_version = PyStructSequence_New(&NcursesVersionType);
4595     if (ncurses_version == NULL) {
4596         return NULL;
4597     }
4598 
4599 #define SetIntItem(flag) \
4600     PyStructSequence_SET_ITEM(ncurses_version, pos++, PyLong_FromLong(flag)); \
4601     if (PyErr_Occurred()) { \
4602         Py_CLEAR(ncurses_version); \
4603         return NULL; \
4604     }
4605 
4606     SetIntItem(NCURSES_VERSION_MAJOR)
4607     SetIntItem(NCURSES_VERSION_MINOR)
4608     SetIntItem(NCURSES_VERSION_PATCH)
4609 #undef SetIntItem
4610 
4611     return ncurses_version;
4612 }
4613 
4614 #endif /* NCURSES_VERSION */
4615 
4616 /*[clinic input]
4617 _curses.has_extended_color_support
4618 
4619 Return True if the module supports extended colors; otherwise, return False.
4620 
4621 Extended color support allows more than 256 color-pairs for terminals
4622 that support more than 16 colors (e.g. xterm-256color).
4623 [clinic start generated code]*/
4624 
4625 static PyObject *
_curses_has_extended_color_support_impl(PyObject * module)4626 _curses_has_extended_color_support_impl(PyObject *module)
4627 /*[clinic end generated code: output=68f1be2b57d92e22 input=4b905f046e35ee9f]*/
4628 {
4629     return PyBool_FromLong(_NCURSES_EXTENDED_COLOR_FUNCS);
4630 }
4631 
4632 /* List of functions defined in the module */
4633 
4634 static PyMethodDef PyCurses_methods[] = {
4635     _CURSES_BAUDRATE_METHODDEF
4636     _CURSES_BEEP_METHODDEF
4637     _CURSES_CAN_CHANGE_COLOR_METHODDEF
4638     _CURSES_CBREAK_METHODDEF
4639     _CURSES_COLOR_CONTENT_METHODDEF
4640     _CURSES_COLOR_PAIR_METHODDEF
4641     _CURSES_CURS_SET_METHODDEF
4642     _CURSES_DEF_PROG_MODE_METHODDEF
4643     _CURSES_DEF_SHELL_MODE_METHODDEF
4644     _CURSES_DELAY_OUTPUT_METHODDEF
4645     _CURSES_DOUPDATE_METHODDEF
4646     _CURSES_ECHO_METHODDEF
4647     _CURSES_ENDWIN_METHODDEF
4648     _CURSES_ERASECHAR_METHODDEF
4649     _CURSES_FILTER_METHODDEF
4650     _CURSES_FLASH_METHODDEF
4651     _CURSES_FLUSHINP_METHODDEF
4652     _CURSES_GETMOUSE_METHODDEF
4653     _CURSES_UNGETMOUSE_METHODDEF
4654     _CURSES_GETSYX_METHODDEF
4655     _CURSES_GETWIN_METHODDEF
4656     _CURSES_HAS_COLORS_METHODDEF
4657     _CURSES_HAS_EXTENDED_COLOR_SUPPORT_METHODDEF
4658     _CURSES_HAS_IC_METHODDEF
4659     _CURSES_HAS_IL_METHODDEF
4660     _CURSES_HAS_KEY_METHODDEF
4661     _CURSES_HALFDELAY_METHODDEF
4662     _CURSES_INIT_COLOR_METHODDEF
4663     _CURSES_INIT_PAIR_METHODDEF
4664     _CURSES_INITSCR_METHODDEF
4665     _CURSES_INTRFLUSH_METHODDEF
4666     _CURSES_ISENDWIN_METHODDEF
4667     _CURSES_IS_TERM_RESIZED_METHODDEF
4668     _CURSES_KEYNAME_METHODDEF
4669     _CURSES_KILLCHAR_METHODDEF
4670     _CURSES_LONGNAME_METHODDEF
4671     _CURSES_META_METHODDEF
4672     _CURSES_MOUSEINTERVAL_METHODDEF
4673     _CURSES_MOUSEMASK_METHODDEF
4674     _CURSES_NAPMS_METHODDEF
4675     _CURSES_NEWPAD_METHODDEF
4676     _CURSES_NEWWIN_METHODDEF
4677     _CURSES_NL_METHODDEF
4678     _CURSES_NOCBREAK_METHODDEF
4679     _CURSES_NOECHO_METHODDEF
4680     _CURSES_NONL_METHODDEF
4681     _CURSES_NOQIFLUSH_METHODDEF
4682     _CURSES_NORAW_METHODDEF
4683     _CURSES_PAIR_CONTENT_METHODDEF
4684     _CURSES_PAIR_NUMBER_METHODDEF
4685     _CURSES_PUTP_METHODDEF
4686     _CURSES_QIFLUSH_METHODDEF
4687     _CURSES_RAW_METHODDEF
4688     _CURSES_RESET_PROG_MODE_METHODDEF
4689     _CURSES_RESET_SHELL_MODE_METHODDEF
4690     _CURSES_RESETTY_METHODDEF
4691     _CURSES_RESIZETERM_METHODDEF
4692     _CURSES_RESIZE_TERM_METHODDEF
4693     _CURSES_SAVETTY_METHODDEF
4694 #if defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102
4695     _CURSES_GET_ESCDELAY_METHODDEF
4696     _CURSES_SET_ESCDELAY_METHODDEF
4697 #endif
4698     _CURSES_GET_TABSIZE_METHODDEF
4699     _CURSES_SET_TABSIZE_METHODDEF
4700     _CURSES_SETSYX_METHODDEF
4701     _CURSES_SETUPTERM_METHODDEF
4702     _CURSES_START_COLOR_METHODDEF
4703     _CURSES_TERMATTRS_METHODDEF
4704     _CURSES_TERMNAME_METHODDEF
4705     _CURSES_TIGETFLAG_METHODDEF
4706     _CURSES_TIGETNUM_METHODDEF
4707     _CURSES_TIGETSTR_METHODDEF
4708     _CURSES_TPARM_METHODDEF
4709     _CURSES_TYPEAHEAD_METHODDEF
4710     _CURSES_UNCTRL_METHODDEF
4711     _CURSES_UNGETCH_METHODDEF
4712     _CURSES_UPDATE_LINES_COLS_METHODDEF
4713     _CURSES_UNGET_WCH_METHODDEF
4714     _CURSES_USE_ENV_METHODDEF
4715     _CURSES_USE_DEFAULT_COLORS_METHODDEF
4716     {NULL,                  NULL}         /* sentinel */
4717 };
4718 
4719 /* Initialization function for the module */
4720 
4721 
4722 static struct PyModuleDef _cursesmodule = {
4723     PyModuleDef_HEAD_INIT,
4724     "_curses",
4725     NULL,
4726     -1,
4727     PyCurses_methods,
4728     NULL,
4729     NULL,
4730     NULL,
4731     NULL
4732 };
4733 
4734 static void
curses_destructor(PyObject * op)4735 curses_destructor(PyObject *op)
4736 {
4737     void *ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME);
4738     Py_DECREF(*(void **)ptr);
4739     PyMem_Free(ptr);
4740 }
4741 
4742 PyMODINIT_FUNC
PyInit__curses(void)4743 PyInit__curses(void)
4744 {
4745     PyObject *m, *d, *v, *c_api_object;
4746 
4747     /* Initialize object type */
4748     if (PyType_Ready(&PyCursesWindow_Type) < 0)
4749         return NULL;
4750 
4751     /* Create the module and add the functions */
4752     m = PyModule_Create(&_cursesmodule);
4753     if (m == NULL)
4754         return NULL;
4755 
4756     /* Add some symbolic constants to the module */
4757     d = PyModule_GetDict(m);
4758     if (d == NULL)
4759         return NULL;
4760     ModDict = d; /* For PyCurses_InitScr to use later */
4761 
4762     void **PyCurses_API = PyMem_Calloc(PyCurses_API_pointers, sizeof(void *));
4763     if (PyCurses_API == NULL) {
4764         PyErr_NoMemory();
4765         return NULL;
4766     }
4767     /* Initialize the C API pointer array */
4768     PyCurses_API[0] = (void *)Py_NewRef(&PyCursesWindow_Type);
4769     PyCurses_API[1] = (void *)func_PyCursesSetupTermCalled;
4770     PyCurses_API[2] = (void *)func_PyCursesInitialised;
4771     PyCurses_API[3] = (void *)func_PyCursesInitialisedColor;
4772 
4773     /* Add a capsule for the C API */
4774     c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME,
4775                                  curses_destructor);
4776     if (c_api_object == NULL) {
4777         Py_DECREF(PyCurses_API[0]);
4778         PyMem_Free(PyCurses_API);
4779         return NULL;
4780     }
4781     if (PyDict_SetItemString(d, "_C_API", c_api_object) < 0) {
4782         Py_DECREF(c_api_object);
4783         return NULL;
4784     }
4785     Py_DECREF(c_api_object);
4786 
4787     /* For exception curses.error */
4788     PyCursesError = PyErr_NewException("_curses.error", NULL, NULL);
4789     PyDict_SetItemString(d, "error", PyCursesError);
4790 
4791     /* Make the version available */
4792     v = PyBytes_FromString(PyCursesVersion);
4793     PyDict_SetItemString(d, "version", v);
4794     PyDict_SetItemString(d, "__version__", v);
4795     Py_DECREF(v);
4796 
4797 #ifdef NCURSES_VERSION
4798     /* ncurses_version */
4799     if (NcursesVersionType.tp_name == NULL) {
4800         if (_PyStructSequence_InitType(&NcursesVersionType,
4801                                        &ncurses_version_desc,
4802                                        Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) {
4803             return NULL;
4804         }
4805     }
4806     v = make_ncurses_version();
4807     if (v == NULL) {
4808         return NULL;
4809     }
4810     PyDict_SetItemString(d, "ncurses_version", v);
4811     Py_DECREF(v);
4812 #endif /* NCURSES_VERSION */
4813 
4814     SetDictInt("ERR", ERR);
4815     SetDictInt("OK", OK);
4816 
4817     /* Here are some attributes you can add to chars to print */
4818 
4819     SetDictInt("A_ATTRIBUTES",      A_ATTRIBUTES);
4820     SetDictInt("A_NORMAL",              A_NORMAL);
4821     SetDictInt("A_STANDOUT",            A_STANDOUT);
4822     SetDictInt("A_UNDERLINE",           A_UNDERLINE);
4823     SetDictInt("A_REVERSE",             A_REVERSE);
4824     SetDictInt("A_BLINK",               A_BLINK);
4825     SetDictInt("A_DIM",                 A_DIM);
4826     SetDictInt("A_BOLD",                A_BOLD);
4827     SetDictInt("A_ALTCHARSET",          A_ALTCHARSET);
4828     SetDictInt("A_INVIS",           A_INVIS);
4829     SetDictInt("A_PROTECT",         A_PROTECT);
4830     SetDictInt("A_CHARTEXT",        A_CHARTEXT);
4831     SetDictInt("A_COLOR",           A_COLOR);
4832 
4833     /* The following are never available with strict SYSV curses */
4834 #ifdef A_HORIZONTAL
4835     SetDictInt("A_HORIZONTAL",      A_HORIZONTAL);
4836 #endif
4837 #ifdef A_LEFT
4838     SetDictInt("A_LEFT",            A_LEFT);
4839 #endif
4840 #ifdef A_LOW
4841     SetDictInt("A_LOW",             A_LOW);
4842 #endif
4843 #ifdef A_RIGHT
4844     SetDictInt("A_RIGHT",           A_RIGHT);
4845 #endif
4846 #ifdef A_TOP
4847     SetDictInt("A_TOP",             A_TOP);
4848 #endif
4849 #ifdef A_VERTICAL
4850     SetDictInt("A_VERTICAL",        A_VERTICAL);
4851 #endif
4852 
4853     /* ncurses extension */
4854 #ifdef A_ITALIC
4855     SetDictInt("A_ITALIC",          A_ITALIC);
4856 #endif
4857 
4858     SetDictInt("COLOR_BLACK",       COLOR_BLACK);
4859     SetDictInt("COLOR_RED",         COLOR_RED);
4860     SetDictInt("COLOR_GREEN",       COLOR_GREEN);
4861     SetDictInt("COLOR_YELLOW",      COLOR_YELLOW);
4862     SetDictInt("COLOR_BLUE",        COLOR_BLUE);
4863     SetDictInt("COLOR_MAGENTA",     COLOR_MAGENTA);
4864     SetDictInt("COLOR_CYAN",        COLOR_CYAN);
4865     SetDictInt("COLOR_WHITE",       COLOR_WHITE);
4866 
4867 #ifdef NCURSES_MOUSE_VERSION
4868     /* Mouse-related constants */
4869     SetDictInt("BUTTON1_PRESSED",          BUTTON1_PRESSED);
4870     SetDictInt("BUTTON1_RELEASED",         BUTTON1_RELEASED);
4871     SetDictInt("BUTTON1_CLICKED",          BUTTON1_CLICKED);
4872     SetDictInt("BUTTON1_DOUBLE_CLICKED",   BUTTON1_DOUBLE_CLICKED);
4873     SetDictInt("BUTTON1_TRIPLE_CLICKED",   BUTTON1_TRIPLE_CLICKED);
4874 
4875     SetDictInt("BUTTON2_PRESSED",          BUTTON2_PRESSED);
4876     SetDictInt("BUTTON2_RELEASED",         BUTTON2_RELEASED);
4877     SetDictInt("BUTTON2_CLICKED",          BUTTON2_CLICKED);
4878     SetDictInt("BUTTON2_DOUBLE_CLICKED",   BUTTON2_DOUBLE_CLICKED);
4879     SetDictInt("BUTTON2_TRIPLE_CLICKED",   BUTTON2_TRIPLE_CLICKED);
4880 
4881     SetDictInt("BUTTON3_PRESSED",          BUTTON3_PRESSED);
4882     SetDictInt("BUTTON3_RELEASED",         BUTTON3_RELEASED);
4883     SetDictInt("BUTTON3_CLICKED",          BUTTON3_CLICKED);
4884     SetDictInt("BUTTON3_DOUBLE_CLICKED",   BUTTON3_DOUBLE_CLICKED);
4885     SetDictInt("BUTTON3_TRIPLE_CLICKED",   BUTTON3_TRIPLE_CLICKED);
4886 
4887     SetDictInt("BUTTON4_PRESSED",          BUTTON4_PRESSED);
4888     SetDictInt("BUTTON4_RELEASED",         BUTTON4_RELEASED);
4889     SetDictInt("BUTTON4_CLICKED",          BUTTON4_CLICKED);
4890     SetDictInt("BUTTON4_DOUBLE_CLICKED",   BUTTON4_DOUBLE_CLICKED);
4891     SetDictInt("BUTTON4_TRIPLE_CLICKED",   BUTTON4_TRIPLE_CLICKED);
4892 
4893 #if NCURSES_MOUSE_VERSION > 1
4894     SetDictInt("BUTTON5_PRESSED",          BUTTON5_PRESSED);
4895     SetDictInt("BUTTON5_RELEASED",         BUTTON5_RELEASED);
4896     SetDictInt("BUTTON5_CLICKED",          BUTTON5_CLICKED);
4897     SetDictInt("BUTTON5_DOUBLE_CLICKED",   BUTTON5_DOUBLE_CLICKED);
4898     SetDictInt("BUTTON5_TRIPLE_CLICKED",   BUTTON5_TRIPLE_CLICKED);
4899 #endif
4900 
4901     SetDictInt("BUTTON_SHIFT",             BUTTON_SHIFT);
4902     SetDictInt("BUTTON_CTRL",              BUTTON_CTRL);
4903     SetDictInt("BUTTON_ALT",               BUTTON_ALT);
4904 
4905     SetDictInt("ALL_MOUSE_EVENTS",         ALL_MOUSE_EVENTS);
4906     SetDictInt("REPORT_MOUSE_POSITION",    REPORT_MOUSE_POSITION);
4907 #endif
4908     /* Now set everything up for KEY_ variables */
4909     {
4910         int key;
4911         char *key_n;
4912         char *key_n2;
4913         for (key=KEY_MIN;key < KEY_MAX; key++) {
4914             key_n = (char *)keyname(key);
4915             if (key_n == NULL || strcmp(key_n,"UNKNOWN KEY")==0)
4916                 continue;
4917             if (strncmp(key_n,"KEY_F(",6)==0) {
4918                 char *p1, *p2;
4919                 key_n2 = PyMem_Malloc(strlen(key_n)+1);
4920                 if (!key_n2) {
4921                     PyErr_NoMemory();
4922                     break;
4923                 }
4924                 p1 = key_n;
4925                 p2 = key_n2;
4926                 while (*p1) {
4927                     if (*p1 != '(' && *p1 != ')') {
4928                         *p2 = *p1;
4929                         p2++;
4930                     }
4931                     p1++;
4932                 }
4933                 *p2 = (char)0;
4934             } else
4935                 key_n2 = key_n;
4936             SetDictInt(key_n2,key);
4937             if (key_n2 != key_n)
4938                 PyMem_Free(key_n2);
4939         }
4940         SetDictInt("KEY_MIN", KEY_MIN);
4941         SetDictInt("KEY_MAX", KEY_MAX);
4942     }
4943 
4944     if (PyModule_AddType(m, &PyCursesWindow_Type) < 0) {
4945         return NULL;
4946     }
4947     return m;
4948 }
4949