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