aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cyclone/Makefile.sources2
-rw-r--r--cyclone/build_counter4
-rw-r--r--cyclone/hammer/comment.c69
-rw-r--r--cyclone/hammer/seq.c1
-rw-r--r--cyclone/hammer/testmess.c158
-rw-r--r--cyclone/notes.txt8
-rw-r--r--shared/common/loud.c8
-rw-r--r--shared/common/loud.h1
-rw-r--r--shared/common/props.c487
-rw-r--r--shared/common/props.h20
-rw-r--r--shared/getridof.baddeps2
-rw-r--r--shared/hammer/file.c26
-rw-r--r--shared/notes.txt11
-rw-r--r--shared/toxy/scriptlet.c5
-rw-r--r--shared/unstable/fragile.c11
-rw-r--r--shared/unstable/fragile.h1
-rw-r--r--test/toxy/lbpict.wid4
-rw-r--r--test/toxy/setup.wid8
-rw-r--r--test/toxy/stress/bulkyhurd.pd163
-rw-r--r--test/toxy/stress/mstots.pd50
-rw-r--r--test/toxy/stress/nbulkyhurds.pd16
-rw-r--r--toxy/build_counter4
-rw-r--r--toxy/notes.txt16
-rw-r--r--toxy/tot.c148
-rw-r--r--toxy/widget.c474
-rw-r--r--toxy/widgettype.c39
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
diff --git a/toxy/tot.c b/toxy/tot.c
index ef2c978..0fb5763 100644
--- a/toxy/tot.c
+++ b/toxy/tot.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. */
@@ -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)