forked from len0rd/rockbox
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29871 a1c6a512-1295-4272-9138-f99709370657
1510 lines
40 KiB
C
1510 lines
40 KiB
C
/* 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. */
|
|
|
|
/* changes by Thomas Musil IEM KUG Graz Austria 2001 */
|
|
/* the methods for calling the gui-objects from menu are implemented */
|
|
/* all changes are labeled with iemlib */
|
|
|
|
#include "m_pd.h"
|
|
#include "m_imp.h"
|
|
#include "s_stuff.h"
|
|
#include "t_tk.h"
|
|
#include "g_canvas.h"
|
|
|
|
#ifdef ROCKBOX
|
|
#include "plugin.h"
|
|
#include "../../pdbox.h"
|
|
#else /* ROCKBOX */
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#endif /* ROCKBOX */
|
|
|
|
static t_class *text_class;
|
|
static t_class *message_class;
|
|
static t_class *gatom_class;
|
|
static void text_vis(t_gobj *z, t_glist *glist, int vis);
|
|
static void text_displace(t_gobj *z, t_glist *glist,
|
|
int dx, int dy);
|
|
static void text_getrect(t_gobj *z, t_glist *glist,
|
|
int *xp1, int *yp1, int *xp2, int *yp2);
|
|
|
|
void canvas_startmotion(t_canvas *x);
|
|
t_widgetbehavior text_widgetbehavior;
|
|
|
|
/* ----------------- the "text" object. ------------------ */
|
|
|
|
/* add a "text" object (comment) to a glist. While this one goes for any glist,
|
|
the other 3 below are for canvases only. (why?) This is called
|
|
without args if invoked from the GUI; otherwise at least x and y
|
|
are provided. */
|
|
|
|
void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
t_text *x = (t_text *)pd_new(text_class);
|
|
t_atom at;
|
|
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
#endif
|
|
|
|
x->te_width = 0; /* don't know it yet. */
|
|
x->te_type = T_TEXT;
|
|
x->te_binbuf = binbuf_new();
|
|
if (argc > 1)
|
|
{
|
|
x->te_xpix = atom_getfloatarg(0, argc, argv);
|
|
x->te_ypix = atom_getfloatarg(1, argc, argv);
|
|
if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2);
|
|
else
|
|
{
|
|
SETSYMBOL(&at, gensym("comment"));
|
|
binbuf_restore(x->te_binbuf, 1, &at);
|
|
}
|
|
glist_add(gl, &x->te_g);
|
|
}
|
|
else
|
|
{
|
|
int xpix, ypix;
|
|
pd_vmess((t_pd *)glist_getcanvas(gl), gensym("editmode"), "i", 1);
|
|
SETSYMBOL(&at, gensym("comment"));
|
|
glist_noselect(gl);
|
|
glist_getnextxy(gl, &xpix, &ypix);
|
|
x->te_xpix = glist_pixelstox(gl, xpix-3);
|
|
x->te_ypix = glist_pixelstoy(gl, ypix-3);
|
|
binbuf_restore(x->te_binbuf, 1, &at);
|
|
glist_add(gl, &x->te_g);
|
|
glist_noselect(gl);
|
|
glist_select(gl, &x->te_g);
|
|
/* it would be nice to "activate" here, but then the second,
|
|
"put-me-down" click changes the text selection, which is quite
|
|
irritating, so I took this back out. It's OK in messages
|
|
and objects though since there's no text in them at menu
|
|
creation. */
|
|
/* gobj_activate(&x->te_g, gl, 1); */
|
|
canvas_startmotion(glist_getcanvas(gl));
|
|
}
|
|
}
|
|
|
|
/* ----------------- the "object" object. ------------------ */
|
|
|
|
extern t_pd *newest;
|
|
void canvas_getargs(int *argcp, t_atom **argvp);
|
|
|
|
static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected,
|
|
t_binbuf *b)
|
|
{
|
|
t_text *x;
|
|
int argc;
|
|
t_atom *argv;
|
|
newest = 0;
|
|
canvas_setcurrent((t_canvas *)gl);
|
|
canvas_getargs(&argc, &argv);
|
|
binbuf_eval(b, &pd_objectmaker, argc, argv);
|
|
if (binbuf_getnatom(b))
|
|
{
|
|
if (!newest)
|
|
{
|
|
binbuf_print(b);
|
|
post("... couldn't create");
|
|
x = 0;
|
|
}
|
|
else if (!(x = pd_checkobject(newest)))
|
|
{
|
|
binbuf_print(b);
|
|
post("... didn't return a patchable object");
|
|
}
|
|
}
|
|
else x = 0;
|
|
if (!x)
|
|
{
|
|
|
|
/* LATER make the color reflect this */
|
|
x = (t_text *)pd_new(text_class);
|
|
}
|
|
x->te_binbuf = b;
|
|
x->te_xpix = xpix;
|
|
x->te_ypix = ypix;
|
|
x->te_width = 0;
|
|
x->te_type = T_OBJECT;
|
|
glist_add(gl, &x->te_g);
|
|
if (selected)
|
|
{
|
|
/* this is called if we've been created from the menu. */
|
|
glist_select(gl, &x->te_g);
|
|
gobj_activate(&x->te_g, gl, 1);
|
|
}
|
|
if (pd_class(&x->ob_pd) == vinlet_class)
|
|
canvas_resortinlets(glist_getcanvas(gl));
|
|
if (pd_class(&x->ob_pd) == voutlet_class)
|
|
canvas_resortoutlets(glist_getcanvas(gl));
|
|
canvas_unsetcurrent((t_canvas *)gl);
|
|
}
|
|
|
|
/* object creation routine. These are called without any arguments if
|
|
they're invoked from the
|
|
gui; when pasting or restoring from a file, we get at least x and y. */
|
|
|
|
void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
#else
|
|
t_text *x;
|
|
#endif
|
|
|
|
if (argc >= 2)
|
|
{
|
|
t_binbuf *b = binbuf_new();
|
|
binbuf_restore(b, argc-2, argv+2);
|
|
canvas_objtext(gl, atom_getintarg(0, argc, argv),
|
|
atom_getintarg(1, argc, argv), 0, b);
|
|
}
|
|
else
|
|
{
|
|
t_binbuf *b = binbuf_new();
|
|
int xpix, ypix;
|
|
pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
|
|
glist_noselect(gl);
|
|
glist_getnextxy(gl, &xpix, &ypix);
|
|
canvas_objtext(gl, xpix, ypix, 1, b);
|
|
canvas_startmotion(glist_getcanvas(gl));
|
|
}
|
|
}
|
|
|
|
/* make an object box for an object that's already there. */
|
|
|
|
/* iemlib */
|
|
void canvas_iemguis(t_glist *gl, t_symbol *guiobjname)
|
|
{
|
|
t_atom at;
|
|
t_binbuf *b = binbuf_new();
|
|
int xpix, ypix;
|
|
|
|
pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
|
|
glist_noselect(gl);
|
|
SETSYMBOL(&at, guiobjname);
|
|
binbuf_restore(b, 1, &at);
|
|
glist_getnextxy(gl, &xpix, &ypix);
|
|
canvas_objtext(gl, xpix, ypix, 1, b);
|
|
canvas_startmotion(glist_getcanvas(gl));
|
|
}
|
|
|
|
void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("bng"));
|
|
}
|
|
|
|
void canvas_toggle(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("tgl"));
|
|
}
|
|
|
|
void canvas_vslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("vsl"));
|
|
}
|
|
|
|
void canvas_hslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("hsl"));
|
|
}
|
|
|
|
void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("hdl"));
|
|
}
|
|
|
|
void canvas_vdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("vdl"));
|
|
}
|
|
|
|
void canvas_hradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("hradio"));
|
|
}
|
|
|
|
void canvas_vradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("vradio"));
|
|
}
|
|
|
|
void canvas_vumeter(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("vu"));
|
|
}
|
|
|
|
void canvas_mycnv(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("cnv"));
|
|
}
|
|
|
|
void canvas_numbox(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
(void) argc;
|
|
(void) argv;
|
|
#endif
|
|
canvas_iemguis(gl, gensym("nbx"));
|
|
}
|
|
|
|
/* iemlib */
|
|
|
|
void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv)
|
|
{
|
|
x->te_width = 0; /* don't know it yet. */
|
|
x->te_type = T_OBJECT;
|
|
x->te_binbuf = binbuf_new();
|
|
x->te_xpix = atom_getfloatarg(0, argc, argv);
|
|
x->te_ypix = atom_getfloatarg(1, argc, argv);
|
|
if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2);
|
|
glist_add(gl, &x->te_g);
|
|
}
|
|
|
|
/* ---------------------- the "message" text item ------------------------ */
|
|
|
|
typedef struct _messresponder
|
|
{
|
|
t_pd mr_pd;
|
|
t_outlet *mr_outlet;
|
|
} t_messresponder;
|
|
|
|
typedef struct _message
|
|
{
|
|
t_text m_text;
|
|
t_messresponder m_messresponder;
|
|
t_glist *m_glist;
|
|
t_clock *m_clock;
|
|
} t_message;
|
|
|
|
static t_class *message_class, *messresponder_class;
|
|
|
|
static void messresponder_bang(t_messresponder *x)
|
|
{
|
|
outlet_bang(x->mr_outlet);
|
|
}
|
|
|
|
static void messresponder_float(t_messresponder *x, t_float f)
|
|
{
|
|
outlet_float(x->mr_outlet, f);
|
|
}
|
|
|
|
static void messresponder_symbol(t_messresponder *x, t_symbol *s)
|
|
{
|
|
outlet_symbol(x->mr_outlet, s);
|
|
}
|
|
|
|
static void messresponder_list(t_messresponder *x,
|
|
t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
outlet_list(x->mr_outlet, s, argc, argv);
|
|
}
|
|
|
|
static void messresponder_anything(t_messresponder *x,
|
|
t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
outlet_anything(x->mr_outlet, s, argc, argv);
|
|
}
|
|
|
|
static void message_bang(t_message *x)
|
|
{
|
|
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 0, 0);
|
|
}
|
|
|
|
static void message_float(t_message *x, t_float f)
|
|
{
|
|
t_atom at;
|
|
SETFLOAT(&at, f);
|
|
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
|
|
}
|
|
|
|
static void message_symbol(t_message *x, t_symbol *s)
|
|
{
|
|
t_atom at;
|
|
SETSYMBOL(&at, s);
|
|
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
|
|
}
|
|
|
|
static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
#endif
|
|
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, argc, argv);
|
|
}
|
|
|
|
static void message_set(t_message *x, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
#endif
|
|
binbuf_clear(x->m_text.te_binbuf);
|
|
binbuf_add(x->m_text.te_binbuf, argc, argv);
|
|
glist_retext(x->m_glist, &x->m_text);
|
|
}
|
|
|
|
static void message_add2(t_message *x, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
#endif
|
|
binbuf_add(x->m_text.te_binbuf, argc, argv);
|
|
glist_retext(x->m_glist, &x->m_text);
|
|
}
|
|
|
|
static void message_add(t_message *x, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
#endif
|
|
binbuf_add(x->m_text.te_binbuf, argc, argv);
|
|
binbuf_addsemi(x->m_text.te_binbuf);
|
|
glist_retext(x->m_glist, &x->m_text);
|
|
}
|
|
|
|
static void message_click(t_message *x,
|
|
t_floatarg xpos, t_floatarg ypos, t_floatarg shift,
|
|
t_floatarg ctrl, t_floatarg alt)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) xpos;
|
|
(void) ypos;
|
|
(void) shift;
|
|
(void) ctrl;
|
|
(void) alt;
|
|
#endif
|
|
message_float(x, 0);
|
|
if (glist_isvisible(x->m_glist))
|
|
{
|
|
#ifndef ROCKBOX
|
|
t_rtext *y = glist_findrtext(x->m_glist, &x->m_text);
|
|
sys_vgui(".x%x.c itemconfigure %sR -width 5\n",
|
|
glist_getcanvas(x->m_glist), rtext_gettag(y));
|
|
#endif
|
|
clock_delay(x->m_clock, 120);
|
|
}
|
|
}
|
|
|
|
static void message_tick(t_message *x)
|
|
{
|
|
if (glist_isvisible(x->m_glist))
|
|
{
|
|
#ifndef ROCKBOX
|
|
t_rtext *y = glist_findrtext(x->m_glist, &x->m_text);
|
|
sys_vgui(".x%x.c itemconfigure %sR -width 1\n",
|
|
glist_getcanvas(x->m_glist), rtext_gettag(y));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void message_free(t_message *x)
|
|
{
|
|
clock_free(x->m_clock);
|
|
}
|
|
|
|
void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
#endif
|
|
t_message *x = (t_message *)pd_new(message_class);
|
|
x->m_messresponder.mr_pd = messresponder_class;
|
|
x->m_messresponder.mr_outlet = outlet_new(&x->m_text, &s_float);
|
|
x->m_text.te_width = 0; /* don't know it yet. */
|
|
x->m_text.te_type = T_MESSAGE;
|
|
x->m_text.te_binbuf = binbuf_new();
|
|
x->m_glist = gl;
|
|
x->m_clock = clock_new(x, (t_method)message_tick);
|
|
if (argc > 1)
|
|
{
|
|
x->m_text.te_xpix = atom_getfloatarg(0, argc, argv);
|
|
x->m_text.te_ypix = atom_getfloatarg(1, argc, argv);
|
|
if (argc > 2) binbuf_restore(x->m_text.te_binbuf, argc-2, argv+2);
|
|
glist_add(gl, &x->m_text.te_g);
|
|
}
|
|
else
|
|
{
|
|
int xpix, ypix;
|
|
pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
|
|
glist_noselect(gl);
|
|
glist_getnextxy(gl, &xpix, &ypix);
|
|
x->m_text.te_xpix = xpix-3;
|
|
x->m_text.te_ypix = ypix-3;
|
|
glist_add(gl, &x->m_text.te_g);
|
|
glist_noselect(gl);
|
|
glist_select(gl, &x->m_text.te_g);
|
|
gobj_activate(&x->m_text.te_g, gl, 1);
|
|
canvas_startmotion(glist_getcanvas(gl));
|
|
}
|
|
}
|
|
|
|
/* ---------------------- the "atom" text item ------------------------ */
|
|
|
|
#define ATOMBUFSIZE 40
|
|
#define ATOM_LABELLEFT 0
|
|
#define ATOM_LABELRIGHT 1
|
|
#define ATOM_LABELUP 2
|
|
#define ATOM_LABELDOWN 3
|
|
|
|
typedef struct _gatom
|
|
{
|
|
t_text a_text;
|
|
t_atom a_atom; /* this holds the value and the type */
|
|
t_glist *a_glist; /* owning glist */
|
|
t_float a_toggle; /* value to toggle to */
|
|
t_float a_draghi; /* high end of drag range */
|
|
t_float a_draglo; /* low end of drag range */
|
|
t_symbol *a_label; /* symbol to show as label next to box */
|
|
t_symbol *a_symfrom; /* "receive" name -- bind ourselvs to this */
|
|
t_symbol *a_symto; /* "send" name -- send to this on output */
|
|
char a_buf[ATOMBUFSIZE];/* string buffer for typing */
|
|
char a_shift; /* was shift key down when dragging started? */
|
|
char a_wherelabel; /* 0-3 for left, right, above, below */
|
|
t_symbol *a_expanded_to; /* a_symto after $0, $1, ... expansion */
|
|
} t_gatom;
|
|
|
|
/* prepend "-" as necessary to avoid empty strings, so we can
|
|
use them in Pd messages. A more complete solution would be
|
|
to introduce some quoting mechanism; but then we'd be much more
|
|
complicated. */
|
|
static t_symbol *gatom_escapit(t_symbol *s)
|
|
{
|
|
if (!*s->s_name)
|
|
return (gensym("-"));
|
|
else if (*s->s_name == '-')
|
|
{
|
|
char shmo[100];
|
|
shmo[0] = '-';
|
|
strncpy(shmo+1, s->s_name, 99);
|
|
shmo[99] = 0;
|
|
return (gensym(shmo));
|
|
}
|
|
else return (iemgui_dollar2raute(s));
|
|
}
|
|
|
|
/* undo previous operation: strip leading "-" if found. */
|
|
static t_symbol *gatom_unescapit(t_symbol *s)
|
|
{
|
|
if (*s->s_name == '-')
|
|
return (gensym(s->s_name+1));
|
|
else return (iemgui_raute2dollar(s));
|
|
}
|
|
|
|
#if 0 /* ??? */
|
|
/* expand leading $0, $1, etc. in the symbol */
|
|
static t_symbol *gatom_realizedollar(t_gatom *x, t_symbol *s)
|
|
{
|
|
return (canvas_realizedollar(x->a_glist, s));
|
|
}
|
|
#endif
|
|
|
|
static void gatom_retext(t_gatom *x, int senditup)
|
|
{
|
|
binbuf_clear(x->a_text.te_binbuf);
|
|
binbuf_add(x->a_text.te_binbuf, 1, &x->a_atom);
|
|
if (senditup)
|
|
glist_retext(x->a_glist, &x->a_text);
|
|
}
|
|
|
|
static void gatom_set(t_gatom *x, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
t_atom oldatom = x->a_atom;
|
|
int senditup = 0;
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
#endif
|
|
if (!argc) return;
|
|
if (x->a_atom.a_type == A_FLOAT)
|
|
x->a_atom.a_w.w_float = atom_getfloat(argv),
|
|
senditup = (x->a_atom.a_w.w_float != oldatom.a_w.w_float);
|
|
else if (x->a_atom.a_type == A_SYMBOL)
|
|
x->a_atom.a_w.w_symbol = atom_getsymbol(argv),
|
|
senditup = (x->a_atom.a_w.w_symbol != oldatom.a_w.w_symbol);
|
|
gatom_retext(x, senditup);
|
|
x->a_buf[0] = 0;
|
|
}
|
|
|
|
static void gatom_bang(t_gatom *x)
|
|
{
|
|
if (x->a_atom.a_type == A_FLOAT)
|
|
{
|
|
if (x->a_text.te_outlet)
|
|
outlet_float(x->a_text.te_outlet, x->a_atom.a_w.w_float);
|
|
if (*x->a_expanded_to->s_name && x->a_expanded_to->s_thing)
|
|
{
|
|
if (x->a_symto == x->a_symfrom)
|
|
pd_error(x,
|
|
"%s: atom with same send/receive name (infinite loop)",
|
|
x->a_symto->s_name);
|
|
else pd_float(x->a_expanded_to->s_thing, x->a_atom.a_w.w_float);
|
|
}
|
|
}
|
|
else if (x->a_atom.a_type == A_SYMBOL)
|
|
{
|
|
if (x->a_text.te_outlet)
|
|
outlet_symbol(x->a_text.te_outlet, x->a_atom.a_w.w_symbol);
|
|
if (*x->a_symto->s_name && x->a_expanded_to->s_thing)
|
|
{
|
|
if (x->a_symto == x->a_symfrom)
|
|
pd_error(x,
|
|
"%s: atom with same send/receive name (infinite loop)",
|
|
x->a_symto->s_name);
|
|
else pd_symbol(x->a_expanded_to->s_thing, x->a_atom.a_w.w_symbol);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void gatom_float(t_gatom *x, t_float f)
|
|
{
|
|
t_atom at;
|
|
SETFLOAT(&at, f);
|
|
gatom_set(x, 0, 1, &at);
|
|
gatom_bang(x);
|
|
}
|
|
|
|
static void gatom_clipfloat(t_gatom *x, t_float f)
|
|
{
|
|
if (x->a_draglo != 0 || x->a_draghi != 0)
|
|
{
|
|
if (f < x->a_draglo)
|
|
f = x->a_draglo;
|
|
if (f > x->a_draghi)
|
|
f = x->a_draghi;
|
|
}
|
|
gatom_float(x, f);
|
|
}
|
|
|
|
static void gatom_symbol(t_gatom *x, t_symbol *s)
|
|
{
|
|
t_atom at;
|
|
SETSYMBOL(&at, s);
|
|
gatom_set(x, 0, 1, &at);
|
|
gatom_bang(x);
|
|
}
|
|
|
|
static void gatom_motion(void *z, t_floatarg dx, t_floatarg dy)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) dx;
|
|
#endif
|
|
t_gatom *x = (t_gatom *)z;
|
|
if (dy == 0) return;
|
|
if (x->a_atom.a_type == A_FLOAT)
|
|
{
|
|
if (x->a_shift)
|
|
{
|
|
double nval = x->a_atom.a_w.w_float - 0.01 * dy;
|
|
double trunc = 0.01 * (floor(100. * nval + 0.5));
|
|
if (trunc < nval + 0.0001 && trunc > nval - 0.0001) nval = trunc;
|
|
gatom_clipfloat(x, nval);
|
|
}
|
|
else
|
|
{
|
|
double nval = x->a_atom.a_w.w_float - dy;
|
|
double trunc = 0.01 * (floor(100. * nval + 0.5));
|
|
if (trunc < nval + 0.0001 && trunc > nval - 0.0001) nval = trunc;
|
|
trunc = floor(nval + 0.5);
|
|
if (trunc < nval + 0.001 && trunc > nval - 0.001) nval = trunc;
|
|
gatom_clipfloat(x, nval);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void gatom_key(void *z, t_floatarg f)
|
|
{
|
|
t_gatom *x = (t_gatom *)z;
|
|
int c = f;
|
|
int len = strlen(x->a_buf);
|
|
t_atom at;
|
|
char sbuf[ATOMBUFSIZE + 4];
|
|
if (c == 0)
|
|
{
|
|
/* we're being notified that no more keys will come for this grab */
|
|
if (x->a_buf[0])
|
|
gatom_retext(x, 1);
|
|
return;
|
|
}
|
|
else if (c == ' ') return;
|
|
else if (c == '\b')
|
|
{
|
|
if (len > 0)
|
|
x->a_buf[len-1] = 0;
|
|
goto redraw;
|
|
}
|
|
else if (c == '\n')
|
|
{
|
|
if (x->a_atom.a_type == A_FLOAT)
|
|
x->a_atom.a_w.w_float = atof(x->a_buf);
|
|
else if (x->a_atom.a_type == A_SYMBOL)
|
|
x->a_atom.a_w.w_symbol = gensym(x->a_buf);
|
|
else bug("gatom_key");
|
|
gatom_bang(x);
|
|
gatom_retext(x, 1);
|
|
x->a_buf[0] = 0;
|
|
}
|
|
else if (len < (ATOMBUFSIZE-1))
|
|
{
|
|
/* for numbers, only let reasonable characters through */
|
|
if ((x->a_atom.a_type == A_SYMBOL) ||
|
|
((c >= '0' && c <= '9') || c == '.' || c == '-'
|
|
|| c == 'e' || c == 'E'))
|
|
{
|
|
x->a_buf[len] = c;
|
|
x->a_buf[len+1] = 0;
|
|
goto redraw;
|
|
}
|
|
}
|
|
return;
|
|
redraw:
|
|
/* LATER figure out how to avoid creating all these symbols! */
|
|
#ifdef ROCKBOX
|
|
snprintf(sbuf, sizeof(sbuf), "%s...", x->a_buf);
|
|
#else /* ROCKBOX */
|
|
sprintf(sbuf, "%s...", x->a_buf);
|
|
#endif
|
|
SETSYMBOL(&at, gensym(sbuf));
|
|
binbuf_clear(x->a_text.te_binbuf);
|
|
binbuf_add(x->a_text.te_binbuf, 1, &at);
|
|
glist_retext(x->a_glist, &x->a_text);
|
|
}
|
|
|
|
static void gatom_click(t_gatom *x,
|
|
t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl,
|
|
t_floatarg alt)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) ctrl;
|
|
#endif
|
|
if (x->a_text.te_width == 1)
|
|
{
|
|
if (x->a_atom.a_type == A_FLOAT)
|
|
gatom_float(x, (x->a_atom.a_w.w_float == 0));
|
|
}
|
|
else
|
|
{
|
|
if (alt)
|
|
{
|
|
if (x->a_atom.a_type != A_FLOAT) return;
|
|
if (x->a_atom.a_w.w_float != 0)
|
|
{
|
|
x->a_toggle = x->a_atom.a_w.w_float;
|
|
gatom_float(x, 0);
|
|
return;
|
|
}
|
|
else gatom_float(x, x->a_toggle);
|
|
}
|
|
x->a_shift = shift;
|
|
x->a_buf[0] = 0;
|
|
glist_grab(x->a_glist, &x->a_text.te_g, gatom_motion, gatom_key,
|
|
xpos, ypos);
|
|
}
|
|
}
|
|
|
|
/* message back from dialog window */
|
|
static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv)
|
|
{
|
|
t_float width = atom_getfloatarg(0, argc, argv);
|
|
t_float draglo = atom_getfloatarg(1, argc, argv);
|
|
t_float draghi = atom_getfloatarg(2, argc, argv);
|
|
t_symbol *label = gatom_unescapit(atom_getsymbolarg(3, argc, argv));
|
|
t_float wherelabel = atom_getfloatarg(4, argc, argv);
|
|
t_symbol *symfrom = gatom_unescapit(atom_getsymbolarg(5, argc, argv));
|
|
t_symbol *symto = gatom_unescapit(atom_getsymbolarg(6, argc, argv));
|
|
|
|
#ifdef ROCKBOX
|
|
(void) sel;
|
|
#endif
|
|
|
|
gobj_vis(&x->a_text.te_g, x->a_glist, 0);
|
|
if (!*symfrom->s_name && *x->a_symfrom->s_name)
|
|
inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
|
|
else if (*symfrom->s_name && !*x->a_symfrom->s_name && x->a_text.te_inlet)
|
|
{
|
|
canvas_deletelinesforio(x->a_glist, &x->a_text,
|
|
x->a_text.te_inlet, 0);
|
|
inlet_free(x->a_text.te_inlet);
|
|
}
|
|
if (!*symto->s_name && *x->a_symto->s_name)
|
|
outlet_new(&x->a_text, 0);
|
|
else if (*symto->s_name && !*x->a_symto->s_name && x->a_text.te_outlet)
|
|
{
|
|
canvas_deletelinesforio(x->a_glist, &x->a_text,
|
|
0, x->a_text.te_outlet);
|
|
outlet_free(x->a_text.te_outlet);
|
|
}
|
|
if (draglo >= draghi)
|
|
draglo = draghi = 0;
|
|
x->a_draglo = draglo;
|
|
x->a_draghi = draghi;
|
|
if (width < 0)
|
|
width = 4;
|
|
else if (width > 80)
|
|
width = 80;
|
|
x->a_text.te_width = width;
|
|
x->a_wherelabel = ((int)wherelabel & 3);
|
|
x->a_label = label;
|
|
if (*x->a_symfrom->s_name)
|
|
pd_unbind(&x->a_text.te_pd,
|
|
canvas_realizedollar(x->a_glist, x->a_symfrom));
|
|
x->a_symfrom = symfrom;
|
|
if (*x->a_symfrom->s_name)
|
|
pd_bind(&x->a_text.te_pd,
|
|
canvas_realizedollar(x->a_glist, x->a_symfrom));
|
|
x->a_symto = symto;
|
|
x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto);
|
|
gobj_vis(&x->a_text.te_g, x->a_glist, 1);
|
|
|
|
/* glist_retext(x->a_glist, &x->a_text); */
|
|
}
|
|
|
|
/* ---------------- gatom-specific widget functions --------------- */
|
|
static void gatom_getwherelabel(t_gatom *x, t_glist *glist, int *xp, int *yp)
|
|
{
|
|
int x1, y1, x2, y2 /*, width, height */;
|
|
text_getrect(&x->a_text.te_g, glist, &x1, &y1, &x2, &y2);
|
|
/* width = x2 - x1; */
|
|
/* height = y2 - y1; */
|
|
if (x->a_wherelabel == ATOM_LABELLEFT)
|
|
{
|
|
*xp = x1 - 3 -
|
|
strlen(canvas_realizedollar(x->a_glist, x->a_label)->s_name) *
|
|
#ifdef ROCKBOX
|
|
8;
|
|
#else
|
|
sys_fontwidth(glist_getfont(glist));
|
|
#endif
|
|
*yp = y1 + 2;
|
|
}
|
|
else if (x->a_wherelabel == ATOM_LABELRIGHT)
|
|
{
|
|
*xp = x2 + 2;
|
|
*yp = y1 + 2;
|
|
}
|
|
else if (x->a_wherelabel == ATOM_LABELUP)
|
|
{
|
|
*xp = x1 - 1;
|
|
#ifdef ROCKBOX
|
|
*yp = y1 - 1 - 10;
|
|
#else
|
|
*yp = y1 - 1 - sys_fontheight(glist_getfont(glist));;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
*xp = x1 - 1;
|
|
*yp = y2 + 3;
|
|
}
|
|
}
|
|
|
|
static void gatom_displace(t_gobj *z, t_glist *glist,
|
|
int dx, int dy)
|
|
{
|
|
#ifndef ROCKBOX
|
|
t_gatom *x = (t_gatom*)z;
|
|
#endif
|
|
text_displace(z, glist, dx, dy);
|
|
#ifndef ROCKBOX
|
|
sys_vgui(".x%x.c move %x.l %d %d\n", glist_getcanvas(glist),
|
|
x, dx, dy);
|
|
#endif
|
|
}
|
|
|
|
static void gatom_vis(t_gobj *z, t_glist *glist, int vis)
|
|
{
|
|
t_gatom *x = (t_gatom*)z;
|
|
text_vis(z, glist, vis);
|
|
if (*x->a_label->s_name)
|
|
{
|
|
if (vis)
|
|
{
|
|
int x1, y1;
|
|
gatom_getwherelabel(x, glist, &x1, &y1);
|
|
#ifndef ROCKBOX
|
|
sys_vgui("pdtk_text_new .x%x.c %x.l %f %f {%s} %d %s\n",
|
|
glist_getcanvas(glist), x,
|
|
(double)x1, (double)y1,
|
|
canvas_realizedollar(x->a_glist, x->a_label)->s_name,
|
|
sys_hostfontsize(glist_getfont(glist)),
|
|
"black");
|
|
#endif
|
|
}
|
|
#ifndef ROCKBOX
|
|
else sys_vgui(".x%x.c delete %x.l\n", glist_getcanvas(glist), x);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void canvas_atom(t_glist *gl, t_atomtype type,
|
|
t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
t_gatom *x = (t_gatom *)pd_new(gatom_class);
|
|
t_atom at;
|
|
|
|
#ifdef ROCKBOX
|
|
(void) s;
|
|
#endif
|
|
|
|
x->a_text.te_width = 0; /* don't know it yet. */
|
|
x->a_text.te_type = T_ATOM;
|
|
x->a_text.te_binbuf = binbuf_new();
|
|
x->a_glist = gl;
|
|
x->a_atom.a_type = type;
|
|
x->a_toggle = 1;
|
|
x->a_draglo = 0;
|
|
x->a_draghi = 0;
|
|
x->a_wherelabel = 0;
|
|
x->a_label = &s_;
|
|
x->a_symfrom = &s_;
|
|
x->a_symto = x->a_expanded_to = &s_;
|
|
if (type == A_FLOAT)
|
|
{
|
|
x->a_atom.a_w.w_float = 0;
|
|
x->a_text.te_width = 5;
|
|
SETFLOAT(&at, 0);
|
|
}
|
|
else
|
|
{
|
|
x->a_atom.a_w.w_symbol = &s_symbol;
|
|
x->a_text.te_width = 10;
|
|
SETSYMBOL(&at, &s_symbol);
|
|
}
|
|
binbuf_add(x->a_text.te_binbuf, 1, &at);
|
|
if (argc > 1)
|
|
/* create from file. x, y, width, low-range, high-range, flags,
|
|
label, receive-name, send-name */
|
|
{
|
|
x->a_text.te_xpix = atom_getfloatarg(0, argc, argv);
|
|
x->a_text.te_ypix = atom_getfloatarg(1, argc, argv);
|
|
x->a_text.te_width = atom_getintarg(2, argc, argv);
|
|
/* sanity check because some very old patches have trash in this
|
|
field... remove this in 2003 or so: */
|
|
if (x->a_text.te_width < 0 || x->a_text.te_width > 500)
|
|
x->a_text.te_width = 4;
|
|
x->a_draglo = atom_getfloatarg(3, argc, argv);
|
|
x->a_draghi = atom_getfloatarg(4, argc, argv);
|
|
x->a_wherelabel = (((int)atom_getfloatarg(5, argc, argv)) & 3);
|
|
x->a_label = gatom_unescapit(atom_getsymbolarg(6, argc, argv));
|
|
x->a_symfrom = gatom_unescapit(atom_getsymbolarg(7, argc, argv));
|
|
if (*x->a_symfrom->s_name)
|
|
pd_bind(&x->a_text.te_pd,
|
|
canvas_realizedollar(x->a_glist, x->a_symfrom));
|
|
|
|
x->a_symto = gatom_unescapit(atom_getsymbolarg(8, argc, argv));
|
|
x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto);
|
|
if (x->a_symto == &s_)
|
|
outlet_new(&x->a_text,
|
|
x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol);
|
|
if (x->a_symfrom == &s_)
|
|
inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
|
|
glist_add(gl, &x->a_text.te_g);
|
|
}
|
|
else
|
|
{
|
|
int xpix, ypix;
|
|
outlet_new(&x->a_text,
|
|
x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol);
|
|
inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
|
|
pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
|
|
glist_noselect(gl);
|
|
glist_getnextxy(gl, &xpix, &ypix);
|
|
x->a_text.te_xpix = xpix;
|
|
x->a_text.te_ypix = ypix;
|
|
glist_add(gl, &x->a_text.te_g);
|
|
glist_noselect(gl);
|
|
glist_select(gl, &x->a_text.te_g);
|
|
canvas_startmotion(glist_getcanvas(gl));
|
|
}
|
|
}
|
|
|
|
void canvas_floatatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
canvas_atom(gl, A_FLOAT, s, argc, argv);
|
|
}
|
|
|
|
void canvas_symbolatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
|
|
{
|
|
canvas_atom(gl, A_SYMBOL, s, argc, argv);
|
|
}
|
|
|
|
static void gatom_free(t_gatom *x)
|
|
{
|
|
if (*x->a_symfrom->s_name)
|
|
pd_unbind(&x->a_text.te_pd,
|
|
canvas_realizedollar(x->a_glist, x->a_symfrom));
|
|
#ifndef ROCKBOX
|
|
gfxstub_deleteforkey(x);
|
|
#endif
|
|
}
|
|
|
|
static void gatom_properties(t_gobj *z, t_glist *owner)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) z;
|
|
(void) owner;
|
|
#else /* ROCKBOX */
|
|
t_gatom *x = (t_gatom *)z;
|
|
char buf[200];
|
|
sprintf(buf, "pdtk_gatom_dialog %%s %d %g %g %d %s %s %s\n",
|
|
x->a_text.te_width, x->a_draglo, x->a_draghi,
|
|
x->a_wherelabel, gatom_escapit(x->a_label)->s_name,
|
|
gatom_escapit(x->a_symfrom)->s_name,
|
|
gatom_escapit(x->a_symto)->s_name);
|
|
gfxstub_new(&x->a_text.te_pd, x, buf);
|
|
#endif /* ROCKBOX */
|
|
}
|
|
|
|
|
|
/* -------------------- widget behavior for text objects ------------ */
|
|
|
|
static void text_getrect(t_gobj *z, t_glist *glist,
|
|
int *xp1, int *yp1, int *xp2, int *yp2)
|
|
{
|
|
t_text *x = (t_text *)z;
|
|
int width, height, iscomment = (x->te_type == T_TEXT);
|
|
float x1, y1, x2, y2;
|
|
|
|
/* for number boxes, we know width and height a priori, and should
|
|
report them here so that graphs can get swelled to fit. */
|
|
|
|
if (x->te_type == T_ATOM && x->te_width > 0)
|
|
{
|
|
#ifdef ROCKBOX
|
|
int fontwidth = 8, fontheight = 10;
|
|
#else
|
|
int font = glist_getfont(glist);
|
|
int fontwidth = sys_fontwidth(font), fontheight = sys_fontheight(font);
|
|
#endif
|
|
width = (x->te_width > 0 ? x->te_width : 6) * fontwidth + 2;
|
|
height = fontheight + 1; /* borrowed from TMARGIN, etc, in g_rtext.c */
|
|
}
|
|
/* if we're invisible we don't know our size so we just lie about
|
|
it. This is called on invisible boxes to establish order of inlets
|
|
and possibly other reasons.
|
|
To find out if the box is visible we can't just check the "vis"
|
|
flag because we might be within the vis() routine and not have set
|
|
that yet. So we check directly whether the "rtext" list has been
|
|
built. LATER reconsider when "vis" flag should be on and off? */
|
|
|
|
else if (glist->gl_editor && glist->gl_editor->e_rtext)
|
|
{
|
|
t_rtext *y = glist_findrtext(glist, x);
|
|
width = rtext_width(y);
|
|
height = rtext_height(y) - (iscomment << 1);
|
|
}
|
|
else width = height = 10;
|
|
x1 = text_xpix(x, glist);
|
|
y1 = text_ypix(x, glist);
|
|
x2 = x1 + width;
|
|
y2 = y1 + height;
|
|
y1 += iscomment;
|
|
*xp1 = x1;
|
|
*yp1 = y1;
|
|
*xp2 = x2;
|
|
*yp2 = y2;
|
|
}
|
|
|
|
static void text_displace(t_gobj *z, t_glist *glist,
|
|
int dx, int dy)
|
|
{
|
|
t_text *x = (t_text *)z;
|
|
x->te_xpix += dx;
|
|
x->te_ypix += dy;
|
|
if (glist_isvisible(glist))
|
|
{
|
|
t_rtext *y = glist_findrtext(glist, x);
|
|
rtext_displace(y, dx, dy);
|
|
text_drawborder(x, glist, rtext_gettag(y),
|
|
rtext_width(y), rtext_height(y), 0);
|
|
canvas_fixlinesfor(glist_getcanvas(glist), x);
|
|
}
|
|
}
|
|
|
|
static void text_select(t_gobj *z, t_glist *glist, int state)
|
|
{
|
|
t_text *x = (t_text *)z;
|
|
t_rtext *y = glist_findrtext(glist, x);
|
|
rtext_select(y, state);
|
|
if (glist_isvisible(glist) && text_shouldvis(x, glist))
|
|
#ifdef ROCKBOX
|
|
{
|
|
}
|
|
#else /* ROCKBOX */
|
|
sys_vgui(".x%x.c itemconfigure %sR -fill %s\n", glist,
|
|
rtext_gettag(y), (state? "blue" : "black"));
|
|
#endif /* ROCKBOX */
|
|
}
|
|
|
|
static void text_activate(t_gobj *z, t_glist *glist, int state)
|
|
{
|
|
t_text *x = (t_text *)z;
|
|
t_rtext *y = glist_findrtext(glist, x);
|
|
if (z->g_pd != gatom_class) rtext_activate(y, state);
|
|
}
|
|
|
|
static void text_delete(t_gobj *z, t_glist *glist)
|
|
{
|
|
t_text *x = (t_text *)z;
|
|
canvas_deletelinesfor(glist, x);
|
|
}
|
|
|
|
/* return true if the text box should be drawn.
|
|
We don't show object boxes inside graphs. */
|
|
int text_shouldvis(t_text *x, t_glist *glist)
|
|
{
|
|
return (glist->gl_havewindow ||
|
|
(x->te_pd != canvas_class && x->te_pd->c_wb != &text_widgetbehavior) ||
|
|
(x->te_pd == canvas_class && (((t_glist *)x)->gl_isgraph)));
|
|
}
|
|
|
|
static void text_vis(t_gobj *z, t_glist *glist, int vis)
|
|
{
|
|
t_text *x = (t_text *)z;
|
|
if (vis)
|
|
{
|
|
if (text_shouldvis(x, glist))
|
|
{
|
|
t_rtext *y = glist_findrtext(glist, x);
|
|
if (x->te_type == T_ATOM)
|
|
glist_retext(glist, x);
|
|
text_drawborder(x, glist, rtext_gettag(y),
|
|
rtext_width(y), rtext_height(y), 1);
|
|
rtext_draw(y);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_rtext *y = glist_findrtext(glist, x);
|
|
if (text_shouldvis(x, glist))
|
|
{
|
|
text_eraseborder(x, glist, rtext_gettag(y));
|
|
rtext_erase(y);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int text_click(t_gobj *z, struct _glist *glist,
|
|
int xpix, int ypix, int shift, int alt, int dbl, int doit)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) glist;
|
|
(void) dbl;
|
|
#endif
|
|
t_text *x = (t_text *)z;
|
|
if (x->te_type == T_OBJECT)
|
|
{
|
|
t_symbol *clicksym = gensym("click");
|
|
if (zgetfn(&x->te_pd, clicksym))
|
|
{
|
|
if (doit)
|
|
pd_vmess(&x->te_pd, clicksym, "fffff",
|
|
(double)xpix, (double)ypix,
|
|
(double)shift, 0, (double)alt);
|
|
return (1);
|
|
}
|
|
else return (0);
|
|
}
|
|
else if (x->te_type == T_ATOM)
|
|
{
|
|
if (doit)
|
|
gatom_click((t_gatom *)x, (t_floatarg)xpix, (t_floatarg)ypix,
|
|
(t_floatarg)shift, 0, (t_floatarg)alt);
|
|
return (1);
|
|
}
|
|
else if (x->te_type == T_MESSAGE)
|
|
{
|
|
if (doit)
|
|
message_click((t_message *)x, (t_floatarg)xpix, (t_floatarg)ypix,
|
|
(t_floatarg)shift, 0, (t_floatarg)alt);
|
|
return (1);
|
|
}
|
|
else return (0);
|
|
}
|
|
|
|
void text_save(t_gobj *z, t_binbuf *b)
|
|
{
|
|
t_text *x = (t_text *)z;
|
|
if (x->te_type == T_OBJECT)
|
|
{
|
|
/* if we have a "saveto" method, and if we don't happen to be
|
|
a canvas that's an abstraction, the saveto method does the work */
|
|
if (zgetfn(&x->te_pd, gensym("saveto")) &&
|
|
!((pd_class(&x->te_pd) == canvas_class) &&
|
|
(canvas_isabstraction((t_canvas *)x)
|
|
|| canvas_istable((t_canvas *)x))))
|
|
{
|
|
mess1(&x->te_pd, gensym("saveto"), b);
|
|
binbuf_addv(b, "ssii", gensym("#X"), gensym("restore"),
|
|
(t_int)x->te_xpix, (t_int)x->te_ypix);
|
|
}
|
|
else /* otherwise just save the text */
|
|
{
|
|
binbuf_addv(b, "ssii", gensym("#X"), gensym("obj"),
|
|
(t_int)x->te_xpix, (t_int)x->te_ypix);
|
|
}
|
|
binbuf_addbinbuf(b, x->te_binbuf);
|
|
binbuf_addv(b, ";");
|
|
}
|
|
else if (x->te_type == T_MESSAGE)
|
|
{
|
|
binbuf_addv(b, "ssii", gensym("#X"), gensym("msg"),
|
|
(t_int)x->te_xpix, (t_int)x->te_ypix);
|
|
binbuf_addbinbuf(b, x->te_binbuf);
|
|
binbuf_addv(b, ";");
|
|
}
|
|
else if (x->te_type == T_ATOM)
|
|
{
|
|
t_atomtype t = ((t_gatom *)x)->a_atom.a_type;
|
|
t_symbol *sel = (t == A_SYMBOL ? gensym("symbolatom") :
|
|
(t == A_FLOAT ? gensym("floatatom") : gensym("intatom")));
|
|
t_symbol *label = gatom_escapit(((t_gatom *)x)->a_label);
|
|
t_symbol *symfrom = gatom_escapit(((t_gatom *)x)->a_symfrom);
|
|
t_symbol *symto = gatom_escapit(((t_gatom *)x)->a_symto);
|
|
binbuf_addv(b, "ssiiifffsss", gensym("#X"), sel,
|
|
(t_int)x->te_xpix, (t_int)x->te_ypix, (t_int)x->te_width,
|
|
(double)((t_gatom *)x)->a_draglo,
|
|
(double)((t_gatom *)x)->a_draghi,
|
|
(double)((t_gatom *)x)->a_wherelabel,
|
|
label, symfrom, symto);
|
|
binbuf_addv(b, ";");
|
|
}
|
|
else
|
|
{
|
|
binbuf_addv(b, "ssii", gensym("#X"), gensym("text"),
|
|
(t_int)x->te_xpix, (t_int)x->te_ypix);
|
|
binbuf_addbinbuf(b, x->te_binbuf);
|
|
binbuf_addv(b, ";");
|
|
}
|
|
}
|
|
|
|
/* this one is for everyone but "gatoms"; it's imposed in m_class.c */
|
|
t_widgetbehavior text_widgetbehavior =
|
|
{
|
|
text_getrect,
|
|
text_displace,
|
|
text_select,
|
|
text_activate,
|
|
text_delete,
|
|
text_vis,
|
|
text_click,
|
|
};
|
|
|
|
static t_widgetbehavior gatom_widgetbehavior =
|
|
{
|
|
text_getrect,
|
|
gatom_displace,
|
|
text_select,
|
|
text_activate,
|
|
text_delete,
|
|
gatom_vis,
|
|
text_click,
|
|
};
|
|
|
|
/* -------------------- the "text" class ------------ */
|
|
|
|
#ifdef MACOSX
|
|
#define EXTRAPIX 2
|
|
#else
|
|
#define EXTRAPIX 1
|
|
#endif
|
|
|
|
/* draw inlets and outlets for a text object or for a graph. */
|
|
void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
|
|
char *tag, int x1, int y1, int x2, int y2)
|
|
{
|
|
#ifdef ROCKBOX
|
|
(void) glist;
|
|
(void) ob;
|
|
(void) firsttime;
|
|
(void) tag;
|
|
(void) x1;
|
|
(void) y1;
|
|
(void) x2;
|
|
(void) y2;
|
|
#else /* ROCKBOX */
|
|
int n = obj_noutlets(ob), i;
|
|
int width = x2 - x1;
|
|
int nplus = (n == 1 ? 1 : n-1);
|
|
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
int onset = x1 + (width - IOWIDTH) * i / nplus;
|
|
if (firsttime)
|
|
sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %so%d\n",
|
|
glist_getcanvas(glist),
|
|
onset, y2 - 1,
|
|
onset + IOWIDTH, y2,
|
|
tag, i);
|
|
else
|
|
sys_vgui(".x%x.c coords %so%d %d %d %d %d\n",
|
|
glist_getcanvas(glist), tag, i,
|
|
onset, y2 - 1,
|
|
onset + IOWIDTH, y2);
|
|
}
|
|
|
|
n = obj_ninlets(ob);
|
|
nplus = (n == 1 ? 1 : n-1);
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
int onset = x1 + (width - IOWIDTH) * i / nplus;
|
|
if (firsttime)
|
|
sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %si%d\n",
|
|
glist_getcanvas(glist),
|
|
onset, y1,
|
|
onset + IOWIDTH, y1 + EXTRAPIX,
|
|
tag, i);
|
|
else
|
|
sys_vgui(".x%x.c coords %si%d %d %d %d %d\n",
|
|
glist_getcanvas(glist), tag, i,
|
|
onset, y1,
|
|
onset + IOWIDTH, y1 + EXTRAPIX);
|
|
}
|
|
#endif /* ROCKBOX */
|
|
}
|
|
|
|
void text_drawborder(t_text *x, t_glist *glist,
|
|
char *tag, int width2, int height2, int firsttime)
|
|
{
|
|
t_object *ob;
|
|
int x1, y1, x2, y2 /* , width, height */;
|
|
|
|
#ifdef ROCKBOX
|
|
(void) width2;
|
|
(void) height2;
|
|
#endif
|
|
|
|
text_getrect(&x->te_g, glist, &x1, &y1, &x2, &y2);
|
|
/* width = x2 - x1; */
|
|
/* height = y2 - y1; */
|
|
if (x->te_type == T_OBJECT)
|
|
{
|
|
#ifndef ROCKBOX
|
|
if (firsttime)
|
|
sys_vgui(".x%x.c create line\
|
|
%d %d %d %d %d %d %d %d %d %d -tags %sR\n",
|
|
glist_getcanvas(glist),
|
|
x1, y1, x2, y1, x2, y2, x1, y2, x1, y1, tag);
|
|
else
|
|
sys_vgui(".x%x.c coords %sR\
|
|
%d %d %d %d %d %d %d %d %d %d\n",
|
|
glist_getcanvas(glist), tag,
|
|
x1, y1, x2, y1, x2, y2, x1, y2, x1, y1);
|
|
#endif
|
|
}
|
|
else if (x->te_type == T_MESSAGE)
|
|
{
|
|
#ifndef ROCKBOX
|
|
if (firsttime)
|
|
sys_vgui(".x%x.c create line\
|
|
%d %d %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
|
|
glist_getcanvas(glist),
|
|
x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2,
|
|
x1, y2, x1, y1,
|
|
tag);
|
|
else
|
|
sys_vgui(".x%x.c coords %sR\
|
|
%d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
|
glist_getcanvas(glist), tag,
|
|
x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2,
|
|
x1, y2, x1, y1);
|
|
#endif
|
|
}
|
|
else if (x->te_type == T_ATOM)
|
|
{
|
|
#ifndef ROCKBOX
|
|
if (firsttime)
|
|
sys_vgui(".x%x.c create line\
|
|
%d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
|
|
glist_getcanvas(glist),
|
|
x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1,
|
|
tag);
|
|
else
|
|
sys_vgui(".x%x.c coords %sR\
|
|
%d %d %d %d %d %d %d %d %d %d %d %d\n",
|
|
glist_getcanvas(glist), tag,
|
|
x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1);
|
|
#endif
|
|
}
|
|
/* draw inlets/outlets */
|
|
|
|
if ((ob = pd_checkobject(&x->te_pd)))
|
|
glist_drawiofor(glist, ob, firsttime, tag, x1, y1, x2, y2);
|
|
}
|
|
|
|
void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag)
|
|
{
|
|
int i, n;
|
|
#ifdef ROCKBOX
|
|
(void) glist;
|
|
(void) tag;
|
|
#endif
|
|
n = obj_noutlets(ob);
|
|
for (i = 0; i < n; i++)
|
|
#ifdef ROCKBOX
|
|
;
|
|
#else /* ROCKBOX */
|
|
sys_vgui(".x%x.c delete %so%d\n",
|
|
glist_getcanvas(glist), tag, i);
|
|
#endif /* ROCKBOX */
|
|
n = obj_ninlets(ob);
|
|
for (i = 0; i < n; i++)
|
|
#ifdef ROCKBOX
|
|
;
|
|
#else /* ROCKBOX */
|
|
sys_vgui(".x%x.c delete %si%d\n",
|
|
glist_getcanvas(glist), tag, i);
|
|
#endif /* ROCKBOX */
|
|
}
|
|
|
|
void text_eraseborder(t_text *x, t_glist *glist, char *tag)
|
|
{
|
|
if (x->te_type == T_TEXT) return;
|
|
#ifndef ROCKBOX
|
|
sys_vgui(".x%x.c delete %sR\n",
|
|
glist_getcanvas(glist), tag);
|
|
#endif
|
|
glist_eraseiofor(glist, x, tag);
|
|
}
|
|
|
|
/* change text; if T_OBJECT, remake it. LATER we'll have an undo buffer
|
|
which should be filled in here before making the change. */
|
|
|
|
void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize)
|
|
{
|
|
if (x->te_type == T_OBJECT)
|
|
{
|
|
t_binbuf *b = binbuf_new();
|
|
int natom1, natom2;
|
|
t_atom *vec1, *vec2;
|
|
binbuf_text(b, buf, bufsize);
|
|
natom1 = binbuf_getnatom(x->te_binbuf);
|
|
vec1 = binbuf_getvec(x->te_binbuf);
|
|
natom2 = binbuf_getnatom(b);
|
|
vec2 = binbuf_getvec(b);
|
|
/* special case: if pd args change just pass the message on. */
|
|
if (natom1 >= 1 && natom2 >= 1 && vec1[0].a_type == A_SYMBOL
|
|
&& !strcmp(vec1[0].a_w.w_symbol->s_name, "pd") &&
|
|
vec2[0].a_type == A_SYMBOL
|
|
&& !strcmp(vec2[0].a_w.w_symbol->s_name, "pd"))
|
|
{
|
|
typedmess(&x->te_pd, gensym("rename"), natom2-1, vec2+1);
|
|
binbuf_free(x->te_binbuf);
|
|
x->te_binbuf = b;
|
|
}
|
|
else /* normally, just destroy the old one and make a new one. */
|
|
{
|
|
int xwas = x->te_xpix, ywas = x->te_ypix;
|
|
glist_delete(glist, &x->te_g);
|
|
canvas_objtext(glist, xwas, ywas, 0, b);
|
|
/* if it's an abstraction loadbang it here */
|
|
if (newest && pd_class(newest) == canvas_class)
|
|
canvas_loadbang((t_canvas *)newest);
|
|
canvas_restoreconnections(glist_getcanvas(glist));
|
|
}
|
|
/* if we made a new "pd" or changed a window name,
|
|
update window list */
|
|
if (natom2 >= 1 && vec2[0].a_type == A_SYMBOL
|
|
&& !strcmp(vec2[0].a_w.w_symbol->s_name, "pd"))
|
|
canvas_updatewindowlist();
|
|
}
|
|
else binbuf_text(x->te_binbuf, buf, bufsize);
|
|
}
|
|
|
|
void g_text_setup(void)
|
|
{
|
|
text_class = class_new(gensym("text"), 0, 0, sizeof(t_text),
|
|
CLASS_NOINLET | CLASS_PATCHABLE, 0);
|
|
|
|
message_class = class_new(gensym("message"), 0, (t_method)message_free,
|
|
sizeof(t_message), CLASS_PATCHABLE, 0);
|
|
class_addbang(message_class, message_bang);
|
|
class_addfloat(message_class, message_float);
|
|
class_addsymbol(message_class, message_symbol);
|
|
class_addlist(message_class, message_list);
|
|
class_addanything(message_class, message_list);
|
|
|
|
class_addmethod(message_class, (t_method)message_click, gensym("click"),
|
|
A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
|
|
class_addmethod(message_class, (t_method)message_set, gensym("set"),
|
|
A_GIMME, 0);
|
|
class_addmethod(message_class, (t_method)message_add, gensym("add"),
|
|
A_GIMME, 0);
|
|
class_addmethod(message_class, (t_method)message_add2, gensym("add2"),
|
|
A_GIMME, 0);
|
|
|
|
messresponder_class = class_new(gensym("messresponder"), 0, 0,
|
|
sizeof(t_text), CLASS_PD, 0);
|
|
class_addbang(messresponder_class, messresponder_bang);
|
|
class_addfloat(messresponder_class, (t_method) messresponder_float);
|
|
class_addsymbol(messresponder_class, messresponder_symbol);
|
|
class_addlist(messresponder_class, messresponder_list);
|
|
class_addanything(messresponder_class, messresponder_anything);
|
|
|
|
gatom_class = class_new(gensym("gatom"), 0, (t_method)gatom_free,
|
|
sizeof(t_gatom), CLASS_NOINLET | CLASS_PATCHABLE, 0);
|
|
class_addbang(gatom_class, gatom_bang);
|
|
class_addfloat(gatom_class, gatom_float);
|
|
class_addsymbol(gatom_class, gatom_symbol);
|
|
class_addmethod(gatom_class, (t_method)gatom_set, gensym("set"),
|
|
A_GIMME, 0);
|
|
class_addmethod(gatom_class, (t_method)gatom_click, gensym("click"),
|
|
A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
|
|
class_addmethod(gatom_class, (t_method)gatom_param, gensym("param"),
|
|
A_GIMME, 0);
|
|
class_setwidget(gatom_class, &gatom_widgetbehavior);
|
|
class_setpropertiesfn(gatom_class, gatom_properties);
|
|
}
|
|
|