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