diff options
-rw-r--r-- | tcl_class.cxx | 75 | ||||
-rw-r--r-- | tcl_extras.h | 2 | ||||
-rw-r--r-- | tcl_widgetbehavior.cxx | 34 |
3 files changed, 87 insertions, 24 deletions
diff --git a/tcl_class.cxx b/tcl_class.cxx index bd583a9..01aebaf 100644 --- a/tcl_class.cxx +++ b/tcl_class.cxx @@ -37,35 +37,56 @@ t_class* tclpd_guiclass_new(const char* name, int flags) { } t_tcl* tclpd_new(t_symbol* classsym, int ac, t_atom* at) { + // lookup in class table const char* name = classsym->s_name; t_class* qlass = class_table[string(name)]; + t_tcl* self = (t_tcl*)pd_new(qlass); self->ninlets = 1 /* qlass->c_firstin ??? */; + char s[64]; snprintf(s, 64, "tclpd:%s:x%lx", name, objectSequentialId++); self->self = Tcl_NewStringObj(s, -1); Tcl_IncrRefCount(self->self); + + // store in object table (for later lookup) object_table[string(s)] = (t_pd*)self; - Tcl_Obj *av[ac+2]; + + // build constructor command + Tcl_Obj *av[ac+2]; InitArray(av, ac+2, NULL); av[0] = Tcl_NewStringObj(name, -1); Tcl_IncrRefCount(av[0]); av[1] = self->self; + Tcl_IncrRefCount(av[1]); for(int i=0; i<ac; i++) { if(pd_to_tcl(&at[i], &av[2+i]) == TCL_ERROR) { - tclpd_interp_error(TCL_ERROR); - pd_free((t_pd*)self); - return 0; +#ifdef DEBUG + post("pd_to_tcl: tclpd_new: failed during conversion. check memory leaks!"); +#endif + goto error; } } if(Tcl_EvalObjv(tcl_for_pd, ac+2, av, 0) != TCL_OK) { - tclpd_interp_error(TCL_ERROR); - pd_free((t_pd*)self); - return 0; + goto error; } + + for(int i = 0; i < (ac+2); i++) + Tcl_DecrRefCount(av[i]); + return self; + +error: + tclpd_interp_error(TCL_ERROR); + for(int i = 0; i < (ac+2); i++) { + if(!av[i]) break; + Tcl_DecrRefCount(av[i]); + } + pd_free((t_pd*)self); + return 0; } void tclpd_free(t_tcl* self) { + Tcl_DecrRefCount(self->self); #ifdef DEBUG post("tclpd_free called"); #endif @@ -76,25 +97,42 @@ void tclpd_anything(t_tcl* self, t_symbol* s, int ac, t_atom* at) { } void tclpd_inlet_anything(t_tcl* self, int inlet, t_symbol* s, int ac, t_atom* at) { -/* proxy method */ - Tcl_Obj* av[ac+3]; + // proxy method - format: <self> <inlet#> <selector> ... + Tcl_Obj* av[ac+3]; InitArray(av, ac+3, NULL); + int result; + av[0] = self->self; + Tcl_IncrRefCount(av[0]); av[1] = Tcl_NewIntObj(inlet); Tcl_IncrRefCount(av[1]); av[2] = Tcl_NewStringObj(s->s_name, -1); Tcl_IncrRefCount(av[2]); for(int i=0; i<ac; i++) { if(pd_to_tcl(&at[i], &av[3+i]) == TCL_ERROR) { - tclpd_interp_error(TCL_ERROR); - return; +#ifdef DEBUG + post("pd_to_tcl: tclpd_inlet_anything: failed during conversion. check memory leaks!"); +#endif + goto error; } } - int result = Tcl_EvalObjv(tcl_for_pd, ac+3, av, 0); - Tcl_DecrRefCount(av[1]); - Tcl_DecrRefCount(av[2]); + result = Tcl_EvalObjv(tcl_for_pd, ac+3, av, 0); if(result != TCL_OK) { - tclpd_interp_error(TCL_ERROR); + goto error; + } + + for(int i=0; i < (ac+3); i++) + Tcl_DecrRefCount(av[i]); + + // OK + return; + +error: + tclpd_interp_error(TCL_ERROR); + for(int i=0; i < (ac+3); i++) { + if(!av[i]) break; + Tcl_DecrRefCount(av[i]); } + return; } /* Tcl glue: */ @@ -127,9 +165,13 @@ void poststring2 (const char *s) { } void tclpd_save(t_gobj* z, t_binbuf* b) { - Tcl_Obj* av[3], *res; + Tcl_Obj* av[3]; InitArray(av, 3, NULL); + Tcl_Obj* res; + t_tcl* x = (t_tcl*)z; + av[0] = x->self; + Tcl_IncrRefCount(av[0]); av[1] = Tcl_NewStringObj("object", -1); Tcl_IncrRefCount(av[1]); av[2] = Tcl_NewStringObj("save", -1); @@ -172,6 +214,7 @@ void tclpd_save(t_gobj* z, t_binbuf* b) { pd_error(x, "Tcl: object save: failed"); tclpd_interp_error(result); } + Tcl_DecrRefCount(av[0]); Tcl_DecrRefCount(av[1]); Tcl_DecrRefCount(av[2]); } diff --git a/tcl_extras.h b/tcl_extras.h index 6d52989..9bca803 100644 --- a/tcl_extras.h +++ b/tcl_extras.h @@ -12,6 +12,8 @@ #define TCLPD_VERSION "0.2" +#define InitArray(name, size, value) for(int zz=0; zz<(size); zz++) name[zz]=value + typedef struct _t_tcl { t_object o; Tcl_Obj* self; diff --git a/tcl_widgetbehavior.cxx b/tcl_widgetbehavior.cxx index 55634d5..8167803 100644 --- a/tcl_widgetbehavior.cxx +++ b/tcl_widgetbehavior.cxx @@ -2,10 +2,12 @@ #include <string.h> int tclpd_guiclass_click(t_gobj* z, t_glist* glist, int xpix, int ypix, int shift, int alt, int dbl, int doit) { - Tcl_Obj* av[9], *o = NULL; + Tcl_Obj* av[9]; InitArray(av, 9, NULL); + Tcl_Obj* o = NULL; int i = 0; t_tcl* x = (t_tcl*)z; av[0] = x->self; + Tcl_IncrRefCount(av[0]); av[1] = Tcl_NewStringObj("widgetbehavior", -1); Tcl_IncrRefCount(av[1]); av[2] = Tcl_NewStringObj("click", -1); @@ -24,7 +26,6 @@ int tclpd_guiclass_click(t_gobj* z, t_glist* glist, int xpix, int ypix, int shif Tcl_IncrRefCount(av[8]); int result = Tcl_EvalObjv(tcl_for_pd, 9, av, 0); if(result != TCL_OK) { - tclpd_interp_error(result); goto error; } o = Tcl_GetObjResult(tcl_for_pd); @@ -32,14 +33,17 @@ int tclpd_guiclass_click(t_gobj* z, t_glist* glist, int xpix, int ypix, int shif if(strlen(Tcl_GetStringFromObj(o, NULL)) > 0) { result = Tcl_GetIntFromObj(tcl_for_pd, o, &i); if(result != TCL_OK) { - tclpd_interp_error(result); goto error; } } goto cleanup; + error: + tclpd_interp_error(result); + cleanup: if(o) Tcl_DecrRefCount(o); + Tcl_DecrRefCount(av[0]); Tcl_DecrRefCount(av[1]); Tcl_DecrRefCount(av[2]); Tcl_DecrRefCount(av[3]); @@ -52,10 +56,13 @@ cleanup: } void tclpd_guiclass_getrect(t_gobj* z, t_glist* owner, int* xp1, int* yp1, int* xp2, int* yp2) { - Tcl_Obj* av[5], *o, *theList = NULL; + Tcl_Obj* av[5]; InitArray(av, 5, NULL); + Tcl_Obj* o; + Tcl_Obj* theList = NULL; int tmp[4], i, length; t_tcl* x = (t_tcl*)z; av[0] = x->self; + Tcl_IncrRefCount(av[0]); av[1] = Tcl_NewStringObj("widgetbehavior", -1); Tcl_IncrRefCount(av[1]); av[2] = Tcl_NewStringObj("getrect", -1); @@ -100,6 +107,7 @@ void tclpd_guiclass_getrect(t_gobj* z, t_glist* owner, int* xp1, int* yp1, int* error: cleanup: if(theList) Tcl_DecrRefCount(theList); + Tcl_DecrRefCount(av[0]); Tcl_DecrRefCount(av[1]); Tcl_DecrRefCount(av[2]); Tcl_DecrRefCount(av[3]); @@ -107,10 +115,13 @@ cleanup: } void tclpd_guiclass_displace(t_gobj* z, t_glist* glist, int dx, int dy) { - Tcl_Obj* av[5], *theList = NULL, *o; + Tcl_Obj* av[5]; InitArray(av, 5, NULL); + Tcl_Obj* theList = NULL; + Tcl_Obj* o; int length, i, tmp[2]; t_tcl* x = (t_tcl*)z; av[0] = x->self; + Tcl_IncrRefCount(av[0]); av[1] = Tcl_NewStringObj("widgetbehavior", -1); Tcl_IncrRefCount(av[1]); av[2] = Tcl_NewStringObj("displace", -1); @@ -157,6 +168,7 @@ void tclpd_guiclass_displace(t_gobj* z, t_glist* glist, int dx, int dy) { error: cleanup: if(theList) Tcl_DecrRefCount(theList); + Tcl_DecrRefCount(av[0]); Tcl_DecrRefCount(av[1]); Tcl_DecrRefCount(av[2]); Tcl_DecrRefCount(av[3]); @@ -164,9 +176,10 @@ cleanup: } void tclpd_guiclass_select(t_gobj* z, t_glist* glist, int selected) { - Tcl_Obj* av[4]; + Tcl_Obj* av[4]; InitArray(av, 4, NULL); t_tcl* x = (t_tcl*)z; av[0] = x->self; + Tcl_IncrRefCount(av[0]); av[1] = Tcl_NewStringObj("widgetbehavior", -1); Tcl_IncrRefCount(av[1]); av[2] = Tcl_NewStringObj("select", -1); @@ -181,15 +194,17 @@ void tclpd_guiclass_select(t_gobj* z, t_glist* glist, int selected) { goto cleanup; error: cleanup: + Tcl_DecrRefCount(av[0]); Tcl_DecrRefCount(av[1]); Tcl_DecrRefCount(av[2]); Tcl_DecrRefCount(av[3]); } void tclpd_guiclass_activate(t_gobj* z, t_glist* glist, int state) { - Tcl_Obj* av[4]; + Tcl_Obj* av[4]; InitArray(av, 4, NULL); t_tcl* x = (t_tcl*)z; av[0] = x->self; + Tcl_IncrRefCount(av[0]); av[1] = Tcl_NewStringObj("widgetbehavior", -1); Tcl_IncrRefCount(av[1]); av[2] = Tcl_NewStringObj("activate", -1); @@ -204,6 +219,7 @@ void tclpd_guiclass_activate(t_gobj* z, t_glist* glist, int state) { goto cleanup; error: cleanup: + Tcl_DecrRefCount(av[0]); Tcl_DecrRefCount(av[1]); Tcl_DecrRefCount(av[2]); Tcl_DecrRefCount(av[3]); @@ -215,9 +231,10 @@ void tclpd_guiclass_delete(t_gobj* z, t_glist* glist) { } void tclpd_guiclass_vis(t_gobj* z, t_glist* glist, int vis) { - Tcl_Obj* av[7]; + Tcl_Obj* av[7]; InitArray(av, 7, NULL); t_tcl* x = (t_tcl*)z; av[0] = x->self; + Tcl_IncrRefCount(av[0]); av[1] = Tcl_NewStringObj("widgetbehavior", -1); Tcl_IncrRefCount(av[1]); av[2] = Tcl_NewStringObj("vis", -1); @@ -240,6 +257,7 @@ void tclpd_guiclass_vis(t_gobj* z, t_glist* glist, int vis) { goto cleanup; error: cleanup: + Tcl_DecrRefCount(av[0]); Tcl_DecrRefCount(av[1]); Tcl_DecrRefCount(av[2]); Tcl_DecrRefCount(av[3]); |