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