blob: 228f4971ac372d445c40ea2e39e3bee6684f1906 [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
9static char *PyCursesVersion = "2.1";
10
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
Martin v. Löwisc838ec12012-06-14 16:00:24 +020024#define _curses_panelstate(o) ((_curses_panelstate *)PyModule_GetState(o))
25
Martin v. Löwisc838ec12012-06-14 16:00:24 +020026static int
27_curses_panel_clear(PyObject *m)
28{
29 Py_CLEAR(_curses_panelstate(m)->PyCursesError);
30 return 0;
31}
32
33static int
34_curses_panel_traverse(PyObject *m, visitproc visit, void *arg)
35{
36 Py_VISIT(_curses_panelstate(m)->PyCursesError);
37 return 0;
38}
39
40static void
41_curses_panel_free(void *m)
42{
43 _curses_panel_clear((PyObject *) m);
44}
45
46static struct PyModuleDef _curses_panelmodule;
47
48#define _curses_panelstate_global \
49((_curses_panelstate *) PyModule_GetState(PyState_FindModule(&_curses_panelmodule)))
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000050
51/* Utility Functions */
52
53/*
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000054 * Check the return code from a curses function and return None
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000055 * or raise an exception as appropriate.
56 */
57
58static PyObject *
59PyCursesCheckERR(int code, char *fname)
60{
61 if (code != ERR) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000062 Py_INCREF(Py_None);
63 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000064 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 if (fname == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +020066 PyErr_SetString(_curses_panelstate_global->PyCursesError, catchall_ERR);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 } else {
Martin v. Löwisc838ec12012-06-14 16:00:24 +020068 PyErr_Format(_curses_panelstate_global->PyCursesError, "%s() returned ERR", fname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000069 }
70 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000071 }
72}
73
74/*****************************************************************************
75 The Panel Object
76******************************************************************************/
77
78/* Definition of the panel object and panel type */
79
80typedef struct {
81 PyObject_HEAD
82 PANEL *pan;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000083 PyCursesWindowObject *wo; /* for reference counts */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000084} PyCursesPanelObject;
85
Martin v. Löwisbc07cb82012-06-14 16:01:23 +020086#define PyCursesPanel_Check(v) \
87 (Py_TYPE(v) == _curses_panelstate_global->PyCursesPanel_Type)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000088
89/* Some helper functions. The problem is that there's always a window
90 associated with a panel. To ensure that Python's GC doesn't pull
91 this window from under our feet we need to keep track of references
92 to the corresponding window object within Python. We can't use
93 dupwin(oldwin) to keep a copy of the curses WINDOW because the
94 contents of oldwin is copied only once; code like
95
96 win = newwin(...)
97 pan = win.panel()
98 win.addstr(some_string)
99 pan.window().addstr(other_string)
100
101 will fail. */
102
103/* We keep a linked list of PyCursesPanelObjects, lop. A list should
104 suffice, I don't expect more than a handful or at most a few
105 dozens of panel objects within a typical program. */
106typedef struct _list_of_panels {
107 PyCursesPanelObject *po;
108 struct _list_of_panels *next;
109} list_of_panels;
110
111/* list anchor */
112static list_of_panels *lop;
113
114/* Insert a new panel object into lop */
115static int
116insert_lop(PyCursesPanelObject *po)
117{
118 list_of_panels *new;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000119
Victor Stinnerb6404912013-07-07 16:21:41 +0200120 if ((new = (list_of_panels *)PyMem_Malloc(sizeof(list_of_panels))) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000121 PyErr_NoMemory();
122 return -1;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000123 }
124 new->po = po;
125 new->next = lop;
126 lop = new;
127 return 0;
128}
129
130/* Remove the panel object from lop */
131static void
132remove_lop(PyCursesPanelObject *po)
133{
134 list_of_panels *temp, *n;
135
136 temp = lop;
137 if (temp->po == po) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000138 lop = temp->next;
Victor Stinnerb6404912013-07-07 16:21:41 +0200139 PyMem_Free(temp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000140 return;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000141 }
Thomas Wouters47f003d2006-03-07 13:38:14 +0000142 while (temp->next == NULL || temp->next->po != po) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 if (temp->next == NULL) {
144 PyErr_SetString(PyExc_RuntimeError,
145 "remove_lop: can't find Panel Object");
146 return;
147 }
148 temp = temp->next;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000149 }
150 n = temp->next->next;
Victor Stinnerb6404912013-07-07 16:21:41 +0200151 PyMem_Free(temp->next);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000152 temp->next = n;
153 return;
154}
155
156/* Return the panel object that corresponds to pan */
157static PyCursesPanelObject *
158find_po(PANEL *pan)
159{
160 list_of_panels *temp;
161 for (temp = lop; temp->po->pan != pan; temp = temp->next)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 if (temp->next == NULL) return NULL; /* not found!? */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000163 return temp->po;
164}
165
166/* Function Prototype Macros - They are ugly but very, very useful. ;-)
167
168 X - function name
169 TYPE - parameter Type
170 ERGSTR - format string for construction of the return value
171 PARSESTR - format string for argument parsing */
172
173#define Panel_NoArgNoReturnFunction(X) \
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000174static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self) \
175{ return PyCursesCheckERR(X(self->pan), # X); }
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000176
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000177#define Panel_NoArgTrueFalseFunction(X) \
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000178static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self) \
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000179{ \
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000180 if (X (self->pan) == FALSE) { Py_INCREF(Py_False); return Py_False; } \
181 else { Py_INCREF(Py_True); return Py_True; } }
182
183#define Panel_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \
Fred Drake4e36d582000-12-23 05:46:23 +0000184static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self, PyObject *args) \
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000185{ \
186 TYPE arg1, arg2; \
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000187 if (!PyArg_ParseTuple(args, PARSESTR, &arg1, &arg2)) return NULL; \
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000188 return PyCursesCheckERR(X(self->pan, arg1, arg2), # X); }
189
190/* ------------- PANEL routines --------------- */
191
192Panel_NoArgNoReturnFunction(bottom_panel)
193Panel_NoArgNoReturnFunction(hide_panel)
194Panel_NoArgNoReturnFunction(show_panel)
195Panel_NoArgNoReturnFunction(top_panel)
196Panel_NoArgTrueFalseFunction(panel_hidden)
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000197Panel_TwoArgNoReturnFunction(move_panel, int, "ii;y,x")
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000198
199/* Allocation and deallocation of Panel Objects */
200
201static PyObject *
202PyCursesPanel_New(PANEL *pan, PyCursesWindowObject *wo)
203{
204 PyCursesPanelObject *po;
205
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200206 po = PyObject_NEW(PyCursesPanelObject,
207 (PyTypeObject *)(_curses_panelstate_global)->PyCursesPanel_Type);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000208 if (po == NULL) return NULL;
209 po->pan = pan;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000210 if (insert_lop(po) < 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000211 po->wo = NULL;
212 Py_DECREF(po);
213 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000214 }
Victor Stinnera7612272010-03-03 21:56:53 +0000215 po->wo = wo;
216 Py_INCREF(wo);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000217 return (PyObject *)po;
218}
219
220static void
221PyCursesPanel_Dealloc(PyCursesPanelObject *po)
222{
Serhiy Storchakadf40b622016-05-09 00:11:59 +0300223 PyObject *obj = (PyObject *) panel_userptr(po->pan);
224 if (obj) {
225 (void)set_panel_userptr(po->pan, NULL);
226 Py_DECREF(obj);
227 }
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000228 (void)del_panel(po->pan);
Victor Stinnera7612272010-03-03 21:56:53 +0000229 if (po->wo != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000230 Py_DECREF(po->wo);
231 remove_lop(po);
Victor Stinnera7612272010-03-03 21:56:53 +0000232 }
Michael W. Hudsoncf6bfe42002-01-30 15:47:34 +0000233 PyObject_DEL(po);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000234}
235
236/* panel_above(NULL) returns the bottom panel in the stack. To get
237 this behaviour we use curses.panel.bottom_panel(). */
238static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000239PyCursesPanel_above(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000240{
241 PANEL *pan;
242 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000243
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000244 pan = panel_above(self->pan);
245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000246 if (pan == NULL) { /* valid output, it means the calling panel
247 is on top of the stack */
248 Py_INCREF(Py_None);
249 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000250 }
251 po = find_po(pan);
252 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000253 PyErr_SetString(PyExc_RuntimeError,
254 "panel_above: can't find Panel Object");
255 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000256 }
257 Py_INCREF(po);
258 return (PyObject *)po;
259}
260
261/* panel_below(NULL) returns the top panel in the stack. To get
Andrew M. Kuchlingae89af92001-01-19 15:35:26 +0000262 this behaviour we use curses.panel.top_panel(). */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000263static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000264PyCursesPanel_below(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000265{
266 PANEL *pan;
267 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000268
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000269 pan = panel_below(self->pan);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270
271 if (pan == NULL) { /* valid output, it means the calling panel
272 is on the bottom of the stack */
273 Py_INCREF(Py_None);
274 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000275 }
276 po = find_po(pan);
277 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000278 PyErr_SetString(PyExc_RuntimeError,
279 "panel_below: can't find Panel Object");
280 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000281 }
282 Py_INCREF(po);
283 return (PyObject *)po;
284}
285
286static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000287PyCursesPanel_window(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000288{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000289 Py_INCREF(self->wo);
290 return (PyObject *)self->wo;
291}
292
293static PyObject *
294PyCursesPanel_replace_panel(PyCursesPanelObject *self, PyObject *args)
295{
296 PyCursesPanelObject *po;
297 PyCursesWindowObject *temp;
298 int rtn;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000300 if (PyTuple_Size(args) != 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000301 PyErr_SetString(PyExc_TypeError, "replace requires one argument");
302 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000303 }
304 if (!PyArg_ParseTuple(args, "O!;window object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000305 &PyCursesWindow_Type, &temp))
306 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000307
308 po = find_po(self->pan);
309 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 PyErr_SetString(PyExc_RuntimeError,
311 "replace_panel: can't find Panel Object");
312 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000313 }
314
315 rtn = replace_panel(self->pan, temp->win);
316 if (rtn == ERR) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200317 PyErr_SetString(_curses_panelstate_global->PyCursesError, "replace_panel() returned ERR");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000318 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000319 }
Serhiy Storchaka5a57ade2015-12-24 10:35:59 +0200320 Py_INCREF(temp);
Serhiy Storchaka57a01d32016-04-10 18:05:40 +0300321 Py_SETREF(po->wo, temp);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000322 Py_INCREF(Py_None);
323 return Py_None;
324}
325
326static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000327PyCursesPanel_set_panel_userptr(PyCursesPanelObject *self, PyObject *obj)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000328{
Andrew Kuchling53e5ea72013-06-15 14:04:04 -0400329 PyObject *oldobj;
Andrew Kuchling9290dd12013-06-22 14:50:56 -0400330 int rc;
Andrew Kuchling53e5ea72013-06-15 14:04:04 -0400331 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000332 Py_INCREF(obj);
Andrew Kuchling9290dd12013-06-22 14:50:56 -0400333 oldobj = (PyObject *) panel_userptr(self->pan);
334 rc = set_panel_userptr(self->pan, (void*)obj);
335 if (rc == ERR) {
336 /* In case of an ncurses error, decref the new object again */
337 Py_DECREF(obj);
338 }
339 Py_XDECREF(oldobj);
340 return PyCursesCheckERR(rc, "set_panel_userptr");
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000341}
342
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000343static PyObject *
344PyCursesPanel_userptr(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000345{
346 PyObject *obj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000347 PyCursesInitialised;
Fred Drake4e36d582000-12-23 05:46:23 +0000348 obj = (PyObject *) panel_userptr(self->pan);
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000349 if (obj == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200350 PyErr_SetString(_curses_panelstate_global->PyCursesError, "no userptr set");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000351 return NULL;
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000352 }
353
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000354 Py_INCREF(obj);
355 return obj;
356}
357
358
359/* Module interface */
360
361static PyMethodDef PyCursesPanel_Methods[] = {
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000362 {"above", (PyCFunction)PyCursesPanel_above, METH_NOARGS},
363 {"below", (PyCFunction)PyCursesPanel_below, METH_NOARGS},
364 {"bottom", (PyCFunction)PyCursesPanel_bottom_panel, METH_NOARGS},
365 {"hidden", (PyCFunction)PyCursesPanel_panel_hidden, METH_NOARGS},
366 {"hide", (PyCFunction)PyCursesPanel_hide_panel, METH_NOARGS},
367 {"move", (PyCFunction)PyCursesPanel_move_panel, METH_VARARGS},
Neal Norwitz01b26942002-03-31 14:55:17 +0000368 {"replace", (PyCFunction)PyCursesPanel_replace_panel, METH_VARARGS},
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000369 {"set_userptr", (PyCFunction)PyCursesPanel_set_panel_userptr, METH_O},
370 {"show", (PyCFunction)PyCursesPanel_show_panel, METH_NOARGS},
371 {"top", (PyCFunction)PyCursesPanel_top_panel, METH_NOARGS},
372 {"userptr", (PyCFunction)PyCursesPanel_userptr, METH_NOARGS},
373 {"window", (PyCFunction)PyCursesPanel_window, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000374 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000375};
376
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000377/* -------------------------------------------------------*/
378
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200379static PyType_Slot PyCursesPanel_Type_slots[] = {
380 {Py_tp_dealloc, PyCursesPanel_Dealloc},
381 {Py_tp_methods, PyCursesPanel_Methods},
382 {0, 0},
383};
384
385static PyType_Spec PyCursesPanel_Type_spec = {
386 "_curses_panel.curses panel",
387 sizeof(PyCursesPanelObject),
388 0,
389 Py_TPFLAGS_DEFAULT,
390 PyCursesPanel_Type_slots
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000391};
392
393/* Wrapper for panel_above(NULL). This function returns the bottom
394 panel of the stack, so it's renamed to bottom_panel().
395 panel.above() *requires* a panel object in the first place which
396 may be undesirable. */
397static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000398PyCurses_bottom_panel(PyObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000399{
400 PANEL *pan;
401 PyCursesPanelObject *po;
402
403 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000404
405 pan = panel_above(NULL);
406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000407 if (pan == NULL) { /* valid output, it means
408 there's no panel at all */
409 Py_INCREF(Py_None);
410 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000411 }
412 po = find_po(pan);
413 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000414 PyErr_SetString(PyExc_RuntimeError,
415 "panel_above: can't find Panel Object");
416 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000417 }
418 Py_INCREF(po);
419 return (PyObject *)po;
420}
421
422static PyObject *
423PyCurses_new_panel(PyObject *self, PyObject *args)
424{
425 PyCursesWindowObject *win;
426 PANEL *pan;
427
Fred Drake4e36d582000-12-23 05:46:23 +0000428 if (!PyArg_ParseTuple(args, "O!", &PyCursesWindow_Type, &win))
429 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000430 pan = new_panel(win->win);
431 if (pan == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200432 PyErr_SetString(_curses_panelstate_global->PyCursesError, catchall_NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000434 }
435 return (PyObject *)PyCursesPanel_New(pan, win);
436}
437
438
439/* Wrapper for panel_below(NULL). This function returns the top panel
440 of the stack, so it's renamed to top_panel(). panel.below()
441 *requires* a panel object in the first place which may be
442 undesirable. */
443static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000444PyCurses_top_panel(PyObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000445{
446 PANEL *pan;
447 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000449 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000450
451 pan = panel_below(NULL);
452
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000453 if (pan == NULL) { /* valid output, it means
454 there's no panel at all */
455 Py_INCREF(Py_None);
456 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000457 }
458 po = find_po(pan);
459 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 PyErr_SetString(PyExc_RuntimeError,
461 "panel_below: can't find Panel Object");
462 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000463 }
464 Py_INCREF(po);
465 return (PyObject *)po;
466}
467
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000468static PyObject *PyCurses_update_panels(PyObject *self)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000469{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000470 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000471 update_panels();
472 Py_INCREF(Py_None);
473 return Py_None;
474}
475
476
477/* List of functions defined in the module */
478
479static PyMethodDef PyCurses_methods[] = {
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000480 {"bottom_panel", (PyCFunction)PyCurses_bottom_panel, METH_NOARGS},
481 {"new_panel", (PyCFunction)PyCurses_new_panel, METH_VARARGS},
482 {"top_panel", (PyCFunction)PyCurses_top_panel, METH_NOARGS},
483 {"update_panels", (PyCFunction)PyCurses_update_panels, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000485};
486
487/* Initialization function for the module */
488
Martin v. Löwis1a214512008-06-11 05:26:20 +0000489
490static struct PyModuleDef _curses_panelmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000491 PyModuleDef_HEAD_INIT,
492 "_curses_panel",
493 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200494 sizeof(_curses_panelstate),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000495 PyCurses_methods,
496 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200497 _curses_panel_traverse,
498 _curses_panel_clear,
499 _curses_panel_free
Martin v. Löwis1a214512008-06-11 05:26:20 +0000500};
501
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000502PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000503PyInit__curses_panel(void)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000504{
505 PyObject *m, *d, *v;
506
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000507 /* Create the module and add the functions */
Martin v. Löwis1a214512008-06-11 05:26:20 +0000508 m = PyModule_Create(&_curses_panelmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000509 if (m == NULL)
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200510 goto fail;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000511 d = PyModule_GetDict(m);
512
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200513 /* Initialize object type */
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300514 v = PyType_FromSpec(&PyCursesPanel_Type_spec);
515 if (v == NULL)
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200516 goto fail;
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300517 ((PyTypeObject *)v)->tp_new = NULL;
518 _curses_panelstate(m)->PyCursesPanel_Type = v;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200519
520 import_curses();
Victor Stinner569f3642013-07-18 02:31:21 +0200521 if (PyErr_Occurred())
522 goto fail;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200523
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000524 /* For exception _curses_panel.error */
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200525 _curses_panelstate(m)->PyCursesError = PyErr_NewException("_curses_panel.error", NULL, NULL);
526 PyDict_SetItemString(d, "error", _curses_panelstate(m)->PyCursesError);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000527
528 /* Make the version available */
Neal Norwitz53cbdaa2007-08-23 21:42:55 +0000529 v = PyUnicode_FromString(PyCursesVersion);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000530 PyDict_SetItemString(d, "version", v);
531 PyDict_SetItemString(d, "__version__", v);
532 Py_DECREF(v);
Martin v. Löwis1a214512008-06-11 05:26:20 +0000533 return m;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200534 fail:
535 Py_XDECREF(m);
536 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000537}