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