symbian-qemu-0.9.1-12/python-2.6.1/Modules/_curses_panel.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  *   Interface to the ncurses panel library
       
     3  *
       
     4  * Original version by Thomas Gellekum
       
     5  */
       
     6 
       
     7 /* Release Number */
       
     8 
       
     9 static char *PyCursesVersion = "2.1";
       
    10 
       
    11 /* Includes */
       
    12 
       
    13 #include "Python.h"
       
    14 
       
    15 #include "py_curses.h"
       
    16 
       
    17 #include <panel.h>
       
    18 
       
    19 static PyObject *PyCursesError;
       
    20 
       
    21 
       
    22 /* Utility Functions */
       
    23 
       
    24 /*
       
    25  * Check the return code from a curses function and return None 
       
    26  * or raise an exception as appropriate.
       
    27  */
       
    28 
       
    29 static PyObject *
       
    30 PyCursesCheckERR(int code, char *fname)
       
    31 {
       
    32     if (code != ERR) {
       
    33 	Py_INCREF(Py_None);
       
    34 	return Py_None;
       
    35     } else {
       
    36 	if (fname == NULL) {
       
    37 	    PyErr_SetString(PyCursesError, catchall_ERR);
       
    38 	} else {
       
    39 	    PyErr_Format(PyCursesError, "%s() returned ERR", fname);
       
    40 	}
       
    41 	return NULL;
       
    42     }
       
    43 }
       
    44 
       
    45 /*****************************************************************************
       
    46  The Panel Object
       
    47 ******************************************************************************/
       
    48 
       
    49 /* Definition of the panel object and panel type */
       
    50 
       
    51 typedef struct {
       
    52     PyObject_HEAD
       
    53     PANEL *pan;
       
    54     PyCursesWindowObject *wo;	/* for reference counts */
       
    55 } PyCursesPanelObject;
       
    56 
       
    57 PyTypeObject PyCursesPanel_Type;
       
    58 
       
    59 #define PyCursesPanel_Check(v)	 (Py_TYPE(v) == &PyCursesPanel_Type)
       
    60 
       
    61 /* Some helper functions. The problem is that there's always a window
       
    62    associated with a panel. To ensure that Python's GC doesn't pull
       
    63    this window from under our feet we need to keep track of references
       
    64    to the corresponding window object within Python. We can't use
       
    65    dupwin(oldwin) to keep a copy of the curses WINDOW because the
       
    66    contents of oldwin is copied only once; code like
       
    67 
       
    68    win = newwin(...)
       
    69    pan = win.panel()
       
    70    win.addstr(some_string)
       
    71    pan.window().addstr(other_string)
       
    72 
       
    73    will fail. */
       
    74 
       
    75 /* We keep a linked list of PyCursesPanelObjects, lop. A list should
       
    76    suffice, I don't expect more than a handful or at most a few
       
    77    dozens of panel objects within a typical program. */
       
    78 typedef struct _list_of_panels {
       
    79     PyCursesPanelObject *po;
       
    80     struct _list_of_panels *next;
       
    81 } list_of_panels;
       
    82 
       
    83 /* list anchor */
       
    84 static list_of_panels *lop;
       
    85 
       
    86 /* Insert a new panel object into lop */
       
    87 static int
       
    88 insert_lop(PyCursesPanelObject *po)
       
    89 {
       
    90     list_of_panels *new;
       
    91     
       
    92     if ((new = (list_of_panels *)malloc(sizeof(list_of_panels))) == NULL) {
       
    93 	PyErr_NoMemory();
       
    94 	return -1;
       
    95     }
       
    96     new->po = po;
       
    97     new->next = lop;
       
    98     lop = new;
       
    99     return 0;
       
   100 }
       
   101 
       
   102 /* Remove the panel object from lop */
       
   103 static void
       
   104 remove_lop(PyCursesPanelObject *po)
       
   105 {
       
   106     list_of_panels *temp, *n;
       
   107 
       
   108     temp = lop;
       
   109     if (temp->po == po) {
       
   110 	lop = temp->next;
       
   111 	free(temp);
       
   112 	return;
       
   113     }
       
   114     while (temp->next == NULL || temp->next->po != po) {
       
   115 	if (temp->next == NULL) {
       
   116 	    PyErr_SetString(PyExc_RuntimeError,
       
   117 			    "remove_lop: can't find Panel Object");
       
   118 	    return;
       
   119 	}
       
   120 	temp = temp->next;
       
   121     }
       
   122     n = temp->next->next;
       
   123     free(temp->next);
       
   124     temp->next = n;
       
   125     return;
       
   126 }
       
   127 
       
   128 /* Return the panel object that corresponds to pan */
       
   129 static PyCursesPanelObject *
       
   130 find_po(PANEL *pan)
       
   131 {
       
   132     list_of_panels *temp;
       
   133     for (temp = lop; temp->po->pan != pan; temp = temp->next)
       
   134 	if (temp->next == NULL) return NULL;	/* not found!? */
       
   135     return temp->po;
       
   136 }
       
   137 
       
   138 /* Function Prototype Macros - They are ugly but very, very useful. ;-)
       
   139 
       
   140    X - function name
       
   141    TYPE - parameter Type
       
   142    ERGSTR - format string for construction of the return value
       
   143    PARSESTR - format string for argument parsing */
       
   144 
       
   145 #define Panel_NoArgNoReturnFunction(X) \
       
   146 static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self) \
       
   147 { return PyCursesCheckERR(X(self->pan), # X); }
       
   148 
       
   149 #define Panel_NoArgTrueFalseFunction(X) \
       
   150 static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self) \
       
   151 { \
       
   152   if (X (self->pan) == FALSE) { Py_INCREF(Py_False); return Py_False; } \
       
   153   else { Py_INCREF(Py_True); return Py_True; } }
       
   154 
       
   155 #define Panel_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \
       
   156 static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self, PyObject *args) \
       
   157 { \
       
   158   TYPE arg1, arg2; \
       
   159   if (!PyArg_ParseTuple(args, PARSESTR, &arg1, &arg2)) return NULL; \
       
   160   return PyCursesCheckERR(X(self->pan, arg1, arg2), # X); }
       
   161 
       
   162 /* ------------- PANEL routines --------------- */
       
   163 
       
   164 Panel_NoArgNoReturnFunction(bottom_panel)
       
   165 Panel_NoArgNoReturnFunction(hide_panel)
       
   166 Panel_NoArgNoReturnFunction(show_panel)
       
   167 Panel_NoArgNoReturnFunction(top_panel)
       
   168 Panel_NoArgTrueFalseFunction(panel_hidden)
       
   169 Panel_TwoArgNoReturnFunction(move_panel, int, "ii;y,x")
       
   170 
       
   171 /* Allocation and deallocation of Panel Objects */
       
   172 
       
   173 static PyObject *
       
   174 PyCursesPanel_New(PANEL *pan, PyCursesWindowObject *wo)
       
   175 {
       
   176     PyCursesPanelObject *po;
       
   177 
       
   178     po = PyObject_NEW(PyCursesPanelObject, &PyCursesPanel_Type);
       
   179     if (po == NULL) return NULL;
       
   180     po->pan = pan;
       
   181     po->wo = wo;
       
   182     Py_INCREF(wo);
       
   183     if (insert_lop(po) < 0) {
       
   184 	PyObject_DEL(po);
       
   185 	return NULL;
       
   186     }
       
   187     return (PyObject *)po;
       
   188 }
       
   189 
       
   190 static void
       
   191 PyCursesPanel_Dealloc(PyCursesPanelObject *po)
       
   192 {
       
   193     (void)del_panel(po->pan);
       
   194     Py_DECREF(po->wo);
       
   195     remove_lop(po);
       
   196     PyObject_DEL(po);
       
   197 }
       
   198 
       
   199 /* panel_above(NULL) returns the bottom panel in the stack. To get
       
   200    this behaviour we use curses.panel.bottom_panel(). */
       
   201 static PyObject *
       
   202 PyCursesPanel_above(PyCursesPanelObject *self)
       
   203 {
       
   204     PANEL *pan;
       
   205     PyCursesPanelObject *po;
       
   206     
       
   207     pan = panel_above(self->pan);
       
   208 
       
   209     if (pan == NULL) {		/* valid output, it means the calling panel
       
   210 				   is on top of the stack */
       
   211 	Py_INCREF(Py_None);
       
   212 	return Py_None;
       
   213     }
       
   214     po = find_po(pan);
       
   215     if (po == NULL) {
       
   216 	PyErr_SetString(PyExc_RuntimeError,
       
   217 			"panel_above: can't find Panel Object");
       
   218 	return NULL;
       
   219     }
       
   220     Py_INCREF(po);
       
   221     return (PyObject *)po;
       
   222 }
       
   223 
       
   224 /* panel_below(NULL) returns the top panel in the stack. To get
       
   225    this behaviour we use curses.panel.top_panel(). */
       
   226 static PyObject *
       
   227 PyCursesPanel_below(PyCursesPanelObject *self)
       
   228 {
       
   229     PANEL *pan;
       
   230     PyCursesPanelObject *po;
       
   231     
       
   232     pan = panel_below(self->pan);
       
   233     
       
   234     if (pan == NULL) {		/* valid output, it means the calling panel
       
   235 				   is on the bottom of the stack */
       
   236 	Py_INCREF(Py_None);
       
   237 	return Py_None;
       
   238     }
       
   239     po = find_po(pan);
       
   240     if (po == NULL) {
       
   241 	PyErr_SetString(PyExc_RuntimeError,
       
   242 			"panel_below: can't find Panel Object");
       
   243 	return NULL;
       
   244     }
       
   245     Py_INCREF(po);
       
   246     return (PyObject *)po;
       
   247 }
       
   248 
       
   249 static PyObject *
       
   250 PyCursesPanel_window(PyCursesPanelObject *self)
       
   251 {
       
   252     Py_INCREF(self->wo);
       
   253     return (PyObject *)self->wo;
       
   254 }
       
   255 
       
   256 static PyObject *
       
   257 PyCursesPanel_replace_panel(PyCursesPanelObject *self, PyObject *args)
       
   258 {
       
   259     PyCursesPanelObject *po;
       
   260     PyCursesWindowObject *temp;
       
   261     int rtn;
       
   262     
       
   263     if (PyTuple_Size(args) != 1) {
       
   264 	PyErr_SetString(PyExc_TypeError, "replace requires one argument");
       
   265 	return NULL;
       
   266     }
       
   267     if (!PyArg_ParseTuple(args, "O!;window object",
       
   268 			  &PyCursesWindow_Type, &temp))
       
   269 	return NULL;
       
   270 
       
   271     po = find_po(self->pan);
       
   272     if (po == NULL) {
       
   273 	PyErr_SetString(PyExc_RuntimeError,
       
   274 			"replace_panel: can't find Panel Object");
       
   275 	return NULL;
       
   276     }
       
   277 
       
   278     rtn = replace_panel(self->pan, temp->win);
       
   279     if (rtn == ERR) {
       
   280 	PyErr_SetString(PyCursesError, "replace_panel() returned ERR");
       
   281 	return NULL;
       
   282     }
       
   283     Py_DECREF(po->wo);
       
   284     po->wo = temp;
       
   285     Py_INCREF(po->wo);
       
   286     Py_INCREF(Py_None);
       
   287     return Py_None;
       
   288 }
       
   289 
       
   290 static PyObject *
       
   291 PyCursesPanel_set_panel_userptr(PyCursesPanelObject *self, PyObject *obj)
       
   292 {
       
   293     Py_INCREF(obj);
       
   294     return PyCursesCheckERR(set_panel_userptr(self->pan, (void*)obj),
       
   295                             "set_panel_userptr");
       
   296 }
       
   297 
       
   298 static PyObject *
       
   299 PyCursesPanel_userptr(PyCursesPanelObject *self)
       
   300 {
       
   301     PyObject *obj;
       
   302     PyCursesInitialised; 
       
   303     obj = (PyObject *) panel_userptr(self->pan);
       
   304     if (obj == NULL) {
       
   305 	PyErr_SetString(PyCursesError, "no userptr set");
       
   306 	return NULL;
       
   307     }
       
   308 
       
   309     Py_INCREF(obj);
       
   310     return obj;
       
   311 }
       
   312 
       
   313 
       
   314 /* Module interface */
       
   315 
       
   316 static PyMethodDef PyCursesPanel_Methods[] = {
       
   317     {"above",           (PyCFunction)PyCursesPanel_above, METH_NOARGS},
       
   318     {"below",           (PyCFunction)PyCursesPanel_below, METH_NOARGS},
       
   319     {"bottom",          (PyCFunction)PyCursesPanel_bottom_panel, METH_NOARGS},
       
   320     {"hidden",          (PyCFunction)PyCursesPanel_panel_hidden, METH_NOARGS},
       
   321     {"hide",            (PyCFunction)PyCursesPanel_hide_panel, METH_NOARGS},
       
   322     {"move",            (PyCFunction)PyCursesPanel_move_panel, METH_VARARGS},
       
   323     {"replace",         (PyCFunction)PyCursesPanel_replace_panel, METH_VARARGS},
       
   324     {"set_userptr",     (PyCFunction)PyCursesPanel_set_panel_userptr, METH_O},
       
   325     {"show",            (PyCFunction)PyCursesPanel_show_panel, METH_NOARGS},
       
   326     {"top",             (PyCFunction)PyCursesPanel_top_panel, METH_NOARGS},
       
   327     {"userptr",         (PyCFunction)PyCursesPanel_userptr, METH_NOARGS},
       
   328     {"window",          (PyCFunction)PyCursesPanel_window, METH_NOARGS},
       
   329     {NULL,		NULL}   /* sentinel */
       
   330 };
       
   331 
       
   332 static PyObject *
       
   333 PyCursesPanel_GetAttr(PyCursesPanelObject *self, char *name)
       
   334 {
       
   335     return Py_FindMethod(PyCursesPanel_Methods, (PyObject *)self, name);
       
   336 }
       
   337 
       
   338 /* -------------------------------------------------------*/
       
   339 
       
   340 PyTypeObject PyCursesPanel_Type = {
       
   341     PyVarObject_HEAD_INIT(NULL, 0)
       
   342     "_curses_panel.curses panel",	/*tp_name*/
       
   343     sizeof(PyCursesPanelObject),	/*tp_basicsize*/
       
   344     0,			/*tp_itemsize*/
       
   345     /* methods */
       
   346     (destructor)PyCursesPanel_Dealloc, /*tp_dealloc*/
       
   347     0,			/*tp_print*/
       
   348     (getattrfunc)PyCursesPanel_GetAttr, /*tp_getattr*/
       
   349     (setattrfunc)0, /*tp_setattr*/
       
   350     0,			/*tp_compare*/
       
   351     0,			/*tp_repr*/
       
   352     0,			/*tp_as_number*/
       
   353     0,			/*tp_as_sequence*/
       
   354     0,			/*tp_as_mapping*/
       
   355     0,			/*tp_hash*/
       
   356 };
       
   357 
       
   358 /* Wrapper for panel_above(NULL). This function returns the bottom
       
   359    panel of the stack, so it's renamed to bottom_panel().
       
   360    panel.above() *requires* a panel object in the first place which
       
   361    may be undesirable. */
       
   362 static PyObject *
       
   363 PyCurses_bottom_panel(PyObject *self)
       
   364 {
       
   365     PANEL *pan;
       
   366     PyCursesPanelObject *po;
       
   367 
       
   368     PyCursesInitialised;
       
   369 
       
   370     pan = panel_above(NULL);
       
   371 
       
   372     if (pan == NULL) {		/* valid output, it means
       
   373 				   there's no panel at all */  
       
   374 	Py_INCREF(Py_None);
       
   375 	return Py_None;
       
   376     }
       
   377     po = find_po(pan);
       
   378     if (po == NULL) {
       
   379 	PyErr_SetString(PyExc_RuntimeError,
       
   380 			"panel_above: can't find Panel Object");
       
   381 	return NULL;
       
   382     }
       
   383     Py_INCREF(po);
       
   384     return (PyObject *)po;
       
   385 }
       
   386 
       
   387 static PyObject *
       
   388 PyCurses_new_panel(PyObject *self, PyObject *args)
       
   389 {
       
   390     PyCursesWindowObject *win;
       
   391     PANEL *pan;
       
   392 
       
   393     if (!PyArg_ParseTuple(args, "O!", &PyCursesWindow_Type, &win))
       
   394         return NULL;
       
   395     pan = new_panel(win->win);
       
   396     if (pan == NULL) {
       
   397 	PyErr_SetString(PyCursesError, catchall_NULL);
       
   398 	return NULL;
       
   399     }
       
   400     return (PyObject *)PyCursesPanel_New(pan, win);
       
   401 }
       
   402 
       
   403 
       
   404 /* Wrapper for panel_below(NULL). This function returns the top panel
       
   405    of the stack, so it's renamed to top_panel(). panel.below()
       
   406    *requires* a panel object in the first place which may be
       
   407    undesirable. */
       
   408 static PyObject *
       
   409 PyCurses_top_panel(PyObject *self)
       
   410 {
       
   411     PANEL *pan;
       
   412     PyCursesPanelObject *po;
       
   413     
       
   414     PyCursesInitialised;
       
   415 
       
   416     pan = panel_below(NULL);
       
   417 
       
   418     if (pan == NULL) {		/* valid output, it means
       
   419 				   there's no panel at all */
       
   420 	Py_INCREF(Py_None);
       
   421 	return Py_None;
       
   422     }
       
   423     po = find_po(pan);
       
   424     if (po == NULL) {
       
   425 	PyErr_SetString(PyExc_RuntimeError,
       
   426 			"panel_below: can't find Panel Object");
       
   427 	return NULL;
       
   428     }
       
   429     Py_INCREF(po);
       
   430     return (PyObject *)po;
       
   431 }
       
   432 
       
   433 static PyObject *PyCurses_update_panels(PyObject *self)
       
   434 { 
       
   435     PyCursesInitialised;
       
   436     update_panels();
       
   437     Py_INCREF(Py_None);
       
   438     return Py_None;
       
   439 }
       
   440 
       
   441 
       
   442 /* List of functions defined in the module */
       
   443 
       
   444 static PyMethodDef PyCurses_methods[] = {
       
   445     {"bottom_panel",        (PyCFunction)PyCurses_bottom_panel,  METH_NOARGS},
       
   446     {"new_panel",           (PyCFunction)PyCurses_new_panel,     METH_VARARGS},
       
   447     {"top_panel",           (PyCFunction)PyCurses_top_panel,     METH_NOARGS},
       
   448     {"update_panels",       (PyCFunction)PyCurses_update_panels, METH_NOARGS},
       
   449     {NULL,		NULL}		/* sentinel */
       
   450 };
       
   451 
       
   452 /* Initialization function for the module */
       
   453 
       
   454 PyMODINIT_FUNC
       
   455 init_curses_panel(void)
       
   456 {
       
   457     PyObject *m, *d, *v;
       
   458 
       
   459     /* Initialize object type */
       
   460     Py_TYPE(&PyCursesPanel_Type) = &PyType_Type;
       
   461 
       
   462     import_curses();
       
   463 
       
   464     /* Create the module and add the functions */
       
   465     m = Py_InitModule("_curses_panel", PyCurses_methods);
       
   466     if (m == NULL)
       
   467     	return;
       
   468     d = PyModule_GetDict(m);
       
   469 
       
   470     /* For exception _curses_panel.error */
       
   471     PyCursesError = PyErr_NewException("_curses_panel.error", NULL, NULL);
       
   472     PyDict_SetItemString(d, "error", PyCursesError);
       
   473 
       
   474     /* Make the version available */
       
   475     v = PyString_FromString(PyCursesVersion);
       
   476     PyDict_SetItemString(d, "version", v);
       
   477     PyDict_SetItemString(d, "__version__", v);
       
   478     Py_DECREF(v);
       
   479 }