blob: 3e9fffd9587e6592226a68d9fabb886bcf813d5d [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{
223 (void)del_panel(po->pan);
Victor Stinnera7612272010-03-03 21:56:53 +0000224 if (po->wo != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 Py_DECREF(po->wo);
226 remove_lop(po);
Victor Stinnera7612272010-03-03 21:56:53 +0000227 }
Michael W. Hudsoncf6bfe42002-01-30 15:47:34 +0000228 PyObject_DEL(po);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000229}
230
231/* panel_above(NULL) returns the bottom panel in the stack. To get
232 this behaviour we use curses.panel.bottom_panel(). */
233static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000234PyCursesPanel_above(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000235{
236 PANEL *pan;
237 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000238
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000239 pan = panel_above(self->pan);
240
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000241 if (pan == NULL) { /* valid output, it means the calling panel
242 is on top of the stack */
243 Py_INCREF(Py_None);
244 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000245 }
246 po = find_po(pan);
247 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000248 PyErr_SetString(PyExc_RuntimeError,
249 "panel_above: can't find Panel Object");
250 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000251 }
252 Py_INCREF(po);
253 return (PyObject *)po;
254}
255
256/* panel_below(NULL) returns the top panel in the stack. To get
Andrew M. Kuchlingae89af92001-01-19 15:35:26 +0000257 this behaviour we use curses.panel.top_panel(). */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000258static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000259PyCursesPanel_below(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000260{
261 PANEL *pan;
262 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000264 pan = panel_below(self->pan);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000265
266 if (pan == NULL) { /* valid output, it means the calling panel
267 is on the bottom of the stack */
268 Py_INCREF(Py_None);
269 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000270 }
271 po = find_po(pan);
272 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000273 PyErr_SetString(PyExc_RuntimeError,
274 "panel_below: can't find Panel Object");
275 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000276 }
277 Py_INCREF(po);
278 return (PyObject *)po;
279}
280
281static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000282PyCursesPanel_window(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000283{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000284 Py_INCREF(self->wo);
285 return (PyObject *)self->wo;
286}
287
288static PyObject *
289PyCursesPanel_replace_panel(PyCursesPanelObject *self, PyObject *args)
290{
291 PyCursesPanelObject *po;
292 PyCursesWindowObject *temp;
293 int rtn;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000294
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000295 if (PyTuple_Size(args) != 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296 PyErr_SetString(PyExc_TypeError, "replace requires one argument");
297 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000298 }
299 if (!PyArg_ParseTuple(args, "O!;window object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000300 &PyCursesWindow_Type, &temp))
301 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000302
303 po = find_po(self->pan);
304 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000305 PyErr_SetString(PyExc_RuntimeError,
306 "replace_panel: can't find Panel Object");
307 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000308 }
309
310 rtn = replace_panel(self->pan, temp->win);
311 if (rtn == ERR) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200312 PyErr_SetString(_curses_panelstate_global->PyCursesError, "replace_panel() returned ERR");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000314 }
315 Py_DECREF(po->wo);
316 po->wo = temp;
317 Py_INCREF(po->wo);
318 Py_INCREF(Py_None);
319 return Py_None;
320}
321
322static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000323PyCursesPanel_set_panel_userptr(PyCursesPanelObject *self, PyObject *obj)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000324{
Andrew Kuchling53e5ea72013-06-15 14:04:04 -0400325 PyObject *oldobj;
Andrew Kuchling9290dd12013-06-22 14:50:56 -0400326 int rc;
Andrew Kuchling53e5ea72013-06-15 14:04:04 -0400327 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000328 Py_INCREF(obj);
Andrew Kuchling9290dd12013-06-22 14:50:56 -0400329 oldobj = (PyObject *) panel_userptr(self->pan);
330 rc = set_panel_userptr(self->pan, (void*)obj);
331 if (rc == ERR) {
332 /* In case of an ncurses error, decref the new object again */
333 Py_DECREF(obj);
334 }
335 Py_XDECREF(oldobj);
336 return PyCursesCheckERR(rc, "set_panel_userptr");
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000337}
338
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000339static PyObject *
340PyCursesPanel_userptr(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000341{
342 PyObject *obj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000343 PyCursesInitialised;
Fred Drake4e36d582000-12-23 05:46:23 +0000344 obj = (PyObject *) panel_userptr(self->pan);
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000345 if (obj == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200346 PyErr_SetString(_curses_panelstate_global->PyCursesError, "no userptr set");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000347 return NULL;
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000348 }
349
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000350 Py_INCREF(obj);
351 return obj;
352}
353
354
355/* Module interface */
356
357static PyMethodDef PyCursesPanel_Methods[] = {
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000358 {"above", (PyCFunction)PyCursesPanel_above, METH_NOARGS},
359 {"below", (PyCFunction)PyCursesPanel_below, METH_NOARGS},
360 {"bottom", (PyCFunction)PyCursesPanel_bottom_panel, METH_NOARGS},
361 {"hidden", (PyCFunction)PyCursesPanel_panel_hidden, METH_NOARGS},
362 {"hide", (PyCFunction)PyCursesPanel_hide_panel, METH_NOARGS},
363 {"move", (PyCFunction)PyCursesPanel_move_panel, METH_VARARGS},
Neal Norwitz01b26942002-03-31 14:55:17 +0000364 {"replace", (PyCFunction)PyCursesPanel_replace_panel, METH_VARARGS},
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000365 {"set_userptr", (PyCFunction)PyCursesPanel_set_panel_userptr, METH_O},
366 {"show", (PyCFunction)PyCursesPanel_show_panel, METH_NOARGS},
367 {"top", (PyCFunction)PyCursesPanel_top_panel, METH_NOARGS},
368 {"userptr", (PyCFunction)PyCursesPanel_userptr, METH_NOARGS},
369 {"window", (PyCFunction)PyCursesPanel_window, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000371};
372
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000373/* -------------------------------------------------------*/
374
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200375static PyType_Slot PyCursesPanel_Type_slots[] = {
376 {Py_tp_dealloc, PyCursesPanel_Dealloc},
377 {Py_tp_methods, PyCursesPanel_Methods},
378 {0, 0},
379};
380
381static PyType_Spec PyCursesPanel_Type_spec = {
382 "_curses_panel.curses panel",
383 sizeof(PyCursesPanelObject),
384 0,
385 Py_TPFLAGS_DEFAULT,
386 PyCursesPanel_Type_slots
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000387};
388
389/* Wrapper for panel_above(NULL). This function returns the bottom
390 panel of the stack, so it's renamed to bottom_panel().
391 panel.above() *requires* a panel object in the first place which
392 may be undesirable. */
393static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000394PyCurses_bottom_panel(PyObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000395{
396 PANEL *pan;
397 PyCursesPanelObject *po;
398
399 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000400
401 pan = panel_above(NULL);
402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 if (pan == NULL) { /* valid output, it means
404 there's no panel at all */
405 Py_INCREF(Py_None);
406 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000407 }
408 po = find_po(pan);
409 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000410 PyErr_SetString(PyExc_RuntimeError,
411 "panel_above: can't find Panel Object");
412 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000413 }
414 Py_INCREF(po);
415 return (PyObject *)po;
416}
417
418static PyObject *
419PyCurses_new_panel(PyObject *self, PyObject *args)
420{
421 PyCursesWindowObject *win;
422 PANEL *pan;
423
Fred Drake4e36d582000-12-23 05:46:23 +0000424 if (!PyArg_ParseTuple(args, "O!", &PyCursesWindow_Type, &win))
425 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000426 pan = new_panel(win->win);
427 if (pan == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200428 PyErr_SetString(_curses_panelstate_global->PyCursesError, catchall_NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000429 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000430 }
431 return (PyObject *)PyCursesPanel_New(pan, win);
432}
433
434
435/* Wrapper for panel_below(NULL). This function returns the top panel
436 of the stack, so it's renamed to top_panel(). panel.below()
437 *requires* a panel object in the first place which may be
438 undesirable. */
439static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000440PyCurses_top_panel(PyObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000441{
442 PANEL *pan;
443 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000444
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000445 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000446
447 pan = panel_below(NULL);
448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000449 if (pan == NULL) { /* valid output, it means
450 there's no panel at all */
451 Py_INCREF(Py_None);
452 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000453 }
454 po = find_po(pan);
455 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 PyErr_SetString(PyExc_RuntimeError,
457 "panel_below: can't find Panel Object");
458 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000459 }
460 Py_INCREF(po);
461 return (PyObject *)po;
462}
463
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000464static PyObject *PyCurses_update_panels(PyObject *self)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000465{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000466 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000467 update_panels();
468 Py_INCREF(Py_None);
469 return Py_None;
470}
471
472
473/* List of functions defined in the module */
474
475static PyMethodDef PyCurses_methods[] = {
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000476 {"bottom_panel", (PyCFunction)PyCurses_bottom_panel, METH_NOARGS},
477 {"new_panel", (PyCFunction)PyCurses_new_panel, METH_VARARGS},
478 {"top_panel", (PyCFunction)PyCurses_top_panel, METH_NOARGS},
479 {"update_panels", (PyCFunction)PyCurses_update_panels, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000480 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000481};
482
483/* Initialization function for the module */
484
Martin v. Löwis1a214512008-06-11 05:26:20 +0000485
486static struct PyModuleDef _curses_panelmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000487 PyModuleDef_HEAD_INIT,
488 "_curses_panel",
489 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200490 sizeof(_curses_panelstate),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000491 PyCurses_methods,
492 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200493 _curses_panel_traverse,
494 _curses_panel_clear,
495 _curses_panel_free
Martin v. Löwis1a214512008-06-11 05:26:20 +0000496};
497
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000498PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000499PyInit__curses_panel(void)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000500{
501 PyObject *m, *d, *v;
502
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000503 /* Create the module and add the functions */
Martin v. Löwis1a214512008-06-11 05:26:20 +0000504 m = PyModule_Create(&_curses_panelmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000505 if (m == NULL)
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200506 goto fail;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000507 d = PyModule_GetDict(m);
508
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200509 /* Initialize object type */
510 _curses_panelstate(m)->PyCursesPanel_Type = \
511 PyType_FromSpec(&PyCursesPanel_Type_spec);
512 if (_curses_panelstate(m)->PyCursesPanel_Type == NULL)
513 goto fail;
514
515 import_curses();
516
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000517 /* For exception _curses_panel.error */
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200518 _curses_panelstate(m)->PyCursesError = PyErr_NewException("_curses_panel.error", NULL, NULL);
519 PyDict_SetItemString(d, "error", _curses_panelstate(m)->PyCursesError);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000520
521 /* Make the version available */
Neal Norwitz53cbdaa2007-08-23 21:42:55 +0000522 v = PyUnicode_FromString(PyCursesVersion);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000523 PyDict_SetItemString(d, "version", v);
524 PyDict_SetItemString(d, "__version__", v);
525 Py_DECREF(v);
Martin v. Löwis1a214512008-06-11 05:26:20 +0000526 return m;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200527 fail:
528 Py_XDECREF(m);
529 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000530}