blob: 7d773d3f8c721fd8dae48117be7c4d741da4216a [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;
21} _curses_panelstate;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000022
Martin v. Löwisc838ec12012-06-14 16:00:24 +020023#define _curses_panelstate(o) ((_curses_panelstate *)PyModule_GetState(o))
24
25/*static PyObject *PyCursesError;*/
26
27static int
28_curses_panel_clear(PyObject *m)
29{
30 Py_CLEAR(_curses_panelstate(m)->PyCursesError);
31 return 0;
32}
33
34static int
35_curses_panel_traverse(PyObject *m, visitproc visit, void *arg)
36{
37 Py_VISIT(_curses_panelstate(m)->PyCursesError);
38 return 0;
39}
40
41static void
42_curses_panel_free(void *m)
43{
44 _curses_panel_clear((PyObject *) m);
45}
46
47static struct PyModuleDef _curses_panelmodule;
48
49#define _curses_panelstate_global \
50((_curses_panelstate *) PyModule_GetState(PyState_FindModule(&_curses_panelmodule)))
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000051
52/* Utility Functions */
53
54/*
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000055 * Check the return code from a curses function and return None
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000056 * or raise an exception as appropriate.
57 */
58
59static PyObject *
60PyCursesCheckERR(int code, char *fname)
61{
62 if (code != ERR) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 Py_INCREF(Py_None);
64 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000065 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000066 if (fname == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +020067 PyErr_SetString(_curses_panelstate_global->PyCursesError, catchall_ERR);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000068 } else {
Martin v. Löwisc838ec12012-06-14 16:00:24 +020069 PyErr_Format(_curses_panelstate_global->PyCursesError, "%s() returned ERR", fname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 }
71 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000072 }
73}
74
75/*****************************************************************************
76 The Panel Object
77******************************************************************************/
78
79/* Definition of the panel object and panel type */
80
81typedef struct {
82 PyObject_HEAD
83 PANEL *pan;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000084 PyCursesWindowObject *wo; /* for reference counts */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000085} PyCursesPanelObject;
86
87PyTypeObject PyCursesPanel_Type;
88
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000089#define PyCursesPanel_Check(v) (Py_TYPE(v) == &PyCursesPanel_Type)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +000090
91/* Some helper functions. The problem is that there's always a window
92 associated with a panel. To ensure that Python's GC doesn't pull
93 this window from under our feet we need to keep track of references
94 to the corresponding window object within Python. We can't use
95 dupwin(oldwin) to keep a copy of the curses WINDOW because the
96 contents of oldwin is copied only once; code like
97
98 win = newwin(...)
99 pan = win.panel()
100 win.addstr(some_string)
101 pan.window().addstr(other_string)
102
103 will fail. */
104
105/* We keep a linked list of PyCursesPanelObjects, lop. A list should
106 suffice, I don't expect more than a handful or at most a few
107 dozens of panel objects within a typical program. */
108typedef struct _list_of_panels {
109 PyCursesPanelObject *po;
110 struct _list_of_panels *next;
111} list_of_panels;
112
113/* list anchor */
114static list_of_panels *lop;
115
116/* Insert a new panel object into lop */
117static int
118insert_lop(PyCursesPanelObject *po)
119{
120 list_of_panels *new;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000121
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000122 if ((new = (list_of_panels *)malloc(sizeof(list_of_panels))) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000123 PyErr_NoMemory();
124 return -1;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000125 }
126 new->po = po;
127 new->next = lop;
128 lop = new;
129 return 0;
130}
131
132/* Remove the panel object from lop */
133static void
134remove_lop(PyCursesPanelObject *po)
135{
136 list_of_panels *temp, *n;
137
138 temp = lop;
139 if (temp->po == po) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000140 lop = temp->next;
141 free(temp);
142 return;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000143 }
Thomas Wouters47f003d2006-03-07 13:38:14 +0000144 while (temp->next == NULL || temp->next->po != po) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 if (temp->next == NULL) {
146 PyErr_SetString(PyExc_RuntimeError,
147 "remove_lop: can't find Panel Object");
148 return;
149 }
150 temp = temp->next;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000151 }
152 n = temp->next->next;
153 free(temp->next);
154 temp->next = n;
155 return;
156}
157
158/* Return the panel object that corresponds to pan */
159static PyCursesPanelObject *
160find_po(PANEL *pan)
161{
162 list_of_panels *temp;
163 for (temp = lop; temp->po->pan != pan; temp = temp->next)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000164 if (temp->next == NULL) return NULL; /* not found!? */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000165 return temp->po;
166}
167
168/* Function Prototype Macros - They are ugly but very, very useful. ;-)
169
170 X - function name
171 TYPE - parameter Type
172 ERGSTR - format string for construction of the return value
173 PARSESTR - format string for argument parsing */
174
175#define Panel_NoArgNoReturnFunction(X) \
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000176static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self) \
177{ return PyCursesCheckERR(X(self->pan), # X); }
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000178
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000179#define Panel_NoArgTrueFalseFunction(X) \
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000180static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self) \
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000181{ \
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000182 if (X (self->pan) == FALSE) { Py_INCREF(Py_False); return Py_False; } \
183 else { Py_INCREF(Py_True); return Py_True; } }
184
185#define Panel_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \
Fred Drake4e36d582000-12-23 05:46:23 +0000186static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self, PyObject *args) \
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000187{ \
188 TYPE arg1, arg2; \
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000189 if (!PyArg_ParseTuple(args, PARSESTR, &arg1, &arg2)) return NULL; \
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000190 return PyCursesCheckERR(X(self->pan, arg1, arg2), # X); }
191
192/* ------------- PANEL routines --------------- */
193
194Panel_NoArgNoReturnFunction(bottom_panel)
195Panel_NoArgNoReturnFunction(hide_panel)
196Panel_NoArgNoReturnFunction(show_panel)
197Panel_NoArgNoReturnFunction(top_panel)
198Panel_NoArgTrueFalseFunction(panel_hidden)
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000199Panel_TwoArgNoReturnFunction(move_panel, int, "ii;y,x")
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000200
201/* Allocation and deallocation of Panel Objects */
202
203static PyObject *
204PyCursesPanel_New(PANEL *pan, PyCursesWindowObject *wo)
205{
206 PyCursesPanelObject *po;
207
208 po = PyObject_NEW(PyCursesPanelObject, &PyCursesPanel_Type);
209 if (po == NULL) return NULL;
210 po->pan = pan;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000211 if (insert_lop(po) < 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 po->wo = NULL;
213 Py_DECREF(po);
214 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000215 }
Victor Stinnera7612272010-03-03 21:56:53 +0000216 po->wo = wo;
217 Py_INCREF(wo);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000218 return (PyObject *)po;
219}
220
221static void
222PyCursesPanel_Dealloc(PyCursesPanelObject *po)
223{
224 (void)del_panel(po->pan);
Victor Stinnera7612272010-03-03 21:56:53 +0000225 if (po->wo != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 Py_DECREF(po->wo);
227 remove_lop(po);
Victor Stinnera7612272010-03-03 21:56:53 +0000228 }
Michael W. Hudsoncf6bfe42002-01-30 15:47:34 +0000229 PyObject_DEL(po);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000230}
231
232/* panel_above(NULL) returns the bottom panel in the stack. To get
233 this behaviour we use curses.panel.bottom_panel(). */
234static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000235PyCursesPanel_above(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000236{
237 PANEL *pan;
238 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000239
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000240 pan = panel_above(self->pan);
241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 if (pan == NULL) { /* valid output, it means the calling panel
243 is on top of the stack */
244 Py_INCREF(Py_None);
245 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000246 }
247 po = find_po(pan);
248 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000249 PyErr_SetString(PyExc_RuntimeError,
250 "panel_above: can't find Panel Object");
251 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000252 }
253 Py_INCREF(po);
254 return (PyObject *)po;
255}
256
257/* panel_below(NULL) returns the top panel in the stack. To get
Andrew M. Kuchlingae89af92001-01-19 15:35:26 +0000258 this behaviour we use curses.panel.top_panel(). */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000259static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000260PyCursesPanel_below(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000261{
262 PANEL *pan;
263 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000265 pan = panel_below(self->pan);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266
267 if (pan == NULL) { /* valid output, it means the calling panel
268 is on the bottom of the stack */
269 Py_INCREF(Py_None);
270 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000271 }
272 po = find_po(pan);
273 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000274 PyErr_SetString(PyExc_RuntimeError,
275 "panel_below: can't find Panel Object");
276 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000277 }
278 Py_INCREF(po);
279 return (PyObject *)po;
280}
281
282static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000283PyCursesPanel_window(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000284{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000285 Py_INCREF(self->wo);
286 return (PyObject *)self->wo;
287}
288
289static PyObject *
290PyCursesPanel_replace_panel(PyCursesPanelObject *self, PyObject *args)
291{
292 PyCursesPanelObject *po;
293 PyCursesWindowObject *temp;
294 int rtn;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000295
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000296 if (PyTuple_Size(args) != 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 PyErr_SetString(PyExc_TypeError, "replace requires one argument");
298 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000299 }
300 if (!PyArg_ParseTuple(args, "O!;window object",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000301 &PyCursesWindow_Type, &temp))
302 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000303
304 po = find_po(self->pan);
305 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000306 PyErr_SetString(PyExc_RuntimeError,
307 "replace_panel: can't find Panel Object");
308 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000309 }
310
311 rtn = replace_panel(self->pan, temp->win);
312 if (rtn == ERR) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200313 PyErr_SetString(_curses_panelstate_global->PyCursesError, "replace_panel() returned ERR");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000314 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000315 }
316 Py_DECREF(po->wo);
317 po->wo = temp;
318 Py_INCREF(po->wo);
319 Py_INCREF(Py_None);
320 return Py_None;
321}
322
323static PyObject *
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000324PyCursesPanel_set_panel_userptr(PyCursesPanelObject *self, PyObject *obj)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000325{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000326 Py_INCREF(obj);
Martin v. Löwisa38d9162001-10-13 08:50:10 +0000327 return PyCursesCheckERR(set_panel_userptr(self->pan, (void*)obj),
Fred Drake4e36d582000-12-23 05:46:23 +0000328 "set_panel_userptr");
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000329}
330
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000331static PyObject *
332PyCursesPanel_userptr(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000333{
334 PyObject *obj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000335 PyCursesInitialised;
Fred Drake4e36d582000-12-23 05:46:23 +0000336 obj = (PyObject *) panel_userptr(self->pan);
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000337 if (obj == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200338 PyErr_SetString(_curses_panelstate_global->PyCursesError, "no userptr set");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000339 return NULL;
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000340 }
341
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000342 Py_INCREF(obj);
343 return obj;
344}
345
346
347/* Module interface */
348
349static PyMethodDef PyCursesPanel_Methods[] = {
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000350 {"above", (PyCFunction)PyCursesPanel_above, METH_NOARGS},
351 {"below", (PyCFunction)PyCursesPanel_below, METH_NOARGS},
352 {"bottom", (PyCFunction)PyCursesPanel_bottom_panel, METH_NOARGS},
353 {"hidden", (PyCFunction)PyCursesPanel_panel_hidden, METH_NOARGS},
354 {"hide", (PyCFunction)PyCursesPanel_hide_panel, METH_NOARGS},
355 {"move", (PyCFunction)PyCursesPanel_move_panel, METH_VARARGS},
Neal Norwitz01b26942002-03-31 14:55:17 +0000356 {"replace", (PyCFunction)PyCursesPanel_replace_panel, METH_VARARGS},
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000357 {"set_userptr", (PyCFunction)PyCursesPanel_set_panel_userptr, METH_O},
358 {"show", (PyCFunction)PyCursesPanel_show_panel, METH_NOARGS},
359 {"top", (PyCFunction)PyCursesPanel_top_panel, METH_NOARGS},
360 {"userptr", (PyCFunction)PyCursesPanel_userptr, METH_NOARGS},
361 {"window", (PyCFunction)PyCursesPanel_window, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000363};
364
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000365/* -------------------------------------------------------*/
366
367PyTypeObject PyCursesPanel_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000368 PyVarObject_HEAD_INIT(NULL, 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000369 "_curses_panel.curses panel", /*tp_name*/
370 sizeof(PyCursesPanelObject), /*tp_basicsize*/
371 0, /*tp_itemsize*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000372 /* methods */
373 (destructor)PyCursesPanel_Dealloc, /*tp_dealloc*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000374 0, /*tp_print*/
375 0, /*tp_getattr*/
376 0, /*tp_setattr*/
377 0, /*tp_reserved*/
378 0, /*tp_repr*/
379 0, /*tp_as_number*/
380 0, /*tp_as_sequence*/
381 0, /*tp_as_mapping*/
382 0, /*tp_hash*/
383 0, /*tp_call*/
384 0, /*tp_str*/
385 0, /*tp_getattro*/
386 0, /*tp_setattro*/
387 0, /*tp_as_buffer*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000388 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389 0, /*tp_doc*/
390 0, /*tp_traverse*/
391 0, /*tp_clear*/
392 0, /*tp_richcompare*/
393 0, /*tp_weaklistoffset*/
394 0, /*tp_iter*/
395 0, /*tp_iternext*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000396 PyCursesPanel_Methods, /*tp_methods*/
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000397};
398
399/* Wrapper for panel_above(NULL). This function returns the bottom
400 panel of the stack, so it's renamed to bottom_panel().
401 panel.above() *requires* a panel object in the first place which
402 may be undesirable. */
403static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000404PyCurses_bottom_panel(PyObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000405{
406 PANEL *pan;
407 PyCursesPanelObject *po;
408
409 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000410
411 pan = panel_above(NULL);
412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000413 if (pan == NULL) { /* valid output, it means
414 there's no panel at all */
415 Py_INCREF(Py_None);
416 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000417 }
418 po = find_po(pan);
419 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000420 PyErr_SetString(PyExc_RuntimeError,
421 "panel_above: can't find Panel Object");
422 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000423 }
424 Py_INCREF(po);
425 return (PyObject *)po;
426}
427
428static PyObject *
429PyCurses_new_panel(PyObject *self, PyObject *args)
430{
431 PyCursesWindowObject *win;
432 PANEL *pan;
433
Fred Drake4e36d582000-12-23 05:46:23 +0000434 if (!PyArg_ParseTuple(args, "O!", &PyCursesWindow_Type, &win))
435 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000436 pan = new_panel(win->win);
437 if (pan == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200438 PyErr_SetString(_curses_panelstate_global->PyCursesError, catchall_NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000439 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000440 }
441 return (PyObject *)PyCursesPanel_New(pan, win);
442}
443
444
445/* Wrapper for panel_below(NULL). This function returns the top panel
446 of the stack, so it's renamed to top_panel(). panel.below()
447 *requires* a panel object in the first place which may be
448 undesirable. */
449static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000450PyCurses_top_panel(PyObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000451{
452 PANEL *pan;
453 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000454
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000455 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000456
457 pan = panel_below(NULL);
458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000459 if (pan == NULL) { /* valid output, it means
460 there's no panel at all */
461 Py_INCREF(Py_None);
462 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000463 }
464 po = find_po(pan);
465 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 PyErr_SetString(PyExc_RuntimeError,
467 "panel_below: can't find Panel Object");
468 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000469 }
470 Py_INCREF(po);
471 return (PyObject *)po;
472}
473
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000474static PyObject *PyCurses_update_panels(PyObject *self)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000475{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000476 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000477 update_panels();
478 Py_INCREF(Py_None);
479 return Py_None;
480}
481
482
483/* List of functions defined in the module */
484
485static PyMethodDef PyCurses_methods[] = {
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000486 {"bottom_panel", (PyCFunction)PyCurses_bottom_panel, METH_NOARGS},
487 {"new_panel", (PyCFunction)PyCurses_new_panel, METH_VARARGS},
488 {"top_panel", (PyCFunction)PyCurses_top_panel, METH_NOARGS},
489 {"update_panels", (PyCFunction)PyCurses_update_panels, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000491};
492
493/* Initialization function for the module */
494
Martin v. Löwis1a214512008-06-11 05:26:20 +0000495
496static struct PyModuleDef _curses_panelmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 PyModuleDef_HEAD_INIT,
498 "_curses_panel",
499 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200500 sizeof(_curses_panelstate),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000501 PyCurses_methods,
502 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200503 _curses_panel_traverse,
504 _curses_panel_clear,
505 _curses_panel_free
Martin v. Löwis1a214512008-06-11 05:26:20 +0000506};
507
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000508PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000509PyInit__curses_panel(void)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000510{
511 PyObject *m, *d, *v;
512
Fred Drake2174f802001-01-27 18:58:04 +0000513 /* Initialize object type */
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000514 if (PyType_Ready(&PyCursesPanel_Type) < 0)
515 return NULL;
Guido van Rossuma120ffc2001-01-22 15:29:14 +0000516
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000517 import_curses();
Fred Drake2174f802001-01-27 18:58:04 +0000518
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000519 /* Create the module and add the functions */
Martin v. Löwis1a214512008-06-11 05:26:20 +0000520 m = PyModule_Create(&_curses_panelmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000521 if (m == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000522 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000523 d = PyModule_GetDict(m);
524
525 /* For exception _curses_panel.error */
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200526 _curses_panelstate(m)->PyCursesError = PyErr_NewException("_curses_panel.error", NULL, NULL);
527 PyDict_SetItemString(d, "error", _curses_panelstate(m)->PyCursesError);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000528
529 /* Make the version available */
Neal Norwitz53cbdaa2007-08-23 21:42:55 +0000530 v = PyUnicode_FromString(PyCursesVersion);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000531 PyDict_SetItemString(d, "version", v);
532 PyDict_SetItemString(d, "__version__", v);
533 Py_DECREF(v);
Martin v. Löwis1a214512008-06-11 05:26:20 +0000534 return m;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000535}