blob: 1c7d0842e84ab5400fa65d696e7f2ff25fe746fb [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
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000120 if ((new = (list_of_panels *)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;
139 free(temp);
140 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;
151 free(temp->next);
152 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 M. Kuchling7b59ed22000-12-22 21:54:12 +0000325 Py_INCREF(obj);
Martin v. Löwisa38d9162001-10-13 08:50:10 +0000326 return PyCursesCheckERR(set_panel_userptr(self->pan, (void*)obj),
Fred Drake4e36d582000-12-23 05:46:23 +0000327 "set_panel_userptr");
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000328}
329
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000330static PyObject *
331PyCursesPanel_userptr(PyCursesPanelObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000332{
333 PyObject *obj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 PyCursesInitialised;
Fred Drake4e36d582000-12-23 05:46:23 +0000335 obj = (PyObject *) panel_userptr(self->pan);
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000336 if (obj == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200337 PyErr_SetString(_curses_panelstate_global->PyCursesError, "no userptr set");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000338 return NULL;
Neal Norwitz5e3d8622006-01-09 06:24:35 +0000339 }
340
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000341 Py_INCREF(obj);
342 return obj;
343}
344
345
346/* Module interface */
347
348static PyMethodDef PyCursesPanel_Methods[] = {
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000349 {"above", (PyCFunction)PyCursesPanel_above, METH_NOARGS},
350 {"below", (PyCFunction)PyCursesPanel_below, METH_NOARGS},
351 {"bottom", (PyCFunction)PyCursesPanel_bottom_panel, METH_NOARGS},
352 {"hidden", (PyCFunction)PyCursesPanel_panel_hidden, METH_NOARGS},
353 {"hide", (PyCFunction)PyCursesPanel_hide_panel, METH_NOARGS},
354 {"move", (PyCFunction)PyCursesPanel_move_panel, METH_VARARGS},
Neal Norwitz01b26942002-03-31 14:55:17 +0000355 {"replace", (PyCFunction)PyCursesPanel_replace_panel, METH_VARARGS},
Martin v. Löwisc0e16712002-01-17 23:08:27 +0000356 {"set_userptr", (PyCFunction)PyCursesPanel_set_panel_userptr, METH_O},
357 {"show", (PyCFunction)PyCursesPanel_show_panel, METH_NOARGS},
358 {"top", (PyCFunction)PyCursesPanel_top_panel, METH_NOARGS},
359 {"userptr", (PyCFunction)PyCursesPanel_userptr, METH_NOARGS},
360 {"window", (PyCFunction)PyCursesPanel_window, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000361 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000362};
363
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000364/* -------------------------------------------------------*/
365
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200366static PyType_Slot PyCursesPanel_Type_slots[] = {
367 {Py_tp_dealloc, PyCursesPanel_Dealloc},
368 {Py_tp_methods, PyCursesPanel_Methods},
369 {0, 0},
370};
371
372static PyType_Spec PyCursesPanel_Type_spec = {
373 "_curses_panel.curses panel",
374 sizeof(PyCursesPanelObject),
375 0,
376 Py_TPFLAGS_DEFAULT,
377 PyCursesPanel_Type_slots
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000378};
379
380/* Wrapper for panel_above(NULL). This function returns the bottom
381 panel of the stack, so it's renamed to bottom_panel().
382 panel.above() *requires* a panel object in the first place which
383 may be undesirable. */
384static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000385PyCurses_bottom_panel(PyObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000386{
387 PANEL *pan;
388 PyCursesPanelObject *po;
389
390 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000391
392 pan = panel_above(NULL);
393
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000394 if (pan == NULL) { /* valid output, it means
395 there's no panel at all */
396 Py_INCREF(Py_None);
397 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000398 }
399 po = find_po(pan);
400 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000401 PyErr_SetString(PyExc_RuntimeError,
402 "panel_above: can't find Panel Object");
403 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000404 }
405 Py_INCREF(po);
406 return (PyObject *)po;
407}
408
409static PyObject *
410PyCurses_new_panel(PyObject *self, PyObject *args)
411{
412 PyCursesWindowObject *win;
413 PANEL *pan;
414
Fred Drake4e36d582000-12-23 05:46:23 +0000415 if (!PyArg_ParseTuple(args, "O!", &PyCursesWindow_Type, &win))
416 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000417 pan = new_panel(win->win);
418 if (pan == NULL) {
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200419 PyErr_SetString(_curses_panelstate_global->PyCursesError, catchall_NULL);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000420 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000421 }
422 return (PyObject *)PyCursesPanel_New(pan, win);
423}
424
425
426/* Wrapper for panel_below(NULL). This function returns the top panel
427 of the stack, so it's renamed to top_panel(). panel.below()
428 *requires* a panel object in the first place which may be
429 undesirable. */
430static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000431PyCurses_top_panel(PyObject *self)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000432{
433 PANEL *pan;
434 PyCursesPanelObject *po;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000435
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000436 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000437
438 pan = panel_below(NULL);
439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 if (pan == NULL) { /* valid output, it means
441 there's no panel at all */
442 Py_INCREF(Py_None);
443 return Py_None;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000444 }
445 po = find_po(pan);
446 if (po == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000447 PyErr_SetString(PyExc_RuntimeError,
448 "panel_below: can't find Panel Object");
449 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000450 }
451 Py_INCREF(po);
452 return (PyObject *)po;
453}
454
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000455static PyObject *PyCurses_update_panels(PyObject *self)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456{
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000457 PyCursesInitialised;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000458 update_panels();
459 Py_INCREF(Py_None);
460 return Py_None;
461}
462
463
464/* List of functions defined in the module */
465
466static PyMethodDef PyCurses_methods[] = {
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000467 {"bottom_panel", (PyCFunction)PyCurses_bottom_panel, METH_NOARGS},
468 {"new_panel", (PyCFunction)PyCurses_new_panel, METH_VARARGS},
469 {"top_panel", (PyCFunction)PyCurses_top_panel, METH_NOARGS},
470 {"update_panels", (PyCFunction)PyCurses_update_panels, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000471 {NULL, NULL} /* sentinel */
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000472};
473
474/* Initialization function for the module */
475
Martin v. Löwis1a214512008-06-11 05:26:20 +0000476
477static struct PyModuleDef _curses_panelmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000478 PyModuleDef_HEAD_INIT,
479 "_curses_panel",
480 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200481 sizeof(_curses_panelstate),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000482 PyCurses_methods,
483 NULL,
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200484 _curses_panel_traverse,
485 _curses_panel_clear,
486 _curses_panel_free
Martin v. Löwis1a214512008-06-11 05:26:20 +0000487};
488
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000489PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000490PyInit__curses_panel(void)
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000491{
492 PyObject *m, *d, *v;
493
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000494 /* Create the module and add the functions */
Martin v. Löwis1a214512008-06-11 05:26:20 +0000495 m = PyModule_Create(&_curses_panelmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000496 if (m == NULL)
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200497 goto fail;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000498 d = PyModule_GetDict(m);
499
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200500 /* Initialize object type */
501 _curses_panelstate(m)->PyCursesPanel_Type = \
502 PyType_FromSpec(&PyCursesPanel_Type_spec);
503 if (_curses_panelstate(m)->PyCursesPanel_Type == NULL)
504 goto fail;
505
506 import_curses();
507
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000508 /* For exception _curses_panel.error */
Martin v. Löwisc838ec12012-06-14 16:00:24 +0200509 _curses_panelstate(m)->PyCursesError = PyErr_NewException("_curses_panel.error", NULL, NULL);
510 PyDict_SetItemString(d, "error", _curses_panelstate(m)->PyCursesError);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000511
512 /* Make the version available */
Neal Norwitz53cbdaa2007-08-23 21:42:55 +0000513 v = PyUnicode_FromString(PyCursesVersion);
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000514 PyDict_SetItemString(d, "version", v);
515 PyDict_SetItemString(d, "__version__", v);
516 Py_DECREF(v);
Martin v. Löwis1a214512008-06-11 05:26:20 +0000517 return m;
Martin v. Löwisbc07cb82012-06-14 16:01:23 +0200518 fail:
519 Py_XDECREF(m);
520 return NULL;
Andrew M. Kuchling7b59ed22000-12-22 21:54:12 +0000521}