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