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 */
17 #include "../../pdbox.h"
25 static t_class
*text_class
;
26 static t_class
*message_class
;
27 static t_class
*gatom_class
;
28 static void text_vis(t_gobj
*z
, t_glist
*glist
, int vis
);
29 static void text_displace(t_gobj
*z
, t_glist
*glist
,
31 static void text_getrect(t_gobj
*z
, t_glist
*glist
,
32 int *xp1
, int *yp1
, int *xp2
, int *yp2
);
34 void canvas_startmotion(t_canvas
*x
);
35 t_widgetbehavior text_widgetbehavior
;
37 /* ----------------- the "text" object. ------------------ */
39 /* add a "text" object (comment) to a glist. While this one goes for any glist,
40 the other 3 below are for canvases only. (why?) This is called
41 without args if invoked from the GUI; otherwise at least x and y
44 void glist_text(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
46 t_text
*x
= (t_text
*)pd_new(text_class
);
53 x
->te_width
= 0; /* don't know it yet. */
55 x
->te_binbuf
= binbuf_new();
58 x
->te_xpix
= atom_getfloatarg(0, argc
, argv
);
59 x
->te_ypix
= atom_getfloatarg(1, argc
, argv
);
60 if (argc
> 2) binbuf_restore(x
->te_binbuf
, argc
-2, argv
+2);
63 SETSYMBOL(&at
, gensym("comment"));
64 binbuf_restore(x
->te_binbuf
, 1, &at
);
66 glist_add(gl
, &x
->te_g
);
71 pd_vmess((t_pd
*)glist_getcanvas(gl
), gensym("editmode"), "i", 1);
72 SETSYMBOL(&at
, gensym("comment"));
74 glist_getnextxy(gl
, &xpix
, &ypix
);
75 x
->te_xpix
= glist_pixelstox(gl
, xpix
-3);
76 x
->te_ypix
= glist_pixelstoy(gl
, ypix
-3);
77 binbuf_restore(x
->te_binbuf
, 1, &at
);
78 glist_add(gl
, &x
->te_g
);
80 glist_select(gl
, &x
->te_g
);
81 /* it would be nice to "activate" here, but then the second,
82 "put-me-down" click changes the text selection, which is quite
83 irritating, so I took this back out. It's OK in messages
84 and objects though since there's no text in them at menu
86 /* gobj_activate(&x->te_g, gl, 1); */
87 canvas_startmotion(glist_getcanvas(gl
));
91 /* ----------------- the "object" object. ------------------ */
94 void canvas_getargs(int *argcp
, t_atom
**argvp
);
96 static void canvas_objtext(t_glist
*gl
, int xpix
, int ypix
, int selected
,
103 canvas_setcurrent((t_canvas
*)gl
);
104 canvas_getargs(&argc
, &argv
);
105 binbuf_eval(b
, &pd_objectmaker
, argc
, argv
);
106 if (binbuf_getnatom(b
))
111 post("... couldn't create");
114 else if (!(x
= pd_checkobject(newest
)))
117 post("... didn't return a patchable object");
124 /* LATER make the color reflect this */
125 x
= (t_text
*)pd_new(text_class
);
131 x
->te_type
= T_OBJECT
;
132 glist_add(gl
, &x
->te_g
);
135 /* this is called if we've been created from the menu. */
136 glist_select(gl
, &x
->te_g
);
137 gobj_activate(&x
->te_g
, gl
, 1);
139 if (pd_class(&x
->ob_pd
) == vinlet_class
)
140 canvas_resortinlets(glist_getcanvas(gl
));
141 if (pd_class(&x
->ob_pd
) == voutlet_class
)
142 canvas_resortoutlets(glist_getcanvas(gl
));
143 canvas_unsetcurrent((t_canvas
*)gl
);
146 /* object creation routine. These are called without any arguments if
147 they're invoked from the
148 gui; when pasting or restoring from a file, we get at least x and y. */
150 void canvas_obj(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
160 t_binbuf
*b
= binbuf_new();
161 binbuf_restore(b
, argc
-2, argv
+2);
162 canvas_objtext(gl
, atom_getintarg(0, argc
, argv
),
163 atom_getintarg(1, argc
, argv
), 0, b
);
167 t_binbuf
*b
= binbuf_new();
169 pd_vmess(&gl
->gl_pd
, gensym("editmode"), "i", 1);
171 glist_getnextxy(gl
, &xpix
, &ypix
);
172 canvas_objtext(gl
, xpix
, ypix
, 1, b
);
173 canvas_startmotion(glist_getcanvas(gl
));
177 /* make an object box for an object that's already there. */
180 void canvas_iemguis(t_glist
*gl
, t_symbol
*guiobjname
)
183 t_binbuf
*b
= binbuf_new();
186 pd_vmess(&gl
->gl_pd
, gensym("editmode"), "i", 1);
188 SETSYMBOL(&at
, guiobjname
);
189 binbuf_restore(b
, 1, &at
);
190 glist_getnextxy(gl
, &xpix
, &ypix
);
191 canvas_objtext(gl
, xpix
, ypix
, 1, b
);
192 canvas_startmotion(glist_getcanvas(gl
));
195 void canvas_bng(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
202 canvas_iemguis(gl
, gensym("bng"));
205 void canvas_toggle(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
212 canvas_iemguis(gl
, gensym("tgl"));
215 void canvas_vslider(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
222 canvas_iemguis(gl
, gensym("vsl"));
225 void canvas_hslider(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
232 canvas_iemguis(gl
, gensym("hsl"));
235 void canvas_hdial(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
242 canvas_iemguis(gl
, gensym("hdl"));
245 void canvas_vdial(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
252 canvas_iemguis(gl
, gensym("vdl"));
255 void canvas_hradio(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
262 canvas_iemguis(gl
, gensym("hradio"));
265 void canvas_vradio(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
272 canvas_iemguis(gl
, gensym("vradio"));
275 void canvas_vumeter(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
282 canvas_iemguis(gl
, gensym("vu"));
285 void canvas_mycnv(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
292 canvas_iemguis(gl
, gensym("cnv"));
295 void canvas_numbox(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
302 canvas_iemguis(gl
, gensym("nbx"));
307 void canvas_objfor(t_glist
*gl
, t_text
*x
, int argc
, t_atom
*argv
)
309 x
->te_width
= 0; /* don't know it yet. */
310 x
->te_type
= T_OBJECT
;
311 x
->te_binbuf
= binbuf_new();
312 x
->te_xpix
= atom_getfloatarg(0, argc
, argv
);
313 x
->te_ypix
= atom_getfloatarg(1, argc
, argv
);
314 if (argc
> 2) binbuf_restore(x
->te_binbuf
, argc
-2, argv
+2);
315 glist_add(gl
, &x
->te_g
);
318 /* ---------------------- the "message" text item ------------------------ */
320 typedef struct _messresponder
326 typedef struct _message
329 t_messresponder m_messresponder
;
334 static t_class
*message_class
, *messresponder_class
;
336 static void messresponder_bang(t_messresponder
*x
)
338 outlet_bang(x
->mr_outlet
);
341 static void messresponder_float(t_messresponder
*x
, t_float f
)
343 outlet_float(x
->mr_outlet
, f
);
346 static void messresponder_symbol(t_messresponder
*x
, t_symbol
*s
)
348 outlet_symbol(x
->mr_outlet
, s
);
351 static void messresponder_list(t_messresponder
*x
,
352 t_symbol
*s
, int argc
, t_atom
*argv
)
354 outlet_list(x
->mr_outlet
, s
, argc
, argv
);
357 static void messresponder_anything(t_messresponder
*x
,
358 t_symbol
*s
, int argc
, t_atom
*argv
)
360 outlet_anything(x
->mr_outlet
, s
, argc
, argv
);
363 static void message_bang(t_message
*x
)
365 binbuf_eval(x
->m_text
.te_binbuf
, &x
->m_messresponder
.mr_pd
, 0, 0);
368 static void message_float(t_message
*x
, t_float f
)
372 binbuf_eval(x
->m_text
.te_binbuf
, &x
->m_messresponder
.mr_pd
, 1, &at
);
375 static void message_symbol(t_message
*x
, t_symbol
*s
)
379 binbuf_eval(x
->m_text
.te_binbuf
, &x
->m_messresponder
.mr_pd
, 1, &at
);
382 static void message_list(t_message
*x
, t_symbol
*s
, int argc
, t_atom
*argv
)
387 binbuf_eval(x
->m_text
.te_binbuf
, &x
->m_messresponder
.mr_pd
, argc
, argv
);
390 static void message_set(t_message
*x
, t_symbol
*s
, int argc
, t_atom
*argv
)
395 binbuf_clear(x
->m_text
.te_binbuf
);
396 binbuf_add(x
->m_text
.te_binbuf
, argc
, argv
);
397 glist_retext(x
->m_glist
, &x
->m_text
);
400 static void message_add2(t_message
*x
, t_symbol
*s
, int argc
, t_atom
*argv
)
405 binbuf_add(x
->m_text
.te_binbuf
, argc
, argv
);
406 glist_retext(x
->m_glist
, &x
->m_text
);
409 static void message_add(t_message
*x
, t_symbol
*s
, int argc
, t_atom
*argv
)
414 binbuf_add(x
->m_text
.te_binbuf
, argc
, argv
);
415 binbuf_addsemi(x
->m_text
.te_binbuf
);
416 glist_retext(x
->m_glist
, &x
->m_text
);
419 static void message_click(t_message
*x
,
420 t_floatarg xpos
, t_floatarg ypos
, t_floatarg shift
,
421 t_floatarg ctrl
, t_floatarg alt
)
431 if (glist_isvisible(x
->m_glist
))
434 t_rtext
*y
= glist_findrtext(x
->m_glist
, &x
->m_text
);
435 sys_vgui(".x%x.c itemconfigure %sR -width 5\n",
436 glist_getcanvas(x
->m_glist
), rtext_gettag(y
));
438 clock_delay(x
->m_clock
, 120);
442 static void message_tick(t_message
*x
)
444 if (glist_isvisible(x
->m_glist
))
447 t_rtext
*y
= glist_findrtext(x
->m_glist
, &x
->m_text
);
448 sys_vgui(".x%x.c itemconfigure %sR -width 1\n",
449 glist_getcanvas(x
->m_glist
), rtext_gettag(y
));
454 static void message_free(t_message
*x
)
456 clock_free(x
->m_clock
);
459 void canvas_msg(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
464 t_message
*x
= (t_message
*)pd_new(message_class
);
465 x
->m_messresponder
.mr_pd
= messresponder_class
;
466 x
->m_messresponder
.mr_outlet
= outlet_new(&x
->m_text
, &s_float
);
467 x
->m_text
.te_width
= 0; /* don't know it yet. */
468 x
->m_text
.te_type
= T_MESSAGE
;
469 x
->m_text
.te_binbuf
= binbuf_new();
471 x
->m_clock
= clock_new(x
, (t_method
)message_tick
);
474 x
->m_text
.te_xpix
= atom_getfloatarg(0, argc
, argv
);
475 x
->m_text
.te_ypix
= atom_getfloatarg(1, argc
, argv
);
476 if (argc
> 2) binbuf_restore(x
->m_text
.te_binbuf
, argc
-2, argv
+2);
477 glist_add(gl
, &x
->m_text
.te_g
);
482 pd_vmess(&gl
->gl_pd
, gensym("editmode"), "i", 1);
484 glist_getnextxy(gl
, &xpix
, &ypix
);
485 x
->m_text
.te_xpix
= xpix
-3;
486 x
->m_text
.te_ypix
= ypix
-3;
487 glist_add(gl
, &x
->m_text
.te_g
);
489 glist_select(gl
, &x
->m_text
.te_g
);
490 gobj_activate(&x
->m_text
.te_g
, gl
, 1);
491 canvas_startmotion(glist_getcanvas(gl
));
495 /* ---------------------- the "atom" text item ------------------------ */
497 #define ATOMBUFSIZE 40
498 #define ATOM_LABELLEFT 0
499 #define ATOM_LABELRIGHT 1
500 #define ATOM_LABELUP 2
501 #define ATOM_LABELDOWN 3
503 typedef struct _gatom
506 t_atom a_atom
; /* this holds the value and the type */
507 t_glist
*a_glist
; /* owning glist */
508 t_float a_toggle
; /* value to toggle to */
509 t_float a_draghi
; /* high end of drag range */
510 t_float a_draglo
; /* low end of drag range */
511 t_symbol
*a_label
; /* symbol to show as label next to box */
512 t_symbol
*a_symfrom
; /* "receive" name -- bind ourselvs to this */
513 t_symbol
*a_symto
; /* "send" name -- send to this on output */
514 char a_buf
[ATOMBUFSIZE
];/* string buffer for typing */
515 char a_shift
; /* was shift key down when dragging started? */
516 char a_wherelabel
; /* 0-3 for left, right, above, below */
517 t_symbol
*a_expanded_to
; /* a_symto after $0, $1, ... expansion */
520 /* prepend "-" as necessary to avoid empty strings, so we can
521 use them in Pd messages. A more complete solution would be
522 to introduce some quoting mechanism; but then we'd be much more
524 static t_symbol
*gatom_escapit(t_symbol
*s
)
527 return (gensym("-"));
528 else if (*s
->s_name
== '-')
532 strncpy(shmo
+1, s
->s_name
, 99);
534 return (gensym(shmo
));
536 else return (iemgui_dollar2raute(s
));
539 /* undo previous operation: strip leading "-" if found. */
540 static t_symbol
*gatom_unescapit(t_symbol
*s
)
542 if (*s
->s_name
== '-')
543 return (gensym(s
->s_name
+1));
544 else return (iemgui_raute2dollar(s
));
548 /* expand leading $0, $1, etc. in the symbol */
549 static t_symbol
*gatom_realizedollar(t_gatom
*x
, t_symbol
*s
)
551 return (canvas_realizedollar(x
->a_glist
, s
));
555 static void gatom_retext(t_gatom
*x
, int senditup
)
557 binbuf_clear(x
->a_text
.te_binbuf
);
558 binbuf_add(x
->a_text
.te_binbuf
, 1, &x
->a_atom
);
560 glist_retext(x
->a_glist
, &x
->a_text
);
563 static void gatom_set(t_gatom
*x
, t_symbol
*s
, int argc
, t_atom
*argv
)
565 t_atom oldatom
= x
->a_atom
;
571 if (x
->a_atom
.a_type
== A_FLOAT
)
572 x
->a_atom
.a_w
.w_float
= atom_getfloat(argv
),
573 senditup
= (x
->a_atom
.a_w
.w_float
!= oldatom
.a_w
.w_float
);
574 else if (x
->a_atom
.a_type
== A_SYMBOL
)
575 x
->a_atom
.a_w
.w_symbol
= atom_getsymbol(argv
),
576 senditup
= (x
->a_atom
.a_w
.w_symbol
!= oldatom
.a_w
.w_symbol
);
577 gatom_retext(x
, senditup
);
581 static void gatom_bang(t_gatom
*x
)
583 if (x
->a_atom
.a_type
== A_FLOAT
)
585 if (x
->a_text
.te_outlet
)
586 outlet_float(x
->a_text
.te_outlet
, x
->a_atom
.a_w
.w_float
);
587 if (*x
->a_expanded_to
->s_name
&& x
->a_expanded_to
->s_thing
)
589 if (x
->a_symto
== x
->a_symfrom
)
591 "%s: atom with same send/receive name (infinite loop)",
593 else pd_float(x
->a_expanded_to
->s_thing
, x
->a_atom
.a_w
.w_float
);
596 else if (x
->a_atom
.a_type
== A_SYMBOL
)
598 if (x
->a_text
.te_outlet
)
599 outlet_symbol(x
->a_text
.te_outlet
, x
->a_atom
.a_w
.w_symbol
);
600 if (*x
->a_symto
->s_name
&& x
->a_expanded_to
->s_thing
)
602 if (x
->a_symto
== x
->a_symfrom
)
604 "%s: atom with same send/receive name (infinite loop)",
606 else pd_symbol(x
->a_expanded_to
->s_thing
, x
->a_atom
.a_w
.w_symbol
);
611 static void gatom_float(t_gatom
*x
, t_float f
)
615 gatom_set(x
, 0, 1, &at
);
619 static void gatom_clipfloat(t_gatom
*x
, t_float f
)
621 if (x
->a_draglo
!= 0 || x
->a_draghi
!= 0)
631 static void gatom_symbol(t_gatom
*x
, t_symbol
*s
)
635 gatom_set(x
, 0, 1, &at
);
639 static void gatom_motion(void *z
, t_floatarg dx
, t_floatarg dy
)
644 t_gatom
*x
= (t_gatom
*)z
;
646 if (x
->a_atom
.a_type
== A_FLOAT
)
650 double nval
= x
->a_atom
.a_w
.w_float
- 0.01 * dy
;
651 double trunc
= 0.01 * (floor(100. * nval
+ 0.5));
652 if (trunc
< nval
+ 0.0001 && trunc
> nval
- 0.0001) nval
= trunc
;
653 gatom_clipfloat(x
, nval
);
657 double nval
= x
->a_atom
.a_w
.w_float
- dy
;
658 double trunc
= 0.01 * (floor(100. * nval
+ 0.5));
659 if (trunc
< nval
+ 0.0001 && trunc
> nval
- 0.0001) nval
= trunc
;
660 trunc
= floor(nval
+ 0.5);
661 if (trunc
< nval
+ 0.001 && trunc
> nval
- 0.001) nval
= trunc
;
662 gatom_clipfloat(x
, nval
);
667 static void gatom_key(void *z
, t_floatarg f
)
669 t_gatom
*x
= (t_gatom
*)z
;
671 int len
= strlen(x
->a_buf
);
673 char sbuf
[ATOMBUFSIZE
+ 4];
676 /* we're being notified that no more keys will come for this grab */
681 else if (c
== ' ') return;
690 if (x
->a_atom
.a_type
== A_FLOAT
)
691 x
->a_atom
.a_w
.w_float
= atof(x
->a_buf
);
692 else if (x
->a_atom
.a_type
== A_SYMBOL
)
693 x
->a_atom
.a_w
.w_symbol
= gensym(x
->a_buf
);
694 else bug("gatom_key");
699 else if (len
< (ATOMBUFSIZE
-1))
701 /* for numbers, only let reasonable characters through */
702 if ((x
->a_atom
.a_type
== A_SYMBOL
) ||
703 ((c
>= '0' && c
<= '9') || c
== '.' || c
== '-'
704 || c
== 'e' || c
== 'E'))
713 /* LATER figure out how to avoid creating all these symbols! */
715 snprintf(sbuf
, sizeof(sbuf
), "%s...", x
->a_buf
);
717 sprintf(sbuf
, "%s...", x
->a_buf
);
719 SETSYMBOL(&at
, gensym(sbuf
));
720 binbuf_clear(x
->a_text
.te_binbuf
);
721 binbuf_add(x
->a_text
.te_binbuf
, 1, &at
);
722 glist_retext(x
->a_glist
, &x
->a_text
);
725 static void gatom_click(t_gatom
*x
,
726 t_floatarg xpos
, t_floatarg ypos
, t_floatarg shift
, t_floatarg ctrl
,
732 if (x
->a_text
.te_width
== 1)
734 if (x
->a_atom
.a_type
== A_FLOAT
)
735 gatom_float(x
, (x
->a_atom
.a_w
.w_float
== 0));
741 if (x
->a_atom
.a_type
!= A_FLOAT
) return;
742 if (x
->a_atom
.a_w
.w_float
!= 0)
744 x
->a_toggle
= x
->a_atom
.a_w
.w_float
;
748 else gatom_float(x
, x
->a_toggle
);
752 glist_grab(x
->a_glist
, &x
->a_text
.te_g
, gatom_motion
, gatom_key
,
757 /* message back from dialog window */
758 static void gatom_param(t_gatom
*x
, t_symbol
*sel
, int argc
, t_atom
*argv
)
760 t_float width
= atom_getfloatarg(0, argc
, argv
);
761 t_float draglo
= atom_getfloatarg(1, argc
, argv
);
762 t_float draghi
= atom_getfloatarg(2, argc
, argv
);
763 t_symbol
*label
= gatom_unescapit(atom_getsymbolarg(3, argc
, argv
));
764 t_float wherelabel
= atom_getfloatarg(4, argc
, argv
);
765 t_symbol
*symfrom
= gatom_unescapit(atom_getsymbolarg(5, argc
, argv
));
766 t_symbol
*symto
= gatom_unescapit(atom_getsymbolarg(6, argc
, argv
));
772 gobj_vis(&x
->a_text
.te_g
, x
->a_glist
, 0);
773 if (!*symfrom
->s_name
&& *x
->a_symfrom
->s_name
)
774 inlet_new(&x
->a_text
, &x
->a_text
.te_pd
, 0, 0);
775 else if (*symfrom
->s_name
&& !*x
->a_symfrom
->s_name
&& x
->a_text
.te_inlet
)
777 canvas_deletelinesforio(x
->a_glist
, &x
->a_text
,
778 x
->a_text
.te_inlet
, 0);
779 inlet_free(x
->a_text
.te_inlet
);
781 if (!*symto
->s_name
&& *x
->a_symto
->s_name
)
782 outlet_new(&x
->a_text
, 0);
783 else if (*symto
->s_name
&& !*x
->a_symto
->s_name
&& x
->a_text
.te_outlet
)
785 canvas_deletelinesforio(x
->a_glist
, &x
->a_text
,
786 0, x
->a_text
.te_outlet
);
787 outlet_free(x
->a_text
.te_outlet
);
789 if (draglo
>= draghi
)
791 x
->a_draglo
= draglo
;
792 x
->a_draghi
= draghi
;
797 x
->a_text
.te_width
= width
;
798 x
->a_wherelabel
= ((int)wherelabel
& 3);
800 if (*x
->a_symfrom
->s_name
)
801 pd_unbind(&x
->a_text
.te_pd
,
802 canvas_realizedollar(x
->a_glist
, x
->a_symfrom
));
803 x
->a_symfrom
= symfrom
;
804 if (*x
->a_symfrom
->s_name
)
805 pd_bind(&x
->a_text
.te_pd
,
806 canvas_realizedollar(x
->a_glist
, x
->a_symfrom
));
808 x
->a_expanded_to
= canvas_realizedollar(x
->a_glist
, x
->a_symto
);
809 gobj_vis(&x
->a_text
.te_g
, x
->a_glist
, 1);
811 /* glist_retext(x->a_glist, &x->a_text); */
814 /* ---------------- gatom-specific widget functions --------------- */
815 static void gatom_getwherelabel(t_gatom
*x
, t_glist
*glist
, int *xp
, int *yp
)
817 int x1
, y1
, x2
, y2
, width
, height
;
818 text_getrect(&x
->a_text
.te_g
, glist
, &x1
, &y1
, &x2
, &y2
);
821 if (x
->a_wherelabel
== ATOM_LABELLEFT
)
824 strlen(canvas_realizedollar(x
->a_glist
, x
->a_label
)->s_name
) *
828 sys_fontwidth(glist_getfont(glist
));
832 else if (x
->a_wherelabel
== ATOM_LABELRIGHT
)
837 else if (x
->a_wherelabel
== ATOM_LABELUP
)
843 *yp
= y1
- 1 - sys_fontheight(glist_getfont(glist
));;
853 static void gatom_displace(t_gobj
*z
, t_glist
*glist
,
857 t_gatom
*x
= (t_gatom
*)z
;
859 text_displace(z
, glist
, dx
, dy
);
861 sys_vgui(".x%x.c move %x.l %d %d\n", glist_getcanvas(glist
),
866 static void gatom_vis(t_gobj
*z
, t_glist
*glist
, int vis
)
868 t_gatom
*x
= (t_gatom
*)z
;
869 text_vis(z
, glist
, vis
);
870 if (*x
->a_label
->s_name
)
875 gatom_getwherelabel(x
, glist
, &x1
, &y1
);
877 sys_vgui("pdtk_text_new .x%x.c %x.l %f %f {%s} %d %s\n",
878 glist_getcanvas(glist
), x
,
879 (double)x1
, (double)y1
,
880 canvas_realizedollar(x
->a_glist
, x
->a_label
)->s_name
,
881 sys_hostfontsize(glist_getfont(glist
)),
886 else sys_vgui(".x%x.c delete %x.l\n", glist_getcanvas(glist
), x
);
891 void canvas_atom(t_glist
*gl
, t_atomtype type
,
892 t_symbol
*s
, int argc
, t_atom
*argv
)
894 t_gatom
*x
= (t_gatom
*)pd_new(gatom_class
);
901 x
->a_text
.te_width
= 0; /* don't know it yet. */
902 x
->a_text
.te_type
= T_ATOM
;
903 x
->a_text
.te_binbuf
= binbuf_new();
905 x
->a_atom
.a_type
= type
;
912 x
->a_symto
= x
->a_expanded_to
= &s_
;
915 x
->a_atom
.a_w
.w_float
= 0;
916 x
->a_text
.te_width
= 5;
921 x
->a_atom
.a_w
.w_symbol
= &s_symbol
;
922 x
->a_text
.te_width
= 10;
923 SETSYMBOL(&at
, &s_symbol
);
925 binbuf_add(x
->a_text
.te_binbuf
, 1, &at
);
927 /* create from file. x, y, width, low-range, high-range, flags,
928 label, receive-name, send-name */
930 x
->a_text
.te_xpix
= atom_getfloatarg(0, argc
, argv
);
931 x
->a_text
.te_ypix
= atom_getfloatarg(1, argc
, argv
);
932 x
->a_text
.te_width
= atom_getintarg(2, argc
, argv
);
933 /* sanity check because some very old patches have trash in this
934 field... remove this in 2003 or so: */
935 if (x
->a_text
.te_width
< 0 || x
->a_text
.te_width
> 500)
936 x
->a_text
.te_width
= 4;
937 x
->a_draglo
= atom_getfloatarg(3, argc
, argv
);
938 x
->a_draghi
= atom_getfloatarg(4, argc
, argv
);
939 x
->a_wherelabel
= (((int)atom_getfloatarg(5, argc
, argv
)) & 3);
940 x
->a_label
= gatom_unescapit(atom_getsymbolarg(6, argc
, argv
));
941 x
->a_symfrom
= gatom_unescapit(atom_getsymbolarg(7, argc
, argv
));
942 if (*x
->a_symfrom
->s_name
)
943 pd_bind(&x
->a_text
.te_pd
,
944 canvas_realizedollar(x
->a_glist
, x
->a_symfrom
));
946 x
->a_symto
= gatom_unescapit(atom_getsymbolarg(8, argc
, argv
));
947 x
->a_expanded_to
= canvas_realizedollar(x
->a_glist
, x
->a_symto
);
948 if (x
->a_symto
== &s_
)
949 outlet_new(&x
->a_text
,
950 x
->a_atom
.a_type
== A_FLOAT
? &s_float
: &s_symbol
);
951 if (x
->a_symfrom
== &s_
)
952 inlet_new(&x
->a_text
, &x
->a_text
.te_pd
, 0, 0);
953 glist_add(gl
, &x
->a_text
.te_g
);
958 outlet_new(&x
->a_text
,
959 x
->a_atom
.a_type
== A_FLOAT
? &s_float
: &s_symbol
);
960 inlet_new(&x
->a_text
, &x
->a_text
.te_pd
, 0, 0);
961 pd_vmess(&gl
->gl_pd
, gensym("editmode"), "i", 1);
963 glist_getnextxy(gl
, &xpix
, &ypix
);
964 x
->a_text
.te_xpix
= xpix
;
965 x
->a_text
.te_ypix
= ypix
;
966 glist_add(gl
, &x
->a_text
.te_g
);
968 glist_select(gl
, &x
->a_text
.te_g
);
969 canvas_startmotion(glist_getcanvas(gl
));
973 void canvas_floatatom(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
975 canvas_atom(gl
, A_FLOAT
, s
, argc
, argv
);
978 void canvas_symbolatom(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
)
980 canvas_atom(gl
, A_SYMBOL
, s
, argc
, argv
);
983 static void gatom_free(t_gatom
*x
)
985 if (*x
->a_symfrom
->s_name
)
986 pd_unbind(&x
->a_text
.te_pd
,
987 canvas_realizedollar(x
->a_glist
, x
->a_symfrom
));
989 gfxstub_deleteforkey(x
);
993 static void gatom_properties(t_gobj
*z
, t_glist
*owner
)
999 t_gatom
*x
= (t_gatom
*)z
;
1001 sprintf(buf
, "pdtk_gatom_dialog %%s %d %g %g %d %s %s %s\n",
1002 x
->a_text
.te_width
, x
->a_draglo
, x
->a_draghi
,
1003 x
->a_wherelabel
, gatom_escapit(x
->a_label
)->s_name
,
1004 gatom_escapit(x
->a_symfrom
)->s_name
,
1005 gatom_escapit(x
->a_symto
)->s_name
);
1006 gfxstub_new(&x
->a_text
.te_pd
, x
, buf
);
1007 #endif /* ROCKBOX */
1011 /* -------------------- widget behavior for text objects ------------ */
1013 static void text_getrect(t_gobj
*z
, t_glist
*glist
,
1014 int *xp1
, int *yp1
, int *xp2
, int *yp2
)
1016 t_text
*x
= (t_text
*)z
;
1017 int width
, height
, iscomment
= (x
->te_type
== T_TEXT
);
1018 float x1
, y1
, x2
, y2
;
1020 /* for number boxes, we know width and height a priori, and should
1021 report them here so that graphs can get swelled to fit. */
1023 if (x
->te_type
== T_ATOM
&& x
->te_width
> 0)
1026 int fontwidth
= 8, fontheight
= 10;
1028 int font
= glist_getfont(glist
);
1029 int fontwidth
= sys_fontwidth(font
), fontheight
= sys_fontheight(font
);
1031 width
= (x
->te_width
> 0 ? x
->te_width
: 6) * fontwidth
+ 2;
1032 height
= fontheight
+ 1; /* borrowed from TMARGIN, etc, in g_rtext.c */
1034 /* if we're invisible we don't know our size so we just lie about
1035 it. This is called on invisible boxes to establish order of inlets
1036 and possibly other reasons.
1037 To find out if the box is visible we can't just check the "vis"
1038 flag because we might be within the vis() routine and not have set
1039 that yet. So we check directly whether the "rtext" list has been
1040 built. LATER reconsider when "vis" flag should be on and off? */
1042 else if (glist
->gl_editor
&& glist
->gl_editor
->e_rtext
)
1044 t_rtext
*y
= glist_findrtext(glist
, x
);
1045 width
= rtext_width(y
);
1046 height
= rtext_height(y
) - (iscomment
<< 1);
1048 else width
= height
= 10;
1049 x1
= text_xpix(x
, glist
);
1050 y1
= text_ypix(x
, glist
);
1060 static void text_displace(t_gobj
*z
, t_glist
*glist
,
1063 t_text
*x
= (t_text
*)z
;
1066 if (glist_isvisible(glist
))
1068 t_rtext
*y
= glist_findrtext(glist
, x
);
1069 rtext_displace(y
, dx
, dy
);
1070 text_drawborder(x
, glist
, rtext_gettag(y
),
1071 rtext_width(y
), rtext_height(y
), 0);
1072 canvas_fixlinesfor(glist_getcanvas(glist
), x
);
1076 static void text_select(t_gobj
*z
, t_glist
*glist
, int state
)
1078 t_text
*x
= (t_text
*)z
;
1079 t_rtext
*y
= glist_findrtext(glist
, x
);
1080 rtext_select(y
, state
);
1081 if (glist_isvisible(glist
) && text_shouldvis(x
, glist
))
1086 sys_vgui(".x%x.c itemconfigure %sR -fill %s\n", glist
,
1087 rtext_gettag(y
), (state
? "blue" : "black"));
1088 #endif /* ROCKBOX */
1091 static void text_activate(t_gobj
*z
, t_glist
*glist
, int state
)
1093 t_text
*x
= (t_text
*)z
;
1094 t_rtext
*y
= glist_findrtext(glist
, x
);
1095 if (z
->g_pd
!= gatom_class
) rtext_activate(y
, state
);
1098 static void text_delete(t_gobj
*z
, t_glist
*glist
)
1100 t_text
*x
= (t_text
*)z
;
1101 canvas_deletelinesfor(glist
, x
);
1104 /* return true if the text box should be drawn.
1105 We don't show object boxes inside graphs. */
1106 int text_shouldvis(t_text
*x
, t_glist
*glist
)
1108 return (glist
->gl_havewindow
||
1109 (x
->te_pd
!= canvas_class
&& x
->te_pd
->c_wb
!= &text_widgetbehavior
) ||
1110 (x
->te_pd
== canvas_class
&& (((t_glist
*)x
)->gl_isgraph
)));
1113 static void text_vis(t_gobj
*z
, t_glist
*glist
, int vis
)
1115 t_text
*x
= (t_text
*)z
;
1118 if (text_shouldvis(x
, glist
))
1120 t_rtext
*y
= glist_findrtext(glist
, x
);
1121 if (x
->te_type
== T_ATOM
)
1122 glist_retext(glist
, x
);
1123 text_drawborder(x
, glist
, rtext_gettag(y
),
1124 rtext_width(y
), rtext_height(y
), 1);
1130 t_rtext
*y
= glist_findrtext(glist
, x
);
1131 if (text_shouldvis(x
, glist
))
1133 text_eraseborder(x
, glist
, rtext_gettag(y
));
1139 static int text_click(t_gobj
*z
, struct _glist
*glist
,
1140 int xpix
, int ypix
, int shift
, int alt
, int dbl
, int doit
)
1146 t_text
*x
= (t_text
*)z
;
1147 if (x
->te_type
== T_OBJECT
)
1149 t_symbol
*clicksym
= gensym("click");
1150 if (zgetfn(&x
->te_pd
, clicksym
))
1153 pd_vmess(&x
->te_pd
, clicksym
, "fffff",
1154 (double)xpix
, (double)ypix
,
1155 (double)shift
, 0, (double)alt
);
1160 else if (x
->te_type
== T_ATOM
)
1163 gatom_click((t_gatom
*)x
, (t_floatarg
)xpix
, (t_floatarg
)ypix
,
1164 (t_floatarg
)shift
, 0, (t_floatarg
)alt
);
1167 else if (x
->te_type
== T_MESSAGE
)
1170 message_click((t_message
*)x
, (t_floatarg
)xpix
, (t_floatarg
)ypix
,
1171 (t_floatarg
)shift
, 0, (t_floatarg
)alt
);
1177 void text_save(t_gobj
*z
, t_binbuf
*b
)
1179 t_text
*x
= (t_text
*)z
;
1180 if (x
->te_type
== T_OBJECT
)
1182 /* if we have a "saveto" method, and if we don't happen to be
1183 a canvas that's an abstraction, the saveto method does the work */
1184 if (zgetfn(&x
->te_pd
, gensym("saveto")) &&
1185 !((pd_class(&x
->te_pd
) == canvas_class
) &&
1186 (canvas_isabstraction((t_canvas
*)x
)
1187 || canvas_istable((t_canvas
*)x
))))
1189 mess1(&x
->te_pd
, gensym("saveto"), b
);
1190 binbuf_addv(b
, "ssii", gensym("#X"), gensym("restore"),
1191 (t_int
)x
->te_xpix
, (t_int
)x
->te_ypix
);
1193 else /* otherwise just save the text */
1195 binbuf_addv(b
, "ssii", gensym("#X"), gensym("obj"),
1196 (t_int
)x
->te_xpix
, (t_int
)x
->te_ypix
);
1198 binbuf_addbinbuf(b
, x
->te_binbuf
);
1199 binbuf_addv(b
, ";");
1201 else if (x
->te_type
== T_MESSAGE
)
1203 binbuf_addv(b
, "ssii", gensym("#X"), gensym("msg"),
1204 (t_int
)x
->te_xpix
, (t_int
)x
->te_ypix
);
1205 binbuf_addbinbuf(b
, x
->te_binbuf
);
1206 binbuf_addv(b
, ";");
1208 else if (x
->te_type
== T_ATOM
)
1210 t_atomtype t
= ((t_gatom
*)x
)->a_atom
.a_type
;
1211 t_symbol
*sel
= (t
== A_SYMBOL
? gensym("symbolatom") :
1212 (t
== A_FLOAT
? gensym("floatatom") : gensym("intatom")));
1213 t_symbol
*label
= gatom_escapit(((t_gatom
*)x
)->a_label
);
1214 t_symbol
*symfrom
= gatom_escapit(((t_gatom
*)x
)->a_symfrom
);
1215 t_symbol
*symto
= gatom_escapit(((t_gatom
*)x
)->a_symto
);
1216 binbuf_addv(b
, "ssiiifffsss", gensym("#X"), sel
,
1217 (t_int
)x
->te_xpix
, (t_int
)x
->te_ypix
, (t_int
)x
->te_width
,
1218 (double)((t_gatom
*)x
)->a_draglo
,
1219 (double)((t_gatom
*)x
)->a_draghi
,
1220 (double)((t_gatom
*)x
)->a_wherelabel
,
1221 label
, symfrom
, symto
);
1222 binbuf_addv(b
, ";");
1226 binbuf_addv(b
, "ssii", gensym("#X"), gensym("text"),
1227 (t_int
)x
->te_xpix
, (t_int
)x
->te_ypix
);
1228 binbuf_addbinbuf(b
, x
->te_binbuf
);
1229 binbuf_addv(b
, ";");
1233 /* this one is for everyone but "gatoms"; it's imposed in m_class.c */
1234 t_widgetbehavior text_widgetbehavior
=
1245 static t_widgetbehavior gatom_widgetbehavior
=
1256 /* -------------------- the "text" class ------------ */
1264 /* draw inlets and outlets for a text object or for a graph. */
1265 void glist_drawiofor(t_glist
*glist
, t_object
*ob
, int firsttime
,
1266 char *tag
, int x1
, int y1
, int x2
, int y2
)
1268 int n
= obj_noutlets(ob
), nplus
= (n
== 1 ? 1 : n
-1), i
;
1278 int width
= x2
- x1
;
1279 #endif /* ROCKBOX */
1280 for (i
= 0; i
< n
; i
++)
1283 int onset
= x1
+ (width
- IOWIDTH
) * i
/ nplus
;
1285 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %so%d\n",
1286 glist_getcanvas(glist
),
1288 onset
+ IOWIDTH
, y2
,
1291 sys_vgui(".x%x.c coords %so%d %d %d %d %d\n",
1292 glist_getcanvas(glist
), tag
, i
,
1294 onset
+ IOWIDTH
, y2
);
1295 #endif /* ROCKBOX */
1297 n
= obj_ninlets(ob
);
1298 nplus
= (n
== 1 ? 1 : n
-1);
1299 for (i
= 0; i
< n
; i
++)
1302 int onset
= x1
+ (width
- IOWIDTH
) * i
/ nplus
;
1304 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %si%d\n",
1305 glist_getcanvas(glist
),
1307 onset
+ IOWIDTH
, y1
+ EXTRAPIX
,
1310 sys_vgui(".x%x.c coords %si%d %d %d %d %d\n",
1311 glist_getcanvas(glist
), tag
, i
,
1313 onset
+ IOWIDTH
, y1
+ EXTRAPIX
);
1314 #endif /* ROCKBOX */
1318 void text_drawborder(t_text
*x
, t_glist
*glist
,
1319 char *tag
, int width2
, int height2
, int firsttime
)
1322 int x1
, y1
, x2
, y2
, width
, height
;
1329 text_getrect(&x
->te_g
, glist
, &x1
, &y1
, &x2
, &y2
);
1332 if (x
->te_type
== T_OBJECT
)
1336 sys_vgui(".x%x.c create line\
1337 %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
1338 glist_getcanvas(glist
),
1339 x1
, y1
, x2
, y1
, x2
, y2
, x1
, y2
, x1
, y1
, tag
);
1341 sys_vgui(".x%x.c coords %sR\
1342 %d %d %d %d %d %d %d %d %d %d\n",
1343 glist_getcanvas(glist
), tag
,
1344 x1
, y1
, x2
, y1
, x2
, y2
, x1
, y2
, x1
, y1
);
1347 else if (x
->te_type
== T_MESSAGE
)
1351 sys_vgui(".x%x.c create line\
1352 %d %d %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
1353 glist_getcanvas(glist
),
1354 x1
, y1
, x2
+4, y1
, x2
, y1
+4, x2
, y2
-4, x2
+4, y2
,
1358 sys_vgui(".x%x.c coords %sR\
1359 %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
1360 glist_getcanvas(glist
), tag
,
1361 x1
, y1
, x2
+4, y1
, x2
, y1
+4, x2
, y2
-4, x2
+4, y2
,
1365 else if (x
->te_type
== T_ATOM
)
1369 sys_vgui(".x%x.c create line\
1370 %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
1371 glist_getcanvas(glist
),
1372 x1
, y1
, x2
-4, y1
, x2
, y1
+4, x2
, y2
, x1
, y2
, x1
, y1
,
1375 sys_vgui(".x%x.c coords %sR\
1376 %d %d %d %d %d %d %d %d %d %d %d %d\n",
1377 glist_getcanvas(glist
), tag
,
1378 x1
, y1
, x2
-4, y1
, x2
, y1
+4, x2
, y2
, x1
, y2
, x1
, y1
);
1381 /* draw inlets/outlets */
1383 if ((ob
= pd_checkobject(&x
->te_pd
)))
1384 glist_drawiofor(glist
, ob
, firsttime
, tag
, x1
, y1
, x2
, y2
);
1387 void glist_eraseiofor(t_glist
*glist
, t_object
*ob
, char *tag
)
1394 n
= obj_noutlets(ob
);
1395 for (i
= 0; i
< n
; i
++)
1399 sys_vgui(".x%x.c delete %so%d\n",
1400 glist_getcanvas(glist
), tag
, i
);
1401 #endif /* ROCKBOX */
1402 n
= obj_ninlets(ob
);
1403 for (i
= 0; i
< n
; i
++)
1407 sys_vgui(".x%x.c delete %si%d\n",
1408 glist_getcanvas(glist
), tag
, i
);
1409 #endif /* ROCKBOX */
1412 void text_eraseborder(t_text
*x
, t_glist
*glist
, char *tag
)
1414 if (x
->te_type
== T_TEXT
) return;
1416 sys_vgui(".x%x.c delete %sR\n",
1417 glist_getcanvas(glist
), tag
);
1419 glist_eraseiofor(glist
, x
, tag
);
1422 /* change text; if T_OBJECT, remake it. LATER we'll have an undo buffer
1423 which should be filled in here before making the change. */
1425 void text_setto(t_text
*x
, t_glist
*glist
, char *buf
, int bufsize
)
1427 if (x
->te_type
== T_OBJECT
)
1429 t_binbuf
*b
= binbuf_new();
1431 t_atom
*vec1
, *vec2
;
1432 binbuf_text(b
, buf
, bufsize
);
1433 natom1
= binbuf_getnatom(x
->te_binbuf
);
1434 vec1
= binbuf_getvec(x
->te_binbuf
);
1435 natom2
= binbuf_getnatom(b
);
1436 vec2
= binbuf_getvec(b
);
1437 /* special case: if pd args change just pass the message on. */
1438 if (natom1
>= 1 && natom2
>= 1 && vec1
[0].a_type
== A_SYMBOL
1439 && !strcmp(vec1
[0].a_w
.w_symbol
->s_name
, "pd") &&
1440 vec2
[0].a_type
== A_SYMBOL
1441 && !strcmp(vec2
[0].a_w
.w_symbol
->s_name
, "pd"))
1443 typedmess(&x
->te_pd
, gensym("rename"), natom2
-1, vec2
+1);
1444 binbuf_free(x
->te_binbuf
);
1447 else /* normally, just destroy the old one and make a new one. */
1449 int xwas
= x
->te_xpix
, ywas
= x
->te_ypix
;
1450 glist_delete(glist
, &x
->te_g
);
1451 canvas_objtext(glist
, xwas
, ywas
, 0, b
);
1452 /* if it's an abstraction loadbang it here */
1453 if (newest
&& pd_class(newest
) == canvas_class
)
1454 canvas_loadbang((t_canvas
*)newest
);
1455 canvas_restoreconnections(glist_getcanvas(glist
));
1457 /* if we made a new "pd" or changed a window name,
1458 update window list */
1459 if (natom2
>= 1 && vec2
[0].a_type
== A_SYMBOL
1460 && !strcmp(vec2
[0].a_w
.w_symbol
->s_name
, "pd"))
1461 canvas_updatewindowlist();
1463 else binbuf_text(x
->te_binbuf
, buf
, bufsize
);
1466 void g_text_setup(void)
1468 text_class
= class_new(gensym("text"), 0, 0, sizeof(t_text
),
1469 CLASS_NOINLET
| CLASS_PATCHABLE
, 0);
1471 message_class
= class_new(gensym("message"), 0, (t_method
)message_free
,
1472 sizeof(t_message
), CLASS_PATCHABLE
, 0);
1473 class_addbang(message_class
, message_bang
);
1474 class_addfloat(message_class
, message_float
);
1475 class_addsymbol(message_class
, message_symbol
);
1476 class_addlist(message_class
, message_list
);
1477 class_addanything(message_class
, message_list
);
1479 class_addmethod(message_class
, (t_method
)message_click
, gensym("click"),
1480 A_FLOAT
, A_FLOAT
, A_FLOAT
, A_FLOAT
, A_FLOAT
, 0);
1481 class_addmethod(message_class
, (t_method
)message_set
, gensym("set"),
1483 class_addmethod(message_class
, (t_method
)message_add
, gensym("add"),
1485 class_addmethod(message_class
, (t_method
)message_add2
, gensym("add2"),
1488 messresponder_class
= class_new(gensym("messresponder"), 0, 0,
1489 sizeof(t_text
), CLASS_PD
, 0);
1490 class_addbang(messresponder_class
, messresponder_bang
);
1491 class_addfloat(messresponder_class
, (t_method
) messresponder_float
);
1492 class_addsymbol(messresponder_class
, messresponder_symbol
);
1493 class_addlist(messresponder_class
, messresponder_list
);
1494 class_addanything(messresponder_class
, messresponder_anything
);
1496 gatom_class
= class_new(gensym("gatom"), 0, (t_method
)gatom_free
,
1497 sizeof(t_gatom
), CLASS_NOINLET
| CLASS_PATCHABLE
, 0);
1498 class_addbang(gatom_class
, gatom_bang
);
1499 class_addfloat(gatom_class
, gatom_float
);
1500 class_addsymbol(gatom_class
, gatom_symbol
);
1501 class_addmethod(gatom_class
, (t_method
)gatom_set
, gensym("set"),
1503 class_addmethod(gatom_class
, (t_method
)gatom_click
, gensym("click"),
1504 A_FLOAT
, A_FLOAT
, A_FLOAT
, A_FLOAT
, A_FLOAT
, 0);
1505 class_addmethod(gatom_class
, (t_method
)gatom_param
, gensym("param"),
1507 class_setwidget(gatom_class
, &gatom_widgetbehavior
);
1508 class_setpropertiesfn(gatom_class
, gatom_properties
);