blob: 759b73109d25c16028678dc985117e6848bae23e [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 }
Serhiy Storchaka5a57ade2015-12-24 10:35:59 +0200315 Py_INCREF(temp);
316 Py_SETREF(po->wo, temp);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000317 Py_INCREF(Py_None);
318 return Py_None;
319}
320
321static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000322PyCursesPanel_set_panel_userptr(PyCursesPanelObject *self, PyObject *obj)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000323{
Andrew Kuchling53e5ea72013-06-15 14:04:04 -0400324 PyObject *oldobj;
Andrew Kuchling9290dd12013-06-22 14:50:56 -0400325 int rc;
Andrew Kuchling53e5ea72013-06-15 14:04:04 -0400326 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000327 Py_INCREF(obj);
Andrew Kuchling9290dd12013-06-22 14:50:56 -0400328 oldobj = (PyObject *) panel_userptr(self->pan);
329 rc = set_panel_userptr(self->pan, (void*)obj);
330 if (rc == ERR) {
331 /* In case of an ncurses error, decref the new object again */
332 Py_DECREF(obj);
333 }
334 Py_XDECREF(oldobj);
335 return PyCursesCheckERR(rc, "set_panel_userptr");
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000336}
337
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000338static PyObject *
339PyCursesPanel_userptr(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000340{
341 PyObject *obj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000342 PyCursesInitialised;
Fred Drake4e36d582000-12-23 05:46:23 +0000343 obj = (PyObject *) panel_userptr(self->pan);
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000344 if (obj == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200345 PyErr_SetString(_curses_panelstate_global->PyCursesError, "no userptr set");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000346 return NULL;
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000347 }
348
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000349 Py_INCREF(obj);
350 return obj;
351}
352
353
354/* Module interface */
355
356static PyMethodDef PyCursesPanel_Methods[] = {
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000357 {"above", (PyCFunction)PyCursesPanel_above, METH_NOARGS},
358 {"below", (PyCFunction)PyCursesPanel_below, METH_NOARGS},
359 {"bottom", (PyCFunction)PyCursesPanel_bottom_panel, METH_NOARGS},
360 {"hidden", (PyCFunction)PyCursesPanel_panel_hidden, METH_NOARGS},
361 {"hide", (PyCFunction)PyCursesPanel_hide_panel, METH_NOARGS},
362 {"move", (PyCFunction)PyCursesPanel_move_panel, METH_VARARGS},
Neal Norwitz01b26942002-03-31 14:55:17 +0000363 {"replace", (PyCFunction)PyCursesPanel_replace_panel, METH_VARARGS},
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000364 {"set_userptr", (PyCFunction)PyCursesPanel_set_panel_userptr, METH_O},
365 {"show", (PyCFunction)PyCursesPanel_show_panel, METH_NOARGS},
366 {"top", (PyCFunction)PyCursesPanel_top_panel, METH_NOARGS},
367 {"userptr", (PyCFunction)PyCursesPanel_userptr, METH_NOARGS},
368 {"window", (PyCFunction)PyCursesPanel_window, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000369 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000370};
371
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000372/* -------------------------------------------------------*/
373
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200374static PyType_Slot PyCursesPanel_Type_slots[] = {
375 {Py_tp_dealloc, PyCursesPanel_Dealloc},
376 {Py_tp_methods, PyCursesPanel_Methods},
377 {0, 0},
378};
379
380static PyType_Spec PyCursesPanel_Type_spec = {
381 "_curses_panel.curses panel",
382 sizeof(PyCursesPanelObject),
383 0,
384 Py_TPFLAGS_DEFAULT,
385 PyCursesPanel_Type_slots
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000386};
387
388/* Wrapper for panel_above(NULL). This function returns the bottom
389 panel of the stack, so it's renamed to bottom_panel().
390 panel.above() *requires* a panel object in the first place which
391 may be undesirable. */
392static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000393PyCurses_bottom_panel(PyObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000394{
395 PANEL *pan;
396 PyCursesPanelObject *po;
397
398 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000399
400 pan = panel_above(NULL);
401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000402 if (pan == NULL) { /* valid output, it means
403 there's no panel at all */
404 Py_INCREF(Py_None);
405 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000406 }
407 po = find_po(pan);
408 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000409 PyErr_SetString(PyExc_RuntimeError,
410 "panel_above: can't find Panel Object");
411 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000412 }
413 Py_INCREF(po);
414 return (PyObject *)po;
415}
416
417static PyObject *
418PyCurses_new_panel(PyObject *self, PyObject *args)
419{
420 PyCursesWindowObject *win;
421 PANEL *pan;
422
Fred Drake4e36d582000-12-23 05:46:23 +0000423 if (!PyArg_ParseTuple(args, "O!", &PyCursesWindow_Type, &win))
424 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000425 pan = new_panel(win->win);
426 if (pan == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200427 PyErr_SetString(_curses_panelstate_global->PyCursesError, catchall_NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000428 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000429 }
430 return (PyObject *)PyCursesPanel_New(pan, win);
431}
432
433
434/* Wrapper for panel_below(NULL). This function returns the top panel
435 of the stack, so it's renamed to top_panel(). panel.below()
436 *requires* a panel object in the first place which may be
437 undesirable. */
438static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000439PyCurses_top_panel(PyObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000440{
441 PANEL *pan;
442 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000444 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000445
446 pan = panel_below(NULL);
447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448 if (pan == NULL) { /* valid output, it means
449 there's no panel at all */
450 Py_INCREF(Py_None);
451 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000452 }
453 po = find_po(pan);
454 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000455 PyErr_SetString(PyExc_RuntimeError,
456 "panel_below: can't find Panel Object");
457 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000458 }
459 Py_INCREF(po);
460 return (PyObject *)po;
461}
462
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000463static PyObject *PyCurses_update_panels(PyObject *self)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000465 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000466 update_panels();
467 Py_INCREF(Py_None);
468 return Py_None;
469}
470
471
472/* List of functions defined in the module */
473
474static PyMethodDef PyCurses_methods[] = {
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000475 {"bottom_panel", (PyCFunction)PyCurses_bottom_panel, METH_NOARGS},
476 {"new_panel", (PyCFunction)PyCurses_new_panel, METH_VARARGS},
477 {"top_panel", (PyCFunction)PyCurses_top_panel, METH_NOARGS},
478 {"update_panels", (PyCFunction)PyCurses_update_panels, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000479 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000480};
481
482/* Initialization function for the module */
483
Martin v. Löwis1a214512008-06-11 05:26:20 +0000484
485static struct PyModuleDef _curses_panelmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 PyModuleDef_HEAD_INIT,
487 "_curses_panel",
488 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200489 sizeof(_curses_panelstate),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 PyCurses_methods,
491 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200492 _curses_panel_traverse,
493 _curses_panel_clear,
494 _curses_panel_free
Martin v. Löwis1a214512008-06-11 05:26:20 +0000495};
496
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000497PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000498PyInit__curses_panel(void)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000499{
500 PyObject *m, *d, *v;
501
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000502 /* Create the module and add the functions */
Martin v. Löwis1a214512008-06-11 05:26:20 +0000503 m = PyModule_Create(&_curses_panelmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000504 if (m == NULL)
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200505 goto fail;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000506 d = PyModule_GetDict(m);
507
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200508 /* Initialize object type */
509 _curses_panelstate(m)->PyCursesPanel_Type = \
510 PyType_FromSpec(&PyCursesPanel_Type_spec);
511 if (_curses_panelstate(m)->PyCursesPanel_Type == NULL)
512 goto fail;
513
514 import_curses();
Victor Stinner569f3642013-07-18 02:31:21 +0200515 if (PyErr_Occurred())
516 goto fail;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200517
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000518 /* For exception _curses_panel.error */
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200519 _curses_panelstate(m)->PyCursesError = PyErr_NewException("_curses_panel.error", NULL, NULL);
520 PyDict_SetItemString(d, "error", _curses_panelstate(m)->PyCursesError);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000521
522 /* Make the version available */
Neal Norwitz53cbdaa2007-08-23 21:42:55 +0000523 v = PyUnicode_FromString(PyCursesVersion);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000524 PyDict_SetItemString(d, "version", v);
525 PyDict_SetItemString(d, "__version__", v);
526 Py_DECREF(v);
Martin v. Löwis1a214512008-06-11 05:26:20 +0000527 return m;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200528 fail:
529 Py_XDECREF(m);
530 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000531}