1 
2 #include "Python.h"
3 #include "config.h"
4 
5 #ifdef HAVE_ALLOCA_H
6 #include <alloca.h>
7 #endif
8 
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <sys/stat.h>
12 #include <sys/time.h>
13 #include <unistd.h>
14 
15 #include "structmember.h"
16 #include "nls.h"
17 #include "newt.h"
18 #include "newt_pr.h"
19 
20 #if PY_MAJOR_VERSION >= 3
21   #define PyInt_FromLong PyLong_FromLong
22   #define PyInt_AsLong PyLong_AsLong
23   #define PyString_FromString PyUnicode_FromString
24   #define MOD_ERROR_VAL NULL
25   #define MOD_SUCCESS_VAL(val) val
26   #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
27 #else
28   #define MOD_ERROR_VAL
29   #define MOD_SUCCESS_VAL(val)
30   #define MOD_INIT(name) void init##name(void)
31 #endif
32 
33 typedef struct snackWidget_s snackWidget;
34 typedef struct snackGrid_s snackGrid;
35 typedef struct snackForm_s snackForm;
36 
37 struct callbackStruct {
38     PyObject * cb, * data;
39 };
40 
41 /* Integer to pointer, 64-bit-sane */
42 #define I2P(x) ((void *)(long)(x))
43 
44 static struct callbackStruct suspend;
45 static struct callbackStruct helpCallback;
46 
47 static void emptyDestructor(PyObject * s);
48 
49 static snackWidget * buttonWidget(PyObject * s, PyObject * args);
50 static snackWidget * compactbuttonWidget(PyObject * s, PyObject * args);
51 static PyObject * centeredWindow(PyObject * s, PyObject * args);
52 static snackWidget * checkboxWidget(PyObject * s, PyObject * args);
53 static PyObject * choiceWindow(PyObject * s, PyObject * args);
54 static snackWidget * entryWidget(PyObject * s, PyObject * args);
55 static PyObject * drawRootText(PyObject * s, PyObject * args);
56 static PyObject * doResume(PyObject * s, PyObject * args);
57 static PyObject * doSuspend(PyObject * s, PyObject * args);
58 static PyObject * doSuspend(PyObject * s, PyObject * args);
59 static snackForm * formCreate(PyObject * s, PyObject * args);
60 static snackGrid * gridCreate(PyObject * s, PyObject * args);
61 static PyObject * gridWrappedWindow(PyObject * s, PyObject * args);
62 static PyObject * finishScreen(PyObject * s, PyObject * args);
63 static PyObject * initScreen(PyObject * s, PyObject * args);
64 static snackWidget * labelWidget(PyObject * s, PyObject * args);
65 static snackWidget * listboxWidget(PyObject * s, PyObject * args);
66 static PyObject * messageWindow(PyObject * s, PyObject * args);
67 static PyObject * openWindow(PyObject * s, PyObject * args);
68 static PyObject * popHelpLine(PyObject * s, PyObject * args);
69 static PyObject * popWindow(PyObject * s, PyObject * args);
70 static PyObject * popWindowNoRefresh(PyObject * s, PyObject * args);
71 static PyObject * pushHelpLine(PyObject * s, PyObject * args);
72 static snackWidget * radioButtonWidget(PyObject * s, PyObject * args);
73 static PyObject * refreshScreen(PyObject * s, PyObject * args);
74 static PyObject * setColor(PyObject * s, PyObject * args);
75 static PyObject * scaleWidget(PyObject * s, PyObject * args);
76 static PyObject * scaleSet(snackWidget * s, PyObject * args);
77 static PyObject * screenSize(PyObject * s, PyObject * args);
78 static PyObject * setSuspendCallback(PyObject * s, PyObject * args);
79 static PyObject * setHelpCallback(PyObject * s, PyObject * args);
80 static PyObject * reflowText(PyObject * s, PyObject * args);
81 static snackWidget * textWidget(PyObject * s, PyObject * args);
82 static PyObject * ternaryWindow(PyObject * s, PyObject * args);
83 static snackWidget * checkboxTreeWidget(PyObject * s, PyObject * args, PyObject * kwargs);
84 static PyObject * pywstrlen(PyObject * s, PyObject * args);
85 static PyObject * widget_get_checkboxValue(PyObject *self, void *closure);
86 static PyObject * widget_get_radioValue(PyObject *self, void *closure);
87 
88 static PyMethodDef snackModuleMethods[] = {
89     { "button", (PyCFunction) buttonWidget, METH_VARARGS, NULL },
90     { "compactbutton", (PyCFunction) compactbuttonWidget, METH_VARARGS, NULL },
91     { "checkbox", (PyCFunction) checkboxWidget, METH_VARARGS, NULL },
92     { "choice", choiceWindow, METH_VARARGS, NULL },
93     { "centeredwindow", centeredWindow, METH_VARARGS, NULL },
94     { "drawroottext", drawRootText, METH_VARARGS, NULL },
95     { "entry", (PyCFunction) entryWidget, METH_VARARGS, NULL },
96     { "finish", finishScreen, METH_VARARGS, NULL },
97     { "form", (PyCFunction) formCreate, METH_VARARGS, NULL },
98     { "grid", (PyCFunction) gridCreate, METH_VARARGS, NULL },
99     { "gridwrappedwindow", gridWrappedWindow, METH_VARARGS, NULL },
100     { "helpcallback", setHelpCallback, METH_VARARGS, NULL },
101     { "init", initScreen, METH_VARARGS, NULL },
102     { "label", (PyCFunction) labelWidget, METH_VARARGS, NULL },
103     { "listbox", (PyCFunction) listboxWidget, METH_VARARGS, NULL },
104     { "message", messageWindow, METH_VARARGS, NULL },
105     { "openwindow", openWindow, METH_VARARGS, NULL },
106     { "pophelpline", popHelpLine, METH_VARARGS, NULL },
107     { "popwindow", popWindow, METH_VARARGS, NULL },
108     { "popwindownorefresh", popWindowNoRefresh, METH_VARARGS, NULL },
109     { "pushhelpline", pushHelpLine, METH_VARARGS, NULL },
110     { "radiobutton", (PyCFunction) radioButtonWidget, METH_VARARGS, NULL },
111     { "reflow", (PyCFunction) reflowText, METH_VARARGS, NULL },
112     { "refresh", refreshScreen, METH_VARARGS, NULL },
113     { "setcolor", setColor, METH_VARARGS, NULL },
114     { "resume", doResume, METH_VARARGS, NULL },
115     { "scale", scaleWidget, METH_VARARGS, NULL },
116     { "size", screenSize, METH_VARARGS, NULL },
117     { "suspend", doSuspend, METH_VARARGS, NULL },
118     { "suspendcallback", setSuspendCallback, METH_VARARGS, NULL },
119     { "ternary", ternaryWindow, METH_VARARGS, NULL },
120     { "textbox", (PyCFunction) textWidget, METH_VARARGS, NULL },
121     { "checkboxtree", (PyCFunction) checkboxTreeWidget, METH_VARARGS | METH_KEYWORDS, NULL },
122     { "wstrlen", (PyCFunction) pywstrlen, METH_VARARGS | METH_KEYWORDS, NULL },
123     { NULL }
124 } ;
125 
126 #if PY_MAJOR_VERSION >= 3
127 static struct PyModuleDef moduledef = {
128     PyModuleDef_HEAD_INIT,
129         "_snack",            /* m_name */
130         NULL,                /* m_doc */
131         -1,                  /* m_size */
132         snackModuleMethods,  /* m_methods */
133         NULL,                /* m_reload */
134         NULL,                /* m_traverse */
135         NULL,                /* m_clear */
136         NULL,                /* m_free */
137     };
138 #endif
139 
140 static struct PyGetSetDef widget_getset[] = {
141         { "checkboxValue", widget_get_checkboxValue, 0, NULL, NULL },
142         { "radioValue", widget_get_radioValue, 0, NULL, NULL },
143         { NULL }
144 };
145 
146 struct snackGrid_s {
147     PyObject_HEAD
148     newtGrid grid;
149 } ;
150 
151 static PyObject * gridPlace(snackGrid * s, PyObject * args);
152 static PyObject * gridSetField(snackGrid * s, PyObject * args);
153 
154 static PyMethodDef gridMethods[] = {
155     { "place", (PyCFunction) gridPlace, METH_VARARGS, NULL },
156     { "setfield", (PyCFunction) gridSetField, METH_VARARGS, NULL },
157     { NULL }
158 };
159 
160 static PyTypeObject snackGridType = {
161         PyVarObject_HEAD_INIT(&PyType_Type, 0)
162         "snackgrid",                    /* tp_name */
163         sizeof(snackGrid),              /* tp_size */
164         0,                              /* tp_itemsize */
165         emptyDestructor,      			/* tp_dealloc */
166         0,                              /* tp_print */
167         0,                   		/* tp_getattr */
168         0,                              /* tp_setattr */
169         0,                              /* tp_compare */
170         0,                              /* tp_repr */
171         0,                              /* tp_as_number */
172         0,                              /* tp_as_sequence */
173         0,                		/* tp_as_mapping */
174 	0,                              /* tp_hash */
175 	0,                              /* tp_call */
176 	0,                              /* tp_str */
177 	PyObject_GenericGetAttr,        /* tp_getattro */
178 	0,                              /* tp_setattro */
179 	0,                              /* tp_as_buffer */
180 	Py_TPFLAGS_DEFAULT,             /* tp_flags */
181 	0,                              /* tp_doc */
182 	0,                              /* tp_traverse */
183 	0,                              /* tp_clear */
184 	0,                              /* tp_richcompare */
185 	0,                              /* tp_weaklistoffset */
186 	0,                              /* tp_iter */
187 	0,                              /* tp_iternext */
188 	gridMethods                     /* tp_methods */
189 };
190 
191 struct snackForm_s {
192     PyObject_HEAD
193     newtComponent fo;
194 } ;
195 
196 static PyObject * formAdd(snackForm * s, PyObject * args);
197 static PyObject * formDraw(snackForm * s, PyObject * args);
198 static PyObject * formRun(snackForm * s, PyObject * args);
199 static PyObject * formHotKey(snackForm * s, PyObject * args);
200 static PyObject * formSetCurrent(snackForm * form, PyObject * args);
201 static PyObject * formSetTimer(snackForm * form, PyObject * args);
202 static PyObject * formWatchFD(snackForm * form, PyObject * args);
203 
204 static PyMethodDef formMethods[] = {
205     { "add", (PyCFunction) formAdd, METH_VARARGS, NULL },
206     { "draw", (PyCFunction) formDraw, METH_VARARGS, NULL },
207     { "run", (PyCFunction) formRun, METH_VARARGS, NULL },
208     { "addhotkey", (PyCFunction) formHotKey, METH_VARARGS, NULL },
209     { "setcurrent", (PyCFunction) formSetCurrent, METH_VARARGS, NULL },
210     { "settimer", (PyCFunction) formSetTimer, METH_VARARGS, NULL },
211     { "watchfd", (PyCFunction) formWatchFD, METH_VARARGS, NULL },
212     { NULL }
213 };
214 
215 static PyTypeObject snackFormType = {
216         PyVarObject_HEAD_INIT(&PyType_Type, 0)
217         "snackform",                    /* tp_name */
218         sizeof(snackForm),              /* tp_size */
219         0,                              /* tp_itemsize */
220         emptyDestructor,      		/* tp_dealloc */
221         0,                              /* tp_print */
222         0,                     		/* tp_getattr */
223         0,                              /* tp_setattr */
224         0,                              /* tp_compare */
225         0,                              /* tp_repr */
226         0,                              /* tp_as_number */
227         0,                              /* tp_as_sequence */
228         0,                		/* tp_as_mapping */
229 	0,                              /* tp_hash */
230 	0,                              /* tp_call */
231 	0,                              /* tp_str */
232 	PyObject_GenericGetAttr,        /* tp_getattro */
233 	0,                              /* tp_setattro */
234 	0,                              /* tp_as_buffer */
235 	Py_TPFLAGS_DEFAULT,             /* tp_flags */
236 	0,                              /* tp_doc */
237 	0,                              /* tp_traverse */
238 	0,                              /* tp_clear */
239 	0,                              /* tp_richcompare */
240 	0,                              /* tp_weaklistoffset */
241 	0,                              /* tp_iter */
242 	0,                              /* tp_iternext */
243 	formMethods                     /* tp_methods */
244 };
245 
246 struct snackWidget_s {
247     PyObject_HEAD
248     newtComponent co;
249     char achar;
250     void * apointer;
251     int anint;
252     struct callbackStruct scs;
253 } ;
254 
255 static PyObject * widgetAddCallback(snackWidget * s, PyObject * args);
256 static void widgetDestructor(PyObject * s);
257 static PyObject * widgetEntrySetValue(snackWidget * s, PyObject * args);
258 static PyObject * widgetLabelText(snackWidget * s, PyObject * args);
259 static PyObject * widgetLabelSetColors(snackWidget * s, PyObject * args);
260 static PyObject * widgetListboxSetW(snackWidget * s, PyObject * args);
261 static PyObject * widgetListboxAdd(snackWidget * s, PyObject * args);
262 static PyObject * widgetListboxIns(snackWidget * s, PyObject * args);
263 static PyObject * widgetListboxDel(snackWidget * s, PyObject * args);
264 static PyObject * widgetListboxGet(snackWidget * s, PyObject * args);
265 static PyObject * widgetListboxGetSel(snackWidget * s, PyObject * args);
266 static PyObject * widgetListboxSet(snackWidget * s, PyObject * args);
267 static PyObject * widgetListboxClear(snackWidget * s, PyObject * args);
268 static PyObject * widgetTextboxText(snackWidget * s, PyObject * args);
269 static PyObject * widgetTextboxHeight(snackWidget * s, PyObject * args);
270 static PyObject * widgetCheckboxTreeAddItem(snackWidget * s, PyObject * args);
271 static PyObject * widgetCheckboxTreeGetSel(snackWidget * s, PyObject * args);
272 static PyObject * widgetCheckboxTreeGetCur(snackWidget * s, PyObject * args);
273 static PyObject * widgetCheckboxTreeSetEntry(snackWidget * s, PyObject * args);
274 static PyObject * widgetCheckboxTreeSetWidth(snackWidget * s, PyObject * args);
275 static PyObject * widgetCheckboxTreeSetCurrent(snackWidget * s, PyObject * args);
276 static PyObject * widgetCheckboxTreeSetEntryValue(snackWidget * s, PyObject * args);
277 static PyObject * widgetCheckboxTreeGetEntryValue(snackWidget * s, PyObject * args);
278 static PyObject * widgetEntrySetFlags(snackWidget * s, PyObject * args);
279 static PyObject * widgetCheckboxSetFlags(snackWidget * s, PyObject * args);
280 static PyObject * widgetCheckboxSetValue(snackWidget * s, PyObject * args);
281 
282 static PyMethodDef widgetMethods[] = {
283     { "setCallback", (PyCFunction) widgetAddCallback, METH_VARARGS, NULL },
284     { "labelSetColors", (PyCFunction) widgetLabelSetColors, METH_VARARGS, NULL },
285     { "labelText", (PyCFunction) widgetLabelText, METH_VARARGS, NULL },
286     { "textboxText", (PyCFunction) widgetTextboxText, METH_VARARGS, NULL },
287     { "textboxHeight", (PyCFunction) widgetTextboxHeight, METH_VARARGS, NULL },
288     { "entrySetValue", (PyCFunction) widgetEntrySetValue, METH_VARARGS, NULL },
289     { "listboxAddItem", (PyCFunction) widgetListboxAdd, METH_VARARGS, NULL },
290     { "listboxInsertItem", (PyCFunction) widgetListboxIns, METH_VARARGS, NULL },
291     { "listboxGetCurrent", (PyCFunction) widgetListboxGet, METH_VARARGS, NULL },
292     { "listboxGetSelection", (PyCFunction) widgetListboxGetSel, METH_VARARGS, NULL },
293     { "listboxSetCurrent", (PyCFunction) widgetListboxSet, METH_VARARGS, NULL },
294     { "listboxSetWidth", (PyCFunction) widgetListboxSetW, METH_VARARGS, NULL },
295     { "listboxDeleteItem", (PyCFunction) widgetListboxDel, METH_VARARGS, NULL },
296     { "listboxClear", (PyCFunction) widgetListboxClear, METH_VARARGS, NULL },
297     { "scaleSet", (PyCFunction) scaleSet, METH_VARARGS, NULL },
298     { "checkboxtreeAddItem", (PyCFunction) widgetCheckboxTreeAddItem,
299       METH_VARARGS, NULL },
300     { "checkboxtreeGetCurrent", (PyCFunction) widgetCheckboxTreeGetCur,
301       METH_VARARGS, NULL },
302     { "checkboxtreeGetEntryValue", (PyCFunction) widgetCheckboxTreeGetEntryValue,
303       METH_VARARGS, NULL },
304     { "checkboxtreeSetEntry", (PyCFunction) widgetCheckboxTreeSetEntry,
305       METH_VARARGS, NULL },
306     { "checkboxtreeSetWidth", (PyCFunction) widgetCheckboxTreeSetWidth, METH_VARARGS, NULL },
307     { "checkboxtreeSetCurrent", (PyCFunction) widgetCheckboxTreeSetCurrent,
308       METH_VARARGS, NULL },
309     { "checkboxtreeSetEntryValue", (PyCFunction) widgetCheckboxTreeSetEntryValue,
310       METH_VARARGS, NULL },
311     { "checkboxtreeGetSelection", (PyCFunction) widgetCheckboxTreeGetSel,
312       METH_VARARGS, NULL },
313     { "entrySetFlags", (PyCFunction) widgetEntrySetFlags, METH_VARARGS, NULL },
314     { "checkboxSetFlags", (PyCFunction) widgetCheckboxSetFlags, METH_VARARGS, NULL },
315     { "checkboxSetValue", (PyCFunction) widgetCheckboxSetValue, METH_VARARGS, NULL },
316     { NULL }
317 };
318 
319 static PyMemberDef widget_members[] = {
320         { "key",
321 #if SIZEOF_VOID_P == SIZEOF_LONG
322 		T_LONG,
323 #elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
324 		T_LONGLONG,
325 #else
326 #error unsupported pointer size
327 #endif
328 		offsetof(snackWidget, co), 0, NULL },
329         { "entryValue", T_STRING, offsetof(snackWidget, apointer), 0, NULL },
330 	{ NULL }
331 };
332 
333 static PyTypeObject snackWidgetType = {
334         PyVarObject_HEAD_INIT(&PyType_Type, 0)
335         "snackwidget",                  /* tp_name */
336         sizeof(snackWidget),            /* tp_size */
337         0,                              /* tp_itemsize */
338         widgetDestructor,      		/* tp_dealloc */
339         0,                              /* tp_print */
340         0,                   		/* tp_getattr */
341         0,                              /* tp_setattr */
342         0,                              /* tp_compare */
343         0,                              /* tp_repr */
344         0,                              /* tp_as_number */
345         0,                              /* tp_as_sequence */
346         0,                		/* tp_as_mapping */
347 	0,                              /* tp_hash */
348 	0,                              /* tp_call */
349 	0,                              /* tp_str */
350 	PyObject_GenericGetAttr,        /* tp_getattro */
351 	0,                              /* tp_setattro */
352 	0,                              /* tp_as_buffer */
353 	Py_TPFLAGS_DEFAULT,             /* tp_flags */
354 	0,                              /* tp_doc */
355 	0,                              /* tp_traverse */
356 	0,                              /* tp_clear */
357 	0,                              /* tp_richcompare */
358 	0,                              /* tp_weaklistoffset */
359 	0,                              /* tp_iter */
360 	0,                              /* tp_iternext */
361 	widgetMethods,                  /* tp_methods */
362 	widget_members,                 /* tp_members */
363 	widget_getset                   /* tp_getset */
364 };
365 
snackWidgetNew(void)366 static snackWidget * snackWidgetNew (void) {
367     snackWidget * widget;
368 
369     widget = PyObject_NEW(snackWidget, &snackWidgetType);
370     if (!widget)
371 	return NULL;
372 
373     widget->scs.cb = NULL;
374     widget->scs.data = NULL;
375 
376     return widget;
377 }
378 
initScreen(PyObject * s,PyObject * args)379 static PyObject * initScreen(PyObject * s, PyObject * args) {
380     suspend.cb = NULL;
381     suspend.data = NULL;
382 
383     newtInit();
384     newtCls();
385 
386     Py_INCREF(Py_None);
387     return Py_None;
388 }
389 
finishScreen(PyObject * s,PyObject * args)390 static PyObject * finishScreen(PyObject * s, PyObject * args) {
391     Py_XDECREF (suspend.cb);
392     Py_XDECREF (suspend.data);
393 
394     newtFinished();
395     Py_INCREF(Py_None);
396     return Py_None;
397 }
398 
refreshScreen(PyObject * s,PyObject * args)399 static PyObject * refreshScreen(PyObject * s, PyObject * args) {
400     newtRefresh();
401     Py_INCREF(Py_None);
402     return Py_None;
403 }
404 
setColor(PyObject * s,PyObject * args)405 static PyObject * setColor(PyObject * s, PyObject * args) {
406     char * fg, * bg;
407     int colorset;
408     if (!PyArg_ParseTuple(args, "iss", &colorset, &fg, &bg))
409 	return NULL;
410 
411     newtSetColor(colorset, fg, bg);
412 
413     Py_INCREF(Py_None);
414     return Py_None;
415 }
416 
scaleWidget(PyObject * s,PyObject * args)417 static PyObject * scaleWidget(PyObject * s, PyObject * args) {
418     snackWidget * widget;
419     int width, fullAmount;
420 
421     if (!PyArg_ParseTuple(args, "ii", &width, &fullAmount)) return NULL;
422 
423     widget = snackWidgetNew ();
424     if (!widget)
425 	return NULL;
426     widget->co = newtScale(-1, -1, width, fullAmount);
427 
428     return (PyObject *) widget;
429 }
430 
scaleSet(snackWidget * s,PyObject * args)431 static PyObject * scaleSet(snackWidget * s, PyObject * args) {
432     int amount;
433 
434     if (!PyArg_ParseTuple(args, "i", &amount)) return NULL;
435 
436     newtScaleSet(s->co, amount);
437 
438     Py_INCREF(Py_None);
439     return Py_None;
440 }
441 
screenSize(PyObject * s,PyObject * args)442 static PyObject * screenSize(PyObject * s, PyObject * args) {
443     int width, height;
444 
445     if (!PyArg_ParseTuple(args, ""))
446 	return NULL;
447 
448     newtGetScreenSize(&width, &height);
449 
450     return Py_BuildValue("(ii)", width, height);
451 }
452 
helpCallbackMarshall(newtComponent co,void * data)453 static void helpCallbackMarshall(newtComponent co, void * data) {
454     PyObject * args, * result;
455 
456     PyGILState_STATE _state = PyGILState_Ensure();
457 
458     args = Py_BuildValue("(O)", data);
459     result = PyEval_CallObject(helpCallback.cb, args);
460     Py_DECREF (args);
461     Py_XDECREF(result);
462 
463     PyGILState_Release(_state);
464 
465     return;
466 }
467 
suspendCallbackMarshall(void * data)468 static void suspendCallbackMarshall(void * data) {
469     struct callbackStruct * scs = data;
470     PyObject * args, * result;
471 
472     PyGILState_STATE _state = PyGILState_Ensure();
473 
474     if (scs->data) {
475 	args = Py_BuildValue("(O)", scs->data);
476 	result = PyEval_CallObject(scs->cb, args);
477 	Py_DECREF (args);
478     } else
479 	result = PyEval_CallObject(scs->cb, NULL);
480 
481     if (!result) {
482 	PyErr_Print();
483 	PyErr_Clear();
484     }
485 
486     Py_XDECREF(result);
487 
488     PyGILState_Release(_state);
489 
490     return;
491 }
492 
callbackMarshall(newtComponent co,void * data)493 static void callbackMarshall(newtComponent co, void * data) {
494     struct callbackStruct * scs = data;
495     PyObject * args, * result;
496 
497     PyGILState_STATE _state = PyGILState_Ensure();
498 
499     if (scs->data) {
500 	args = Py_BuildValue("(O)", scs->data);
501 	result = PyEval_CallObject(scs->cb, args);
502 	Py_DECREF (args);
503     } else
504 	result = PyEval_CallObject(scs->cb, NULL);
505 
506     if (!result) {
507 	PyErr_Print();
508 	PyErr_Clear();
509     }
510 
511     Py_XDECREF(result);
512 
513     PyGILState_Release(_state);
514 
515     return;
516 }
517 
setSuspendCallback(PyObject * s,PyObject * args)518 static PyObject * setSuspendCallback(PyObject * s, PyObject * args) {
519     if (!PyArg_ParseTuple(args, "O|O", &suspend.cb, &suspend.data))
520 	return NULL;
521 
522     Py_INCREF (suspend.cb);
523     Py_XINCREF (suspend.data);
524 
525     newtSetSuspendCallback(suspendCallbackMarshall, &suspend);
526 
527     Py_INCREF(Py_None);
528     return Py_None;
529 }
530 
setHelpCallback(PyObject * s,PyObject * args)531 static PyObject * setHelpCallback(PyObject * s, PyObject * args) {
532     if (!PyArg_ParseTuple(args, "O", &helpCallback.cb))
533 	return NULL;
534 
535     /*if (helpCallback.cb) {
536 	Py_DECREF (helpCallback.cb);
537     }*/
538 
539     Py_INCREF (helpCallback.cb);
540 
541     newtSetHelpCallback(helpCallbackMarshall);
542 
543     Py_INCREF(Py_None);
544     return Py_None;
545 }
546 
drawRootText(PyObject * s,PyObject * args)547 static PyObject * drawRootText(PyObject * s, PyObject * args) {
548     int left, top;
549     char * text;
550 
551     if (!PyArg_ParseTuple(args, "iis", &left, &top, &text))
552 	return NULL;
553 
554     newtDrawRootText(left, top, text);
555 
556     Py_INCREF(Py_None);
557     return Py_None;
558 }
559 
doSuspend(PyObject * s,PyObject * args)560 static PyObject * doSuspend(PyObject * s, PyObject * args) {
561     newtSuspend();
562 
563     Py_INCREF(Py_None);
564     return Py_None;
565 }
566 
doResume(PyObject * s,PyObject * args)567 static PyObject * doResume(PyObject * s, PyObject * args) {
568     newtResume();
569 
570     Py_INCREF(Py_None);
571     return Py_None;
572 }
573 
popHelpLine(PyObject * s,PyObject * args)574 static PyObject * popHelpLine(PyObject * s, PyObject * args) {
575     newtPopHelpLine();
576     Py_INCREF(Py_None);
577     return Py_None;
578 }
579 
pushHelpLine(PyObject * s,PyObject * args)580 static PyObject * pushHelpLine(PyObject * s, PyObject * args) {
581     char * text;
582 
583     if (!PyArg_ParseTuple(args, "s", &text))
584 	return NULL;
585 
586     if (!strcmp(text, "*default*"))
587 	newtPushHelpLine(NULL);
588     else
589 	newtPushHelpLine(text);
590 
591     Py_INCREF(Py_None);
592     return Py_None;
593 }
594 
reflowText(PyObject * s,PyObject * args)595 static PyObject * reflowText(PyObject * s, PyObject * args) {
596     char * text, * new;
597     int width, minus = 5, plus = 5;
598     int realWidth, realHeight;
599     PyObject * tuple;
600 
601     if (!PyArg_ParseTuple(args, "si|ii", &text, &width, &minus, &plus))
602 	return NULL;
603 
604     new = newtReflowText(text, width, minus, plus, &realWidth, &realHeight);
605 
606     tuple = Py_BuildValue("(sii)", new, realWidth, realHeight);
607     free(new);
608 
609     return tuple;
610 }
611 
centeredWindow(PyObject * s,PyObject * args)612 static PyObject * centeredWindow(PyObject * s, PyObject * args) {
613     int width, height;
614     char * title;
615 
616     if (!PyArg_ParseTuple(args, "iis", &width, &height, &title))
617 	return NULL;
618 
619     newtCenteredWindow(width, height, title);
620 
621     Py_INCREF(Py_None);
622     return Py_None;
623 }
624 
gridWrappedWindow(PyObject * s,PyObject * args)625 static PyObject * gridWrappedWindow(PyObject * s, PyObject * args) {
626     snackGrid * grid;
627     char * title;
628     int x = -1, y = -1;
629 
630     if (!PyArg_ParseTuple(args, "O!s|ii", &snackGridType, &grid, &title,
631 			  &x, &y))
632 	return NULL;
633 
634     if (y == -1)
635 	newtGridWrappedWindow(grid->grid, title);
636     else
637 	newtGridWrappedWindowAt(grid->grid, title, x, y);
638 
639     Py_INCREF(Py_None);
640     return Py_None;
641 }
642 
openWindow(PyObject * s,PyObject * args)643 static PyObject * openWindow(PyObject * s, PyObject * args) {
644     int left, top, width, height;
645     char * title;
646 
647     if (!PyArg_ParseTuple(args, "iiiis", &left, &top, &width, &height, &title))
648 	return NULL;
649 
650     newtOpenWindow(left, top, width, height, title);
651 
652     Py_INCREF(Py_None);
653     return Py_None;
654 }
655 
popWindow(PyObject * s,PyObject * args)656 static PyObject * popWindow(PyObject * s, PyObject * args) {
657     newtPopWindow();
658     Py_INCREF(Py_None);
659     return Py_None;
660 }
661 
popWindowNoRefresh(PyObject * s,PyObject * args)662 static PyObject * popWindowNoRefresh(PyObject * s, PyObject * args) {
663     newtPopWindowNoRefresh();
664     Py_INCREF(Py_None);
665     return Py_None;
666 }
667 
messageWindow(PyObject * s,PyObject * args)668 static PyObject * messageWindow(PyObject * s, PyObject * args) {
669     char * title, * text;
670     char * okbutton = "Ok";
671 
672     if (!PyArg_ParseTuple(args, "ss|s", &title, &text, &okbutton))
673 	return NULL;
674 
675     Py_BEGIN_ALLOW_THREADS
676     newtWinMessage(title, okbutton, text);
677     Py_END_ALLOW_THREADS
678 
679     Py_INCREF(Py_None);
680     return Py_None;
681 }
682 
choiceWindow(PyObject * s,PyObject * args)683 static PyObject * choiceWindow(PyObject * s, PyObject * args) {
684     char * title, * text;
685     char * okbutton = "Ok";
686     char * cancelbutton = "Cancel";
687     int rc;
688 
689     if (!PyArg_ParseTuple(args, "ss|ss", &title, &text, &okbutton,
690 			  &cancelbutton))
691 	return NULL;
692 
693     Py_BEGIN_ALLOW_THREADS
694     rc = newtWinChoice(title, okbutton, cancelbutton, text);
695     Py_END_ALLOW_THREADS
696 
697     return Py_BuildValue("i", rc);
698 }
699 
ternaryWindow(PyObject * s,PyObject * args)700 static PyObject * ternaryWindow(PyObject * s, PyObject * args) {
701     char * title, * text, * button1, * button2, * button3;
702     int rc;
703 
704     if (!PyArg_ParseTuple(args, "sssss", &title, &text, &button1, &button2,
705 			  &button3))
706 	return NULL;
707 
708     Py_BEGIN_ALLOW_THREADS
709     rc = newtWinTernary(title, button1, button2, button3, text);
710     Py_END_ALLOW_THREADS
711 
712     return Py_BuildValue("i", rc);
713 }
714 
buttonWidget(PyObject * s,PyObject * args)715 static snackWidget * buttonWidget(PyObject * s, PyObject * args) {
716     snackWidget * widget;
717     char * label;
718 
719     if (!PyArg_ParseTuple(args, "s", &label)) return NULL;
720 
721     widget = snackWidgetNew ();
722     if (!widget)
723 	return NULL;
724     widget->co = newtButton(-1, -1, label);
725 
726     return widget;
727 }
728 
compactbuttonWidget(PyObject * s,PyObject * args)729 static snackWidget * compactbuttonWidget(PyObject * s, PyObject * args) {
730     snackWidget * widget;
731     char * label;
732 
733     if (!PyArg_ParseTuple(args, "s", &label)) return NULL;
734 
735     widget = snackWidgetNew ();
736     if (!widget)
737 	return NULL;
738     widget->co = newtCompactButton(-1, -1, label);
739 
740     return widget;
741 }
742 
labelWidget(PyObject * s,PyObject * args)743 static snackWidget * labelWidget(PyObject * s, PyObject * args) {
744     char * label;
745     snackWidget * widget;
746 
747     if (!PyArg_ParseTuple(args, "s", &label)) return NULL;
748 
749     widget = snackWidgetNew ();
750     if (!widget)
751 	return NULL;
752     widget->co = newtLabel(-1, -1, label);
753 
754     return widget;
755 }
756 
widgetLabelText(snackWidget * s,PyObject * args)757 static PyObject * widgetLabelText(snackWidget * s, PyObject * args) {
758     char * label;
759 
760     if (!PyArg_ParseTuple(args, "s", &label)) return NULL;
761 
762     newtLabelSetText(s->co, label);
763 
764     Py_INCREF(Py_None);
765     return Py_None;
766 }
767 
widgetLabelSetColors(snackWidget * s,PyObject * args)768 static PyObject * widgetLabelSetColors(snackWidget * s, PyObject * args) {
769     int colorset;
770 
771     if (!PyArg_ParseTuple(args, "i", &colorset)) return NULL;
772 
773     newtLabelSetColors(s->co, colorset);
774 
775     Py_INCREF(Py_None);
776     return Py_None;
777 }
778 
widgetTextboxText(snackWidget * s,PyObject * args)779 static PyObject * widgetTextboxText(snackWidget * s, PyObject * args) {
780     char * text;
781 
782     if (!PyArg_ParseTuple(args, "s", &text)) return NULL;
783 
784     newtTextboxSetText(s->co, text);
785 
786     Py_INCREF(Py_None);
787     return Py_None;
788 }
789 
widgetTextboxHeight(snackWidget * s,PyObject * args)790 static PyObject * widgetTextboxHeight(snackWidget * s, PyObject * args) {
791     int height;
792 
793     if (!PyArg_ParseTuple(args, "i", &height)) return NULL;
794 
795     newtTextboxSetHeight(s->co, height);
796 
797     Py_INCREF(Py_None);
798     return Py_None;
799 }
800 
listboxWidget(PyObject * s,PyObject * args)801 static snackWidget * listboxWidget(PyObject * s, PyObject * args) {
802     snackWidget * widget;
803     int height;
804     int doScroll = 0, returnExit = 0, showCursor = 0, multiple = 0, border = 0;
805 
806     if (!PyArg_ParseTuple(args, "i|iiiii", &height, &doScroll, &returnExit,
807 					   &showCursor, &multiple, &border))
808 	return NULL;
809 
810     widget = snackWidgetNew ();
811     if (!widget)
812 	return NULL;
813     widget->co = newtListbox(-1, -1, height,
814 			     (doScroll ? NEWT_FLAG_SCROLL : 0) |
815 			     (returnExit ? NEWT_FLAG_RETURNEXIT : 0) |
816 			     (showCursor ? NEWT_FLAG_SHOWCURSOR : 0) |
817 			     (multiple ? NEWT_FLAG_MULTIPLE : 0) |
818 			     (border ? NEWT_FLAG_BORDER : 0)
819 			     );
820     widget->anint = 1;
821 
822     return widget;
823 }
824 
textWidget(PyObject * s,PyObject * args)825 static snackWidget * textWidget(PyObject * s, PyObject * args) {
826     char * text;
827     int width, height;
828     int scrollBar = 0;
829     int wrap = 0;
830     snackWidget * widget;
831 
832     if (!PyArg_ParseTuple(args, "iis|ii", &width, &height, &text, &scrollBar, &wrap))
833 	return NULL;
834 
835     widget = snackWidgetNew ();
836     if (!widget)
837 	return NULL;
838     widget->co = newtTextbox(-1, -1, width, height,
839 				(scrollBar ? NEWT_FLAG_SCROLL : 0) |
840  			        (wrap ? NEWT_FLAG_WRAP : 0));
841     newtTextboxSetText(widget->co, text);
842 
843     return widget;
844 }
845 
radioButtonWidget(PyObject * s,PyObject * args)846 static snackWidget * radioButtonWidget(PyObject * s, PyObject * args) {
847     snackWidget * widget, * group;
848     char * text;
849     int isOn;
850 
851     if (!PyArg_ParseTuple(args, "sOi", &text, &group, &isOn))
852 		return NULL;
853 
854     widget = snackWidgetNew ();
855     if (!widget)
856 	return NULL;
857 
858     if ((PyObject *) group == Py_None)
859 	widget->co = newtRadiobutton(-1, -1, text, isOn, NULL);
860     else
861 	widget->co = newtRadiobutton(-1, -1, text, isOn, group->co);
862 
863     return widget;
864 }
865 
checkboxWidget(PyObject * s,PyObject * args)866 static snackWidget * checkboxWidget(PyObject * s, PyObject * args) {
867     snackWidget * widget;
868     char * text;
869     int isOn;
870 
871     if (!PyArg_ParseTuple(args, "si", &text, &isOn)) return NULL;
872 
873     widget = snackWidgetNew ();
874     if (!widget)
875 	return NULL;
876     widget->co = newtCheckbox(-1, -1, text, isOn ? '*' : ' ', NULL,
877 				&widget->achar);
878 
879     return widget;
880 }
881 
widgetCheckboxSetFlags(snackWidget * s,PyObject * args)882 static PyObject * widgetCheckboxSetFlags(snackWidget * s, PyObject * args) {
883     int flag, sense;
884 
885     if (!PyArg_ParseTuple(args, "ii", &flag, &sense)) return NULL;
886 
887     newtCheckboxSetFlags(s->co, flag, sense);
888 
889     Py_INCREF(Py_None);
890     return Py_None;
891 }
892 
widgetCheckboxSetValue(snackWidget * s,PyObject * args)893 static PyObject * widgetCheckboxSetValue(snackWidget * s, PyObject * args) {
894     char *value;
895 
896     if (!PyArg_ParseTuple(args, "s", &value)) return NULL;
897 
898     newtCheckboxSetValue(s->co, *value);
899 
900     Py_INCREF(Py_None);
901     return Py_None;
902 }
903 
entryWidget(PyObject * s,PyObject * args)904 static snackWidget * entryWidget(PyObject * s, PyObject * args) {
905     snackWidget * widget;
906     int width;
907     char * initial;
908     int isHidden, isScrolled, returnExit, isPassword;
909 
910     if (!PyArg_ParseTuple(args, "isiiii", &width, &initial,
911 			  &isHidden, &isPassword, &isScrolled, &returnExit)) return NULL;
912 
913     widget = snackWidgetNew ();
914     if (!widget)
915 	return NULL;
916     widget->co = newtEntry(-1, -1, initial, width,
917                            (const char **) &widget->apointer,
918 			   (isHidden ? NEWT_FLAG_HIDDEN : 0) |
919 			   (isPassword ? NEWT_FLAG_PASSWORD : 0) |
920 			   (returnExit ? NEWT_FLAG_RETURNEXIT : 0) |
921 			   (isScrolled ? NEWT_FLAG_SCROLL : 0));
922 
923     return widget;
924 }
925 
formCreate(PyObject * s,PyObject * args)926 static snackForm * formCreate(PyObject * s, PyObject * args) {
927     snackForm * form;
928     PyObject * help = Py_None;
929 
930     if (!PyArg_ParseTuple(args, "|O", &help)) return NULL;
931 
932     if (help == Py_None)
933 	help = NULL;
934 
935     form = PyObject_NEW(snackForm, &snackFormType);
936     form->fo = newtForm(NULL, help, 0);
937 
938     return form;
939 }
940 
gridCreate(PyObject * s,PyObject * args)941 static snackGrid * gridCreate(PyObject * s, PyObject * args) {
942     int rows, cols;
943     snackGrid * grid;
944 
945     if (!PyArg_ParseTuple(args, "ii", &cols, &rows)) return NULL;
946 
947     grid = PyObject_NEW(snackGrid, &snackGridType);
948     grid->grid = newtCreateGrid(cols, rows);
949 
950     return grid;
951 }
952 
gridPlace(snackGrid * grid,PyObject * args)953 static PyObject * gridPlace(snackGrid * grid, PyObject * args) {
954     int x, y;
955 
956     if (!PyArg_ParseTuple(args, "ii", &x, &y)) return NULL;
957 
958     newtGridPlace(grid->grid, x, y);
959 
960     Py_INCREF(Py_None);
961     return Py_None;
962 }
963 
gridSetField(snackGrid * grid,PyObject * args)964 static PyObject * gridSetField(snackGrid * grid, PyObject * args) {
965     snackWidget * w;
966     snackGrid * g;
967     int x, y;
968     int pLeft = 0, pTop = 0, pRight = 0, pBottom = 0;
969     int anchorFlags = 0, growFlags = 0;
970 
971     if (!PyArg_ParseTuple(args, "iiO|(iiii)ii", &x, &y,
972 				&w, &pLeft, &pTop, &pRight, &pBottom,
973 				&anchorFlags, &growFlags))
974 	return NULL;
975 
976     if (Py_TYPE(w) == &snackWidgetType) {
977 	newtGridSetField(grid->grid, x, y, NEWT_GRID_COMPONENT,
978 			 w->co, pLeft, pTop, pRight, pBottom, anchorFlags,
979 			 growFlags);
980     } else {
981 	g = (snackGrid *) w;
982 	newtGridSetField(grid->grid, x, y, NEWT_GRID_SUBGRID,
983 			 g->grid, pLeft, pTop, pRight, pBottom, anchorFlags,
984 			 growFlags);
985     }
986 
987     Py_INCREF(Py_None);
988     return Py_None;
989 }
990 
formDraw(snackForm * s,PyObject * args)991 static PyObject * formDraw(snackForm * s, PyObject * args) {
992     newtDrawForm(s->fo);
993 
994     Py_INCREF(Py_None);
995     return Py_None;
996 }
997 
formAdd(snackForm * s,PyObject * args)998 static PyObject * formAdd(snackForm * s, PyObject * args) {
999     snackWidget * w;
1000     int size = PyTuple_Size(args), i;
1001 
1002     if (!size) {
1003 	/* this is a hack, I should give an error directly */
1004 	if (!PyArg_ParseTuple(args, "O!", &snackWidgetType, &w))
1005 	    return NULL;
1006     }
1007 
1008     for (i = 0; i < size; i++) {
1009 	w = (snackWidget *) PyTuple_GET_ITEM(args, i);
1010 	newtFormAddComponent(s->fo, w->co);
1011     }
1012 
1013     Py_INCREF(Py_None);
1014     return Py_None;
1015 }
1016 
formRun(snackForm * s,PyObject * args)1017 static PyObject * formRun(snackForm * s, PyObject * args) {
1018     struct newtExitStruct result;
1019 
1020     Py_BEGIN_ALLOW_THREADS
1021     newtFormRun(s->fo, &result);
1022     Py_END_ALLOW_THREADS
1023 
1024     if (result.reason == NEWT_EXIT_HOTKEY)
1025 	return Py_BuildValue("(si)", "hotkey", result.u.key);
1026     else if (result.reason == NEWT_EXIT_TIMER)
1027 	return Py_BuildValue("(si)", "timer", 0);
1028     else if (result.reason == NEWT_EXIT_FDREADY)
1029 	return Py_BuildValue("(si)", "fdready", result.u.watch);
1030     else if (result.reason == NEWT_EXIT_COMPONENT)
1031 #if SIZEOF_VOID_P <= SIZEOF_LONG
1032 	return Py_BuildValue("(sl)", "widget", (long)result.u.co);
1033 #else
1034 	return Py_BuildValue("(sL)", "widget", (long long)result.u.co);
1035 #endif
1036     else
1037 	return Py_BuildValue("(si)", "error", 0);
1038 }
1039 
formHotKey(snackForm * s,PyObject * args)1040 static PyObject * formHotKey(snackForm * s, PyObject * args) {
1041     int key;
1042 
1043     if (!PyArg_ParseTuple(args, "i", &key))
1044 	return NULL;
1045 
1046     newtFormAddHotKey(s->fo, key);
1047 
1048     Py_INCREF(Py_None);
1049     return Py_None;
1050 }
1051 
formSetTimer(snackForm * form,PyObject * args)1052 static PyObject * formSetTimer(snackForm * form, PyObject * args) {
1053     int millisecs;
1054 
1055     if (!PyArg_ParseTuple(args, "i", &millisecs))
1056 	return NULL;
1057 
1058     newtFormSetTimer(form->fo, millisecs);
1059 
1060     Py_INCREF(Py_None);
1061     return Py_None;
1062 }
1063 
formWatchFD(snackForm * form,PyObject * args)1064 static PyObject * formWatchFD(snackForm * form, PyObject * args) {
1065     int fd, fdflags;
1066 
1067     if (!PyArg_ParseTuple(args, "ii", &fd, &fdflags))
1068 	return NULL;
1069 
1070     newtFormWatchFd(form->fo, fd, fdflags);
1071 
1072     Py_INCREF(Py_None);
1073     return Py_None;
1074 }
1075 
formSetCurrent(snackForm * form,PyObject * args)1076 static PyObject * formSetCurrent(snackForm * form, PyObject * args) {
1077     snackWidget * w;
1078 
1079     if (!PyArg_ParseTuple(args, "O", &w))
1080 	return NULL;
1081 
1082     newtFormSetCurrent(form->fo, w->co);
1083 
1084     Py_INCREF(Py_None);
1085     return Py_None;
1086 }
1087 
widget_get_checkboxValue(PyObject * self,void * closure)1088 static PyObject * widget_get_checkboxValue(PyObject *self, void *closure)
1089 {
1090 	snackWidget *w = (snackWidget *)self;
1091 
1092 	return Py_BuildValue("i", w->achar == ' ' ? 0 : 1);
1093 }
1094 
widget_get_radioValue(PyObject * self,void * closure)1095 static PyObject * widget_get_radioValue(PyObject *self, void *closure)
1096 {
1097 	snackWidget *w = (snackWidget *)self;
1098 
1099 #if SIZEOF_VOID_P <= SIZEOF_LONG
1100 	return Py_BuildValue("l", (long)newtRadioGetCurrent(w->co));
1101 #else
1102 	return Py_BuildValue("L", (long long)newtRadioGetCurrent(w->co));
1103 #endif
1104 }
1105 
widgetDestructor(PyObject * o)1106 static void widgetDestructor(PyObject * o) {
1107     snackWidget * s = (snackWidget *) o;
1108 
1109     Py_XDECREF (s->scs.cb);
1110     Py_XDECREF (s->scs.data);
1111 
1112     PyObject_Free(o);
1113 }
1114 
widgetAddCallback(snackWidget * s,PyObject * args)1115 static PyObject * widgetAddCallback(snackWidget * s, PyObject * args) {
1116     s->scs.cb = NULL;
1117     s->scs.data = NULL;
1118 
1119     if (!PyArg_ParseTuple(args, "O|O", &s->scs.cb, &s->scs.data))
1120 	return NULL;
1121 
1122     Py_INCREF (s->scs.cb);
1123     Py_XINCREF (s->scs.data);
1124 
1125     newtComponentAddCallback(s->co, callbackMarshall, &s->scs);
1126 
1127     Py_INCREF(Py_None);
1128     return Py_None;
1129 }
1130 
widgetEntrySetValue(snackWidget * s,PyObject * args)1131 static PyObject * widgetEntrySetValue(snackWidget * s, PyObject * args) {
1132     char * val;
1133     int cursorAtEnd = 1;
1134 
1135     if (!PyArg_ParseTuple(args, "s|i", &val, &cursorAtEnd))
1136 	return NULL;
1137 
1138     newtEntrySet(s->co, val, cursorAtEnd);
1139 
1140     Py_INCREF(Py_None);
1141     return Py_None;
1142 }
1143 
widgetEntrySetFlags(snackWidget * s,PyObject * args)1144 static PyObject * widgetEntrySetFlags(snackWidget * s, PyObject * args) {
1145     int flag, sense;
1146 
1147     if (!PyArg_ParseTuple(args, "ii", &flag, &sense)) return NULL;
1148 
1149     newtEntrySetFlags(s->co, flag, sense);
1150 
1151     Py_INCREF(Py_None);
1152     return Py_None;
1153 }
1154 
1155 
widgetListboxAdd(snackWidget * s,PyObject * args)1156 static PyObject * widgetListboxAdd(snackWidget * s, PyObject * args) {
1157     char * text;
1158 
1159     if (!PyArg_ParseTuple(args, "s", &text))
1160 	return NULL;
1161 
1162     newtListboxAddEntry(s->co, text, I2P(s->anint));
1163 
1164     return PyInt_FromLong(s->anint++);
1165 }
1166 
widgetListboxIns(snackWidget * s,PyObject * args)1167 static PyObject * widgetListboxIns(snackWidget * s, PyObject * args) {
1168     char * text;
1169     int key;
1170 
1171     if (!PyArg_ParseTuple(args, "si", &text, &key))
1172 	return NULL;
1173 
1174     newtListboxInsertEntry(s->co, text, I2P(s->anint), I2P(key));
1175 
1176     return PyInt_FromLong(s->anint++);
1177 }
1178 
widgetListboxDel(snackWidget * s,PyObject * args)1179 static PyObject * widgetListboxDel(snackWidget * s, PyObject * args) {
1180     int key;
1181 
1182     if (!PyArg_ParseTuple(args, "i", &key))
1183 	return NULL;
1184 
1185     newtListboxDeleteEntry(s->co, I2P(key));
1186 
1187     Py_INCREF(Py_None);
1188     return Py_None;
1189 }
1190 
widgetListboxGet(snackWidget * s,PyObject * args)1191 static PyObject * widgetListboxGet(snackWidget * s, PyObject * args) {
1192     if (!PyArg_ParseTuple(args, ""))
1193 	return NULL;
1194 
1195     return PyInt_FromLong((long) newtListboxGetCurrent(s->co));
1196 }
1197 
widgetListboxGetSel(snackWidget * s,PyObject * args)1198 static PyObject * widgetListboxGetSel(snackWidget * s, PyObject * args) {
1199     void ** selection;
1200     int numselected;
1201     int i;
1202     PyObject * sel, * int_obj;
1203 
1204     if (!PyArg_ParseTuple(args, ""))
1205         return NULL;
1206 
1207     selection = (void **) newtListboxGetSelection(s->co, &numselected);
1208 
1209     sel = PyList_New(0);
1210 
1211     if (!selection) {
1212 	return sel;
1213     }
1214 
1215     for (i = 0; i < numselected; i++) {
1216 	int_obj = PyInt_FromLong((long) selection[i]);
1217 	PyList_Append(sel, int_obj);
1218 	Py_DECREF(int_obj);
1219     }
1220     free(selection);
1221 
1222     return sel;
1223 }
1224 
widgetListboxSet(snackWidget * s,PyObject * args)1225 static PyObject * widgetListboxSet(snackWidget * s, PyObject * args) {
1226     int index;
1227 
1228     if (!PyArg_ParseTuple(args, "i", &index))
1229 	return NULL;
1230 
1231     newtListboxSetCurrentByKey(s->co, I2P(index));
1232 
1233     Py_INCREF(Py_None);
1234     return Py_None;
1235 }
1236 
widgetListboxSetW(snackWidget * s,PyObject * args)1237 static PyObject * widgetListboxSetW(snackWidget * s, PyObject * args) {
1238     int width;
1239 
1240     if (!PyArg_ParseTuple(args, "i", &width))
1241 	return NULL;
1242 
1243     newtListboxSetWidth(s->co, width);
1244 
1245     Py_INCREF(Py_None);
1246     return Py_None;
1247 }
1248 
widgetListboxClear(snackWidget * s,PyObject * args)1249 static PyObject * widgetListboxClear(snackWidget * s, PyObject * args) {
1250   if (!PyArg_ParseTuple(args, ""))
1251     return NULL;
1252 
1253   newtListboxClear(s->co);
1254 
1255   Py_INCREF(Py_None);
1256   return Py_None;
1257 }
1258 
emptyDestructor(PyObject * s)1259 static void emptyDestructor(PyObject * s) {
1260 }
1261 
checkboxTreeWidget(PyObject * s,PyObject * args,PyObject * kwargs)1262 static snackWidget * checkboxTreeWidget(PyObject * s, PyObject * args, PyObject * kwargs) {
1263     int height;
1264     int scrollBar = 0;
1265     int hide_checkbox = 0;
1266     int unselectable = 0;
1267     int flags;
1268     snackWidget * widget;
1269     const char *kw[] = {"height", "scrollbar", "hide_checkbox", "unselectable", NULL};
1270 
1271     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii", (char **) kw,
1272 		&height, &scrollBar, &hide_checkbox, &unselectable))
1273 	return NULL;
1274 
1275     flags = (scrollBar ? NEWT_FLAG_SCROLL : 0) |
1276 	(hide_checkbox ? NEWT_CHECKBOXTREE_HIDE_BOX : 0) |
1277 	(unselectable ? NEWT_CHECKBOXTREE_UNSELECTABLE : 0);
1278 
1279     widget = snackWidgetNew ();
1280     if (!widget)
1281 	return NULL;
1282     widget->co = newtCheckboxTree(-1, -1, height, flags);
1283 
1284     widget->anint = 1;
1285 
1286     return widget;
1287 }
1288 
widgetCheckboxTreeAddItem(snackWidget * s,PyObject * args)1289 static PyObject * widgetCheckboxTreeAddItem(snackWidget * s, PyObject * args) {
1290     char * text;
1291     int selected = 0;
1292     PyObject * pathList, * o;
1293     int len;
1294     int * path;
1295     int i;
1296 
1297     if (!PyArg_ParseTuple(args, "sOi", &text, &pathList, &selected))
1298 	return NULL;
1299 
1300     len = PyTuple_Size(pathList);
1301     path = alloca(sizeof(*path) * (len + 1));
1302     for (i = 0; i < len; i++) {
1303         o = PyTuple_GetItem(pathList, i);
1304 	path[i] = PyInt_AsLong(o);
1305     }
1306     path[len] = NEWT_ARG_LAST;
1307 
1308     newtCheckboxTreeAddArray(s->co, text, I2P(s->anint),
1309     			     selected ? NEWT_FLAG_SELECTED : 0, path);
1310 
1311     return PyInt_FromLong(s->anint++);
1312 }
1313 
widgetCheckboxTreeGetCur(snackWidget * s,PyObject * args)1314 static PyObject * widgetCheckboxTreeGetCur(snackWidget * s, PyObject * args) {
1315     if (!PyArg_ParseTuple(args, ""))
1316 	return NULL;
1317 
1318     return PyInt_FromLong((long)newtCheckboxTreeGetCurrent(s->co));
1319 }
1320 
widgetCheckboxTreeSetEntry(snackWidget * s,PyObject * args)1321 static PyObject * widgetCheckboxTreeSetEntry(snackWidget * s, PyObject * args) {
1322     int data;
1323     char *text;
1324 
1325     if (!PyArg_ParseTuple(args, "is", &data, &text)) return NULL;
1326 
1327     newtCheckboxTreeSetEntry(s->co, I2P(data), text);
1328 
1329     Py_INCREF(Py_None);
1330     return Py_None;
1331 }
1332 
widgetCheckboxTreeSetWidth(snackWidget * s,PyObject * args)1333 static PyObject * widgetCheckboxTreeSetWidth(snackWidget * s, PyObject * args) {
1334     int width;
1335 
1336     if (!PyArg_ParseTuple(args, "i", &width))
1337 	return NULL;
1338 
1339     newtCheckboxTreeSetWidth(s->co, width);
1340 
1341     Py_INCREF(Py_None);
1342     return Py_None;
1343 }
1344 
widgetCheckboxTreeSetCurrent(snackWidget * s,PyObject * args)1345 static PyObject * widgetCheckboxTreeSetCurrent(snackWidget * s, PyObject * args) {
1346     int data;
1347 
1348     if (!PyArg_ParseTuple(args, "i", &data)) return NULL;
1349 
1350     newtCheckboxTreeSetCurrent(s->co, I2P(data));
1351 
1352     Py_INCREF(Py_None);
1353     return Py_None;
1354 }
1355 
widgetCheckboxTreeSetEntryValue(snackWidget * s,PyObject * args)1356 static PyObject * widgetCheckboxTreeSetEntryValue(snackWidget * s, PyObject * args) {
1357     int data;
1358     int isOn = 1;
1359 
1360     if (!PyArg_ParseTuple(args, "i|i", &data, &isOn)) return NULL;
1361 
1362     newtCheckboxTreeSetEntryValue(s->co, I2P(data),
1363 				  isOn ? NEWT_CHECKBOXTREE_SELECTED :
1364 					 NEWT_CHECKBOXTREE_UNSELECTED);
1365 
1366     Py_INCREF(Py_None);
1367     return Py_None;
1368 }
1369 
widgetCheckboxTreeGetEntryValue(snackWidget * s,PyObject * args)1370 static PyObject * widgetCheckboxTreeGetEntryValue(snackWidget * s, PyObject * args) {
1371     int data;
1372     int isOn = 0;
1373     int isBranch = 0;
1374     char selection;
1375 
1376     if (!PyArg_ParseTuple(args, "i", &data)) return NULL;
1377 
1378     selection = newtCheckboxTreeGetEntryValue(s->co, I2P(data));
1379 
1380     if (selection == -1) {
1381 	PyErr_SetString(PyExc_KeyError, "unknown entry");
1382 	return NULL;
1383     }
1384 
1385     switch (selection) {
1386     case NEWT_CHECKBOXTREE_EXPANDED:
1387 	isOn = 1;
1388     case NEWT_CHECKBOXTREE_COLLAPSED:
1389 	isBranch = 1;
1390 	break;
1391     case NEWT_CHECKBOXTREE_UNSELECTED:
1392 	break;
1393     default:
1394 	isOn = 1;
1395 	break;
1396     }
1397     return Py_BuildValue("(ii)", isBranch, isOn);
1398 }
1399 
widgetCheckboxTreeGetSel(snackWidget * s,PyObject * args)1400 static PyObject * widgetCheckboxTreeGetSel(snackWidget * s,
1401 					      PyObject * args) {
1402     void ** selection;
1403     int numselected;
1404     int i;
1405     PyObject * sel, * int_obj;
1406 
1407     if (!PyArg_ParseTuple(args, ""))
1408 	return NULL;
1409 
1410     selection = (void **) newtCheckboxTreeGetSelection(s->co, &numselected);
1411 
1412     sel = PyList_New(0);
1413 
1414     if (!selection) {
1415 	return sel;
1416     }
1417 
1418     for (i = 0; i < numselected; i++) {
1419 	int_obj = PyInt_FromLong((long) selection[i]);
1420 	PyList_Append(sel, int_obj);
1421 	Py_DECREF(int_obj);
1422     }
1423     free(selection);
1424 
1425     return sel;
1426 }
1427 
pywstrlen(PyObject * s,PyObject * args)1428 static PyObject * pywstrlen(PyObject * s, PyObject * args)
1429 {
1430     char *str;
1431     int len = -1;
1432 
1433     if (!PyArg_ParseTuple(args, "s|i", &str, &len)) return NULL;
1434 
1435     return PyInt_FromLong(wstrlen(str, len));
1436 }
1437 
setitemstring_decref(PyObject * dict,const char * s,PyObject * o)1438 static void setitemstring_decref(PyObject * dict,
1439 				const char * s, PyObject * o)
1440 {
1441     PyDict_SetItemString(dict, s, o);
1442     Py_DECREF(o);
1443 }
1444 
MOD_INIT(_snack)1445 MOD_INIT(_snack)
1446 {
1447     PyObject * d, * m;
1448 
1449 #if PY_MAJOR_VERSION >= 3
1450     m = PyModule_Create(&moduledef);
1451 #else
1452     m = Py_InitModule("_snack", snackModuleMethods);
1453 #endif
1454 
1455     if (!m)
1456 	    return MOD_ERROR_VAL;
1457 
1458     d = PyModule_GetDict(m);
1459 
1460     setitemstring_decref(d, "ANCHOR_LEFT", PyInt_FromLong(NEWT_ANCHOR_LEFT));
1461     setitemstring_decref(d, "ANCHOR_TOP", PyInt_FromLong(NEWT_ANCHOR_TOP));
1462     setitemstring_decref(d, "ANCHOR_RIGHT", PyInt_FromLong(NEWT_ANCHOR_RIGHT));
1463     setitemstring_decref(d, "ANCHOR_BOTTOM",
1464 			 PyInt_FromLong(NEWT_ANCHOR_BOTTOM));
1465     setitemstring_decref(d, "GRID_GROWX", PyInt_FromLong(NEWT_GRID_FLAG_GROWX));
1466     setitemstring_decref(d, "GRID_GROWY", PyInt_FromLong(NEWT_GRID_FLAG_GROWY));
1467 
1468     setitemstring_decref(d, "FD_READ", PyInt_FromLong(NEWT_FD_READ));
1469     setitemstring_decref(d, "FD_WRITE", PyInt_FromLong(NEWT_FD_WRITE));
1470     setitemstring_decref(d, "FD_EXCEPT", PyInt_FromLong(NEWT_FD_EXCEPT));
1471 
1472     setitemstring_decref(d, "FORM_EXIT_HOTKEY", PyString_FromString("hotkey"));
1473     setitemstring_decref(d, "FORM_EXIT_WIDGET", PyString_FromString("widget"));
1474     setitemstring_decref(d, "FORM_EXIT_TIMER", PyString_FromString("timer"));
1475     setitemstring_decref(d, "FORM_EXIT_FDREADY", PyString_FromString("fdready"));
1476     setitemstring_decref(d, "FORM_EXIT_ERROR", PyString_FromString("error"));
1477 
1478     setitemstring_decref(d, "KEY_TAB", PyInt_FromLong(NEWT_KEY_TAB));
1479     setitemstring_decref(d, "KEY_ENTER", PyInt_FromLong(NEWT_KEY_ENTER));
1480     setitemstring_decref(d, "KEY_SUSPEND", PyInt_FromLong(NEWT_KEY_SUSPEND));
1481     setitemstring_decref(d, "KEY_UP", PyInt_FromLong(NEWT_KEY_UP));
1482     setitemstring_decref(d, "KEY_DOWN", PyInt_FromLong(NEWT_KEY_DOWN));
1483     setitemstring_decref(d, "KEY_LEFT", PyInt_FromLong(NEWT_KEY_LEFT));
1484     setitemstring_decref(d, "KEY_RIGHT", PyInt_FromLong(NEWT_KEY_RIGHT));
1485     setitemstring_decref(d, "KEY_BACKSPACE", PyInt_FromLong(NEWT_KEY_BKSPC));
1486     setitemstring_decref(d, "KEY_DELETE", PyInt_FromLong(NEWT_KEY_DELETE));
1487     setitemstring_decref(d, "KEY_HOME", PyInt_FromLong(NEWT_KEY_HOME));
1488     setitemstring_decref(d, "KEY_END", PyInt_FromLong(NEWT_KEY_END));
1489     setitemstring_decref(d, "KEY_UNTAB", PyInt_FromLong(NEWT_KEY_UNTAB));
1490     setitemstring_decref(d, "KEY_PAGEUP", PyInt_FromLong(NEWT_KEY_PGUP));
1491     setitemstring_decref(d, "KEY_PAGEGDOWN", PyInt_FromLong(NEWT_KEY_PGDN));
1492     setitemstring_decref(d, "KEY_INSERT", PyInt_FromLong(NEWT_KEY_INSERT));
1493     setitemstring_decref(d, "KEY_F1", PyInt_FromLong(NEWT_KEY_F1));
1494     setitemstring_decref(d, "KEY_F2", PyInt_FromLong(NEWT_KEY_F2));
1495     setitemstring_decref(d, "KEY_F3", PyInt_FromLong(NEWT_KEY_F3));
1496     setitemstring_decref(d, "KEY_F4", PyInt_FromLong(NEWT_KEY_F4));
1497     setitemstring_decref(d, "KEY_F5", PyInt_FromLong(NEWT_KEY_F5));
1498     setitemstring_decref(d, "KEY_F6", PyInt_FromLong(NEWT_KEY_F6));
1499     setitemstring_decref(d, "KEY_F7", PyInt_FromLong(NEWT_KEY_F7));
1500     setitemstring_decref(d, "KEY_F8", PyInt_FromLong(NEWT_KEY_F8));
1501     setitemstring_decref(d, "KEY_F9", PyInt_FromLong(NEWT_KEY_F9));
1502     setitemstring_decref(d, "KEY_F10", PyInt_FromLong(NEWT_KEY_F10));
1503     setitemstring_decref(d, "KEY_F11", PyInt_FromLong(NEWT_KEY_F11));
1504     setitemstring_decref(d, "KEY_F12", PyInt_FromLong(NEWT_KEY_F12));
1505     setitemstring_decref(d, "KEY_ESC", PyInt_FromLong(NEWT_KEY_ESCAPE));
1506     setitemstring_decref(d, "KEY_RESIZE", PyInt_FromLong(NEWT_KEY_RESIZE));
1507 
1508     setitemstring_decref(d, "FLAG_DISABLED", PyInt_FromLong(NEWT_FLAG_DISABLED));
1509     setitemstring_decref(d, "FLAGS_SET", PyInt_FromLong(NEWT_FLAGS_SET));
1510     setitemstring_decref(d, "FLAGS_RESET", PyInt_FromLong(NEWT_FLAGS_RESET));
1511     setitemstring_decref(d, "FLAGS_TOGGLE", PyInt_FromLong(NEWT_FLAGS_TOGGLE));
1512 
1513     setitemstring_decref(d, "COLORSET_ROOT", PyInt_FromLong(NEWT_COLORSET_ROOT));
1514     setitemstring_decref(d, "COLORSET_BORDER", PyInt_FromLong(NEWT_COLORSET_BORDER));
1515     setitemstring_decref(d, "COLORSET_WINDOW", PyInt_FromLong(NEWT_COLORSET_WINDOW));
1516     setitemstring_decref(d, "COLORSET_SHADOW", PyInt_FromLong(NEWT_COLORSET_SHADOW));
1517     setitemstring_decref(d, "COLORSET_TITLE", PyInt_FromLong(NEWT_COLORSET_TITLE));
1518     setitemstring_decref(d, "COLORSET_BUTTON", PyInt_FromLong(NEWT_COLORSET_BUTTON));
1519     setitemstring_decref(d, "COLORSET_ACTBUTTON", PyInt_FromLong(NEWT_COLORSET_ACTBUTTON));
1520     setitemstring_decref(d, "COLORSET_CHECKBOX", PyInt_FromLong(NEWT_COLORSET_CHECKBOX));
1521     setitemstring_decref(d, "COLORSET_ACTCHECKBOX", PyInt_FromLong(NEWT_COLORSET_ACTCHECKBOX));
1522     setitemstring_decref(d, "COLORSET_ENTRY", PyInt_FromLong(NEWT_COLORSET_ENTRY));
1523     setitemstring_decref(d, "COLORSET_LABEL", PyInt_FromLong(NEWT_COLORSET_LABEL));
1524     setitemstring_decref(d, "COLORSET_LISTBOX", PyInt_FromLong(NEWT_COLORSET_LISTBOX));
1525     setitemstring_decref(d, "COLORSET_ACTLISTBOX", PyInt_FromLong(NEWT_COLORSET_ACTLISTBOX));
1526     setitemstring_decref(d, "COLORSET_TEXTBOX", PyInt_FromLong(NEWT_COLORSET_TEXTBOX));
1527     setitemstring_decref(d, "COLORSET_ACTTEXTBOX", PyInt_FromLong(NEWT_COLORSET_ACTTEXTBOX));
1528     setitemstring_decref(d, "COLORSET_HELPLINE", PyInt_FromLong(NEWT_COLORSET_HELPLINE));
1529     setitemstring_decref(d, "COLORSET_ROOTTEXT", PyInt_FromLong(NEWT_COLORSET_ROOTTEXT));
1530     setitemstring_decref(d, "COLORSET_EMPTYSCALE", PyInt_FromLong(NEWT_COLORSET_EMPTYSCALE));
1531     setitemstring_decref(d, "COLORSET_FULLSCALE", PyInt_FromLong(NEWT_COLORSET_FULLSCALE));
1532     setitemstring_decref(d, "COLORSET_DISENTRY", PyInt_FromLong(NEWT_COLORSET_DISENTRY));
1533     setitemstring_decref(d, "COLORSET_COMPACTBUTTON", PyInt_FromLong(NEWT_COLORSET_COMPACTBUTTON));
1534     setitemstring_decref(d, "COLORSET_ACTSELLISTBOX", PyInt_FromLong(NEWT_COLORSET_ACTSELLISTBOX));
1535     setitemstring_decref(d, "COLORSET_SELLISTBOX", PyInt_FromLong(NEWT_COLORSET_SELLISTBOX));
1536 
1537     return MOD_SUCCESS_VAL(m);
1538 }
1539