From 30fb06bce3c76c7f37d8649aa33927f38ed194a9 Mon Sep 17 00:00:00 2001 From: mescalinum Date: Fri, 28 Oct 2011 19:25:27 +0000 Subject: add open menu svn path=/trunk/externals/loaders/tclpd/; revision=15671 --- Makefile | 3 ++- hashtable.c | 17 ++++++++++++++--- hashtable.h | 5 +++-- tcl_class.c | 26 ++++++++++++++++++++++++++ tcl_extras.h | 7 ++++++- tcl_loader.c | 11 ++++++++--- 6 files changed, 59 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 7b64039..f9a1893 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,8 @@ EXTRA_DIST = tcl.i tcl_extras.h tclpd.tcl $(TCLPD_SOURCES) ChangeLog.txt AUTHORS ALL_CFLAGS = $(PD_INCLUDES) -std=c99 -I/usr/include/tcl8.5 \ -I/Library/Frameworks/Tcl.framework/Headers \ - -Wall -W -Wno-unused-parameter + -Wall -W -Wno-unused-parameter \ + -DHASHTABLE_COPY_KEYS ALL_LDFLAGS = SHARED_LDFLAGS = ALL_LIBS = diff --git a/hashtable.c b/hashtable.c index 0b4409f..c2fa96f 100644 --- a/hashtable.c +++ b/hashtable.c @@ -15,19 +15,27 @@ uint32_t hash_str(const char *s) { list_node_t* list_add(list_node_t* head, const char* k, void* v) { list_node_t* n = (list_node_t*)malloc(sizeof(list_node_t)); n->next = head; +#ifdef HASHTABLE_COPY_KEYS n->k = strdup(k); +#else + n->k = k; +#endif n->v = v; return n; } list_node_t* list_remove(list_node_t* head, const char* k) { + if(!head) return NULL; + list_node_t* tmp; // head remove while(head && strcmp(head->k, k) == 0) { tmp = head; head = head->next; +#ifdef HASHTABLE_COPY_KEYS free(tmp->k); +#endif free(tmp); } @@ -39,6 +47,9 @@ list_node_t* list_remove(list_node_t* head, const char* k) { { tmp = p->next; p->next = p->next->next; +#ifdef HASHTABLE_COPY_KEYS + free(tmp->k); +#endif free(tmp); continue; } @@ -48,14 +59,14 @@ list_node_t* list_remove(list_node_t* head, const char* k) { return head; } -void* list_get(list_node_t* head, const char* k) { +list_node_t* list_get(list_node_t* head, const char* k) { while(head) { if(strcmp(head->k, k) == 0) { - return head->v; + return head; } head = head->next; } - return (void*)0; + return NULL; } size_t list_length(list_node_t* head) { diff --git a/hashtable.h b/hashtable.h index 0baca4c..f2d1a4a 100644 --- a/hashtable.h +++ b/hashtable.h @@ -19,7 +19,7 @@ typedef struct hash_table { uint32_t hash_str(const char *s); list_node_t* list_add(list_node_t* head, const char* k, void* v); list_node_t* list_remove(list_node_t* head, const char* k); -void* list_get(list_node_t* head, const char* k); +list_node_t* list_get(list_node_t* head, const char* k); size_t list_length(list_node_t* head); hash_table_t* hashtable_new(size_t size); @@ -37,7 +37,8 @@ static inline void hashtable_remove(hash_table_t* ht, const char* name) { static inline void* hashtable_get(hash_table_t* ht, const char* name) { uint32_t h = hash_str(name) % ht->sz; - return list_get(ht->t[h], name); + list_node_t* n = list_get(ht->t[h], name); + return n ? n->v : NULL; } #endif // HASHTABLE_H_INCLUDED diff --git a/tcl_class.c b/tcl_class.c index 08fe2e6..596e28d 100644 --- a/tcl_class.c +++ b/tcl_class.c @@ -6,6 +6,7 @@ static hash_table_t* class_table = NULL; static hash_table_t* object_table = NULL; +static hash_table_t* source_table = NULL; #define class_table_add(n, c) hashtable_add(class_table, n, (void*)c) #define class_table_remove(n) hashtable_remove(class_table, n) @@ -32,6 +33,8 @@ t_class* tclpd_class_new(const char* name, int flags) { // is this really necessary given that there is already a 'anything' handler? class_addmethod(c, (t_method)tclpd_loadbang, gensym("loadbang"), A_NULL); + class_addmethod(c, (t_method)tclpd_open, gensym("menu-open"), A_NULL); + char buf[80]; Tcl_Obj* res; int res_i; @@ -80,6 +83,11 @@ t_tcl* tclpd_new(t_symbol* classsym, int ac, t_atom* at) { x->ninlets = 1 /* qlass->c_firstin ??? */; x->x_glist = (t_glist*)canvas_getcurrent(); + x->source_file = (char *)hashtable_get(source_table, name); + if(!x->source_file) { + post("tclpd: missing source file information. open command will not work."); + } + x->classname = Tcl_NewStringObj(name, -1); char so[64]; snprintf(so, 64, "tclpd.%s.x%lx", name, objectSequentialId++); @@ -224,6 +232,13 @@ void tclpd_loadbang(t_tcl* x) { tclpd_inlet_anything(x, 0, gensym("loadbang"), 0, NULL); } +void tclpd_open(t_tcl *x) { + if(!x->source_file) + return; + + sys_vgui("::pd_menucommands::menu_openfile {%s}\n", x->source_file); +} + /* Tcl glue: */ t_proxyinlet* tclpd_add_proxyinlet(t_tcl* x) { @@ -370,3 +385,14 @@ void tclpd_class_namespace_init(const char* classname) { classname, classname, classname); Tcl_Eval(tcl_for_pd, cmd); } + +void source_table_remove(const char *object_name) { + if(!source_table) + source_table = hashtable_new(1 << 7); + hashtable_remove(source_table, object_name); +} + +void source_table_add(const char *object_name, const char *source_file) { + source_table_remove(object_name); + hashtable_add(source_table, object_name, strdup(source_file)); +} diff --git a/tcl_extras.h b/tcl_extras.h index 0f563a8..283816d 100644 --- a/tcl_extras.h +++ b/tcl_extras.h @@ -16,11 +16,15 @@ typedef struct _t_tcl { t_object o; + int ninlets; t_glist* x_glist; + + char *source_file; + + // Tcl-interpreter related objects: Tcl_Obj* self; Tcl_Obj* classname; Tcl_Obj* dispatcher; - int ninlets; } t_tcl; typedef struct _t_proxyinlet { @@ -65,6 +69,7 @@ void tclpd_free (t_tcl* self); 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); void tclpd_loadbang(t_tcl* x); +void tclpd_open(t_tcl* x); t_proxyinlet* tclpd_add_proxyinlet(t_tcl* x); t_tcl* tclpd_get_instance(const char* objectSequentialId); t_pd* tclpd_get_instance_pd(const char* objectSequentialId); diff --git a/tcl_loader.c b/tcl_loader.c index 0766a8c..5167cec 100644 --- a/tcl_loader.c +++ b/tcl_loader.c @@ -2,6 +2,10 @@ #include #include +/* from tcl_class.c: */ +//void source_table_remove(const char *object_name); +void source_table_add(const char *object_name, const char *source_path); + extern int tclpd_do_load_lib(t_canvas *canvas, char *objectname) { #ifdef DEBUG post("Tcl loader: registering tcl class loader mechanism"); @@ -20,12 +24,12 @@ extern int tclpd_do_load_lib(t_canvas *canvas, char *objectname) { return (1); } - /* try looking in the path for (objectname).(tcl) ... */ + /* try looking in the path for (objectname).(tcl) ... */ if ((fd = canvas_open(canvas, objectname, ".tcl", dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) goto gotone; - /* next try (objectname)/(classname).(tcl) ... */ + /* next try (objectname)/(classname).(tcl) ... */ strncpy(filename, objectname, MAXPDSTRING); filename[MAXPDSTRING-2] = 0; strcat(filename, "/"); @@ -40,7 +44,7 @@ extern int tclpd_do_load_lib(t_canvas *canvas, char *objectname) { gotone: close(fd); class_set_extern_dir(gensym(dirbuf)); - /* rebuild the absolute pathname */ + /* rebuild the absolute pathname */ strncpy(filename, dirbuf, MAXPDSTRING); filename[MAXPDSTRING-2] = 0; strcat(filename, "/"); @@ -55,6 +59,7 @@ gotone: // load tcl external: result = Tcl_EvalFile(tcl_for_pd, filename); if(result == TCL_OK) { + source_table_add(objectname, filename); post("Tcl loader: loaded %s", filename); } else { post("Tcl loader: error trying to load %s", filename); -- cgit v1.2.1