Add FS #10214. Initial commit of the original PDa code for the GSoC Pure Data plugin...
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / g_text.c
blob8cf1fe2834d997de7a2566d91d7b9ae046ef4946
1 /* Copyright (c) 1997-1999 Miller Puckette.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
5 /* changes by Thomas Musil IEM KUG Graz Austria 2001 */
6 /* the methods for calling the gui-objects from menu are implemented */
7 /* all changes are labeled with iemlib */
9 #include <stdlib.h>
10 #include "m_pd.h"
11 #include "m_imp.h"
12 #include "s_stuff.h"
13 #include "t_tk.h"
14 #include "g_canvas.h"
15 #include <stdio.h>
16 #include <string.h>
17 #include <math.h>
19 static t_class *text_class;
20 static t_class *message_class;
21 static t_class *gatom_class;
22 static void text_vis(t_gobj *z, t_glist *glist, int vis);
23 static void text_displace(t_gobj *z, t_glist *glist,
24 int dx, int dy);
25 static void text_getrect(t_gobj *z, t_glist *glist,
26 int *xp1, int *yp1, int *xp2, int *yp2);
28 void canvas_startmotion(t_canvas *x);
29 t_widgetbehavior text_widgetbehavior;
31 /* ----------------- the "text" object. ------------------ */
33 /* add a "text" object (comment) to a glist. While this one goes for any glist,
34 the other 3 below are for canvases only. (why?) This is called
35 without args if invoked from the GUI; otherwise at least x and y
36 are provided. */
38 void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
40 t_text *x = (t_text *)pd_new(text_class);
41 t_atom at;
42 x->te_width = 0; /* don't know it yet. */
43 x->te_type = T_TEXT;
44 x->te_binbuf = binbuf_new();
45 if (argc > 1)
47 x->te_xpix = atom_getfloatarg(0, argc, argv);
48 x->te_ypix = atom_getfloatarg(1, argc, argv);
49 if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2);
50 else
52 SETSYMBOL(&at, gensym("comment"));
53 binbuf_restore(x->te_binbuf, 1, &at);
55 glist_add(gl, &x->te_g);
57 else
59 int xpix, ypix;
60 pd_vmess((t_pd *)glist_getcanvas(gl), gensym("editmode"), "i", 1);
61 SETSYMBOL(&at, gensym("comment"));
62 glist_noselect(gl);
63 glist_getnextxy(gl, &xpix, &ypix);
64 x->te_xpix = glist_pixelstox(gl, xpix-3);
65 x->te_ypix = glist_pixelstoy(gl, ypix-3);
66 binbuf_restore(x->te_binbuf, 1, &at);
67 glist_add(gl, &x->te_g);
68 glist_noselect(gl);
69 glist_select(gl, &x->te_g);
70 /* it would be nice to "activate" here, but then the second,
71 "put-me-down" click changes the text selection, which is quite
72 irritating, so I took this back out. It's OK in messages
73 and objects though since there's no text in them at menu
74 creation. */
75 /* gobj_activate(&x->te_g, gl, 1); */
76 canvas_startmotion(glist_getcanvas(gl));
80 /* ----------------- the "object" object. ------------------ */
82 extern t_pd *newest;
83 void canvas_getargs(int *argcp, t_atom **argvp);
85 static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected,
86 t_binbuf *b)
88 t_text *x;
89 int argc;
90 t_atom *argv;
91 newest = 0;
92 canvas_setcurrent((t_canvas *)gl);
93 canvas_getargs(&argc, &argv);
94 binbuf_eval(b, &pd_objectmaker, argc, argv);
95 if (binbuf_getnatom(b))
97 if (!newest)
99 binbuf_print(b);
100 post("... couldn't create");
101 x = 0;
103 else if (!(x = pd_checkobject(newest)))
105 binbuf_print(b);
106 post("... didn't return a patchable object");
109 else x = 0;
110 if (!x)
113 /* LATER make the color reflect this */
114 x = (t_text *)pd_new(text_class);
116 x->te_binbuf = b;
117 x->te_xpix = xpix;
118 x->te_ypix = ypix;
119 x->te_width = 0;
120 x->te_type = T_OBJECT;
121 glist_add(gl, &x->te_g);
122 if (selected)
124 /* this is called if we've been created from the menu. */
125 glist_select(gl, &x->te_g);
126 gobj_activate(&x->te_g, gl, 1);
128 if (pd_class(&x->ob_pd) == vinlet_class)
129 canvas_resortinlets(glist_getcanvas(gl));
130 if (pd_class(&x->ob_pd) == voutlet_class)
131 canvas_resortoutlets(glist_getcanvas(gl));
132 canvas_unsetcurrent((t_canvas *)gl);
135 /* object creation routine. These are called without any arguments if
136 they're invoked from the
137 gui; when pasting or restoring from a file, we get at least x and y. */
139 void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
141 t_text *x;
142 if (argc >= 2)
144 t_binbuf *b = binbuf_new();
145 binbuf_restore(b, argc-2, argv+2);
146 canvas_objtext(gl, atom_getintarg(0, argc, argv),
147 atom_getintarg(1, argc, argv), 0, b);
149 else
151 t_binbuf *b = binbuf_new();
152 int xpix, ypix;
153 pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
154 glist_noselect(gl);
155 glist_getnextxy(gl, &xpix, &ypix);
156 canvas_objtext(gl, xpix, ypix, 1, b);
157 canvas_startmotion(glist_getcanvas(gl));
161 /* make an object box for an object that's already there. */
163 /* iemlib */
164 void canvas_iemguis(t_glist *gl, t_symbol *guiobjname)
166 t_atom at;
167 t_binbuf *b = binbuf_new();
168 int xpix, ypix;
170 pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
171 glist_noselect(gl);
172 SETSYMBOL(&at, guiobjname);
173 binbuf_restore(b, 1, &at);
174 glist_getnextxy(gl, &xpix, &ypix);
175 canvas_objtext(gl, xpix, ypix, 1, b);
176 canvas_startmotion(glist_getcanvas(gl));
179 void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
181 canvas_iemguis(gl, gensym("bng"));
184 void canvas_toggle(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
186 canvas_iemguis(gl, gensym("tgl"));
189 void canvas_vslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
191 canvas_iemguis(gl, gensym("vsl"));
194 void canvas_hslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
196 canvas_iemguis(gl, gensym("hsl"));
199 void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
201 canvas_iemguis(gl, gensym("hdl"));
204 void canvas_vdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
206 canvas_iemguis(gl, gensym("vdl"));
209 void canvas_hradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
211 canvas_iemguis(gl, gensym("hradio"));
214 void canvas_vradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
216 canvas_iemguis(gl, gensym("vradio"));
219 void canvas_vumeter(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
221 canvas_iemguis(gl, gensym("vu"));
224 void canvas_mycnv(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
226 canvas_iemguis(gl, gensym("cnv"));
229 void canvas_numbox(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
231 canvas_iemguis(gl, gensym("nbx"));
234 /* iemlib */
236 void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv)
238 x->te_width = 0; /* don't know it yet. */
239 x->te_type = T_OBJECT;
240 x->te_binbuf = binbuf_new();
241 x->te_xpix = atom_getfloatarg(0, argc, argv);
242 x->te_ypix = atom_getfloatarg(1, argc, argv);
243 if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2);
244 glist_add(gl, &x->te_g);
247 /* ---------------------- the "message" text item ------------------------ */
249 typedef struct _messresponder
251 t_pd mr_pd;
252 t_outlet *mr_outlet;
253 } t_messresponder;
255 typedef struct _message
257 t_text m_text;
258 t_messresponder m_messresponder;
259 t_glist *m_glist;
260 t_clock *m_clock;
261 } t_message;
263 static t_class *message_class, *messresponder_class;
265 static void messresponder_bang(t_messresponder *x)
267 outlet_bang(x->mr_outlet);
270 static void messresponder_float(t_messresponder *x, t_float f)
272 outlet_float(x->mr_outlet, f);
275 static void messresponder_symbol(t_messresponder *x, t_symbol *s)
277 outlet_symbol(x->mr_outlet, s);
280 static void messresponder_list(t_messresponder *x,
281 t_symbol *s, int argc, t_atom *argv)
283 outlet_list(x->mr_outlet, s, argc, argv);
286 static void messresponder_anything(t_messresponder *x,
287 t_symbol *s, int argc, t_atom *argv)
289 outlet_anything(x->mr_outlet, s, argc, argv);
292 static void message_bang(t_message *x)
294 binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 0, 0);
297 static void message_float(t_message *x, t_float f)
299 t_atom at;
300 SETFLOAT(&at, f);
301 binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
304 static void message_symbol(t_message *x, t_symbol *s)
306 t_atom at;
307 SETSYMBOL(&at, s);
308 binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
311 static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv)
313 binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, argc, argv);
316 static void message_set(t_message *x, t_symbol *s, int argc, t_atom *argv)
318 binbuf_clear(x->m_text.te_binbuf);
319 binbuf_add(x->m_text.te_binbuf, argc, argv);
320 glist_retext(x->m_glist, &x->m_text);
323 static void message_add2(t_message *x, t_symbol *s, int argc, t_atom *argv)
325 binbuf_add(x->m_text.te_binbuf, argc, argv);
326 glist_retext(x->m_glist, &x->m_text);
329 static void message_add(t_message *x, t_symbol *s, int argc, t_atom *argv)
331 binbuf_add(x->m_text.te_binbuf, argc, argv);
332 binbuf_addsemi(x->m_text.te_binbuf);
333 glist_retext(x->m_glist, &x->m_text);
336 static void message_click(t_message *x,
337 t_floatarg xpos, t_floatarg ypos, t_floatarg shift,
338 t_floatarg ctrl, t_floatarg alt)
340 message_float(x, 0);
341 if (glist_isvisible(x->m_glist))
343 t_rtext *y = glist_findrtext(x->m_glist, &x->m_text);
344 sys_vgui(".x%x.c itemconfigure %sR -width 5\n",
345 glist_getcanvas(x->m_glist), rtext_gettag(y));
346 clock_delay(x->m_clock, 120);
350 static void message_tick(t_message *x)
352 if (glist_isvisible(x->m_glist))
354 t_rtext *y = glist_findrtext(x->m_glist, &x->m_text);
355 sys_vgui(".x%x.c itemconfigure %sR -width 1\n",
356 glist_getcanvas(x->m_glist), rtext_gettag(y));
360 static void message_free(t_message *x)
362 clock_free(x->m_clock);
365 void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
367 t_message *x = (t_message *)pd_new(message_class);
368 x->m_messresponder.mr_pd = messresponder_class;
369 x->m_messresponder.mr_outlet = outlet_new(&x->m_text, &s_float);
370 x->m_text.te_width = 0; /* don't know it yet. */
371 x->m_text.te_type = T_MESSAGE;
372 x->m_text.te_binbuf = binbuf_new();
373 x->m_glist = gl;
374 x->m_clock = clock_new(x, (t_method)message_tick);
375 if (argc > 1)
377 x->m_text.te_xpix = atom_getfloatarg(0, argc, argv);
378 x->m_text.te_ypix = atom_getfloatarg(1, argc, argv);
379 if (argc > 2) binbuf_restore(x->m_text.te_binbuf, argc-2, argv+2);
380 glist_add(gl, &x->m_text.te_g);
382 else
384 int xpix, ypix;
385 pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
386 glist_noselect(gl);
387 glist_getnextxy(gl, &xpix, &ypix);
388 x->m_text.te_xpix = xpix-3;
389 x->m_text.te_ypix = ypix-3;
390 glist_add(gl, &x->m_text.te_g);
391 glist_noselect(gl);
392 glist_select(gl, &x->m_text.te_g);
393 gobj_activate(&x->m_text.te_g, gl, 1);
394 canvas_startmotion(glist_getcanvas(gl));
398 /* ---------------------- the "atom" text item ------------------------ */
400 #define ATOMBUFSIZE 40
401 #define ATOM_LABELLEFT 0
402 #define ATOM_LABELRIGHT 1
403 #define ATOM_LABELUP 2
404 #define ATOM_LABELDOWN 3
406 typedef struct _gatom
408 t_text a_text;
409 t_atom a_atom; /* this holds the value and the type */
410 t_glist *a_glist; /* owning glist */
411 t_float a_toggle; /* value to toggle to */
412 t_float a_draghi; /* high end of drag range */
413 t_float a_draglo; /* low end of drag range */
414 t_symbol *a_label; /* symbol to show as label next to box */
415 t_symbol *a_symfrom; /* "receive" name -- bind ourselvs to this */
416 t_symbol *a_symto; /* "send" name -- send to this on output */
417 char a_buf[ATOMBUFSIZE];/* string buffer for typing */
418 char a_shift; /* was shift key down when dragging started? */
419 char a_wherelabel; /* 0-3 for left, right, above, below */
420 t_symbol *a_expanded_to; /* a_symto after $0, $1, ... expansion */
421 } t_gatom;
423 /* prepend "-" as necessary to avoid empty strings, so we can
424 use them in Pd messages. A more complete solution would be
425 to introduce some quoting mechanism; but then we'd be much more
426 complicated. */
427 static t_symbol *gatom_escapit(t_symbol *s)
429 if (!*s->s_name)
430 return (gensym("-"));
431 else if (*s->s_name == '-')
433 char shmo[100];
434 shmo[0] = '-';
435 strncpy(shmo+1, s->s_name, 99);
436 shmo[99] = 0;
437 return (gensym(shmo));
439 else return (iemgui_dollar2raute(s));
442 /* undo previous operation: strip leading "-" if found. */
443 static t_symbol *gatom_unescapit(t_symbol *s)
445 if (*s->s_name == '-')
446 return (gensym(s->s_name+1));
447 else return (iemgui_raute2dollar(s));
450 #if 0 /* ??? */
451 /* expand leading $0, $1, etc. in the symbol */
452 static t_symbol *gatom_realizedollar(t_gatom *x, t_symbol *s)
454 return (canvas_realizedollar(x->a_glist, s));
456 #endif
458 static void gatom_retext(t_gatom *x, int senditup)
460 binbuf_clear(x->a_text.te_binbuf);
461 binbuf_add(x->a_text.te_binbuf, 1, &x->a_atom);
462 if (senditup)
463 glist_retext(x->a_glist, &x->a_text);
466 static void gatom_set(t_gatom *x, t_symbol *s, int argc, t_atom *argv)
468 t_atom oldatom = x->a_atom;
469 int senditup = 0;
470 if (!argc) return;
471 if (x->a_atom.a_type == A_FLOAT)
472 x->a_atom.a_w.w_float = atom_getfloat(argv),
473 senditup = (x->a_atom.a_w.w_float != oldatom.a_w.w_float);
474 else if (x->a_atom.a_type == A_SYMBOL)
475 x->a_atom.a_w.w_symbol = atom_getsymbol(argv),
476 senditup = (x->a_atom.a_w.w_symbol != oldatom.a_w.w_symbol);
477 gatom_retext(x, senditup);
478 x->a_buf[0] = 0;
481 static void gatom_bang(t_gatom *x)
483 if (x->a_atom.a_type == A_FLOAT)
485 if (x->a_text.te_outlet)
486 outlet_float(x->a_text.te_outlet, x->a_atom.a_w.w_float);
487 if (*x->a_expanded_to->s_name && x->a_expanded_to->s_thing)
489 if (x->a_symto == x->a_symfrom)
490 pd_error(x,
491 "%s: atom with same send/receive name (infinite loop)",
492 x->a_symto->s_name);
493 else pd_float(x->a_expanded_to->s_thing, x->a_atom.a_w.w_float);
496 else if (x->a_atom.a_type == A_SYMBOL)
498 if (x->a_text.te_outlet)
499 outlet_symbol(x->a_text.te_outlet, x->a_atom.a_w.w_symbol);
500 if (*x->a_symto->s_name && x->a_expanded_to->s_thing)
502 if (x->a_symto == x->a_symfrom)
503 pd_error(x,
504 "%s: atom with same send/receive name (infinite loop)",
505 x->a_symto->s_name);
506 else pd_symbol(x->a_expanded_to->s_thing, x->a_atom.a_w.w_symbol);
511 static void gatom_float(t_gatom *x, t_float f)
513 t_atom at;
514 SETFLOAT(&at, f);
515 gatom_set(x, 0, 1, &at);
516 gatom_bang(x);
519 static void gatom_clipfloat(t_gatom *x, t_float f)
521 if (x->a_draglo != 0 || x->a_draghi != 0)
523 if (f < x->a_draglo)
524 f = x->a_draglo;
525 if (f > x->a_draghi)
526 f = x->a_draghi;
528 gatom_float(x, f);
531 static void gatom_symbol(t_gatom *x, t_symbol *s)
533 t_atom at;
534 SETSYMBOL(&at, s);
535 gatom_set(x, 0, 1, &at);
536 gatom_bang(x);
539 static void gatom_motion(void *z, t_floatarg dx, t_floatarg dy)
541 t_gatom *x = (t_gatom *)z;
542 if (dy == 0) return;
543 if (x->a_atom.a_type == A_FLOAT)
545 if (x->a_shift)
547 double nval = x->a_atom.a_w.w_float - 0.01 * dy;
548 double trunc = 0.01 * (floor(100. * nval + 0.5));
549 if (trunc < nval + 0.0001 && trunc > nval - 0.0001) nval = trunc;
550 gatom_clipfloat(x, nval);
552 else
554 double nval = x->a_atom.a_w.w_float - dy;
555 double trunc = 0.01 * (floor(100. * nval + 0.5));
556 if (trunc < nval + 0.0001 && trunc > nval - 0.0001) nval = trunc;
557 trunc = floor(nval + 0.5);
558 if (trunc < nval + 0.001 && trunc > nval - 0.001) nval = trunc;
559 gatom_clipfloat(x, nval);
564 static void gatom_key(void *z, t_floatarg f)
566 t_gatom *x = (t_gatom *)z;
567 int c = f;
568 int len = strlen(x->a_buf);
569 t_atom at;
570 char sbuf[ATOMBUFSIZE + 4];
571 if (c == 0)
573 /* we're being notified that no more keys will come for this grab */
574 if (x->a_buf[0])
575 gatom_retext(x, 1);
576 return;
578 else if (c == ' ') return;
579 else if (c == '\b')
581 if (len > 0)
582 x->a_buf[len-1] = 0;
583 goto redraw;
585 else if (c == '\n')
587 if (x->a_atom.a_type == A_FLOAT)
588 x->a_atom.a_w.w_float = atof(x->a_buf);
589 else if (x->a_atom.a_type == A_SYMBOL)
590 x->a_atom.a_w.w_symbol = gensym(x->a_buf);
591 else bug("gatom_key");
592 gatom_bang(x);
593 gatom_retext(x, 1);
594 x->a_buf[0] = 0;
596 else if (len < (ATOMBUFSIZE-1))
598 /* for numbers, only let reasonable characters through */
599 if ((x->a_atom.a_type == A_SYMBOL) ||
600 (c >= '0' && c <= '9' || c == '.' || c == '-'
601 || c == 'e' || c == 'E'))
603 x->a_buf[len] = c;
604 x->a_buf[len+1] = 0;
605 goto redraw;
608 return;
609 redraw:
610 /* LATER figure out how to avoid creating all these symbols! */
611 sprintf(sbuf, "%s...", x->a_buf);
612 SETSYMBOL(&at, gensym(sbuf));
613 binbuf_clear(x->a_text.te_binbuf);
614 binbuf_add(x->a_text.te_binbuf, 1, &at);
615 glist_retext(x->a_glist, &x->a_text);
618 static void gatom_click(t_gatom *x,
619 t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl,
620 t_floatarg alt)
622 if (x->a_text.te_width == 1)
624 if (x->a_atom.a_type == A_FLOAT)
625 gatom_float(x, (x->a_atom.a_w.w_float == 0));
627 else
629 if (alt)
631 if (x->a_atom.a_type != A_FLOAT) return;
632 if (x->a_atom.a_w.w_float != 0)
634 x->a_toggle = x->a_atom.a_w.w_float;
635 gatom_float(x, 0);
636 return;
638 else gatom_float(x, x->a_toggle);
640 x->a_shift = shift;
641 x->a_buf[0] = 0;
642 glist_grab(x->a_glist, &x->a_text.te_g, gatom_motion, gatom_key,
643 xpos, ypos);
647 /* message back from dialog window */
648 static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv)
650 t_float width = atom_getfloatarg(0, argc, argv);
651 t_float draglo = atom_getfloatarg(1, argc, argv);
652 t_float draghi = atom_getfloatarg(2, argc, argv);
653 t_symbol *label = gatom_unescapit(atom_getsymbolarg(3, argc, argv));
654 t_float wherelabel = atom_getfloatarg(4, argc, argv);
655 t_symbol *symfrom = gatom_unescapit(atom_getsymbolarg(5, argc, argv));
656 t_symbol *symto = gatom_unescapit(atom_getsymbolarg(6, argc, argv));
658 gobj_vis(&x->a_text.te_g, x->a_glist, 0);
659 if (!*symfrom->s_name && *x->a_symfrom->s_name)
660 inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
661 else if (*symfrom->s_name && !*x->a_symfrom->s_name && x->a_text.te_inlet)
663 canvas_deletelinesforio(x->a_glist, &x->a_text,
664 x->a_text.te_inlet, 0);
665 inlet_free(x->a_text.te_inlet);
667 if (!*symto->s_name && *x->a_symto->s_name)
668 outlet_new(&x->a_text, 0);
669 else if (*symto->s_name && !*x->a_symto->s_name && x->a_text.te_outlet)
671 canvas_deletelinesforio(x->a_glist, &x->a_text,
672 0, x->a_text.te_outlet);
673 outlet_free(x->a_text.te_outlet);
675 if (draglo >= draghi)
676 draglo = draghi = 0;
677 x->a_draglo = draglo;
678 x->a_draghi = draghi;
679 if (width < 0)
680 width = 4;
681 else if (width > 80)
682 width = 80;
683 x->a_text.te_width = width;
684 x->a_wherelabel = ((int)wherelabel & 3);
685 x->a_label = label;
686 if (*x->a_symfrom->s_name)
687 pd_unbind(&x->a_text.te_pd,
688 canvas_realizedollar(x->a_glist, x->a_symfrom));
689 x->a_symfrom = symfrom;
690 if (*x->a_symfrom->s_name)
691 pd_bind(&x->a_text.te_pd,
692 canvas_realizedollar(x->a_glist, x->a_symfrom));
693 x->a_symto = symto;
694 x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto);
695 gobj_vis(&x->a_text.te_g, x->a_glist, 1);
697 /* glist_retext(x->a_glist, &x->a_text); */
700 /* ---------------- gatom-specific widget functions --------------- */
701 static void gatom_getwherelabel(t_gatom *x, t_glist *glist, int *xp, int *yp)
703 int x1, y1, x2, y2, width, height;
704 text_getrect(&x->a_text.te_g, glist, &x1, &y1, &x2, &y2);
705 width = x2 - x1;
706 height = y2 - y1;
707 if (x->a_wherelabel == ATOM_LABELLEFT)
709 *xp = x1 - 3 -
710 strlen(canvas_realizedollar(x->a_glist, x->a_label)->s_name) *
711 sys_fontwidth(glist_getfont(glist));
712 *yp = y1 + 2;
714 else if (x->a_wherelabel == ATOM_LABELRIGHT)
716 *xp = x2 + 2;
717 *yp = y1 + 2;
719 else if (x->a_wherelabel == ATOM_LABELUP)
721 *xp = x1 - 1;
722 *yp = y1 - 1 - sys_fontheight(glist_getfont(glist));;
724 else
726 *xp = x1 - 1;
727 *yp = y2 + 3;
731 static void gatom_displace(t_gobj *z, t_glist *glist,
732 int dx, int dy)
734 t_gatom *x = (t_gatom*)z;
735 text_displace(z, glist, dx, dy);
736 sys_vgui(".x%x.c move %x.l %d %d\n", glist_getcanvas(glist),
737 x, dx, dy);
740 static void gatom_vis(t_gobj *z, t_glist *glist, int vis)
742 t_gatom *x = (t_gatom*)z;
743 text_vis(z, glist, vis);
744 if (*x->a_label->s_name)
746 if (vis)
748 int x1, y1;
749 gatom_getwherelabel(x, glist, &x1, &y1);
750 sys_vgui("pdtk_text_new .x%x.c %x.l %f %f {%s} %d %s\n",
751 glist_getcanvas(glist), x,
752 (double)x1, (double)y1,
753 canvas_realizedollar(x->a_glist, x->a_label)->s_name,
754 sys_hostfontsize(glist_getfont(glist)),
755 "black");
757 else sys_vgui(".x%x.c delete %x.l\n", glist_getcanvas(glist), x);
761 void canvas_atom(t_glist *gl, t_atomtype type,
762 t_symbol *s, int argc, t_atom *argv)
764 t_gatom *x = (t_gatom *)pd_new(gatom_class);
765 t_atom at;
766 x->a_text.te_width = 0; /* don't know it yet. */
767 x->a_text.te_type = T_ATOM;
768 x->a_text.te_binbuf = binbuf_new();
769 x->a_glist = gl;
770 x->a_atom.a_type = type;
771 x->a_toggle = 1;
772 x->a_draglo = 0;
773 x->a_draghi = 0;
774 x->a_wherelabel = 0;
775 x->a_label = &s_;
776 x->a_symfrom = &s_;
777 x->a_symto = x->a_expanded_to = &s_;
778 if (type == A_FLOAT)
780 x->a_atom.a_w.w_float = 0;
781 x->a_text.te_width = 5;
782 SETFLOAT(&at, 0);
784 else
786 x->a_atom.a_w.w_symbol = &s_symbol;
787 x->a_text.te_width = 10;
788 SETSYMBOL(&at, &s_symbol);
790 binbuf_add(x->a_text.te_binbuf, 1, &at);
791 if (argc > 1)
792 /* create from file. x, y, width, low-range, high-range, flags,
793 label, receive-name, send-name */
795 x->a_text.te_xpix = atom_getfloatarg(0, argc, argv);
796 x->a_text.te_ypix = atom_getfloatarg(1, argc, argv);
797 x->a_text.te_width = atom_getintarg(2, argc, argv);
798 /* sanity check because some very old patches have trash in this
799 field... remove this in 2003 or so: */
800 if (x->a_text.te_width < 0 || x->a_text.te_width > 500)
801 x->a_text.te_width = 4;
802 x->a_draglo = atom_getfloatarg(3, argc, argv);
803 x->a_draghi = atom_getfloatarg(4, argc, argv);
804 x->a_wherelabel = (((int)atom_getfloatarg(5, argc, argv)) & 3);
805 x->a_label = gatom_unescapit(atom_getsymbolarg(6, argc, argv));
806 x->a_symfrom = gatom_unescapit(atom_getsymbolarg(7, argc, argv));
807 if (*x->a_symfrom->s_name)
808 pd_bind(&x->a_text.te_pd,
809 canvas_realizedollar(x->a_glist, x->a_symfrom));
811 x->a_symto = gatom_unescapit(atom_getsymbolarg(8, argc, argv));
812 x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto);
813 if (x->a_symto == &s_)
814 outlet_new(&x->a_text,
815 x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol);
816 if (x->a_symfrom == &s_)
817 inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
818 glist_add(gl, &x->a_text.te_g);
820 else
822 int xpix, ypix;
823 outlet_new(&x->a_text,
824 x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol);
825 inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
826 pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
827 glist_noselect(gl);
828 glist_getnextxy(gl, &xpix, &ypix);
829 x->a_text.te_xpix = xpix;
830 x->a_text.te_ypix = ypix;
831 glist_add(gl, &x->a_text.te_g);
832 glist_noselect(gl);
833 glist_select(gl, &x->a_text.te_g);
834 canvas_startmotion(glist_getcanvas(gl));
838 void canvas_floatatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
840 canvas_atom(gl, A_FLOAT, s, argc, argv);
843 void canvas_symbolatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
845 canvas_atom(gl, A_SYMBOL, s, argc, argv);
848 static void gatom_free(t_gatom *x)
850 if (*x->a_symfrom->s_name)
851 pd_unbind(&x->a_text.te_pd,
852 canvas_realizedollar(x->a_glist, x->a_symfrom));
853 gfxstub_deleteforkey(x);
856 static void gatom_properties(t_gobj *z, t_glist *owner)
858 t_gatom *x = (t_gatom *)z;
859 char buf[200];
860 sprintf(buf, "pdtk_gatom_dialog %%s %d %g %g %d %s %s %s\n",
861 x->a_text.te_width, x->a_draglo, x->a_draghi,
862 x->a_wherelabel, gatom_escapit(x->a_label)->s_name,
863 gatom_escapit(x->a_symfrom)->s_name,
864 gatom_escapit(x->a_symto)->s_name);
865 gfxstub_new(&x->a_text.te_pd, x, buf);
869 /* -------------------- widget behavior for text objects ------------ */
871 static void text_getrect(t_gobj *z, t_glist *glist,
872 int *xp1, int *yp1, int *xp2, int *yp2)
874 t_text *x = (t_text *)z;
875 int width, height, iscomment = (x->te_type == T_TEXT);
876 float x1, y1, x2, y2;
878 /* for number boxes, we know width and height a priori, and should
879 report them here so that graphs can get swelled to fit. */
881 if (x->te_type == T_ATOM && x->te_width > 0)
883 int font = glist_getfont(glist);
884 int fontwidth = sys_fontwidth(font), fontheight = sys_fontheight(font);
885 width = (x->te_width > 0 ? x->te_width : 6) * fontwidth + 2;
886 height = fontheight + 1; /* borrowed from TMARGIN, etc, in g_rtext.c */
888 /* if we're invisible we don't know our size so we just lie about
889 it. This is called on invisible boxes to establish order of inlets
890 and possibly other reasons.
891 To find out if the box is visible we can't just check the "vis"
892 flag because we might be within the vis() routine and not have set
893 that yet. So we check directly whether the "rtext" list has been
894 built. LATER reconsider when "vis" flag should be on and off? */
896 else if (glist->gl_editor && glist->gl_editor->e_rtext)
898 t_rtext *y = glist_findrtext(glist, x);
899 width = rtext_width(y);
900 height = rtext_height(y) - (iscomment << 1);
902 else width = height = 10;
903 x1 = text_xpix(x, glist);
904 y1 = text_ypix(x, glist);
905 x2 = x1 + width;
906 y2 = y1 + height;
907 y1 += iscomment;
908 *xp1 = x1;
909 *yp1 = y1;
910 *xp2 = x2;
911 *yp2 = y2;
914 static void text_displace(t_gobj *z, t_glist *glist,
915 int dx, int dy)
917 t_text *x = (t_text *)z;
918 x->te_xpix += dx;
919 x->te_ypix += dy;
920 if (glist_isvisible(glist))
922 t_rtext *y = glist_findrtext(glist, x);
923 rtext_displace(y, dx, dy);
924 text_drawborder(x, glist, rtext_gettag(y),
925 rtext_width(y), rtext_height(y), 0);
926 canvas_fixlinesfor(glist_getcanvas(glist), x);
930 static void text_select(t_gobj *z, t_glist *glist, int state)
932 t_text *x = (t_text *)z;
933 t_rtext *y = glist_findrtext(glist, x);
934 rtext_select(y, state);
935 if (glist_isvisible(glist) && text_shouldvis(x, glist))
936 sys_vgui(".x%x.c itemconfigure %sR -fill %s\n", glist,
937 rtext_gettag(y), (state? "blue" : "black"));
940 static void text_activate(t_gobj *z, t_glist *glist, int state)
942 t_text *x = (t_text *)z;
943 t_rtext *y = glist_findrtext(glist, x);
944 if (z->g_pd != gatom_class) rtext_activate(y, state);
947 static void text_delete(t_gobj *z, t_glist *glist)
949 t_text *x = (t_text *)z;
950 canvas_deletelinesfor(glist, x);
953 /* return true if the text box should be drawn.
954 We don't show object boxes inside graphs. */
955 int text_shouldvis(t_text *x, t_glist *glist)
957 return (glist->gl_havewindow ||
958 (x->te_pd != canvas_class && x->te_pd->c_wb != &text_widgetbehavior) ||
959 (x->te_pd == canvas_class && (((t_glist *)x)->gl_isgraph)));
962 static void text_vis(t_gobj *z, t_glist *glist, int vis)
964 t_text *x = (t_text *)z;
965 if (vis)
967 if (text_shouldvis(x, glist))
969 t_rtext *y = glist_findrtext(glist, x);
970 if (x->te_type == T_ATOM)
971 glist_retext(glist, x);
972 text_drawborder(x, glist, rtext_gettag(y),
973 rtext_width(y), rtext_height(y), 1);
974 rtext_draw(y);
977 else
979 t_rtext *y = glist_findrtext(glist, x);
980 if (text_shouldvis(x, glist))
982 text_eraseborder(x, glist, rtext_gettag(y));
983 rtext_erase(y);
988 static int text_click(t_gobj *z, struct _glist *glist,
989 int xpix, int ypix, int shift, int alt, int dbl, int doit)
991 t_text *x = (t_text *)z;
992 if (x->te_type == T_OBJECT)
994 t_symbol *clicksym = gensym("click");
995 if (zgetfn(&x->te_pd, clicksym))
997 if (doit)
998 pd_vmess(&x->te_pd, clicksym, "fffff",
999 (double)xpix, (double)ypix,
1000 (double)shift, 0, (double)alt);
1001 return (1);
1003 else return (0);
1005 else if (x->te_type == T_ATOM)
1007 if (doit)
1008 gatom_click((t_gatom *)x, (t_floatarg)xpix, (t_floatarg)ypix,
1009 (t_floatarg)shift, 0, (t_floatarg)alt);
1010 return (1);
1012 else if (x->te_type == T_MESSAGE)
1014 if (doit)
1015 message_click((t_message *)x, (t_floatarg)xpix, (t_floatarg)ypix,
1016 (t_floatarg)shift, 0, (t_floatarg)alt);
1017 return (1);
1019 else return (0);
1022 void text_save(t_gobj *z, t_binbuf *b)
1024 t_text *x = (t_text *)z;
1025 if (x->te_type == T_OBJECT)
1027 /* if we have a "saveto" method, and if we don't happen to be
1028 a canvas that's an abstraction, the saveto method does the work */
1029 if (zgetfn(&x->te_pd, gensym("saveto")) &&
1030 !((pd_class(&x->te_pd) == canvas_class) &&
1031 (canvas_isabstraction((t_canvas *)x)
1032 || canvas_istable((t_canvas *)x))))
1034 mess1(&x->te_pd, gensym("saveto"), b);
1035 binbuf_addv(b, "ssii", gensym("#X"), gensym("restore"),
1036 (t_int)x->te_xpix, (t_int)x->te_ypix);
1038 else /* otherwise just save the text */
1040 binbuf_addv(b, "ssii", gensym("#X"), gensym("obj"),
1041 (t_int)x->te_xpix, (t_int)x->te_ypix);
1043 binbuf_addbinbuf(b, x->te_binbuf);
1044 binbuf_addv(b, ";");
1046 else if (x->te_type == T_MESSAGE)
1048 binbuf_addv(b, "ssii", gensym("#X"), gensym("msg"),
1049 (t_int)x->te_xpix, (t_int)x->te_ypix);
1050 binbuf_addbinbuf(b, x->te_binbuf);
1051 binbuf_addv(b, ";");
1053 else if (x->te_type == T_ATOM)
1055 t_atomtype t = ((t_gatom *)x)->a_atom.a_type;
1056 t_symbol *sel = (t == A_SYMBOL ? gensym("symbolatom") :
1057 (t == A_FLOAT ? gensym("floatatom") : gensym("intatom")));
1058 t_symbol *label = gatom_escapit(((t_gatom *)x)->a_label);
1059 t_symbol *symfrom = gatom_escapit(((t_gatom *)x)->a_symfrom);
1060 t_symbol *symto = gatom_escapit(((t_gatom *)x)->a_symto);
1061 binbuf_addv(b, "ssiiifffsss", gensym("#X"), sel,
1062 (t_int)x->te_xpix, (t_int)x->te_ypix, (t_int)x->te_width,
1063 (double)((t_gatom *)x)->a_draglo,
1064 (double)((t_gatom *)x)->a_draghi,
1065 (double)((t_gatom *)x)->a_wherelabel,
1066 label, symfrom, symto);
1067 binbuf_addv(b, ";");
1069 else
1071 binbuf_addv(b, "ssii", gensym("#X"), gensym("text"),
1072 (t_int)x->te_xpix, (t_int)x->te_ypix);
1073 binbuf_addbinbuf(b, x->te_binbuf);
1074 binbuf_addv(b, ";");
1078 /* this one is for everyone but "gatoms"; it's imposed in m_class.c */
1079 t_widgetbehavior text_widgetbehavior =
1081 text_getrect,
1082 text_displace,
1083 text_select,
1084 text_activate,
1085 text_delete,
1086 text_vis,
1087 text_click,
1090 static t_widgetbehavior gatom_widgetbehavior =
1092 text_getrect,
1093 gatom_displace,
1094 text_select,
1095 text_activate,
1096 text_delete,
1097 gatom_vis,
1098 text_click,
1101 /* -------------------- the "text" class ------------ */
1103 #ifdef MACOSX
1104 #define EXTRAPIX 2
1105 #else
1106 #define EXTRAPIX 1
1107 #endif
1109 /* draw inlets and outlets for a text object or for a graph. */
1110 void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
1111 char *tag, int x1, int y1, int x2, int y2)
1113 int n = obj_noutlets(ob), nplus = (n == 1 ? 1 : n-1), i;
1114 int width = x2 - x1;
1115 for (i = 0; i < n; i++)
1117 int onset = x1 + (width - IOWIDTH) * i / nplus;
1118 if (firsttime)
1119 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %so%d\n",
1120 glist_getcanvas(glist),
1121 onset, y2 - 1,
1122 onset + IOWIDTH, y2,
1123 tag, i);
1124 else
1125 sys_vgui(".x%x.c coords %so%d %d %d %d %d\n",
1126 glist_getcanvas(glist), tag, i,
1127 onset, y2 - 1,
1128 onset + IOWIDTH, y2);
1130 n = obj_ninlets(ob);
1131 nplus = (n == 1 ? 1 : n-1);
1132 for (i = 0; i < n; i++)
1134 int onset = x1 + (width - IOWIDTH) * i / nplus;
1135 if (firsttime)
1136 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %si%d\n",
1137 glist_getcanvas(glist),
1138 onset, y1,
1139 onset + IOWIDTH, y1 + EXTRAPIX,
1140 tag, i);
1141 else
1142 sys_vgui(".x%x.c coords %si%d %d %d %d %d\n",
1143 glist_getcanvas(glist), tag, i,
1144 onset, y1,
1145 onset + IOWIDTH, y1 + EXTRAPIX);
1149 void text_drawborder(t_text *x, t_glist *glist,
1150 char *tag, int width2, int height2, int firsttime)
1152 t_object *ob;
1153 int x1, y1, x2, y2, width, height;
1154 text_getrect(&x->te_g, glist, &x1, &y1, &x2, &y2);
1155 width = x2 - x1;
1156 height = y2 - y1;
1157 if (x->te_type == T_OBJECT)
1159 if (firsttime)
1160 sys_vgui(".x%x.c create line\
1161 %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
1162 glist_getcanvas(glist),
1163 x1, y1, x2, y1, x2, y2, x1, y2, x1, y1, tag);
1164 else
1165 sys_vgui(".x%x.c coords %sR\
1166 %d %d %d %d %d %d %d %d %d %d\n",
1167 glist_getcanvas(glist), tag,
1168 x1, y1, x2, y1, x2, y2, x1, y2, x1, y1);
1170 else if (x->te_type == T_MESSAGE)
1172 if (firsttime)
1173 sys_vgui(".x%x.c create line\
1174 %d %d %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
1175 glist_getcanvas(glist),
1176 x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2,
1177 x1, y2, x1, y1,
1178 tag);
1179 else
1180 sys_vgui(".x%x.c coords %sR\
1181 %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
1182 glist_getcanvas(glist), tag,
1183 x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2,
1184 x1, y2, x1, y1);
1186 else if (x->te_type == T_ATOM)
1188 if (firsttime)
1189 sys_vgui(".x%x.c create line\
1190 %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
1191 glist_getcanvas(glist),
1192 x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1,
1193 tag);
1194 else
1195 sys_vgui(".x%x.c coords %sR\
1196 %d %d %d %d %d %d %d %d %d %d %d %d\n",
1197 glist_getcanvas(glist), tag,
1198 x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1);
1200 /* draw inlets/outlets */
1202 if (ob = pd_checkobject(&x->te_pd))
1203 glist_drawiofor(glist, ob, firsttime, tag, x1, y1, x2, y2);
1206 void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag)
1208 int i, n;
1209 n = obj_noutlets(ob);
1210 for (i = 0; i < n; i++)
1211 sys_vgui(".x%x.c delete %so%d\n",
1212 glist_getcanvas(glist), tag, i);
1213 n = obj_ninlets(ob);
1214 for (i = 0; i < n; i++)
1215 sys_vgui(".x%x.c delete %si%d\n",
1216 glist_getcanvas(glist), tag, i);
1219 void text_eraseborder(t_text *x, t_glist *glist, char *tag)
1221 if (x->te_type == T_TEXT) return;
1222 sys_vgui(".x%x.c delete %sR\n",
1223 glist_getcanvas(glist), tag);
1224 glist_eraseiofor(glist, x, tag);
1227 /* change text; if T_OBJECT, remake it. LATER we'll have an undo buffer
1228 which should be filled in here before making the change. */
1230 void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize)
1232 if (x->te_type == T_OBJECT)
1234 t_binbuf *b = binbuf_new();
1235 int natom1, natom2;
1236 t_atom *vec1, *vec2;
1237 binbuf_text(b, buf, bufsize);
1238 natom1 = binbuf_getnatom(x->te_binbuf);
1239 vec1 = binbuf_getvec(x->te_binbuf);
1240 natom2 = binbuf_getnatom(b);
1241 vec2 = binbuf_getvec(b);
1242 /* special case: if pd args change just pass the message on. */
1243 if (natom1 >= 1 && natom2 >= 1 && vec1[0].a_type == A_SYMBOL
1244 && !strcmp(vec1[0].a_w.w_symbol->s_name, "pd") &&
1245 vec2[0].a_type == A_SYMBOL
1246 && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd"))
1248 typedmess(&x->te_pd, gensym("rename"), natom2-1, vec2+1);
1249 binbuf_free(x->te_binbuf);
1250 x->te_binbuf = b;
1252 else /* normally, just destroy the old one and make a new one. */
1254 int xwas = x->te_xpix, ywas = x->te_ypix;
1255 glist_delete(glist, &x->te_g);
1256 canvas_objtext(glist, xwas, ywas, 0, b);
1257 /* if it's an abstraction loadbang it here */
1258 if (newest && pd_class(newest) == canvas_class)
1259 canvas_loadbang((t_canvas *)newest);
1260 canvas_restoreconnections(glist_getcanvas(glist));
1262 /* if we made a new "pd" or changed a window name,
1263 update window list */
1264 if (natom2 >= 1 && vec2[0].a_type == A_SYMBOL
1265 && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd"))
1266 canvas_updatewindowlist();
1268 else binbuf_text(x->te_binbuf, buf, bufsize);
1271 void g_text_setup(void)
1273 text_class = class_new(gensym("text"), 0, 0, sizeof(t_text),
1274 CLASS_NOINLET | CLASS_PATCHABLE, 0);
1276 message_class = class_new(gensym("message"), 0, (t_method)message_free,
1277 sizeof(t_message), CLASS_PATCHABLE, 0);
1278 class_addbang(message_class, message_bang);
1279 class_addfloat(message_class, message_float);
1280 class_addsymbol(message_class, message_symbol);
1281 class_addlist(message_class, message_list);
1282 class_addanything(message_class, message_list);
1284 class_addmethod(message_class, (t_method)message_click, gensym("click"),
1285 A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
1286 class_addmethod(message_class, (t_method)message_set, gensym("set"),
1287 A_GIMME, 0);
1288 class_addmethod(message_class, (t_method)message_add, gensym("add"),
1289 A_GIMME, 0);
1290 class_addmethod(message_class, (t_method)message_add2, gensym("add2"),
1291 A_GIMME, 0);
1293 messresponder_class = class_new(gensym("messresponder"), 0, 0,
1294 sizeof(t_text), CLASS_PD, 0);
1295 class_addbang(messresponder_class, messresponder_bang);
1296 class_addfloat(messresponder_class, (t_method) messresponder_float);
1297 class_addsymbol(messresponder_class, messresponder_symbol);
1298 class_addlist(messresponder_class, messresponder_list);
1299 class_addanything(messresponder_class, messresponder_anything);
1301 gatom_class = class_new(gensym("gatom"), 0, (t_method)gatom_free,
1302 sizeof(t_gatom), CLASS_NOINLET | CLASS_PATCHABLE, 0);
1303 class_addbang(gatom_class, gatom_bang);
1304 class_addfloat(gatom_class, gatom_float);
1305 class_addsymbol(gatom_class, gatom_symbol);
1306 class_addmethod(gatom_class, (t_method)gatom_set, gensym("set"),
1307 A_GIMME, 0);
1308 class_addmethod(gatom_class, (t_method)gatom_click, gensym("click"),
1309 A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
1310 class_addmethod(gatom_class, (t_method)gatom_param, gensym("param"),
1311 A_GIMME, 0);
1312 class_setwidget(gatom_class, &gatom_widgetbehavior);
1313 class_setpropertiesfn(gatom_class, gatom_properties);
1317 /* Copyright (c) 1997-1999 Miller Puckette.
1318 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
1319 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
1321 /* changes by Thomas Musil IEM KUG Graz Austria 2001 */
1322 /* the methods for calling the gui-objects from menu are implemented */
1323 /* all changes are labeled with iemlib */
1325 #include <stdlib.h>
1326 #include "m_pd.h"
1327 #include "m_imp.h"
1328 #include "s_stuff.h"
1329 #include "t_tk.h"
1330 #include "g_canvas.h"
1331 #include <stdio.h>
1332 #include <string.h>
1333 #include <math.h>
1335 static t_class *text_class;
1336 static t_class *message_class;
1337 static t_class *gatom_class;
1338 static void text_vis(t_gobj *z, t_glist *glist, int vis);
1339 static void text_displace(t_gobj *z, t_glist *glist,
1340 int dx, int dy);
1341 static void text_getrect(t_gobj *z, t_glist *glist,
1342 int *xp1, int *yp1, int *xp2, int *yp2);
1344 void canvas_startmotion(t_canvas *x);
1345 t_widgetbehavior text_widgetbehavior;
1347 /* ----------------- the "text" object. ------------------ */
1349 /* add a "text" object (comment) to a glist. While this one goes for any glist,
1350 the other 3 below are for canvases only. (why?) This is called
1351 without args if invoked from the GUI; otherwise at least x and y
1352 are provided. */
1354 void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1356 t_text *x = (t_text *)pd_new(text_class);
1357 t_atom at;
1358 x->te_width = 0; /* don't know it yet. */
1359 x->te_type = T_TEXT;
1360 x->te_binbuf = binbuf_new();
1361 if (argc > 1)
1363 x->te_xpix = atom_getfloatarg(0, argc, argv);
1364 x->te_ypix = atom_getfloatarg(1, argc, argv);
1365 if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2);
1366 else
1368 SETSYMBOL(&at, gensym("comment"));
1369 binbuf_restore(x->te_binbuf, 1, &at);
1371 glist_add(gl, &x->te_g);
1373 else
1375 int xpix, ypix;
1376 pd_vmess((t_pd *)glist_getcanvas(gl), gensym("editmode"), "i", 1);
1377 SETSYMBOL(&at, gensym("comment"));
1378 glist_noselect(gl);
1379 glist_getnextxy(gl, &xpix, &ypix);
1380 x->te_xpix = glist_pixelstox(gl, xpix-3);
1381 x->te_ypix = glist_pixelstoy(gl, ypix-3);
1382 binbuf_restore(x->te_binbuf, 1, &at);
1383 glist_add(gl, &x->te_g);
1384 glist_noselect(gl);
1385 glist_select(gl, &x->te_g);
1386 /* it would be nice to "activate" here, but then the second,
1387 "put-me-down" click changes the text selection, which is quite
1388 irritating, so I took this back out. It's OK in messages
1389 and objects though since there's no text in them at menu
1390 creation. */
1391 /* gobj_activate(&x->te_g, gl, 1); */
1392 canvas_startmotion(glist_getcanvas(gl));
1396 /* ----------------- the "object" object. ------------------ */
1398 extern t_pd *newest;
1399 void canvas_getargs(int *argcp, t_atom **argvp);
1401 static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected,
1402 t_binbuf *b)
1404 t_text *x;
1405 int argc;
1406 t_atom *argv;
1407 newest = 0;
1408 canvas_setcurrent((t_canvas *)gl);
1409 canvas_getargs(&argc, &argv);
1410 binbuf_eval(b, &pd_objectmaker, argc, argv);
1411 if (binbuf_getnatom(b))
1413 if (!newest)
1415 binbuf_print(b);
1416 post("... couldn't create");
1417 x = 0;
1419 else if (!(x = pd_checkobject(newest)))
1421 binbuf_print(b);
1422 post("... didn't return a patchable object");
1425 else x = 0;
1426 if (!x)
1429 /* LATER make the color reflect this */
1430 x = (t_text *)pd_new(text_class);
1432 x->te_binbuf = b;
1433 x->te_xpix = xpix;
1434 x->te_ypix = ypix;
1435 x->te_width = 0;
1436 x->te_type = T_OBJECT;
1437 glist_add(gl, &x->te_g);
1438 if (selected)
1440 /* this is called if we've been created from the menu. */
1441 glist_select(gl, &x->te_g);
1442 gobj_activate(&x->te_g, gl, 1);
1444 if (pd_class(&x->ob_pd) == vinlet_class)
1445 canvas_resortinlets(glist_getcanvas(gl));
1446 if (pd_class(&x->ob_pd) == voutlet_class)
1447 canvas_resortoutlets(glist_getcanvas(gl));
1448 canvas_unsetcurrent((t_canvas *)gl);
1451 /* object creation routine. These are called without any arguments if
1452 they're invoked from the
1453 gui; when pasting or restoring from a file, we get at least x and y. */
1455 void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1457 t_text *x;
1458 if (argc >= 2)
1460 t_binbuf *b = binbuf_new();
1461 binbuf_restore(b, argc-2, argv+2);
1462 canvas_objtext(gl, atom_getintarg(0, argc, argv),
1463 atom_getintarg(1, argc, argv), 0, b);
1465 else
1467 t_binbuf *b = binbuf_new();
1468 int xpix, ypix;
1469 pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
1470 glist_noselect(gl);
1471 glist_getnextxy(gl, &xpix, &ypix);
1472 canvas_objtext(gl, xpix, ypix, 1, b);
1473 canvas_startmotion(glist_getcanvas(gl));
1477 /* make an object box for an object that's already there. */
1479 /* iemlib */
1480 void canvas_iemguis(t_glist *gl, t_symbol *guiobjname)
1482 t_atom at;
1483 t_binbuf *b = binbuf_new();
1484 int xpix, ypix;
1486 pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
1487 glist_noselect(gl);
1488 SETSYMBOL(&at, guiobjname);
1489 binbuf_restore(b, 1, &at);
1490 glist_getnextxy(gl, &xpix, &ypix);
1491 canvas_objtext(gl, xpix, ypix, 1, b);
1492 canvas_startmotion(glist_getcanvas(gl));
1495 void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1497 canvas_iemguis(gl, gensym("bng"));
1500 void canvas_toggle(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1502 canvas_iemguis(gl, gensym("tgl"));
1505 void canvas_vslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1507 canvas_iemguis(gl, gensym("vsl"));
1510 void canvas_hslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1512 canvas_iemguis(gl, gensym("hsl"));
1515 void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1517 canvas_iemguis(gl, gensym("hdl"));
1520 void canvas_vdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1522 canvas_iemguis(gl, gensym("vdl"));
1525 void canvas_hradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1527 canvas_iemguis(gl, gensym("hradio"));
1530 void canvas_vradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1532 canvas_iemguis(gl, gensym("vradio"));
1535 void canvas_vumeter(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1537 canvas_iemguis(gl, gensym("vu"));
1540 void canvas_mycnv(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1542 canvas_iemguis(gl, gensym("cnv"));
1545 void canvas_numbox(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1547 canvas_iemguis(gl, gensym("nbx"));
1550 /* iemlib */
1552 void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv)
1554 x->te_width = 0; /* don't know it yet. */
1555 x->te_type = T_OBJECT;
1556 x->te_binbuf = binbuf_new();
1557 x->te_xpix = atom_getfloatarg(0, argc, argv);
1558 x->te_ypix = atom_getfloatarg(1, argc, argv);
1559 if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2);
1560 glist_add(gl, &x->te_g);
1563 /* ---------------------- the "message" text item ------------------------ */
1565 typedef struct _messresponder
1567 t_pd mr_pd;
1568 t_outlet *mr_outlet;
1569 } t_messresponder;
1571 typedef struct _message
1573 t_text m_text;
1574 t_messresponder m_messresponder;
1575 t_glist *m_glist;
1576 t_clock *m_clock;
1577 } t_message;
1579 static t_class *message_class, *messresponder_class;
1581 static void messresponder_bang(t_messresponder *x)
1583 outlet_bang(x->mr_outlet);
1586 static void messresponder_float(t_messresponder *x, t_float f)
1588 outlet_float(x->mr_outlet, f);
1591 static void messresponder_symbol(t_messresponder *x, t_symbol *s)
1593 outlet_symbol(x->mr_outlet, s);
1596 static void messresponder_list(t_messresponder *x,
1597 t_symbol *s, int argc, t_atom *argv)
1599 outlet_list(x->mr_outlet, s, argc, argv);
1602 static void messresponder_anything(t_messresponder *x,
1603 t_symbol *s, int argc, t_atom *argv)
1605 outlet_anything(x->mr_outlet, s, argc, argv);
1608 static void message_bang(t_message *x)
1610 binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 0, 0);
1613 static void message_float(t_message *x, t_float f)
1615 t_atom at;
1616 SETFLOAT(&at, f);
1617 binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
1620 static void message_symbol(t_message *x, t_symbol *s)
1622 t_atom at;
1623 SETSYMBOL(&at, s);
1624 binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
1627 static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv)
1629 binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, argc, argv);
1632 static void message_set(t_message *x, t_symbol *s, int argc, t_atom *argv)
1634 binbuf_clear(x->m_text.te_binbuf);
1635 binbuf_add(x->m_text.te_binbuf, argc, argv);
1636 glist_retext(x->m_glist, &x->m_text);
1639 static void message_add2(t_message *x, t_symbol *s, int argc, t_atom *argv)
1641 binbuf_add(x->m_text.te_binbuf, argc, argv);
1642 glist_retext(x->m_glist, &x->m_text);
1645 static void message_add(t_message *x, t_symbol *s, int argc, t_atom *argv)
1647 binbuf_add(x->m_text.te_binbuf, argc, argv);
1648 binbuf_addsemi(x->m_text.te_binbuf);
1649 glist_retext(x->m_glist, &x->m_text);
1652 static void message_click(t_message *x,
1653 t_floatarg xpos, t_floatarg ypos, t_floatarg shift,
1654 t_floatarg ctrl, t_floatarg alt)
1656 message_float(x, 0);
1657 if (glist_isvisible(x->m_glist))
1659 t_rtext *y = glist_findrtext(x->m_glist, &x->m_text);
1660 sys_vgui(".x%x.c itemconfigure %sR -width 5\n",
1661 glist_getcanvas(x->m_glist), rtext_gettag(y));
1662 clock_delay(x->m_clock, 120);
1666 static void message_tick(t_message *x)
1668 if (glist_isvisible(x->m_glist))
1670 t_rtext *y = glist_findrtext(x->m_glist, &x->m_text);
1671 sys_vgui(".x%x.c itemconfigure %sR -width 1\n",
1672 glist_getcanvas(x->m_glist), rtext_gettag(y));
1676 static void message_free(t_message *x)
1678 clock_free(x->m_clock);
1681 void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
1683 t_message *x = (t_message *)pd_new(message_class);
1684 x->m_messresponder.mr_pd = messresponder_class;
1685 x->m_messresponder.mr_outlet = outlet_new(&x->m_text, &s_float);
1686 x->m_text.te_width = 0; /* don't know it yet. */
1687 x->m_text.te_type = T_MESSAGE;
1688 x->m_text.te_binbuf = binbuf_new();
1689 x->m_glist = gl;
1690 x->m_clock = clock_new(x, (t_method)message_tick);
1691 if (argc > 1)
1693 x->m_text.te_xpix = atom_getfloatarg(0, argc, argv);
1694 x->m_text.te_ypix = atom_getfloatarg(1, argc, argv);
1695 if (argc > 2) binbuf_restore(x->m_text.te_binbuf, argc-2, argv+2);
1696 glist_add(gl, &x->m_text.te_g);
1698 else
1700 int xpix, ypix;
1701 pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
1702 glist_noselect(gl);
1703 glist_getnextxy(gl, &xpix, &ypix);
1704 x->m_text.te_xpix = xpix-3;
1705 x->m_text.te_ypix = ypix-3;
1706 glist_add(gl, &x->m_text.te_g);
1707 glist_noselect(gl);
1708 glist_select(gl, &x->m_text.te_g);
1709 gobj_activate(&x->m_text.te_g, gl, 1);
1710 canvas_startmotion(glist_getcanvas(gl));
1714 /* ---------------------- the "atom" text item ------------------------ */
1716 #define ATOMBUFSIZE 40
1717 #define ATOM_LABELLEFT 0
1718 #define ATOM_LABELRIGHT 1
1719 #define ATOM_LABELUP 2
1720 #define ATOM_LABELDOWN 3
1722 typedef struct _gatom
1724 t_text a_text;
1725 t_atom a_atom; /* this holds the value and the type */
1726 t_glist *a_glist; /* owning glist */
1727 t_float a_toggle; /* value to toggle to */
1728 t_float a_draghi; /* high end of drag range */
1729 t_float a_draglo; /* low end of drag range */
1730 t_symbol *a_label; /* symbol to show as label next to box */
1731 t_symbol *a_symfrom; /* "receive" name -- bind ourselvs to this */
1732 t_symbol *a_symto; /* "send" name -- send to this on output */
1733 char a_buf[ATOMBUFSIZE];/* string buffer for typing */
1734 char a_shift; /* was shift key down when dragging started? */
1735 char a_wherelabel; /* 0-3 for left, right, above, below */
1736 t_symbol *a_expanded_to; /* a_symto after $0, $1, ... expansion */
1737 } t_gatom;
1739 /* prepend "-" as necessary to avoid empty strings, so we can
1740 use them in Pd messages. A more complete solution would be
1741 to introduce some quoting mechanism; but then we'd be much more
1742 complicated. */
1743 static t_symbol *gatom_escapit(t_symbol *s)
1745 if (!*s->s_name)
1746 return (gensym("-"));
1747 else if (*s->s_name == '-')
1749 char shmo[100];
1750 shmo[0] = '-';
1751 strncpy(shmo+1, s->s_name, 99);
1752 shmo[99] = 0;
1753 return (gensym(shmo));
1755 else return (iemgui_dollar2raute(s));
1758 /* undo previous operation: strip leading "-" if found. */
1759 static t_symbol *gatom_unescapit(t_symbol *s)
1761 if (*s->s_name == '-')
1762 return (gensym(s->s_name+1));
1763 else return (iemgui_raute2dollar(s));
1766 #if 0 /* ??? */
1767 /* expand leading $0, $1, etc. in the symbol */
1768 static t_symbol *gatom_realizedollar(t_gatom *x, t_symbol *s)
1770 return (canvas_realizedollar(x->a_glist, s));
1772 #endif
1774 static void gatom_retext(t_gatom *x, int senditup)
1776 binbuf_clear(x->a_text.te_binbuf);
1777 binbuf_add(x->a_text.te_binbuf, 1, &x->a_atom);
1778 if (senditup)
1779 glist_retext(x->a_glist, &x->a_text);
1782 static void gatom_set(t_gatom *x, t_symbol *s, int argc, t_atom *argv)
1784 t_atom oldatom = x->a_atom;
1785 int senditup = 0;
1786 if (!argc) return;
1787 if (x->a_atom.a_type == A_FLOAT)
1788 x->a_atom.a_w.w_float = atom_getfloat(argv),
1789 senditup = (x->a_atom.a_w.w_float != oldatom.a_w.w_float);
1790 else if (x->a_atom.a_type == A_SYMBOL)
1791 x->a_atom.a_w.w_symbol = atom_getsymbol(argv),
1792 senditup = (x->a_atom.a_w.w_symbol != oldatom.a_w.w_symbol);
1793 gatom_retext(x, senditup);
1794 x->a_buf[0] = 0;
1797 static void gatom_bang(t_gatom *x)
1799 if (x->a_atom.a_type == A_FLOAT)
1801 if (x->a_text.te_outlet)
1802 outlet_float(x->a_text.te_outlet, x->a_atom.a_w.w_float);
1803 if (*x->a_expanded_to->s_name && x->a_expanded_to->s_thing)
1805 if (x->a_symto == x->a_symfrom)
1806 pd_error(x,
1807 "%s: atom with same send/receive name (infinite loop)",
1808 x->a_symto->s_name);
1809 else pd_float(x->a_expanded_to->s_thing, x->a_atom.a_w.w_float);
1812 else if (x->a_atom.a_type == A_SYMBOL)
1814 if (x->a_text.te_outlet)
1815 outlet_symbol(x->a_text.te_outlet, x->a_atom.a_w.w_symbol);
1816 if (*x->a_symto->s_name && x->a_expanded_to->s_thing)
1818 if (x->a_symto == x->a_symfrom)
1819 pd_error(x,
1820 "%s: atom with same send/receive name (infinite loop)",
1821 x->a_symto->s_name);
1822 else pd_symbol(x->a_expanded_to->s_thing, x->a_atom.a_w.w_symbol);
1827 static void gatom_float(t_gatom *x, t_float f)
1829 t_atom at;
1830 SETFLOAT(&at, f);
1831 gatom_set(x, 0, 1, &at);
1832 gatom_bang(x);
1835 static void gatom_clipfloat(t_gatom *x, t_float f)
1837 if (x->a_draglo != 0 || x->a_draghi != 0)
1839 if (f < x->a_draglo)
1840 f = x->a_draglo;
1841 if (f > x->a_draghi)
1842 f = x->a_draghi;
1844 gatom_float(x, f);
1847 static void gatom_symbol(t_gatom *x, t_symbol *s)
1849 t_atom at;
1850 SETSYMBOL(&at, s);
1851 gatom_set(x, 0, 1, &at);
1852 gatom_bang(x);
1855 static void gatom_motion(void *z, t_floatarg dx, t_floatarg dy)
1857 t_gatom *x = (t_gatom *)z;
1858 if (dy == 0) return;
1859 if (x->a_atom.a_type == A_FLOAT)
1861 if (x->a_shift)
1863 double nval = x->a_atom.a_w.w_float - 0.01 * dy;
1864 double trunc = 0.01 * (floor(100. * nval + 0.5));
1865 if (trunc < nval + 0.0001 && trunc > nval - 0.0001) nval = trunc;
1866 gatom_clipfloat(x, nval);
1868 else
1870 double nval = x->a_atom.a_w.w_float - dy;
1871 double trunc = 0.01 * (floor(100. * nval + 0.5));
1872 if (trunc < nval + 0.0001 && trunc > nval - 0.0001) nval = trunc;
1873 trunc = floor(nval + 0.5);
1874 if (trunc < nval + 0.001 && trunc > nval - 0.001) nval = trunc;
1875 gatom_clipfloat(x, nval);
1880 static void gatom_key(void *z, t_floatarg f)
1882 t_gatom *x = (t_gatom *)z;
1883 int c = f;
1884 int len = strlen(x->a_buf);
1885 t_atom at;
1886 char sbuf[ATOMBUFSIZE + 4];
1887 if (c == 0)
1889 /* we're being notified that no more keys will come for this grab */
1890 if (x->a_buf[0])
1891 gatom_retext(x, 1);
1892 return;
1894 else if (c == ' ') return;
1895 else if (c == '\b')
1897 if (len > 0)
1898 x->a_buf[len-1] = 0;
1899 goto redraw;
1901 else if (c == '\n')
1903 if (x->a_atom.a_type == A_FLOAT)
1904 x->a_atom.a_w.w_float = atof(x->a_buf);
1905 else if (x->a_atom.a_type == A_SYMBOL)
1906 x->a_atom.a_w.w_symbol = gensym(x->a_buf);
1907 else bug("gatom_key");
1908 gatom_bang(x);
1909 gatom_retext(x, 1);
1910 x->a_buf[0] = 0;
1912 else if (len < (ATOMBUFSIZE-1))
1914 /* for numbers, only let reasonable characters through */
1915 if ((x->a_atom.a_type == A_SYMBOL) ||
1916 (c >= '0' && c <= '9' || c == '.' || c == '-'
1917 || c == 'e' || c == 'E'))
1919 x->a_buf[len] = c;
1920 x->a_buf[len+1] = 0;
1921 goto redraw;
1924 return;
1925 redraw:
1926 /* LATER figure out how to avoid creating all these symbols! */
1927 sprintf(sbuf, "%s...", x->a_buf);
1928 SETSYMBOL(&at, gensym(sbuf));
1929 binbuf_clear(x->a_text.te_binbuf);
1930 binbuf_add(x->a_text.te_binbuf, 1, &at);
1931 glist_retext(x->a_glist, &x->a_text);
1934 static void gatom_click(t_gatom *x,
1935 t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl,
1936 t_floatarg alt)
1938 if (x->a_text.te_width == 1)
1940 if (x->a_atom.a_type == A_FLOAT)
1941 gatom_float(x, (x->a_atom.a_w.w_float == 0));
1943 else
1945 if (alt)
1947 if (x->a_atom.a_type != A_FLOAT) return;
1948 if (x->a_atom.a_w.w_float != 0)
1950 x->a_toggle = x->a_atom.a_w.w_float;
1951 gatom_float(x, 0);
1952 return;
1954 else gatom_float(x, x->a_toggle);
1956 x->a_shift = shift;
1957 x->a_buf[0] = 0;
1958 glist_grab(x->a_glist, &x->a_text.te_g, gatom_motion, gatom_key,
1959 xpos, ypos);
1963 /* message back from dialog window */
1964 static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv)
1966 t_float width = atom_getfloatarg(0, argc, argv);
1967 t_float draglo = atom_getfloatarg(1, argc, argv);
1968 t_float draghi = atom_getfloatarg(2, argc, argv);
1969 t_symbol *label = gatom_unescapit(atom_getsymbolarg(3, argc, argv));
1970 t_float wherelabel = atom_getfloatarg(4, argc, argv);
1971 t_symbol *symfrom = gatom_unescapit(atom_getsymbolarg(5, argc, argv));
1972 t_symbol *symto = gatom_unescapit(atom_getsymbolarg(6, argc, argv));
1974 gobj_vis(&x->a_text.te_g, x->a_glist, 0);
1975 if (!*symfrom->s_name && *x->a_symfrom->s_name)
1976 inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
1977 else if (*symfrom->s_name && !*x->a_symfrom->s_name && x->a_text.te_inlet)
1979 canvas_deletelinesforio(x->a_glist, &x->a_text,
1980 x->a_text.te_inlet, 0);
1981 inlet_free(x->a_text.te_inlet);
1983 if (!*symto->s_name && *x->a_symto->s_name)
1984 outlet_new(&x->a_text, 0);
1985 else if (*symto->s_name && !*x->a_symto->s_name && x->a_text.te_outlet)
1987 canvas_deletelinesforio(x->a_glist, &x->a_text,
1988 0, x->a_text.te_outlet);
1989 outlet_free(x->a_text.te_outlet);
1991 if (draglo >= draghi)
1992 draglo = draghi = 0;
1993 x->a_draglo = draglo;
1994 x->a_draghi = draghi;
1995 if (width < 0)
1996 width = 4;
1997 else if (width > 80)
1998 width = 80;
1999 x->a_text.te_width = width;
2000 x->a_wherelabel = ((int)wherelabel & 3);
2001 x->a_label = label;
2002 if (*x->a_symfrom->s_name)
2003 pd_unbind(&x->a_text.te_pd,
2004 canvas_realizedollar(x->a_glist, x->a_symfrom));
2005 x->a_symfrom = symfrom;
2006 if (*x->a_symfrom->s_name)
2007 pd_bind(&x->a_text.te_pd,
2008 canvas_realizedollar(x->a_glist, x->a_symfrom));
2009 x->a_symto = symto;
2010 x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto);
2011 gobj_vis(&x->a_text.te_g, x->a_glist, 1);
2013 /* glist_retext(x->a_glist, &x->a_text); */
2016 /* ---------------- gatom-specific widget functions --------------- */
2017 static void gatom_getwherelabel(t_gatom *x, t_glist *glist, int *xp, int *yp)
2019 int x1, y1, x2, y2, width, height;
2020 text_getrect(&x->a_text.te_g, glist, &x1, &y1, &x2, &y2);
2021 width = x2 - x1;
2022 height = y2 - y1;
2023 if (x->a_wherelabel == ATOM_LABELLEFT)
2025 *xp = x1 - 3 -
2026 strlen(canvas_realizedollar(x->a_glist, x->a_label)->s_name) *
2027 sys_fontwidth(glist_getfont(glist));
2028 *yp = y1 + 2;
2030 else if (x->a_wherelabel == ATOM_LABELRIGHT)
2032 *xp = x2 + 2;
2033 *yp = y1 + 2;
2035 else if (x->a_wherelabel == ATOM_LABELUP)
2037 *xp = x1 - 1;
2038 *yp = y1 - 1 - sys_fontheight(glist_getfont(glist));;
2040 else
2042 *xp = x1 - 1;
2043 *yp = y2 + 3;
2047 static void gatom_displace(t_gobj *z, t_glist *glist,
2048 int dx, int dy)
2050 t_gatom *x = (t_gatom*)z;
2051 text_displace(z, glist, dx, dy);
2052 sys_vgui(".x%x.c move %x.l %d %d\n", glist_getcanvas(glist),
2053 x, dx, dy);
2056 static void gatom_vis(t_gobj *z, t_glist *glist, int vis)
2058 t_gatom *x = (t_gatom*)z;
2059 text_vis(z, glist, vis);
2060 if (*x->a_label->s_name)
2062 if (vis)
2064 int x1, y1;
2065 gatom_getwherelabel(x, glist, &x1, &y1);
2066 sys_vgui("pdtk_text_new .x%x.c %x.l %f %f {%s} %d %s\n",
2067 glist_getcanvas(glist), x,
2068 (double)x1, (double)y1,
2069 canvas_realizedollar(x->a_glist, x->a_label)->s_name,
2070 sys_hostfontsize(glist_getfont(glist)),
2071 "black");
2073 else sys_vgui(".x%x.c delete %x.l\n", glist_getcanvas(glist), x);
2077 void canvas_atom(t_glist *gl, t_atomtype type,
2078 t_symbol *s, int argc, t_atom *argv)
2080 t_gatom *x = (t_gatom *)pd_new(gatom_class);
2081 t_atom at;
2082 x->a_text.te_width = 0; /* don't know it yet. */
2083 x->a_text.te_type = T_ATOM;
2084 x->a_text.te_binbuf = binbuf_new();
2085 x->a_glist = gl;
2086 x->a_atom.a_type = type;
2087 x->a_toggle = 1;
2088 x->a_draglo = 0;
2089 x->a_draghi = 0;
2090 x->a_wherelabel = 0;
2091 x->a_label = &s_;
2092 x->a_symfrom = &s_;
2093 x->a_symto = x->a_expanded_to = &s_;
2094 if (type == A_FLOAT)
2096 x->a_atom.a_w.w_float = 0;
2097 x->a_text.te_width = 5;
2098 SETFLOAT(&at, 0);
2100 else
2102 x->a_atom.a_w.w_symbol = &s_symbol;
2103 x->a_text.te_width = 10;
2104 SETSYMBOL(&at, &s_symbol);
2106 binbuf_add(x->a_text.te_binbuf, 1, &at);
2107 if (argc > 1)
2108 /* create from file. x, y, width, low-range, high-range, flags,
2109 label, receive-name, send-name */
2111 x->a_text.te_xpix = atom_getfloatarg(0, argc, argv);
2112 x->a_text.te_ypix = atom_getfloatarg(1, argc, argv);
2113 x->a_text.te_width = atom_getintarg(2, argc, argv);
2114 /* sanity check because some very old patches have trash in this
2115 field... remove this in 2003 or so: */
2116 if (x->a_text.te_width < 0 || x->a_text.te_width > 500)
2117 x->a_text.te_width = 4;
2118 x->a_draglo = atom_getfloatarg(3, argc, argv);
2119 x->a_draghi = atom_getfloatarg(4, argc, argv);
2120 x->a_wherelabel = (((int)atom_getfloatarg(5, argc, argv)) & 3);
2121 x->a_label = gatom_unescapit(atom_getsymbolarg(6, argc, argv));
2122 x->a_symfrom = gatom_unescapit(atom_getsymbolarg(7, argc, argv));
2123 if (*x->a_symfrom->s_name)
2124 pd_bind(&x->a_text.te_pd,
2125 canvas_realizedollar(x->a_glist, x->a_symfrom));
2127 x->a_symto = gatom_unescapit(atom_getsymbolarg(8, argc, argv));
2128 x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto);
2129 if (x->a_symto == &s_)
2130 outlet_new(&x->a_text,
2131 x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol);
2132 if (x->a_symfrom == &s_)
2133 inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
2134 glist_add(gl, &x->a_text.te_g);
2136 else
2138 int xpix, ypix;
2139 outlet_new(&x->a_text,
2140 x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol);
2141 inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
2142 pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
2143 glist_noselect(gl);
2144 glist_getnextxy(gl, &xpix, &ypix);
2145 x->a_text.te_xpix = xpix;
2146 x->a_text.te_ypix = ypix;
2147 glist_add(gl, &x->a_text.te_g);
2148 glist_noselect(gl);
2149 glist_select(gl, &x->a_text.te_g);
2150 canvas_startmotion(glist_getcanvas(gl));
2154 void canvas_floatatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
2156 canvas_atom(gl, A_FLOAT, s, argc, argv);
2159 void canvas_symbolatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
2161 canvas_atom(gl, A_SYMBOL, s, argc, argv);
2164 static void gatom_free(t_gatom *x)
2166 if (*x->a_symfrom->s_name)
2167 pd_unbind(&x->a_text.te_pd,
2168 canvas_realizedollar(x->a_glist, x->a_symfrom));
2169 gfxstub_deleteforkey(x);
2172 static void gatom_properties(t_gobj *z, t_glist *owner)
2174 t_gatom *x = (t_gatom *)z;
2175 char buf[200];
2176 sprintf(buf, "pdtk_gatom_dialog %%s %d %g %g %d %s %s %s\n",
2177 x->a_text.te_width, x->a_draglo, x->a_draghi,
2178 x->a_wherelabel, gatom_escapit(x->a_label)->s_name,
2179 gatom_escapit(x->a_symfrom)->s_name,
2180 gatom_escapit(x->a_symto)->s_name);
2181 gfxstub_new(&x->a_text.te_pd, x, buf);
2185 /* -------------------- widget behavior for text objects ------------ */
2187 static void text_getrect(t_gobj *z, t_glist *glist,
2188 int *xp1, int *yp1, int *xp2, int *yp2)
2190 t_text *x = (t_text *)z;
2191 int width, height, iscomment = (x->te_type == T_TEXT);
2192 float x1, y1, x2, y2;
2194 /* for number boxes, we know width and height a priori, and should
2195 report them here so that graphs can get swelled to fit. */
2197 if (x->te_type == T_ATOM && x->te_width > 0)
2199 int font = glist_getfont(glist);
2200 int fontwidth = sys_fontwidth(font), fontheight = sys_fontheight(font);
2201 width = (x->te_width > 0 ? x->te_width : 6) * fontwidth + 2;
2202 height = fontheight + 1; /* borrowed from TMARGIN, etc, in g_rtext.c */
2204 /* if we're invisible we don't know our size so we just lie about
2205 it. This is called on invisible boxes to establish order of inlets
2206 and possibly other reasons.
2207 To find out if the box is visible we can't just check the "vis"
2208 flag because we might be within the vis() routine and not have set
2209 that yet. So we check directly whether the "rtext" list has been
2210 built. LATER reconsider when "vis" flag should be on and off? */
2212 else if (glist->gl_editor && glist->gl_editor->e_rtext)
2214 t_rtext *y = glist_findrtext(glist, x);
2215 width = rtext_width(y);
2216 height = rtext_height(y) - (iscomment << 1);
2218 else width = height = 10;
2219 x1 = text_xpix(x, glist);
2220 y1 = text_ypix(x, glist);
2221 x2 = x1 + width;
2222 y2 = y1 + height;
2223 y1 += iscomment;
2224 *xp1 = x1;
2225 *yp1 = y1;
2226 *xp2 = x2;
2227 *yp2 = y2;
2230 static void text_displace(t_gobj *z, t_glist *glist,
2231 int dx, int dy)
2233 t_text *x = (t_text *)z;
2234 x->te_xpix += dx;
2235 x->te_ypix += dy;
2236 if (glist_isvisible(glist))
2238 t_rtext *y = glist_findrtext(glist, x);
2239 rtext_displace(y, dx, dy);
2240 text_drawborder(x, glist, rtext_gettag(y),
2241 rtext_width(y), rtext_height(y), 0);
2242 canvas_fixlinesfor(glist_getcanvas(glist), x);
2246 static void text_select(t_gobj *z, t_glist *glist, int state)
2248 t_text *x = (t_text *)z;
2249 t_rtext *y = glist_findrtext(glist, x);
2250 rtext_select(y, state);
2251 if (glist_isvisible(glist) && text_shouldvis(x, glist))
2252 sys_vgui(".x%x.c itemconfigure %sR -fill %s\n", glist,
2253 rtext_gettag(y), (state? "blue" : "black"));
2256 static void text_activate(t_gobj *z, t_glist *glist, int state)
2258 t_text *x = (t_text *)z;
2259 t_rtext *y = glist_findrtext(glist, x);
2260 if (z->g_pd != gatom_class) rtext_activate(y, state);
2263 static void text_delete(t_gobj *z, t_glist *glist)
2265 t_text *x = (t_text *)z;
2266 canvas_deletelinesfor(glist, x);
2269 /* return true if the text box should be drawn.
2270 We don't show object boxes inside graphs. */
2271 int text_shouldvis(t_text *x, t_glist *glist)
2273 return (glist->gl_havewindow ||
2274 (x->te_pd != canvas_class && x->te_pd->c_wb != &text_widgetbehavior) ||
2275 (x->te_pd == canvas_class && (((t_glist *)x)->gl_isgraph)));
2278 static void text_vis(t_gobj *z, t_glist *glist, int vis)
2280 t_text *x = (t_text *)z;
2281 if (vis)
2283 if (text_shouldvis(x, glist))
2285 t_rtext *y = glist_findrtext(glist, x);
2286 if (x->te_type == T_ATOM)
2287 glist_retext(glist, x);
2288 text_drawborder(x, glist, rtext_gettag(y),
2289 rtext_width(y), rtext_height(y), 1);
2290 rtext_draw(y);
2293 else
2295 t_rtext *y = glist_findrtext(glist, x);
2296 if (text_shouldvis(x, glist))
2298 text_eraseborder(x, glist, rtext_gettag(y));
2299 rtext_erase(y);
2304 static int text_click(t_gobj *z, struct _glist *glist,
2305 int xpix, int ypix, int shift, int alt, int dbl, int doit)
2307 t_text *x = (t_text *)z;
2308 if (x->te_type == T_OBJECT)
2310 t_symbol *clicksym = gensym("click");
2311 if (zgetfn(&x->te_pd, clicksym))
2313 if (doit)
2314 pd_vmess(&x->te_pd, clicksym, "fffff",
2315 (double)xpix, (double)ypix,
2316 (double)shift, 0, (double)alt);
2317 return (1);
2319 else return (0);
2321 else if (x->te_type == T_ATOM)
2323 if (doit)
2324 gatom_click((t_gatom *)x, (t_floatarg)xpix, (t_floatarg)ypix,
2325 (t_floatarg)shift, 0, (t_floatarg)alt);
2326 return (1);
2328 else if (x->te_type == T_MESSAGE)
2330 if (doit)
2331 message_click((t_message *)x, (t_floatarg)xpix, (t_floatarg)ypix,
2332 (t_floatarg)shift, 0, (t_floatarg)alt);
2333 return (1);
2335 else return (0);
2338 void text_save(t_gobj *z, t_binbuf *b)
2340 t_text *x = (t_text *)z;
2341 if (x->te_type == T_OBJECT)
2343 /* if we have a "saveto" method, and if we don't happen to be
2344 a canvas that's an abstraction, the saveto method does the work */
2345 if (zgetfn(&x->te_pd, gensym("saveto")) &&
2346 !((pd_class(&x->te_pd) == canvas_class) &&
2347 (canvas_isabstraction((t_canvas *)x)
2348 || canvas_istable((t_canvas *)x))))
2350 mess1(&x->te_pd, gensym("saveto"), b);
2351 binbuf_addv(b, "ssii", gensym("#X"), gensym("restore"),
2352 (t_int)x->te_xpix, (t_int)x->te_ypix);
2354 else /* otherwise just save the text */
2356 binbuf_addv(b, "ssii", gensym("#X"), gensym("obj"),
2357 (t_int)x->te_xpix, (t_int)x->te_ypix);
2359 binbuf_addbinbuf(b, x->te_binbuf);
2360 binbuf_addv(b, ";");
2362 else if (x->te_type == T_MESSAGE)
2364 binbuf_addv(b, "ssii", gensym("#X"), gensym("msg"),
2365 (t_int)x->te_xpix, (t_int)x->te_ypix);
2366 binbuf_addbinbuf(b, x->te_binbuf);
2367 binbuf_addv(b, ";");
2369 else if (x->te_type == T_ATOM)
2371 t_atomtype t = ((t_gatom *)x)->a_atom.a_type;
2372 t_symbol *sel = (t == A_SYMBOL ? gensym("symbolatom") :
2373 (t == A_FLOAT ? gensym("floatatom") : gensym("intatom")));
2374 t_symbol *label = gatom_escapit(((t_gatom *)x)->a_label);
2375 t_symbol *symfrom = gatom_escapit(((t_gatom *)x)->a_symfrom);
2376 t_symbol *symto = gatom_escapit(((t_gatom *)x)->a_symto);
2377 binbuf_addv(b, "ssiiifffsss", gensym("#X"), sel,
2378 (t_int)x->te_xpix, (t_int)x->te_ypix, (t_int)x->te_width,
2379 (double)((t_gatom *)x)->a_draglo,
2380 (double)((t_gatom *)x)->a_draghi,
2381 (double)((t_gatom *)x)->a_wherelabel,
2382 label, symfrom, symto);
2383 binbuf_addv(b, ";");
2385 else
2387 binbuf_addv(b, "ssii", gensym("#X"), gensym("text"),
2388 (t_int)x->te_xpix, (t_int)x->te_ypix);
2389 binbuf_addbinbuf(b, x->te_binbuf);
2390 binbuf_addv(b, ";");
2394 /* this one is for everyone but "gatoms"; it's imposed in m_class.c */
2395 t_widgetbehavior text_widgetbehavior =
2397 text_getrect,
2398 text_displace,
2399 text_select,
2400 text_activate,
2401 text_delete,
2402 text_vis,
2403 text_click,
2406 static t_widgetbehavior gatom_widgetbehavior =
2408 text_getrect,
2409 gatom_displace,
2410 text_select,
2411 text_activate,
2412 text_delete,
2413 gatom_vis,
2414 text_click,
2417 /* -------------------- the "text" class ------------ */
2419 #ifdef MACOSX
2420 #define EXTRAPIX 2
2421 #else
2422 #define EXTRAPIX 1
2423 #endif
2425 /* draw inlets and outlets for a text object or for a graph. */
2426 void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
2427 char *tag, int x1, int y1, int x2, int y2)
2429 int n = obj_noutlets(ob), nplus = (n == 1 ? 1 : n-1), i;
2430 int width = x2 - x1;
2431 for (i = 0; i < n; i++)
2433 int onset = x1 + (width - IOWIDTH) * i / nplus;
2434 if (firsttime)
2435 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %so%d\n",
2436 glist_getcanvas(glist),
2437 onset, y2 - 1,
2438 onset + IOWIDTH, y2,
2439 tag, i);
2440 else
2441 sys_vgui(".x%x.c coords %so%d %d %d %d %d\n",
2442 glist_getcanvas(glist), tag, i,
2443 onset, y2 - 1,
2444 onset + IOWIDTH, y2);
2446 n = obj_ninlets(ob);
2447 nplus = (n == 1 ? 1 : n-1);
2448 for (i = 0; i < n; i++)
2450 int onset = x1 + (width - IOWIDTH) * i / nplus;
2451 if (firsttime)
2452 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %si%d\n",
2453 glist_getcanvas(glist),
2454 onset, y1,
2455 onset + IOWIDTH, y1 + EXTRAPIX,
2456 tag, i);
2457 else
2458 sys_vgui(".x%x.c coords %si%d %d %d %d %d\n",
2459 glist_getcanvas(glist), tag, i,
2460 onset, y1,
2461 onset + IOWIDTH, y1 + EXTRAPIX);
2465 void text_drawborder(t_text *x, t_glist *glist,
2466 char *tag, int width2, int height2, int firsttime)
2468 t_object *ob;
2469 int x1, y1, x2, y2, width, height;
2470 text_getrect(&x->te_g, glist, &x1, &y1, &x2, &y2);
2471 width = x2 - x1;
2472 height = y2 - y1;
2473 if (x->te_type == T_OBJECT)
2475 if (firsttime)
2476 sys_vgui(".x%x.c create line\
2477 %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
2478 glist_getcanvas(glist),
2479 x1, y1, x2, y1, x2, y2, x1, y2, x1, y1, tag);
2480 else
2481 sys_vgui(".x%x.c coords %sR\
2482 %d %d %d %d %d %d %d %d %d %d\n",
2483 glist_getcanvas(glist), tag,
2484 x1, y1, x2, y1, x2, y2, x1, y2, x1, y1);
2486 else if (x->te_type == T_MESSAGE)
2488 if (firsttime)
2489 sys_vgui(".x%x.c create line\
2490 %d %d %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
2491 glist_getcanvas(glist),
2492 x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2,
2493 x1, y2, x1, y1,
2494 tag);
2495 else
2496 sys_vgui(".x%x.c coords %sR\
2497 %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
2498 glist_getcanvas(glist), tag,
2499 x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2,
2500 x1, y2, x1, y1);
2502 else if (x->te_type == T_ATOM)
2504 if (firsttime)
2505 sys_vgui(".x%x.c create line\
2506 %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
2507 glist_getcanvas(glist),
2508 x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1,
2509 tag);
2510 else
2511 sys_vgui(".x%x.c coords %sR\
2512 %d %d %d %d %d %d %d %d %d %d %d %d\n",
2513 glist_getcanvas(glist), tag,
2514 x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1);
2516 /* draw inlets/outlets */
2518 if (ob = pd_checkobject(&x->te_pd))
2519 glist_drawiofor(glist, ob, firsttime, tag, x1, y1, x2, y2);
2522 void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag)
2524 int i, n;
2525 n = obj_noutlets(ob);
2526 for (i = 0; i < n; i++)
2527 sys_vgui(".x%x.c delete %so%d\n",
2528 glist_getcanvas(glist), tag, i);
2529 n = obj_ninlets(ob);
2530 for (i = 0; i < n; i++)
2531 sys_vgui(".x%x.c delete %si%d\n",
2532 glist_getcanvas(glist), tag, i);
2535 void text_eraseborder(t_text *x, t_glist *glist, char *tag)
2537 if (x->te_type == T_TEXT) return;
2538 sys_vgui(".x%x.c delete %sR\n",
2539 glist_getcanvas(glist), tag);
2540 glist_eraseiofor(glist, x, tag);
2543 /* change text; if T_OBJECT, remake it. LATER we'll have an undo buffer
2544 which should be filled in here before making the change. */
2546 void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize)
2548 if (x->te_type == T_OBJECT)
2550 t_binbuf *b = binbuf_new();
2551 int natom1, natom2;
2552 t_atom *vec1, *vec2;
2553 binbuf_text(b, buf, bufsize);
2554 natom1 = binbuf_getnatom(x->te_binbuf);
2555 vec1 = binbuf_getvec(x->te_binbuf);
2556 natom2 = binbuf_getnatom(b);
2557 vec2 = binbuf_getvec(b);
2558 /* special case: if pd args change just pass the message on. */
2559 if (natom1 >= 1 && natom2 >= 1 && vec1[0].a_type == A_SYMBOL
2560 && !strcmp(vec1[0].a_w.w_symbol->s_name, "pd") &&
2561 vec2[0].a_type == A_SYMBOL
2562 && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd"))
2564 typedmess(&x->te_pd, gensym("rename"), natom2-1, vec2+1);
2565 binbuf_free(x->te_binbuf);
2566 x->te_binbuf = b;
2568 else /* normally, just destroy the old one and make a new one. */
2570 int xwas = x->te_xpix, ywas = x->te_ypix;
2571 glist_delete(glist, &x->te_g);
2572 canvas_objtext(glist, xwas, ywas, 0, b);
2573 /* if it's an abstraction loadbang it here */
2574 if (newest && pd_class(newest) == canvas_class)
2575 canvas_loadbang((t_canvas *)newest);
2576 canvas_restoreconnections(glist_getcanvas(glist));
2578 /* if we made a new "pd" or changed a window name,
2579 update window list */
2580 if (natom2 >= 1 && vec2[0].a_type == A_SYMBOL
2581 && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd"))
2582 canvas_updatewindowlist();
2584 else binbuf_text(x->te_binbuf, buf, bufsize);
2587 void g_text_setup(void)
2589 text_class = class_new(gensym("text"), 0, 0, sizeof(t_text),
2590 CLASS_NOINLET | CLASS_PATCHABLE, 0);
2592 message_class = class_new(gensym("message"), 0, (t_method)message_free,
2593 sizeof(t_message), CLASS_PATCHABLE, 0);
2594 class_addbang(message_class, message_bang);
2595 class_addfloat(message_class, message_float);
2596 class_addsymbol(message_class, message_symbol);
2597 class_addlist(message_class, message_list);
2598 class_addanything(message_class, message_list);
2600 class_addmethod(message_class, (t_method)message_click, gensym("click"),
2601 A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
2602 class_addmethod(message_class, (t_method)message_set, gensym("set"),
2603 A_GIMME, 0);
2604 class_addmethod(message_class, (t_method)message_add, gensym("add"),
2605 A_GIMME, 0);
2606 class_addmethod(message_class, (t_method)message_add2, gensym("add2"),
2607 A_GIMME, 0);
2609 messresponder_class = class_new(gensym("messresponder"), 0, 0,
2610 sizeof(t_text), CLASS_PD, 0);
2611 class_addbang(messresponder_class, messresponder_bang);
2612 class_addfloat(messresponder_class, (t_method) messresponder_float);
2613 class_addsymbol(messresponder_class, messresponder_symbol);
2614 class_addlist(messresponder_class, messresponder_list);
2615 class_addanything(messresponder_class, messresponder_anything);
2617 gatom_class = class_new(gensym("gatom"), 0, (t_method)gatom_free,
2618 sizeof(t_gatom), CLASS_NOINLET | CLASS_PATCHABLE, 0);
2619 class_addbang(gatom_class, gatom_bang);
2620 class_addfloat(gatom_class, gatom_float);
2621 class_addsymbol(gatom_class, gatom_symbol);
2622 class_addmethod(gatom_class, (t_method)gatom_set, gensym("set"),
2623 A_GIMME, 0);
2624 class_addmethod(gatom_class, (t_method)gatom_click, gensym("click"),
2625 A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
2626 class_addmethod(gatom_class, (t_method)gatom_param, gensym("param"),
2627 A_GIMME, 0);
2628 class_setwidget(gatom_class, &gatom_widgetbehavior);
2629 class_setpropertiesfn(gatom_class, gatom_properties);