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=88c860abdbb50e0c]*/
142 
143 #include "clinic/_cursesmodule.c.h"
144 
145 /* Definition of exception curses.error */
146 
147 static PyObject *PyCursesError;
148 
149 /* Tells whether setupterm() has been called to initialise terminfo.  */
150 static int initialised_setupterm = FALSE;
151 
152 /* Tells whether initscr() has been called to initialise curses.  */
153 static int initialised = FALSE;
154 
155 /* Tells whether start_color() has been called to initialise color usage. */
156 static int initialisedcolors = FALSE;
157 
158 static char *screen_encoding = NULL;
159 
160 /* Utility Macros */
161 #define PyCursesSetupTermCalled                                         \
162     if (initialised_setupterm != TRUE) {                                \
163         PyErr_SetString(PyCursesError,                                  \
164                         "must call (at least) setupterm() first");      \
165         return 0; }
166 
167 #define PyCursesInitialised                             \
168     if (initialised != TRUE) {                          \
169         PyErr_SetString(PyCursesError,                  \
170                         "must call initscr() first");   \
171         return 0; }
172 
173 #define PyCursesInitialisedColor                                \
174     if (initialisedcolors != TRUE) {                            \
175         PyErr_SetString(PyCursesError,                          \
176                         "must call start_color() first");       \
177         return 0; }
178 
179 /* Utility Functions */
180 
181 static inline int
color_pair_to_attr(short color_number)182 color_pair_to_attr(short color_number)
183 {
184     return ((int)color_number << 8);
185 }
186 
187 static inline short
attr_to_color_pair(int attr)188 attr_to_color_pair(int attr)
189 {
190     return (short)((attr & A_COLOR) >> 8);
191 }
192 
193 /*
194  * Check the return code from a curses function and return None
195  * or raise an exception as appropriate.  These are exported using the
196  * capsule API.
197  */
198 
199 static PyObject *
PyCursesCheckERR(int code,const char * fname)200 PyCursesCheckERR(int code, const char *fname)
201 {
202     if (code != ERR) {
203         Py_RETURN_NONE;
204     } else {
205         if (fname == NULL) {
206             PyErr_SetString(PyCursesError, catchall_ERR);
207         } else {
208             PyErr_Format(PyCursesError, "%s() returned ERR", fname);
209         }
210         return NULL;
211     }
212 }
213 
214 /* Convert an object to a byte (an integer of type chtype):
215 
216    - int
217    - bytes of length 1
218    - str of length 1
219 
220    Return 1 on success, 0 on error (invalid type or integer overflow). */
221 static int
PyCurses_ConvertToChtype(PyCursesWindowObject * win,PyObject * obj,chtype * ch)222 PyCurses_ConvertToChtype(PyCursesWindowObject *win, PyObject *obj, chtype *ch)
223 {
224     long value;
225     if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) {
226         value = (unsigned char)PyBytes_AsString(obj)[0];
227     }
228     else if (PyUnicode_Check(obj)) {
229         if (PyUnicode_GetLength(obj) != 1) {
230             PyErr_Format(PyExc_TypeError,
231                          "expect bytes or str of length 1, or int, "
232                          "got a str of length %zi",
233                          PyUnicode_GET_LENGTH(obj));
234             return 0;
235         }
236         value = PyUnicode_READ_CHAR(obj, 0);
237         if (128 < value) {
238             PyObject *bytes;
239             const char *encoding;
240             if (win)
241                 encoding = win->encoding;
242             else
243                 encoding = screen_encoding;
244             bytes = PyUnicode_AsEncodedString(obj, encoding, NULL);
245             if (bytes == NULL)
246                 return 0;
247             if (PyBytes_GET_SIZE(bytes) == 1)
248                 value = (unsigned char)PyBytes_AS_STRING(bytes)[0];
249             else
250                 value = -1;
251             Py_DECREF(bytes);
252             if (value < 0)
253                 goto overflow;
254         }
255     }
256     else if (PyLong_CheckExact(obj)) {
257         int long_overflow;
258         value = PyLong_AsLongAndOverflow(obj, &long_overflow);
259         if (long_overflow)
260             goto overflow;
261     }
262     else {
263         PyErr_Format(PyExc_TypeError,
264                      "expect bytes or str of length 1, or int, got %s",
265                      Py_TYPE(obj)->tp_name);
266         return 0;
267     }
268     *ch = (chtype)value;
269     if ((long)*ch != value)
270         goto overflow;
271     return 1;
272 
273 overflow:
274     PyErr_SetString(PyExc_OverflowError,
275                     "byte doesn't fit in chtype");
276     return 0;
277 }
278 
279 /* Convert an object to a byte (chtype) or a character (cchar_t):
280 
281     - int
282     - bytes of length 1
283     - str of length 1
284 
285    Return:
286 
287     - 2 if obj is a character (written into *wch)
288     - 1 if obj is a byte (written into *ch)
289     - 0 on error: raise an exception */
290 static int
PyCurses_ConvertToCchar_t(PyCursesWindowObject * win,PyObject * obj,chtype * ch,wchar_t * wch)291 PyCurses_ConvertToCchar_t(PyCursesWindowObject *win, PyObject *obj,
292                           chtype *ch
293 #ifdef HAVE_NCURSESW
294                           , wchar_t *wch
295 #endif
296                           )
297 {
298     long value;
299 #ifdef HAVE_NCURSESW
300     wchar_t buffer[2];
301 #endif
302 
303     if (PyUnicode_Check(obj)) {
304 #ifdef HAVE_NCURSESW
305         if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) {
306             PyErr_Format(PyExc_TypeError,
307                          "expect bytes or str of length 1, or int, "
308                          "got a str of length %zi",
309                          PyUnicode_GET_LENGTH(obj));
310             return 0;
311         }
312         *wch = buffer[0];
313         return 2;
314 #else
315         return PyCurses_ConvertToChtype(win, obj, ch);
316 #endif
317     }
318     else if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) {
319         value = (unsigned char)PyBytes_AsString(obj)[0];
320     }
321     else if (PyLong_CheckExact(obj)) {
322         int overflow;
323         value = PyLong_AsLongAndOverflow(obj, &overflow);
324         if (overflow) {
325             PyErr_SetString(PyExc_OverflowError,
326                             "int doesn't fit in long");
327             return 0;
328         }
329     }
330     else {
331         PyErr_Format(PyExc_TypeError,
332                      "expect bytes or str of length 1, or int, got %s",
333                      Py_TYPE(obj)->tp_name);
334         return 0;
335     }
336 
337     *ch = (chtype)value;
338     if ((long)*ch != value) {
339         PyErr_Format(PyExc_OverflowError,
340                      "byte doesn't fit in chtype");
341         return 0;
342     }
343     return 1;
344 }
345 
346 /* Convert an object to a byte string (char*) or a wide character string
347    (wchar_t*). Return:
348 
349     - 2 if obj is a character string (written into *wch)
350     - 1 if obj is a byte string (written into *bytes)
351     - 0 on error: raise an exception */
352 static int
PyCurses_ConvertToString(PyCursesWindowObject * win,PyObject * obj,PyObject ** bytes,wchar_t ** wstr)353 PyCurses_ConvertToString(PyCursesWindowObject *win, PyObject *obj,
354                          PyObject **bytes, wchar_t **wstr)
355 {
356     char *str;
357     if (PyUnicode_Check(obj)) {
358 #ifdef HAVE_NCURSESW
359         assert (wstr != NULL);
360 
361         *wstr = PyUnicode_AsWideCharString(obj, NULL);
362         if (*wstr == NULL)
363             return 0;
364         return 2;
365 #else
366         assert (wstr == NULL);
367         *bytes = PyUnicode_AsEncodedString(obj, win->encoding, NULL);
368         if (*bytes == NULL)
369             return 0;
370         /* check for embedded null bytes */
371         if (PyBytes_AsStringAndSize(*bytes, &str, NULL) < 0) {
372             return 0;
373         }
374         return 1;
375 #endif
376     }
377     else if (PyBytes_Check(obj)) {
378         Py_INCREF(obj);
379         *bytes = obj;
380         /* check for embedded null bytes */
381         if (PyBytes_AsStringAndSize(*bytes, &str, NULL) < 0) {
382             return 0;
383         }
384         return 1;
385     }
386 
387     PyErr_Format(PyExc_TypeError, "expect bytes or str, got %s",
388                  Py_TYPE(obj)->tp_name);
389     return 0;
390 }
391 
392 /* Function versions of the 3 functions for testing whether curses has been
393    initialised or not. */
394 
func_PyCursesSetupTermCalled(void)395 static int func_PyCursesSetupTermCalled(void)
396 {
397     PyCursesSetupTermCalled;
398     return 1;
399 }
400 
func_PyCursesInitialised(void)401 static int func_PyCursesInitialised(void)
402 {
403     PyCursesInitialised;
404     return 1;
405 }
406 
func_PyCursesInitialisedColor(void)407 static int func_PyCursesInitialisedColor(void)
408 {
409     PyCursesInitialisedColor;
410     return 1;
411 }
412 
413 /*****************************************************************************
414  The Window Object
415 ******************************************************************************/
416 
417 /* Definition of the window type */
418 
419 PyTypeObject PyCursesWindow_Type;
420 
421 /* Function prototype macros for Window object
422 
423    X - function name
424    TYPE - parameter Type
425    ERGSTR - format string for construction of the return value
426    PARSESTR - format string for argument parsing
427 */
428 
429 #define Window_NoArgNoReturnFunction(X)                         \
430     static PyObject *PyCursesWindow_ ## X                       \
431     (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored))  \
432     { return PyCursesCheckERR(X(self->win), # X); }
433 
434 #define Window_NoArgTrueFalseFunction(X)                                \
435     static PyObject * PyCursesWindow_ ## X                              \
436     (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored))          \
437     {                                                                   \
438         if (X (self->win) == FALSE) { Py_RETURN_FALSE; } \
439         else { Py_RETURN_TRUE; } }
440 
441 #define Window_NoArgNoReturnVoidFunction(X)                     \
442     static PyObject * PyCursesWindow_ ## X                      \
443     (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored))  \
444     {                                                           \
445         X(self->win); Py_RETURN_NONE; }
446 
447 #define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR)               \
448     static PyObject * PyCursesWindow_ ## X                              \
449     (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored))          \
450     {                                                                   \
451         TYPE arg1, arg2;                                                \
452         X(self->win,arg1,arg2); return Py_BuildValue(ERGSTR, arg1, arg2); }
453 
454 #define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR)            \
455     static PyObject * PyCursesWindow_ ## X                              \
456     (PyCursesWindowObject *self, PyObject *args)                        \
457     {                                                                   \
458         TYPE arg1;                                                      \
459         if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) return NULL;      \
460         X(self->win,arg1); Py_RETURN_NONE; }
461 
462 #define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR)                \
463     static PyObject * PyCursesWindow_ ## X                              \
464     (PyCursesWindowObject *self, PyObject *args)                        \
465     {                                                                   \
466         TYPE arg1;                                                      \
467         if (!PyArg_ParseTuple(args,PARSESTR, &arg1)) return NULL;       \
468         return PyCursesCheckERR(X(self->win, arg1), # X); }
469 
470 #define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR)                \
471     static PyObject * PyCursesWindow_ ## X                              \
472     (PyCursesWindowObject *self, PyObject *args)                        \
473     {                                                                   \
474         TYPE arg1, arg2;                                                \
475         if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) return NULL; \
476         return PyCursesCheckERR(X(self->win, arg1, arg2), # X); }
477 
478 /* ------------- WINDOW routines --------------- */
479 
480 Window_NoArgNoReturnFunction(untouchwin)
Window_NoArgNoReturnFunction(touchwin)481 Window_NoArgNoReturnFunction(touchwin)
482 Window_NoArgNoReturnFunction(redrawwin)
483 Window_NoArgNoReturnFunction(winsertln)
484 Window_NoArgNoReturnFunction(werase)
485 Window_NoArgNoReturnFunction(wdeleteln)
486 
487 Window_NoArgTrueFalseFunction(is_wintouched)
488 
489 Window_NoArgNoReturnVoidFunction(wsyncup)
490 Window_NoArgNoReturnVoidFunction(wsyncdown)
491 Window_NoArgNoReturnVoidFunction(wstandend)
492 Window_NoArgNoReturnVoidFunction(wstandout)
493 Window_NoArgNoReturnVoidFunction(wcursyncup)
494 Window_NoArgNoReturnVoidFunction(wclrtoeol)
495 Window_NoArgNoReturnVoidFunction(wclrtobot)
496 Window_NoArgNoReturnVoidFunction(wclear)
497 
498 Window_OneArgNoReturnVoidFunction(idcok, int, "i;True(1) or False(0)")
499 #ifdef HAVE_CURSES_IMMEDOK
500 Window_OneArgNoReturnVoidFunction(immedok, int, "i;True(1) or False(0)")
501 #endif
502 Window_OneArgNoReturnVoidFunction(wtimeout, int, "i;delay")
503 
504 Window_NoArg2TupleReturnFunction(getyx, int, "ii")
505 Window_NoArg2TupleReturnFunction(getbegyx, int, "ii")
506 Window_NoArg2TupleReturnFunction(getmaxyx, int, "ii")
507 Window_NoArg2TupleReturnFunction(getparyx, int, "ii")
508 
509 Window_OneArgNoReturnFunction(clearok, int, "i;True(1) or False(0)")
510 Window_OneArgNoReturnFunction(idlok, int, "i;True(1) or False(0)")
511 Window_OneArgNoReturnFunction(keypad, int, "i;True(1) or False(0)")
512 Window_OneArgNoReturnFunction(leaveok, int, "i;True(1) or False(0)")
513 Window_OneArgNoReturnFunction(nodelay, int, "i;True(1) or False(0)")
514 Window_OneArgNoReturnFunction(notimeout, int, "i;True(1) or False(0)")
515 Window_OneArgNoReturnFunction(scrollok, int, "i;True(1) or False(0)")
516 Window_OneArgNoReturnFunction(winsdelln, int, "i;nlines")
517 #ifdef HAVE_CURSES_SYNCOK
518 Window_OneArgNoReturnFunction(syncok, int, "i;True(1) or False(0)")
519 #endif
520 
521 Window_TwoArgNoReturnFunction(mvwin, int, "ii;y,x")
522 Window_TwoArgNoReturnFunction(mvderwin, int, "ii;y,x")
523 Window_TwoArgNoReturnFunction(wmove, int, "ii;y,x")
524 #ifndef STRICT_SYSV_CURSES
525 Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns")
526 #endif
527 
528 /* Allocation and deallocation of Window Objects */
529 
530 static PyObject *
531 PyCursesWindow_New(WINDOW *win, const char *encoding)
532 {
533     PyCursesWindowObject *wo;
534 
535     if (encoding == NULL) {
536 #if defined(MS_WINDOWS)
537         char *buffer[100];
538         UINT cp;
539         cp = GetConsoleOutputCP();
540         if (cp != 0) {
541             PyOS_snprintf(buffer, sizeof(buffer), "cp%u", cp);
542             encoding = buffer;
543         }
544 #elif defined(CODESET)
545         const char *codeset = nl_langinfo(CODESET);
546         if (codeset != NULL && codeset[0] != 0)
547             encoding = codeset;
548 #endif
549         if (encoding == NULL)
550             encoding = "utf-8";
551     }
552 
553     wo = PyObject_NEW(PyCursesWindowObject, &PyCursesWindow_Type);
554     if (wo == NULL) return NULL;
555     wo->win = win;
556     wo->encoding = _PyMem_Strdup(encoding);
557     if (wo->encoding == NULL) {
558         Py_DECREF(wo);
559         PyErr_NoMemory();
560         return NULL;
561     }
562     return (PyObject *)wo;
563 }
564 
565 static void
PyCursesWindow_Dealloc(PyCursesWindowObject * wo)566 PyCursesWindow_Dealloc(PyCursesWindowObject *wo)
567 {
568     if (wo->win != stdscr) delwin(wo->win);
569     if (wo->encoding != NULL)
570         PyMem_Free(wo->encoding);
571     PyObject_DEL(wo);
572 }
573 
574 /* Addch, Addstr, Addnstr */
575 
576 /*[clinic input]
577 
578 curses.window.addch
579 
580     [
581     y: int
582       Y-coordinate.
583     x: int
584       X-coordinate.
585     ]
586 
587     ch: object
588       Character to add.
589 
590     [
591     attr: long
592       Attributes for the character.
593     ]
594     /
595 
596 Paint character ch at (y, x) with attributes attr.
597 
598 Paint character ch at (y, x) with attributes attr,
599 overwriting any character previously painted at that location.
600 By default, the character position and attributes are the
601 current settings for the window object.
602 [clinic start generated code]*/
603 
604 static PyObject *
curses_window_addch_impl(PyCursesWindowObject * self,int group_left_1,int y,int x,PyObject * ch,int group_right_1,long attr)605 curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y,
606                          int x, PyObject *ch, int group_right_1, long attr)
607 /*[clinic end generated code: output=99f7f85078ec06c3 input=5a41efb34a2de338]*/
608 {
609     PyCursesWindowObject *cwself = (PyCursesWindowObject *)self;
610     int coordinates_group = group_left_1;
611     int attr_group = group_right_1;
612     int rtn;
613     int type;
614     chtype cch = 0;
615 #ifdef HAVE_NCURSESW
616     wchar_t wstr[2];
617     cchar_t wcval;
618 #endif
619     const char *funcname;
620 
621     if (!attr_group)
622       attr = A_NORMAL;
623 
624 #ifdef HAVE_NCURSESW
625     type = PyCurses_ConvertToCchar_t(cwself, ch, &cch, wstr);
626     if (type == 2) {
627         funcname = "add_wch";
628         wstr[1] = L'\0';
629         setcchar(&wcval, wstr, attr, attr_to_color_pair(attr), NULL);
630         if (coordinates_group)
631             rtn = mvwadd_wch(cwself->win,y,x, &wcval);
632         else {
633             rtn = wadd_wch(cwself->win, &wcval);
634         }
635     }
636     else
637 #else
638     type = PyCurses_ConvertToCchar_t(cwself, ch, &cch);
639 #endif
640     if (type == 1) {
641         funcname = "addch";
642         if (coordinates_group)
643             rtn = mvwaddch(cwself->win,y,x, cch | attr);
644         else {
645             rtn = waddch(cwself->win, cch | attr);
646         }
647     }
648     else {
649         return NULL;
650     }
651     return PyCursesCheckERR(rtn, funcname);
652 }
653 
654 static PyObject *
PyCursesWindow_AddStr(PyCursesWindowObject * self,PyObject * args)655 PyCursesWindow_AddStr(PyCursesWindowObject *self, PyObject *args)
656 {
657     int rtn;
658     int x, y;
659     int strtype;
660     PyObject *strobj, *bytesobj = NULL;
661 #ifdef HAVE_NCURSESW
662     wchar_t *wstr = NULL;
663 #endif
664     attr_t attr = A_NORMAL , attr_old = A_NORMAL;
665     long lattr;
666     int use_xy = FALSE, use_attr = FALSE;
667     const char *funcname;
668 
669     switch (PyTuple_Size(args)) {
670     case 1:
671         if (!PyArg_ParseTuple(args,"O;str", &strobj))
672             return NULL;
673         break;
674     case 2:
675         if (!PyArg_ParseTuple(args,"Ol;str,attr", &strobj, &lattr))
676             return NULL;
677         attr = lattr;
678         use_attr = TRUE;
679         break;
680     case 3:
681         if (!PyArg_ParseTuple(args,"iiO;int,int,str", &y, &x, &strobj))
682             return NULL;
683         use_xy = TRUE;
684         break;
685     case 4:
686         if (!PyArg_ParseTuple(args,"iiOl;int,int,str,attr", &y, &x, &strobj, &lattr))
687             return NULL;
688         attr = lattr;
689         use_xy = use_attr = TRUE;
690         break;
691     default:
692         PyErr_SetString(PyExc_TypeError, "addstr requires 1 to 4 arguments");
693         return NULL;
694     }
695 #ifdef HAVE_NCURSESW
696     strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr);
697 #else
698     strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL);
699 #endif
700     if (strtype == 0)
701         return NULL;
702     if (use_attr == TRUE) {
703         attr_old = getattrs(self->win);
704         (void)wattrset(self->win,attr);
705     }
706 #ifdef HAVE_NCURSESW
707     if (strtype == 2) {
708         funcname = "addwstr";
709         if (use_xy == TRUE)
710             rtn = mvwaddwstr(self->win,y,x,wstr);
711         else
712             rtn = waddwstr(self->win,wstr);
713         PyMem_Free(wstr);
714     }
715     else
716 #endif
717     {
718         char *str = PyBytes_AS_STRING(bytesobj);
719         funcname = "addstr";
720         if (use_xy == TRUE)
721             rtn = mvwaddstr(self->win,y,x,str);
722         else
723             rtn = waddstr(self->win,str);
724         Py_DECREF(bytesobj);
725     }
726     if (use_attr == TRUE)
727         (void)wattrset(self->win,attr_old);
728     return PyCursesCheckERR(rtn, funcname);
729 }
730 
731 static PyObject *
PyCursesWindow_AddNStr(PyCursesWindowObject * self,PyObject * args)732 PyCursesWindow_AddNStr(PyCursesWindowObject *self, PyObject *args)
733 {
734     int rtn, x, y, n;
735     int strtype;
736     PyObject *strobj, *bytesobj = NULL;
737 #ifdef HAVE_NCURSESW
738     wchar_t *wstr = NULL;
739 #endif
740     attr_t attr = A_NORMAL , attr_old = A_NORMAL;
741     long lattr;
742     int use_xy = FALSE, use_attr = FALSE;
743     const char *funcname;
744 
745     switch (PyTuple_Size(args)) {
746     case 2:
747         if (!PyArg_ParseTuple(args,"Oi;str,n", &strobj, &n))
748             return NULL;
749         break;
750     case 3:
751         if (!PyArg_ParseTuple(args,"Oil;str,n,attr", &strobj, &n, &lattr))
752             return NULL;
753         attr = lattr;
754         use_attr = TRUE;
755         break;
756     case 4:
757         if (!PyArg_ParseTuple(args,"iiOi;y,x,str,n", &y, &x, &strobj, &n))
758             return NULL;
759         use_xy = TRUE;
760         break;
761     case 5:
762         if (!PyArg_ParseTuple(args,"iiOil;y,x,str,n,attr", &y, &x, &strobj, &n, &lattr))
763             return NULL;
764         attr = lattr;
765         use_xy = use_attr = TRUE;
766         break;
767     default:
768         PyErr_SetString(PyExc_TypeError, "addnstr requires 2 to 5 arguments");
769         return NULL;
770     }
771 #ifdef HAVE_NCURSESW
772     strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr);
773 #else
774     strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL);
775 #endif
776     if (strtype == 0)
777         return NULL;
778 
779     if (use_attr == TRUE) {
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 == TRUE)
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         char *str = PyBytes_AS_STRING(bytesobj);
796         funcname = "addnstr";
797         if (use_xy == TRUE)
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 == TRUE)
804         (void)wattrset(self->win,attr_old);
805     return PyCursesCheckERR(rtn, funcname);
806 }
807 
808 static PyObject *
PyCursesWindow_Bkgd(PyCursesWindowObject * self,PyObject * args)809 PyCursesWindow_Bkgd(PyCursesWindowObject *self, PyObject *args)
810 {
811     PyObject *temp;
812     chtype bkgd;
813     attr_t attr = A_NORMAL;
814     long lattr;
815 
816     switch (PyTuple_Size(args)) {
817     case 1:
818         if (!PyArg_ParseTuple(args, "O;ch or int", &temp))
819             return NULL;
820         break;
821     case 2:
822         if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr))
823             return NULL;
824         attr = lattr;
825         break;
826     default:
827         PyErr_SetString(PyExc_TypeError, "bkgd requires 1 or 2 arguments");
828         return NULL;
829     }
830 
831     if (!PyCurses_ConvertToChtype(self, temp, &bkgd))
832         return NULL;
833 
834     return PyCursesCheckERR(wbkgd(self->win, bkgd | attr), "bkgd");
835 }
836 
837 static PyObject *
PyCursesWindow_AttrOff(PyCursesWindowObject * self,PyObject * args)838 PyCursesWindow_AttrOff(PyCursesWindowObject *self, PyObject *args)
839 {
840     long lattr;
841     if (!PyArg_ParseTuple(args,"l;attr", &lattr))
842         return NULL;
843     return PyCursesCheckERR(wattroff(self->win, (attr_t)lattr), "attroff");
844 }
845 
846 static PyObject *
PyCursesWindow_AttrOn(PyCursesWindowObject * self,PyObject * args)847 PyCursesWindow_AttrOn(PyCursesWindowObject *self, PyObject *args)
848 {
849     long lattr;
850     if (!PyArg_ParseTuple(args,"l;attr", &lattr))
851         return NULL;
852     return PyCursesCheckERR(wattron(self->win, (attr_t)lattr), "attron");
853 }
854 
855 static PyObject *
PyCursesWindow_AttrSet(PyCursesWindowObject * self,PyObject * args)856 PyCursesWindow_AttrSet(PyCursesWindowObject *self, PyObject *args)
857 {
858     long lattr;
859     if (!PyArg_ParseTuple(args,"l;attr", &lattr))
860         return NULL;
861     return PyCursesCheckERR(wattrset(self->win, (attr_t)lattr), "attrset");
862 }
863 
864 static PyObject *
PyCursesWindow_BkgdSet(PyCursesWindowObject * self,PyObject * args)865 PyCursesWindow_BkgdSet(PyCursesWindowObject *self, PyObject *args)
866 {
867     PyObject *temp;
868     chtype bkgd;
869     attr_t attr = A_NORMAL;
870     long lattr;
871 
872     switch (PyTuple_Size(args)) {
873     case 1:
874         if (!PyArg_ParseTuple(args, "O;ch or int", &temp))
875             return NULL;
876         break;
877     case 2:
878         if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr))
879             return NULL;
880         attr = lattr;
881         break;
882     default:
883         PyErr_SetString(PyExc_TypeError, "bkgdset requires 1 or 2 arguments");
884         return NULL;
885     }
886 
887     if (!PyCurses_ConvertToChtype(self, temp, &bkgd))
888         return NULL;
889 
890     wbkgdset(self->win, bkgd | attr);
891     return PyCursesCheckERR(0, "bkgdset");
892 }
893 
894 static PyObject *
PyCursesWindow_Border(PyCursesWindowObject * self,PyObject * args)895 PyCursesWindow_Border(PyCursesWindowObject *self, PyObject *args)
896 {
897     PyObject *temp[8];
898     chtype ch[8];
899     int i;
900 
901     /* Clear the array of parameters */
902     for(i=0; i<8; i++) {
903         temp[i] = NULL;
904         ch[i] = 0;
905     }
906 
907     if (!PyArg_ParseTuple(args,"|OOOOOOOO;ls,rs,ts,bs,tl,tr,bl,br",
908                           &temp[0], &temp[1], &temp[2], &temp[3],
909                           &temp[4], &temp[5], &temp[6], &temp[7]))
910         return NULL;
911 
912     for(i=0; i<8; i++) {
913         if (temp[i] != NULL && !PyCurses_ConvertToChtype(self, temp[i], &ch[i]))
914             return NULL;
915     }
916 
917     wborder(self->win,
918             ch[0], ch[1], ch[2], ch[3],
919             ch[4], ch[5], ch[6], ch[7]);
920     Py_RETURN_NONE;
921 }
922 
923 static PyObject *
PyCursesWindow_Box(PyCursesWindowObject * self,PyObject * args)924 PyCursesWindow_Box(PyCursesWindowObject *self, PyObject *args)
925 {
926     PyObject *temp1, *temp2;
927     chtype ch1=0,ch2=0;
928     switch(PyTuple_Size(args)){
929     case 0: break;
930     default:
931         if (!PyArg_ParseTuple(args,"OO;verch,horch", &temp1, &temp2))
932             return NULL;
933         if (!PyCurses_ConvertToChtype(self, temp1, &ch1)) {
934             return NULL;
935         }
936         if (!PyCurses_ConvertToChtype(self, temp2, &ch2)) {
937             return NULL;
938         }
939     }
940     box(self->win,ch1,ch2);
941     Py_RETURN_NONE;
942 }
943 
944 #if defined(HAVE_NCURSES_H) || defined(MVWDELCH_IS_EXPRESSION)
945 #define py_mvwdelch mvwdelch
946 #else
py_mvwdelch(WINDOW * w,int y,int x)947 int py_mvwdelch(WINDOW *w, int y, int x)
948 {
949     mvwdelch(w,y,x);
950     /* On HP/UX, mvwdelch already returns. On other systems,
951        we may well run into this return statement. */
952     return 0;
953 }
954 #endif
955 
956 #if defined(HAVE_CURSES_IS_PAD)
957 #define py_is_pad(win)      is_pad(win)
958 #elif defined(WINDOW_HAS_FLAGS)
959 #define py_is_pad(win)      ((win) ? ((win)->_flags & _ISPAD) != 0 : FALSE)
960 #endif
961 
962 /* chgat, added by Fabian Kreutz <fabian.kreutz at gmx.net> */
963 #ifdef HAVE_CURSES_WCHGAT
964 static PyObject *
PyCursesWindow_ChgAt(PyCursesWindowObject * self,PyObject * args)965 PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args)
966 {
967     int rtn;
968     int x, y;
969     int num = -1;
970     short color;
971     attr_t attr = A_NORMAL;
972     long lattr;
973     int use_xy = FALSE;
974 
975     switch (PyTuple_Size(args)) {
976     case 1:
977         if (!PyArg_ParseTuple(args,"l;attr", &lattr))
978             return NULL;
979         attr = lattr;
980         break;
981     case 2:
982         if (!PyArg_ParseTuple(args,"il;n,attr", &num, &lattr))
983             return NULL;
984         attr = lattr;
985         break;
986     case 3:
987         if (!PyArg_ParseTuple(args,"iil;int,int,attr", &y, &x, &lattr))
988             return NULL;
989         attr = lattr;
990         use_xy = TRUE;
991         break;
992     case 4:
993         if (!PyArg_ParseTuple(args,"iiil;int,int,n,attr", &y, &x, &num, &lattr))
994             return NULL;
995         attr = lattr;
996         use_xy = TRUE;
997         break;
998     default:
999         PyErr_SetString(PyExc_TypeError, "chgat requires 1 to 4 arguments");
1000         return NULL;
1001     }
1002 
1003     color = (short)((attr >> 8) & 0xff);
1004     attr = attr - (color << 8);
1005 
1006     if (use_xy == TRUE) {
1007         rtn = mvwchgat(self->win,y,x,num,attr,color,NULL);
1008         touchline(self->win,y,1);
1009     } else {
1010         getyx(self->win,y,x);
1011         rtn = wchgat(self->win,num,attr,color,NULL);
1012         touchline(self->win,y,1);
1013     }
1014     return PyCursesCheckERR(rtn, "chgat");
1015 }
1016 #endif
1017 
1018 static PyObject *
PyCursesWindow_DelCh(PyCursesWindowObject * self,PyObject * args)1019 PyCursesWindow_DelCh(PyCursesWindowObject *self, PyObject *args)
1020 {
1021     int rtn;
1022     int x, y;
1023 
1024     switch (PyTuple_Size(args)) {
1025     case 0:
1026         rtn = wdelch(self->win);
1027         break;
1028     case 2:
1029         if (!PyArg_ParseTuple(args,"ii;y,x", &y, &x))
1030             return NULL;
1031         rtn = py_mvwdelch(self->win,y,x);
1032         break;
1033     default:
1034         PyErr_SetString(PyExc_TypeError, "delch requires 0 or 2 arguments");
1035         return NULL;
1036     }
1037     return PyCursesCheckERR(rtn, "[mv]wdelch");
1038 }
1039 
1040 static PyObject *
PyCursesWindow_DerWin(PyCursesWindowObject * self,PyObject * args)1041 PyCursesWindow_DerWin(PyCursesWindowObject *self, PyObject *args)
1042 {
1043     WINDOW *win;
1044     int nlines, ncols, begin_y, begin_x;
1045 
1046     nlines = 0;
1047     ncols  = 0;
1048     switch (PyTuple_Size(args)) {
1049     case 2:
1050         if (!PyArg_ParseTuple(args,"ii;begin_y,begin_x",&begin_y,&begin_x))
1051             return NULL;
1052         break;
1053     case 4:
1054         if (!PyArg_ParseTuple(args, "iiii;nlines,ncols,begin_y,begin_x",
1055                               &nlines,&ncols,&begin_y,&begin_x))
1056             return NULL;
1057         break;
1058     default:
1059         PyErr_SetString(PyExc_TypeError, "derwin requires 2 or 4 arguments");
1060         return NULL;
1061     }
1062 
1063     win = derwin(self->win,nlines,ncols,begin_y,begin_x);
1064 
1065     if (win == NULL) {
1066         PyErr_SetString(PyCursesError, catchall_NULL);
1067         return NULL;
1068     }
1069 
1070     return (PyObject *)PyCursesWindow_New(win, NULL);
1071 }
1072 
1073 static PyObject *
PyCursesWindow_EchoChar(PyCursesWindowObject * self,PyObject * args)1074 PyCursesWindow_EchoChar(PyCursesWindowObject *self, PyObject *args)
1075 {
1076     PyObject *temp;
1077     chtype ch;
1078     attr_t attr = A_NORMAL;
1079     long lattr;
1080 
1081     switch (PyTuple_Size(args)) {
1082     case 1:
1083         if (!PyArg_ParseTuple(args,"O;ch or int", &temp))
1084             return NULL;
1085         break;
1086     case 2:
1087         if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr))
1088             return NULL;
1089         attr = lattr;
1090         break;
1091     default:
1092         PyErr_SetString(PyExc_TypeError, "echochar requires 1 or 2 arguments");
1093 
1094 
1095         return NULL;
1096     }
1097 
1098     if (!PyCurses_ConvertToChtype(self, temp, &ch))
1099         return NULL;
1100 
1101 #ifdef py_is_pad
1102     if (py_is_pad(self->win)) {
1103         return PyCursesCheckERR(pechochar(self->win, ch | attr),
1104                                 "echochar");
1105     }
1106     else
1107 #endif
1108         return PyCursesCheckERR(wechochar(self->win, ch | attr),
1109                                 "echochar");
1110 }
1111 
1112 #ifdef NCURSES_MOUSE_VERSION
1113 static PyObject *
PyCursesWindow_Enclose(PyCursesWindowObject * self,PyObject * args)1114 PyCursesWindow_Enclose(PyCursesWindowObject *self, PyObject *args)
1115 {
1116     int x, y;
1117     if (!PyArg_ParseTuple(args,"ii;y,x", &y, &x))
1118         return NULL;
1119 
1120     return PyLong_FromLong( wenclose(self->win,y,x) );
1121 }
1122 #endif
1123 
1124 static PyObject *
PyCursesWindow_GetBkgd(PyCursesWindowObject * self)1125 PyCursesWindow_GetBkgd(PyCursesWindowObject *self)
1126 {
1127     return PyLong_FromLong((long) getbkgd(self->win));
1128 }
1129 
1130 static PyObject *
PyCursesWindow_GetCh(PyCursesWindowObject * self,PyObject * args)1131 PyCursesWindow_GetCh(PyCursesWindowObject *self, PyObject *args)
1132 {
1133     int x, y;
1134     int rtn;
1135 
1136     switch (PyTuple_Size(args)) {
1137     case 0:
1138         Py_BEGIN_ALLOW_THREADS
1139         rtn = wgetch(self->win);
1140         Py_END_ALLOW_THREADS
1141         break;
1142     case 2:
1143         if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
1144             return NULL;
1145         Py_BEGIN_ALLOW_THREADS
1146         rtn = mvwgetch(self->win,y,x);
1147         Py_END_ALLOW_THREADS
1148         break;
1149     default:
1150         PyErr_SetString(PyExc_TypeError, "getch requires 0 or 2 arguments");
1151         return NULL;
1152     }
1153     return PyLong_FromLong((long)rtn);
1154 }
1155 
1156 static PyObject *
PyCursesWindow_GetKey(PyCursesWindowObject * self,PyObject * args)1157 PyCursesWindow_GetKey(PyCursesWindowObject *self, PyObject *args)
1158 {
1159     int x, y;
1160     int rtn;
1161 
1162     switch (PyTuple_Size(args)) {
1163     case 0:
1164         Py_BEGIN_ALLOW_THREADS
1165         rtn = wgetch(self->win);
1166         Py_END_ALLOW_THREADS
1167         break;
1168     case 2:
1169         if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
1170             return NULL;
1171         Py_BEGIN_ALLOW_THREADS
1172         rtn = mvwgetch(self->win,y,x);
1173         Py_END_ALLOW_THREADS
1174         break;
1175     default:
1176         PyErr_SetString(PyExc_TypeError, "getkey requires 0 or 2 arguments");
1177         return NULL;
1178     }
1179     if (rtn == ERR) {
1180         /* getch() returns ERR in nodelay mode */
1181         PyErr_CheckSignals();
1182         if (!PyErr_Occurred())
1183             PyErr_SetString(PyCursesError, "no input");
1184         return NULL;
1185     } else if (rtn <= 255) {
1186 #ifdef NCURSES_VERSION_MAJOR
1187 #if NCURSES_VERSION_MAJOR*100+NCURSES_VERSION_MINOR <= 507
1188         /* Work around a bug in ncurses 5.7 and earlier */
1189         if (rtn < 0) {
1190             rtn += 256;
1191         }
1192 #endif
1193 #endif
1194         return PyUnicode_FromOrdinal(rtn);
1195     } else {
1196         const char *knp = keyname(rtn);
1197         return PyUnicode_FromString((knp == NULL) ? "" : knp);
1198     }
1199 }
1200 
1201 #ifdef HAVE_NCURSESW
1202 static PyObject *
PyCursesWindow_Get_WCh(PyCursesWindowObject * self,PyObject * args)1203 PyCursesWindow_Get_WCh(PyCursesWindowObject *self, PyObject *args)
1204 {
1205     int x, y;
1206     int ct;
1207     wint_t rtn;
1208 
1209     switch (PyTuple_Size(args)) {
1210     case 0:
1211         Py_BEGIN_ALLOW_THREADS
1212         ct = wget_wch(self->win,&rtn);
1213         Py_END_ALLOW_THREADS
1214         break;
1215     case 2:
1216         if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
1217             return NULL;
1218         Py_BEGIN_ALLOW_THREADS
1219         ct = mvwget_wch(self->win,y,x,&rtn);
1220         Py_END_ALLOW_THREADS
1221         break;
1222     default:
1223         PyErr_SetString(PyExc_TypeError, "get_wch requires 0 or 2 arguments");
1224         return NULL;
1225     }
1226     if (ct == ERR) {
1227         if (PyErr_CheckSignals())
1228             return NULL;
1229 
1230         /* get_wch() returns ERR in nodelay mode */
1231         PyErr_SetString(PyCursesError, "no input");
1232         return NULL;
1233     }
1234     if (ct == KEY_CODE_YES)
1235         return PyLong_FromLong(rtn);
1236     else
1237         return PyUnicode_FromOrdinal(rtn);
1238 }
1239 #endif
1240 
1241 static PyObject *
PyCursesWindow_GetStr(PyCursesWindowObject * self,PyObject * args)1242 PyCursesWindow_GetStr(PyCursesWindowObject *self, PyObject *args)
1243 {
1244     int x, y, n;
1245     char rtn[1024]; /* This should be big enough.. I hope */
1246     int rtn2;
1247 
1248     switch (PyTuple_Size(args)) {
1249     case 0:
1250         Py_BEGIN_ALLOW_THREADS
1251         rtn2 = wgetnstr(self->win,rtn, 1023);
1252         Py_END_ALLOW_THREADS
1253         break;
1254     case 1:
1255         if (!PyArg_ParseTuple(args,"i;n", &n))
1256             return NULL;
1257         if (n < 0) {
1258             PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
1259             return NULL;
1260         }
1261         Py_BEGIN_ALLOW_THREADS
1262         rtn2 = wgetnstr(self->win, rtn, Py_MIN(n, 1023));
1263         Py_END_ALLOW_THREADS
1264         break;
1265     case 2:
1266         if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
1267             return NULL;
1268         Py_BEGIN_ALLOW_THREADS
1269 #ifdef STRICT_SYSV_CURSES
1270         rtn2 = wmove(self->win,y,x)==ERR ? ERR : wgetnstr(self->win, rtn, 1023);
1271 #else
1272         rtn2 = mvwgetnstr(self->win,y,x,rtn, 1023);
1273 #endif
1274         Py_END_ALLOW_THREADS
1275         break;
1276     case 3:
1277         if (!PyArg_ParseTuple(args,"iii;y,x,n", &y, &x, &n))
1278             return NULL;
1279         if (n < 0) {
1280             PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
1281             return NULL;
1282         }
1283 #ifdef STRICT_SYSV_CURSES
1284         Py_BEGIN_ALLOW_THREADS
1285         rtn2 = wmove(self->win,y,x)==ERR ? ERR :
1286         wgetnstr(self->win, rtn, Py_MIN(n, 1023));
1287         Py_END_ALLOW_THREADS
1288 #else
1289         Py_BEGIN_ALLOW_THREADS
1290         rtn2 = mvwgetnstr(self->win, y, x, rtn, Py_MIN(n, 1023));
1291         Py_END_ALLOW_THREADS
1292 #endif
1293         break;
1294     default:
1295         PyErr_SetString(PyExc_TypeError, "getstr requires 0 to 3 arguments");
1296         return NULL;
1297     }
1298     if (rtn2 == ERR)
1299         rtn[0] = 0;
1300     return PyBytes_FromString(rtn);
1301 }
1302 
1303 static PyObject *
PyCursesWindow_Hline(PyCursesWindowObject * self,PyObject * args)1304 PyCursesWindow_Hline(PyCursesWindowObject *self, PyObject *args)
1305 {
1306     PyObject *temp;
1307     chtype ch;
1308     int n, x, y, code = OK;
1309     attr_t attr = A_NORMAL;
1310     long lattr;
1311 
1312     switch (PyTuple_Size(args)) {
1313     case 2:
1314         if (!PyArg_ParseTuple(args, "Oi;ch or int,n", &temp, &n))
1315             return NULL;
1316         break;
1317     case 3:
1318         if (!PyArg_ParseTuple(args, "Oil;ch or int,n,attr", &temp, &n, &lattr))
1319             return NULL;
1320         attr = lattr;
1321         break;
1322     case 4:
1323         if (!PyArg_ParseTuple(args, "iiOi;y,x,ch or int,n", &y, &x, &temp, &n))
1324             return NULL;
1325         code = wmove(self->win, y, x);
1326         break;
1327     case 5:
1328         if (!PyArg_ParseTuple(args, "iiOil; y,x,ch or int,n,attr",
1329                               &y, &x, &temp, &n, &lattr))
1330             return NULL;
1331         attr = lattr;
1332         code = wmove(self->win, y, x);
1333         break;
1334     default:
1335         PyErr_SetString(PyExc_TypeError, "hline requires 2 to 5 arguments");
1336         return NULL;
1337     }
1338 
1339     if (code != ERR) {
1340         if (!PyCurses_ConvertToChtype(self, temp, &ch))
1341             return NULL;
1342         return PyCursesCheckERR(whline(self->win, ch | attr, n), "hline");
1343     } else
1344         return PyCursesCheckERR(code, "wmove");
1345 }
1346 
1347 static PyObject *
PyCursesWindow_InsCh(PyCursesWindowObject * self,PyObject * args)1348 PyCursesWindow_InsCh(PyCursesWindowObject *self, PyObject *args)
1349 {
1350     int rtn, x, y, use_xy = FALSE;
1351     PyObject *temp;
1352     chtype ch = 0;
1353     attr_t attr = A_NORMAL;
1354     long lattr;
1355 
1356     switch (PyTuple_Size(args)) {
1357     case 1:
1358         if (!PyArg_ParseTuple(args, "O;ch or int", &temp))
1359             return NULL;
1360         break;
1361     case 2:
1362         if (!PyArg_ParseTuple(args, "Ol;ch or int,attr", &temp, &lattr))
1363             return NULL;
1364         attr = lattr;
1365         break;
1366     case 3:
1367         if (!PyArg_ParseTuple(args,"iiO;y,x,ch or int", &y, &x, &temp))
1368             return NULL;
1369         use_xy = TRUE;
1370         break;
1371     case 4:
1372         if (!PyArg_ParseTuple(args,"iiOl;y,x,ch or int, attr", &y, &x, &temp, &lattr))
1373             return NULL;
1374         attr = lattr;
1375         use_xy = TRUE;
1376         break;
1377     default:
1378         PyErr_SetString(PyExc_TypeError, "insch requires 1 to 4 arguments");
1379         return NULL;
1380     }
1381 
1382     if (!PyCurses_ConvertToChtype(self, temp, &ch))
1383         return NULL;
1384 
1385     if (use_xy == TRUE)
1386         rtn = mvwinsch(self->win,y,x, ch | attr);
1387     else {
1388         rtn = winsch(self->win, ch | attr);
1389     }
1390     return PyCursesCheckERR(rtn, "insch");
1391 }
1392 
1393 static PyObject *
PyCursesWindow_InCh(PyCursesWindowObject * self,PyObject * args)1394 PyCursesWindow_InCh(PyCursesWindowObject *self, PyObject *args)
1395 {
1396     int x, y;
1397     unsigned long rtn;
1398 
1399     switch (PyTuple_Size(args)) {
1400     case 0:
1401         rtn = winch(self->win);
1402         break;
1403     case 2:
1404         if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
1405             return NULL;
1406         rtn = mvwinch(self->win,y,x);
1407         break;
1408     default:
1409         PyErr_SetString(PyExc_TypeError, "inch requires 0 to 2 arguments");
1410         return NULL;
1411     }
1412     return PyLong_FromUnsignedLong(rtn);
1413 }
1414 
1415 static PyObject *
PyCursesWindow_InStr(PyCursesWindowObject * self,PyObject * args)1416 PyCursesWindow_InStr(PyCursesWindowObject *self, PyObject *args)
1417 {
1418     int x, y, n;
1419     char rtn[1024]; /* This should be big enough.. I hope */
1420     int rtn2;
1421 
1422     switch (PyTuple_Size(args)) {
1423     case 0:
1424         rtn2 = winnstr(self->win,rtn, 1023);
1425         break;
1426     case 1:
1427         if (!PyArg_ParseTuple(args,"i;n", &n))
1428             return NULL;
1429         if (n < 0) {
1430             PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
1431             return NULL;
1432         }
1433         rtn2 = winnstr(self->win, rtn, Py_MIN(n, 1023));
1434         break;
1435     case 2:
1436         if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
1437             return NULL;
1438         rtn2 = mvwinnstr(self->win,y,x,rtn,1023);
1439         break;
1440     case 3:
1441         if (!PyArg_ParseTuple(args, "iii;y,x,n", &y, &x, &n))
1442             return NULL;
1443         if (n < 0) {
1444             PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
1445             return NULL;
1446         }
1447         rtn2 = mvwinnstr(self->win, y, x, rtn, Py_MIN(n,1023));
1448         break;
1449     default:
1450         PyErr_SetString(PyExc_TypeError, "instr requires 0 or 3 arguments");
1451         return NULL;
1452     }
1453     if (rtn2 == ERR)
1454         rtn[0] = 0;
1455     return PyBytes_FromString(rtn);
1456 }
1457 
1458 static PyObject *
PyCursesWindow_InsStr(PyCursesWindowObject * self,PyObject * args)1459 PyCursesWindow_InsStr(PyCursesWindowObject *self, PyObject *args)
1460 {
1461     int rtn;
1462     int x, y;
1463     int strtype;
1464     PyObject *strobj, *bytesobj = NULL;
1465 #ifdef HAVE_NCURSESW
1466     wchar_t *wstr = NULL;
1467 #endif
1468     attr_t attr = A_NORMAL , attr_old = A_NORMAL;
1469     long lattr;
1470     int use_xy = FALSE, use_attr = FALSE;
1471     const char *funcname;
1472 
1473     switch (PyTuple_Size(args)) {
1474     case 1:
1475         if (!PyArg_ParseTuple(args,"O;str", &strobj))
1476             return NULL;
1477         break;
1478     case 2:
1479         if (!PyArg_ParseTuple(args,"Ol;str,attr", &strobj, &lattr))
1480             return NULL;
1481         attr = lattr;
1482         use_attr = TRUE;
1483         break;
1484     case 3:
1485         if (!PyArg_ParseTuple(args,"iiO;y,x,str", &y, &x, &strobj))
1486             return NULL;
1487         use_xy = TRUE;
1488         break;
1489     case 4:
1490         if (!PyArg_ParseTuple(args,"iiOl;y,x,str,attr", &y, &x, &strobj, &lattr))
1491             return NULL;
1492         attr = lattr;
1493         use_xy = use_attr = TRUE;
1494         break;
1495     default:
1496         PyErr_SetString(PyExc_TypeError, "insstr requires 1 to 4 arguments");
1497         return NULL;
1498     }
1499 
1500 #ifdef HAVE_NCURSESW
1501     strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr);
1502 #else
1503     strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL);
1504 #endif
1505     if (strtype == 0)
1506         return NULL;
1507 
1508     if (use_attr == TRUE) {
1509         attr_old = getattrs(self->win);
1510         (void)wattrset(self->win,attr);
1511     }
1512 #ifdef HAVE_NCURSESW
1513     if (strtype == 2) {
1514         funcname = "inswstr";
1515         if (use_xy == TRUE)
1516             rtn = mvwins_wstr(self->win,y,x,wstr);
1517         else
1518             rtn = wins_wstr(self->win,wstr);
1519         PyMem_Free(wstr);
1520     }
1521     else
1522 #endif
1523     {
1524         char *str = PyBytes_AS_STRING(bytesobj);
1525         funcname = "insstr";
1526         if (use_xy == TRUE)
1527             rtn = mvwinsstr(self->win,y,x,str);
1528         else
1529             rtn = winsstr(self->win,str);
1530         Py_DECREF(bytesobj);
1531     }
1532     if (use_attr == TRUE)
1533         (void)wattrset(self->win,attr_old);
1534     return PyCursesCheckERR(rtn, funcname);
1535 }
1536 
1537 static PyObject *
PyCursesWindow_InsNStr(PyCursesWindowObject * self,PyObject * args)1538 PyCursesWindow_InsNStr(PyCursesWindowObject *self, PyObject *args)
1539 {
1540     int rtn, x, y, n;
1541     int strtype;
1542     PyObject *strobj, *bytesobj = NULL;
1543 #ifdef HAVE_NCURSESW
1544     wchar_t *wstr = NULL;
1545 #endif
1546     attr_t attr = A_NORMAL , attr_old = A_NORMAL;
1547     long lattr;
1548     int use_xy = FALSE, use_attr = FALSE;
1549     const char *funcname;
1550 
1551     switch (PyTuple_Size(args)) {
1552     case 2:
1553         if (!PyArg_ParseTuple(args,"Oi;str,n", &strobj, &n))
1554             return NULL;
1555         break;
1556     case 3:
1557         if (!PyArg_ParseTuple(args,"Oil;str,n,attr", &strobj, &n, &lattr))
1558             return NULL;
1559         attr = lattr;
1560         use_attr = TRUE;
1561         break;
1562     case 4:
1563         if (!PyArg_ParseTuple(args,"iiOi;y,x,str,n", &y, &x, &strobj, &n))
1564             return NULL;
1565         use_xy = TRUE;
1566         break;
1567     case 5:
1568         if (!PyArg_ParseTuple(args,"iiOil;y,x,str,n,attr", &y, &x, &strobj, &n, &lattr))
1569             return NULL;
1570         attr = lattr;
1571         use_xy = use_attr = TRUE;
1572         break;
1573     default:
1574         PyErr_SetString(PyExc_TypeError, "insnstr requires 2 to 5 arguments");
1575         return NULL;
1576     }
1577 
1578 #ifdef HAVE_NCURSESW
1579     strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr);
1580 #else
1581     strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL);
1582 #endif
1583     if (strtype == 0)
1584         return NULL;
1585 
1586     if (use_attr == TRUE) {
1587         attr_old = getattrs(self->win);
1588         (void)wattrset(self->win,attr);
1589     }
1590 #ifdef HAVE_NCURSESW
1591     if (strtype == 2) {
1592         funcname = "insn_wstr";
1593         if (use_xy == TRUE)
1594             rtn = mvwins_nwstr(self->win,y,x,wstr,n);
1595         else
1596             rtn = wins_nwstr(self->win,wstr,n);
1597         PyMem_Free(wstr);
1598     }
1599     else
1600 #endif
1601     {
1602         char *str = PyBytes_AS_STRING(bytesobj);
1603         funcname = "insnstr";
1604         if (use_xy == TRUE)
1605             rtn = mvwinsnstr(self->win,y,x,str,n);
1606         else
1607             rtn = winsnstr(self->win,str,n);
1608         Py_DECREF(bytesobj);
1609     }
1610     if (use_attr == TRUE)
1611         (void)wattrset(self->win,attr_old);
1612     return PyCursesCheckERR(rtn, funcname);
1613 }
1614 
1615 static PyObject *
PyCursesWindow_Is_LineTouched(PyCursesWindowObject * self,PyObject * args)1616 PyCursesWindow_Is_LineTouched(PyCursesWindowObject *self, PyObject *args)
1617 {
1618     int line, erg;
1619     if (!PyArg_ParseTuple(args,"i;line", &line))
1620         return NULL;
1621     erg = is_linetouched(self->win, line);
1622     if (erg == ERR) {
1623         PyErr_SetString(PyExc_TypeError,
1624                         "is_linetouched: line number outside of boundaries");
1625         return NULL;
1626     } else
1627         if (erg == FALSE) {
1628             Py_RETURN_FALSE;
1629         } else {
1630             Py_RETURN_TRUE;
1631         }
1632 }
1633 
1634 static PyObject *
PyCursesWindow_NoOutRefresh(PyCursesWindowObject * self,PyObject * args)1635 PyCursesWindow_NoOutRefresh(PyCursesWindowObject *self, PyObject *args)
1636 {
1637     int pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol;
1638     int rtn;
1639 
1640 #ifndef py_is_pad
1641     if (0)
1642 #else
1643         if (py_is_pad(self->win))
1644 #endif
1645         {
1646             switch(PyTuple_Size(args)) {
1647             case 6:
1648                 if (!PyArg_ParseTuple(args,
1649                                       "iiiiii;" \
1650                                       "pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol",
1651                                       &pminrow, &pmincol, &sminrow,
1652                                       &smincol, &smaxrow, &smaxcol))
1653                     return NULL;
1654                 Py_BEGIN_ALLOW_THREADS
1655                 rtn = pnoutrefresh(self->win,
1656                                    pminrow, pmincol, sminrow,
1657                                    smincol, smaxrow, smaxcol);
1658                 Py_END_ALLOW_THREADS
1659                 return PyCursesCheckERR(rtn, "pnoutrefresh");
1660             default:
1661                 PyErr_SetString(PyCursesError,
1662                                 "noutrefresh() called for a pad "
1663                                 "requires 6 arguments");
1664                 return NULL;
1665             }
1666         } else {
1667             if (!PyArg_ParseTuple(args, ":noutrefresh"))
1668                 return NULL;
1669 
1670             Py_BEGIN_ALLOW_THREADS
1671             rtn = wnoutrefresh(self->win);
1672             Py_END_ALLOW_THREADS
1673             return PyCursesCheckERR(rtn, "wnoutrefresh");
1674         }
1675 }
1676 
1677 static PyObject *
PyCursesWindow_Overlay(PyCursesWindowObject * self,PyObject * args)1678 PyCursesWindow_Overlay(PyCursesWindowObject *self, PyObject *args)
1679 {
1680     PyCursesWindowObject *temp;
1681     int use_copywin = FALSE;
1682     int sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol;
1683     int rtn;
1684 
1685     switch (PyTuple_Size(args)) {
1686     case 1:
1687         if (!PyArg_ParseTuple(args, "O!;window object",
1688                               &PyCursesWindow_Type, &temp))
1689             return NULL;
1690         break;
1691     case 7:
1692         if (!PyArg_ParseTuple(args, "O!iiiiii;window object, int, int, int, int, int, int",
1693                               &PyCursesWindow_Type, &temp, &sminrow, &smincol,
1694                               &dminrow, &dmincol, &dmaxrow, &dmaxcol))
1695             return NULL;
1696         use_copywin = TRUE;
1697         break;
1698     default:
1699         PyErr_SetString(PyExc_TypeError,
1700                         "overlay requires one or seven arguments");
1701         return NULL;
1702     }
1703 
1704     if (use_copywin == TRUE) {
1705         rtn = copywin(self->win, temp->win, sminrow, smincol,
1706                       dminrow, dmincol, dmaxrow, dmaxcol, TRUE);
1707         return PyCursesCheckERR(rtn, "copywin");
1708     }
1709     else {
1710         rtn = overlay(self->win, temp->win);
1711         return PyCursesCheckERR(rtn, "overlay");
1712     }
1713 }
1714 
1715 static PyObject *
PyCursesWindow_Overwrite(PyCursesWindowObject * self,PyObject * args)1716 PyCursesWindow_Overwrite(PyCursesWindowObject *self, PyObject *args)
1717 {
1718     PyCursesWindowObject *temp;
1719     int use_copywin = FALSE;
1720     int sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol;
1721     int rtn;
1722 
1723     switch (PyTuple_Size(args)) {
1724     case 1:
1725         if (!PyArg_ParseTuple(args, "O!;window object",
1726                               &PyCursesWindow_Type, &temp))
1727             return NULL;
1728         break;
1729     case 7:
1730         if (!PyArg_ParseTuple(args, "O!iiiiii;window object, int, int, int, int, int, int",
1731                               &PyCursesWindow_Type, &temp, &sminrow, &smincol,
1732                               &dminrow, &dmincol, &dmaxrow, &dmaxcol))
1733             return NULL;
1734         use_copywin = TRUE;
1735         break;
1736     default:
1737         PyErr_SetString(PyExc_TypeError,
1738                         "overwrite requires one or seven arguments");
1739         return NULL;
1740     }
1741 
1742     if (use_copywin == TRUE) {
1743         rtn = copywin(self->win, temp->win, sminrow, smincol,
1744                       dminrow, dmincol, dmaxrow, dmaxcol, FALSE);
1745         return PyCursesCheckERR(rtn, "copywin");
1746     }
1747     else {
1748         rtn = overwrite(self->win, temp->win);
1749         return PyCursesCheckERR(rtn, "overwrite");
1750     }
1751 }
1752 
1753 static PyObject *
PyCursesWindow_PutWin(PyCursesWindowObject * self,PyObject * stream)1754 PyCursesWindow_PutWin(PyCursesWindowObject *self, PyObject *stream)
1755 {
1756     /* We have to simulate this by writing to a temporary FILE*,
1757        then reading back, then writing to the argument stream. */
1758     FILE *fp;
1759     PyObject *res = NULL;
1760 
1761     fp = tmpfile();
1762     if (fp == NULL)
1763         return PyErr_SetFromErrno(PyExc_OSError);
1764     if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0)
1765         goto exit;
1766     res = PyCursesCheckERR(putwin(self->win, fp), "putwin");
1767     if (res == NULL)
1768         goto exit;
1769     fseek(fp, 0, 0);
1770     while (1) {
1771         char buf[BUFSIZ];
1772         Py_ssize_t n = fread(buf, 1, BUFSIZ, fp);
1773         _Py_IDENTIFIER(write);
1774 
1775         if (n <= 0)
1776             break;
1777         Py_DECREF(res);
1778         res = _PyObject_CallMethodId(stream, &PyId_write, "y#", buf, n);
1779         if (res == NULL)
1780             break;
1781     }
1782 
1783 exit:
1784     fclose(fp);
1785     return res;
1786 }
1787 
1788 static PyObject *
PyCursesWindow_RedrawLine(PyCursesWindowObject * self,PyObject * args)1789 PyCursesWindow_RedrawLine(PyCursesWindowObject *self, PyObject *args)
1790 {
1791     int beg, num;
1792     if (!PyArg_ParseTuple(args, "ii;beg,num", &beg, &num))
1793         return NULL;
1794     return PyCursesCheckERR(wredrawln(self->win,beg,num), "redrawln");
1795 }
1796 
1797 static PyObject *
PyCursesWindow_Refresh(PyCursesWindowObject * self,PyObject * args)1798 PyCursesWindow_Refresh(PyCursesWindowObject *self, PyObject *args)
1799 {
1800     int pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol;
1801     int rtn;
1802 
1803 #ifndef py_is_pad
1804     if (0)
1805 #else
1806         if (py_is_pad(self->win))
1807 #endif
1808         {
1809             switch(PyTuple_Size(args)) {
1810             case 6:
1811                 if (!PyArg_ParseTuple(args,
1812                                       "iiiiii;" \
1813                                       "pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol",
1814                                       &pminrow, &pmincol, &sminrow,
1815                                       &smincol, &smaxrow, &smaxcol))
1816                     return NULL;
1817 
1818                 Py_BEGIN_ALLOW_THREADS
1819                 rtn = prefresh(self->win,
1820                                pminrow, pmincol, sminrow,
1821                                smincol, smaxrow, smaxcol);
1822                 Py_END_ALLOW_THREADS
1823                 return PyCursesCheckERR(rtn, "prefresh");
1824             default:
1825                 PyErr_SetString(PyCursesError,
1826                                 "refresh() for a pad requires 6 arguments");
1827                 return NULL;
1828             }
1829         } else {
1830             if (!PyArg_ParseTuple(args, ":refresh"))
1831                 return NULL;
1832             Py_BEGIN_ALLOW_THREADS
1833             rtn = wrefresh(self->win);
1834             Py_END_ALLOW_THREADS
1835             return PyCursesCheckERR(rtn, "prefresh");
1836         }
1837 }
1838 
1839 static PyObject *
PyCursesWindow_SetScrollRegion(PyCursesWindowObject * self,PyObject * args)1840 PyCursesWindow_SetScrollRegion(PyCursesWindowObject *self, PyObject *args)
1841 {
1842     int x, y;
1843     if (!PyArg_ParseTuple(args,"ii;top, bottom",&y,&x))
1844         return NULL;
1845     return PyCursesCheckERR(wsetscrreg(self->win,y,x), "wsetscrreg");
1846 }
1847 
1848 static PyObject *
PyCursesWindow_SubWin(PyCursesWindowObject * self,PyObject * args)1849 PyCursesWindow_SubWin(PyCursesWindowObject *self, PyObject *args)
1850 {
1851     WINDOW *win;
1852     int nlines, ncols, begin_y, begin_x;
1853 
1854     nlines = 0;
1855     ncols  = 0;
1856     switch (PyTuple_Size(args)) {
1857     case 2:
1858         if (!PyArg_ParseTuple(args,"ii;begin_y,begin_x",&begin_y,&begin_x))
1859             return NULL;
1860         break;
1861     case 4:
1862         if (!PyArg_ParseTuple(args, "iiii;nlines,ncols,begin_y,begin_x",
1863                               &nlines,&ncols,&begin_y,&begin_x))
1864             return NULL;
1865         break;
1866     default:
1867         PyErr_SetString(PyExc_TypeError, "subwin requires 2 or 4 arguments");
1868         return NULL;
1869     }
1870 
1871     /* printf("Subwin: %i %i %i %i   \n", nlines, ncols, begin_y, begin_x); */
1872 #ifdef py_is_pad
1873     if (py_is_pad(self->win)) {
1874         win = subpad(self->win, nlines, ncols, begin_y, begin_x);
1875     }
1876     else
1877 #endif
1878         win = subwin(self->win, nlines, ncols, begin_y, begin_x);
1879 
1880     if (win == NULL) {
1881         PyErr_SetString(PyCursesError, catchall_NULL);
1882         return NULL;
1883     }
1884 
1885     return (PyObject *)PyCursesWindow_New(win, self->encoding);
1886 }
1887 
1888 static PyObject *
PyCursesWindow_Scroll(PyCursesWindowObject * self,PyObject * args)1889 PyCursesWindow_Scroll(PyCursesWindowObject *self, PyObject *args)
1890 {
1891     int nlines;
1892     switch(PyTuple_Size(args)) {
1893     case 0:
1894         return PyCursesCheckERR(scroll(self->win), "scroll");
1895     case 1:
1896         if (!PyArg_ParseTuple(args, "i;nlines", &nlines))
1897             return NULL;
1898         return PyCursesCheckERR(wscrl(self->win, nlines), "scroll");
1899     default:
1900         PyErr_SetString(PyExc_TypeError, "scroll requires 0 or 1 arguments");
1901         return NULL;
1902     }
1903 }
1904 
1905 static PyObject *
PyCursesWindow_TouchLine(PyCursesWindowObject * self,PyObject * args)1906 PyCursesWindow_TouchLine(PyCursesWindowObject *self, PyObject *args)
1907 {
1908     int st, cnt, val;
1909     switch (PyTuple_Size(args)) {
1910     case 2:
1911         if (!PyArg_ParseTuple(args,"ii;start,count",&st,&cnt))
1912             return NULL;
1913         return PyCursesCheckERR(touchline(self->win,st,cnt), "touchline");
1914     case 3:
1915         if (!PyArg_ParseTuple(args, "iii;start,count,val", &st, &cnt, &val))
1916             return NULL;
1917         return PyCursesCheckERR(wtouchln(self->win, st, cnt, val), "touchline");
1918     default:
1919         PyErr_SetString(PyExc_TypeError, "touchline requires 2 or 3 arguments");
1920         return NULL;
1921     }
1922 }
1923 
1924 static PyObject *
PyCursesWindow_Vline(PyCursesWindowObject * self,PyObject * args)1925 PyCursesWindow_Vline(PyCursesWindowObject *self, PyObject *args)
1926 {
1927     PyObject *temp;
1928     chtype ch;
1929     int n, x, y, code = OK;
1930     attr_t attr = A_NORMAL;
1931     long lattr;
1932 
1933     switch (PyTuple_Size(args)) {
1934     case 2:
1935         if (!PyArg_ParseTuple(args, "Oi;ch or int,n", &temp, &n))
1936             return NULL;
1937         break;
1938     case 3:
1939         if (!PyArg_ParseTuple(args, "Oil;ch or int,n,attr", &temp, &n, &lattr))
1940             return NULL;
1941         attr = lattr;
1942         break;
1943     case 4:
1944         if (!PyArg_ParseTuple(args, "iiOi;y,x,ch or int,n", &y, &x, &temp, &n))
1945             return NULL;
1946         code = wmove(self->win, y, x);
1947         break;
1948     case 5:
1949         if (!PyArg_ParseTuple(args, "iiOil; y,x,ch or int,n,attr",
1950                               &y, &x, &temp, &n, &lattr))
1951             return NULL;
1952         attr = lattr;
1953         code = wmove(self->win, y, x);
1954         break;
1955     default:
1956         PyErr_SetString(PyExc_TypeError, "vline requires 2 to 5 arguments");
1957         return NULL;
1958     }
1959 
1960     if (code != ERR) {
1961         if (!PyCurses_ConvertToChtype(self, temp, &ch))
1962             return NULL;
1963         return PyCursesCheckERR(wvline(self->win, ch | attr, n), "vline");
1964     } else
1965         return PyCursesCheckERR(code, "wmove");
1966 }
1967 
1968 static PyObject *
PyCursesWindow_get_encoding(PyCursesWindowObject * self,void * closure)1969 PyCursesWindow_get_encoding(PyCursesWindowObject *self, void *closure)
1970 {
1971     return PyUnicode_FromString(self->encoding);
1972 }
1973 
1974 static int
PyCursesWindow_set_encoding(PyCursesWindowObject * self,PyObject * value,void * Py_UNUSED (ignored))1975 PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value, void *Py_UNUSED(ignored))
1976 {
1977     PyObject *ascii;
1978     char *encoding;
1979 
1980     /* It is illegal to del win.encoding */
1981     if (value == NULL) {
1982         PyErr_SetString(PyExc_TypeError,
1983                         "encoding may not be deleted");
1984         return -1;
1985     }
1986 
1987     if (!PyUnicode_Check(value)) {
1988         PyErr_SetString(PyExc_TypeError,
1989                         "setting encoding to a non-string");
1990         return -1;
1991     }
1992     ascii = PyUnicode_AsASCIIString(value);
1993     if (ascii == NULL)
1994         return -1;
1995     encoding = _PyMem_Strdup(PyBytes_AS_STRING(ascii));
1996     Py_DECREF(ascii);
1997     if (encoding == NULL) {
1998         PyErr_NoMemory();
1999         return -1;
2000     }
2001     PyMem_Free(self->encoding);
2002     self->encoding = encoding;
2003     return 0;
2004 }
2005 
2006 
2007 static PyMethodDef PyCursesWindow_Methods[] = {
2008     CURSES_WINDOW_ADDCH_METHODDEF
2009     {"addnstr",         (PyCFunction)PyCursesWindow_AddNStr, METH_VARARGS},
2010     {"addstr",          (PyCFunction)PyCursesWindow_AddStr, METH_VARARGS},
2011     {"attroff",         (PyCFunction)PyCursesWindow_AttrOff, METH_VARARGS},
2012     {"attron",          (PyCFunction)PyCursesWindow_AttrOn, METH_VARARGS},
2013     {"attrset",         (PyCFunction)PyCursesWindow_AttrSet, METH_VARARGS},
2014     {"bkgd",            (PyCFunction)PyCursesWindow_Bkgd, METH_VARARGS},
2015 #ifdef HAVE_CURSES_WCHGAT
2016     {"chgat",           (PyCFunction)PyCursesWindow_ChgAt, METH_VARARGS},
2017 #endif
2018     {"bkgdset",         (PyCFunction)PyCursesWindow_BkgdSet, METH_VARARGS},
2019     {"border",          (PyCFunction)PyCursesWindow_Border, METH_VARARGS},
2020     {"box",             (PyCFunction)PyCursesWindow_Box, METH_VARARGS},
2021     {"clear",           (PyCFunction)PyCursesWindow_wclear, METH_NOARGS},
2022     {"clearok",         (PyCFunction)PyCursesWindow_clearok, METH_VARARGS},
2023     {"clrtobot",        (PyCFunction)PyCursesWindow_wclrtobot, METH_NOARGS},
2024     {"clrtoeol",        (PyCFunction)PyCursesWindow_wclrtoeol, METH_NOARGS},
2025     {"cursyncup",       (PyCFunction)PyCursesWindow_wcursyncup, METH_NOARGS},
2026     {"delch",           (PyCFunction)PyCursesWindow_DelCh, METH_VARARGS},
2027     {"deleteln",        (PyCFunction)PyCursesWindow_wdeleteln, METH_NOARGS},
2028     {"derwin",          (PyCFunction)PyCursesWindow_DerWin, METH_VARARGS},
2029     {"echochar",        (PyCFunction)PyCursesWindow_EchoChar, METH_VARARGS},
2030 #ifdef NCURSES_MOUSE_VERSION
2031     {"enclose",         (PyCFunction)PyCursesWindow_Enclose, METH_VARARGS},
2032 #endif
2033     {"erase",           (PyCFunction)PyCursesWindow_werase, METH_NOARGS},
2034     {"getbegyx",        (PyCFunction)PyCursesWindow_getbegyx, METH_NOARGS},
2035     {"getbkgd",         (PyCFunction)PyCursesWindow_GetBkgd, METH_NOARGS},
2036     {"getch",           (PyCFunction)PyCursesWindow_GetCh, METH_VARARGS},
2037     {"getkey",          (PyCFunction)PyCursesWindow_GetKey, METH_VARARGS},
2038 #ifdef HAVE_NCURSESW
2039     {"get_wch",         (PyCFunction)PyCursesWindow_Get_WCh, METH_VARARGS},
2040 #endif
2041     {"getmaxyx",        (PyCFunction)PyCursesWindow_getmaxyx, METH_NOARGS},
2042     {"getparyx",        (PyCFunction)PyCursesWindow_getparyx, METH_NOARGS},
2043     {"getstr",          (PyCFunction)PyCursesWindow_GetStr, METH_VARARGS},
2044     {"getyx",           (PyCFunction)PyCursesWindow_getyx, METH_NOARGS},
2045     {"hline",           (PyCFunction)PyCursesWindow_Hline, METH_VARARGS},
2046     {"idcok",           (PyCFunction)PyCursesWindow_idcok, METH_VARARGS},
2047     {"idlok",           (PyCFunction)PyCursesWindow_idlok, METH_VARARGS},
2048 #ifdef HAVE_CURSES_IMMEDOK
2049     {"immedok",         (PyCFunction)PyCursesWindow_immedok, METH_VARARGS},
2050 #endif
2051     {"inch",            (PyCFunction)PyCursesWindow_InCh, METH_VARARGS},
2052     {"insch",           (PyCFunction)PyCursesWindow_InsCh, METH_VARARGS},
2053     {"insdelln",        (PyCFunction)PyCursesWindow_winsdelln, METH_VARARGS},
2054     {"insertln",        (PyCFunction)PyCursesWindow_winsertln, METH_NOARGS},
2055     {"insnstr",         (PyCFunction)PyCursesWindow_InsNStr, METH_VARARGS},
2056     {"insstr",          (PyCFunction)PyCursesWindow_InsStr, METH_VARARGS},
2057     {"instr",           (PyCFunction)PyCursesWindow_InStr, METH_VARARGS},
2058     {"is_linetouched",  (PyCFunction)PyCursesWindow_Is_LineTouched, METH_VARARGS},
2059     {"is_wintouched",   (PyCFunction)PyCursesWindow_is_wintouched, METH_NOARGS},
2060     {"keypad",          (PyCFunction)PyCursesWindow_keypad, METH_VARARGS},
2061     {"leaveok",         (PyCFunction)PyCursesWindow_leaveok, METH_VARARGS},
2062     {"move",            (PyCFunction)PyCursesWindow_wmove, METH_VARARGS},
2063     {"mvderwin",        (PyCFunction)PyCursesWindow_mvderwin, METH_VARARGS},
2064     {"mvwin",           (PyCFunction)PyCursesWindow_mvwin, METH_VARARGS},
2065     {"nodelay",         (PyCFunction)PyCursesWindow_nodelay, METH_VARARGS},
2066     {"notimeout",       (PyCFunction)PyCursesWindow_notimeout, METH_VARARGS},
2067     {"noutrefresh",     (PyCFunction)PyCursesWindow_NoOutRefresh, METH_VARARGS},
2068     {"overlay",         (PyCFunction)PyCursesWindow_Overlay, METH_VARARGS},
2069     {"overwrite",       (PyCFunction)PyCursesWindow_Overwrite,
2070      METH_VARARGS},
2071     {"putwin",          (PyCFunction)PyCursesWindow_PutWin, METH_O},
2072     {"redrawln",        (PyCFunction)PyCursesWindow_RedrawLine, METH_VARARGS},
2073     {"redrawwin",       (PyCFunction)PyCursesWindow_redrawwin, METH_NOARGS},
2074     {"refresh",         (PyCFunction)PyCursesWindow_Refresh, METH_VARARGS},
2075 #ifndef STRICT_SYSV_CURSES
2076     {"resize",          (PyCFunction)PyCursesWindow_wresize, METH_VARARGS},
2077 #endif
2078     {"scroll",          (PyCFunction)PyCursesWindow_Scroll, METH_VARARGS},
2079     {"scrollok",        (PyCFunction)PyCursesWindow_scrollok, METH_VARARGS},
2080     {"setscrreg",       (PyCFunction)PyCursesWindow_SetScrollRegion, METH_VARARGS},
2081     {"standend",        (PyCFunction)PyCursesWindow_wstandend, METH_NOARGS},
2082     {"standout",        (PyCFunction)PyCursesWindow_wstandout, METH_NOARGS},
2083     {"subpad",          (PyCFunction)PyCursesWindow_SubWin, METH_VARARGS},
2084     {"subwin",          (PyCFunction)PyCursesWindow_SubWin, METH_VARARGS},
2085     {"syncdown",        (PyCFunction)PyCursesWindow_wsyncdown, METH_NOARGS},
2086 #ifdef HAVE_CURSES_SYNCOK
2087     {"syncok",          (PyCFunction)PyCursesWindow_syncok, METH_VARARGS},
2088 #endif
2089     {"syncup",          (PyCFunction)PyCursesWindow_wsyncup, METH_NOARGS},
2090     {"timeout",         (PyCFunction)PyCursesWindow_wtimeout, METH_VARARGS},
2091     {"touchline",       (PyCFunction)PyCursesWindow_TouchLine, METH_VARARGS},
2092     {"touchwin",        (PyCFunction)PyCursesWindow_touchwin, METH_NOARGS},
2093     {"untouchwin",      (PyCFunction)PyCursesWindow_untouchwin, METH_NOARGS},
2094     {"vline",           (PyCFunction)PyCursesWindow_Vline, METH_VARARGS},
2095     {NULL,                  NULL}   /* sentinel */
2096 };
2097 
2098 static PyGetSetDef PyCursesWindow_getsets[] = {
2099     {"encoding",
2100      (getter)PyCursesWindow_get_encoding,
2101      (setter)PyCursesWindow_set_encoding,
2102      "the typecode character used to create the array"},
2103     {NULL, NULL, NULL, NULL }  /* sentinel */
2104 };
2105 
2106 /* -------------------------------------------------------*/
2107 
2108 PyTypeObject PyCursesWindow_Type = {
2109     PyVarObject_HEAD_INIT(NULL, 0)
2110     "_curses.window",           /*tp_name*/
2111     sizeof(PyCursesWindowObject),       /*tp_basicsize*/
2112     0,                          /*tp_itemsize*/
2113     /* methods */
2114     (destructor)PyCursesWindow_Dealloc, /*tp_dealloc*/
2115     0,                          /*tp_print*/
2116     (getattrfunc)0,             /*tp_getattr*/
2117     (setattrfunc)0,             /*tp_setattr*/
2118     0,                          /*tp_reserved*/
2119     0,                          /*tp_repr*/
2120     0,                          /*tp_as_number*/
2121     0,                          /*tp_as_sequence*/
2122     0,                          /*tp_as_mapping*/
2123     0,                          /*tp_hash*/
2124     0,                          /*tp_call*/
2125     0,                          /*tp_str*/
2126     0,                          /*tp_getattro*/
2127     0,                          /*tp_setattro*/
2128     0,                          /*tp_as_buffer*/
2129     Py_TPFLAGS_DEFAULT,         /*tp_flags*/
2130     0,                          /*tp_doc*/
2131     0,                          /*tp_traverse*/
2132     0,                          /*tp_clear*/
2133     0,                          /*tp_richcompare*/
2134     0,                          /*tp_weaklistoffset*/
2135     0,                          /*tp_iter*/
2136     0,                          /*tp_iternext*/
2137     PyCursesWindow_Methods,     /*tp_methods*/
2138     0,                          /* tp_members */
2139     PyCursesWindow_getsets,     /* tp_getset */
2140 };
2141 
2142 /*********************************************************************
2143  Global Functions
2144 **********************************************************************/
2145 
2146 NoArgNoReturnFunction(beep)
NoArgNoReturnFunction(def_prog_mode)2147 NoArgNoReturnFunction(def_prog_mode)
2148 NoArgNoReturnFunction(def_shell_mode)
2149 NoArgNoReturnFunction(doupdate)
2150 NoArgNoReturnFunction(endwin)
2151 NoArgNoReturnFunction(flash)
2152 NoArgNoReturnFunction(nocbreak)
2153 NoArgNoReturnFunction(noecho)
2154 NoArgNoReturnFunction(nonl)
2155 NoArgNoReturnFunction(noraw)
2156 NoArgNoReturnFunction(reset_prog_mode)
2157 NoArgNoReturnFunction(reset_shell_mode)
2158 NoArgNoReturnFunction(resetty)
2159 NoArgNoReturnFunction(savetty)
2160 
2161 NoArgOrFlagNoReturnFunction(cbreak)
2162 NoArgOrFlagNoReturnFunction(echo)
2163 NoArgOrFlagNoReturnFunction(nl)
2164 NoArgOrFlagNoReturnFunction(raw)
2165 
2166 NoArgReturnIntFunction(baudrate)
2167 NoArgReturnIntFunction(termattrs)
2168 
2169 NoArgReturnStringFunction(termname)
2170 NoArgReturnStringFunction(longname)
2171 
2172 NoArgTrueFalseFunction(can_change_color)
2173 NoArgTrueFalseFunction(has_colors)
2174 NoArgTrueFalseFunction(has_ic)
2175 NoArgTrueFalseFunction(has_il)
2176 NoArgTrueFalseFunction(isendwin)
2177 NoArgNoReturnVoidFunction(flushinp)
2178 NoArgNoReturnVoidFunction(noqiflush)
2179 
2180 #ifdef HAVE_CURSES_FILTER
2181 static PyObject *
2182 PyCurses_filter(PyObject *self)
2183 {
2184     /* not checking for PyCursesInitialised here since filter() must
2185        be called before initscr() */
2186     filter();
2187     Py_RETURN_NONE;
2188 }
2189 #endif
2190 
2191 static PyObject *
PyCurses_Color_Content(PyObject * self,PyObject * args)2192 PyCurses_Color_Content(PyObject *self, PyObject *args)
2193 {
2194     short color,r,g,b;
2195 
2196     PyCursesInitialised;
2197     PyCursesInitialisedColor;
2198 
2199     if (!PyArg_ParseTuple(args, "h:color_content", &color)) return NULL;
2200 
2201     if (color_content(color, &r, &g, &b) != ERR)
2202         return Py_BuildValue("(iii)", r, g, b);
2203     else {
2204         PyErr_SetString(PyCursesError,
2205                         "Argument 1 was out of range. Check value of COLORS.");
2206         return NULL;
2207     }
2208 }
2209 
2210 static PyObject *
PyCurses_color_pair(PyObject * self,PyObject * args)2211 PyCurses_color_pair(PyObject *self, PyObject *args)
2212 {
2213     int n;
2214 
2215     PyCursesInitialised;
2216     PyCursesInitialisedColor;
2217 
2218     if (!PyArg_ParseTuple(args, "i:color_pair", &n)) return NULL;
2219     return PyLong_FromLong(color_pair_to_attr(n));
2220 }
2221 
2222 static PyObject *
PyCurses_Curs_Set(PyObject * self,PyObject * args)2223 PyCurses_Curs_Set(PyObject *self, PyObject *args)
2224 {
2225     int vis,erg;
2226 
2227     PyCursesInitialised;
2228 
2229     if (!PyArg_ParseTuple(args, "i:curs_set", &vis)) return NULL;
2230 
2231     erg = curs_set(vis);
2232     if (erg == ERR) return PyCursesCheckERR(erg, "curs_set");
2233 
2234     return PyLong_FromLong((long) erg);
2235 }
2236 
2237 static PyObject *
PyCurses_Delay_Output(PyObject * self,PyObject * args)2238 PyCurses_Delay_Output(PyObject *self, PyObject *args)
2239 {
2240     int ms;
2241 
2242     PyCursesInitialised;
2243 
2244     if (!PyArg_ParseTuple(args, "i:delay_output", &ms)) return NULL;
2245 
2246     return PyCursesCheckERR(delay_output(ms), "delay_output");
2247 }
2248 
2249 static PyObject *
PyCurses_EraseChar(PyObject * self)2250 PyCurses_EraseChar(PyObject *self)
2251 {
2252     char ch;
2253 
2254     PyCursesInitialised;
2255 
2256     ch = erasechar();
2257 
2258     return PyBytes_FromStringAndSize(&ch, 1);
2259 }
2260 
2261 #ifdef getsyx
2262 static PyObject *
PyCurses_getsyx(PyObject * self)2263 PyCurses_getsyx(PyObject *self)
2264 {
2265     int x = 0;
2266     int y = 0;
2267 
2268     PyCursesInitialised;
2269 
2270     getsyx(y, x);
2271 
2272     return Py_BuildValue("(ii)", y, x);
2273 }
2274 #endif
2275 
2276 #ifdef NCURSES_MOUSE_VERSION
2277 static PyObject *
PyCurses_GetMouse(PyObject * self)2278 PyCurses_GetMouse(PyObject *self)
2279 {
2280     int rtn;
2281     MEVENT event;
2282 
2283     PyCursesInitialised;
2284 
2285     rtn = getmouse( &event );
2286     if (rtn == ERR) {
2287         PyErr_SetString(PyCursesError, "getmouse() returned ERR");
2288         return NULL;
2289     }
2290     return Py_BuildValue("(hiiik)",
2291                          (short)event.id,
2292                          (int)event.x, (int)event.y, (int)event.z,
2293                          (unsigned long) event.bstate);
2294 }
2295 
2296 static PyObject *
PyCurses_UngetMouse(PyObject * self,PyObject * args)2297 PyCurses_UngetMouse(PyObject *self, PyObject *args)
2298 {
2299     MEVENT event;
2300     short id;
2301     int x, y, z;
2302     unsigned long bstate;
2303 
2304     PyCursesInitialised;
2305     if (!PyArg_ParseTuple(args, "hiiik",
2306                           &id, &x, &y, &z, &bstate))
2307         return NULL;
2308 
2309     event.id = id;
2310     event.x = x;
2311     event.y = y;
2312     event.z = z;
2313     event.bstate = bstate;
2314     return PyCursesCheckERR(ungetmouse(&event), "ungetmouse");
2315 }
2316 #endif
2317 
2318 static PyObject *
PyCurses_GetWin(PyCursesWindowObject * self,PyObject * stream)2319 PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream)
2320 {
2321     FILE *fp;
2322     PyObject *data;
2323     size_t datalen;
2324     WINDOW *win;
2325     _Py_IDENTIFIER(read);
2326     PyObject *res = NULL;
2327 
2328     PyCursesInitialised;
2329 
2330     fp = tmpfile();
2331     if (fp == NULL)
2332         return PyErr_SetFromErrno(PyExc_OSError);
2333 
2334     if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0)
2335         goto error;
2336 
2337 
2338     data = _PyObject_CallMethodId(stream, &PyId_read, NULL);
2339     if (data == NULL)
2340         goto error;
2341     if (!PyBytes_Check(data)) {
2342         PyErr_Format(PyExc_TypeError,
2343                      "f.read() returned %.100s instead of bytes",
2344                      data->ob_type->tp_name);
2345         Py_DECREF(data);
2346         goto error;
2347     }
2348     datalen = PyBytes_GET_SIZE(data);
2349     if (fwrite(PyBytes_AS_STRING(data), 1, datalen, fp) != datalen) {
2350         Py_DECREF(data);
2351         PyErr_SetFromErrno(PyExc_OSError);
2352         goto error;
2353     }
2354     Py_DECREF(data);
2355 
2356     fseek(fp, 0, 0);
2357     win = getwin(fp);
2358     if (win == NULL) {
2359         PyErr_SetString(PyCursesError, catchall_NULL);
2360         goto error;
2361     }
2362     res = PyCursesWindow_New(win, NULL);
2363 
2364 error:
2365     fclose(fp);
2366     return res;
2367 }
2368 
2369 static PyObject *
PyCurses_HalfDelay(PyObject * self,PyObject * args)2370 PyCurses_HalfDelay(PyObject *self, PyObject *args)
2371 {
2372     unsigned char tenths;
2373 
2374     PyCursesInitialised;
2375 
2376     if (!PyArg_ParseTuple(args, "b:halfdelay", &tenths)) return NULL;
2377 
2378     return PyCursesCheckERR(halfdelay(tenths), "halfdelay");
2379 }
2380 
2381 #ifdef HAVE_CURSES_HAS_KEY
2382 static PyObject *
PyCurses_has_key(PyObject * self,PyObject * args)2383 PyCurses_has_key(PyObject *self, PyObject *args)
2384 {
2385     int ch;
2386 
2387     PyCursesInitialised;
2388 
2389     if (!PyArg_ParseTuple(args,"i",&ch)) return NULL;
2390 
2391     if (has_key(ch) == FALSE) {
2392         Py_RETURN_FALSE;
2393     }
2394     Py_RETURN_TRUE;
2395 }
2396 #endif
2397 
2398 static PyObject *
PyCurses_Init_Color(PyObject * self,PyObject * args)2399 PyCurses_Init_Color(PyObject *self, PyObject *args)
2400 {
2401     short color, r, g, b;
2402 
2403     PyCursesInitialised;
2404     PyCursesInitialisedColor;
2405 
2406     switch(PyTuple_Size(args)) {
2407     case 4:
2408         if (!PyArg_ParseTuple(args, "hhhh;color,r,g,b", &color, &r, &g, &b)) return NULL;
2409         break;
2410     default:
2411         PyErr_SetString(PyExc_TypeError, "init_color requires 4 arguments");
2412         return NULL;
2413     }
2414 
2415     return PyCursesCheckERR(init_color(color, r, g, b), "init_color");
2416 }
2417 
2418 static PyObject *
PyCurses_Init_Pair(PyObject * self,PyObject * args)2419 PyCurses_Init_Pair(PyObject *self, PyObject *args)
2420 {
2421     short pair, f, b;
2422 
2423     PyCursesInitialised;
2424     PyCursesInitialisedColor;
2425 
2426     if (PyTuple_Size(args) != 3) {
2427         PyErr_SetString(PyExc_TypeError, "init_pair requires 3 arguments");
2428         return NULL;
2429     }
2430 
2431     if (!PyArg_ParseTuple(args, "hhh;pair, f, b", &pair, &f, &b)) return NULL;
2432 
2433     return PyCursesCheckERR(init_pair(pair, f, b), "init_pair");
2434 }
2435 
2436 static PyObject *ModDict;
2437 
2438 static PyObject *
PyCurses_InitScr(PyObject * self)2439 PyCurses_InitScr(PyObject *self)
2440 {
2441     WINDOW *win;
2442     PyCursesWindowObject *winobj;
2443 
2444     if (initialised == TRUE) {
2445         wrefresh(stdscr);
2446         return (PyObject *)PyCursesWindow_New(stdscr, NULL);
2447     }
2448 
2449     win = initscr();
2450 
2451     if (win == NULL) {
2452         PyErr_SetString(PyCursesError, catchall_NULL);
2453         return NULL;
2454     }
2455 
2456     initialised = initialised_setupterm = TRUE;
2457 
2458 /* This was moved from initcurses() because it core dumped on SGI,
2459    where they're not defined until you've called initscr() */
2460 #define SetDictInt(string,ch)                                           \
2461     do {                                                                \
2462         PyObject *o = PyLong_FromLong((long) (ch));                     \
2463         if (o && PyDict_SetItemString(ModDict, string, o) == 0)     {   \
2464             Py_DECREF(o);                                               \
2465         }                                                               \
2466     } while (0)
2467 
2468     /* Here are some graphic symbols you can use */
2469     SetDictInt("ACS_ULCORNER",      (ACS_ULCORNER));
2470     SetDictInt("ACS_LLCORNER",      (ACS_LLCORNER));
2471     SetDictInt("ACS_URCORNER",      (ACS_URCORNER));
2472     SetDictInt("ACS_LRCORNER",      (ACS_LRCORNER));
2473     SetDictInt("ACS_LTEE",          (ACS_LTEE));
2474     SetDictInt("ACS_RTEE",          (ACS_RTEE));
2475     SetDictInt("ACS_BTEE",          (ACS_BTEE));
2476     SetDictInt("ACS_TTEE",          (ACS_TTEE));
2477     SetDictInt("ACS_HLINE",         (ACS_HLINE));
2478     SetDictInt("ACS_VLINE",         (ACS_VLINE));
2479     SetDictInt("ACS_PLUS",          (ACS_PLUS));
2480 #if !defined(__hpux) || defined(HAVE_NCURSES_H)
2481     /* On HP/UX 11, these are of type cchar_t, which is not an
2482        integral type. If this is a problem on more platforms, a
2483        configure test should be added to determine whether ACS_S1
2484        is of integral type. */
2485     SetDictInt("ACS_S1",            (ACS_S1));
2486     SetDictInt("ACS_S9",            (ACS_S9));
2487     SetDictInt("ACS_DIAMOND",       (ACS_DIAMOND));
2488     SetDictInt("ACS_CKBOARD",       (ACS_CKBOARD));
2489     SetDictInt("ACS_DEGREE",        (ACS_DEGREE));
2490     SetDictInt("ACS_PLMINUS",       (ACS_PLMINUS));
2491     SetDictInt("ACS_BULLET",        (ACS_BULLET));
2492     SetDictInt("ACS_LARROW",        (ACS_LARROW));
2493     SetDictInt("ACS_RARROW",        (ACS_RARROW));
2494     SetDictInt("ACS_DARROW",        (ACS_DARROW));
2495     SetDictInt("ACS_UARROW",        (ACS_UARROW));
2496     SetDictInt("ACS_BOARD",         (ACS_BOARD));
2497     SetDictInt("ACS_LANTERN",       (ACS_LANTERN));
2498     SetDictInt("ACS_BLOCK",         (ACS_BLOCK));
2499 #endif
2500     SetDictInt("ACS_BSSB",          (ACS_ULCORNER));
2501     SetDictInt("ACS_SSBB",          (ACS_LLCORNER));
2502     SetDictInt("ACS_BBSS",          (ACS_URCORNER));
2503     SetDictInt("ACS_SBBS",          (ACS_LRCORNER));
2504     SetDictInt("ACS_SBSS",          (ACS_RTEE));
2505     SetDictInt("ACS_SSSB",          (ACS_LTEE));
2506     SetDictInt("ACS_SSBS",          (ACS_BTEE));
2507     SetDictInt("ACS_BSSS",          (ACS_TTEE));
2508     SetDictInt("ACS_BSBS",          (ACS_HLINE));
2509     SetDictInt("ACS_SBSB",          (ACS_VLINE));
2510     SetDictInt("ACS_SSSS",          (ACS_PLUS));
2511 
2512     /* The following are never available with strict SYSV curses */
2513 #ifdef ACS_S3
2514     SetDictInt("ACS_S3",            (ACS_S3));
2515 #endif
2516 #ifdef ACS_S7
2517     SetDictInt("ACS_S7",            (ACS_S7));
2518 #endif
2519 #ifdef ACS_LEQUAL
2520     SetDictInt("ACS_LEQUAL",        (ACS_LEQUAL));
2521 #endif
2522 #ifdef ACS_GEQUAL
2523     SetDictInt("ACS_GEQUAL",        (ACS_GEQUAL));
2524 #endif
2525 #ifdef ACS_PI
2526     SetDictInt("ACS_PI",            (ACS_PI));
2527 #endif
2528 #ifdef ACS_NEQUAL
2529     SetDictInt("ACS_NEQUAL",        (ACS_NEQUAL));
2530 #endif
2531 #ifdef ACS_STERLING
2532     SetDictInt("ACS_STERLING",      (ACS_STERLING));
2533 #endif
2534 
2535     SetDictInt("LINES", LINES);
2536     SetDictInt("COLS", COLS);
2537 
2538     winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL);
2539     screen_encoding = winobj->encoding;
2540     return (PyObject *)winobj;
2541 }
2542 
2543 static PyObject *
PyCurses_setupterm(PyObject * self,PyObject * args,PyObject * keywds)2544 PyCurses_setupterm(PyObject* self, PyObject *args, PyObject* keywds)
2545 {
2546     int fd = -1;
2547     int err;
2548     char* termstr = NULL;
2549 
2550     static char *kwlist[] = {"term", "fd", NULL};
2551 
2552     if (!PyArg_ParseTupleAndKeywords(
2553             args, keywds, "|zi:setupterm", kwlist, &termstr, &fd)) {
2554         return NULL;
2555     }
2556 
2557     if (fd == -1) {
2558         PyObject* sys_stdout;
2559 
2560         sys_stdout = PySys_GetObject("stdout");
2561 
2562         if (sys_stdout == NULL || sys_stdout == Py_None) {
2563             PyErr_SetString(
2564                 PyCursesError,
2565                 "lost sys.stdout");
2566             return NULL;
2567         }
2568 
2569         fd = PyObject_AsFileDescriptor(sys_stdout);
2570 
2571         if (fd == -1) {
2572             return NULL;
2573         }
2574     }
2575 
2576     if (!initialised_setupterm && setupterm(termstr,fd,&err) == ERR) {
2577         const char* s = "setupterm: unknown error";
2578 
2579         if (err == 0) {
2580             s = "setupterm: could not find terminal";
2581         } else if (err == -1) {
2582             s = "setupterm: could not find terminfo database";
2583         }
2584 
2585         PyErr_SetString(PyCursesError,s);
2586         return NULL;
2587     }
2588 
2589     initialised_setupterm = TRUE;
2590 
2591     Py_RETURN_NONE;
2592 }
2593 
2594 static PyObject *
PyCurses_IntrFlush(PyObject * self,PyObject * args)2595 PyCurses_IntrFlush(PyObject *self, PyObject *args)
2596 {
2597     int ch;
2598 
2599     PyCursesInitialised;
2600 
2601     switch(PyTuple_Size(args)) {
2602     case 1:
2603         if (!PyArg_ParseTuple(args,"i;True(1), False(0)",&ch)) return NULL;
2604         break;
2605     default:
2606         PyErr_SetString(PyExc_TypeError, "intrflush requires 1 argument");
2607         return NULL;
2608     }
2609 
2610     return PyCursesCheckERR(intrflush(NULL,ch), "intrflush");
2611 }
2612 
2613 #ifdef HAVE_CURSES_IS_TERM_RESIZED
2614 static PyObject *
PyCurses_Is_Term_Resized(PyObject * self,PyObject * args)2615 PyCurses_Is_Term_Resized(PyObject *self, PyObject *args)
2616 {
2617     int lines;
2618     int columns;
2619     int result;
2620 
2621     PyCursesInitialised;
2622 
2623     if (!PyArg_ParseTuple(args,"ii:is_term_resized", &lines, &columns))
2624         return NULL;
2625     result = is_term_resized(lines, columns);
2626     if (result == TRUE) {
2627         Py_RETURN_TRUE;
2628     } else {
2629         Py_RETURN_FALSE;
2630     }
2631 }
2632 #endif /* HAVE_CURSES_IS_TERM_RESIZED */
2633 
2634 static PyObject *
PyCurses_KeyName(PyObject * self,PyObject * args)2635 PyCurses_KeyName(PyObject *self, PyObject *args)
2636 {
2637     const char *knp;
2638     int ch;
2639 
2640     PyCursesInitialised;
2641 
2642     if (!PyArg_ParseTuple(args,"i",&ch)) return NULL;
2643 
2644     if (ch < 0) {
2645         PyErr_SetString(PyExc_ValueError, "invalid key number");
2646         return NULL;
2647     }
2648     knp = keyname(ch);
2649 
2650     return PyBytes_FromString((knp == NULL) ? "" : knp);
2651 }
2652 
2653 static PyObject *
PyCurses_KillChar(PyObject * self)2654 PyCurses_KillChar(PyObject *self)
2655 {
2656     char ch;
2657 
2658     ch = killchar();
2659 
2660     return PyBytes_FromStringAndSize(&ch, 1);
2661 }
2662 
2663 static PyObject *
PyCurses_Meta(PyObject * self,PyObject * args)2664 PyCurses_Meta(PyObject *self, PyObject *args)
2665 {
2666     int ch;
2667 
2668     PyCursesInitialised;
2669 
2670     switch(PyTuple_Size(args)) {
2671     case 1:
2672         if (!PyArg_ParseTuple(args,"i;True(1), False(0)",&ch)) return NULL;
2673         break;
2674     default:
2675         PyErr_SetString(PyExc_TypeError, "meta requires 1 argument");
2676         return NULL;
2677     }
2678 
2679     return PyCursesCheckERR(meta(stdscr, ch), "meta");
2680 }
2681 
2682 #ifdef NCURSES_MOUSE_VERSION
2683 static PyObject *
PyCurses_MouseInterval(PyObject * self,PyObject * args)2684 PyCurses_MouseInterval(PyObject *self, PyObject *args)
2685 {
2686     int interval;
2687     PyCursesInitialised;
2688 
2689     if (!PyArg_ParseTuple(args,"i;interval",&interval))
2690         return NULL;
2691     return PyCursesCheckERR(mouseinterval(interval), "mouseinterval");
2692 }
2693 
2694 static PyObject *
PyCurses_MouseMask(PyObject * self,PyObject * args)2695 PyCurses_MouseMask(PyObject *self, PyObject *args)
2696 {
2697     unsigned long newmask;
2698     mmask_t oldmask, availmask;
2699 
2700     PyCursesInitialised;
2701     if (!PyArg_ParseTuple(args,"k;mousemask",&newmask))
2702         return NULL;
2703     availmask = mousemask((mmask_t)newmask, &oldmask);
2704     return Py_BuildValue("(kk)",
2705                          (unsigned long)availmask, (unsigned long)oldmask);
2706 }
2707 #endif
2708 
2709 static PyObject *
PyCurses_Napms(PyObject * self,PyObject * args)2710 PyCurses_Napms(PyObject *self, PyObject *args)
2711 {
2712     int ms;
2713 
2714     PyCursesInitialised;
2715     if (!PyArg_ParseTuple(args, "i;ms", &ms)) return NULL;
2716 
2717     return Py_BuildValue("i", napms(ms));
2718 }
2719 
2720 
2721 static PyObject *
PyCurses_NewPad(PyObject * self,PyObject * args)2722 PyCurses_NewPad(PyObject *self, PyObject *args)
2723 {
2724     WINDOW *win;
2725     int nlines, ncols;
2726 
2727     PyCursesInitialised;
2728 
2729     if (!PyArg_ParseTuple(args,"ii;nlines,ncols",&nlines,&ncols)) return NULL;
2730 
2731     win = newpad(nlines, ncols);
2732 
2733     if (win == NULL) {
2734         PyErr_SetString(PyCursesError, catchall_NULL);
2735         return NULL;
2736     }
2737 
2738     return (PyObject *)PyCursesWindow_New(win, NULL);
2739 }
2740 
2741 static PyObject *
PyCurses_NewWindow(PyObject * self,PyObject * args)2742 PyCurses_NewWindow(PyObject *self, PyObject *args)
2743 {
2744     WINDOW *win;
2745     int nlines, ncols, begin_y=0, begin_x=0;
2746 
2747     PyCursesInitialised;
2748 
2749     switch (PyTuple_Size(args)) {
2750     case 2:
2751         if (!PyArg_ParseTuple(args,"ii;nlines,ncols",&nlines,&ncols))
2752             return NULL;
2753         break;
2754     case 4:
2755         if (!PyArg_ParseTuple(args, "iiii;nlines,ncols,begin_y,begin_x",
2756                               &nlines,&ncols,&begin_y,&begin_x))
2757             return NULL;
2758         break;
2759     default:
2760         PyErr_SetString(PyExc_TypeError, "newwin requires 2 or 4 arguments");
2761         return NULL;
2762     }
2763 
2764     win = newwin(nlines,ncols,begin_y,begin_x);
2765     if (win == NULL) {
2766         PyErr_SetString(PyCursesError, catchall_NULL);
2767         return NULL;
2768     }
2769 
2770     return (PyObject *)PyCursesWindow_New(win, NULL);
2771 }
2772 
2773 static PyObject *
PyCurses_Pair_Content(PyObject * self,PyObject * args)2774 PyCurses_Pair_Content(PyObject *self, PyObject *args)
2775 {
2776     short pair,f,b;
2777 
2778     PyCursesInitialised;
2779     PyCursesInitialisedColor;
2780 
2781     switch(PyTuple_Size(args)) {
2782     case 1:
2783         if (!PyArg_ParseTuple(args, "h;pair", &pair)) return NULL;
2784         break;
2785     default:
2786         PyErr_SetString(PyExc_TypeError, "pair_content requires 1 argument");
2787         return NULL;
2788     }
2789 
2790     if (pair_content(pair, &f, &b)==ERR) {
2791         PyErr_SetString(PyCursesError,
2792                         "Argument 1 was out of range. (1..COLOR_PAIRS-1)");
2793         return NULL;
2794     }
2795 
2796     return Py_BuildValue("(ii)", f, b);
2797 }
2798 
2799 static PyObject *
PyCurses_pair_number(PyObject * self,PyObject * args)2800 PyCurses_pair_number(PyObject *self, PyObject *args)
2801 {
2802     int n;
2803 
2804     PyCursesInitialised;
2805     PyCursesInitialisedColor;
2806 
2807     switch(PyTuple_Size(args)) {
2808     case 1:
2809         if (!PyArg_ParseTuple(args, "i;pairvalue", &n)) return NULL;
2810         break;
2811     default:
2812         PyErr_SetString(PyExc_TypeError,
2813                         "pair_number requires 1 argument");
2814         return NULL;
2815     }
2816 
2817     return PyLong_FromLong(attr_to_color_pair(n));
2818 }
2819 
2820 static PyObject *
PyCurses_Putp(PyObject * self,PyObject * args)2821 PyCurses_Putp(PyObject *self, PyObject *args)
2822 {
2823     char *str;
2824 
2825     if (!PyArg_ParseTuple(args,"y;str", &str))
2826         return NULL;
2827     return PyCursesCheckERR(putp(str), "putp");
2828 }
2829 
2830 static PyObject *
PyCurses_QiFlush(PyObject * self,PyObject * args)2831 PyCurses_QiFlush(PyObject *self, PyObject *args)
2832 {
2833     int flag = 0;
2834 
2835     PyCursesInitialised;
2836 
2837     switch(PyTuple_Size(args)) {
2838     case 0:
2839         qiflush();
2840         Py_RETURN_NONE;
2841     case 1:
2842         if (!PyArg_ParseTuple(args, "i;True(1) or False(0)", &flag)) return NULL;
2843         if (flag) qiflush();
2844         else noqiflush();
2845         Py_RETURN_NONE;
2846     default:
2847         PyErr_SetString(PyExc_TypeError, "qiflush requires 0 or 1 arguments");
2848         return NULL;
2849     }
2850 }
2851 
2852 /* Internal helper used for updating curses.LINES, curses.COLS, _curses.LINES
2853  * and _curses.COLS */
2854 #if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)
2855 static int
update_lines_cols(void)2856 update_lines_cols(void)
2857 {
2858     PyObject *o;
2859     PyObject *m = PyImport_ImportModuleNoBlock("curses");
2860     _Py_IDENTIFIER(LINES);
2861     _Py_IDENTIFIER(COLS);
2862 
2863     if (!m)
2864         return 0;
2865 
2866     o = PyLong_FromLong(LINES);
2867     if (!o) {
2868         Py_DECREF(m);
2869         return 0;
2870     }
2871     if (_PyObject_SetAttrId(m, &PyId_LINES, o)) {
2872         Py_DECREF(m);
2873         Py_DECREF(o);
2874         return 0;
2875     }
2876     /* PyId_LINES.object will be initialized here. */
2877     if (PyDict_SetItem(ModDict, PyId_LINES.object, o)) {
2878         Py_DECREF(m);
2879         Py_DECREF(o);
2880         return 0;
2881     }
2882     Py_DECREF(o);
2883     o = PyLong_FromLong(COLS);
2884     if (!o) {
2885         Py_DECREF(m);
2886         return 0;
2887     }
2888     if (_PyObject_SetAttrId(m, &PyId_COLS, o)) {
2889         Py_DECREF(m);
2890         Py_DECREF(o);
2891         return 0;
2892     }
2893     if (PyDict_SetItem(ModDict, PyId_COLS.object, o)) {
2894         Py_DECREF(m);
2895         Py_DECREF(o);
2896         return 0;
2897     }
2898     Py_DECREF(o);
2899     Py_DECREF(m);
2900     return 1;
2901 }
2902 
2903 static PyObject *
PyCurses_update_lines_cols(PyObject * self)2904 PyCurses_update_lines_cols(PyObject *self)
2905 {
2906   return PyLong_FromLong((long) update_lines_cols());
2907 }
2908 
2909 #endif
2910 
2911 #ifdef HAVE_CURSES_RESIZETERM
2912 static PyObject *
PyCurses_ResizeTerm(PyObject * self,PyObject * args)2913 PyCurses_ResizeTerm(PyObject *self, PyObject *args)
2914 {
2915     int lines;
2916     int columns;
2917     PyObject *result;
2918 
2919     PyCursesInitialised;
2920 
2921     if (!PyArg_ParseTuple(args,"ii:resizeterm", &lines, &columns))
2922         return NULL;
2923 
2924     result = PyCursesCheckERR(resizeterm(lines, columns), "resizeterm");
2925     if (!result)
2926         return NULL;
2927     if (!update_lines_cols())
2928         return NULL;
2929     return result;
2930 }
2931 
2932 #endif
2933 
2934 #ifdef HAVE_CURSES_RESIZE_TERM
2935 static PyObject *
PyCurses_Resize_Term(PyObject * self,PyObject * args)2936 PyCurses_Resize_Term(PyObject *self, PyObject *args)
2937 {
2938     int lines;
2939     int columns;
2940 
2941     PyObject *result;
2942 
2943     PyCursesInitialised;
2944 
2945     if (!PyArg_ParseTuple(args,"ii:resize_term", &lines, &columns))
2946         return NULL;
2947 
2948     result = PyCursesCheckERR(resize_term(lines, columns), "resize_term");
2949     if (!result)
2950         return NULL;
2951     if (!update_lines_cols())
2952         return NULL;
2953     return result;
2954 }
2955 #endif /* HAVE_CURSES_RESIZE_TERM */
2956 
2957 #ifdef getsyx
2958 static PyObject *
PyCurses_setsyx(PyObject * self,PyObject * args)2959 PyCurses_setsyx(PyObject *self, PyObject *args)
2960 {
2961     int y,x;
2962 
2963     PyCursesInitialised;
2964 
2965     if (PyTuple_Size(args)!=2) {
2966         PyErr_SetString(PyExc_TypeError, "setsyx requires 2 arguments");
2967         return NULL;
2968     }
2969 
2970     if (!PyArg_ParseTuple(args, "ii;y, x", &y, &x)) return NULL;
2971 
2972     setsyx(y,x);
2973 
2974     Py_RETURN_NONE;
2975 }
2976 #endif
2977 
2978 static PyObject *
PyCurses_Start_Color(PyObject * self)2979 PyCurses_Start_Color(PyObject *self)
2980 {
2981     int code;
2982     PyObject *c, *cp;
2983 
2984     PyCursesInitialised;
2985 
2986     code = start_color();
2987     if (code != ERR) {
2988         initialisedcolors = TRUE;
2989         c = PyLong_FromLong((long) COLORS);
2990         if (c == NULL)
2991             return NULL;
2992         PyDict_SetItemString(ModDict, "COLORS", c);
2993         Py_DECREF(c);
2994         cp = PyLong_FromLong((long) COLOR_PAIRS);
2995         if (cp == NULL)
2996             return NULL;
2997         PyDict_SetItemString(ModDict, "COLOR_PAIRS", cp);
2998         Py_DECREF(cp);
2999         Py_RETURN_NONE;
3000     } else {
3001         PyErr_SetString(PyCursesError, "start_color() returned ERR");
3002         return NULL;
3003     }
3004 }
3005 
3006 static PyObject *
PyCurses_tigetflag(PyObject * self,PyObject * args)3007 PyCurses_tigetflag(PyObject *self, PyObject *args)
3008 {
3009     char *capname;
3010 
3011     PyCursesSetupTermCalled;
3012 
3013     if (!PyArg_ParseTuple(args, "s", &capname))
3014         return NULL;
3015 
3016     return PyLong_FromLong( (long) tigetflag( capname ) );
3017 }
3018 
3019 static PyObject *
PyCurses_tigetnum(PyObject * self,PyObject * args)3020 PyCurses_tigetnum(PyObject *self, PyObject *args)
3021 {
3022     char *capname;
3023 
3024     PyCursesSetupTermCalled;
3025 
3026     if (!PyArg_ParseTuple(args, "s", &capname))
3027         return NULL;
3028 
3029     return PyLong_FromLong( (long) tigetnum( capname ) );
3030 }
3031 
3032 static PyObject *
PyCurses_tigetstr(PyObject * self,PyObject * args)3033 PyCurses_tigetstr(PyObject *self, PyObject *args)
3034 {
3035     char *capname;
3036 
3037     PyCursesSetupTermCalled;
3038 
3039     if (!PyArg_ParseTuple(args, "s", &capname))
3040         return NULL;
3041 
3042     capname = tigetstr( capname );
3043     if (capname == NULL || capname == (char*) -1) {
3044         Py_RETURN_NONE;
3045     }
3046     return PyBytes_FromString( capname );
3047 }
3048 
3049 static PyObject *
PyCurses_tparm(PyObject * self,PyObject * args)3050 PyCurses_tparm(PyObject *self, PyObject *args)
3051 {
3052     char* fmt;
3053     char* result = NULL;
3054     int i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0,i8=0,i9=0;
3055 
3056     PyCursesSetupTermCalled;
3057 
3058     if (!PyArg_ParseTuple(args, "y|iiiiiiiii:tparm",
3059                           &fmt, &i1, &i2, &i3, &i4,
3060                           &i5, &i6, &i7, &i8, &i9)) {
3061         return NULL;
3062     }
3063 
3064     result = tparm(fmt,i1,i2,i3,i4,i5,i6,i7,i8,i9);
3065     if (!result) {
3066         PyErr_SetString(PyCursesError, "tparm() returned NULL");
3067         return NULL;
3068     }
3069 
3070     return PyBytes_FromString(result);
3071 }
3072 
3073 #ifdef HAVE_CURSES_TYPEAHEAD
3074 static PyObject *
PyCurses_TypeAhead(PyObject * self,PyObject * args)3075 PyCurses_TypeAhead(PyObject *self, PyObject *args)
3076 {
3077     int fd;
3078 
3079     PyCursesInitialised;
3080 
3081     if (!PyArg_ParseTuple(args,"i;fd",&fd)) return NULL;
3082 
3083     return PyCursesCheckERR(typeahead( fd ), "typeahead");
3084 }
3085 #endif
3086 
3087 static PyObject *
PyCurses_UnCtrl(PyObject * self,PyObject * args)3088 PyCurses_UnCtrl(PyObject *self, PyObject *args)
3089 {
3090     PyObject *temp;
3091     chtype ch;
3092 
3093     PyCursesInitialised;
3094 
3095     if (!PyArg_ParseTuple(args,"O;ch or int",&temp)) return NULL;
3096 
3097     if (!PyCurses_ConvertToChtype(NULL, temp, &ch))
3098         return NULL;
3099 
3100     return PyBytes_FromString(unctrl(ch));
3101 }
3102 
3103 static PyObject *
PyCurses_UngetCh(PyObject * self,PyObject * args)3104 PyCurses_UngetCh(PyObject *self, PyObject *args)
3105 {
3106     PyObject *temp;
3107     chtype ch;
3108 
3109     PyCursesInitialised;
3110 
3111     if (!PyArg_ParseTuple(args,"O;ch or int",&temp))
3112         return NULL;
3113 
3114     if (!PyCurses_ConvertToChtype(NULL, temp, &ch))
3115         return NULL;
3116 
3117     return PyCursesCheckERR(ungetch(ch), "ungetch");
3118 }
3119 
3120 #ifdef HAVE_NCURSESW
3121 /* Convert an object to a character (wchar_t):
3122 
3123     - int
3124     - str of length 1
3125 
3126    Return 1 on success, 0 on error. */
3127 static int
PyCurses_ConvertToWchar_t(PyObject * obj,wchar_t * wch)3128 PyCurses_ConvertToWchar_t(PyObject *obj,
3129                           wchar_t *wch)
3130 {
3131     if (PyUnicode_Check(obj)) {
3132         wchar_t buffer[2];
3133         if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) {
3134             PyErr_Format(PyExc_TypeError,
3135                          "expect str of length 1 or int, "
3136                          "got a str of length %zi",
3137                          PyUnicode_GET_LENGTH(obj));
3138             return 0;
3139         }
3140         *wch = buffer[0];
3141         return 2;
3142     }
3143     else if (PyLong_CheckExact(obj)) {
3144         long value;
3145         int overflow;
3146         value = PyLong_AsLongAndOverflow(obj, &overflow);
3147         if (overflow) {
3148             PyErr_SetString(PyExc_OverflowError,
3149                             "int doesn't fit in long");
3150             return 0;
3151         }
3152         *wch = (wchar_t)value;
3153         if ((long)*wch != value) {
3154             PyErr_Format(PyExc_OverflowError,
3155                          "character doesn't fit in wchar_t");
3156             return 0;
3157         }
3158         return 1;
3159     }
3160     else {
3161         PyErr_Format(PyExc_TypeError,
3162                      "expect str of length 1 or int, got %s",
3163                      Py_TYPE(obj)->tp_name);
3164         return 0;
3165     }
3166 }
3167 
3168 static PyObject *
PyCurses_Unget_Wch(PyObject * self,PyObject * args)3169 PyCurses_Unget_Wch(PyObject *self, PyObject *args)
3170 {
3171     PyObject *obj;
3172     wchar_t wch;
3173 
3174     PyCursesInitialised;
3175 
3176     if (!PyArg_ParseTuple(args,"O", &obj))
3177         return NULL;
3178 
3179     if (!PyCurses_ConvertToWchar_t(obj, &wch))
3180         return NULL;
3181     return PyCursesCheckERR(unget_wch(wch), "unget_wch");
3182 }
3183 #endif
3184 
3185 #ifdef HAVE_CURSES_TYPEAHEAD
3186 static PyObject *
PyCurses_Use_Env(PyObject * self,PyObject * args)3187 PyCurses_Use_Env(PyObject *self, PyObject *args)
3188 {
3189     int flag;
3190 
3191     switch(PyTuple_Size(args)) {
3192     case 1:
3193         if (!PyArg_ParseTuple(args,"i;True(1), False(0)",&flag))
3194             return NULL;
3195         break;
3196     default:
3197         PyErr_SetString(PyExc_TypeError, "use_env requires 1 argument");
3198         return NULL;
3199     }
3200     use_env(flag);
3201     Py_RETURN_NONE;
3202 }
3203 #endif
3204 
3205 #ifndef STRICT_SYSV_CURSES
3206 static PyObject *
PyCurses_Use_Default_Colors(PyObject * self)3207 PyCurses_Use_Default_Colors(PyObject *self)
3208 {
3209     int code;
3210 
3211     PyCursesInitialised;
3212     PyCursesInitialisedColor;
3213 
3214     code = use_default_colors();
3215     if (code != ERR) {
3216         Py_RETURN_NONE;
3217     } else {
3218         PyErr_SetString(PyCursesError, "use_default_colors() returned ERR");
3219         return NULL;
3220     }
3221 }
3222 #endif /* STRICT_SYSV_CURSES */
3223 
3224 /* List of functions defined in the module */
3225 
3226 static PyMethodDef PyCurses_methods[] = {
3227     {"baudrate",            (PyCFunction)PyCurses_baudrate, METH_NOARGS},
3228     {"beep",                (PyCFunction)PyCurses_beep, METH_NOARGS},
3229     {"can_change_color",    (PyCFunction)PyCurses_can_change_color, METH_NOARGS},
3230     {"cbreak",              (PyCFunction)PyCurses_cbreak, METH_VARARGS},
3231     {"color_content",       (PyCFunction)PyCurses_Color_Content, METH_VARARGS},
3232     {"color_pair",          (PyCFunction)PyCurses_color_pair, METH_VARARGS},
3233     {"curs_set",            (PyCFunction)PyCurses_Curs_Set, METH_VARARGS},
3234     {"def_prog_mode",       (PyCFunction)PyCurses_def_prog_mode, METH_NOARGS},
3235     {"def_shell_mode",      (PyCFunction)PyCurses_def_shell_mode, METH_NOARGS},
3236     {"delay_output",        (PyCFunction)PyCurses_Delay_Output, METH_VARARGS},
3237     {"doupdate",            (PyCFunction)PyCurses_doupdate, METH_NOARGS},
3238     {"echo",                (PyCFunction)PyCurses_echo, METH_VARARGS},
3239     {"endwin",              (PyCFunction)PyCurses_endwin, METH_NOARGS},
3240     {"erasechar",           (PyCFunction)PyCurses_EraseChar, METH_NOARGS},
3241 #ifdef HAVE_CURSES_FILTER
3242     {"filter",              (PyCFunction)PyCurses_filter, METH_NOARGS},
3243 #endif
3244     {"flash",               (PyCFunction)PyCurses_flash, METH_NOARGS},
3245     {"flushinp",            (PyCFunction)PyCurses_flushinp, METH_NOARGS},
3246 #ifdef NCURSES_MOUSE_VERSION
3247     {"getmouse",            (PyCFunction)PyCurses_GetMouse, METH_NOARGS},
3248     {"ungetmouse",          (PyCFunction)PyCurses_UngetMouse, METH_VARARGS},
3249 #endif
3250 #ifdef getsyx
3251     {"getsyx",              (PyCFunction)PyCurses_getsyx, METH_NOARGS},
3252 #endif
3253     {"getwin",              (PyCFunction)PyCurses_GetWin, METH_O},
3254     {"has_colors",          (PyCFunction)PyCurses_has_colors, METH_NOARGS},
3255     {"has_ic",              (PyCFunction)PyCurses_has_ic, METH_NOARGS},
3256     {"has_il",              (PyCFunction)PyCurses_has_il, METH_NOARGS},
3257 #ifdef HAVE_CURSES_HAS_KEY
3258     {"has_key",             (PyCFunction)PyCurses_has_key, METH_VARARGS},
3259 #endif
3260     {"halfdelay",           (PyCFunction)PyCurses_HalfDelay, METH_VARARGS},
3261     {"init_color",          (PyCFunction)PyCurses_Init_Color, METH_VARARGS},
3262     {"init_pair",           (PyCFunction)PyCurses_Init_Pair, METH_VARARGS},
3263     {"initscr",             (PyCFunction)PyCurses_InitScr, METH_NOARGS},
3264     {"intrflush",           (PyCFunction)PyCurses_IntrFlush, METH_VARARGS},
3265     {"isendwin",            (PyCFunction)PyCurses_isendwin, METH_NOARGS},
3266 #ifdef HAVE_CURSES_IS_TERM_RESIZED
3267     {"is_term_resized",     (PyCFunction)PyCurses_Is_Term_Resized, METH_VARARGS},
3268 #endif
3269     {"keyname",             (PyCFunction)PyCurses_KeyName, METH_VARARGS},
3270     {"killchar",            (PyCFunction)PyCurses_KillChar, METH_NOARGS},
3271     {"longname",            (PyCFunction)PyCurses_longname, METH_NOARGS},
3272     {"meta",                (PyCFunction)PyCurses_Meta, METH_VARARGS},
3273 #ifdef NCURSES_MOUSE_VERSION
3274     {"mouseinterval",       (PyCFunction)PyCurses_MouseInterval, METH_VARARGS},
3275     {"mousemask",           (PyCFunction)PyCurses_MouseMask, METH_VARARGS},
3276 #endif
3277     {"napms",               (PyCFunction)PyCurses_Napms, METH_VARARGS},
3278     {"newpad",              (PyCFunction)PyCurses_NewPad, METH_VARARGS},
3279     {"newwin",              (PyCFunction)PyCurses_NewWindow, METH_VARARGS},
3280     {"nl",                  (PyCFunction)PyCurses_nl, METH_VARARGS},
3281     {"nocbreak",            (PyCFunction)PyCurses_nocbreak, METH_NOARGS},
3282     {"noecho",              (PyCFunction)PyCurses_noecho, METH_NOARGS},
3283     {"nonl",                (PyCFunction)PyCurses_nonl, METH_NOARGS},
3284     {"noqiflush",           (PyCFunction)PyCurses_noqiflush, METH_NOARGS},
3285     {"noraw",               (PyCFunction)PyCurses_noraw, METH_NOARGS},
3286     {"pair_content",        (PyCFunction)PyCurses_Pair_Content, METH_VARARGS},
3287     {"pair_number",         (PyCFunction)PyCurses_pair_number, METH_VARARGS},
3288     {"putp",                (PyCFunction)PyCurses_Putp, METH_VARARGS},
3289     {"qiflush",             (PyCFunction)PyCurses_QiFlush, METH_VARARGS},
3290     {"raw",                 (PyCFunction)PyCurses_raw, METH_VARARGS},
3291     {"reset_prog_mode",     (PyCFunction)PyCurses_reset_prog_mode, METH_NOARGS},
3292     {"reset_shell_mode",    (PyCFunction)PyCurses_reset_shell_mode, METH_NOARGS},
3293     {"resetty",             (PyCFunction)PyCurses_resetty, METH_NOARGS},
3294 #ifdef HAVE_CURSES_RESIZETERM
3295     {"resizeterm",          (PyCFunction)PyCurses_ResizeTerm, METH_VARARGS},
3296 #endif
3297 #ifdef HAVE_CURSES_RESIZE_TERM
3298     {"resize_term",         (PyCFunction)PyCurses_Resize_Term, METH_VARARGS},
3299 #endif
3300     {"savetty",             (PyCFunction)PyCurses_savetty, METH_NOARGS},
3301 #ifdef getsyx
3302     {"setsyx",              (PyCFunction)PyCurses_setsyx, METH_VARARGS},
3303 #endif
3304     {"setupterm",           (PyCFunction)PyCurses_setupterm,
3305      METH_VARARGS|METH_KEYWORDS},
3306     {"start_color",         (PyCFunction)PyCurses_Start_Color, METH_NOARGS},
3307     {"termattrs",           (PyCFunction)PyCurses_termattrs, METH_NOARGS},
3308     {"termname",            (PyCFunction)PyCurses_termname, METH_NOARGS},
3309     {"tigetflag",           (PyCFunction)PyCurses_tigetflag, METH_VARARGS},
3310     {"tigetnum",            (PyCFunction)PyCurses_tigetnum, METH_VARARGS},
3311     {"tigetstr",            (PyCFunction)PyCurses_tigetstr, METH_VARARGS},
3312     {"tparm",               (PyCFunction)PyCurses_tparm, METH_VARARGS},
3313 #ifdef HAVE_CURSES_TYPEAHEAD
3314     {"typeahead",           (PyCFunction)PyCurses_TypeAhead, METH_VARARGS},
3315 #endif
3316     {"unctrl",              (PyCFunction)PyCurses_UnCtrl, METH_VARARGS},
3317     {"ungetch",             (PyCFunction)PyCurses_UngetCh, METH_VARARGS},
3318 #if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)
3319     {"update_lines_cols",   (PyCFunction)PyCurses_update_lines_cols, METH_NOARGS},
3320 #endif
3321 #ifdef HAVE_NCURSESW
3322     {"unget_wch",           (PyCFunction)PyCurses_Unget_Wch, METH_VARARGS},
3323 #endif
3324 #ifdef HAVE_CURSES_USE_ENV
3325     {"use_env",             (PyCFunction)PyCurses_Use_Env, METH_VARARGS},
3326 #endif
3327 #ifndef STRICT_SYSV_CURSES
3328     {"use_default_colors",  (PyCFunction)PyCurses_Use_Default_Colors, METH_NOARGS},
3329 #endif
3330     {NULL,                  NULL}         /* sentinel */
3331 };
3332 
3333 /* Initialization function for the module */
3334 
3335 
3336 static struct PyModuleDef _cursesmodule = {
3337     PyModuleDef_HEAD_INIT,
3338     "_curses",
3339     NULL,
3340     -1,
3341     PyCurses_methods,
3342     NULL,
3343     NULL,
3344     NULL,
3345     NULL
3346 };
3347 
3348 PyMODINIT_FUNC
PyInit__curses(void)3349 PyInit__curses(void)
3350 {
3351     PyObject *m, *d, *v, *c_api_object;
3352     static void *PyCurses_API[PyCurses_API_pointers];
3353 
3354     /* Initialize object type */
3355     if (PyType_Ready(&PyCursesWindow_Type) < 0)
3356         return NULL;
3357 
3358     /* Initialize the C API pointer array */
3359     PyCurses_API[0] = (void *)&PyCursesWindow_Type;
3360     PyCurses_API[1] = (void *)func_PyCursesSetupTermCalled;
3361     PyCurses_API[2] = (void *)func_PyCursesInitialised;
3362     PyCurses_API[3] = (void *)func_PyCursesInitialisedColor;
3363 
3364     /* Create the module and add the functions */
3365     m = PyModule_Create(&_cursesmodule);
3366     if (m == NULL)
3367         return NULL;
3368 
3369     /* Add some symbolic constants to the module */
3370     d = PyModule_GetDict(m);
3371     if (d == NULL)
3372         return NULL;
3373     ModDict = d; /* For PyCurses_InitScr to use later */
3374 
3375     /* Add a capsule for the C API */
3376     c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, NULL);
3377     PyDict_SetItemString(d, "_C_API", c_api_object);
3378     Py_DECREF(c_api_object);
3379 
3380     /* For exception curses.error */
3381     PyCursesError = PyErr_NewException("_curses.error", NULL, NULL);
3382     PyDict_SetItemString(d, "error", PyCursesError);
3383 
3384     /* Make the version available */
3385     v = PyBytes_FromString(PyCursesVersion);
3386     PyDict_SetItemString(d, "version", v);
3387     PyDict_SetItemString(d, "__version__", v);
3388     Py_DECREF(v);
3389 
3390     SetDictInt("ERR", ERR);
3391     SetDictInt("OK", OK);
3392 
3393     /* Here are some attributes you can add to chars to print */
3394 
3395     SetDictInt("A_ATTRIBUTES",      A_ATTRIBUTES);
3396     SetDictInt("A_NORMAL",              A_NORMAL);
3397     SetDictInt("A_STANDOUT",            A_STANDOUT);
3398     SetDictInt("A_UNDERLINE",           A_UNDERLINE);
3399     SetDictInt("A_REVERSE",             A_REVERSE);
3400     SetDictInt("A_BLINK",               A_BLINK);
3401     SetDictInt("A_DIM",                 A_DIM);
3402     SetDictInt("A_BOLD",                A_BOLD);
3403     SetDictInt("A_ALTCHARSET",          A_ALTCHARSET);
3404     SetDictInt("A_INVIS",           A_INVIS);
3405     SetDictInt("A_PROTECT",         A_PROTECT);
3406     SetDictInt("A_CHARTEXT",        A_CHARTEXT);
3407     SetDictInt("A_COLOR",           A_COLOR);
3408 
3409     /* The following are never available with strict SYSV curses */
3410 #ifdef A_HORIZONTAL
3411     SetDictInt("A_HORIZONTAL",      A_HORIZONTAL);
3412 #endif
3413 #ifdef A_LEFT
3414     SetDictInt("A_LEFT",            A_LEFT);
3415 #endif
3416 #ifdef A_LOW
3417     SetDictInt("A_LOW",             A_LOW);
3418 #endif
3419 #ifdef A_RIGHT
3420     SetDictInt("A_RIGHT",           A_RIGHT);
3421 #endif
3422 #ifdef A_TOP
3423     SetDictInt("A_TOP",             A_TOP);
3424 #endif
3425 #ifdef A_VERTICAL
3426     SetDictInt("A_VERTICAL",        A_VERTICAL);
3427 #endif
3428 
3429     /* ncurses extension */
3430 #ifdef A_ITALIC
3431     SetDictInt("A_ITALIC",          A_ITALIC);
3432 #endif
3433 
3434     SetDictInt("COLOR_BLACK",       COLOR_BLACK);
3435     SetDictInt("COLOR_RED",         COLOR_RED);
3436     SetDictInt("COLOR_GREEN",       COLOR_GREEN);
3437     SetDictInt("COLOR_YELLOW",      COLOR_YELLOW);
3438     SetDictInt("COLOR_BLUE",        COLOR_BLUE);
3439     SetDictInt("COLOR_MAGENTA",     COLOR_MAGENTA);
3440     SetDictInt("COLOR_CYAN",        COLOR_CYAN);
3441     SetDictInt("COLOR_WHITE",       COLOR_WHITE);
3442 
3443 #ifdef NCURSES_MOUSE_VERSION
3444     /* Mouse-related constants */
3445     SetDictInt("BUTTON1_PRESSED",          BUTTON1_PRESSED);
3446     SetDictInt("BUTTON1_RELEASED",         BUTTON1_RELEASED);
3447     SetDictInt("BUTTON1_CLICKED",          BUTTON1_CLICKED);
3448     SetDictInt("BUTTON1_DOUBLE_CLICKED",   BUTTON1_DOUBLE_CLICKED);
3449     SetDictInt("BUTTON1_TRIPLE_CLICKED",   BUTTON1_TRIPLE_CLICKED);
3450 
3451     SetDictInt("BUTTON2_PRESSED",          BUTTON2_PRESSED);
3452     SetDictInt("BUTTON2_RELEASED",         BUTTON2_RELEASED);
3453     SetDictInt("BUTTON2_CLICKED",          BUTTON2_CLICKED);
3454     SetDictInt("BUTTON2_DOUBLE_CLICKED",   BUTTON2_DOUBLE_CLICKED);
3455     SetDictInt("BUTTON2_TRIPLE_CLICKED",   BUTTON2_TRIPLE_CLICKED);
3456 
3457     SetDictInt("BUTTON3_PRESSED",          BUTTON3_PRESSED);
3458     SetDictInt("BUTTON3_RELEASED",         BUTTON3_RELEASED);
3459     SetDictInt("BUTTON3_CLICKED",          BUTTON3_CLICKED);
3460     SetDictInt("BUTTON3_DOUBLE_CLICKED",   BUTTON3_DOUBLE_CLICKED);
3461     SetDictInt("BUTTON3_TRIPLE_CLICKED",   BUTTON3_TRIPLE_CLICKED);
3462 
3463     SetDictInt("BUTTON4_PRESSED",          BUTTON4_PRESSED);
3464     SetDictInt("BUTTON4_RELEASED",         BUTTON4_RELEASED);
3465     SetDictInt("BUTTON4_CLICKED",          BUTTON4_CLICKED);
3466     SetDictInt("BUTTON4_DOUBLE_CLICKED",   BUTTON4_DOUBLE_CLICKED);
3467     SetDictInt("BUTTON4_TRIPLE_CLICKED",   BUTTON4_TRIPLE_CLICKED);
3468 
3469     SetDictInt("BUTTON_SHIFT",             BUTTON_SHIFT);
3470     SetDictInt("BUTTON_CTRL",              BUTTON_CTRL);
3471     SetDictInt("BUTTON_ALT",               BUTTON_ALT);
3472 
3473     SetDictInt("ALL_MOUSE_EVENTS",         ALL_MOUSE_EVENTS);
3474     SetDictInt("REPORT_MOUSE_POSITION",    REPORT_MOUSE_POSITION);
3475 #endif
3476     /* Now set everything up for KEY_ variables */
3477     {
3478         int key;
3479         char *key_n;
3480         char *key_n2;
3481         for (key=KEY_MIN;key < KEY_MAX; key++) {
3482             key_n = (char *)keyname(key);
3483             if (key_n == NULL || strcmp(key_n,"UNKNOWN KEY")==0)
3484                 continue;
3485             if (strncmp(key_n,"KEY_F(",6)==0) {
3486                 char *p1, *p2;
3487                 key_n2 = PyMem_Malloc(strlen(key_n)+1);
3488                 if (!key_n2) {
3489                     PyErr_NoMemory();
3490                     break;
3491                 }
3492                 p1 = key_n;
3493                 p2 = key_n2;
3494                 while (*p1) {
3495                     if (*p1 != '(' && *p1 != ')') {
3496                         *p2 = *p1;
3497                         p2++;
3498                     }
3499                     p1++;
3500                 }
3501                 *p2 = (char)0;
3502             } else
3503                 key_n2 = key_n;
3504             SetDictInt(key_n2,key);
3505             if (key_n2 != key_n)
3506                 PyMem_Free(key_n2);
3507         }
3508         SetDictInt("KEY_MIN", KEY_MIN);
3509         SetDictInt("KEY_MAX", KEY_MAX);
3510     }
3511     return m;
3512 }
3513