1/*
2 *   This is a curses module for Python.
3 *
4 *   Based on prior work by Lance Ellinghaus and Oliver Andrich
5 *   Version 1.2 of this module: Copyright 1994 by Lance Ellinghouse,
6 *    Cathedral City, California Republic, United States of America.
7 *
8 *   Version 1.5b1, heavily extended for ncurses by Oliver Andrich:
9 *   Copyright 1996,1997 by Oliver Andrich, Koblenz, Germany.
10 *
11 *   Tidied for Python 1.6, and currently maintained by <amk@amk.ca>.
12 *
13 *   Permission is hereby granted, free of charge, to any person obtaining
14 *   a copy of this source file to use, copy, modify, merge, or publish it
15 *   subject to the following conditions:
16 *
17 *   The above copyright notice and this permission notice shall be included
18 *   in all copies or in any new file that contains a substantial portion of
19 *   this file.
20 *
21 *   THE  AUTHOR  MAKES  NO  REPRESENTATIONS ABOUT  THE  SUITABILITY  OF
22 *   THE  SOFTWARE FOR  ANY  PURPOSE.  IT IS  PROVIDED  "AS IS"  WITHOUT
23 *   EXPRESS OR  IMPLIED WARRANTY.  THE AUTHOR DISCLAIMS  ALL WARRANTIES
24 *   WITH  REGARD TO  THIS  SOFTWARE, INCLUDING  ALL IMPLIED  WARRANTIES
25 *   OF   MERCHANTABILITY,  FITNESS   FOR  A   PARTICULAR  PURPOSE   AND
26 *   NON-INFRINGEMENT  OF THIRD  PARTY  RIGHTS. IN  NO  EVENT SHALL  THE
27 *   AUTHOR  BE LIABLE  TO  YOU  OR ANY  OTHER  PARTY  FOR ANY  SPECIAL,
28 *   INDIRECT,  OR  CONSEQUENTIAL  DAMAGES  OR  ANY  DAMAGES  WHATSOEVER
29 *   WHETHER IN AN  ACTION OF CONTRACT, NEGLIGENCE,  STRICT LIABILITY OR
30 *   ANY OTHER  ACTION ARISING OUT OF  OR IN CONNECTION WITH  THE USE OR
31 *   PERFORMANCE OF THIS SOFTWARE.
32 */
33
34/*
35
36  A number of SysV or ncurses functions don't have wrappers yet; if you
37  need a given function, add it and send a patch.  See
38  https://www.python.org/dev/patches/ for instructions on how to submit
39  patches to Python.
40
41  Here's a list of currently unsupported functions:
42
43  addchnstr addchstr color_set define_key
44  del_curterm delscreen dupwin inchnstr inchstr innstr keyok
45  mcprint mvaddchnstr mvaddchstr mvcur mvinchnstr
46  mvinchstr mvinnstr mmvwaddchnstr mvwaddchstr
47  mvwinchnstr mvwinchstr mvwinnstr newterm
48  restartterm ripoffline scr_dump
49  scr_init scr_restore scr_set scrl set_curterm set_term setterm
50  tgetent tgetflag tgetnum tgetstr tgoto timeout tputs
51  vidattr vidputs waddchnstr waddchstr
52  wcolor_set winchnstr winchstr winnstr wmouse_trafo wscrl
53
54  Low-priority:
55  slk_attr slk_attr_off slk_attr_on slk_attr_set slk_attroff
56  slk_attron slk_attrset slk_clear slk_color slk_init slk_label
57  slk_noutrefresh slk_refresh slk_restore slk_set slk_touch
58
59  Menu extension (ncurses and probably SYSV):
60  current_item free_item free_menu item_count item_description
61  item_index item_init item_name item_opts item_opts_off
62  item_opts_on item_term item_userptr item_value item_visible
63  menu_back menu_driver menu_fore menu_format menu_grey
64  menu_init menu_items menu_mark menu_opts menu_opts_off
65  menu_opts_on menu_pad menu_pattern menu_request_by_name
66  menu_request_name menu_spacing menu_sub menu_term menu_userptr
67  menu_win new_item new_menu pos_menu_cursor post_menu
68  scale_menu set_current_item set_item_init set_item_opts
69  set_item_term set_item_userptr set_item_value set_menu_back
70  set_menu_fore set_menu_format set_menu_grey set_menu_init
71  set_menu_items set_menu_mark set_menu_opts set_menu_pad
72  set_menu_pattern set_menu_spacing set_menu_sub set_menu_term
73  set_menu_userptr set_menu_win set_top_row top_row unpost_menu
74
75  Form extension (ncurses and probably SYSV):
76  current_field data_ahead data_behind dup_field
77  dynamic_fieldinfo field_arg field_back field_buffer
78  field_count field_fore field_index field_info field_init
79  field_just field_opts field_opts_off field_opts_on field_pad
80  field_status field_term field_type field_userptr form_driver
81  form_fields form_init form_opts form_opts_off form_opts_on
82  form_page form_request_by_name form_request_name form_sub
83  form_term form_userptr form_win free_field free_form
84  link_field link_fieldtype move_field new_field new_form
85  new_page pos_form_cursor post_form scale_form
86  set_current_field set_field_back set_field_buffer
87  set_field_fore set_field_init set_field_just set_field_opts
88  set_field_pad set_field_status set_field_term set_field_type
89  set_field_userptr set_fieldtype_arg set_fieldtype_choice
90  set_form_fields set_form_init set_form_opts set_form_page
91  set_form_sub set_form_term set_form_userptr set_form_win
92  set_max_field set_new_page unpost_form
93
94
95*/
96
97/* Release Number */
98
99static 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 */
136typedef 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]
166module _curses
167class _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
173static PyObject *PyCursesError;
174
175/* Tells whether setupterm() has been called to initialise terminfo.  */
176static int initialised_setupterm = FALSE;
177
178/* Tells whether initscr() has been called to initialise curses.  */
179static int initialised = FALSE;
180
181/* Tells whether start_color() has been called to initialise color usage. */
182static int initialisedcolors = FALSE;
183
184static 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
213static PyObject *
214PyCursesCheckERR(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). */
235static int
236PyCurses_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
287overflow:
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 */
304static int
305PyCurses_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 */
366static int
367PyCurses_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
408static int
409color_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
432static int
433color_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]
447class 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]
454class 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
460static int
461pair_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]
496class 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
502static int
503component_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]
528class 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
537static int func_PyCursesSetupTermCalled(void)
538{
539    PyCursesSetupTermCalled;
540    return 1;
541}
542
543static int func_PyCursesInitialised(void)
544{
545    PyCursesInitialised;
546    return 1;
547}
548
549static 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
561PyTypeObject 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
621Window_NoArgNoReturnFunction(untouchwin)
622Window_NoArgNoReturnFunction(touchwin)
623Window_NoArgNoReturnFunction(redrawwin)
624Window_NoArgNoReturnFunction(winsertln)
625Window_NoArgNoReturnFunction(werase)
626Window_NoArgNoReturnFunction(wdeleteln)
627
628Window_NoArgTrueFalseFunction(is_wintouched)
629
630Window_NoArgNoReturnVoidFunction(wsyncup)
631Window_NoArgNoReturnVoidFunction(wsyncdown)
632Window_NoArgNoReturnVoidFunction(wstandend)
633Window_NoArgNoReturnVoidFunction(wstandout)
634Window_NoArgNoReturnVoidFunction(wcursyncup)
635Window_NoArgNoReturnVoidFunction(wclrtoeol)
636Window_NoArgNoReturnVoidFunction(wclrtobot)
637Window_NoArgNoReturnVoidFunction(wclear)
638
639Window_OneArgNoReturnVoidFunction(idcok, int, "i;True(1) or False(0)")
640#ifdef HAVE_CURSES_IMMEDOK
641Window_OneArgNoReturnVoidFunction(immedok, int, "i;True(1) or False(0)")
642#endif
643Window_OneArgNoReturnVoidFunction(wtimeout, int, "i;delay")
644
645Window_NoArg2TupleReturnFunction(getyx, int, "ii")
646Window_NoArg2TupleReturnFunction(getbegyx, int, "ii")
647Window_NoArg2TupleReturnFunction(getmaxyx, int, "ii")
648Window_NoArg2TupleReturnFunction(getparyx, int, "ii")
649
650Window_OneArgNoReturnFunction(clearok, int, "i;True(1) or False(0)")
651Window_OneArgNoReturnFunction(idlok, int, "i;True(1) or False(0)")
652Window_OneArgNoReturnFunction(keypad, int, "i;True(1) or False(0)")
653Window_OneArgNoReturnFunction(leaveok, int, "i;True(1) or False(0)")
654Window_OneArgNoReturnFunction(nodelay, int, "i;True(1) or False(0)")
655Window_OneArgNoReturnFunction(notimeout, int, "i;True(1) or False(0)")
656Window_OneArgNoReturnFunction(scrollok, int, "i;True(1) or False(0)")
657Window_OneArgNoReturnFunction(winsdelln, int, "i;nlines")
658#ifdef HAVE_CURSES_SYNCOK
659Window_OneArgNoReturnFunction(syncok, int, "i;True(1) or False(0)")
660#endif
661
662Window_TwoArgNoReturnFunction(mvwin, int, "ii;y,x")
663Window_TwoArgNoReturnFunction(mvderwin, int, "ii;y,x")
664Window_TwoArgNoReturnFunction(wmove, int, "ii;y,x")
665#ifndef STRICT_SYSV_CURSES
666Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns")
667#endif
668
669/* Allocation and deallocation of Window Objects */
670
671static PyObject *
672PyCursesWindow_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
706static void
707PyCursesWindow_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
736Paint the character.
737
738Paint character ch at (y, x) with attributes attr,
739overwriting any character previously painted at that location.
740By default, the character position and attributes are the
741current settings for the window object.
742[clinic start generated code]*/
743
744static PyObject *
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
809Paint the string.
810
811Paint the string str at (y, x) with attributes attr,
812overwriting anything previously on the display.
813By default, the character position and attributes are the
814current settings for the window object.
815[clinic start generated code]*/
816
817static PyObject *
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
892Paint at most n characters of the string.
893
894Paint at most n characters of the string str at (y, x) with
895attributes attr, overwriting anything previously on the display.
896By default, the character position and attributes are the
897current settings for the window object.
898[clinic start generated code]*/
899
900static PyObject *
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
962Set the background property of the window.
963[clinic start generated code]*/
964
965static PyObject *
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
983Remove attribute attr from the "background" set.
984[clinic start generated code]*/
985
986static PyObject *
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
999Add attribute attr from the "background" set.
1000[clinic start generated code]*/
1001
1002static PyObject *
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
1015Set the "background" set of attributes.
1016[clinic start generated code]*/
1017
1018static PyObject *
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
1034Set the window's background.
1035[clinic start generated code]*/
1036
1037static PyObject *
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
1072Draw a border around the edges of the window.
1073
1074Each parameter specifies the character to use for a specific part of the
1075border.  The characters can be specified as integers or as one-character
1076strings.  A 0 value for any parameter will cause the default character to be
1077used for that parameter.
1078[clinic start generated code]*/
1079
1080static PyObject *
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
1126Draw a border around the edges of the window.
1127
1128Similar to border(), but both ls and rs are verch and both ts and bs are
1129horch.  The default corner characters are always used by this function.
1130[clinic start generated code]*/
1131
1132static PyObject *
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
1153int 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
1187Set the attributes of characters.
1188
1189Set the attributes of num characters at the current cursor position, or at
1190position (y, x) if supplied.  If no value of num is given or num = -1, the
1191attribute will be set on all the characters to the end of the line.  This
1192function does not move the cursor.  The changed line will be touched using
1193the touchline() method so that the contents will be redisplayed by the next
1194window refresh.
1195[-clinic start generated code]*/
1196static PyObject *
1197PyCursesWindow_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
1261Delete any character at (y, x).
1262[clinic start generated code]*/
1263
1264static PyObject *
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
1292Create a sub-window (window-relative coordinates).
1293
1294derwin() is the same as calling subwin(), except that begin_y and begin_x
1295are relative to the origin of the window, rather than relative to the entire
1296screen.
1297[clinic start generated code]*/
1298
1299static PyObject *
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
1326Add character ch with attribute attr, and refresh.
1327[clinic start generated code]*/
1328
1329static PyObject *
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
1360Return True if the screen-relative coordinates are enclosed by the window.
1361[clinic start generated code]*/
1362
1363static PyObject *
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
1374Return the window's current background character/attribute pair.
1375[clinic start generated code]*/
1376
1377static long
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
1395Get a character code from terminal keyboard.
1396
1397The integer returned does not have to be in ASCII range: function keys,
1398keypad keys and so on return numbers higher than 256.  In no-delay mode, -1
1399is returned if there is no input, else getch() waits until a key is pressed.
1400[clinic start generated code]*/
1401
1402static int
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
1432Get a character (string) from terminal keyboard.
1433
1434Returning a string instead of an integer, as getch() does.  Function keys,
1435keypad keys and other special keys return a multibyte string containing the
1436key name.  In no-delay mode, an exception is raised if there is no input.
1437[clinic start generated code]*/
1438
1439static PyObject *
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
1489Get a wide character from terminal keyboard.
1490
1491Return a character for most keys, or an integer for function keys,
1492keypad keys, and other special keys.
1493[clinic start generated code]*/
1494
1495static PyObject *
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
1540Read a string from the user, with primitive line editing capacity.
1541[-clinic start generated code]*/
1542
1543static PyObject *
1544PyCursesWindow_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
1626Display a horizontal line.
1627[clinic start generated code]*/
1628
1629static PyObject *
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
1666Insert a character before the current or specified position.
1667
1668All characters to the right of the cursor are shifted one position right, with
1669the rightmost characters on the line being lost.
1670[clinic start generated code]*/
1671
1672static PyObject *
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
1705Return the character at the given position in the window.
1706
1707The bottom 8 bits are the character proper, and upper bits are the attributes.
1708[clinic start generated code]*/
1709
1710static unsigned long
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
1740Return a string of characters, extracted from the window.
1741
1742Return a string of characters, extracted from the window starting at the
1743current cursor position, or at y, x if specified.  Attributes are stripped
1744from the characters.  If n is specified, instr() returns a string at most
1745n characters long (exclusive of the trailing NUL).
1746[-clinic start generated code]*/
1747static PyObject *
1748PyCursesWindow_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
1809Insert the string before the current or specified position.
1810
1811Insert a character string (as many characters as will fit on the line)
1812before the character under the cursor.  All characters to the right of
1813the cursor are shifted right, with the rightmost characters on the line
1814being lost.  The cursor position does not change (after moving to y, x,
1815if specified).
1816[clinic start generated code]*/
1817
1818static PyObject *
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
1893Insert at most n characters of the string.
1894
1895Insert a character string (as many characters as will fit on the line)
1896before the character under the cursor, up to n characters.  If n is zero
1897or negative, the entire string is inserted.  All characters to the right
1898of the cursor are shifted right, with the rightmost characters on the line
1899being lost.  The cursor position does not change (after moving to y, x, if
1900specified).
1901[clinic start generated code]*/
1902
1903static PyObject *
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
1963Return True if the specified line was modified, otherwise return False.
1964
1965Raise a curses.error exception if line is not valid for the given window.
1966[clinic start generated code]*/
1967
1968static PyObject *
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
1996Mark for refresh but wait.
1997
1998This function updates the data structure representing the desired state of the
1999window, but does not force an update of the physical screen.  To accomplish
2000that, call doupdate().
2001[clinic start generated code]*/
2002
2003static PyObject *
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
2013Mark for refresh but wait.
2014
2015This function updates the data structure representing the desired state of the
2016window, but does not force an update of the physical screen.  To accomplish
2017that, call doupdate().
2018[clinic start generated code]*/
2019
2020static 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
2068Overlay the window on top of destwin.
2069
2070The windows need not be the same size, only the overlapping region is copied.
2071This copy is non-destructive, which means that the current background
2072character does not overwrite the old contents of destwin.
2073
2074To get fine-grained control over the copied region, the second form of
2075overlay() can be used.  sminrow and smincol are the upper-left coordinates
2076of the source window, and the other variables mark a rectangle in the
2077destination window.
2078[clinic start generated code]*/
2079
2080static PyObject *
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
2115Overwrite the window on top of destwin.
2116
2117The windows need not be the same size, in which case only the overlapping
2118region is copied.  This copy is destructive, which means that the current
2119background character overwrites the old contents of destwin.
2120
2121To get fine-grained control over the copied region, the second form of
2122overwrite() can be used. sminrow and smincol are the upper-left coordinates
2123of the source window, the other variables mark a rectangle in the destination
2124window.
2125[clinic start generated code]*/
2126
2127static PyObject *
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
2154Write all data associated with the window into the provided file object.
2155
2156This information can be later retrieved using the getwin() function.
2157[clinic start generated code]*/
2158
2159static PyObject *
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
2190exit:
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
2204Mark the specified lines corrupted.
2205
2206They should be completely redrawn on the next refresh() call.
2207[clinic start generated code]*/
2208
2209static PyObject *
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
2229Update the display immediately.
2230
2231Synchronize actual screen with previous drawing/deleting methods.
2232The 6 optional arguments can only be specified when the window is a pad
2233created with newpad().  The additional parameters are needed to indicate
2234what part of the pad and screen are involved.  pminrow and pmincol specify
2235the upper left-hand corner of the rectangle to be displayed in the pad.
2236sminrow, smincol, smaxrow, and smaxcol specify the edges of the rectangle to
2237be displayed on the screen.  The lower right-hand corner of the rectangle to
2238be displayed in the pad is calculated from the screen coordinates, since the
2239rectangles must be the same size.  Both rectangles must be entirely contained
2240within their respective structures.  Negative values of pminrow, pmincol,
2241sminrow, or smincol are treated as if they were zero.
2242[clinic start generated code]*/
2243
2244static PyObject *
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
2286Define a software scrolling region.
2287
2288All scrolling actions will take place in this region.
2289[clinic start generated code]*/
2290
2291static PyObject *
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
2314Create a sub-window (screen-relative coordinates).
2315
2316By default, the sub-window will extend from the specified position to the
2317lower right corner of the window.
2318[clinic start generated code]*/
2319
2320static PyObject *
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
2353Scroll the screen or scrolling region.
2354
2355Scroll upward if the argument is positive and downward if it is negative.
2356[clinic start generated code]*/
2357
2358static PyObject *
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
2381Pretend count lines have been changed, starting with line start.
2382
2383If changed is supplied, it specifies whether the affected lines are marked
2384as having been changed (changed=True) or unchanged (changed=False).
2385[clinic start generated code]*/
2386
2387static PyObject *
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
2421Display a vertical line.
2422[clinic start generated code]*/
2423
2424static PyObject *
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
2441static PyObject *
2442PyCursesWindow_get_encoding(PyCursesWindowObject *self, void *closure)
2443{
2444    return PyUnicode_FromString(self->encoding);
2445}
2446
2447static int
2448PyCursesWindow_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
2481static 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
2567static 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
2577PyTypeObject 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
2665static PyObject *
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
2679Return the output speed of the terminal in bits per second.
2680[clinic start generated code]*/
2681
2682static PyObject *
2683_curses_baudrate_impl(PyObject *module)
2684/*[clinic end generated code: output=3c63c6c401d7d9c0 input=921f022ed04a0fd9]*/
2685NoArgReturnIntFunctionBody(baudrate)
2686
2687/*[clinic input]
2688_curses.beep
2689
2690Emit a short attention sound.
2691[clinic start generated code]*/
2692
2693static PyObject *
2694_curses_beep_impl(PyObject *module)
2695/*[clinic end generated code: output=425274962abe49a2 input=a35698ca7d0162bc]*/
2696NoArgNoReturnFunctionBody(beep)
2697
2698/*[clinic input]
2699_curses.can_change_color
2700
2701Return True if the programmer can change the colors displayed by the terminal.
2702[clinic start generated code]*/
2703
2704static PyObject *
2705_curses_can_change_color_impl(PyObject *module)
2706/*[clinic end generated code: output=359df8c3c77d8bf1 input=d7718884de0092f2]*/
2707NoArgTrueFalseFunctionBody(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
2716Enter cbreak mode.
2717
2718In cbreak mode (sometimes called "rare" mode) normal tty line buffering is
2719turned off and characters are available to be read one by one.  However,
2720unlike raw mode, special characters (interrupt, quit, suspend, and flow
2721control) retain their effects on the tty driver and calling program.
2722Calling first raw() then cbreak() leaves the terminal in cbreak mode.
2723[clinic start generated code]*/
2724
2725static PyObject *
2726_curses_cbreak_impl(PyObject *module, int flag)
2727/*[clinic end generated code: output=9f9dee9664769751 input=150be619eb1f1458]*/
2728NoArgOrFlagNoReturnFunctionBody(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
2737Return the red, green, and blue (RGB) components of the specified color.
2738
2739A 3-tuple is returned, containing the R, G, B values for the given color,
2740which will be between 0 (no component) and 1000 (maximum amount of component).
2741[clinic start generated code]*/
2742
2743static 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
2768Return the attribute value for displaying text in the specified color.
2769
2770This attribute value can be combined with A_STANDOUT, A_REVERSE, and the
2771other A_* attributes.  pair_number() is the counterpart to this function.
2772[clinic start generated code]*/
2773
2774static PyObject *
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
2791Set the cursor state.
2792
2793If the terminal supports the visibility requested, the previous cursor
2794state is returned; otherwise, an exception is raised.  On many terminals,
2795the "visible" mode is an underline cursor and the "very visible" mode is
2796a block cursor.
2797[clinic start generated code]*/
2798
2799static PyObject *
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
2816Save the current terminal mode as the "program" mode.
2817
2818The "program" mode is the mode when the running program is using curses.
2819
2820Subsequent calls to reset_prog_mode() will restore this mode.
2821[clinic start generated code]*/
2822
2823static PyObject *
2824_curses_def_prog_mode_impl(PyObject *module)
2825/*[clinic end generated code: output=05d5a351fff874aa input=768b9cace620dda5]*/
2826NoArgNoReturnFunctionBody(def_prog_mode)
2827
2828/*[clinic input]
2829_curses.def_shell_mode
2830
2831Save the current terminal mode as the "shell" mode.
2832
2833The "shell" mode is the mode when the running program is not using curses.
2834
2835Subsequent calls to reset_shell_mode() will restore this mode.
2836[clinic start generated code]*/
2837
2838static PyObject *
2839_curses_def_shell_mode_impl(PyObject *module)
2840/*[clinic end generated code: output=d6e42f5c768f860f input=5ead21f6f0baa894]*/
2841NoArgNoReturnFunctionBody(def_shell_mode)
2842
2843/*[clinic input]
2844_curses.delay_output
2845
2846    ms: int
2847        Duration in milliseconds.
2848    /
2849
2850Insert a pause in output.
2851[clinic start generated code]*/
2852
2853static 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
2865Update the physical screen to match the virtual screen.
2866[clinic start generated code]*/
2867
2868static PyObject *
2869_curses_doupdate_impl(PyObject *module)
2870/*[clinic end generated code: output=f34536975a75680c input=8da80914432a6489]*/
2871NoArgNoReturnFunctionBody(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
2880Enter echo mode.
2881
2882In echo mode, each character input is echoed to the screen as it is entered.
2883[clinic start generated code]*/
2884
2885static PyObject *
2886_curses_echo_impl(PyObject *module, int flag)
2887/*[clinic end generated code: output=03acb2ddfa6c8729 input=2e9e891d637eac5d]*/
2888NoArgOrFlagNoReturnFunctionBody(echo, flag)
2889
2890/*[clinic input]
2891_curses.endwin
2892
2893De-initialize the library, and return terminal to normal status.
2894[clinic start generated code]*/
2895
2896static PyObject *
2897_curses_endwin_impl(PyObject *module)
2898/*[clinic end generated code: output=c0150cd96d2f4128 input=e172cfa43062f3fa]*/
2899NoArgNoReturnFunctionBody(endwin)
2900
2901/*[clinic input]
2902_curses.erasechar
2903
2904Return the user's current erase character.
2905[clinic start generated code]*/
2906
2907static 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
2923Flash the screen.
2924
2925That is, change it to reverse-video and then change it back in a short interval.
2926[clinic start generated code]*/
2927
2928static PyObject *
2929_curses_flash_impl(PyObject *module)
2930/*[clinic end generated code: output=488b8a0ebd9ea9b8 input=02fdfb06c8fc3171]*/
2931NoArgNoReturnFunctionBody(flash)
2932
2933/*[clinic input]
2934_curses.flushinp
2935
2936Flush all input buffers.
2937
2938This throws away any typeahead that has been typed by the user and has not
2939yet been processed by the program.
2940[clinic start generated code]*/
2941
2942static PyObject *
2943_curses_flushinp_impl(PyObject *module)
2944/*[clinic end generated code: output=7e7a1fc1473960f5 input=59d042e705cef5ec]*/
2945NoArgNoReturnVoidFunctionBody(flushinp)
2946
2947#ifdef getsyx
2948/*[clinic input]
2949_curses.getsyx
2950
2951Return the current coordinates of the virtual screen cursor.
2952
2953Return a (y, x) tuple.  If leaveok is currently true, return (-1, -1).
2954[clinic start generated code]*/
2955
2956static 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
2975Retrieve the queued mouse event.
2976
2977After getch() returns KEY_MOUSE to signal a mouse event, this function
2978returns a 5-tuple (id, x, y, z, bstate).
2979[clinic start generated code]*/
2980
2981static PyObject *
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
3011Push a KEY_MOUSE event onto the input queue.
3012
3013The following getmouse() will return the given state data.
3014[clinic start generated code]*/
3015
3016static PyObject *
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
3040Read window related data stored in the file by an earlier putwin() call.
3041
3042The routine then creates and initializes a new window using that data,
3043returning the new window object.
3044[clinic start generated code]*/
3045
3046static PyObject *
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
3092error:
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
3104Enter half-delay mode.
3105
3106Use nocbreak() to leave half-delay mode.
3107[clinic start generated code]*/
3108
3109static PyObject *
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
3121Return True if the terminal can display colors; otherwise, return False.
3122[clinic start generated code]*/
3123
3124static PyObject *
3125_curses_has_colors_impl(PyObject *module)
3126/*[clinic end generated code: output=db5667483139e3e2 input=b2ec41b739d896c6]*/
3127NoArgTrueFalseFunctionBody(has_colors)
3128
3129/*[clinic input]
3130_curses.has_ic
3131
3132Return True if the terminal has insert- and delete-character capabilities.
3133[clinic start generated code]*/
3134
3135static PyObject *
3136_curses_has_ic_impl(PyObject *module)
3137/*[clinic end generated code: output=6be24da9cb1268fe input=9bc2d3a797cc7324]*/
3138NoArgTrueFalseFunctionBody(has_ic)
3139
3140/*[clinic input]
3141_curses.has_il
3142
3143Return True if the terminal has insert- and delete-line capabilities.
3144[clinic start generated code]*/
3145
3146static PyObject *
3147_curses_has_il_impl(PyObject *module)
3148/*[clinic end generated code: output=d45bd7788ff9f5f4 input=cd939d5607ee5427]*/
3149NoArgTrueFalseFunctionBody(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
3159Return True if the current terminal type recognizes a key with that value.
3160[clinic start generated code]*/
3161
3162static 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
3185Change the definition of a color.
3186
3187When init_color() is used, all occurrences of that color on the screen
3188immediately change to the new definition.  This function is a no-op on
3189most terminals; it is active only if can_change_color() returns true.
3190[clinic start generated code]*/
3191
3192static PyObject *
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
3215Change the definition of a color-pair.
3216
3217If the color-pair was previously initialized, the screen is refreshed and
3218all occurrences of that color-pair are changed to the new definition.
3219[clinic start generated code]*/
3220
3221static PyObject *
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
3244static PyObject *ModDict;
3245
3246/*[clinic input]
3247_curses.initscr
3248
3249Initialize the library.
3250
3251Return a WindowObject which represents the whole screen.
3252[clinic start generated code]*/
3253
3254static PyObject *
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
3370Initialize the terminal.
3371[clinic start generated code]*/
3372
3373static PyObject *
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
3422Gets the curses ESCDELAY setting.
3423
3424Gets the number of milliseconds to wait after reading an escape character,
3425to distinguish between an individual escape character entered on the
3426keyboard from escape sequences sent by cursor and function keys.
3427[clinic start generated code]*/
3428
3429static PyObject *
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
3441Sets the curses ESCDELAY setting.
3442
3443Sets the number of milliseconds to wait after reading an escape character,
3444to distinguish between an individual escape character entered on the
3445keyboard from escape sequences sent by cursor and function keys.
3446[clinic start generated code]*/
3447
3448static PyObject *
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
3463Gets the curses TABSIZE setting.
3464
3465Gets the number of columns used by the curses library when converting a tab
3466character to spaces as it adds the tab to a window.
3467[clinic start generated code]*/
3468
3469static PyObject *
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
3481Sets the curses TABSIZE setting.
3482
3483Sets the number of columns used by the curses library when converting a tab
3484character to spaces as it adds the tab to a window.
3485[clinic start generated code]*/
3486
3487static PyObject *
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
3508static PyObject *
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
3520Return True if endwin() has been called.
3521[clinic start generated code]*/
3522
3523static PyObject *
3524_curses_isendwin_impl(PyObject *module)
3525/*[clinic end generated code: output=d73179e4a7e1eb8c input=6cdb01a7ebf71397]*/
3526NoArgTrueFalseFunctionBody(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
3538Return True if resize_term() would modify the window structure, False otherwise.
3539[clinic start generated code]*/
3540
3541static 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
3558Return the name of specified key.
3559[clinic start generated code]*/
3560
3561static PyObject *
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
3581Return the user's current line kill character.
3582[clinic start generated code]*/
3583
3584static PyObject *
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
3598Return the terminfo long name field describing the current terminal.
3599
3600The maximum length of a verbose description is 128 characters.  It is defined
3601only after the call to initscr().
3602[clinic start generated code]*/
3603
3604static PyObject *
3605_curses_longname_impl(PyObject *module)
3606/*[clinic end generated code: output=fdf30433727ef568 input=84c3f20201b1098e]*/
3607NoArgReturnStringFunctionBody(longname)
3608
3609/*[clinic input]
3610_curses.meta
3611
3612    yes: bool(accept={int})
3613    /
3614
3615Enable/disable meta keys.
3616
3617If yes is True, allow 8-bit characters to be input.  If yes is False,
3618allow only 7-bit characters.
3619[clinic start generated code]*/
3620
3621static 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
3638Set and retrieve the maximum time between press and release in a click.
3639
3640Set the maximum time that can elapse between press and release events in
3641order for them to be recognized as a click, and return the previous interval
3642value.
3643[clinic start generated code]*/
3644
3645static PyObject *
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
3660Set the mouse events to be reported, and return a tuple (availmask, oldmask).
3661
3662Return a tuple (availmask, oldmask).  availmask indicates which of the
3663specified mouse events can be reported; on complete failure it returns 0.
3664oldmask is the previous value of the given window's mouse event mask.
3665If this function is never called, no mouse events are ever reported.
3666[clinic start generated code]*/
3667
3668static PyObject *
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
3688Sleep for specified time.
3689[clinic start generated code]*/
3690
3691static PyObject *
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
3710Create and return a pointer to a new pad data structure.
3711[clinic start generated code]*/
3712
3713static PyObject *
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
3746Return a new window.
3747
3748By default, the window will extend from the specified position to the lower
3749right corner of the screen.
3750[clinic start generated code]*/
3751
3752static PyObject *
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
3777Enter newline mode.
3778
3779This mode translates the return key into newline on input, and translates
3780newline into return and line-feed on output.  Newline mode is initially on.
3781[clinic start generated code]*/
3782
3783static PyObject *
3784_curses_nl_impl(PyObject *module, int flag)
3785/*[clinic end generated code: output=b39cc0ffc9015003 input=cf36a63f7b86e28a]*/
3786NoArgOrFlagNoReturnFunctionBody(nl, flag)
3787
3788/*[clinic input]
3789_curses.nocbreak
3790
3791Leave cbreak mode.
3792
3793Return to normal "cooked" mode with line buffering.
3794[clinic start generated code]*/
3795
3796static PyObject *
3797_curses_nocbreak_impl(PyObject *module)
3798/*[clinic end generated code: output=eabf3833a4fbf620 input=e4b65f7d734af400]*/
3799NoArgNoReturnFunctionBody(nocbreak)
3800
3801/*[clinic input]
3802_curses.noecho
3803
3804Leave echo mode.
3805
3806Echoing of input characters is turned off.
3807[clinic start generated code]*/
3808
3809static PyObject *
3810_curses_noecho_impl(PyObject *module)
3811/*[clinic end generated code: output=cc95ab45bc98f41b input=76714df529e614c3]*/
3812NoArgNoReturnFunctionBody(noecho)
3813
3814/*[clinic input]
3815_curses.nonl
3816
3817Leave newline mode.
3818
3819Disable translation of return into newline on input, and disable low-level
3820translation of newline into newline/return on output.
3821[clinic start generated code]*/
3822
3823static PyObject *
3824_curses_nonl_impl(PyObject *module)
3825/*[clinic end generated code: output=99e917e9715770c6 input=9d37dd122d3022fc]*/
3826NoArgNoReturnFunctionBody(nonl)
3827
3828/*[clinic input]
3829_curses.noqiflush
3830
3831Disable queue flushing.
3832
3833When queue flushing is disabled, normal flush of input and output queues
3834associated with the INTR, QUIT and SUSP characters will not be done.
3835[clinic start generated code]*/
3836
3837static PyObject *
3838_curses_noqiflush_impl(PyObject *module)
3839/*[clinic end generated code: output=8b95a4229bbf0877 input=ba3e6b2e3e54c4df]*/
3840NoArgNoReturnVoidFunctionBody(noqiflush)
3841
3842/*[clinic input]
3843_curses.noraw
3844
3845Leave raw mode.
3846
3847Return to normal "cooked" mode with line buffering.
3848[clinic start generated code]*/
3849
3850static PyObject *
3851_curses_noraw_impl(PyObject *module)
3852/*[clinic end generated code: output=39894e5524c430cc input=6ec86692096dffb5]*/
3853NoArgNoReturnFunctionBody(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
3862Return a tuple (fg, bg) containing the colors for the requested color pair.
3863[clinic start generated code]*/
3864
3865static 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
3896Return the number of the color-pair set by the specified attribute value.
3897
3898color_pair() is the counterpart to this function.
3899[clinic start generated code]*/
3900
3901static PyObject *
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
3917Emit the value of a specified terminfo capability for the current terminal.
3918
3919Note that the output of putp() always goes to standard output.
3920[clinic start generated code]*/
3921
3922static PyObject *
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
3936Enable queue flushing.
3937
3938If queue flushing is enabled, all output in the display driver queue
3939will be flushed when the INTR, QUIT and SUSP characters are read.
3940[clinic start generated code]*/
3941
3942static PyObject *
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)
3960static int
3961update_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
4013static PyObject *
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
4032Enter raw mode.
4033
4034In raw mode, normal line buffering and processing of interrupt, quit,
4035suspend, and flow control keys are turned off; characters are presented to
4036curses input functions one by one.
4037[clinic start generated code]*/
4038
4039static PyObject *
4040_curses_raw_impl(PyObject *module, int flag)
4041/*[clinic end generated code: output=a750e4b342be015b input=e36d8db27832b848]*/
4042NoArgOrFlagNoReturnFunctionBody(raw, flag)
4043
4044/*[clinic input]
4045_curses.reset_prog_mode
4046
4047Restore the terminal to "program" mode, as previously saved by def_prog_mode().
4048[clinic start generated code]*/
4049
4050static PyObject *
4051_curses_reset_prog_mode_impl(PyObject *module)
4052/*[clinic end generated code: output=15eb765abf0b6575 input=3d82bea2b3243471]*/
4053NoArgNoReturnFunctionBody(reset_prog_mode)
4054
4055/*[clinic input]
4056_curses.reset_shell_mode
4057
4058Restore the terminal to "shell" mode, as previously saved by def_shell_mode().
4059[clinic start generated code]*/
4060
4061static PyObject *
4062_curses_reset_shell_mode_impl(PyObject *module)
4063/*[clinic end generated code: output=0238de2962090d33 input=1c738fa64bd1a24f]*/
4064NoArgNoReturnFunctionBody(reset_shell_mode)
4065
4066/*[clinic input]
4067_curses.resetty
4068
4069Restore terminal mode.
4070[clinic start generated code]*/
4071
4072static PyObject *
4073_curses_resetty_impl(PyObject *module)
4074/*[clinic end generated code: output=ff4b448e80a7cd63 input=940493de03624bb0]*/
4075NoArgNoReturnFunctionBody(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
4087Resize the standard and current windows to the specified dimensions.
4088
4089Adjusts other bookkeeping data used by the curses library that record the
4090window dimensions (in particular the SIGWINCH handler).
4091[clinic start generated code]*/
4092
4093static 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
4123Backend function used by resizeterm(), performing most of the work.
4124
4125When resizing the windows, resize_term() blank-fills the areas that are
4126extended.  The calling application should fill in these areas with appropriate
4127data.  The resize_term() function attempts to resize all windows.  However,
4128due to the calling convention of pads, it is not possible to resize these
4129without additional interaction with the application.
4130[clinic start generated code]*/
4131
4132static PyObject *
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
4154Save terminal mode.
4155[clinic start generated code]*/
4156
4157static PyObject *
4158_curses_savetty_impl(PyObject *module)
4159/*[clinic end generated code: output=6babc49f12b42199 input=fce6b2b7d2200102]*/
4160NoArgNoReturnFunctionBody(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
4172Set the virtual screen cursor.
4173
4174If y and x are both -1, then leaveok is set.
4175[clinic start generated code]*/
4176
4177static 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
4192Initializes eight basic colors and global variables COLORS and COLOR_PAIRS.
4193
4194Must be called if the programmer wants to use colors, and before any other
4195color manipulation routine is called.  It is good practice to call this
4196routine right after initscr().
4197
4198It also restores the colors on the terminal to the values they had when the
4199terminal was just turned on.
4200[clinic start generated code]*/
4201
4202static PyObject *
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
4240Return a logical OR of all video attributes supported by the terminal.
4241[clinic start generated code]*/
4242
4243static PyObject *
4244_curses_termattrs_impl(PyObject *module)
4245/*[clinic end generated code: output=b06f437fce1b6fc4 input=0559882a04f84d1d]*/
4246NoArgReturnIntFunctionBody(termattrs)
4247
4248/*[clinic input]
4249_curses.termname
4250
4251Return the value of the environment variable TERM, truncated to 14 characters.
4252[clinic start generated code]*/
4253
4254static PyObject *
4255_curses_termname_impl(PyObject *module)
4256/*[clinic end generated code: output=96375577ebbd67fd input=33c08d000944f33f]*/
4257NoArgReturnStringFunctionBody(termname)
4258
4259/*[clinic input]
4260_curses.tigetflag
4261
4262    capname: str
4263        The terminfo capability name.
4264    /
4265
4266Return the value of the Boolean capability.
4267
4268The value -1 is returned if capname is not a Boolean capability, or 0 if
4269it is canceled or absent from the terminal description.
4270[clinic start generated code]*/
4271
4272static 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
4288Return the value of the numeric capability.
4289
4290The value -2 is returned if capname is not a numeric capability, or -1 if
4291it is canceled or absent from the terminal description.
4292[clinic start generated code]*/
4293
4294static PyObject *
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
4310Return the value of the string capability.
4311
4312None is returned if capname is not a string capability, or is canceled or
4313absent from the terminal description.
4314[clinic start generated code]*/
4315
4316static PyObject *
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
4345Instantiate the specified byte string with the supplied parameters.
4346[clinic start generated code]*/
4347
4348static PyObject *
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
4374Specify that the file descriptor fd be used for typeahead checking.
4375
4376If fd is -1, then no typeahead checking is done.
4377[clinic start generated code]*/
4378
4379static PyObject *
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
4395Return a string which is a printable representation of the character ch.
4396
4397Control characters are displayed as a caret followed by the character,
4398for example as ^C.  Printing characters are left as they are.
4399[clinic start generated code]*/
4400
4401static PyObject *
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
4421Push ch so the next getch() will return it.
4422[clinic start generated code]*/
4423
4424static PyObject *
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. */
4445static int
4446PyCurses_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
4492Push ch so the next get_wch() will return it.
4493[clinic start generated code]*/
4494
4495static PyObject *
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
4516Use environment variables LINES and COLUMNS.
4517
4518If used, this function should be called before initscr() or newterm() are
4519called.
4520
4521When flag is False, the values of lines and columns specified in the terminfo
4522database will be used, even if environment variables LINES and COLUMNS (used
4523by default) are set, or if curses is running in a window (in which case
4524default behavior would be to use the window size if LINES and COLUMNS are
4525not set).
4526[clinic start generated code]*/
4527
4528static PyObject *
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
4541Allow use of default values for colors on terminals supporting this feature.
4542
4543Use this to support transparency in your application.  The default color
4544is assigned to the color number -1.
4545[clinic start generated code]*/
4546
4547static PyObject *
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
4569PyDoc_STRVAR(ncurses_version__doc__,
4570"curses.ncurses_version\n\
4571\n\
4572Ncurses version information as a named tuple.");
4573
4574static PyStructSequence_Field ncurses_version_fields[] = {
4575    {"major", "Major release number"},
4576    {"minor", "Minor release number"},
4577    {"patch", "Patch release number"},
4578    {0}
4579};
4580
4581static PyStructSequence_Desc ncurses_version_desc = {
4582    "curses.ncurses_version",  /* name */
4583    ncurses_version__doc__,    /* doc */
4584    ncurses_version_fields,    /* fields */
4585    3
4586};
4587
4588static PyObject *
4589make_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
4619Return True if the module supports extended colors; otherwise, return False.
4620
4621Extended color support allows more than 256 color-pairs for terminals
4622that support more than 16 colors (e.g. xterm-256color).
4623[clinic start generated code]*/
4624
4625static PyObject *
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
4634static 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
4722static 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
4734static void
4735curses_destructor(PyObject *op)
4736{
4737    void *ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME);
4738    Py_DECREF(*(void **)ptr);
4739    PyMem_Free(ptr);
4740}
4741
4742PyMODINIT_FUNC
4743PyInit__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