blob: 7ca91f641617a327ce97c8a7ae3e6a5ce9c19509 [file] [log] [blame]
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +00001/*
2 * Interface to the ncurses panel library
3 *
4 * Original version by Thomas Gellekum
5 */
6
7/* Release Number */
8
Serhiy Storchaka2d06e842015-12-25 19:53:18 +02009static const char PyCursesVersion[] = "2.1";
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000010
11/* Includes */
12
13#include "Python.h"
14
15#include "py_curses.h"
16
17#include <panel.h>
18
Martin v. Löwisc838ec12012-06-14 16:00:24 +020019typedef struct {
20 PyObject *PyCursesError;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +020021 PyObject *PyCursesPanel_Type;
Martin v. Löwisc838ec12012-06-14 16:00:24 +020022} _curses_panelstate;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000023
Hai Shif707d942020-03-16 21:15:01 +080024static inline _curses_panelstate*
25get_curses_panelstate(PyObject *module)
26{
27 void *state = PyModule_GetState(module);
28 assert(state != NULL);
29 return (_curses_panelstate *)state;
30}
Martin v. Löwisc838ec12012-06-14 16:00:24 +020031
Martin v. Löwisc838ec12012-06-14 16:00:24 +020032static int
33_curses_panel_clear(PyObject *m)
34{
Hai Shif707d942020-03-16 21:15:01 +080035 Py_CLEAR(get_curses_panelstate(m)->PyCursesError);
Martin v. Löwisc838ec12012-06-14 16:00:24 +020036 return 0;
37}
38
39static int
40_curses_panel_traverse(PyObject *m, visitproc visit, void *arg)
41{
Hai Shif707d942020-03-16 21:15:01 +080042 Py_VISIT(get_curses_panelstate(m)->PyCursesError);
Martin v. Löwisc838ec12012-06-14 16:00:24 +020043 return 0;
44}
45
46static void
47_curses_panel_free(void *m)
48{
49 _curses_panel_clear((PyObject *) m);
50}
51
52static struct PyModuleDef _curses_panelmodule;
53
54#define _curses_panelstate_global \
55((_curses_panelstate *) PyModule_GetState(PyState_FindModule(&_curses_panelmodule)))
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000056
57/* Utility Functions */
58
59/*
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 * Check the return code from a curses function and return None
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000061 * or raise an exception as appropriate.
62 */
63
64static PyObject *
Serhiy Storchakaef1585e2015-12-25 20:01:53 +020065PyCursesCheckERR(int code, const char *fname)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000066{
67 if (code != ERR) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +020068 Py_RETURN_NONE;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000069 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 if (fname == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +020071 PyErr_SetString(_curses_panelstate_global->PyCursesError, catchall_ERR);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 } else {
Martin v. Löwisc838ec12012-06-14 16:00:24 +020073 PyErr_Format(_curses_panelstate_global->PyCursesError, "%s() returned ERR", fname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000074 }
75 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000076 }
77}
78
79/*****************************************************************************
80 The Panel Object
81******************************************************************************/
82
83/* Definition of the panel object and panel type */
84
85typedef struct {
86 PyObject_HEAD
87 PANEL *pan;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000088 PyCursesWindowObject *wo; /* for reference counts */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000089} PyCursesPanelObject;
90
Martin v. Löwisbc07cb82012-06-14 16:01:23 +020091#define PyCursesPanel_Check(v) \
Dong-hee Na1b55b652020-02-17 19:09:15 +090092 Py_IS_TYPE(v, _curses_panelstate_global->PyCursesPanel_Type)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000093
94/* Some helper functions. The problem is that there's always a window
95 associated with a panel. To ensure that Python's GC doesn't pull
96 this window from under our feet we need to keep track of references
97 to the corresponding window object within Python. We can't use
98 dupwin(oldwin) to keep a copy of the curses WINDOW because the
99 contents of oldwin is copied only once; code like
100
101 win = newwin(...)
102 pan = win.panel()
103 win.addstr(some_string)
104 pan.window().addstr(other_string)
105
106 will fail. */
107
108/* We keep a linked list of PyCursesPanelObjects, lop. A list should
109 suffice, I don't expect more than a handful or at most a few
110 dozens of panel objects within a typical program. */
111typedef struct _list_of_panels {
112 PyCursesPanelObject *po;
113 struct _list_of_panels *next;
114} list_of_panels;
115
116/* list anchor */
117static list_of_panels *lop;
118
119/* Insert a new panel object into lop */
120static int
121insert_lop(PyCursesPanelObject *po)
122{
123 list_of_panels *new;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000124
Victor Stinnerb6404912013-07-07 16:21:41 +0200125 if ((new = (list_of_panels *)PyMem_Malloc(sizeof(list_of_panels))) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000126 PyErr_NoMemory();
127 return -1;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000128 }
129 new->po = po;
130 new->next = lop;
131 lop = new;
132 return 0;
133}
134
135/* Remove the panel object from lop */
136static void
137remove_lop(PyCursesPanelObject *po)
138{
139 list_of_panels *temp, *n;
140
141 temp = lop;
142 if (temp->po == po) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 lop = temp->next;
Victor Stinnerb6404912013-07-07 16:21:41 +0200144 PyMem_Free(temp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 return;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000146 }
Thomas Wouters47f003d2006-03-07 13:38:14 +0000147 while (temp->next == NULL || temp->next->po != po) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000148 if (temp->next == NULL) {
149 PyErr_SetString(PyExc_RuntimeError,
150 "remove_lop: can't find Panel Object");
151 return;
152 }
153 temp = temp->next;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000154 }
155 n = temp->next->next;
Victor Stinnerb6404912013-07-07 16:21:41 +0200156 PyMem_Free(temp->next);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000157 temp->next = n;
158 return;
159}
160
161/* Return the panel object that corresponds to pan */
162static PyCursesPanelObject *
163find_po(PANEL *pan)
164{
165 list_of_panels *temp;
166 for (temp = lop; temp->po->pan != pan; temp = temp->next)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000167 if (temp->next == NULL) return NULL; /* not found!? */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000168 return temp->po;
169}
170
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300171/*[clinic input]
172module _curses_panel
173class _curses_panel.panel "PyCursesPanelObject *" "&PyCursesPanel_Type"
174[clinic start generated code]*/
175/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2f4ef263ca850a31]*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000176
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300177#include "clinic/_curses_panel.c.h"
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000178
179/* ------------- PANEL routines --------------- */
180
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300181/*[clinic input]
182_curses_panel.panel.bottom
183
184Push the panel to the bottom of the stack.
185[clinic start generated code]*/
186
187static PyObject *
188_curses_panel_panel_bottom_impl(PyCursesPanelObject *self)
189/*[clinic end generated code: output=7aa7d14d7e1d1ce6 input=b6c920c071b61e2e]*/
190{
191 return PyCursesCheckERR(bottom_panel(self->pan), "bottom");
192}
193
194/*[clinic input]
195_curses_panel.panel.hide
196
197Hide the panel.
198
199This does not delete the object, it just makes the window on screen invisible.
200[clinic start generated code]*/
201
202static PyObject *
203_curses_panel_panel_hide_impl(PyCursesPanelObject *self)
204/*[clinic end generated code: output=a7bbbd523e1eab49 input=f6ab884e99386118]*/
205{
206 return PyCursesCheckERR(hide_panel(self->pan), "hide");
207}
208
209/*[clinic input]
210_curses_panel.panel.show
211
212Display the panel (which might have been hidden).
213[clinic start generated code]*/
214
215static PyObject *
216_curses_panel_panel_show_impl(PyCursesPanelObject *self)
217/*[clinic end generated code: output=6b4553ab45c97769 input=57b167bbefaa3755]*/
218{
219 return PyCursesCheckERR(show_panel(self->pan), "show");
220}
221
222/*[clinic input]
223_curses_panel.panel.top
224
225Push panel to the top of the stack.
226[clinic start generated code]*/
227
228static PyObject *
229_curses_panel_panel_top_impl(PyCursesPanelObject *self)
230/*[clinic end generated code: output=0f5f2f8cdd2d1777 input=be33975ec3ca0e9a]*/
231{
232 return PyCursesCheckERR(top_panel(self->pan), "top");
233}
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000234
235/* Allocation and deallocation of Panel Objects */
236
237static PyObject *
238PyCursesPanel_New(PANEL *pan, PyCursesWindowObject *wo)
239{
240 PyCursesPanelObject *po;
241
Victor Stinner92055202020-04-08 00:38:15 +0200242 po = PyObject_New(PyCursesPanelObject,
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200243 (PyTypeObject *)(_curses_panelstate_global)->PyCursesPanel_Type);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000244 if (po == NULL) return NULL;
245 po->pan = pan;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000246 if (insert_lop(po) < 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000247 po->wo = NULL;
248 Py_DECREF(po);
249 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000250 }
Victor Stinnera7612272010-03-03 21:56:53 +0000251 po->wo = wo;
252 Py_INCREF(wo);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000253 return (PyObject *)po;
254}
255
256static void
257PyCursesPanel_Dealloc(PyCursesPanelObject *po)
258{
Eddie Elizondo364f0b02019-03-27 07:52:18 -0400259 PyObject *tp, *obj;
260
261 tp = (PyObject *) Py_TYPE(po);
262 obj = (PyObject *) panel_userptr(po->pan);
Serhiy Storchakadf40b622016-05-09 00:11:59 +0300263 if (obj) {
264 (void)set_panel_userptr(po->pan, NULL);
265 Py_DECREF(obj);
266 }
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000267 (void)del_panel(po->pan);
Victor Stinnera7612272010-03-03 21:56:53 +0000268 if (po->wo != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000269 Py_DECREF(po->wo);
270 remove_lop(po);
Victor Stinnera7612272010-03-03 21:56:53 +0000271 }
Michael W. Hudsoncf6bfe42002-01-30 15:47:34 +0000272 PyObject_DEL(po);
Eddie Elizondo364f0b02019-03-27 07:52:18 -0400273 Py_DECREF(tp);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000274}
275
276/* panel_above(NULL) returns the bottom panel in the stack. To get
277 this behaviour we use curses.panel.bottom_panel(). */
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300278/*[clinic input]
279_curses_panel.panel.above
280
281Return the panel above the current panel.
282[clinic start generated code]*/
283
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000284static PyObject *
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300285_curses_panel_panel_above_impl(PyCursesPanelObject *self)
286/*[clinic end generated code: output=70ac06d25fd3b4da input=c059994022976788]*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000287{
288 PANEL *pan;
289 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000290
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000291 pan = panel_above(self->pan);
292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000293 if (pan == NULL) { /* valid output, it means the calling panel
294 is on top of the stack */
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200295 Py_RETURN_NONE;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000296 }
297 po = find_po(pan);
298 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299 PyErr_SetString(PyExc_RuntimeError,
300 "panel_above: can't find Panel Object");
301 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000302 }
303 Py_INCREF(po);
304 return (PyObject *)po;
305}
306
307/* panel_below(NULL) returns the top panel in the stack. To get
Andrew M. Kuchlingae89af92001-01-19 15:35:26 +0000308 this behaviour we use curses.panel.top_panel(). */
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300309/*[clinic input]
310_curses_panel.panel.below
311
312Return the panel below the current panel.
313[clinic start generated code]*/
314
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000315static PyObject *
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300316_curses_panel_panel_below_impl(PyCursesPanelObject *self)
317/*[clinic end generated code: output=282861122e06e3de input=cc08f61936d297c6]*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000318{
319 PANEL *pan;
320 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000321
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000322 pan = panel_below(self->pan);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000323
324 if (pan == NULL) { /* valid output, it means the calling panel
325 is on the bottom of the stack */
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200326 Py_RETURN_NONE;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000327 }
328 po = find_po(pan);
329 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000330 PyErr_SetString(PyExc_RuntimeError,
331 "panel_below: can't find Panel Object");
332 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000333 }
334 Py_INCREF(po);
335 return (PyObject *)po;
336}
337
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300338/*[clinic input]
339_curses_panel.panel.hidden
340
341Return True if the panel is hidden (not visible), False otherwise.
342[clinic start generated code]*/
343
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000344static PyObject *
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300345_curses_panel_panel_hidden_impl(PyCursesPanelObject *self)
346/*[clinic end generated code: output=66eebd1ab4501a71 input=453d4b4fce25e21a]*/
347{
348 if (panel_hidden(self->pan))
349 Py_RETURN_TRUE;
350 else
351 Py_RETURN_FALSE;
352}
353
354/*[clinic input]
355_curses_panel.panel.move
356
357 y: int
358 x: int
359 /
360
361Move the panel to the screen coordinates (y, x).
362[clinic start generated code]*/
363
364static PyObject *
365_curses_panel_panel_move_impl(PyCursesPanelObject *self, int y, int x)
366/*[clinic end generated code: output=d867535a89777415 input=e0b36b78acc03fba]*/
367{
368 return PyCursesCheckERR(move_panel(self->pan, y, x), "move_panel");
369}
370
371/*[clinic input]
372_curses_panel.panel.window
373
374Return the window object associated with the panel.
375[clinic start generated code]*/
376
377static PyObject *
378_curses_panel_panel_window_impl(PyCursesPanelObject *self)
379/*[clinic end generated code: output=5f05940d4106b4cb input=6067353d2c307901]*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000380{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000381 Py_INCREF(self->wo);
382 return (PyObject *)self->wo;
383}
384
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300385/*[clinic input]
386_curses_panel.panel.replace
387
388 win: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type")
389 /
390
391Change the window associated with the panel to the window win.
392[clinic start generated code]*/
393
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000394static PyObject *
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300395_curses_panel_panel_replace_impl(PyCursesPanelObject *self,
396 PyCursesWindowObject *win)
397/*[clinic end generated code: output=2253a95f7b287255 input=4b1c4283987d9dfa]*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000398{
399 PyCursesPanelObject *po;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000400 int rtn;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000401
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000402 po = find_po(self->pan);
403 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000404 PyErr_SetString(PyExc_RuntimeError,
405 "replace_panel: can't find Panel Object");
406 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000407 }
408
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300409 rtn = replace_panel(self->pan, win->win);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000410 if (rtn == ERR) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200411 PyErr_SetString(_curses_panelstate_global->PyCursesError, "replace_panel() returned ERR");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000412 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000413 }
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300414 Py_INCREF(win);
415 Py_SETREF(po->wo, win);
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200416 Py_RETURN_NONE;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000417}
418
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300419/*[clinic input]
420_curses_panel.panel.set_userptr
421
422 obj: object
423 /
424
animalize463572c2019-02-25 07:18:48 +0800425Set the panel's user pointer to obj.
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300426[clinic start generated code]*/
427
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000428static PyObject *
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300429_curses_panel_panel_set_userptr(PyCursesPanelObject *self, PyObject *obj)
animalize463572c2019-02-25 07:18:48 +0800430/*[clinic end generated code: output=6fb145b3af88cf4a input=d2c6a9dbefabbf39]*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000431{
Andrew Kuchling53e5ea72013-06-15 14:04:04 -0400432 PyObject *oldobj;
Andrew Kuchling9290dd12013-06-22 14:50:56 -0400433 int rc;
Andrew Kuchling53e5ea72013-06-15 14:04:04 -0400434 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000435 Py_INCREF(obj);
Andrew Kuchling9290dd12013-06-22 14:50:56 -0400436 oldobj = (PyObject *) panel_userptr(self->pan);
437 rc = set_panel_userptr(self->pan, (void*)obj);
438 if (rc == ERR) {
439 /* In case of an ncurses error, decref the new object again */
440 Py_DECREF(obj);
441 }
442 Py_XDECREF(oldobj);
443 return PyCursesCheckERR(rc, "set_panel_userptr");
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000444}
445
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300446/*[clinic input]
447_curses_panel.panel.userptr
448
449Return the user pointer for the panel.
450[clinic start generated code]*/
451
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000452static PyObject *
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300453_curses_panel_panel_userptr_impl(PyCursesPanelObject *self)
454/*[clinic end generated code: output=e849c307b5dc9237 input=f78b7a47aef0fd50]*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000455{
456 PyObject *obj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 PyCursesInitialised;
Fred Drake4e36d582000-12-23 05:46:23 +0000458 obj = (PyObject *) panel_userptr(self->pan);
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000459 if (obj == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200460 PyErr_SetString(_curses_panelstate_global->PyCursesError, "no userptr set");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 return NULL;
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000462 }
463
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000464 Py_INCREF(obj);
465 return obj;
466}
467
468
469/* Module interface */
470
471static PyMethodDef PyCursesPanel_Methods[] = {
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300472 _CURSES_PANEL_PANEL_ABOVE_METHODDEF
473 _CURSES_PANEL_PANEL_BELOW_METHODDEF
474 _CURSES_PANEL_PANEL_BOTTOM_METHODDEF
475 _CURSES_PANEL_PANEL_HIDDEN_METHODDEF
476 _CURSES_PANEL_PANEL_HIDE_METHODDEF
477 _CURSES_PANEL_PANEL_MOVE_METHODDEF
478 _CURSES_PANEL_PANEL_REPLACE_METHODDEF
479 _CURSES_PANEL_PANEL_SET_USERPTR_METHODDEF
480 _CURSES_PANEL_PANEL_SHOW_METHODDEF
481 _CURSES_PANEL_PANEL_TOP_METHODDEF
482 _CURSES_PANEL_PANEL_USERPTR_METHODDEF
483 _CURSES_PANEL_PANEL_WINDOW_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000485};
486
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000487/* -------------------------------------------------------*/
488
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200489static PyType_Slot PyCursesPanel_Type_slots[] = {
490 {Py_tp_dealloc, PyCursesPanel_Dealloc},
491 {Py_tp_methods, PyCursesPanel_Methods},
492 {0, 0},
493};
494
495static PyType_Spec PyCursesPanel_Type_spec = {
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300496 "_curses_panel.panel",
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200497 sizeof(PyCursesPanelObject),
498 0,
499 Py_TPFLAGS_DEFAULT,
500 PyCursesPanel_Type_slots
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000501};
502
503/* Wrapper for panel_above(NULL). This function returns the bottom
504 panel of the stack, so it's renamed to bottom_panel().
505 panel.above() *requires* a panel object in the first place which
506 may be undesirable. */
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300507/*[clinic input]
508_curses_panel.bottom_panel
509
510Return the bottom panel in the panel stack.
511[clinic start generated code]*/
512
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000513static PyObject *
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300514_curses_panel_bottom_panel_impl(PyObject *module)
515/*[clinic end generated code: output=3aba9f985f4c2bd0 input=634c2a8078b3d7e4]*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000516{
517 PANEL *pan;
518 PyCursesPanelObject *po;
519
520 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000521
522 pan = panel_above(NULL);
523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 if (pan == NULL) { /* valid output, it means
525 there's no panel at all */
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200526 Py_RETURN_NONE;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000527 }
528 po = find_po(pan);
529 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000530 PyErr_SetString(PyExc_RuntimeError,
531 "panel_above: can't find Panel Object");
532 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000533 }
534 Py_INCREF(po);
535 return (PyObject *)po;
536}
537
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300538/*[clinic input]
539_curses_panel.new_panel
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000540
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300541 win: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type")
542 /
543
544Return a panel object, associating it with the given window win.
545[clinic start generated code]*/
546
547static PyObject *
548_curses_panel_new_panel_impl(PyObject *module, PyCursesWindowObject *win)
549/*[clinic end generated code: output=45e948e0176a9bd2 input=74d4754e0ebe4800]*/
550{
551 PANEL *pan = new_panel(win->win);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000552 if (pan == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200553 PyErr_SetString(_curses_panelstate_global->PyCursesError, catchall_NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000555 }
556 return (PyObject *)PyCursesPanel_New(pan, win);
557}
558
559
560/* Wrapper for panel_below(NULL). This function returns the top panel
561 of the stack, so it's renamed to top_panel(). panel.below()
562 *requires* a panel object in the first place which may be
563 undesirable. */
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300564/*[clinic input]
565_curses_panel.top_panel
566
567Return the top panel in the panel stack.
568[clinic start generated code]*/
569
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000570static PyObject *
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300571_curses_panel_top_panel_impl(PyObject *module)
572/*[clinic end generated code: output=86704988bea8508e input=e62d6278dba39e79]*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000573{
574 PANEL *pan;
575 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000576
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000577 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000578
579 pan = panel_below(NULL);
580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 if (pan == NULL) { /* valid output, it means
582 there's no panel at all */
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200583 Py_RETURN_NONE;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000584 }
585 po = find_po(pan);
586 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000587 PyErr_SetString(PyExc_RuntimeError,
588 "panel_below: can't find Panel Object");
589 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000590 }
591 Py_INCREF(po);
592 return (PyObject *)po;
593}
594
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300595/*[clinic input]
596_curses_panel.update_panels
597
598Updates the virtual screen after changes in the panel stack.
599
animalize463572c2019-02-25 07:18:48 +0800600This does not call curses.doupdate(), so you'll have to do this yourself.
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300601[clinic start generated code]*/
602
603static PyObject *
604_curses_panel_update_panels_impl(PyObject *module)
animalize463572c2019-02-25 07:18:48 +0800605/*[clinic end generated code: output=2f3b4c2e03d90ded input=5299624c9a708621]*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000607 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000608 update_panels();
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200609 Py_RETURN_NONE;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000610}
611
612
613/* List of functions defined in the module */
614
615static PyMethodDef PyCurses_methods[] = {
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300616 _CURSES_PANEL_BOTTOM_PANEL_METHODDEF
617 _CURSES_PANEL_NEW_PANEL_METHODDEF
618 _CURSES_PANEL_TOP_PANEL_METHODDEF
619 _CURSES_PANEL_UPDATE_PANELS_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000621};
622
623/* Initialization function for the module */
624
Martin v. Löwis1a214512008-06-11 05:26:20 +0000625
626static struct PyModuleDef _curses_panelmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000627 PyModuleDef_HEAD_INIT,
628 "_curses_panel",
629 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200630 sizeof(_curses_panelstate),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 PyCurses_methods,
632 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200633 _curses_panel_traverse,
634 _curses_panel_clear,
635 _curses_panel_free
Martin v. Löwis1a214512008-06-11 05:26:20 +0000636};
637
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000638PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000639PyInit__curses_panel(void)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000640{
641 PyObject *m, *d, *v;
642
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000643 /* Create the module and add the functions */
Martin v. Löwis1a214512008-06-11 05:26:20 +0000644 m = PyModule_Create(&_curses_panelmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000645 if (m == NULL)
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200646 goto fail;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000647 d = PyModule_GetDict(m);
648
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200649 /* Initialize object type */
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300650 v = PyType_FromSpec(&PyCursesPanel_Type_spec);
651 if (v == NULL)
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200652 goto fail;
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300653 ((PyTypeObject *)v)->tp_new = NULL;
Hai Shif707d942020-03-16 21:15:01 +0800654 get_curses_panelstate(m)->PyCursesPanel_Type = v;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200655
656 import_curses();
Victor Stinner569f3642013-07-18 02:31:21 +0200657 if (PyErr_Occurred())
658 goto fail;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200659
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000660 /* For exception _curses_panel.error */
Hai Shif707d942020-03-16 21:15:01 +0800661 get_curses_panelstate(m)->PyCursesError = PyErr_NewException("_curses_panel.error", NULL, NULL);
662 PyDict_SetItemString(d, "error", get_curses_panelstate(m)->PyCursesError);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000663
664 /* Make the version available */
Neal Norwitz53cbdaa2007-08-23 21:42:55 +0000665 v = PyUnicode_FromString(PyCursesVersion);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000666 PyDict_SetItemString(d, "version", v);
667 PyDict_SetItemString(d, "__version__", v);
668 Py_DECREF(v);
Serhiy Storchakab00854c2018-05-10 11:27:23 +0300669
Hai Shif707d942020-03-16 21:15:01 +0800670 Py_INCREF(get_curses_panelstate(m)->PyCursesPanel_Type);
671 PyModule_AddObject(m, "panel",
672 (PyObject *)get_curses_panelstate(m)->PyCursesPanel_Type);
Martin v. Löwis1a214512008-06-11 05:26:20 +0000673 return m;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200674 fail:
675 Py_XDECREF(m);
676 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000677}