diff options
author | N.N. <krzyszcz@users.sourceforge.net> | 2005-03-12 00:19:13 +0000 |
---|---|---|
committer | N.N. <krzyszcz@users.sourceforge.net> | 2005-03-12 00:19:13 +0000 |
commit | 3573488ef227bd7719eae892c72784cace95ffd4 (patch) | |
tree | 025299aeb3ad4574da705d836a396483cab229be | |
parent | 1eef182b31a4cb2f55e26e7527469fc2902368a3 (diff) |
cyclone alpha54 and toxy alpha16 (see notes.txt for cyclone, toxy and shared)
svn path=/trunk/externals/miXed/; revision=2618
-rw-r--r-- | cyclone/Makefile.sources | 2 | ||||
-rw-r--r-- | cyclone/build_counter | 4 | ||||
-rw-r--r-- | cyclone/hammer/comment.c | 69 | ||||
-rw-r--r-- | cyclone/hammer/seq.c | 1 | ||||
-rw-r--r-- | cyclone/hammer/testmess.c | 158 | ||||
-rw-r--r-- | cyclone/notes.txt | 8 | ||||
-rw-r--r-- | shared/common/loud.c | 8 | ||||
-rw-r--r-- | shared/common/loud.h | 1 | ||||
-rw-r--r-- | shared/common/props.c | 487 | ||||
-rw-r--r-- | shared/common/props.h | 20 | ||||
-rw-r--r-- | shared/getridof.baddeps | 2 | ||||
-rw-r--r-- | shared/hammer/file.c | 26 | ||||
-rw-r--r-- | shared/notes.txt | 11 | ||||
-rw-r--r-- | shared/toxy/scriptlet.c | 5 | ||||
-rw-r--r-- | shared/unstable/fragile.c | 11 | ||||
-rw-r--r-- | shared/unstable/fragile.h | 1 | ||||
-rw-r--r-- | test/toxy/lbpict.wid | 4 | ||||
-rw-r--r-- | test/toxy/setup.wid | 8 | ||||
-rw-r--r-- | test/toxy/stress/bulkyhurd.pd | 163 | ||||
-rw-r--r-- | test/toxy/stress/mstots.pd | 50 | ||||
-rw-r--r-- | test/toxy/stress/nbulkyhurds.pd | 16 | ||||
-rw-r--r-- | toxy/build_counter | 4 | ||||
-rw-r--r-- | toxy/notes.txt | 16 | ||||
-rw-r--r-- | toxy/tot.c | 148 | ||||
-rw-r--r-- | toxy/widget.c | 474 | ||||
-rw-r--r-- | toxy/widgettype.c | 39 |
26 files changed, 1215 insertions, 521 deletions
diff --git a/cyclone/Makefile.sources b/cyclone/Makefile.sources index 2ec02fc..96d3007 100644 --- a/cyclone/Makefile.sources +++ b/cyclone/Makefile.sources @@ -5,7 +5,6 @@ TYPES = HPLAIN HLOUD HFITTER HFORKY HFRAGILE HGROW HGROWFITTER \ SGROW SGROWCLC SGROWFORKY SVEFL SARSIC SARSICFITTER SFILE HPLAIN_SOURCES = \ -hammer/testmess.c \ hammer/accum.c \ hammer/acos.c \ hammer/asin.c \ @@ -61,6 +60,7 @@ hammer/comment.c HFRAGILE_SOURCES = \ hammer/grab.c \ +hammer/testmess.c \ hammer/universal.c HGROW_SOURCES = \ diff --git a/cyclone/build_counter b/cyclone/build_counter index a0a93b7..5a0c15d 100644 --- a/cyclone/build_counter +++ b/cyclone/build_counter @@ -1,7 +1,7 @@ #define CYCLONE_VERSION "0.1" #define CYCLONE_RELEASE "alpha" -#define CYCLONE_BUILD 53 +#define CYCLONE_BUILD 54 #if 0 -CYCLONE_SNAPSHOT = 0.1-alpha53 +CYCLONE_SNAPSHOT = 0.1-alpha54 #endif diff --git a/cyclone/hammer/comment.c b/cyclone/hammer/comment.c index 8f885a6..6a52bb8 100644 --- a/cyclone/hammer/comment.c +++ b/cyclone/hammer/comment.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2004 krzYszcz and others. +/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ @@ -77,7 +77,7 @@ static void comment_draw(t_comment *x) { char buf[COMMENT_OUTBUFSIZE], *outbuf, *outp; int cvid = (int)x->x_canvas; - int reqsize = x->x_textbufsize + 350; /* FIXME estimation */ + int reqsize = x->x_textbufsize + 250; /* FIXME estimation */ if (reqsize > COMMENT_OUTBUFSIZE) { #ifdef COMMENT_DEBUG @@ -88,30 +88,15 @@ static void comment_draw(t_comment *x) } else outbuf = buf; outp = outbuf; - if (x->x_encoding) - sprintf(outp, "set tt [comment_entext %s {%.*s}]\n", - x->x_encoding->s_name, x->x_textbufsize, x->x_textbuf); - else - sprintf(outp, "set tt {%.*s}\n", x->x_textbufsize, x->x_textbuf); - outp += strlen(outp); - sprintf(outp, ".x%x.c create text %f %f -text $tt \ - -tags {%s %s} -font {%s %d} -fill %s", cvid, + sprintf(outp, "comment_draw %s .x%x.c %s %s %f %f %s %d %s %s {%.*s} %d\n", + x->x_bindsym->s_name, cvid, x->x_texttag, x->x_tag, (float)(text_xpix((t_text *)x, x->x_glist) + COMMENT_LMARGIN), (float)(text_ypix((t_text *)x, x->x_glist) + COMMENT_TMARGIN), - x->x_texttag, x->x_tag, x->x_fontfamily->s_name, x->x_fontsize, + x->x_fontfamily->s_name, x->x_fontsize, (glist_isselected(x->x_glist, &x->x_glist->gl_gobj) ? - "blue" : x->x_color)); - outp += strlen(outp); - if (x->x_pixwidth) - sprintf(outp, " -width %d -anchor nw\n", x->x_pixwidth); - else - strcpy(outp, " -anchor nw\n"); - outp += strlen(outp); - sprintf(outp, "comment_bbox %s .x%x.c %s\n", - x->x_bindsym->s_name, cvid, x->x_texttag); - outp += strlen(outp); - sprintf(outp, ".x%x.c bind %s <Button> {comment_click %s %%W %%x %%y %s}\n", - cvid, x->x_texttag, x->x_bindsym->s_name, x->x_texttag); + "blue" : x->x_color), + (x->x_encoding ? x->x_encoding->s_name : "\"\""), + x->x_textbufsize, x->x_textbuf, x->x_pixwidth); x->x_bbpending = 1; sys_gui(outbuf); if (outbuf != buf) freebytes(outbuf, reqsize); @@ -132,17 +117,9 @@ static void comment_update(t_comment *x) } else outbuf = buf; outp = outbuf; - if (x->x_encoding) - sprintf(outp, "set tt [comment_entext %s {%.*s}]\n", - x->x_encoding->s_name, x->x_textbufsize, x->x_textbuf); - else - sprintf(outp, "set tt {%.*s}\n", x->x_textbufsize, x->x_textbuf); - outp += strlen(outp); - if (x->x_pixwidth) - sprintf(outp, ".x%x.c itemconfig %s -text $tt -width %d\n", - cvid, x->x_texttag, x->x_pixwidth); - else - sprintf(outp, ".x%x.c itemconfig %s -text $tt\n", cvid, x->x_texttag); + sprintf(outp, "comment_update .x%x.c %s %s {%.*s} %d\n", cvid, + x->x_texttag, (x->x_encoding ? x->x_encoding->s_name : "\"\""), + x->x_textbufsize, x->x_textbuf, x->x_pixwidth); outp += strlen(outp); if (x->x_active) { @@ -846,8 +823,24 @@ void comment_setup(void) /* LATER think how to conditionally (FORKY_VERSION >= 38) replace puts with pdtk_post */ sys_gui("proc comment_entext {enc tt} {\n\ - set rr [catch {encoding convertfrom $enc $tt} tt1]\n\ - if {$rr == 0} {concat $tt1} else {\n\ - puts stderr [concat tcl/tk error: $tt1]\n\ - concat $tt}}\n"); + if {$enc == \"\"} {concat $tt} else {\n\ + set rr [catch {encoding convertfrom $enc $tt} tt1]\n\ + if {$rr == 0} {concat $tt1} else {\n\ + puts stderr [concat tcl/tk error: $tt1]\n\ + concat $tt}}}\n"); + + sys_gui("proc comment_draw {tgt cv tag1 tag2 x y fnm fsz clr enc tt wd} {\n\ + set tt1 [comment_entext $enc $tt]\n\ + if {$wd > 0} {\n\ + $cv create text $x $y -text $tt1 -tags [list $tag1 $tag2] \ + -font [list $fnm $fsz] -fill $clr -width $wd -anchor nw} else {\n\ + $cv create text $x $y -text $tt1 -tags [list $tag1 $tag2] \ + -font [list $fnm $fsz] -fill $clr -anchor nw}\n\ + comment_bbox $tgt $cv $tag1\n\ + $cv bind $tag1 <Button> [list comment_click $tgt %W %x %y $tag1]}\n"); + + sys_gui("proc comment_update {cv tag enc tt wd} {\n\ + set tt1 [comment_entext $enc $tt]\n\ + if {$wd > 0} {$cv itemconfig $tag -text $tt1 -width $wd} else {\n\ + $cv itemconfig $tag -text $tt1}}\n"); } diff --git a/cyclone/hammer/seq.c b/cyclone/hammer/seq.c index 26027c0..38b0769 100644 --- a/cyclone/hammer/seq.c +++ b/cyclone/hammer/seq.c @@ -861,6 +861,7 @@ mfwritefailed: } /* CHECKED text file input: absolute timestamps, semi-terminated, verified */ +/* FIXME prevent loading .pd files... */ static int seq_fromatoms(t_seq *x, int ac, t_atom *av, int abstime) { int i, nevents = 0; diff --git a/cyclone/hammer/testmess.c b/cyclone/hammer/testmess.c index a6e8fe4..862e0f1 100644 --- a/cyclone/hammer/testmess.c +++ b/cyclone/hammer/testmess.c @@ -1,9 +1,15 @@ -/* Copyright (c) 2002-2003 krzYszcz and others. +/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +#include <stdio.h> #include <string.h> #include "m_pd.h" +#include "unstable/fragile.h" + +#ifdef MSW +#define snprintf _snprintf +#endif #define TESTMESS_INISIZE 4 /* LATER rethink */ #define TESTMESS_STACKSIZE 256 @@ -183,49 +189,157 @@ static void testmess_anything(t_testmess *x, t_symbol *s, int ac, t_atom *av) x->x_messfun(x, s, ac, av); } -static void testmess_set(t_testmess *x, t_floatarg f1, t_floatarg f2) +static void testmess_setnumbers(t_testmess *x, int natoms, int start) { - int natoms = (int)f1; - if (natoms > 0 && testmess_makeroom(x, natoms * 2, 0)) + if (natoms <= 0) + natoms = 100; + if (testmess_makeroom(x, natoms * 2, 0)) { t_atom *ap; - int i = (int)f2;; testmess_setnatoms(x, natoms); ap = x->x_message; while (natoms--) { - SETFLOAT(ap, i); - i++; ap++; + SETFLOAT(ap, (t_float)start); + start++; ap++; } } } -static void testmess_free(t_testmess *x) +#define FRAGILE_HASHSIZE 1024 + +static int fragile_hash(t_symbol *s) { - if (x->x_messbuf != x->x_messini) - freebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf)); + unsigned int hash1 = 0, hash2 = 0; + char *ptr = s->s_name; + while (*ptr) + { + hash1 += *ptr++; + hash2 += hash1; + } + return (hash2 & (FRAGILE_HASHSIZE-1)); } -static void *testmess_new(t_symbol *s, t_floatarg f) +int fragile_symbol_count(void) { - t_testmess *x = (t_testmess *)pd_new(testmess_class); - x->x_appendmode = 1; - x->x_tailwise = 0; - if (s == gensym("stack")) - x->x_method = s, x->x_messfun = testmess_stackmess; - else if (s == gensym("heap")) - x->x_method = s, x->x_messfun = testmess_heapmess; + return (100); +} + +void fragile_getsymbols(t_atom *av) +{ + t_symbol *s = gensym("#N"); + int i; + for (i = 0, s -= fragile_hash(s); i < FRAGILE_HASHSIZE; i++, s++) + { + if (s->s_name) + { + t_symbol *s1; + for (s1 = s; s1; s1 = s1->s_next) + printf("%s\n", s1->s_name); + } + } +} + +static void testmess_setnames(t_testmess *x, t_symbol *s, + int natoms, int nchars) +{ + if (!s) + s = &s_; + if (*s->s_name == 'c') + { + natoms = fragile_class_count(); + if (natoms > 0 && testmess_makeroom(x, natoms * 2, 0)) + { + testmess_setnatoms(x, natoms); + fragile_class_getnames(x->x_message); + } + } + else + { + if (natoms <= 0) + natoms = 100; + if (nchars <= 0) + nchars = 10; + if (testmess_makeroom(x, natoms * 2, 0)) + { + char buf[MAXPDSTRING], fmt[16]; + int i = 0; + t_atom *ap; + testmess_setnatoms(x, natoms); + ap = x->x_message; + sprintf(fmt, "%%.%dx", nchars); + while (natoms--) + { + snprintf(buf, MAXPDSTRING-1, fmt, i); + SETSYMBOL(ap, gensym(buf)); + i++; ap++; + } + } + } +} + +static void testmess_set(t_testmess *x, t_symbol *s, int ac, t_atom *av) +{ + t_symbol *csym = 0, *msym = 0; + t_float f1 = 0., f2 = 0.; + if (ac) + { + if (av->a_type == A_SYMBOL) + csym = av->a_w.w_symbol; + else if (av->a_type == A_FLOAT) + f1 = av->a_w.w_float; + if (ac > 1) + { + if (av[1].a_type == A_SYMBOL) + msym = av[1].a_w.w_symbol; + else if (av[1].a_type == A_FLOAT) + { + if (csym) + f1 = av[1].a_w.w_float; + else + f2 = av[1].a_w.w_float; + if (ac > 2) + { + if (av[2].a_type == A_SYMBOL) + msym = av[2].a_w.w_symbol; + else if (csym && av[2].a_type == A_FLOAT) + f2 = av[2].a_w.w_float; + } + } + } + } + if (msym == gensym("stack")) + x->x_method = msym, x->x_messfun = testmess_stackmess; + else if (msym == gensym("heap")) + x->x_method = msym, x->x_messfun = testmess_heapmess; else { x->x_method = gensym("prealloc"); x->x_messfun = testmess_premess; x->x_tailwise = x->x_appendmode; } + testmess_setnatoms(x, 0); + if (csym) + testmess_setnames(x, csym, (int)f1, (int)f2); + else + testmess_setnumbers(x, (int)f1, (int)f2); +} + +static void testmess_free(t_testmess *x) +{ + if (x->x_messbuf != x->x_messini) + freebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf)); +} + +static void *testmess_new(t_symbol *s, int ac, t_atom *av) +{ + t_testmess *x = (t_testmess *)pd_new(testmess_class); + x->x_appendmode = 1; + x->x_tailwise = 0; x->x_size = TESTMESS_INISIZE; x->x_messbuf = x->x_messini; outlet_new((t_object *)x, &s_anything); - testmess_setnatoms(x, 0); - testmess_set(x, f, 0); + testmess_set(x, s, ac, av); return (x); } @@ -235,11 +349,11 @@ void testmess_setup(void) (t_newmethod)testmess_new, (t_method)testmess_free, sizeof(t_testmess), 0, - A_DEFFLOAT, A_DEFSYM, 0); + A_GIMME, 0); class_addbang(testmess_class, testmess_bang); class_addfloat(testmess_class, testmess_float); class_addsymbol(testmess_class, testmess_symbol); class_addanything(testmess_class, testmess_anything); class_addmethod(testmess_class, (t_method)testmess_set, - gensym("set"), A_FLOAT, A_DEFFLOAT, 0); + gensym("set"), A_GIMME, 0); } diff --git a/cyclone/notes.txt b/cyclone/notes.txt index 8b93d15..6c62f4c 100644 --- a/cyclone/notes.txt +++ b/cyclone/notes.txt @@ -1,10 +1,12 @@ TODO for cyclone - * using maxmode object arguments for abstraction-scoped, selective - compatibility control - * comment behaving better in windows (or is it gatom's fault?) DONE for cyclone +alpha54 + * comment: fixing namespace bug, reducing traffic + * testmess: optionally filling message with symbols (numbers in hex form + or names of all registered classes) + alpha53 * matrix~: incompatible message 'set' * coll: diff --git a/shared/common/loud.c b/shared/common/loud.c index d87d3c0..e1e921d 100644 --- a/shared/common/loud.c +++ b/shared/common/loud.c @@ -366,6 +366,14 @@ void loudbug_startpost(char *fmt, ...) #endif } +void loudbug_stringpost(char *s) +{ + fputs(s, stderr); +#ifdef MSW + fflush(stderr); +#endif +} + void loudbug_endpost(void) { fputs("\n", stderr); diff --git a/shared/common/loud.h b/shared/common/loud.h index 64388c1..297b9c1 100644 --- a/shared/common/loud.h +++ b/shared/common/loud.h @@ -45,6 +45,7 @@ t_loudcontext *loudx_newcontext(t_pd *caller, char *callername, void loudbug_post(char *fmt, ...); void loudbug_startpost(char *fmt, ...); +void loudbug_stringpost(char *s); void loudbug_endpost(void); void loudbug_postatom(int ac, t_atom *av); void loudbug_postbinbuf(t_binbuf *bb); diff --git a/shared/common/props.c b/shared/common/props.c index 4dfe113..4445bf2 100644 --- a/shared/common/props.c +++ b/shared/common/props.c @@ -1,9 +1,10 @@ -/* Copyright (c) 2003 krzYszcz and others. +/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include <string.h> #include "m_pd.h" +#include "common/loud.h" #include "common/grow.h" #include "props.h" @@ -12,9 +13,12 @@ #endif #define PROPS_INISIZE 32 /* LATER rethink */ -#define PROPS_MAXOTHERS 32 +#define PROPS_MAXMIXUPS 32 -enum { PROPS_NONE = 0, PROPS_THIS, PROPS_OTHER }; +/* return values of props_iskey() */ +enum { PROPS_NONE = 0, PROPS_THIS, PROPS_MIXUP }; + +/* 'mode' argument values of props_iskey() and props_update() */ enum { PROPS_SINGLEMODE = 0, PROPS_MULTIMODE }; typedef struct _propelem @@ -29,17 +33,18 @@ struct _props char p_thisescape; char *p_thisinitial; char *p_name; - int p_size; /* as allocated */ - int p_natoms; /* as used */ + int p_size; /* as allocated */ + int p_natoms; /* as used */ t_atom *p_buffer; t_atom p_bufini[PROPS_INISIZE]; + int p_nextindex; t_pd *p_owner; t_propsresolver p_resolver; t_propelem *p_dict; t_propelem *p_nextelem; int p_badupdate; - char p_otherescapes[PROPS_MAXOTHERS]; - t_props *p_otherprops; /* props list's head */ + char p_mixupescapes[PROPS_MAXMIXUPS]; + t_props *p_firstmixup; /* points to the props list's head */ t_props *p_next; }; @@ -112,23 +117,124 @@ static void props_dictadd(t_props *pp, t_symbol *s, int ac, t_atom *av) } } -static char *props_otherinitial(t_props *pp, char c) +/* API calls for lookup (getvalue) and traversal (firstvalue, nextvalue), and + non-api calls (removevalue) of resolved properties. Only dictionary-enabled + properties handle these calls. Plain 'key', without escape, is expected. + Traversal is not thread-safe (will we need threaded props, LATER?) */ + +char *props_getvalue(t_props *pp, char *key) +{ + if (pp->p_resolver) + { + t_propelem *ep = pp->p_dict; + while (ep) + { + if (strcmp(ep->e_key, key)) + ep = ep->e_next; + else + return (ep->e_value); + } + } + return (0); +} + +char *props_nextvalue(t_props *pp, char **keyp) +{ + if (pp->p_nextelem) + { + char *value = pp->p_nextelem->e_value; + *keyp = pp->p_nextelem->e_key; + pp->p_nextelem = pp->p_nextelem->e_next; + return (value); + } + return (0); +} + +char *props_firstvalue(t_props *pp, char **keyp) +{ + if (pp->p_nextelem) + loudbug_bug("props_firstvalue"); + if (pp->p_resolver) + pp->p_nextelem = pp->p_dict; + return (props_nextvalue(pp, keyp)); +} + +static void props_removevalue(t_props *pp, char *key) +{ + if (pp->p_resolver && *key) + { + t_propelem *ep = pp->p_dict, *epp = 0; + while (ep) + { + if (strcmp(ep->e_key, key)) + { + epp = ep; + ep = ep->e_next; + } + else + { + if (epp) + epp->e_next = ep->e_next; + else + pp->p_dict = ep->e_next; + propelem_free(ep); + break; + } + } + } +} + +void props_clearvalues(t_props *pp) { - t_props *pp1 = pp->p_otherprops; + while (pp->p_dict) + { + t_propelem *ep = pp->p_dict->e_next; + propelem_free(pp->p_dict); + pp->p_dict = ep; + } +} + +/* LATER think about 'deep' cloning, i.e. propagating source atoms into + the destination buffer. Since cloning, unless requested by the user, + should never be persistent (source atoms should not stick to the + destination object in a .pd file), deep cloning requires introducing + a two-buffer scheme. There is no reason for deep cloning of arguments, + or handlers, but options could benefit. */ + +void props_clonevalues(t_props *to, t_props *from) +{ + if (to->p_resolver) + { + int ac; + t_atom *ap = props_getfirst(from, &ac); + while (ap) + { + props_dictadd(to, ap->a_w.w_symbol, ac - 1, ap + 1); + ap = props_getnext(from, &ac); + } + } +} + +static char *props_mixupinitial(t_props *pp, char c) +{ + t_props *pp1 = pp->p_firstmixup; while (pp1) { if (pp1 != pp && pp1->p_thisescape == c) return (pp1->p_thisinitial); pp1 = pp1->p_next; } - bug("props_otherinitial"); - post("(%c \"%s\")", c, pp->p_otherescapes); + loudbug_bug("props_mixupinitial"); + loudbug_post("(%c \"%s\")", c, pp->p_mixupescapes); return (0); } -static int props_atstart(t_props *pp, int mode, char *buf) +/* If buf is pp's key, returns PROPS_THIS; otherwise, if PROPS_MULTIMODE + was passed and buf is a key of one of pp's mixups, returns PROPS_MIXUP; + otherwise, returns PROPS_NONE. */ +static int props_iskey(t_props *pp, int mode, char *buf) { - char *otherinitial; + char *mixupinitial; if (*buf == pp->p_thisescape) { char c = buf[1]; @@ -137,27 +243,113 @@ static int props_atstart(t_props *pp, int mode, char *buf) return (PROPS_THIS); } else if (mode == PROPS_MULTIMODE && - *pp->p_otherescapes && strchr(pp->p_otherescapes, *buf)) + *pp->p_mixupescapes && strchr(pp->p_mixupescapes, *buf)) { char c = buf[1]; if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') - || ((otherinitial = props_otherinitial(pp, *buf)) - && *otherinitial && strchr(otherinitial, c))) - return (PROPS_OTHER); + || ((mixupinitial = props_mixupinitial(pp, *buf)) + && *mixupinitial && strchr(mixupinitial, c))) + return (PROPS_MIXUP); } return (PROPS_NONE); } +/* Lookup (getone) and traversal (getfirst, getnext) of unresolved properties. + These calls return a pointer to the key atom (the contents follows it), + unlike the get/first/nextvalue calls, which return the (resolved) value. + Traversal is not thread-safe (will we need threaded props, LATER?) */ + +t_atom *props_getone(t_props *pp, t_symbol *keysym, int *npp) +{ + if (keysym && + props_iskey(pp, PROPS_SINGLEMODE, keysym->s_name) != PROPS_NONE) + { + int ibeg, iend = 0; + t_atom *ap; + for (ibeg = 0, ap = pp->p_buffer; ibeg < pp->p_natoms; ibeg++, ap++) + { + if (ap->a_type == A_SYMBOL && ap->a_w.w_symbol == keysym) + { + for (iend = ibeg + 1, ap++; iend < pp->p_natoms; iend++, ap++) + if (ap->a_type == A_SYMBOL && + props_iskey(pp, PROPS_SINGLEMODE, + ap->a_w.w_symbol->s_name) != PROPS_NONE) + break; + break; + } + } + if (iend > ibeg) + { + *npp = iend - ibeg; + return (pp->p_buffer + ibeg); + } + } + *npp = 0; + return (0); +} + +t_atom *props_getnext(t_props *pp, int *npp) +{ + if (pp->p_nextindex >= 0) + { + int ibeg = pp->p_nextindex; + t_atom *ap; + for (ap = pp->p_buffer + ibeg; ibeg < pp->p_natoms; ibeg++, ap++) + if (ap->a_type == A_SYMBOL && + props_iskey(pp, PROPS_SINGLEMODE, + ap->a_w.w_symbol->s_name) != PROPS_NONE) + break; + if (ibeg < pp->p_natoms) + { + int iend; + for (iend = ibeg + 1, ap++; iend < pp->p_natoms; iend++, ap++) + if (ap->a_type == A_SYMBOL && + props_iskey(pp, PROPS_SINGLEMODE, + ap->a_w.w_symbol->s_name) != PROPS_NONE) + break; + if (iend < pp->p_natoms) + pp->p_nextindex = iend; + else + pp->p_nextindex = -1; + *npp = iend - ibeg; + return (pp->p_buffer + ibeg); + } + else pp->p_nextindex = -1; + } + *npp = 0; + return (0); +} + +t_atom *props_getfirst(t_props *pp, int *npp) +{ + if (pp->p_nextindex >= 0) + loudbug_bug("props_getfirst"); + pp->p_nextindex = 0; + return (props_getnext(pp, npp)); +} + +t_atom *props_getall(t_props *pp, int *npp) +{ + *npp = pp->p_natoms; + return (pp->p_buffer); +} + +char *props_getname(t_props *pp) +{ + return (pp ? pp->p_name : "property"); +} + /* Search for a property, replace its value if found, otherwise add. - Assuming s is valid. Returning nafter - nbefore. */ -static int props_update(t_props *pp, int mode, - t_symbol *s, int ac, t_atom *av, int doit) + If 'filter' contains an exact copy, do nothing. Assuming 'keysym' + is valid. Returning nafter - nbefore. */ +static int props_update(t_props *pp, int mode, t_props *filter, + t_symbol *keysym, int ac, t_atom *av, int doit) { int nadd, ndiff, ibeg, iend = 0; t_atom *ap; for (nadd = 0, ap = av; nadd < ac; nadd++, ap++) - if (ap->a_type == A_SYMBOL - && props_atstart(pp, mode, ap->a_w.w_symbol->s_name)) + if (ap->a_type == A_SYMBOL && + props_iskey(pp, mode, ap->a_w.w_symbol->s_name) != PROPS_NONE) break; if (!nadd) { @@ -166,14 +358,43 @@ static int props_update(t_props *pp, int mode, } pp->p_badupdate = 0; nadd++; + + if (filter) + { + int acf; + t_atom *apf = props_getone(filter, keysym, &acf); + if (acf == nadd) + { + int i; +#ifdef PROPS_DEBUG + loudbug_startpost("checking %s", keysym->s_name); + loudbug_postatom(nadd - 1, av); +#endif + for (i = 1, ap = av, apf++; i < nadd; i++, ap++, apf++) + if (ap->a_type != apf->a_type || + ap->a_w.w_symbol != apf->a_w.w_symbol) + break; + if (i == nadd) +#ifndef PROPS_DEBUG + return (0); +#else + { + loudbug_post(" ... filtered"); + return (0); + } + else loudbug_post(" ... updated"); +#endif + } + } + for (ibeg = 0, ap = pp->p_buffer; ibeg < pp->p_natoms; ibeg++, ap++) { - if (ap->a_type == A_SYMBOL && ap->a_w.w_symbol == s) + if (ap->a_type == A_SYMBOL && ap->a_w.w_symbol == keysym) { for (iend = ibeg + 1, ap++; iend < pp->p_natoms; iend++, ap++) - if (ap->a_type == A_SYMBOL - && props_atstart(pp, PROPS_SINGLEMODE, - ap->a_w.w_symbol->s_name)) + if (ap->a_type == A_SYMBOL && + props_iskey(pp, PROPS_SINGLEMODE, + ap->a_w.w_symbol->s_name) != PROPS_NONE) break; break; } @@ -184,13 +405,13 @@ static int props_update(t_props *pp, int mode, int i, newnatoms = pp->p_natoms + ndiff; if (newnatoms > pp->p_size) { - bug("props_update"); + loudbug_bug("props_update"); return (0); } #ifdef PROPS_DEBUG - post("%s %s, [%d..%d), ndiff %d", - (iend > ibeg ? "replacing" : "adding"), s->s_name, - ibeg, iend, ndiff); + loudbug_post("%s %s, [%d..%d), ndiff %d", + (iend > ibeg ? "replacing" : "adding"), keysym->s_name, + ibeg, iend, ndiff); #endif if (iend > ibeg) { @@ -211,34 +432,38 @@ static int props_update(t_props *pp, int mode, else { ap = pp->p_buffer + pp->p_natoms; - SETSYMBOL(ap, s); + SETSYMBOL(ap, keysym); } ap++; nadd--; - if (pp->p_resolver) props_dictadd(pp, s, nadd, av); + if (pp->p_resolver) + props_dictadd(pp, keysym, nadd, av); for (i = 0; i < nadd; i++) *ap++ = *av++; pp->p_natoms = newnatoms; } return (ndiff); } -/* If in a single mode, ignore `other' properties (their switches are parsed - through as values). If there is an empty property, which is not to be - ignored, do not parse beyond. Return an offending switch, if any. */ -t_symbol *props_add(t_props *pp, int single, t_symbol *s, int ac, t_atom *av) +/* Carve out all properties of a given kind from a message. If in a single + mode, ignore `mixup' properties -- their keys are parsed through as values. + If there is an empty property, which is not to be ignored, do not parse + beyond. Return an offending key symbol, if any. */ +t_symbol *props_add(t_props *pp, int single, t_props *filter, + t_symbol *s, int ac, t_atom *av) { t_symbol *empty = 0; t_atom *av1, *ap; int mode = (single ? PROPS_SINGLEMODE : PROPS_MULTIMODE); int ac1, i, ngrown = 0; - if (!s || !props_atstart(pp, PROPS_SINGLEMODE, s->s_name)) + if (!s || props_iskey(pp, PROPS_SINGLEMODE, s->s_name) == PROPS_NONE) { s = 0; while (ac) { s = (av->a_type == A_SYMBOL ? av->a_w.w_symbol : 0); ac--; av++; - if (s && props_atstart(pp, PROPS_SINGLEMODE, s->s_name)) + if (s && + props_iskey(pp, PROPS_SINGLEMODE, s->s_name) != PROPS_NONE) break; s = 0; } @@ -248,16 +473,16 @@ t_symbol *props_add(t_props *pp, int single, t_symbol *s, int ac, t_atom *av) empty = s; goto done; } - ngrown += props_update(pp, mode, s, ac, av, 0); + ngrown += props_update(pp, mode, filter, s, ac, av, 0); if (pp->p_badupdate) empty = s; else for (i = 0, ap = av; i < ac; i++, ap++) { - if (ap->a_type == A_SYMBOL - && props_atstart(pp, PROPS_SINGLEMODE, - ap->a_w.w_symbol->s_name)) + if (ap->a_type == A_SYMBOL && + props_iskey(pp, PROPS_SINGLEMODE, + ap->a_w.w_symbol->s_name) != PROPS_NONE) { - ngrown += props_update(pp, mode, ap->a_w.w_symbol, + ngrown += props_update(pp, mode, filter, ap->a_w.w_symbol, ac - i - 1, ap + 1, 0); if (pp->p_badupdate) { @@ -277,16 +502,16 @@ t_symbol *props_add(t_props *pp, int single, t_symbol *s, int ac, t_atom *av) if (nrequested != ngrown) goto done; } - props_update(pp, mode, s, ac, av, 1); + props_update(pp, mode, filter, s, ac, av, 1); if (pp->p_badupdate) empty = s; else for (i = 0, ap = av; i < ac; i++, ap++) { - if (ap->a_type == A_SYMBOL - && props_atstart(pp, PROPS_SINGLEMODE, - ap->a_w.w_symbol->s_name)) + if (ap->a_type == A_SYMBOL && + props_iskey(pp, PROPS_SINGLEMODE, + ap->a_w.w_symbol->s_name) != PROPS_NONE) { - props_update(pp, mode, ap->a_w.w_symbol, + props_update(pp, mode, filter, ap->a_w.w_symbol, ac - i - 1, ap + 1, 1); if (pp->p_badupdate) { @@ -299,11 +524,12 @@ done: return (empty); } -/* FIXME remove from p_dict */ -int props_remove(t_props *pp, t_symbol *s) +int props_remove(t_props *pp, t_symbol *keysym) { int ac; - t_atom *av = props_getone(pp, s, &ac); + t_atom *av = props_getone(pp, keysym, &ac); + if (keysym && *keysym->s_name) + props_removevalue(pp, keysym->s_name + 1); if (av) { int i; @@ -316,143 +542,51 @@ int props_remove(t_props *pp, t_symbol *s) else return (0); } -/* LATER think about 'deep' cloning, i.e. propagating source atoms into - the destination buffer. Since cloning, unless requested by the user, - should never be persistent (source atoms should not stick to the - destination object in a .pd file), deep cloning requires introducing - a two-buffer scheme. There is no reason for deep cloning of arguments, - or handlers, but options could benefit. */ - -void props_clone(t_props *to, t_props *from) +static void props_clearone(t_props *pp) { - if (to->p_resolver) - { - /* LATER make this into a generic traversing method */ - int ibeg = 0, iend = 0; - t_atom *abeg = from->p_buffer; - t_atom *ap = abeg; - while (ibeg < from->p_natoms) - { - if (ap->a_type == A_SYMBOL && - props_atstart(from, PROPS_SINGLEMODE, ap->a_w.w_symbol->s_name)) - { - for (iend = ibeg + 1, ap++; iend < from->p_natoms; iend++, ap++) - if (ap->a_type == A_SYMBOL - && props_atstart(from, PROPS_MULTIMODE, - ap->a_w.w_symbol->s_name)) - break; - props_dictadd(to, abeg->a_w.w_symbol, - iend - ibeg - 1, abeg + 1); - if (iend < from->p_natoms) - { - ibeg = iend; - abeg = ap; - } - else break; - } - else - { - ibeg++; - ap++; - } - } - } - else - { - /* LATER */ - } + pp->p_natoms = 0; + props_clearvalues(pp); } -/* only dictionary-enabled properties handle props_...value() calls */ - -char *props_getvalue(t_props *pp, char *key) +void props_clearall(t_props *pp) { - if (pp->p_resolver) + if (pp && (pp = pp->p_firstmixup)) { - t_propelem *ep = pp->p_dict; - while (ep) + while (pp) { - if (strcmp(ep->e_key, key)) - ep = ep->e_next; - else - return (ep->e_value); + props_clearone(pp); + pp = pp->p_next; } } - return (0); + else loudbug_bug("props_clearall"); } -char *props_nextvalue(t_props *pp, char **keyp) +/* Compute pp0 = pp1 - pp2, using key-only equivalence. */ +void props_diff(t_props *pp0, t_props *pp1, t_props *pp2) { - if (pp->p_nextelem) + int ac1; + t_atom *ap1 = props_getfirst(pp1, &ac1); + props_clearone(pp0); + while (ap1) { - char *value = pp->p_nextelem->e_value; - *keyp = pp->p_nextelem->e_key; - pp->p_nextelem = pp->p_nextelem->e_next; - return (value); + int ac2; + if (!props_getone(pp2, ap1->a_w.w_symbol, &ac2)) + props_add(pp0, 0, 0, 0, ac1, ap1); + ap1 = props_getnext(pp1, &ac1); } - return (0); -} - -char *props_firstvalue(t_props *pp, char **keyp) -{ - if (pp->p_resolver) - pp->p_nextelem = pp->p_dict; - return (props_nextvalue(pp, keyp)); -} - -t_atom *props_getone(t_props *pp, t_symbol *s, int *npp) -{ - int ibeg, iend = 0; - t_atom *ap; - if (!(s && props_atstart(pp, PROPS_SINGLEMODE, s->s_name))) - return (0); - for (ibeg = 0, ap = pp->p_buffer; ibeg < pp->p_natoms; ibeg++, ap++) - { - if (ap->a_type == A_SYMBOL && ap->a_w.w_symbol == s) - { - for (iend = ibeg + 1, ap++; iend < pp->p_natoms; iend++, ap++) - if (ap->a_type == A_SYMBOL - && props_atstart(pp, PROPS_MULTIMODE, - ap->a_w.w_symbol->s_name)) - break; - break; - } - } - if (iend > ibeg) - { - *npp = iend - ibeg; - return (pp->p_buffer + ibeg); - } - else return (0); -} - -t_atom *props_getall(t_props *pp, int *npp) -{ - *npp = pp->p_natoms; - return (pp->p_buffer); -} - -char *props_getname(t_props *pp) -{ - return (pp ? pp->p_name : "property"); } static void props_freeone(t_props *pp) { if (pp->p_buffer != pp->p_bufini) freebytes(pp->p_buffer, pp->p_size * sizeof(*pp->p_buffer)); - while (pp->p_dict) - { - t_propelem *ep = pp->p_dict->e_next; - propelem_free(pp->p_dict); - pp->p_dict = ep; - } + props_clearvalues(pp); freebytes(pp, sizeof(*pp)); } void props_freeall(t_props *pp) { - if (pp && (pp = pp->p_otherprops)) + if (pp && (pp = pp->p_firstmixup)) { while (pp) { @@ -461,36 +595,36 @@ void props_freeall(t_props *pp) pp = pp1; } } - else bug("props_freeall"); + else loudbug_bug("props_freeall"); } -void props_setupothers(t_props *pp, t_props *otherprops) +static void props_setupmixups(t_props *pp, t_props *mixup) { t_props *pp1; - pp->p_next = (otherprops ? otherprops->p_otherprops : 0); + pp->p_next = (mixup ? mixup->p_firstmixup : 0); for (pp1 = pp; pp1; pp1 = pp1->p_next) { t_props *pp2; - char *bp = pp1->p_otherescapes; + char *bp = pp1->p_mixupescapes; int i; - pp1->p_otherprops = pp; - for (pp2 = pp, i = 1; pp2 && i < PROPS_MAXOTHERS; + pp1->p_firstmixup = pp; + for (pp2 = pp, i = 1; pp2 && i < PROPS_MAXMIXUPS; pp2 = pp2->p_next, i++) if (pp2 != pp1) *bp++ = pp2->p_thisescape; *bp = 0; #ifdef PROPS_DEBUG - startpost("%c \"%s\" ", pp1->p_thisescape, pp1->p_otherescapes); + loudbug_startpost("%c \"%s\" ", pp1->p_thisescape, pp1->p_mixupescapes); #endif } #ifdef PROPS_DEBUG - endpost(); + loudbug_endpost(); #endif } /* nonzero resolver requires the owner to be nonzero */ t_props *props_new(t_pd *owner, char *name, char *thisdelim, - t_props *otherprops, t_propsresolver resolver) + t_props *mixup, t_propsresolver resolver) { t_props *pp = getbytes(sizeof(*pp)); if (pp) @@ -503,20 +637,21 @@ t_props *props_new(t_pd *owner, char *name, char *thisdelim, } else { - bug("props_new (no escape)"); + loudbug_bug("props_new (no escape)"); pp->p_thisescape = '-'; pp->p_thisinitial = 0; } - props_setupothers(pp, otherprops); + props_setupmixups(pp, mixup); pp->p_size = PROPS_INISIZE; pp->p_natoms = 0; pp->p_buffer = pp->p_bufini; + pp->p_nextindex = -1; if (pp->p_owner = owner) pp->p_resolver = resolver; else { if (resolver) - bug("props_new (no owner)"); + loudbug_bug("props_new (no owner)"); pp->p_resolver = 0; } pp->p_dict = 0; diff --git a/shared/common/props.h b/shared/common/props.h index 8e3add6..c9d81a6 100644 --- a/shared/common/props.h +++ b/shared/common/props.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2003 krzYszcz and others. +/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ @@ -10,17 +10,25 @@ EXTERN_STRUCT _props; typedef char *(*t_propsresolver)(t_pd *, int, t_atom *); -t_symbol *props_add(t_props *pp, int single, t_symbol *s, int ac, t_atom *av); -int props_remove(t_props *pp, t_symbol *s); -void props_clone(t_props *to, t_props *from); char *props_getvalue(t_props *pp, char *key); char *props_firstvalue(t_props *pp, char **keyp); char *props_nextvalue(t_props *pp, char **keyp); -t_atom *props_getone(t_props *pp, t_symbol *s, int *npp); +void props_clearvalues(t_props *pp); +void props_clonevalues(t_props *to, t_props *from); + +t_atom *props_getone(t_props *pp, t_symbol *keysym, int *npp); +t_atom *props_getfirst(t_props *pp, int *npp); +t_atom *props_getnext(t_props *pp, int *npp); t_atom *props_getall(t_props *pp, int *npp); char *props_getname(t_props *pp); + +t_symbol *props_add(t_props *pp, int single, t_props *filter, + t_symbol *s, int ac, t_atom *av); +int props_remove(t_props *pp, t_symbol *keysym); +void props_diff(t_props *pp0, t_props *pp1, t_props *pp2); +void props_clearall(t_props *pp); void props_freeall(t_props *pp); t_props *props_new(t_pd *owner, char *name, char *thisdelim, - t_props *otherprops, t_propsresolver resolver); + t_props *mixup, t_propsresolver resolver); #endif diff --git a/shared/getridof.baddeps b/shared/getridof.baddeps index ebbf3df..7286cd6 100644 --- a/shared/getridof.baddeps +++ b/shared/getridof.baddeps @@ -3,7 +3,7 @@ Some are inevitable, but others can, and should be removed. unstable/fragile -> common/loud unstable/fringe -> unstable/forky -common/props -> common/grow +common/props -> common/grow common/loud common/vefl -> common/loud, unstable/fragile common/qtree -> common/loud common/binport -> common/lex diff --git a/shared/hammer/file.c b/shared/hammer/file.c index c671946..eec3ad3 100644 --- a/shared/hammer/file.c +++ b/shared/hammer/file.c @@ -82,7 +82,7 @@ static void hammereditor_guidefs(void) sys_gui("}\n"); sys_gui("proc hammereditor_dodirty {name} {\n"); - sys_gui(" if {[catch {$name.text edit modified} dirty]} {set dirty 0}\n"); + sys_gui(" if {[catch {$name.text edit modified} dirty]} {set dirty 1}\n"); sys_gui(" set title [wm title $name]\n"); sys_gui(" set dt [string equal -length 1 $title \"*\"]\n"); sys_gui(" if {$dirty} {\n"); @@ -129,7 +129,7 @@ static void hammereditor_guidefs(void) sys_gui("proc hammereditor_close {name ask} {\n"); sys_gui(" if {[winfo exists $name]} {\n"); - sys_gui(" if {[catch {$name.text edit modified} dirty]} {set dirty 0}\n"); + sys_gui(" if {[catch {$name.text edit modified} dirty]} {set dirty 1}\n"); sys_gui(" if {$ask && $dirty} {\n"); sys_gui(" set title [wm title $name]\n"); sys_gui(" if {[string equal -length 1 $title \"*\"]} {\n"); @@ -137,7 +137,7 @@ static void hammereditor_guidefs(void) sys_gui(" }\n"); sys_gui(" set answer [tk_messageBox \\-type yesnocancel \\\n"); sys_gui(" \\-icon question \\\n"); - sys_gui(" \\-message [concat Save changes to $title?]]\n"); + sys_gui(" \\-message [concat Save changes to \\\"$title\\\"?]]\n"); sys_gui(" if {$answer == \"yes\"} {hammereditor_send $name}\n"); sys_gui(" if {$answer != \"cancel\"} {hammereditor_doclose $name}\n"); sys_gui(" } else {hammereditor_doclose $name}\n"); @@ -183,8 +183,24 @@ void hammereditor_close(t_hammerfile *f, int ask) void hammereditor_append(t_hammerfile *f, char *contents) { - if (!contents) contents = ""; - sys_vgui("hammereditor_append .%x {%s}\n", (int)f, contents); + if (contents) + { + char *ptr; + for (ptr = contents; *ptr; ptr++) + { + if (*ptr == '{' || *ptr == '}') + { + char c = *ptr; + *ptr = 0; + sys_vgui("hammereditor_append .%x {%s}\n", (int)f, contents); + sys_vgui("hammereditor_append .%x \"%c\"\n", (int)f, c); + *ptr = c; + contents = ptr + 1; + } + } + if (*contents) + sys_vgui("hammereditor_append .%x {%s}\n", (int)f, contents); + } } void hammereditor_setdirty(t_hammerfile *f, int flag) diff --git a/shared/notes.txt b/shared/notes.txt index de093b8..9f92507 100644 --- a/shared/notes.txt +++ b/shared/notes.txt @@ -5,6 +5,17 @@ TODO for root and shared DONE for root and shared +with cyclone alpha54 and toxy alpha16 + * props: + . code cleanup + . new calls: props_getfirst(), props_getnext(), props_diff(), + props_clearall(), props_clearvalues() + . props_add(): additional argument 'filter' (skip exact input-filter copies) + * fragile: new call fragile_class_getnames() + * hammereditor: + . hammereditor_append() accepts unbalanced braces + . defaults to dirty, if (older) tk misses edit command + with cyclone alpha53 * binport: added half-byte #symbol id * hammereditor: diff --git a/shared/toxy/scriptlet.c b/shared/toxy/scriptlet.c index 348d2c7..bf207c1 100644 --- a/shared/toxy/scriptlet.c +++ b/shared/toxy/scriptlet.c @@ -25,7 +25,8 @@ #define SCRIPTLET_INIDOTSIZE 256 #define SCRIPTLET_MARGIN 64 #define SCRIPTLET_DOTMARGIN 16 -#define SCRIPTLET_MAXPUSH 20000 /* cf SOCKSIZE in t_tkcmd.c, LATER revisit */ +/* cf SOCKSIZE in older versions of t_tkcmd.c, FIXME */ +#define SCRIPTLET_MAXPUSH 20000 enum { SCRIPTLET_CVOK, SCRIPTLET_CVUNKNOWN, SCRIPTLET_CVMISSING }; @@ -475,7 +476,7 @@ static int scriptlet_addfloat(t_scriptlet *sp, t_float f) char buf[64]; if (!sp->s_separator) sp->s_separator = ' '; - sprintf(buf, "%g ", f); + sprintf(buf, "%g", f); return (scriptlet_doappend(sp, buf)); } diff --git a/shared/unstable/fragile.c b/shared/unstable/fragile.c index aed4d83..d91ea58 100644 --- a/shared/unstable/fragile.c +++ b/shared/unstable/fragile.c @@ -15,6 +15,17 @@ int fragile_class_count(void) return (pd_objectmaker->c_nmethod); } +void fragile_class_getnames(t_atom *av) +{ + int ac = pd_objectmaker->c_nmethod; + t_methodentry *mp = pd_objectmaker->c_methods; + while (ac--) + { + SETSYMBOL(av, mp->me_name); + mp++; av++; + } +} + /* Raising and voluntary mutation is a method of resolving name clashes. A raised class hides other equivocal candidates. A simpler method, raising and lowering, works only in global scope, because, currently, Pd diff --git a/shared/unstable/fragile.h b/shared/unstable/fragile.h index 6e79475..b59bb14 100644 --- a/shared/unstable/fragile.h +++ b/shared/unstable/fragile.h @@ -6,6 +6,7 @@ #define __FRAGILE_H__ int fragile_class_count(void); +void fragile_class_getnames(t_atom *av); void fragile_class_raise(t_symbol *cname, t_newmethod thiscall); t_pd *fragile_class_mutate(t_symbol *cname, t_newmethod thiscall, int ac, t_atom *av); diff --git a/test/toxy/lbpict.wid b/test/toxy/lbpict.wid index d7d5771..6378f8e 100644 --- a/test/toxy/lbpict.wid +++ b/test/toxy/lbpict.wid @@ -1,5 +1,7 @@ proc ::toxy::lbpict {path fname} { - $path config -image [image create photo -file $fname] + if {[catch {$path config -image [image create photo -file $fname]} res]} { + puts stderr [concat failed ::toxy::lbpict: $res] + } } #> lbpict label diff --git a/test/toxy/setup.wid b/test/toxy/setup.wid index 1d544c9..ce498c4 100644 --- a/test/toxy/setup.wid +++ b/test/toxy/setup.wid @@ -1,4 +1,4 @@ -package provide toxywidgets 0.1.0.15 +package provide toxywidgets 0.1.0.16 # LATER keep standard widget setup in a .tcl file (transfered into a .wiq), and # glue separate .wid files with standard widget definitions into another .wiq @@ -287,6 +287,9 @@ proc ::toxy::popup {path target remote entries args} { } else { error [concat in ::toxy::popup: $err] } } +# FIXME should be part of the float widget type, but we need it for plain scales +set ::toxy::scale_isactive 1 + #> bang button #. -image ::toxy::img::empty -command .<.> #. -bg pink -activebackground red -width 50 -height 50 @@ -298,9 +301,6 @@ proc ::toxy::popup {path target remote entries args} { #. @float .- set .#1 #. @vset ::toxy::scale_doset .- .#1 -# FIXME -set ::toxy::scale_isactive 1 - #> symbol entry #. -bg pink -font .(helvetica 24.) -width 16 #. @symbol .- delete 0 end .: .- insert 0 .#1 diff --git a/test/toxy/stress/bulkyhurd.pd b/test/toxy/stress/bulkyhurd.pd new file mode 100644 index 0000000..0edda17 --- /dev/null +++ b/test/toxy/stress/bulkyhurd.pd @@ -0,0 +1,163 @@ +#N canvas 26 42 948 596 12; +#X floatatom 17 24 5 0 0 0 - - -; +#X floatatom 17 220 5 0 0 0 - - -; +#N canvas 152 43 785 527 1001-hurd 0; +#X obj 99 7 widget popup 1-p #items test -width 18; +#X obj 259 7 widget popup 2-p #items test -width 18; +#X obj 419 7 widget popup 3-p #items test -width 18; +#X obj 579 7 widget popup 4-p #items test -width 18; +#X obj 99 37 widget popup 5-p #items test; +#X obj 179 37 widget popup 6-p #items test; +#X obj 259 37 widget popup 7-p #items test; +#X obj 339 37 widget popup 8-p #items test; +#X obj 419 37 widget popup 9-p #items test; +#X obj 499 37 widget popup 10-p #items test; +#X obj 579 37 widget popup 11-p #items test; +#X obj 659 37 widget popup 12-p #items test; +#X obj 99 67 widget popup 13-p #items test; +#X obj 179 67 widget popup 14-p #items test; +#X obj 259 67 widget popup 15-p #items test; +#X obj 339 67 widget popup 16-p #items test; +#X obj 419 67 widget popup 17-p #items test; +#X obj 499 67 widget popup 18-p #items test; +#X obj 579 67 widget popup 19-p #items test; +#X obj 659 67 widget popup 20-p #items test; +#X obj 99 97 widget popup 21-p #items test; +#X obj 179 97 widget popup 22-p #items test; +#X obj 259 97 widget popup 23-p #items test; +#X obj 339 97 widget popup 24-p #items test; +#X obj 419 97 widget popup 25-p #items test; +#X obj 499 97 widget popup 26-p #items test; +#X obj 579 97 widget popup 27-p #items test; +#X obj 659 97 widget popup 28-p #items test; +#X obj 99 127 widget popup 29-p #items test; +#X obj 179 127 widget popup 30-p #items test; +#X obj 259 127 widget popup 31-p #items test; +#X obj 339 127 widget popup 32-p #items test; +#X obj 419 127 widget popup 33-p #items test; +#X obj 499 127 widget popup 34-p #items test; +#X obj 579 127 widget popup 35-p #items test; +#X obj 659 127 widget popup 36-p #items test; +#X obj 99 157 widget popup 37-p #items test; +#X obj 179 157 widget popup 38-p #items test; +#X obj 259 157 widget popup 39-p #items test; +#X obj 339 157 widget popup 40-p #items test; +#X obj 419 157 widget popup 41-p #items test; +#X obj 499 157 widget popup 42-p #items test; +#X obj 579 157 widget popup 43-p #items test; +#X obj 659 157 widget popup 44-p #items test; +#X obj 99 187 widget popup 45-p #items test; +#X obj 179 187 widget popup 46-p #items test; +#X obj 259 187 widget popup 47-p #items test; +#X obj 339 187 widget popup 48-p #items test; +#X obj 419 187 widget popup 49-p #items test; +#X obj 499 187 widget popup 50-p #items test; +#X obj 579 187 widget popup 51-p #items test; +#X obj 659 187 widget popup 52-p #items test; +#X obj 99 217 widget popup 53-p #items test; +#X obj 179 217 widget popup 54-p #items test; +#X obj 259 217 widget popup 55-p #items test; +#X obj 339 217 widget popup 56-p #items test; +#X obj 419 217 widget popup 57-p #items test; +#X obj 499 217 widget popup 58-p #items test; +#X obj 579 217 widget popup 59-p #items test; +#X obj 659 217 widget popup 60-p #items test; +#X obj 99 247 widget popup 61-p #items test; +#X obj 179 247 widget popup 62-p #items test; +#X obj 259 247 widget popup 63-p #items test; +#X obj 339 247 widget popup 64-p #items test; +#X obj 419 247 widget popup 65-p #items test; +#X obj 499 247 widget popup 66-p #items test; +#X obj 579 247 widget popup 67-p #items test; +#X obj 659 247 widget popup 68-p #items test; +#X obj 99 277 widget popup 69-p #items test; +#X obj 179 277 widget popup 70-p #items test; +#X obj 259 277 widget popup 71-p #items test; +#X obj 339 277 widget popup 72-p #items test; +#X obj 419 277 widget popup 73-p #items test; +#X obj 499 277 widget popup 74-p #items test; +#X obj 579 277 widget popup 75-p #items test; +#X obj 659 277 widget popup 76-p #items test; +#X obj 99 307 widget popup 77-p #items test; +#X obj 179 307 widget popup 78-p #items test; +#X obj 259 307 widget popup 79-p #items test; +#X obj 339 307 widget popup 80-p #items test; +#X obj 419 307 widget popup 81-p #items test; +#X obj 499 307 widget popup 82-p #items test; +#X obj 579 307 widget popup 83-p #items test; +#X obj 659 307 widget popup 84-p #items test; +#X obj 99 337 widget popup 85-p #items test; +#X obj 179 337 widget popup 86-p #items test; +#X obj 259 337 widget popup 87-p #items test; +#X obj 339 337 widget popup 88-p #items test; +#X obj 419 337 widget popup 89-p #items test; +#X obj 499 337 widget popup 90-p #items test; +#X obj 579 337 widget popup 91-p #items test; +#X obj 659 337 widget popup 92-p #items test; +#X obj 99 367 widget popup 93-p #items test; +#X obj 179 367 widget popup 94-p #items test; +#X obj 259 367 widget popup 95-p #items test; +#X obj 339 367 widget popup 96-p #items test; +#X obj 419 367 widget popup 97-p #items test; +#X obj 499 367 widget popup 98-p #items test; +#X obj 579 367 widget popup 99-p #items test; +#X obj 659 367 widget popup 100-p #items test; +#X obj 99 397 widget popup 101-p #items test; +#X obj 179 397 widget popup 102-p #items test; +#X obj 259 397 widget popup 103-p #items test; +#X obj 339 397 widget popup 104-p #items test; +#X obj 419 397 widget popup 105-p #items test; +#X obj 499 397 widget popup 106-p #items test; +#X obj 579 397 widget popup 107-p #items test; +#X obj 659 397 widget popup 108-p #items test; +#X obj 99 427 widget popup 109-p #items test; +#X obj 179 427 widget popup 110-p #items test; +#X obj 259 427 widget popup 111-p #items test; +#X obj 339 427 widget popup 112-p #items test; +#X obj 419 427 widget popup 113-p #items test; +#X obj 499 427 widget popup 114-p #items test; +#X obj 579 427 widget popup 115-p #items test; +#X obj 659 427 widget popup 116-p #items test; +#X obj 99 457 widget popup 117-p #items test; +#X obj 179 457 widget popup 118-p #items test; +#X obj 259 457 widget popup 119-p #items test; +#X obj 339 457 widget popup 120-p #items test; +#X obj 419 457 widget popup 121-p #items test; +#X obj 499 457 widget popup 122-p #items test; +#X obj 579 457 widget popup 123-p #items test; +#X obj 659 457 widget popup 124-p #items test; +#X obj 99 487 widget popup 125-p #items test; +#X obj 179 487 widget popup 126-p #items test; +#X obj 259 487 widget popup 127-p #items test; +#X obj 339 487 widget popup 128-p #items test; +#X obj 419 487 widget popup 129-p #items test; +#X obj 499 487 widget popup 130-p #items test; +#X obj 579 487 widget popup 131-p #items test; +#X obj 659 487 widget popup 132-p #items test; +#X coords 0 0 1 1 750 550 1; +#X restore 159 19 pd \$0-hurd; +#X obj 20 548 tow \$0-hurd popup p; +#X obj 17 185 tow \$0-hurd popup p; +#X obj 20 271 loadbang; +#X floatatom 32 60 5 0 0 0 - - -; +#X obj 20 351 Uzi; +#X msg 20 314 132; +#X msg 39 430 retarget \$1 popup \$2-p; +#X obj 39 389 prepend list \$0-hurd; +#X obj 32 100 prepend list \$0-hurd; +#X msg 32 142 retarget \$1 popup \$2-p; +#X obj 20 506 testmess c; +#X msg 20 467 #items; +#X connect 0 0 4 0; +#X connect 4 0 1 0; +#X connect 5 0 8 0; +#X connect 6 0 11 0; +#X connect 7 0 14 0; +#X connect 7 2 10 0; +#X connect 8 0 7 0; +#X connect 9 0 3 0; +#X connect 10 0 9 0; +#X connect 11 0 12 0; +#X connect 12 0 4 0; +#X connect 13 0 3 0; +#X connect 14 0 13 0; diff --git a/test/toxy/stress/mstots.pd b/test/toxy/stress/mstots.pd new file mode 100644 index 0000000..7c823e0 --- /dev/null +++ b/test/toxy/stress/mstots.pd @@ -0,0 +1,50 @@ +#N canvas 337 46 624 565 12; +#X obj 278 125 Uzi 10; +#X msg 49 16 1000; +#X msg 103 16 5000; +#X msg 154 16 10000; +#X msg 278 160 push; +#X obj 49 287 tot .; +#X obj 278 291 tot .; +#X msg 374 160 tot catch .(console show.); +#X msg 394 47 50000; +#X text 137 46 don't even try this on windows:; +#X msg 316 207 add #; +#X msg 466 81 80000; +#X obj 50 512 tot .; +#X msg 49 246 tot ::mstots::readclock \$1; +#X obj 49 95 t 0 0 b; +#X msg 62 211 tot ::mstots::setclock; +#X msg 50 369 tot namespace eval mstots .(proc setclock .(.) .(set +::mstots::lastclock [clock clicks -milliseconds].).); +#X obj 374 125 loadbang; +#X obj 50 336 loadbang; +#X floatatom 49 65 5 0 0 0 - - -; +#X msg 70 423 tot namespace eval mstots .(proc readclock .(niter.) +.(set delta [expr .([clock clicks -milliseconds] - $::mstots::lastclock.)] +.: puts [concat $delta ms ([expr .($niter / $delta.)] Mb/s)].).); +#X obj 316 246 testmess . 128 7; +#X text 458 245 1024 characters; +#X text 128 80 this takes ~ one second on a 2.66 linux:; +#X connect 0 0 4 0; +#X connect 1 0 19 0; +#X connect 2 0 19 0; +#X connect 3 0 19 0; +#X connect 4 0 6 0; +#X connect 7 0 6 0; +#X connect 8 0 19 0; +#X connect 10 0 21 0; +#X connect 11 0 19 0; +#X connect 13 0 5 0; +#X connect 14 0 13 0; +#X connect 14 1 0 0; +#X connect 14 2 15 0; +#X connect 15 0 5 0; +#X connect 16 0 12 0; +#X connect 17 0 7 0; +#X connect 17 0 10 0; +#X connect 18 0 16 0; +#X connect 18 0 20 0; +#X connect 19 0 14 0; +#X connect 20 0 12 0; +#X connect 21 0 6 0; diff --git a/test/toxy/stress/nbulkyhurds.pd b/test/toxy/stress/nbulkyhurds.pd new file mode 100644 index 0000000..528df2d --- /dev/null +++ b/test/toxy/stress/nbulkyhurds.pd @@ -0,0 +1,16 @@ +#N canvas 36 57 313 293 12; +#X obj 23 117 Uzi; +#X msg 23 29 10; +#X msg 23 210 \; pd open bulkyhurd.pd \$1; +#X msg 129 117 pwd pwd; +#X obj 66 117 r pwd; +#X obj 23 71 t 0 b; +#X obj 23 162 symbol; +#X obj 129 162 tow .; +#X connect 0 0 6 0; +#X connect 1 0 5 0; +#X connect 3 0 7 0; +#X connect 4 0 6 1; +#X connect 5 0 0 0; +#X connect 5 1 3 0; +#X connect 6 0 2 0; diff --git a/toxy/build_counter b/toxy/build_counter index 3c2910e..8e0975b 100644 --- a/toxy/build_counter +++ b/toxy/build_counter @@ -1,7 +1,7 @@ #define TOXY_VERSION "0.1" #define TOXY_RELEASE "alpha" -#define TOXY_BUILD 15 +#define TOXY_BUILD 16 #if 0 -TOXY_SNAPSHOT = 0.1-alpha15 +TOXY_SNAPSHOT = 0.1-alpha16 #endif diff --git a/toxy/notes.txt b/toxy/notes.txt index aa5119a..775bbcd 100644 --- a/toxy/notes.txt +++ b/toxy/notes.txt @@ -1,7 +1,23 @@ TODO for toxy + * widget + . cached handlers + . better megawidgets + . editor: handle semicolons (need to revisit resolution rules) + . editor: differentiate argument keys from casual #strings (color-names) + * tow: canvas-wide and type-on-canvas-wide broadcasting DONE for toxy +alpha16 + * widget: + . editor for options, handlers and arguments made more or less functional + . better 'redefine' (although still only external types may be redefined) + * tow: + . fixed handling of gop-ed targets and missing windows + . new messages: 'retarget', 'pwd' + * tot: + . scriptlet editor improved a little bit (still unfinished) + alpha15 * fixes for megawidgets . setting sub-item bindings in ::toxy::subwidget @@ -1,4 +1,4 @@ -/* Copyright (c) 2003-2004 krzYszcz and others. +/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ @@ -9,6 +9,7 @@ #include "m_pd.h" #include "g_canvas.h" #include "common/loud.h" +#include "unstable/forky.h" #include "hammer/file.h" #include "hammer/gui.h" #include "common/props.h" @@ -251,31 +252,70 @@ static void tot__callback(t_tot *x, t_symbol *s, int ac, t_atom *av) tot_dooutput(x, x->x_out2, s, ac, av); } -/* LATER use properties in widgetbehavior (if gop visibility rules change) */ -static void tot_click(t_tot *x, t_floatarg xpos, t_floatarg ypos, - t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +static void tot_properties(t_gobj *z, t_glist *glist) { + t_tot *x = (t_tot *)z; int nleft; char *head = scriptlet_getcontents(x->x_persistent, &nleft); - char buf[MAXPDSTRING + 1]; - buf[MAXPDSTRING] = 0; hammereditor_open(x->x_filehandle, "scriptlet editor", 0); - while (nleft > 0) + if (nleft) { - if (nleft > MAXPDSTRING) + char buf[MAXPDSTRING + 1], *lastptr = buf + MAXPDSTRING; + *lastptr = 0; + while (nleft > 0) { - strncpy(buf, head, MAXPDSTRING); - head += MAXPDSTRING; - nleft -= MAXPDSTRING; - } - else - { - strncpy(buf, head, nleft); - buf[nleft] = 0; - nleft = 0; + if (nleft > MAXPDSTRING) + { + strncpy(buf, head, MAXPDSTRING); + head += MAXPDSTRING; + nleft -= MAXPDSTRING; + } + else + { + strncpy(buf, head, nleft); + lastptr = buf + nleft; + *lastptr = 0; + nleft = 0; + } + hammereditor_append(x->x_filehandle, buf); } - hammereditor_append(x->x_filehandle, buf); + hammereditor_append(x->x_filehandle, "\n"); } + hammereditor_setdirty(x->x_filehandle, 0); +} + +static void tot_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av) +{ + t_tot *x = (t_tot *)z; + scriptlet_reset(x->x_persistent); + scriptlet_add(x->x_persistent, 0, 0, ac, av); +} + +static void tot_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + scriptlet_read(((t_tot *)z)->x_persistent, fn); +} + +static void tot_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + scriptlet_write(((t_tot *)z)->x_persistent, fn); +} + +static void tot_read(t_tot *x, t_symbol *s) +{ + if (s && s != &s_) + scriptlet_read(x->x_persistent, s); + else + hammerpanel_open(x->x_filehandle, 0); +} + +static void tot_write(t_tot *x, t_symbol *s) +{ + if (s && s != &s_) + scriptlet_write(x->x_persistent, s); + else + hammerpanel_save(x->x_filehandle, + canvas_getdir(x->x_glist), x->x_defname); } /* This is called for all Map (f==1) and all Destroy (f==0) events, @@ -305,6 +345,38 @@ static void tot__vised(t_tot *x, t_symbol *s, t_floatarg f) } #ifdef TOT_DEBUG +static void tot_postscriptlet(t_scriptlet *sp, char *message) +{ + int nleft; + char *head = scriptlet_getbuffer(sp, &nleft); + loudbug_startpost("*** %s (size %d)", message, nleft); + if (nleft) + { + char buf[MAXPDSTRING + 1], *lastptr = buf + MAXPDSTRING; + *lastptr = 0; + loudbug_stringpost(" ***\n\""); + while (nleft > 0) + { + if (nleft > MAXPDSTRING) + { + strncpy(buf, head, MAXPDSTRING); + head += MAXPDSTRING; + nleft -= MAXPDSTRING; + } + else + { + strncpy(buf, head, nleft); + lastptr = buf + nleft; + *lastptr = 0; + nleft = 0; + } + loudbug_stringpost(buf); + } + loudbug_stringpost("\"\n---------------\n"); + } + else loudbug_stringpost(": \"\" ***\n"); +} + static void tot_debug(t_tot *x) { t_symbol *pn = tot_getpathname(x, 0); @@ -314,40 +386,11 @@ static void tot_debug(t_tot *x) loudbug_post("destination: %s", tot_getcvname(x)->s_name); loudbug_post("pathname%s %s", (pn ? ":" : ""), (pn ? pn->s_name : "unknown")); - bp = scriptlet_getbuffer(x->x_transient, &sz); - loudbug_post("transient buffer (size %d):\n\"%s\"", sz, bp); - bp = scriptlet_getbuffer(x->x_persistent, &sz); - loudbug_post("persistent buffer (size %d):\n\"%s\"", sz, bp); + tot_postscriptlet(x->x_transient, "transient buffer"); + tot_postscriptlet(x->x_persistent, "persistent buffer"); } #endif -static void tot_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) -{ - scriptlet_read(((t_tot *)z)->x_persistent, fn); -} - -static void tot_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) -{ - scriptlet_write(((t_tot *)z)->x_persistent, fn); -} - -static void tot_read(t_tot *x, t_symbol *s) -{ - if (s && s != &s_) - scriptlet_read(x->x_persistent, s); - else - hammerpanel_open(x->x_filehandle, 0); -} - -static void tot_write(t_tot *x, t_symbol *s) -{ - if (s && s != &s_) - scriptlet_write(x->x_persistent, s); - else - hammerpanel_save(x->x_filehandle, - canvas_getdir(x->x_glist), x->x_defname); -} - static void tot_detach(t_tot *x) { t_canvas *cv = tot_getcanvas(x, 1); @@ -571,7 +614,8 @@ static void *tot_new(t_symbol *s1, t_symbol *s2) } else x->x_defname = &s_; x->x_filehandle = hammerfile_new((t_pd *)x, 0, - tot_readhook, tot_writehook, 0); + tot_readhook, tot_writehook, + tot_editorhook); hammergui_bindvised((t_pd *)x); x->x_visedpathname = tot_getvisedpathname(x, 0); x->x_guidetached = 0; @@ -626,15 +670,13 @@ void tot_setup(void) gensym("_rp"), A_GIMME, 0); class_addmethod(tot_class, (t_method)tot__callback, gensym("_cb"), A_GIMME, 0); - class_addmethod(tot_class, (t_method)tot_click, - gensym("click"), - A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); class_addmethod(tot_class, (t_method)tot__vised, gensym("_vised"), A_SYMBOL, A_FLOAT, 0); #ifdef TOT_DEBUG class_addmethod(tot_class, (t_method)tot_debug, gensym("debug"), 0); #endif + forky_setpropertiesfn(tot_class, tot_properties); hammerfile_setup(tot_class, 0); totspy_class = class_new(gensym("tot spy"), 0, 0, sizeof(t_totspy), CLASS_PD, 0); diff --git a/toxy/widget.c b/toxy/widget.c index c0bffd8..da4a78f 100644 --- a/toxy/widget.c +++ b/toxy/widget.c @@ -55,7 +55,7 @@ typedef struct _widgethandlers typedef struct _widget { t_object x_ob; - t_glist *x_glist; /* containing glist */ + t_glist *x_glist; /* containing glist */ t_widgettype *x_typedef; t_symbol *x_type; /* 1st creation arg: our type */ t_symbol *x_tkclass; /* Tk widget class */ @@ -68,6 +68,10 @@ typedef struct _widget t_props *x_options; /* instance options */ t_props *x_handlers; /* instance handlers */ t_props *x_arguments; /* instance arguments */ + t_props *x_xargs; /* type and instance arguments, resolved */ + t_props *x_diffoptions; /* type options minus instance options */ + t_props *x_diffhandlers; /* same for handlers */ + t_props *x_diffarguments; /* same for arguments */ t_widgethandlers x_cache; /* actual handlers */ t_scriptlet *x_iniscript; /* instance initializer */ t_scriptlet *x_optscript; /* option scriptlet */ @@ -89,13 +93,14 @@ typedef struct _widget typedef struct _tow { t_object x_ob; - t_glist *x_glist; /* containing glist */ - t_symbol *x_cvremote; /* null if containing glist is our destination */ + t_glist *x_glist; /* containing glist */ + t_glist *x_targetglist; /* containing or parent glist */ + t_symbol *x_cvremote; /* null if targetglist is set */ t_symbol *x_cvname; - t_symbol *x_type; /* 2nd creation arg: widget's type */ - t_symbol *x_name; /* 3rd creation arg: widget's name */ + t_symbol *x_type; /* 2nd creation arg: widget's type */ + t_symbol *x_name; /* 3rd creation arg: widget's name */ t_widgetentry *x_widgetlist; - struct _tow *x_next; /* next in the global towlist */ + struct _tow *x_next; /* next in the global towlist */ } t_tow; static t_class *widget_class; @@ -103,7 +108,7 @@ static t_class *tow_class; /* Global towlist, searched in widget_attach(). There is no global widgetlist, because a destination glist is searched instead in tow_attach(). */ -static t_tow *towlist = 0; +static t_tow *widget_towlist = 0; static t_symbol *widgetps_mouse; static t_symbol *widgetps_motion; @@ -176,6 +181,7 @@ static void widget_profile(t_widget *x) #define WIDGETPROFILE_HANDLER_QUIT #endif +/* resolving type and instance arguments into x_xargs */ static char *widget_propsresolver(t_pd *owner, int ac, t_atom *av) { t_widget *x = (t_widget *)owner; @@ -256,7 +262,7 @@ static void widget_transtick(t_widget *x) newt->te_ypix = oldt->te_ypix; outlet_new(newt, &s_); inlet_new(newt, &newt->ob_pd, &s_, &s_); - /* FIXME preserve connections */ + /* LATER preserve connections (although connected widget is a bad thing) */ glist_add(x->x_glist, &newt->te_g); if (glist_isvisible(x->x_glist)) { @@ -337,8 +343,7 @@ static void widget_delete(t_gobj *z, t_glist *glist) static void widget_pushoptions(t_widget *x, int doit) { char *mypathname = widget_getmypathname(x, x->x_glist)->s_name; - if (scriptlet_evaluate(x->x_optscript, x->x_transient, 0, - 0, 0, x->x_arguments)) + if (scriptlet_evaluate(x->x_optscript, x->x_transient, 0, 0, 0, x->x_xargs)) { #ifdef WIDGET_DEBUG int sz; @@ -362,13 +367,12 @@ static void widget_pushinits(t_widget *x) { int sz; if (widgettype_ievaluate(x->x_typedef, x->x_transient, 0, - 0, 0, x->x_arguments)) + 0, 0, x->x_xargs)) scriptlet_vpush(x->x_transient, "typeinit"); else if (*widgettype_getinitializer(x->x_typedef, &sz) && sz > 0) loudbug_bug("widget_pushinits (type)"); } - if (scriptlet_evaluate(x->x_iniscript, x->x_transient, 0, - 0, 0, x->x_arguments)) + if (scriptlet_evaluate(x->x_iniscript, x->x_transient, 0, 0, 0, x->x_xargs)) scriptlet_vpush(x->x_transient, "iteminit"); else if (!scriptlet_isempty(x->x_iniscript)) loudbug_bug("widget_pushinits (instance)"); @@ -381,7 +385,7 @@ static void widget_pushconstructors(t_widget *x) { int sz; if (widgettype_cevaluate(x->x_typedef, x->x_transient, 0, - 0, 0, x->x_arguments)) + 0, 0, x->x_xargs)) scriptlet_push(x->x_transient); else if (*widgettype_getconstructor(x->x_typedef, &sz) && sz > 0) loudbug_bug("widget_pushconstructors (type)"); @@ -395,7 +399,7 @@ static void widget_pushdestructors(t_widget *x) { int sz; if (widgettype_devaluate(x->x_typedef, x->x_transient, 0, - 0, 0, x->x_arguments)) + 0, 0, x->x_xargs)) scriptlet_push(x->x_transient); else if (*widgettype_getdestructor(x->x_typedef, &sz) && sz > 0) loudbug_bug("widget_pushdestructors (type)"); @@ -458,56 +462,59 @@ static void widget_save(t_gobj *z, t_binbuf *bb) binbuf_addsemi(bb); } -/* FIXME */ -static void widget_properties(t_gobj *z, t_glist *glist) +static void widget_editorappend(t_widget *x, t_props *pp) { - t_widget *x = (t_widget *)z; + int ac; t_atom *ap; - int ac, nleft; - char *head = scriptlet_getcontents(x->x_optscript, &nleft); - char buf[MAXPDSTRING + 1]; - buf[MAXPDSTRING] = 0; - sprintf(buf, "%s %s", x->x_type->s_name, x->x_name->s_name); - hammereditor_open(x->x_filehandle, buf, 0); - while (nleft > 0) - { - if (nleft > MAXPDSTRING) - { - strncpy(buf, head, MAXPDSTRING); - head += MAXPDSTRING; - nleft -= MAXPDSTRING; - } - else - { - strncpy(buf, head, nleft); - buf[nleft] = 0; - nleft = 0; - } - hammereditor_append(x->x_filehandle, buf); - } - scriptlet_reset(x->x_auxscript); - ap = props_getall(x->x_handlers, &ac); - if (ac) scriptlet_add(x->x_auxscript, 0, 0, ac, ap); - head = scriptlet_getcontents(x->x_auxscript, &nleft); - hammereditor_append(x->x_filehandle, "\n"); - while (nleft > 0) + if (ap = props_getfirst(pp, &ac)) { - if (nleft > MAXPDSTRING) - { - strncpy(buf, head, MAXPDSTRING); - head += MAXPDSTRING; - nleft -= MAXPDSTRING; - } - else + if (pp != x->x_diffoptions) + hammereditor_append(x->x_filehandle, "\n"); + do { - strncpy(buf, head, nleft); - buf[nleft] = 0; - nleft = 0; + int nleft; + char buf[MAXPDSTRING + 1], *head; + buf[MAXPDSTRING] = 0; + scriptlet_reset(x->x_auxscript); + scriptlet_add(x->x_auxscript, 0, 0, ac, ap); + head = scriptlet_getcontents(x->x_auxscript, &nleft); + while (nleft > 0) + { + if (nleft > MAXPDSTRING) + { + strncpy(buf, head, MAXPDSTRING); + head += MAXPDSTRING; + nleft -= MAXPDSTRING; + } + else + { + strncpy(buf, head, nleft); + buf[nleft] = 0; + nleft = 0; + } + hammereditor_append(x->x_filehandle, buf); + } + hammereditor_append(x->x_filehandle, "\n"); } - hammereditor_append(x->x_filehandle, buf); + while (ap = props_getnext(pp, &ac)); } } +static void widget_properties(t_gobj *z, t_glist *glist) +{ + t_widget *x = (t_widget *)z; + char buf[MAXPDSTRING]; + sprintf(buf, "%s %s", x->x_type->s_name, x->x_name->s_name); + hammereditor_open(x->x_filehandle, buf, 0); + widget_editorappend(x, x->x_diffoptions); + widget_editorappend(x, x->x_options); + widget_editorappend(x, x->x_diffhandlers); + widget_editorappend(x, x->x_handlers); + widget_editorappend(x, x->x_diffarguments); + widget_editorappend(x, x->x_arguments); + hammereditor_setdirty(x->x_filehandle, 0); +} + static t_widgetbehavior widget_behavior = { widget_getrect, @@ -532,8 +539,10 @@ static void widget_update(t_widget *x, t_props *op) { t_atom *ap; int ac; + props_diff(x->x_diffoptions, + widgettype_getoptions(x->x_typedef), x->x_options); scriptlet_reset(x->x_optscript); - ap = props_getall(widgettype_getoptions(x->x_typedef), &ac); + ap = props_getall(x->x_diffoptions, &ac); if (ac) scriptlet_add(x->x_optscript, 0, 0, ac, ap); ap = props_getall(x->x_options, &ac); if (ac) scriptlet_add(x->x_optscript, 0, 0, ac, ap); @@ -553,21 +562,32 @@ static void widget_update(t_widget *x, t_props *op) x->x_update = WIDGET_NOVIS; } } - else + else if (op == x->x_handlers) { + props_diff(x->x_diffhandlers, + widgettype_gethandlers(x->x_typedef), x->x_handlers); /* LATER cache handlers. We get here both during construction, and after any change in our handlers -- the cache never stales. */ } + else if (op == x->x_arguments) + { + props_diff(x->x_diffarguments, + widgettype_getarguments(x->x_typedef), x->x_arguments); + props_clearvalues(x->x_xargs); + props_clonevalues(x->x_xargs, x->x_diffarguments); + props_clonevalues(x->x_xargs, x->x_arguments); + } } -static t_symbol *widget_addprops(t_widget *x, t_props *op, int single, +static t_symbol *widget_addprops(t_widget *x, t_props *op, + int single, t_props *filter, t_symbol *s, int ac, t_atom *av) { if (op) { t_symbol *empty; - empty = props_add(op, single, s, ac, av); + empty = props_add(op, single, filter, s, ac, av); if (empty) loud_error((t_pd *)x, "no value given for %s '%s'", props_getname(op), empty->s_name); @@ -581,12 +601,34 @@ static t_symbol *widget_addprops(t_widget *x, t_props *op, int single, } } -static t_symbol *widget_addmessage(t_widget *x, t_symbol *s, int ac, t_atom *av) +static t_symbol *widget_addmessage(t_widget *x, int unique, + t_symbol *s, int ac, t_atom *av) { t_symbol *empty; - if (!(empty = widget_addprops(x, x->x_arguments, 0, s, ac, av)) && - !(empty = widget_addprops(x, x->x_handlers, 0, s, ac, av))) - empty = widget_addprops(x, x->x_options, 0, s, ac, av); + if (s) + { + /* FIXME mixed messages */ + if (*s->s_name == '-') + x->x_update = WIDGET_PUSHVIS; + else if (*s->s_name == '#') + x->x_update = WIDGET_REVIS; + else + x->x_update = WIDGET_NOVIS; + } + /* Instance-type duplicates are not removed, unless 'unique' is set. + If it is set, we are called from editorhook, so we assume duplicates + were not specified explicitly. In other cases we keep duplicates, + because type may change until next time this widget is created or + refreshed. */ + if (!(empty = widget_addprops(x, x->x_arguments, 0, + (unique ? x->x_diffarguments : 0), + s, ac, av)) && + !(empty = widget_addprops(x, x->x_handlers, 0, + (unique ? x->x_diffhandlers : 0), + s, ac, av))) + empty = widget_addprops(x, x->x_options, 0, + (unique ? x->x_diffoptions : 0), + s, ac, av); return (empty); } @@ -597,14 +639,7 @@ static void widget_anything(t_widget *x, t_symbol *s, int ac, t_atom *av) if (*s->s_name == '-' || *s->s_name == '@' || *s->s_name == '#') { t_symbol *empty; - /* FIXME mixed messages */ - if (*s->s_name == '-') - x->x_update = WIDGET_PUSHVIS; - else if (*s->s_name == '#') - x->x_update = WIDGET_REVIS; - else - x->x_update = WIDGET_NOVIS; - if (empty = widget_addmessage(x, s, ac, av)) + if (empty = widget_addmessage(x, 0, s, ac, av)) loud_errand((t_pd *)x, "(use 'remove %s' if that is what you want).", empty->s_name); @@ -629,7 +664,7 @@ static void widget_anything(t_widget *x, t_symbol *s, int ac, t_atom *av) scriptlet_reset(x->x_auxscript); scriptlet_add(x->x_auxscript, 0, 0, hlen - 1, hp + 1); if (scriptlet_evaluate(x->x_auxscript, x->x_transient, 1, - ac, av, x->x_arguments)) + ac, av, x->x_xargs)) { WIDGETPROFILE_HANDLER_PUSH; scriptlet_push(x->x_transient); @@ -681,7 +716,7 @@ static void widget_float(t_widget *x, t_float f) scriptlet_reset(x->x_auxscript); scriptlet_add(x->x_auxscript, 0, 0, ac - 1, av + 1); if (scriptlet_evaluate(x->x_auxscript, x->x_transient, 1, - 1, &at, x->x_arguments)) + 1, &at, x->x_xargs)) { WIDGETPROFILE_HANDLER_PUSH; scriptlet_push(x->x_transient); @@ -709,7 +744,7 @@ static void widget_symbol(t_widget *x, t_symbol *s) scriptlet_reset(x->x_auxscript); scriptlet_add(x->x_auxscript, 0, 0, ac - 1, av + 1); if (scriptlet_evaluate(x->x_auxscript, x->x_transient, 1, - 1, &at, x->x_arguments)) + 1, &at, x->x_xargs)) { WIDGETPROFILE_HANDLER_PUSH; scriptlet_push(x->x_transient); @@ -743,12 +778,12 @@ static void widget_set(t_widget *x, t_symbol *s, int ac, t_atom *av) if (*prp->s_name == '-') { x->x_update = WIDGET_PUSHVIS; - empty = widget_addprops(x, x->x_options, 1, prp, ac, av); + empty = widget_addprops(x, x->x_options, 1, 0, prp, ac, av); } else if (*prp->s_name == '@') - empty = widget_addprops(x, x->x_handlers, 1, prp, ac, av); + empty = widget_addprops(x, x->x_handlers, 1, 0, prp, ac, av); else if (*prp->s_name == '#') - empty = widget_addprops(x, x->x_arguments, 1, prp, ac, av); + empty = widget_addprops(x, x->x_arguments, 1, 0, prp, ac, av); if (empty) loud_errand((t_pd *)x, "(use 'remove %s' if that is what you want).", @@ -772,7 +807,8 @@ static void widget_remove(t_widget *x, t_symbol *s) op = 0; if (op && props_remove(op, s)) { - if (op == x->x_options) x->x_update = WIDGET_REVIS; + if (op == x->x_options) /* LATER rethink */ + x->x_update = WIDGET_REVIS; widget_update(x, op); } else loud_warning((t_pd *)x, 0, "%s %s has not been specified", @@ -795,7 +831,7 @@ static void widget_tot(t_widget *x, t_symbol *s, int ac, t_atom *av) scriptlet_reset(x->x_auxscript); scriptlet_add(x->x_auxscript, 1, 1, ac, av); if (scriptlet_evaluate(x->x_auxscript, x->x_transient, 1, - 0, 0, x->x_arguments)) + 0, 0, x->x_xargs)) scriptlet_push(x->x_transient); } } @@ -803,21 +839,23 @@ static void widget_tot(t_widget *x, t_symbol *s, int ac, t_atom *av) static void widget_refresh(t_widget *x) { x->x_update = WIDGET_REVIS; - widget_update(x, x->x_options); - widget_update(x, x->x_handlers); widget_update(x, x->x_arguments); + widget_update(x, x->x_handlers); + widget_update(x, x->x_options); } static int widget_resettype(t_widget *x, t_widgettype *wt) { - if (wt == x->x_typedef) + if (!wt || /* LATER rethink, cf widgettype_reload() */ + wt == x->x_typedef) { if (!(x->x_tkclass = widgettype_tkclass(x->x_typedef))) x->x_tkclass = x->x_type; - props_clone(x->x_arguments, widgettype_getarguments(x->x_typedef)); - /* FIXME widget_addmessage(x, 0, ac, av); */ + x->x_update = WIDGET_REVIS; + widget_update(x, x->x_arguments); widget_pushconstructors(x); - widget_refresh(x); + widget_update(x, x->x_handlers); + widget_update(x, x->x_options); return (1); } else @@ -832,6 +870,14 @@ static void widget_redefine(t_widget *x) widget_resettype(x, widgettype_reload(x->x_type)); } +static void widget_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av) +{ + t_widget *x = (t_widget *)z; + props_clearall(x->x_options); + widget_addmessage(x, 1, 0, ac, av); + widget_refresh(x); +} + static void widget__failure(t_widget *x) { loud_error((t_pd *)x, "creation failure"); @@ -994,18 +1040,21 @@ static void widget_debug(t_widget *x) widgetbug_postprops("default options:", widgettype_getoptions(x->x_typedef)); widgetbug_postprops("instance options:", x->x_options); + widgetbug_postprops("diff options:", x->x_diffoptions); widgetbug_postprops("default handlers:", widgettype_gethandlers(x->x_typedef)); widgetbug_postprops("instance handlers:", x->x_handlers); + widgetbug_postprops("diff handlers:", x->x_diffhandlers); widgetbug_postprops("default arguments:", widgettype_getarguments(x->x_typedef)); widgetbug_postprops("instance arguments:", x->x_arguments); + widgetbug_postprops("diff arguments:", x->x_diffarguments); loudbug_post("dictionary:"); - bp = props_firstvalue(x->x_arguments, &key); + bp = props_firstvalue(x->x_xargs, &key); while (bp) { loudbug_post("\t%s: \"%s\"", key, bp); - bp = props_nextvalue(x->x_arguments, &key); + bp = props_nextvalue(x->x_xargs, &key); } bp = scriptlet_getcontents(x->x_transient, &sz); loudbug_post("transient buffer (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); @@ -1044,6 +1093,8 @@ static void widget_free(t_widget *x) gui_unbind((t_pd *)x, x->x_cbtarget); gui_unbind((t_pd *)x, x->x_rptarget); props_freeall(x->x_options); + props_freeall(x->x_xargs); + props_freeall(x->x_diffoptions); scriptlet_free(x->x_iniscript); scriptlet_free(x->x_optscript); scriptlet_free(x->x_auxscript); @@ -1111,8 +1162,13 @@ static void *widget_new(t_symbol *s, int ac, t_atom *av) x->x_options = props_new((t_pd *)x, "option", "-", 0, 0); x->x_handlers = props_new((t_pd *)x, "handler", "@", x->x_options, 0); - x->x_arguments = props_new((t_pd *)x, "argument", "#", x->x_options, - widget_propsresolver); + x->x_arguments = props_new((t_pd *)x, "argument", "#", x->x_options, 0); + x->x_xargs = props_new((t_pd *)x, "argument", "#", 0, widget_propsresolver); + x->x_diffoptions = props_new((t_pd *)x, "option", "-", 0, 0); + x->x_diffhandlers = props_new((t_pd *)x, "handler", "@", + x->x_diffoptions, 0); + x->x_diffarguments = props_new((t_pd *)x, "argument", "#", + x->x_diffoptions, 0); outlet_new((t_object *)x, &s_anything); /* LATER consider estimating these, based on widget class and options. @@ -1121,9 +1177,7 @@ static void *widget_new(t_symbol *s, int ac, t_atom *av) but finding gops stretched, to accomodate the widget's default area. */ x->x_width = 5; x->x_height = 5; - props_clone(x->x_arguments, widgettype_getarguments(x->x_typedef)); - widget_addmessage(x, 0, ac, av); - x->x_filehandle = hammerfile_new((t_pd *)x, 0, 0, 0, 0); + x->x_filehandle = hammerfile_new((t_pd *)x, 0, 0, 0, widget_editorhook); x->x_transclock = clock_new(x, (t_method)widget_transtick); x->x_background = 0; x->x_hasstate = 0; @@ -1131,75 +1185,19 @@ static void *widget_new(t_symbol *s, int ac, t_atom *av) x->x_disabled = 0; x->x_vised = 0; widget_attach(x); + widget_addmessage(x, 0, 0, ac, av); widget_pushconstructors(x); return (x); } static t_glist *tow_getglist(t_tow *x, int complain) { - t_glist *glist = - (x->x_cvremote ? - (t_glist *)pd_findbyclass(x->x_cvremote, canvas_class) : x->x_glist); - if (!glist && complain) + t_glist *glist = (x->x_cvremote ? + (t_glist *)pd_findbyclass(x->x_cvremote, canvas_class) : + x->x_targetglist); + if (!glist && x->x_cvname && complain) loud_error((t_pd *)x, "bad canvas name '%s'", x->x_cvname->s_name); - return (glist_getcanvas(glist)); -} - -static void tow_bang(t_tow *x) -{ - t_widgetentry *we; - for (we = x->x_widgetlist; we; we = we->we_next) - widget_bang(we->we_widget); -} - -static void tow_float(t_tow *x, t_float f) -{ - t_widgetentry *we; - for (we = x->x_widgetlist; we; we = we->we_next) - widget_float(we->we_widget, f); -} - -static void tow_symbol(t_tow *x, t_symbol *s) -{ - t_widgetentry *we; - for (we = x->x_widgetlist; we; we = we->we_next) - widget_symbol(we->we_widget, s); -} - -static void tow_anything(t_tow *x, t_symbol *s, int ac, t_atom *av) -{ - t_widgetentry *we; - for (we = x->x_widgetlist; we; we = we->we_next) - typedmess((t_pd *)we->we_widget, s, ac, av); -} - -static void tow_redefine(t_tow *x) -{ - t_widgettype *wt = widgettype_reload(x->x_type); - t_widgetentry *we; - for (we = x->x_widgetlist; we; we = we->we_next) - if (!widget_resettype(we->we_widget, wt)) - break; -} - -static void tow__callback(t_tow *x, t_symbol *s, int ac, t_atom *av) -{ - if (ac == 1) - { - if (av->a_type == A_FLOAT) - outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); - else if (av->a_type == A_SYMBOL) - outlet_symbol(((t_object *)x)->ob_outlet, av->a_w.w_symbol); - } - else if (ac) - { - if (av->a_type == A_FLOAT) - outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); - else if (av->a_type == A_SYMBOL) - outlet_anything(((t_object *)x)->ob_outlet, - av->a_w.w_symbol, ac - 1, av + 1); - } - else outlet_bang(((t_object *)x)->ob_outlet); + return (glist); } static void tow_widgetattach(t_tow *x, t_widget *w) @@ -1246,7 +1244,7 @@ static void tow_widgetdetach(t_tow *x, t_widget *w) static void widget_attach(t_widget *x) { t_tow *t; - for (t = towlist; t; t = t->x_next) + for (t = widget_towlist; t; t = t->x_next) if (x->x_glist == tow_getglist(t, 0) && t->x_type == x->x_type && t->x_name == x->x_name) tow_widgetattach(t, x); @@ -1285,7 +1283,8 @@ static void tow_attach(t_tow *x) #endif } #ifdef TOW_DEBUG - else loudbug_post("glist '%s' not found", x->x_cvname->s_name); + else if (x->x_cvname) + loudbug_post("glist '%s' not found", x->x_cvname->s_name); #endif } @@ -1320,6 +1319,116 @@ static void tow_detach(t_tow *x) } } +static void tow_bang(t_tow *x) +{ + t_widgetentry *we; + for (we = x->x_widgetlist; we; we = we->we_next) + widget_bang(we->we_widget); +} + +static void tow_float(t_tow *x, t_float f) +{ + t_widgetentry *we; + for (we = x->x_widgetlist; we; we = we->we_next) + widget_float(we->we_widget, f); +} + +static void tow_symbol(t_tow *x, t_symbol *s) +{ + t_widgetentry *we; + for (we = x->x_widgetlist; we; we = we->we_next) + widget_symbol(we->we_widget, s); +} + +static void tow_anything(t_tow *x, t_symbol *s, int ac, t_atom *av) +{ + t_widgetentry *we; + for (we = x->x_widgetlist; we; we = we->we_next) + typedmess((t_pd *)we->we_widget, s, ac, av); +} + +static void tow_redefine(t_tow *x) +{ + t_widgettype *wt = widgettype_reload(x->x_type); + t_widgetentry *we; + for (we = x->x_widgetlist; we; we = we->we_next) + if (!widget_resettype(we->we_widget, wt)) + break; +} + +/* LATER broadcasting: canvas-wide or type-on-canvas-wide */ +static void tow_settarget(t_tow *x, t_symbol *s1, t_symbol *s2, t_symbol *s3) +{ + char buf[64]; + if (s1 == &s_ || !strcmp(s1->s_name, ".")) + s1 = 0; + if (s1 && strcmp(s1->s_name, ".parent")) + { + x->x_cvremote = canvas_makebindsym(x->x_cvname = s1); + x->x_targetglist = 0; + } + else + { + x->x_cvremote = 0; + if (s1) + { + if (x->x_glist->gl_owner) + x->x_targetglist = x->x_glist->gl_owner; + else + { /* The case of a tow pointing out from an abstraction, + targeting its parent, is considered invalid (otherwise, + opening an abstraction as a top-level patch should not be + flagged as error). LATER rethink. */ + loud_error((t_pd *)x, "parent of a top level patch requested,"); + loud_errand((t_pd *)x, "this is a dangling tow..."); + x->x_cvname = 0; + x->x_targetglist = 0; + } + } + else x->x_targetglist = x->x_glist; + } + if (x->x_targetglist) + x->x_cvname = x->x_targetglist->gl_name; + x->x_type = s2; + x->x_name = s3; + tow_attach(x); +} + +static void tow_retarget(t_tow *x, t_symbol *s1, t_symbol *s2, t_symbol *s3) +{ + tow_detach(x); + tow_settarget(x, s1, s2, s3); +} + +static void tow_pwd(t_tow *x, t_symbol *s) +{ + t_glist *glist; + t_symbol *dir; + if (s && s->s_thing && (glist = tow_getglist(x, 1)) && + (dir = canvas_getdir(glist))) + pd_symbol(s->s_thing, dir); +} + +static void tow__callback(t_tow *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac == 1) + { + if (av->a_type == A_FLOAT) + outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); + else if (av->a_type == A_SYMBOL) + outlet_symbol(((t_object *)x)->ob_outlet, av->a_w.w_symbol); + } + else if (ac) + { + if (av->a_type == A_FLOAT) + outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); + else if (av->a_type == A_SYMBOL) + outlet_anything(((t_object *)x)->ob_outlet, + av->a_w.w_symbol, ac - 1, av + 1); + } + else outlet_bang(((t_object *)x)->ob_outlet); +} + #ifdef TOW_DEBUG static void tow_debug(t_tow *x) { @@ -1349,14 +1458,14 @@ static void tow_free(t_tow *x) #ifdef TOW_DEBUG loudbug_startpost("updating towlist..."); #endif - for (t1 = 0, t2 = towlist; t2; t2 = t2->x_next) + for (t1 = 0, t2 = widget_towlist; t2; t2 = t2->x_next) { if (t2 == x) { if (t1) t1->x_next = t2->x_next; else - towlist = t2->x_next; + widget_towlist = t2->x_next; #ifdef TOW_DEBUG loudbug_post("ok"); #endif @@ -1370,42 +1479,13 @@ static void tow_free(t_tow *x) static void *tow_new(t_symbol *s1, t_symbol *s2, t_symbol *s3) { t_tow *x = (t_tow *)pd_new(tow_class); - char buf[64]; x->x_glist = canvas_getcurrent(); - if (s1 == &s_ || !strcmp(s1->s_name, ".")) - s1 = 0; - if (s1) - { - if (strcmp(s1->s_name, ".parent")) - x->x_cvremote = canvas_makebindsym(x->x_cvname = s1); - else - { - if (x->x_glist->gl_owner) - { - x->x_glist = x->x_glist->gl_owner; - x->x_cvremote = 0; - x->x_cvname = x->x_glist->gl_name; - } - else - { - /* FIXME */ - loud_error((t_pd *)x, "no parent patch"); - x->x_cvremote = canvas_makebindsym(x->x_cvname = s1); - } - } - } - else - { - x->x_cvremote = 0; - x->x_cvname = x->x_glist->gl_name; - } - x->x_type = s2; - x->x_name = s3; - outlet_new((t_object *)x, &s_anything); + x->x_targetglist = 0; x->x_widgetlist = 0; - x->x_next = towlist; - towlist = x; - tow_attach(x); + x->x_next = widget_towlist; + widget_towlist = x; + outlet_new((t_object *)x, &s_anything); + tow_settarget(x, s1, s2, s3); return (x); } @@ -1481,13 +1561,17 @@ void widget_setup(void) tow_class = class_new(gensym("tow"), (t_newmethod)tow_new, (t_method)tow_free, - sizeof(t_tow), 0, A_SYMBOL, A_SYMBOL, A_SYMBOL, 0); + sizeof(t_tow), 0, A_SYMBOL, A_DEFSYM, A_DEFSYM, 0); class_addbang(tow_class, tow_bang); class_addfloat(tow_class, tow_float); class_addsymbol(tow_class, tow_symbol); class_addanything(tow_class, tow_anything); class_addmethod(tow_class, (t_method)tow_redefine, gensym("redefine"), 0); + class_addmethod(tow_class, (t_method)tow_retarget, + gensym("retarget"), A_SYMBOL, A_SYMBOL, A_SYMBOL, 0); + class_addmethod(tow_class, (t_method)tow_pwd, + gensym("pwd"), A_SYMBOL, 0); class_addmethod(tow_class, (t_method)tow__callback, gensym("_cb"), A_GIMME, 0); #ifdef TOW_DEBUG diff --git a/toxy/widgettype.c b/toxy/widgettype.c index 0b993c1..166a417 100644 --- a/toxy/widgettype.c +++ b/toxy/widgettype.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2003-2004 krzYszcz and others. +/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ @@ -20,9 +20,10 @@ static char masterwidget_builtin[] = struct _widgettype { t_pd wt_pd; - t_symbol *wt_typekey; /* this is a typemap symbol */ - t_symbol *wt_tkclass; /* also 'undefined' flag (gensym symbol) */ - t_symbol *wt_tkpackage; /* gensym symbol */ + t_symbol *wt_typekey; /* this is a typemap symbol */ + t_symbol *wt_tkclass; /* also 'undefined' flag (gensym symbol) */ + t_symbol *wt_tkpackage; /* gensym symbol */ + int wt_isinternal; /* true if built-in or defined in setup.wid */ t_props *wt_options; t_props *wt_handlers; t_props *wt_arguments; @@ -57,6 +58,14 @@ static void widgettype_map(t_widgettype *wt, char *cls, char *pkg) wt->wt_tkpackage = (pkg ? gensym(pkg) : 0); } +static void widgettype_clear(t_widgettype *wt) +{ + props_clearall(wt->wt_options); + scriptlet_reset(wt->wt_iniscript); + scriptlet_reset(wt->wt_newscript); + scriptlet_reset(wt->wt_freescript); +} + #if 0 /* only for debugging (never call, unless certain that nobody references wt) */ static void widgettype_free(t_masterwidget *mw, t_widgettype *wt) @@ -78,6 +87,7 @@ static t_widgettype *widgettype_new(t_masterwidget *mw, t_widgettype *wt = (t_widgettype *)pd_new(widgettype_class); wt->wt_typekey = dict_key(mw->mw_typemap, typ); widgettype_map(wt, cls, pkg); + wt->wt_isinternal = 0; wt->wt_options = props_new(0, "option", "-", 0, 0); wt->wt_handlers = props_new(0, "handler", "@", wt->wt_options, 0); wt->wt_arguments = props_new(0, "argument", "#", wt->wt_options, 0); @@ -117,7 +127,8 @@ static t_scriptlet *masterwidget_cmnthook(t_pd *caller, char *rc, { /* setup.wid or built-in defaults */ if (typeval) { - /* LATER rethink */ + /* LATER may need revisiting, when/if we accept explicit + 'redefine' requests for internal types */ loud_warning((t_pd *)mw, 0, "redefinition of '%s'\ in \"%s.wid\" file, ignored", buf, rc); return (SCRIPTLET_LOCK); @@ -138,7 +149,10 @@ static t_scriptlet *masterwidget_cmnthook(t_pd *caller, char *rc, if (typeval) widgettype_map(typeval, cls, pkg); else + { typeval = widgettype_new(mw, buf, cls, pkg); + typeval->wt_isinternal = (caller == (t_pd *)mw); + } mw->mw_parsedtype = typeval; #ifdef WIDGETTYPE_DEBUG loudbug_post("adding widget type '%s'", typeval->wt_typekey->s_name); @@ -160,11 +174,11 @@ static t_scriptlet *masterwidget_cmnthook(t_pd *caller, char *rc, t_atom *av = binbuf_getvec(mw->mw_bb); t_props *pp; if (!(empty = props_add(pp = mw->mw_parsedtype->wt_options, - 0, 0, ac, av)) && + 0, 0, 0, ac, av)) && !(empty = props_add(pp = mw->mw_parsedtype->wt_handlers, - 0, 0, ac, av))) + 0, 0, 0, ac, av))) empty = props_add(pp = mw->mw_parsedtype->wt_arguments, - 0, 0, ac, av); + 0, 0, 0, ac, av); if (empty) loud_warning((t_pd *)mw, 0, "no value given for %s '%s'\ @@ -266,8 +280,13 @@ t_widgettype *widgettype_reload(t_symbol *s) if (!wt) /* first instance of a type not defined in setup.wid */ wt = widgettype_new(masterwidget, s->s_name, 0, 0); - widgettype_doload(wt, s); - return (wt); + if (wt && !wt->wt_isinternal) + { /* LATER consider safe-loading through a temporary type */ + widgettype_clear(wt); + if (widgettype_doload(wt, s)) + return (wt); + } + return (0); } int widgettype_isdefined(t_widgettype *wt) |