📄 flmodule.c
字号:
/* FL module -- interface to Mark Overmars' FORMS Library. */
/* This code works with FORMS version 2.2 (if you defined
OBSOLETE_FORMS_CALLS), and 2.3.
FORMS can be ftp'ed from ftp.cs.ruu.nl (131.211.80.17), directory
/pub/SGI/FORMS. */
/* A half-hearted attempt has been made to allow programs using this
* module to exploit parallelism (through the threads module). No provisions
* have been made for multiple threads to use this module at the same time,
* though. So, a program with a forms thread and a non-forms thread will work
* fine but a program with two threads using forms will probably crash (unless
* the program takes precaution to ensure that only one thread can be in
* this module at any time). This will have to be fixed some time.
* (A fix will probably also have to synchronize with the gl module).
*/
#include "Python.h"
#include "forms.h"
#include "structmember.h"
/* Generic Forms Objects */
typedef struct {
PyObject_HEAD
FL_OBJECT *ob_generic;
PyMethodDef *ob_methods;
PyObject *ob_callback;
PyObject *ob_callback_arg;
} genericobject;
staticforward PyTypeObject GenericObjecttype;
#define is_genericobject(g) ((g)->ob_type == &GenericObjecttype)
/* List of all objects (XXX this should be a hash table on address...) */
static PyObject *allgenerics = NULL;
static int nfreeslots = 0;
/* Add an object to the list of known objects */
static void
knowgeneric(genericobject *g)
{
int i, n;
/* Create the list if it doesn't already exist */
if (allgenerics == NULL) {
allgenerics = PyList_New(0);
if (allgenerics == NULL) {
PyErr_Clear();
return; /* Too bad, live without allgenerics... */
}
}
if (nfreeslots > 0) {
/* Search the list for reusable slots (NULL items) */
/* XXX This can be made faster! */
n = PyList_Size(allgenerics);
for (i = 0; i < n; i++) {
if (PyList_GetItem(allgenerics, i) == NULL) {
Py_INCREF(g);
PyList_SetItem(allgenerics, i, (PyObject *)g);
nfreeslots--;
return;
}
}
/* Strange... no free slots found... */
nfreeslots = 0;
}
/* No free entries, append new item to the end */
PyList_Append(allgenerics, (PyObject *)g);
}
/* Find an object in the list of known objects */
static genericobject *
findgeneric(FL_OBJECT *generic)
{
int i, n;
genericobject *g;
if (allgenerics == NULL)
return NULL; /* No objects known yet */
n = PyList_Size(allgenerics);
for (i = 0; i < n; i++) {
g = (genericobject *)PyList_GetItem(allgenerics, i);
if (g != NULL && g->ob_generic == generic)
return g;
}
return NULL; /* Unknown object */
}
/* Remove an object from the list of known objects */
static void
forgetgeneric(genericobject *g)
{
int i, n;
Py_XDECREF(g->ob_callback);
g->ob_callback = NULL;
Py_XDECREF(g->ob_callback_arg);
g->ob_callback_arg = NULL;
if (allgenerics == NULL)
return; /* No objects known yet */
n = PyList_Size(allgenerics);
for (i = 0; i < n; i++) {
if (g == (genericobject *)PyList_GetItem(allgenerics, i)) {
PyList_SetItem(allgenerics, i, (PyObject *)NULL);
nfreeslots++;
break;
}
}
}
/* Called when a form is about to be freed --
remove all the objects that we know about from it. */
static void
releaseobjects(FL_FORM *form)
{
int i, n;
genericobject *g;
if (allgenerics == NULL)
return; /* No objects known yet */
n = PyList_Size(allgenerics);
for (i = 0; i < n; i++) {
g = (genericobject *)PyList_GetItem(allgenerics, i);
if (g != NULL && g->ob_generic->form == form) {
fl_delete_object(g->ob_generic);
/* The object is now unreachable for
do_forms and check_forms, so
delete it from the list of known objects */
Py_XDECREF(g->ob_callback);
g->ob_callback = NULL;
Py_XDECREF(g->ob_callback_arg);
g->ob_callback_arg = NULL;
PyList_SetItem(allgenerics, i, (PyObject *)NULL);
nfreeslots++;
}
}
}
/* Methods of generic objects */
static PyObject *
generic_set_call_back(genericobject *g, PyObject *args)
{
if (args == NULL) {
Py_XDECREF(g->ob_callback);
Py_XDECREF(g->ob_callback_arg);
g->ob_callback = NULL;
g->ob_callback_arg = NULL;
}
else {
if (!PyTuple_Check(args) || PyTuple_Size(args) != 2) {
PyErr_BadArgument();
return NULL;
}
Py_XDECREF(g->ob_callback);
Py_XDECREF(g->ob_callback_arg);
g->ob_callback = PyTuple_GetItem(args, 0);
Py_INCREF(g->ob_callback);
g->ob_callback_arg = PyTuple_GetItem(args, 1);
Py_INCREF(g->ob_callback_arg);
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
generic_call(genericobject *g, PyObject *args, void (*func)(FL_OBJECT *))
{
if (!PyArg_NoArgs(args))
return NULL;
(*func)(g->ob_generic);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
generic_delete_object(genericobject *g, PyObject *args)
{
PyObject *res;
res = generic_call(g, args, fl_delete_object);
if (res != NULL)
forgetgeneric(g);
return res;
}
static PyObject *
generic_show_object(genericobject *g, PyObject *args)
{
return generic_call(g, args, fl_show_object);
}
static PyObject *
generic_hide_object(genericobject *g, PyObject *args)
{
return generic_call(g, args, fl_hide_object);
}
static PyObject *
generic_redraw_object(genericobject *g, PyObject *args)
{
return generic_call(g, args, fl_redraw_object);
}
#ifdef OBSOLETE_FORMS_CALLS
/* (un)freeze_object() are obsolete in FORMS 2.2 and unsupported
in 2.3. Since there's no foolproof way to tell which version we're
using, we omit them unconditionally. */
static PyObject *
generic_freeze_object(genericobject *g, PyObject *args)
{
return generic_call(g, args, fl_freeze_object);
}
static PyObject *
generic_unfreeze_object(genericobject *g, PyObject *args)
{
return generic_call(g, args, fl_unfreeze_object);
}
#endif /* OBSOLETE_FORMS_CALLS */
static PyObject *
generic_activate_object(genericobject *g, PyObject *args)
{
return generic_call(g, args, fl_activate_object);
}
static PyObject *
generic_deactivate_object(genericobject *g, PyObject *args)
{
return generic_call(g, args, fl_deactivate_object);
}
static PyObject *
generic_set_object_shortcut(genericobject *g, PyObject *args)
{
char *str;
if (!PyArg_Parse(args, "s", &str))
return NULL;
fl_set_object_shortcut(g->ob_generic, str);
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef generic_methods[] = {
{"set_call_back", (PyCFunction)generic_set_call_back},
{"delete_object", (PyCFunction)generic_delete_object},
{"show_object", (PyCFunction)generic_show_object},
{"hide_object", (PyCFunction)generic_hide_object},
{"redraw_object", (PyCFunction)generic_redraw_object},
#ifdef OBSOLETE_FORMS_CALLS
{"freeze_object", (PyCFunction)generic_freeze_object},
{"unfreeze_object", (PyCFunction)generic_unfreeze_object},
#endif
{"activate_object", (PyCFunction)generic_activate_object},
{"deactivate_object", (PyCFunction)generic_deactivate_object},
{"set_object_shortcut", (PyCFunction)generic_set_object_shortcut},
{NULL, NULL} /* sentinel */
};
static void
generic_dealloc(genericobject *g)
{
fl_free_object(g->ob_generic);
Py_XDECREF(g->ob_callback);
Py_XDECREF(g->ob_callback_arg);
PyObject_Del(g);
}
#define OFF(x) offsetof(FL_OBJECT, x)
static struct memberlist generic_memberlist[] = {
{"objclass", T_INT, OFF(objclass), RO},
{"type", T_INT, OFF(type), RO},
{"boxtype", T_INT, OFF(boxtype)},
{"x", T_FLOAT, OFF(x)},
{"y", T_FLOAT, OFF(y)},
{"w", T_FLOAT, OFF(w)},
{"h", T_FLOAT, OFF(h)},
{"col1", T_INT, OFF(col1)},
{"col2", T_INT, OFF(col2)},
{"align", T_INT, OFF(align)},
{"lcol", T_INT, OFF(lcol)},
{"lsize", T_FLOAT, OFF(lsize)},
/* "label" is treated specially! */
{"lstyle", T_INT, OFF(lstyle)},
{"pushed", T_INT, OFF(pushed), RO},
{"focus", T_INT, OFF(focus), RO},
{"belowmouse", T_INT, OFF(belowmouse),RO},
/* {"frozen", T_INT, OFF(frozen), RO}, */
{"active", T_INT, OFF(active)},
{"input", T_INT, OFF(input)},
{"visible", T_INT, OFF(visible), RO},
{"radio", T_INT, OFF(radio)},
{"automatic", T_INT, OFF(automatic)},
{NULL} /* Sentinel */
};
#undef OFF
static PyObject *
generic_getattr(genericobject *g, char *name)
{
PyObject *meth;
/* XXX Ought to special-case name "__methods__" */
if (g-> ob_methods) {
meth = Py_FindMethod(g->ob_methods, (PyObject *)g, name);
if (meth != NULL) return meth;
PyErr_Clear();
}
meth = Py_FindMethod(generic_methods, (PyObject *)g, name);
if (meth != NULL)
return meth;
PyErr_Clear();
/* "label" is an exception, getmember only works for char pointers,
not for char arrays */
if (strcmp(name, "label") == 0)
return PyString_FromString(g->ob_generic->label);
return PyMember_Get((char *)g->ob_generic, generic_memberlist, name);
}
static int
generic_setattr(genericobject *g, char *name, PyObject *v)
{
int ret;
if (v == NULL) {
PyErr_SetString(PyExc_TypeError,
"can't delete forms object attributes");
return -1;
}
/* "label" is an exception: setmember doesn't set strings;
and FORMS wants you to call a function to set the label */
if (strcmp(name, "label") == 0) {
if (!PyString_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"label attr must be string");
return -1;
}
fl_set_object_label(g->ob_generic, PyString_AsString(v));
return 0;
}
ret = PyMember_Set((char *)g->ob_generic, generic_memberlist, name, v);
/* Rather than calling all the various set_object_* functions,
we call fl_redraw_object here. This is sometimes redundant
but I doubt that's a big problem */
if (ret == 0)
fl_redraw_object(g->ob_generic);
return ret;
}
static PyObject *
generic_repr(genericobject *g)
{
char buf[100];
PyOS_snprintf(buf, sizeof(buf), "<FORMS_object at %p, objclass=%d>",
g, g->ob_generic->objclass);
return PyString_FromString(buf);
}
static PyTypeObject GenericObjecttype = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"fl.FORMS_object", /*tp_name*/
sizeof(genericobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
(destructor)generic_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)generic_getattr, /*tp_getattr*/
(setattrfunc)generic_setattr, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc)generic_repr, /*tp_repr*/
};
static PyObject *
newgenericobject(FL_OBJECT *generic, PyMethodDef *methods)
{
genericobject *g;
g = PyObject_New(genericobject, &GenericObjecttype);
if (g == NULL)
return NULL;
g-> ob_generic = generic;
g->ob_methods = methods;
g->ob_callback = NULL;
g->ob_callback_arg = NULL;
knowgeneric(g);
return (PyObject *)g;
}
/**********************************************************************/
/* Some common calling sequences */
/* void func (object, float) */
static PyObject *
call_forms_INf (void (*func)(FL_OBJECT *, float), FL_OBJECT *obj, PyObject *args)
{
float parameter;
if (!PyArg_Parse(args, "f", ¶meter)) return NULL;
(*func) (obj, parameter);
Py_INCREF(Py_None);
return Py_None;
}
/* void func (object, float) */
static PyObject *
call_forms_INfINf (void (*func)(FL_OBJECT *, float, float), FL_OBJECT *obj, PyObject *args)
{
float par1, par2;
if (!PyArg_Parse(args, "(ff)", &par1, &par2)) return NULL;
(*func) (obj, par1, par2);
Py_INCREF(Py_None);
return Py_None;
}
/* void func (object, int) */
static PyObject *
call_forms_INi (void (*func)(FL_OBJECT *, int), FL_OBJECT *obj, PyObject *args)
{
int parameter;
if (!PyArg_Parse(args, "i", ¶meter)) return NULL;
(*func) (obj, parameter);
Py_INCREF(Py_None);
return Py_None;
}
/* void func (object, char) */
static PyObject *
call_forms_INc (void (*func)(FL_OBJECT *, int), FL_OBJECT *obj, PyObject *args)
{
char *a;
if (!PyArg_Parse(args, "s", &a)) return NULL;
(*func) (obj, a[0]);
Py_INCREF(Py_None);
return Py_None;
}
/* void func (object, string) */
static PyObject *
call_forms_INstr (void (*func)(FL_OBJECT *, char *), FL_OBJECT *obj, PyObject *args)
{
char *a;
if (!PyArg_Parse(args, "s", &a)) return NULL;
(*func) (obj, a);
Py_INCREF(Py_None);
return Py_None;
}
/* void func (object, int, string) */
static PyObject *
call_forms_INiINstr (void (*func)(FL_OBJECT *, int, char *), FL_OBJECT *obj, PyObject *args)
{
char *b;
int a;
if (!PyArg_Parse(args, "(is)", &a, &b)) return NULL;
(*func) (obj, a, b);
Py_INCREF(Py_None);
return Py_None;
}
#ifdef UNUSED
/* void func (object, int, int) */
static PyObject *
call_forms_INiINi (void (*func)(FL_OBJECT *, int, int), FL_OBJECT *obj, PyObject *args)
{
int par1, par2;
if (!PyArg_Parse(args, "(ii)", &par1, &par2)) return NULL;
(*func) (obj, par1, par2);
Py_INCREF(Py_None);
return Py_None;
}
#endif
/* int func (object) */
static PyObject *
call_forms_Ri (int (*func)(FL_OBJECT *), FL_OBJECT *obj, PyObject *args)
{
int retval;
if (!PyArg_NoArgs(args)) return NULL;
retval = (*func) (obj);
return PyInt_FromLong ((long) retval);
}
/* char * func (object) */
static PyObject *
call_forms_Rstr (char * (*func)(FL_OBJECT *), FL_OBJECT *obj, PyObject *args)
{
char *str;
if (!PyArg_NoArgs(args)) return NULL;
str = (*func) (obj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -