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 */
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
,
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
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
);
42 x
->te_width
= 0; /* don't know it yet. */
44 x
->te_binbuf
= binbuf_new();
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);
52 SETSYMBOL(&at
, gensym("comment"));
53 binbuf_restore(x
->te_binbuf
, 1, &at
);
55 glist_add(gl
, &x
->te_g
);
60 pd_vmess((t_pd
*)glist_getcanvas(gl
), gensym("editmode"), "i", 1);
61 SETSYMBOL(&at
, gensym("comment"));
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
);
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
75 /* gobj_activate(&x->te_g, gl, 1); */
76 canvas_startmotion(glist_getcanvas(gl
));
80 /* ----------------- the "object" object. ------------------ */
83 void canvas_getargs(int *argcp
, t_atom
**argvp
);
85 static void canvas_objtext(t_glist
*gl
, int xpix
, int ypix
, int selected
,
92 canvas_setcurrent((t_canvas
*)gl
);
93 canvas_getargs(&argc
, &argv
);
94 binbuf_eval(b
, &pd_objectmaker
, argc
, argv
);
95 if (binbuf_getnatom(b
))
100 post("... couldn't create");
103 else if (!(x
= pd_checkobject(newest
)))
106 post("... didn't return a patchable object");
113 /* LATER make the color reflect this */
114 x
= (t_text
*)pd_new(text_class
);
120 x
->te_type
= T_OBJECT
;
121 glist_add(gl
, &x
->te_g
);
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
)
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
);
151 t_binbuf
*b
= binbuf_new();
153 pd_vmess(&gl
->gl_pd
, gensym("editmode"), "i", 1);
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. */
164 void canvas_iemguis(t_glist
*gl
, t_symbol
*guiobjname
)
167 t_binbuf
*b
= binbuf_new();
170 pd_vmess(&gl
->gl_pd
, gensym("editmode"), "i", 1);
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"));
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
255 typedef struct _message
258 t_messresponder m_messresponder
;
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
)
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
)
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
)
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();
374 x
->m_clock
= clock_new(x
, (t_method
)message_tick
);
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
);
385 pd_vmess(&gl
->gl_pd
, gensym("editmode"), "i", 1);
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
);
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
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 */
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
427 static t_symbol
*gatom_escapit(t_symbol
*s
)
430 return (gensym("-"));
431 else if (*s
->s_name
== '-')
435 strncpy(shmo
+1, s
->s_name
, 99);
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
));
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
));
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
);
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
;
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
);
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
)
491 "%s: atom with same send/receive name (infinite loop)",
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
)
504 "%s: atom with same send/receive name (infinite loop)",
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
)
515 gatom_set(x
, 0, 1, &at
);
519 static void gatom_clipfloat(t_gatom
*x
, t_float f
)
521 if (x
->a_draglo
!= 0 || x
->a_draghi
!= 0)
531 static void gatom_symbol(t_gatom
*x
, t_symbol
*s
)
535 gatom_set(x
, 0, 1, &at
);
539 static void gatom_motion(void *z
, t_floatarg dx
, t_floatarg dy
)
541 t_gatom
*x
= (t_gatom
*)z
;
543 if (x
->a_atom
.a_type
== A_FLOAT
)
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
);
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
;
568 int len
= strlen(x
->a_buf
);
570 char sbuf
[ATOMBUFSIZE
+ 4];
573 /* we're being notified that no more keys will come for this grab */
578 else if (c
== ' ') return;
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");
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'))
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
,
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));
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
;
638 else gatom_float(x
, x
->a_toggle
);
642 glist_grab(x
->a_glist
, &x
->a_text
.te_g
, gatom_motion
, gatom_key
,
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
)
677 x
->a_draglo
= draglo
;
678 x
->a_draghi
= draghi
;
683 x
->a_text
.te_width
= width
;
684 x
->a_wherelabel
= ((int)wherelabel
& 3);
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
));
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
);
707 if (x
->a_wherelabel
== ATOM_LABELLEFT
)
710 strlen(canvas_realizedollar(x
->a_glist
, x
->a_label
)->s_name
) *
711 sys_fontwidth(glist_getfont(glist
));
714 else if (x
->a_wherelabel
== ATOM_LABELRIGHT
)
719 else if (x
->a_wherelabel
== ATOM_LABELUP
)
722 *yp
= y1
- 1 - sys_fontheight(glist_getfont(glist
));;
731 static void gatom_displace(t_gobj
*z
, t_glist
*glist
,
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
),
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
)
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
)),
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
);
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();
770 x
->a_atom
.a_type
= type
;
777 x
->a_symto
= x
->a_expanded_to
= &s_
;
780 x
->a_atom
.a_w
.w_float
= 0;
781 x
->a_text
.te_width
= 5;
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
);
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
);
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);
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
);
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
;
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
);
914 static void text_displace(t_gobj
*z
, t_glist
*glist
,
917 t_text
*x
= (t_text
*)z
;
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
;
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);
979 t_rtext
*y
= glist_findrtext(glist
, x
);
980 if (text_shouldvis(x
, glist
))
982 text_eraseborder(x
, glist
, rtext_gettag(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
))
998 pd_vmess(&x
->te_pd
, clicksym
, "fffff",
999 (double)xpix
, (double)ypix
,
1000 (double)shift
, 0, (double)alt
);
1005 else if (x
->te_type
== T_ATOM
)
1008 gatom_click((t_gatom
*)x
, (t_floatarg
)xpix
, (t_floatarg
)ypix
,
1009 (t_floatarg
)shift
, 0, (t_floatarg
)alt
);
1012 else if (x
->te_type
== T_MESSAGE
)
1015 message_click((t_message
*)x
, (t_floatarg
)xpix
, (t_floatarg
)ypix
,
1016 (t_floatarg
)shift
, 0, (t_floatarg
)alt
);
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
, ";");
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
=
1090 static t_widgetbehavior gatom_widgetbehavior
=
1101 /* -------------------- the "text" class ------------ */
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
;
1119 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %so%d\n",
1120 glist_getcanvas(glist
),
1122 onset
+ IOWIDTH
, y2
,
1125 sys_vgui(".x%x.c coords %so%d %d %d %d %d\n",
1126 glist_getcanvas(glist
), tag
, i
,
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
;
1136 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %si%d\n",
1137 glist_getcanvas(glist
),
1139 onset
+ IOWIDTH
, y1
+ EXTRAPIX
,
1142 sys_vgui(".x%x.c coords %si%d %d %d %d %d\n",
1143 glist_getcanvas(glist
), tag
, i
,
1145 onset
+ IOWIDTH
, y1
+ EXTRAPIX
);
1149 void text_drawborder(t_text
*x
, t_glist
*glist
,
1150 char *tag
, int width2
, int height2
, int firsttime
)
1153 int x1
, y1
, x2
, y2
, width
, height
;
1154 text_getrect(&x
->te_g
, glist
, &x1
, &y1
, &x2
, &y2
);
1157 if (x
->te_type
== T_OBJECT
)
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
);
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
)
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
,
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
,
1186 else if (x
->te_type
== T_ATOM
)
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
,
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
)
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();
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
);
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"),
1288 class_addmethod(message_class
, (t_method
)message_add
, gensym("add"),
1290 class_addmethod(message_class
, (t_method
)message_add2
, gensym("add2"),
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"),
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"),
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 */
1328 #include "s_stuff.h"
1330 #include "g_canvas.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
,
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
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
);
1358 x
->te_width
= 0; /* don't know it yet. */
1359 x
->te_type
= T_TEXT
;
1360 x
->te_binbuf
= binbuf_new();
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);
1368 SETSYMBOL(&at
, gensym("comment"));
1369 binbuf_restore(x
->te_binbuf
, 1, &at
);
1371 glist_add(gl
, &x
->te_g
);
1376 pd_vmess((t_pd
*)glist_getcanvas(gl
), gensym("editmode"), "i", 1);
1377 SETSYMBOL(&at
, gensym("comment"));
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
);
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
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
,
1408 canvas_setcurrent((t_canvas
*)gl
);
1409 canvas_getargs(&argc
, &argv
);
1410 binbuf_eval(b
, &pd_objectmaker
, argc
, argv
);
1411 if (binbuf_getnatom(b
))
1416 post("... couldn't create");
1419 else if (!(x
= pd_checkobject(newest
)))
1422 post("... didn't return a patchable object");
1429 /* LATER make the color reflect this */
1430 x
= (t_text
*)pd_new(text_class
);
1436 x
->te_type
= T_OBJECT
;
1437 glist_add(gl
, &x
->te_g
);
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
)
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
);
1467 t_binbuf
*b
= binbuf_new();
1469 pd_vmess(&gl
->gl_pd
, gensym("editmode"), "i", 1);
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. */
1480 void canvas_iemguis(t_glist
*gl
, t_symbol
*guiobjname
)
1483 t_binbuf
*b
= binbuf_new();
1486 pd_vmess(&gl
->gl_pd
, gensym("editmode"), "i", 1);
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"));
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
1568 t_outlet
*mr_outlet
;
1571 typedef struct _message
1574 t_messresponder m_messresponder
;
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
)
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
)
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();
1690 x
->m_clock
= clock_new(x
, (t_method
)message_tick
);
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
);
1701 pd_vmess(&gl
->gl_pd
, gensym("editmode"), "i", 1);
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
);
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
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 */
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
1743 static t_symbol
*gatom_escapit(t_symbol
*s
)
1746 return (gensym("-"));
1747 else if (*s
->s_name
== '-')
1751 strncpy(shmo
+1, s
->s_name
, 99);
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
));
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
));
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
);
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
;
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
);
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
)
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
)
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
)
1831 gatom_set(x
, 0, 1, &at
);
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
)
1841 if (f
> x
->a_draghi
)
1847 static void gatom_symbol(t_gatom
*x
, t_symbol
*s
)
1851 gatom_set(x
, 0, 1, &at
);
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
)
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
);
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
;
1884 int len
= strlen(x
->a_buf
);
1886 char sbuf
[ATOMBUFSIZE
+ 4];
1889 /* we're being notified that no more keys will come for this grab */
1894 else if (c
== ' ') return;
1898 x
->a_buf
[len
-1] = 0;
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");
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'))
1920 x
->a_buf
[len
+1] = 0;
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
,
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));
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
;
1954 else gatom_float(x
, x
->a_toggle
);
1958 glist_grab(x
->a_glist
, &x
->a_text
.te_g
, gatom_motion
, gatom_key
,
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
;
1997 else if (width
> 80)
1999 x
->a_text
.te_width
= width
;
2000 x
->a_wherelabel
= ((int)wherelabel
& 3);
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
));
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
);
2023 if (x
->a_wherelabel
== ATOM_LABELLEFT
)
2026 strlen(canvas_realizedollar(x
->a_glist
, x
->a_label
)->s_name
) *
2027 sys_fontwidth(glist_getfont(glist
));
2030 else if (x
->a_wherelabel
== ATOM_LABELRIGHT
)
2035 else if (x
->a_wherelabel
== ATOM_LABELUP
)
2038 *yp
= y1
- 1 - sys_fontheight(glist_getfont(glist
));;
2047 static void gatom_displace(t_gobj
*z
, t_glist
*glist
,
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
),
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
)
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
)),
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
);
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();
2086 x
->a_atom
.a_type
= type
;
2090 x
->a_wherelabel
= 0;
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;
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
);
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
);
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);
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
);
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
;
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
);
2230 static void text_displace(t_gobj
*z
, t_glist
*glist
,
2233 t_text
*x
= (t_text
*)z
;
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
;
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);
2295 t_rtext
*y
= glist_findrtext(glist
, x
);
2296 if (text_shouldvis(x
, glist
))
2298 text_eraseborder(x
, glist
, rtext_gettag(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
))
2314 pd_vmess(&x
->te_pd
, clicksym
, "fffff",
2315 (double)xpix
, (double)ypix
,
2316 (double)shift
, 0, (double)alt
);
2321 else if (x
->te_type
== T_ATOM
)
2324 gatom_click((t_gatom
*)x
, (t_floatarg
)xpix
, (t_floatarg
)ypix
,
2325 (t_floatarg
)shift
, 0, (t_floatarg
)alt
);
2328 else if (x
->te_type
== T_MESSAGE
)
2331 message_click((t_message
*)x
, (t_floatarg
)xpix
, (t_floatarg
)ypix
,
2332 (t_floatarg
)shift
, 0, (t_floatarg
)alt
);
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
, ";");
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
=
2406 static t_widgetbehavior gatom_widgetbehavior
=
2417 /* -------------------- the "text" class ------------ */
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
;
2435 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %so%d\n",
2436 glist_getcanvas(glist
),
2438 onset
+ IOWIDTH
, y2
,
2441 sys_vgui(".x%x.c coords %so%d %d %d %d %d\n",
2442 glist_getcanvas(glist
), tag
, i
,
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
;
2452 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %si%d\n",
2453 glist_getcanvas(glist
),
2455 onset
+ IOWIDTH
, y1
+ EXTRAPIX
,
2458 sys_vgui(".x%x.c coords %si%d %d %d %d %d\n",
2459 glist_getcanvas(glist
), tag
, i
,
2461 onset
+ IOWIDTH
, y1
+ EXTRAPIX
);
2465 void text_drawborder(t_text
*x
, t_glist
*glist
,
2466 char *tag
, int width2
, int height2
, int firsttime
)
2469 int x1
, y1
, x2
, y2
, width
, height
;
2470 text_getrect(&x
->te_g
, glist
, &x1
, &y1
, &x2
, &y2
);
2473 if (x
->te_type
== T_OBJECT
)
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
);
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
)
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
,
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
,
2502 else if (x
->te_type
== T_ATOM
)
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
,
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
)
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();
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
);
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"),
2604 class_addmethod(message_class
, (t_method
)message_add
, gensym("add"),
2606 class_addmethod(message_class
, (t_method
)message_add2
, gensym("add2"),
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"),
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"),
2628 class_setwidget(gatom_class
, &gatom_widgetbehavior
);
2629 class_setpropertiesfn(gatom_class
, gatom_properties
);