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