aboutsummaryrefslogtreecommitdiff
path: root/pd/src/g_scalar.c
diff options
context:
space:
mode:
Diffstat (limited to 'pd/src/g_scalar.c')
-rw-r--r--pd/src/g_scalar.c373
1 files changed, 373 insertions, 0 deletions
diff --git a/pd/src/g_scalar.c b/pd/src/g_scalar.c
new file mode 100644
index 00000000..362fb108
--- /dev/null
+++ b/pd/src/g_scalar.c
@@ -0,0 +1,373 @@
+/* Copyright (c) 1997-1999 Miller Puckette.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* This file defines the "scalar" object, which is not a text object, just a
+"gobj". Scalars have templates which describe their structures, which
+can contain numbers, sublists, and arrays.
+
+Also, the "tscalar" object, an ordinary text object that owns a single "scalar"
+and draws it on the parent. This is intended as a way that abstractions can
+control their appearances by adding stuff to draw.
+*/
+
+/* IOhannes :
+ * changed the canvas_restore, so that it might accept $args as well (like "pd $0_test")
+ * so you can make multiple & distinguishable templates
+ * 1511:forum::für::umläute:2001
+ * changes marked with IOhannes
+ * added Krzysztof Czajas fix to avoid crashing...
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h> /* for read/write to files */
+#include "m_pd.h"
+#include "g_canvas.h"
+
+t_class *scalar_class;
+
+void word_init(t_word *wp, t_template *template, t_gpointer *gp)
+{
+ int i, nitems = template->t_n;
+ t_dataslot *datatypes = template->t_vec;
+ for (i = 0; i < nitems; i++, datatypes++, wp++)
+ {
+ int type = datatypes->ds_type;
+ if (type == DT_FLOAT)
+ wp->w_float = 0;
+ else if (type == DT_SYMBOL)
+ wp->w_symbol = &s_symbol;
+ else if (type == DT_ARRAY)
+ {
+ wp->w_array = array_new(datatypes->ds_arraytemplate, gp);
+ }
+ else if (type == DT_LIST)
+ {
+ /* LATER test this and get it to work */
+ wp->w_list = canvas_new(0, 0, 0, 0);
+ }
+ }
+}
+
+void word_restore(t_word *wp, t_template *template,
+ int argc, t_atom *argv)
+{
+ int i, nitems = template->t_n;
+ t_dataslot *datatypes = template->t_vec;
+ for (i = 0; i < nitems; i++, datatypes++, wp++)
+ {
+ int type = datatypes->ds_type;
+ if (type == DT_FLOAT)
+ {
+ float f;
+ if (argc)
+ {
+ f = atom_getfloat(argv);
+ argv++, argc--;
+ }
+ else f = 0;
+ wp->w_float = f;
+ }
+ else if (type == DT_SYMBOL)
+ {
+ t_symbol *s;
+ if (argc)
+ {
+ s = atom_getsymbol(argv);
+ argv++, argc--;
+ }
+ else s = &s_;
+ wp->w_symbol = s;
+ }
+ }
+ if (argc)
+ post("warning: word_restore: extra arguments");
+}
+
+ /* make a new scalar and add to the glist. We create a "gp" here which
+ will be used for array items to point back here. This gp doesn't do
+ reference counting or "validation" updates though; the parent won't go away
+ without the contained arrays going away too. The "gp" is copied out
+ by value in the word_init() routine so we can throw our copy away. */
+
+t_scalar *scalar_new(t_glist *owner, t_symbol *templatesym)
+{
+ t_scalar *x;
+ t_template *template;
+ t_gpointer gp;
+ gpointer_init(&gp);
+ template = template_findbyname(templatesym);
+ if (!template)
+ {
+ error("scalar: couldn't find template %s", templatesym->s_name);
+ return (0);
+ }
+ x = (t_scalar *)getbytes(sizeof(t_scalar) +
+ (template->t_n - 1) * sizeof(*x->sc_vec));
+ x->sc_gobj.g_pd = scalar_class;
+ x->sc_template = templatesym;
+ gpointer_setglist(&gp, owner, x);
+ word_init(x->sc_vec, template, &gp);
+ return (x);
+}
+
+ /* Pd method to create a new scalar, add it to a glist, and initialize
+ it from the message arguments. */
+
+int glist_readscalar(t_glist *x, int natoms, t_atom *vec,
+ int *p_nextmsg, int selectit);
+
+void glist_scalar(t_glist *glist,
+ t_symbol *classname, t_int argc, t_atom *argv)
+{
+ t_symbol *templatesym =
+ canvas_makebindsym(atom_getsymbolarg(0, argc, argv));
+ t_binbuf *b;
+ int natoms, nextmsg = 0;
+ t_atom *vec;
+ if (!template_findbyname(templatesym))
+ {
+ pd_error(glist, "%s: no such template",
+ atom_getsymbolarg(0, argc, argv)->s_name);
+ return;
+ }
+
+ b = binbuf_new();
+ binbuf_restore(b, argc, argv);
+ natoms = binbuf_getnatom(b);
+ vec = binbuf_getvec(b);
+
+ glist_readscalar(glist, natoms, vec, &nextmsg, 0);
+ binbuf_free(b);
+}
+
+/* -------------------- widget behavior for scalar ------------ */
+void scalar_getbasexy(t_scalar *x, float *basex, float *basey)
+{
+ t_template *template = template_findbyname(x->sc_template);
+ *basex = template_getfloat(template, gensym("x"), x->sc_vec, 0);
+ *basey = template_getfloat(template, gensym("y"), x->sc_vec, 0);
+}
+
+static void scalar_getrect(t_gobj *z, t_glist *owner,
+ int *xp1, int *yp1, int *xp2, int *yp2)
+{
+ t_scalar *x = (t_scalar *)z;
+ int hit = 0;
+ t_template *template = template_findbyname(x->sc_template);
+ t_canvas *templatecanvas = template_findcanvas(template);
+ int x1 = 0x7fffffff, x2 = -0x7fffffff, y1 = 0x7fffffff, y2 = -0x7fffffff;
+ t_gobj *y;
+ float basex, basey;
+ scalar_getbasexy(x, &basex, &basey);
+ for (y = templatecanvas->gl_list; y; y = y->g_next)
+ {
+ t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
+ int nx1, ny1, nx2, ny2;
+ if (!wb) continue;
+ (*wb->w_parentgetrectfn)(y, owner,
+ x->sc_vec, template, basex, basey,
+ &nx1, &ny1, &nx2, &ny2);
+ if (hit)
+ {
+ if (nx1 < x1) x1 = nx1;
+ if (ny1 < y1) y1 = ny1;
+ if (nx2 > x2) x2 = nx2;
+ if (ny2 > y2) y2 = ny2;
+ }
+ else x1 = nx1, y1 = ny1, x2 = nx2, y2 = ny2, hit = 1;
+ }
+ if (!hit) x1 = y1 = x2 = y2 = 0;
+ /* post("scalar x1 %d y1 %d x2 %d y2 %d", x1, y1, x2, y2); */
+ *xp1 = x1;
+ *yp1 = y1;
+ *xp2 = x2;
+ *yp2 = y2;
+}
+
+static void scalar_select(t_gobj *z, t_glist *owner, int state)
+{
+ t_scalar *x = (t_scalar *)z;
+ /* post("scalar_select %d", state); */
+ /* later */
+ if (state)
+ {
+ int x1, y1, x2, y2;
+ scalar_getrect(z, owner, &x1, &y1, &x2, &y2);
+ sys_vgui(".x%x.c create line %d %d %d %d %d %d %d %d %d %d \
+ -width 0 -fill blue -tags select%x\n",
+ glist_getcanvas(owner), x1, y1, x1, y2, x2, y2, x2, y1, x1, y1,
+ x);
+ }
+ else sys_vgui(".x%x.c delete select%x\n", glist_getcanvas(owner), x);
+}
+
+static void scalar_displace(t_gobj *z, t_glist *glist, int dx, int dy)
+{
+ t_scalar *x = (t_scalar *)z;
+ t_symbol *templatesym = x->sc_template;
+ t_template *template = template_findbyname(templatesym);
+ t_symbol *zz;
+ int xonset, yonset, xtype, ytype, gotx, goty;
+ if (!template)
+ {
+ error("scalar: couldn't find template %s", templatesym->s_name);
+ return;
+ }
+ gotx = template_find_field(template, gensym("x"), &xonset, &xtype, &zz);
+ if (gotx && (xtype != DT_FLOAT))
+ gotx = 0;
+ goty = template_find_field(template, gensym("y"), &yonset, &ytype, &zz);
+ if (goty && (ytype != DT_FLOAT))
+ goty = 0;
+ if (gotx)
+ *(t_float *)(((char *)(x->sc_vec)) + xonset) +=
+ dx * (glist_pixelstox(glist, 1) - glist_pixelstox(glist, 0));
+ if (goty)
+ *(t_float *)(((char *)(x->sc_vec)) + yonset) +=
+ dy * (glist_pixelstoy(glist, 1) - glist_pixelstoy(glist, 0));
+ glist_redrawitem(glist, z);
+ if (glist_isselected(glist, z))
+ {
+ scalar_select(z, glist, 0);
+ scalar_select(z, glist, 1);
+ }
+}
+
+static void scalar_activate(t_gobj *z, t_glist *owner, int state)
+{
+ /* post("scalar_activate %d", state); */
+ /* later */
+}
+
+static void scalar_delete(t_gobj *z, t_glist *glist)
+{
+ /* nothing to do */
+}
+
+static void scalar_vis(t_gobj *z, t_glist *owner, int vis)
+{
+ t_scalar *x = (t_scalar *)z;
+ t_template *template = template_findbyname(x->sc_template);
+ t_canvas *templatecanvas = template_findcanvas(template);
+ t_gobj *y;
+ float basex, basey;
+ if (!templatecanvas)
+ {
+ bug("scalar_vis"); /* it's still a bug, have to fix this for real... */
+ return; /* proposed by Krzysztof Czaja to avoid crashing */
+ }
+ scalar_getbasexy(x, &basex, &basey);
+
+ for (y = templatecanvas->gl_list; y; y = y->g_next)
+ {
+ t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
+ if (!wb) continue;
+ (*wb->w_parentvisfn)(y, owner, x->sc_vec, template, basex, basey, vis);
+ }
+}
+
+static int scalar_click(t_gobj *z, struct _glist *owner,
+ int xpix, int ypix, int shift, int alt, int dbl, int doit)
+{
+ t_scalar *x = (t_scalar *)z;
+ int hit = 0;
+ t_template *template = template_findbyname(x->sc_template);
+ t_canvas *templatecanvas = template_findcanvas(template);
+ t_gobj *y;
+ float basex, basey;
+ scalar_getbasexy(x, &basex, &basey);
+ for (y = templatecanvas->gl_list; y; y = y->g_next)
+ {
+ t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
+ if (!wb) continue;
+ if (hit = (*wb->w_parentclickfn)(y, owner,
+ x, template, basex, basey,
+ xpix, ypix, shift, alt, dbl, doit))
+ return (hit);
+ }
+ return (0);
+}
+
+void canvas_writescalar(t_symbol *templatesym, t_word *w, t_binbuf *b,
+ int amarrayelement);
+
+static void scalar_save(t_gobj *z, t_binbuf *b)
+{
+ t_scalar *x = (t_scalar *)z;
+ t_binbuf *b2 = binbuf_new();
+ t_atom a, *argv;
+ int i, argc;
+ canvas_writescalar(x->sc_template, x->sc_vec, b2, 0);
+ binbuf_addv(b, "ss", &s__X, gensym("scalar"));
+ binbuf_addbinbuf(b, b2);
+ binbuf_addsemi(b);
+ binbuf_free(b2);
+}
+
+static void scalar_properties(t_gobj *z, struct _glist *owner)
+{
+ t_scalar *x = (t_scalar *)z;
+ char *buf, buf2[80];
+ int bufsize;
+ t_binbuf *b;
+ glist_noselect(owner);
+ glist_select(owner, z);
+ b = glist_writetobinbuf(owner, 0);
+ binbuf_gettext(b, &buf, &bufsize);
+ binbuf_free(b);
+ t_resizebytes(buf, bufsize, bufsize+1);
+ buf[bufsize] = 0;
+ sprintf(buf2, "pdtk_data_dialog %%s {");
+ gfxstub_new((t_pd *)owner, x, buf2);
+ sys_gui(buf);
+ sys_gui("}\n");
+ t_freebytes(buf, bufsize+1);
+}
+
+static t_widgetbehavior scalar_widgetbehavior =
+{
+ scalar_getrect,
+ scalar_displace,
+ scalar_select,
+ scalar_activate,
+ scalar_delete,
+ scalar_vis,
+ scalar_click,
+ scalar_save,
+ scalar_properties,
+};
+
+static void scalar_free(t_scalar *x)
+{
+ int i;
+ t_dataslot *datatypes, *dt;
+ t_symbol *templatesym = x->sc_template;
+ t_template *template = template_findbyname(templatesym);
+ if (!template)
+ {
+ error("scalar: couldn't find template %s", templatesym->s_name);
+ return;
+ }
+ for (dt = template->t_vec, i = 0; i < template->t_n; i++, dt++)
+ {
+ if (dt->ds_type == DT_ARRAY)
+ array_free(x->sc_vec[i].w_array);
+ else if (dt->ds_type == DT_LIST)
+ canvas_free(x->sc_vec[i].w_list);
+ }
+ gfxstub_deleteforkey(x);
+ /* the "size" field in the class is zero, so Pd doesn't try to free
+ us automatically (see pd_free()) */
+ freebytes(x, sizeof(t_scalar) + (template->t_n - 1) * sizeof(*x->sc_vec));
+}
+
+/* ----------------- setup function ------------------- */
+
+void g_scalar_setup(void)
+{
+ scalar_class = class_new(gensym("scalar"), 0, (t_method)scalar_free, 0,
+ CLASS_GOBJ, 0);
+ class_setwidget(scalar_class, &scalar_widgetbehavior);
+}