/*********************************************************** Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The Netherlands. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* Panel module. Interface to the NASA Ames "panel library" for the SGI Graphics Library by David Tristram. NOTE: the panel library dumps core if you don't create a window before calling pnl.mkpanel(). A call to gl.winopen() suffices. If you don't want a window to be created, call gl.noport() before gl.winopen(). */ #include #include #include #include "allobjects.h" #include "import.h" #include "modsupport.h" #include "cgensupport.h" /* The offsetof() macro calculates the offset of a structure member in its structure. Unfortunately this cannot be written down portably, hence it is standardized by ANSI C. For pre-ANSI C compilers, we give a version here that works usually (but watch out!): */ #ifndef offsetof #define offsetof(type, member) ( (int) & ((type*)0) -> member ) #endif /* Panel objects */ typedef struct { OB_HEAD Panel *ob_panel; object *ob_paneldict; } panelobject; extern typeobject Paneltype; /* Really static, forward */ #define is_panelobject(v) ((v)->ob_type == &Paneltype) /* Actuator objects */ typedef struct { OB_HEAD Actuator *ob_actuator; } actuatorobject; extern typeobject Actuatortype; /* Really static, forward */ #define is_actuatorobject(v) ((v)->ob_type == &Actuatortype) static object *newactuatorobject(); /* Forward */ /* Since we allow different types of members than the functions from structmember.c, the memberlist stuff is replicated here. (Historically, it originated in this file and later became a generic feature.) */ /* An array of memberlist structures defines the name, type and offset of selected members of a C structure. These can be read by panel_getmember() and set by panel_setmember() (except if their READONLY flag is set). The array must be terminated with an entry whose name pointer is NULL. */ struct memberlist { char *name; int type; int offset; int readonly; }; /* Types */ #define T_SHORT 0 #define T_DEVICE T_SHORT #define T_LONG 1 #define T_INT T_LONG #define T_BOOL T_LONG #define T_FLOAT 2 #define T_COORD T_FLOAT #define T_STRING 3 #define T_FUNC 4 #define T_ACTUATOR 5 /* Readonly flag */ #define READONLY 1 #define RO READONLY /* Shorthand */ static object * panel_getmember(addr, mlist, name) char *addr; struct memberlist *mlist; char *name; { object *v; register struct memberlist *l; for (l = mlist; l->name != NULL; l++) { if (strcmp(l->name, name) == 0) { addr += l->offset; switch (l->type) { case T_SHORT: v = newintobject((long) *(short*)addr); break; case T_LONG: v = newintobject(*(long*)addr); break; case T_FLOAT: v = newfloatobject(*(float*)addr); break; case T_STRING: if (*(char**)addr == NULL) { INCREF(None); v = None; } else v = newstringobject(*(char**)addr); break; case T_ACTUATOR: v = newactuatorobject(*(Actuator**)addr); break; default: err_badarg(); v = NULL; } return v; } } err_setstr(NameError, name); return NULL; } /* Attempt to set a member. Return: 0 if OK; 1 if not found; -1 if error */ static int panel_setmember(addr, mlist, name, v) char *addr; struct memberlist *mlist; char *name; object *v; { register struct memberlist *l; for (l = mlist; l->name != NULL; l++) { if (strcmp(l->name, name) == 0) { if (l->readonly) { err_setstr(TypeError, "read-only member"); return -1; } addr += l->offset; switch (l->type) { case T_SHORT: if (!is_intobject(v)) { err_setstr(TypeError, "int expected"); return -1; } *(short*)addr = getintvalue(v); break; case T_LONG: if (!is_intobject(v)) { err_setstr(TypeError, "int expected"); return -1; } *(long*)addr = getintvalue(v); break; case T_FLOAT: if (is_intobject(v)) *(float*)addr = getintvalue(v); else if (is_floatobject(v)) *(float*)addr = getfloatvalue(v); else { err_setstr(TypeError,"float expected"); return -1; } break; case T_STRING: /* XXX Should free(*(char**)addr) here but it's dangerous since we don't know if we set the label ourselves */ if (v == None) *(char**)addr = NULL; else if (!is_stringobject(v)) { err_setstr(TypeError, "string expected"); return -1; } else *(char**)addr = strdup(getstringvalue(v)); break; case T_ACTUATOR: if (v == None) *(Actuator**)addr = NULL; else if (!is_actuatorobject(v)) { err_setstr(TypeError, "actuator expected"); return -1; } else *(Actuator**)addr = ((actuatorobject *)v)->ob_actuator; break; default: err_setstr(SystemError, "unknown member type"); return -1; } return 0; /* Found it */ } } return 1; /* Not found */ } /* Panel object methods */ static object * panel_addpanel(self, args) panelobject *self; object *args; { if (!getnoarg(args)) return NULL; pnl_addpanel(self->ob_panel); INCREF(None); return None; } static object * panel_endgroup(self, args) panelobject *self; object *args; { if (!getnoarg(args)) return NULL; pnl_endgroup(self->ob_panel); INCREF(None); return None; } static object * panel_fixpanel(self, args) panelobject *self; object *args; { if (!getnoarg(args)) return NULL; pnl_fixpanel(self->ob_panel); INCREF(None); return None; } static object * panel_strwidth(self, args) panelobject *self; object *args; { object *v; double width; if (!getstrarg(args, &v)) return NULL; width = pnl_strwidth(self->ob_panel, getstringvalue(v)); return newfloatobject(width); } static struct methodlist panel_methods[] = { {"addpanel", panel_addpanel}, {"endgroup", panel_endgroup}, {"fixpanel", panel_fixpanel}, {"strwidth", panel_strwidth}, {NULL, NULL} /* sentinel */ }; static object * newpanelobject() { panelobject *p; p = NEWOBJ(panelobject, &Paneltype); if (p == NULL) return NULL; p->ob_panel = pnl_mkpanel(); if ((p->ob_paneldict = newdictobject()) == NULL) { DECREF(p); return NULL; } return (object *)p; } static void panel_dealloc(p) panelobject *p; { pnl_delpanel(p->ob_panel); if (p->ob_paneldict != NULL) DECREF(p->ob_paneldict); DEL(p); } /* Table of panel members */ #define PANOFF(member) offsetof(Panel, member) static struct memberlist panel_memberlist[] = { {"id", T_SHORT, PANOFF(id), READONLY}, {"a", T_ACTUATOR, PANOFF(a), READONLY}, {"al", T_ACTUATOR, PANOFF(al), READONLY}, {"lastgroup", T_ACTUATOR, PANOFF(lastgroup), READONLY}, {"active", T_BOOL, PANOFF(active)}, {"selectable", T_BOOL, PANOFF(selectable)}, {"x", T_LONG, PANOFF(x)}, {"y", T_LONG, PANOFF(y)}, {"w", T_LONG, PANOFF(w)}, {"h", T_LONG, PANOFF(h)}, {"minx", T_COORD, PANOFF(minx)}, {"maxx", T_COORD, PANOFF(maxx)}, {"miny", T_COORD, PANOFF(miny)}, {"maxy", T_COORD, PANOFF(maxy)}, {"cw", T_COORD, PANOFF(cw)}, {"ch", T_COORD, PANOFF(ch)}, {"gid", T_LONG, PANOFF(gid), READONLY}, {"usergid", T_LONG, PANOFF(usergid), READONLY}, {"vobj", T_LONG, PANOFF(vobj), READONLY}, {"ppu", T_FLOAT, PANOFF(ppu)}, {"label", T_STRING, PANOFF(label)}, /* Panel callbacks are not supported */ {"visible", T_BOOL, PANOFF(visible)}, {"somedirty", T_INT, PANOFF(somedirty)}, {"dirtycnt", T_INT, PANOFF(dirtycnt)}, /* T_PANEL is not supported */ /* {"next", T_PANEL, PANOFF(next), READONLY}, */ {NULL, 0, 0} /* Sentinel */ }; static object * panel_getattr(p, name) panelobject *p; char *name; { object *v; v = dictlookup(p->ob_paneldict, name); if (v != NULL) { INCREF(v); return v; } v = findmethod(panel_methods, (object *)p, name); if (v != NULL) return v; err_clear(); return panel_getmember((char *)p->ob_panel, panel_memberlist, name); } static int panel_setattr(p, name, v) panelobject *p; char *name; object *v; { int err; /* We don't allow deletion of attributes */ if (v == NULL) { err_setstr(TypeError, "read-only panel attribute"); return -1; } err = panel_setmember((char *)p->ob_panel, panel_memberlist, name, v); if (err != 1) return err; return dictinsert(p->ob_paneldict, name, v); } static typeobject Paneltype = { OB_HEAD_INIT(&Typetype) 0, /*ob_size*/ "panel", /*tp_name*/ sizeof(panelobject), /*tp_size*/ 0, /*tp_itemsize*/ /* methods */ panel_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ panel_getattr, /*tp_getattr*/ panel_setattr, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ }; /* Descriptions of actuator-specific data members */ struct memberlist slider_spec[] = { {"mode", T_INT, offsetof(Slider, mode)}, {"finefactor", T_FLOAT, offsetof(Slider, finefactor)}, {"differentialfactor", T_FLOAT, offsetof(Slider, differentialfactor)}, {"valsave", T_FLOAT, offsetof(Slider, valsave), RO}, {"wsave", T_COORD, offsetof(Slider, wsave)}, {"bh", T_COORD, offsetof(Slider, bh)}, {NULL} }; #define palette_spec slider_spec struct memberlist puck_spec[] = { /* Actuators already have members x and y, so the Puck's x and y have different names */ {"puck_x", T_FLOAT, offsetof(Puck, x)}, {"puck_y", T_FLOAT, offsetof(Puck, y)}, {NULL} }; struct memberlist dial_spec[] = { {"mode", T_INT, offsetof(Dial, mode)}, {"finefactor", T_FLOAT, offsetof(Dial, finefactor)}, {"valsave", T_FLOAT, offsetof(Dial, valsave), RO}, {"wsave", T_COORD, offsetof(Dial, wsave)}, {"winds", T_FLOAT, offsetof(Dial, winds)}, {NULL} }; struct memberlist slideroid_spec[] = { {"mode", T_INT, offsetof(Slideroid, mode)}, {"finemode", T_BOOL, offsetof(Slideroid, finemode)}, {"resetmode", T_BOOL, offsetof(Slideroid, resetmode)}, /* XXX Can't do resettarget (pointer to float) */ /* XXX This makes resetval pretty useless... */ /* {"resetval", T_FLOAT, offsetof(Slideroid, resetval)}, */ {"valsave", T_FLOAT, offsetof(Slideroid, valsave), RO}, {"wsave", T_COORD, offsetof(Slideroid, wsave)}, {NULL} }; struct memberlist stripchart_spec[] = { {"firstpt", T_INT, offsetof(Stripchart, firstpt), RO}, {"lastpt", T_INT, offsetof(Stripchart, lastpt), RO}, {"Bind_Low", T_BOOL, offsetof(Stripchart, Bind_Low)}, {"Bind_High", T_BOOL, offsetof(Stripchart, Bind_High)}, /* XXX Can't do y (array of floats) */ {"lowlabel", T_ACTUATOR, offsetof(Stripchart, lowlabel), RO}, {"highlabel", T_ACTUATOR, offsetof(Stripchart, highlabel), RO}, {NULL} }; struct memberlist typein_spec[] = { /* Note: these should be readonly after the actuator is added to a panel */ {"str", T_STRING, offsetof(Typein, str)}, {"len", T_INT, offsetof(Typein, len)}, {NULL} }; struct memberlist typeout_spec[] = { {"mode", T_INT, offsetof(Typeout, mode)}, /* XXX The buffer is managed by the actuator; but how do we add text? */ {"buf", T_STRING, offsetof(Typeout, buf), READONLY}, {"delimstr", T_STRING, offsetof(Typeout, delimstr)}, {"start", T_INT, offsetof(Typeout, start)}, {"dot", T_INT, offsetof(Typeout, dot)}, {"mark", T_INT, offsetof(Typeout, mark)}, {"col", T_INT, offsetof(Typeout, col)}, {"lin", T_INT, offsetof(Typeout, lin)}, {"len", T_INT, offsetof(Typeout, len)}, {"size", T_INT, offsetof(Typeout, size)}, {NULL} }; struct memberlist mouse_spec[] = { /* Actuators already have members x and y, so the Mouse's x and y have different names */ {"mouse_x", T_FLOAT, offsetof(Mouse, x)}, {"mouse_y", T_FLOAT, offsetof(Mouse, y)}, {NULL} }; #define MULOFF(member) offsetof(Multislider, member) struct memberlist multislider_spec[] = { {"mode", T_INT, MULOFF(mode)}, {"n", T_INT, MULOFF(n)}, {"finefactor", T_FLOAT, MULOFF(finefactor)}, {"wsave", T_COORD, MULOFF(wsave)}, {"sa", T_ACTUATOR, MULOFF(sa)}, {"bh", T_COORD, MULOFF(bh)}, {"clrx", T_COORD, MULOFF(clrx)}, {"clry", T_COORD, MULOFF(clry)}, {"clrw", T_COORD, MULOFF(clrw)}, {"clrh", T_COORD, MULOFF(clrh)}, /* XXX acttype? */ {NULL} }; /* XXX Still to do: Frame Icon Cycle Scroll Menu */ /* List of known actuator initializer functions */ struct { char *name; void (*func)(); struct memberlist *spec; } initializerlist[] = { {"analog_bar", pnl_analog_bar}, {"analog_meter", pnl_analog_meter}, {"button", pnl_button}, {"cycle", pnl_cycle}, /* Doesn't exist: */ /* {"dhslider", pnl_dhslider, slider_spec}, */ {"dial", pnl_dial, dial_spec}, {"down_arrow_button", pnl_down_arrow_button}, {"down_double_arrow_button", pnl_down_double_arrow_button}, {"dvslider", pnl_dvslider, slider_spec}, {"filled_hslider", pnl_filled_hslider, slider_spec}, {"filled_slider", pnl_filled_slider, slider_spec}, {"filled_vslider", pnl_filled_vslider, slider_spec}, {"floating_puck", pnl_floating_puck, puck_spec}, {"frame", pnl_frame}, {"graphframe", pnl_graphframe}, {"hmultislider", pnl_hmultislider, multislider_spec}, {"hmultislider_bar", pnl_hmultislider_bar}, {"hmultislider_open_bar", pnl_hmultislider_open_bar}, {"hpalette", pnl_hpalette, palette_spec}, {"hslider", pnl_hslider, slider_spec}, {"icon", pnl_icon}, {"icon_menu", pnl_icon_menu}, {"label", pnl_label}, {"left_arrow_button", pnl_left_arrow_button}, {"left_double_arrow_button", pnl_left_double_arrow_button}, {"menu", pnl_menu}, {"menu_item", pnl_menu_item}, {"meter", pnl_meter}, {"mouse", pnl_mouse, mouse_spec}, {"multislider", pnl_multislider, multislider_spec}, {"multislider_bar", pnl_multislider_bar}, {"multislider_open_bar", pnl_multislider_open_bar}, {"palette", pnl_palette, palette_spec}, {"puck", pnl_puck, puck_spec}, {"radio_button", pnl_radio_button}, {"radio_check_button", pnl_radio_check_button}, {"right_arrow_button", pnl_right_arrow_button}, {"right_double_arrow_button", pnl_right_double_arrow_button}, {"rubber_puck", pnl_rubber_puck, puck_spec}, {"scale_chart", pnl_scale_chart, stripchart_spec}, {"scroll", pnl_scroll}, {"signal", pnl_signal}, {"slider", pnl_slider, slider_spec}, {"slideroid", pnl_slideroid, slideroid_spec}, {"strip_chart", pnl_strip_chart, stripchart_spec}, {"sub_menu", pnl_sub_menu}, {"toggle_button", pnl_toggle_button}, {"typein", pnl_typein, typein_spec}, {"typeout", pnl_typeout, typeout_spec}, {"up_arrow_button", pnl_up_arrow_button}, {"up_double_arrow_button", pnl_up_double_arrow_button}, {"viewframe", pnl_viewframe}, {"vmultislider", pnl_vmultislider, multislider_spec}, {"vmultislider_bar", pnl_vmultislider_bar}, {"vmultislider_open_bar", pnl_vmultislider_open_bar}, {"vpalette", pnl_vpalette, palette_spec}, {"vslider", pnl_vslider, slider_spec}, {"wide_button", pnl_wide_button}, {NULL, NULL} /* Sentinel */ }; /* Pseudo downfunc etc. */ static Actuator *down_pend, *active_pend, *up_pend; static void downfunc(a) Actuator *a; { if (down_pend == NULL) down_pend = a; } static void activefunc(a) Actuator *a; { if (active_pend == NULL) active_pend = a; } static void upfunc(a) Actuator *a; { if (up_pend == NULL) up_pend = a; } /* Lay-out for the user data */ struct userdata { object *dict; /* Dictionary object for additional attributes */ struct memberlist *spec; /* Actuator-specific members */ }; /* Create a new actuator; the actuator type is given as a string */ static Actuator * makeactuator(name) char *name; { Actuator *act; void (*initializer)() = NULL; int i; struct userdata *u; for (i = 0; initializerlist[i].name != NULL; i++) { if (strcmp(initializerlist[i].name, name) == 0) { initializer = initializerlist[i].func; break; } } if (initializerlist[i].name == NULL) { err_badarg(); return NULL; } u = NEW(struct userdata, 1); if (u == NULL) { err_nomem(); return NULL; } u->dict = NULL; u->spec = initializerlist[i].spec; act = pnl_mkact(initializer); act->u = (char *)u; act->downfunc = downfunc; act->activefunc = activefunc; act->upfunc = upfunc; return act; } /* Actuator objects methods */ static object * actuator_addact(self, args) actuatorobject *self; object *args; { Panel *p; if (!is_panelobject(args)) { err_badarg(); return NULL; } p = ((panelobject *)args) -> ob_panel; pnl_addact(self->ob_actuator, p); INCREF(None); return None; } static object * actuator_addsubact(self, args) actuatorobject *self; object *args; { Actuator *a; if (!is_actuatorobject(args)) { err_badarg(); return NULL; } a = ((actuatorobject *)args) -> ob_actuator; pnl_addsubact(self->ob_actuator, a); INCREF(None); return None; } static object * actuator_delact(self, args) actuatorobject *self; object *args; { Panel *p; if (!getnoarg(args)) return NULL; pnl_delact(self->ob_actuator); INCREF(None); return None; } static object * actuator_fixact(self, args) actuatorobject *self; object *args; { Panel *p; if (!getnoarg(args)) return NULL; pnl_fixact(self->ob_actuator); INCREF(None); return None; } static object * actuator_tprint(self, args) actuatorobject *self; object *args; { object *str; if (self->ob_actuator->type != PNL_TYPEOUT) { err_setstr(TypeError, "tprint for non-typeout panel"); return NULL; } if (!getstrarg(args, &str)) return NULL; tprint(self->ob_actuator, getstringvalue(str)); /* XXX Can't turn tprint's errors into exceptions, sorry */ INCREF(None); return None; } static struct methodlist actuator_methods[] = { {"addact", actuator_addact}, {"addsubact", actuator_addsubact}, {"delact", actuator_delact}, {"fixact", actuator_fixact}, {"tprint", actuator_tprint}, {NULL, NULL} /* sentinel */ }; static object * newactuatorobject(act) Actuator *act; { actuatorobject *a; if (act == NULL) { INCREF(None); return None; } a = NEWOBJ(actuatorobject, &Actuatortype); if (a == NULL) return NULL; a->ob_actuator = act; return (object *)a; } static void actuator_dealloc(a) actuatorobject *a; { /* Do NOT delete the actuator; most actuator objects are created to hold a temporary reference to an actuator, like one gotten from pnl_dopanel(). */ DEL(a); } /* Table of actuator members */ #define ACTOFF(member) offsetof(Actuator, member) struct memberlist act_memberlist[] = { {"id", T_SHORT, ACTOFF(id), READONLY}, /* T_PANEL is not defined */ /* {"p", T_PANEL, ACTOFF(p), READONLY}, */ {"pa", T_ACTUATOR, ACTOFF(pa), READONLY}, {"ca", T_ACTUATOR, ACTOFF(ca), READONLY}, {"al", T_ACTUATOR, ACTOFF(al), READONLY}, {"na", T_INT, ACTOFF(na), READONLY}, {"type", T_INT, ACTOFF(type), READONLY}, {"active", T_BOOL, ACTOFF(active)}, {"x", T_COORD, ACTOFF(x)}, {"y", T_COORD, ACTOFF(y)}, {"w", T_COORD, ACTOFF(w)}, {"h", T_COORD, ACTOFF(h)}, {"lx", T_COORD, ACTOFF(lx)}, {"ly", T_COORD, ACTOFF(ly)}, {"lw", T_COORD, ACTOFF(lw)}, {"lh", T_COORD, ACTOFF(lh)}, {"ld", T_COORD, ACTOFF(ld)}, {"val", T_FLOAT, ACTOFF(val)}, {"extval", T_FLOAT, ACTOFF(extval)}, {"initval", T_FLOAT, ACTOFF(initval)}, {"maxval", T_FLOAT, ACTOFF(maxval)}, {"minval", T_FLOAT, ACTOFF(minval)}, {"scalefactor", T_FLOAT, ACTOFF(scalefactor)}, {"label", T_STRING, ACTOFF(label)}, {"key", T_DEVICE, ACTOFF(key)}, {"labeltype", T_INT, ACTOFF(labeltype)}, /* Internal callbacks are not supported; user callbacks are treated special! */ {"dirtycnt", T_INT, ACTOFF(dirtycnt)}, /* members u and data are accessed differently */ {"automatic", T_BOOL, ACTOFF(automatic)}, {"selectable", T_BOOL, ACTOFF(selectable)}, {"visible", T_BOOL, ACTOFF(visible)}, {"beveled", T_BOOL, ACTOFF(beveled)}, {"group", T_ACTUATOR, ACTOFF(group), READONLY}, {"next", T_ACTUATOR, ACTOFF(next), READONLY}, {NULL, 0, 0} /* Sentinel */ }; /* Potential name conflicts between attributes are solved as follows. - Actuator-specific attributes always override generic attributes. - When reading, the dictionary has overrides everything else; when writing, everything else overrides the dictionary. - When reading, methods are tried last. */ static object * actuator_getattr(a, name) actuatorobject *a; char *name; { Actuator *act = a->ob_actuator; struct userdata *u = (struct userdata *) act->u; object *v; if (u != NULL) { /* 1. Try the dictionary */ if (u->dict != NULL) { v = dictlookup(u->dict, name); if (v != NULL) { INCREF(v); return v; } } /* 2. Try actuator-specific attributes */ if (u->spec != NULL) { v = panel_getmember(act->data, u->spec, name); if (v != NULL) return v; err_clear(); } } /* 3. Try generic actuator attributes */ v = panel_getmember((char *)act, act_memberlist, name); if (v != NULL) return v; /* 4. Try methods */ err_clear(); return findmethod(actuator_methods, (object *)a, name); } static int actuator_setattr(a, name, v) actuatorobject *a; char *name; object *v; { Actuator *act = a->ob_actuator; struct userdata *u = (struct userdata *) act->u; int err; /* 0. We don't allow deletion of attributes */ if (v == NULL) { err_setstr(TypeError, "read-only actuator attribute"); return -1; } /* 1. Try actuator-specific attributes */ if (u != NULL && u->spec != NULL) { err = panel_setmember(act->data, u->spec, name, v); if (err != 1) return err; } /* 2. Try generic actuator attributes */ err = panel_setmember((char *)act, act_memberlist, name, v); if (err != 1) return err; /* 3. Try the dictionary */ if (u != NULL) { if (u->dict == NULL && (u->dict = newdictobject()) == NULL) return NULL; return dictinsert(u->dict, name, v); } err_setstr(NameError, name); return -1; } static int actuator_compare(v, w) actuatorobject *v, *w; { long i = (long)v->ob_actuator; long j = (long)w->ob_actuator; return (i < j) ? -1 : (i > j) ? 1 : 0; } static typeobject Actuatortype = { OB_HEAD_INIT(&Typetype) 0, /*ob_size*/ "actuator", /*tp_name*/ sizeof(actuatorobject), /*tp_size*/ 0, /*tp_itemsize*/ /* methods */ actuator_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ actuator_getattr, /*tp_getattr*/ actuator_setattr, /*tp_setattr*/ actuator_compare, /*tp_compare*/ 0, /*tp_repr*/ }; /* The panel module itself */ static object * module_mkpanel(self, args) object *self; object *args; { if (!getnoarg(args)) return NULL; return newpanelobject(); } static object * module_mkact(self, args) object *self; object *args; { object *v; Actuator *a; if (!getstrarg(args, &v)) return NULL; a = makeactuator(getstringvalue(v)); if (a == NULL) return NULL; return newactuatorobject(a); } static object * module_dopanel(self, args) object *self; object *args; { Actuator *a; object *v, *w; if (!getnoarg(args)) return NULL; a = pnl_dopanel(); v = newtupleobject(4); if (v == NULL) return NULL; settupleitem(v, 0, newactuatorobject(a)); settupleitem(v, 1, newactuatorobject(down_pend)); settupleitem(v, 2, newactuatorobject(active_pend)); settupleitem(v, 3, newactuatorobject(up_pend)); down_pend = active_pend = up_pend = NULL; return v; } static object * module_drawpanel(self, args) object *self; object *args; { if (!getnoarg(args)) return NULL; pnl_drawpanel(); INCREF(None); return None; } static object * module_needredraw(self, args) object *self; object *args; { if (!getnoarg(args)) return NULL; pnl_needredraw(); INCREF(None); return None; } static object * module_userredraw(self, args) object *self; object *args; { short wid; if (!getnoarg(args)) return NULL; wid = pnl_userredraw(); return newintobject((long)wid); } static object * module_block(self, args) object *self; object *args; { int flag; if (!getintarg(args, &flag)) return NULL; pnl_block = flag; INCREF(None); return None; } static struct methodlist module_methods[] = { {"block", module_block}, {"dopanel", module_dopanel}, {"drawpanel", module_drawpanel}, {"mkpanel", module_mkpanel}, {"mkact", module_mkact}, {"needredraw", module_needredraw}, {"userredraw", module_userredraw}, {NULL, NULL} /* sentinel */ }; void initpanel() { /* Setting pnl_block to 1 would greatly reduce the CPU usage of an idle application. Unfortunately it also breaks our little hacks to get callback functions in Python called. So we clear pnl_block here. You can set/clear pnl_block from Python using pnl.block(flag). It works if you have no upfuncs. */ pnl_block = 0; initmodule("pnl", module_methods); }