diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/g_text.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/src/g_text.c | 2632 |
1 files changed, 2632 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/g_text.c b/apps/plugins/pdbox/PDa/src/g_text.c new file mode 100644 index 0000000000..8cf1fe2834 --- /dev/null +++ b/apps/plugins/pdbox/PDa/src/g_text.c | |||
@@ -0,0 +1,2632 @@ | |||
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. */ | ||
4 | |||
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 */ | ||
8 | |||
9 | #include <stdlib.h> | ||
10 | #include "m_pd.h" | ||
11 | #include "m_imp.h" | ||
12 | #include "s_stuff.h" | ||
13 | #include "t_tk.h" | ||
14 | #include "g_canvas.h" | ||
15 | #include <stdio.h> | ||
16 | #include <string.h> | ||
17 | #include <math.h> | ||
18 | |||
19 | static t_class *text_class; | ||
20 | static t_class *message_class; | ||
21 | static t_class *gatom_class; | ||
22 | static void text_vis(t_gobj *z, t_glist *glist, int vis); | ||
23 | static void text_displace(t_gobj *z, t_glist *glist, | ||
24 | int dx, int dy); | ||
25 | static void text_getrect(t_gobj *z, t_glist *glist, | ||
26 | int *xp1, int *yp1, int *xp2, int *yp2); | ||
27 | |||
28 | void canvas_startmotion(t_canvas *x); | ||
29 | t_widgetbehavior text_widgetbehavior; | ||
30 | |||
31 | /* ----------------- the "text" object. ------------------ */ | ||
32 | |||
33 | /* add a "text" object (comment) to a glist. While this one goes for any glist, | ||
34 | the other 3 below are for canvases only. (why?) This is called | ||
35 | without args if invoked from the GUI; otherwise at least x and y | ||
36 | are provided. */ | ||
37 | |||
38 | void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
39 | { | ||
40 | t_text *x = (t_text *)pd_new(text_class); | ||
41 | t_atom at; | ||
42 | x->te_width = 0; /* don't know it yet. */ | ||
43 | x->te_type = T_TEXT; | ||
44 | x->te_binbuf = binbuf_new(); | ||
45 | if (argc > 1) | ||
46 | { | ||
47 | x->te_xpix = atom_getfloatarg(0, argc, argv); | ||
48 | x->te_ypix = atom_getfloatarg(1, argc, argv); | ||
49 | if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2); | ||
50 | else | ||
51 | { | ||
52 | SETSYMBOL(&at, gensym("comment")); | ||
53 | binbuf_restore(x->te_binbuf, 1, &at); | ||
54 | } | ||
55 | glist_add(gl, &x->te_g); | ||
56 | } | ||
57 | else | ||
58 | { | ||
59 | int xpix, ypix; | ||
60 | pd_vmess((t_pd *)glist_getcanvas(gl), gensym("editmode"), "i", 1); | ||
61 | SETSYMBOL(&at, gensym("comment")); | ||
62 | glist_noselect(gl); | ||
63 | glist_getnextxy(gl, &xpix, &ypix); | ||
64 | x->te_xpix = glist_pixelstox(gl, xpix-3); | ||
65 | x->te_ypix = glist_pixelstoy(gl, ypix-3); | ||
66 | binbuf_restore(x->te_binbuf, 1, &at); | ||
67 | glist_add(gl, &x->te_g); | ||
68 | glist_noselect(gl); | ||
69 | glist_select(gl, &x->te_g); | ||
70 | /* it would be nice to "activate" here, but then the second, | ||
71 | "put-me-down" click changes the text selection, which is quite | ||
72 | irritating, so I took this back out. It's OK in messages | ||
73 | and objects though since there's no text in them at menu | ||
74 | creation. */ | ||
75 | /* gobj_activate(&x->te_g, gl, 1); */ | ||
76 | canvas_startmotion(glist_getcanvas(gl)); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | /* ----------------- the "object" object. ------------------ */ | ||
81 | |||
82 | extern t_pd *newest; | ||
83 | void canvas_getargs(int *argcp, t_atom **argvp); | ||
84 | |||
85 | static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected, | ||
86 | t_binbuf *b) | ||
87 | { | ||
88 | t_text *x; | ||
89 | int argc; | ||
90 | t_atom *argv; | ||
91 | newest = 0; | ||
92 | canvas_setcurrent((t_canvas *)gl); | ||
93 | canvas_getargs(&argc, &argv); | ||
94 | binbuf_eval(b, &pd_objectmaker, argc, argv); | ||
95 | if (binbuf_getnatom(b)) | ||
96 | { | ||
97 | if (!newest) | ||
98 | { | ||
99 | binbuf_print(b); | ||
100 | post("... couldn't create"); | ||
101 | x = 0; | ||
102 | } | ||
103 | else if (!(x = pd_checkobject(newest))) | ||
104 | { | ||
105 | binbuf_print(b); | ||
106 | post("... didn't return a patchable object"); | ||
107 | } | ||
108 | } | ||
109 | else x = 0; | ||
110 | if (!x) | ||
111 | { | ||
112 | |||
113 | /* LATER make the color reflect this */ | ||
114 | x = (t_text *)pd_new(text_class); | ||
115 | } | ||
116 | x->te_binbuf = b; | ||
117 | x->te_xpix = xpix; | ||
118 | x->te_ypix = ypix; | ||
119 | x->te_width = 0; | ||
120 | x->te_type = T_OBJECT; | ||
121 | glist_add(gl, &x->te_g); | ||
122 | if (selected) | ||
123 | { | ||
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); | ||
127 | } | ||
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); | ||
133 | } | ||
134 | |||
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. */ | ||
138 | |||
139 | void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
140 | { | ||
141 | t_text *x; | ||
142 | if (argc >= 2) | ||
143 | { | ||
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); | ||
148 | } | ||
149 | else | ||
150 | { | ||
151 | t_binbuf *b = binbuf_new(); | ||
152 | int xpix, ypix; | ||
153 | pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); | ||
154 | glist_noselect(gl); | ||
155 | glist_getnextxy(gl, &xpix, &ypix); | ||
156 | canvas_objtext(gl, xpix, ypix, 1, b); | ||
157 | canvas_startmotion(glist_getcanvas(gl)); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | /* make an object box for an object that's already there. */ | ||
162 | |||
163 | /* iemlib */ | ||
164 | void canvas_iemguis(t_glist *gl, t_symbol *guiobjname) | ||
165 | { | ||
166 | t_atom at; | ||
167 | t_binbuf *b = binbuf_new(); | ||
168 | int xpix, ypix; | ||
169 | |||
170 | pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); | ||
171 | glist_noselect(gl); | ||
172 | SETSYMBOL(&at, guiobjname); | ||
173 | binbuf_restore(b, 1, &at); | ||
174 | glist_getnextxy(gl, &xpix, &ypix); | ||
175 | canvas_objtext(gl, xpix, ypix, 1, b); | ||
176 | canvas_startmotion(glist_getcanvas(gl)); | ||
177 | } | ||
178 | |||
179 | void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
180 | { | ||
181 | canvas_iemguis(gl, gensym("bng")); | ||
182 | } | ||
183 | |||
184 | void canvas_toggle(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
185 | { | ||
186 | canvas_iemguis(gl, gensym("tgl")); | ||
187 | } | ||
188 | |||
189 | void canvas_vslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
190 | { | ||
191 | canvas_iemguis(gl, gensym("vsl")); | ||
192 | } | ||
193 | |||
194 | void canvas_hslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
195 | { | ||
196 | canvas_iemguis(gl, gensym("hsl")); | ||
197 | } | ||
198 | |||
199 | void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
200 | { | ||
201 | canvas_iemguis(gl, gensym("hdl")); | ||
202 | } | ||
203 | |||
204 | void canvas_vdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
205 | { | ||
206 | canvas_iemguis(gl, gensym("vdl")); | ||
207 | } | ||
208 | |||
209 | void canvas_hradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
210 | { | ||
211 | canvas_iemguis(gl, gensym("hradio")); | ||
212 | } | ||
213 | |||
214 | void canvas_vradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
215 | { | ||
216 | canvas_iemguis(gl, gensym("vradio")); | ||
217 | } | ||
218 | |||
219 | void canvas_vumeter(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
220 | { | ||
221 | canvas_iemguis(gl, gensym("vu")); | ||
222 | } | ||
223 | |||
224 | void canvas_mycnv(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
225 | { | ||
226 | canvas_iemguis(gl, gensym("cnv")); | ||
227 | } | ||
228 | |||
229 | void canvas_numbox(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
230 | { | ||
231 | canvas_iemguis(gl, gensym("nbx")); | ||
232 | } | ||
233 | |||
234 | /* iemlib */ | ||
235 | |||
236 | void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv) | ||
237 | { | ||
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); | ||
245 | } | ||
246 | |||
247 | /* ---------------------- the "message" text item ------------------------ */ | ||
248 | |||
249 | typedef struct _messresponder | ||
250 | { | ||
251 | t_pd mr_pd; | ||
252 | t_outlet *mr_outlet; | ||
253 | } t_messresponder; | ||
254 | |||
255 | typedef struct _message | ||
256 | { | ||
257 | t_text m_text; | ||
258 | t_messresponder m_messresponder; | ||
259 | t_glist *m_glist; | ||
260 | t_clock *m_clock; | ||
261 | } t_message; | ||
262 | |||
263 | static t_class *message_class, *messresponder_class; | ||
264 | |||
265 | static void messresponder_bang(t_messresponder *x) | ||
266 | { | ||
267 | outlet_bang(x->mr_outlet); | ||
268 | } | ||
269 | |||
270 | static void messresponder_float(t_messresponder *x, t_float f) | ||
271 | { | ||
272 | outlet_float(x->mr_outlet, f); | ||
273 | } | ||
274 | |||
275 | static void messresponder_symbol(t_messresponder *x, t_symbol *s) | ||
276 | { | ||
277 | outlet_symbol(x->mr_outlet, s); | ||
278 | } | ||
279 | |||
280 | static void messresponder_list(t_messresponder *x, | ||
281 | t_symbol *s, int argc, t_atom *argv) | ||
282 | { | ||
283 | outlet_list(x->mr_outlet, s, argc, argv); | ||
284 | } | ||
285 | |||
286 | static void messresponder_anything(t_messresponder *x, | ||
287 | t_symbol *s, int argc, t_atom *argv) | ||
288 | { | ||
289 | outlet_anything(x->mr_outlet, s, argc, argv); | ||
290 | } | ||
291 | |||
292 | static void message_bang(t_message *x) | ||
293 | { | ||
294 | binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 0, 0); | ||
295 | } | ||
296 | |||
297 | static void message_float(t_message *x, t_float f) | ||
298 | { | ||
299 | t_atom at; | ||
300 | SETFLOAT(&at, f); | ||
301 | binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at); | ||
302 | } | ||
303 | |||
304 | static void message_symbol(t_message *x, t_symbol *s) | ||
305 | { | ||
306 | t_atom at; | ||
307 | SETSYMBOL(&at, s); | ||
308 | binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at); | ||
309 | } | ||
310 | |||
311 | static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv) | ||
312 | { | ||
313 | binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, argc, argv); | ||
314 | } | ||
315 | |||
316 | static void message_set(t_message *x, t_symbol *s, int argc, t_atom *argv) | ||
317 | { | ||
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); | ||
321 | } | ||
322 | |||
323 | static void message_add2(t_message *x, t_symbol *s, int argc, t_atom *argv) | ||
324 | { | ||
325 | binbuf_add(x->m_text.te_binbuf, argc, argv); | ||
326 | glist_retext(x->m_glist, &x->m_text); | ||
327 | } | ||
328 | |||
329 | static void message_add(t_message *x, t_symbol *s, int argc, t_atom *argv) | ||
330 | { | ||
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); | ||
334 | } | ||
335 | |||
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) | ||
339 | { | ||
340 | message_float(x, 0); | ||
341 | if (glist_isvisible(x->m_glist)) | ||
342 | { | ||
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); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | static void message_tick(t_message *x) | ||
351 | { | ||
352 | if (glist_isvisible(x->m_glist)) | ||
353 | { | ||
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)); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | static void message_free(t_message *x) | ||
361 | { | ||
362 | clock_free(x->m_clock); | ||
363 | } | ||
364 | |||
365 | void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
366 | { | ||
367 | t_message *x = (t_message *)pd_new(message_class); | ||
368 | x->m_messresponder.mr_pd = messresponder_class; | ||
369 | x->m_messresponder.mr_outlet = outlet_new(&x->m_text, &s_float); | ||
370 | x->m_text.te_width = 0; /* don't know it yet. */ | ||
371 | x->m_text.te_type = T_MESSAGE; | ||
372 | x->m_text.te_binbuf = binbuf_new(); | ||
373 | x->m_glist = gl; | ||
374 | x->m_clock = clock_new(x, (t_method)message_tick); | ||
375 | if (argc > 1) | ||
376 | { | ||
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); | ||
381 | } | ||
382 | else | ||
383 | { | ||
384 | int xpix, ypix; | ||
385 | pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); | ||
386 | glist_noselect(gl); | ||
387 | glist_getnextxy(gl, &xpix, &ypix); | ||
388 | x->m_text.te_xpix = xpix-3; | ||
389 | x->m_text.te_ypix = ypix-3; | ||
390 | glist_add(gl, &x->m_text.te_g); | ||
391 | glist_noselect(gl); | ||
392 | glist_select(gl, &x->m_text.te_g); | ||
393 | gobj_activate(&x->m_text.te_g, gl, 1); | ||
394 | canvas_startmotion(glist_getcanvas(gl)); | ||
395 | } | ||
396 | } | ||
397 | |||
398 | /* ---------------------- the "atom" text item ------------------------ */ | ||
399 | |||
400 | #define ATOMBUFSIZE 40 | ||
401 | #define ATOM_LABELLEFT 0 | ||
402 | #define ATOM_LABELRIGHT 1 | ||
403 | #define ATOM_LABELUP 2 | ||
404 | #define ATOM_LABELDOWN 3 | ||
405 | |||
406 | typedef struct _gatom | ||
407 | { | ||
408 | t_text a_text; | ||
409 | t_atom a_atom; /* this holds the value and the type */ | ||
410 | t_glist *a_glist; /* owning glist */ | ||
411 | t_float a_toggle; /* value to toggle to */ | ||
412 | t_float a_draghi; /* high end of drag range */ | ||
413 | t_float a_draglo; /* low end of drag range */ | ||
414 | t_symbol *a_label; /* symbol to show as label next to box */ | ||
415 | t_symbol *a_symfrom; /* "receive" name -- bind ourselvs to this */ | ||
416 | t_symbol *a_symto; /* "send" name -- send to this on output */ | ||
417 | char a_buf[ATOMBUFSIZE];/* string buffer for typing */ | ||
418 | char a_shift; /* was shift key down when dragging started? */ | ||
419 | char a_wherelabel; /* 0-3 for left, right, above, below */ | ||
420 | t_symbol *a_expanded_to; /* a_symto after $0, $1, ... expansion */ | ||
421 | } t_gatom; | ||
422 | |||
423 | /* prepend "-" as necessary to avoid empty strings, so we can | ||
424 | use them in Pd messages. A more complete solution would be | ||
425 | to introduce some quoting mechanism; but then we'd be much more | ||
426 | complicated. */ | ||
427 | static t_symbol *gatom_escapit(t_symbol *s) | ||
428 | { | ||
429 | if (!*s->s_name) | ||
430 | return (gensym("-")); | ||
431 | else if (*s->s_name == '-') | ||
432 | { | ||
433 | char shmo[100]; | ||
434 | shmo[0] = '-'; | ||
435 | strncpy(shmo+1, s->s_name, 99); | ||
436 | shmo[99] = 0; | ||
437 | return (gensym(shmo)); | ||
438 | } | ||
439 | else return (iemgui_dollar2raute(s)); | ||
440 | } | ||
441 | |||
442 | /* undo previous operation: strip leading "-" if found. */ | ||
443 | static t_symbol *gatom_unescapit(t_symbol *s) | ||
444 | { | ||
445 | if (*s->s_name == '-') | ||
446 | return (gensym(s->s_name+1)); | ||
447 | else return (iemgui_raute2dollar(s)); | ||
448 | } | ||
449 | |||
450 | #if 0 /* ??? */ | ||
451 | /* expand leading $0, $1, etc. in the symbol */ | ||
452 | static t_symbol *gatom_realizedollar(t_gatom *x, t_symbol *s) | ||
453 | { | ||
454 | return (canvas_realizedollar(x->a_glist, s)); | ||
455 | } | ||
456 | #endif | ||
457 | |||
458 | static void gatom_retext(t_gatom *x, int senditup) | ||
459 | { | ||
460 | binbuf_clear(x->a_text.te_binbuf); | ||
461 | binbuf_add(x->a_text.te_binbuf, 1, &x->a_atom); | ||
462 | if (senditup) | ||
463 | glist_retext(x->a_glist, &x->a_text); | ||
464 | } | ||
465 | |||
466 | static void gatom_set(t_gatom *x, t_symbol *s, int argc, t_atom *argv) | ||
467 | { | ||
468 | t_atom oldatom = x->a_atom; | ||
469 | int senditup = 0; | ||
470 | if (!argc) return; | ||
471 | if (x->a_atom.a_type == A_FLOAT) | ||
472 | x->a_atom.a_w.w_float = atom_getfloat(argv), | ||
473 | senditup = (x->a_atom.a_w.w_float != oldatom.a_w.w_float); | ||
474 | else if (x->a_atom.a_type == A_SYMBOL) | ||
475 | x->a_atom.a_w.w_symbol = atom_getsymbol(argv), | ||
476 | senditup = (x->a_atom.a_w.w_symbol != oldatom.a_w.w_symbol); | ||
477 | gatom_retext(x, senditup); | ||
478 | x->a_buf[0] = 0; | ||
479 | } | ||
480 | |||
481 | static void gatom_bang(t_gatom *x) | ||
482 | { | ||
483 | if (x->a_atom.a_type == A_FLOAT) | ||
484 | { | ||
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) | ||
488 | { | ||
489 | if (x->a_symto == x->a_symfrom) | ||
490 | pd_error(x, | ||
491 | "%s: atom with same send/receive name (infinite loop)", | ||
492 | x->a_symto->s_name); | ||
493 | else pd_float(x->a_expanded_to->s_thing, x->a_atom.a_w.w_float); | ||
494 | } | ||
495 | } | ||
496 | else if (x->a_atom.a_type == A_SYMBOL) | ||
497 | { | ||
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) | ||
501 | { | ||
502 | if (x->a_symto == x->a_symfrom) | ||
503 | pd_error(x, | ||
504 | "%s: atom with same send/receive name (infinite loop)", | ||
505 | x->a_symto->s_name); | ||
506 | else pd_symbol(x->a_expanded_to->s_thing, x->a_atom.a_w.w_symbol); | ||
507 | } | ||
508 | } | ||
509 | } | ||
510 | |||
511 | static void gatom_float(t_gatom *x, t_float f) | ||
512 | { | ||
513 | t_atom at; | ||
514 | SETFLOAT(&at, f); | ||
515 | gatom_set(x, 0, 1, &at); | ||
516 | gatom_bang(x); | ||
517 | } | ||
518 | |||
519 | static void gatom_clipfloat(t_gatom *x, t_float f) | ||
520 | { | ||
521 | if (x->a_draglo != 0 || x->a_draghi != 0) | ||
522 | { | ||
523 | if (f < x->a_draglo) | ||
524 | f = x->a_draglo; | ||
525 | if (f > x->a_draghi) | ||
526 | f = x->a_draghi; | ||
527 | } | ||
528 | gatom_float(x, f); | ||
529 | } | ||
530 | |||
531 | static void gatom_symbol(t_gatom *x, t_symbol *s) | ||
532 | { | ||
533 | t_atom at; | ||
534 | SETSYMBOL(&at, s); | ||
535 | gatom_set(x, 0, 1, &at); | ||
536 | gatom_bang(x); | ||
537 | } | ||
538 | |||
539 | static void gatom_motion(void *z, t_floatarg dx, t_floatarg dy) | ||
540 | { | ||
541 | t_gatom *x = (t_gatom *)z; | ||
542 | if (dy == 0) return; | ||
543 | if (x->a_atom.a_type == A_FLOAT) | ||
544 | { | ||
545 | if (x->a_shift) | ||
546 | { | ||
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); | ||
551 | } | ||
552 | else | ||
553 | { | ||
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); | ||
560 | } | ||
561 | } | ||
562 | } | ||
563 | |||
564 | static void gatom_key(void *z, t_floatarg f) | ||
565 | { | ||
566 | t_gatom *x = (t_gatom *)z; | ||
567 | int c = f; | ||
568 | int len = strlen(x->a_buf); | ||
569 | t_atom at; | ||
570 | char sbuf[ATOMBUFSIZE + 4]; | ||
571 | if (c == 0) | ||
572 | { | ||
573 | /* we're being notified that no more keys will come for this grab */ | ||
574 | if (x->a_buf[0]) | ||
575 | gatom_retext(x, 1); | ||
576 | return; | ||
577 | } | ||
578 | else if (c == ' ') return; | ||
579 | else if (c == '\b') | ||
580 | { | ||
581 | if (len > 0) | ||
582 | x->a_buf[len-1] = 0; | ||
583 | goto redraw; | ||
584 | } | ||
585 | else if (c == '\n') | ||
586 | { | ||
587 | if (x->a_atom.a_type == A_FLOAT) | ||
588 | x->a_atom.a_w.w_float = atof(x->a_buf); | ||
589 | else if (x->a_atom.a_type == A_SYMBOL) | ||
590 | x->a_atom.a_w.w_symbol = gensym(x->a_buf); | ||
591 | else bug("gatom_key"); | ||
592 | gatom_bang(x); | ||
593 | gatom_retext(x, 1); | ||
594 | x->a_buf[0] = 0; | ||
595 | } | ||
596 | else if (len < (ATOMBUFSIZE-1)) | ||
597 | { | ||
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')) | ||
602 | { | ||
603 | x->a_buf[len] = c; | ||
604 | x->a_buf[len+1] = 0; | ||
605 | goto redraw; | ||
606 | } | ||
607 | } | ||
608 | return; | ||
609 | redraw: | ||
610 | /* LATER figure out how to avoid creating all these symbols! */ | ||
611 | sprintf(sbuf, "%s...", x->a_buf); | ||
612 | SETSYMBOL(&at, gensym(sbuf)); | ||
613 | binbuf_clear(x->a_text.te_binbuf); | ||
614 | binbuf_add(x->a_text.te_binbuf, 1, &at); | ||
615 | glist_retext(x->a_glist, &x->a_text); | ||
616 | } | ||
617 | |||
618 | static void gatom_click(t_gatom *x, | ||
619 | t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, | ||
620 | t_floatarg alt) | ||
621 | { | ||
622 | if (x->a_text.te_width == 1) | ||
623 | { | ||
624 | if (x->a_atom.a_type == A_FLOAT) | ||
625 | gatom_float(x, (x->a_atom.a_w.w_float == 0)); | ||
626 | } | ||
627 | else | ||
628 | { | ||
629 | if (alt) | ||
630 | { | ||
631 | if (x->a_atom.a_type != A_FLOAT) return; | ||
632 | if (x->a_atom.a_w.w_float != 0) | ||
633 | { | ||
634 | x->a_toggle = x->a_atom.a_w.w_float; | ||
635 | gatom_float(x, 0); | ||
636 | return; | ||
637 | } | ||
638 | else gatom_float(x, x->a_toggle); | ||
639 | } | ||
640 | x->a_shift = shift; | ||
641 | x->a_buf[0] = 0; | ||
642 | glist_grab(x->a_glist, &x->a_text.te_g, gatom_motion, gatom_key, | ||
643 | xpos, ypos); | ||
644 | } | ||
645 | } | ||
646 | |||
647 | /* message back from dialog window */ | ||
648 | static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv) | ||
649 | { | ||
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)); | ||
657 | |||
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) | ||
662 | { | ||
663 | canvas_deletelinesforio(x->a_glist, &x->a_text, | ||
664 | x->a_text.te_inlet, 0); | ||
665 | inlet_free(x->a_text.te_inlet); | ||
666 | } | ||
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) | ||
670 | { | ||
671 | canvas_deletelinesforio(x->a_glist, &x->a_text, | ||
672 | 0, x->a_text.te_outlet); | ||
673 | outlet_free(x->a_text.te_outlet); | ||
674 | } | ||
675 | if (draglo >= draghi) | ||
676 | draglo = draghi = 0; | ||
677 | x->a_draglo = draglo; | ||
678 | x->a_draghi = draghi; | ||
679 | if (width < 0) | ||
680 | width = 4; | ||
681 | else if (width > 80) | ||
682 | width = 80; | ||
683 | x->a_text.te_width = width; | ||
684 | x->a_wherelabel = ((int)wherelabel & 3); | ||
685 | x->a_label = label; | ||
686 | if (*x->a_symfrom->s_name) | ||
687 | pd_unbind(&x->a_text.te_pd, | ||
688 | canvas_realizedollar(x->a_glist, x->a_symfrom)); | ||
689 | x->a_symfrom = symfrom; | ||
690 | if (*x->a_symfrom->s_name) | ||
691 | pd_bind(&x->a_text.te_pd, | ||
692 | canvas_realizedollar(x->a_glist, x->a_symfrom)); | ||
693 | x->a_symto = symto; | ||
694 | x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto); | ||
695 | gobj_vis(&x->a_text.te_g, x->a_glist, 1); | ||
696 | |||
697 | /* glist_retext(x->a_glist, &x->a_text); */ | ||
698 | } | ||
699 | |||
700 | /* ---------------- gatom-specific widget functions --------------- */ | ||
701 | static void gatom_getwherelabel(t_gatom *x, t_glist *glist, int *xp, int *yp) | ||
702 | { | ||
703 | int x1, y1, x2, y2, width, height; | ||
704 | text_getrect(&x->a_text.te_g, glist, &x1, &y1, &x2, &y2); | ||
705 | width = x2 - x1; | ||
706 | height = y2 - y1; | ||
707 | if (x->a_wherelabel == ATOM_LABELLEFT) | ||
708 | { | ||
709 | *xp = x1 - 3 - | ||
710 | strlen(canvas_realizedollar(x->a_glist, x->a_label)->s_name) * | ||
711 | sys_fontwidth(glist_getfont(glist)); | ||
712 | *yp = y1 + 2; | ||
713 | } | ||
714 | else if (x->a_wherelabel == ATOM_LABELRIGHT) | ||
715 | { | ||
716 | *xp = x2 + 2; | ||
717 | *yp = y1 + 2; | ||
718 | } | ||
719 | else if (x->a_wherelabel == ATOM_LABELUP) | ||
720 | { | ||
721 | *xp = x1 - 1; | ||
722 | *yp = y1 - 1 - sys_fontheight(glist_getfont(glist));; | ||
723 | } | ||
724 | else | ||
725 | { | ||
726 | *xp = x1 - 1; | ||
727 | *yp = y2 + 3; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | static void gatom_displace(t_gobj *z, t_glist *glist, | ||
732 | int dx, int dy) | ||
733 | { | ||
734 | t_gatom *x = (t_gatom*)z; | ||
735 | text_displace(z, glist, dx, dy); | ||
736 | sys_vgui(".x%x.c move %x.l %d %d\n", glist_getcanvas(glist), | ||
737 | x, dx, dy); | ||
738 | } | ||
739 | |||
740 | static void gatom_vis(t_gobj *z, t_glist *glist, int vis) | ||
741 | { | ||
742 | t_gatom *x = (t_gatom*)z; | ||
743 | text_vis(z, glist, vis); | ||
744 | if (*x->a_label->s_name) | ||
745 | { | ||
746 | if (vis) | ||
747 | { | ||
748 | int x1, y1; | ||
749 | gatom_getwherelabel(x, glist, &x1, &y1); | ||
750 | sys_vgui("pdtk_text_new .x%x.c %x.l %f %f {%s} %d %s\n", | ||
751 | glist_getcanvas(glist), x, | ||
752 | (double)x1, (double)y1, | ||
753 | canvas_realizedollar(x->a_glist, x->a_label)->s_name, | ||
754 | sys_hostfontsize(glist_getfont(glist)), | ||
755 | "black"); | ||
756 | } | ||
757 | else sys_vgui(".x%x.c delete %x.l\n", glist_getcanvas(glist), x); | ||
758 | } | ||
759 | } | ||
760 | |||
761 | void canvas_atom(t_glist *gl, t_atomtype type, | ||
762 | t_symbol *s, int argc, t_atom *argv) | ||
763 | { | ||
764 | t_gatom *x = (t_gatom *)pd_new(gatom_class); | ||
765 | t_atom at; | ||
766 | x->a_text.te_width = 0; /* don't know it yet. */ | ||
767 | x->a_text.te_type = T_ATOM; | ||
768 | x->a_text.te_binbuf = binbuf_new(); | ||
769 | x->a_glist = gl; | ||
770 | x->a_atom.a_type = type; | ||
771 | x->a_toggle = 1; | ||
772 | x->a_draglo = 0; | ||
773 | x->a_draghi = 0; | ||
774 | x->a_wherelabel = 0; | ||
775 | x->a_label = &s_; | ||
776 | x->a_symfrom = &s_; | ||
777 | x->a_symto = x->a_expanded_to = &s_; | ||
778 | if (type == A_FLOAT) | ||
779 | { | ||
780 | x->a_atom.a_w.w_float = 0; | ||
781 | x->a_text.te_width = 5; | ||
782 | SETFLOAT(&at, 0); | ||
783 | } | ||
784 | else | ||
785 | { | ||
786 | x->a_atom.a_w.w_symbol = &s_symbol; | ||
787 | x->a_text.te_width = 10; | ||
788 | SETSYMBOL(&at, &s_symbol); | ||
789 | } | ||
790 | binbuf_add(x->a_text.te_binbuf, 1, &at); | ||
791 | if (argc > 1) | ||
792 | /* create from file. x, y, width, low-range, high-range, flags, | ||
793 | label, receive-name, send-name */ | ||
794 | { | ||
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)); | ||
810 | |||
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); | ||
819 | } | ||
820 | else | ||
821 | { | ||
822 | int xpix, ypix; | ||
823 | outlet_new(&x->a_text, | ||
824 | x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol); | ||
825 | inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0); | ||
826 | pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); | ||
827 | glist_noselect(gl); | ||
828 | glist_getnextxy(gl, &xpix, &ypix); | ||
829 | x->a_text.te_xpix = xpix; | ||
830 | x->a_text.te_ypix = ypix; | ||
831 | glist_add(gl, &x->a_text.te_g); | ||
832 | glist_noselect(gl); | ||
833 | glist_select(gl, &x->a_text.te_g); | ||
834 | canvas_startmotion(glist_getcanvas(gl)); | ||
835 | } | ||
836 | } | ||
837 | |||
838 | void canvas_floatatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
839 | { | ||
840 | canvas_atom(gl, A_FLOAT, s, argc, argv); | ||
841 | } | ||
842 | |||
843 | void canvas_symbolatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
844 | { | ||
845 | canvas_atom(gl, A_SYMBOL, s, argc, argv); | ||
846 | } | ||
847 | |||
848 | static void gatom_free(t_gatom *x) | ||
849 | { | ||
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); | ||
854 | } | ||
855 | |||
856 | static void gatom_properties(t_gobj *z, t_glist *owner) | ||
857 | { | ||
858 | t_gatom *x = (t_gatom *)z; | ||
859 | char buf[200]; | ||
860 | sprintf(buf, "pdtk_gatom_dialog %%s %d %g %g %d %s %s %s\n", | ||
861 | x->a_text.te_width, x->a_draglo, x->a_draghi, | ||
862 | x->a_wherelabel, gatom_escapit(x->a_label)->s_name, | ||
863 | gatom_escapit(x->a_symfrom)->s_name, | ||
864 | gatom_escapit(x->a_symto)->s_name); | ||
865 | gfxstub_new(&x->a_text.te_pd, x, buf); | ||
866 | } | ||
867 | |||
868 | |||
869 | /* -------------------- widget behavior for text objects ------------ */ | ||
870 | |||
871 | static void text_getrect(t_gobj *z, t_glist *glist, | ||
872 | int *xp1, int *yp1, int *xp2, int *yp2) | ||
873 | { | ||
874 | t_text *x = (t_text *)z; | ||
875 | int width, height, iscomment = (x->te_type == T_TEXT); | ||
876 | float x1, y1, x2, y2; | ||
877 | |||
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. */ | ||
880 | |||
881 | if (x->te_type == T_ATOM && x->te_width > 0) | ||
882 | { | ||
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 */ | ||
887 | } | ||
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? */ | ||
895 | |||
896 | else if (glist->gl_editor && glist->gl_editor->e_rtext) | ||
897 | { | ||
898 | t_rtext *y = glist_findrtext(glist, x); | ||
899 | width = rtext_width(y); | ||
900 | height = rtext_height(y) - (iscomment << 1); | ||
901 | } | ||
902 | else width = height = 10; | ||
903 | x1 = text_xpix(x, glist); | ||
904 | y1 = text_ypix(x, glist); | ||
905 | x2 = x1 + width; | ||
906 | y2 = y1 + height; | ||
907 | y1 += iscomment; | ||
908 | *xp1 = x1; | ||
909 | *yp1 = y1; | ||
910 | *xp2 = x2; | ||
911 | *yp2 = y2; | ||
912 | } | ||
913 | |||
914 | static void text_displace(t_gobj *z, t_glist *glist, | ||
915 | int dx, int dy) | ||
916 | { | ||
917 | t_text *x = (t_text *)z; | ||
918 | x->te_xpix += dx; | ||
919 | x->te_ypix += dy; | ||
920 | if (glist_isvisible(glist)) | ||
921 | { | ||
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); | ||
927 | } | ||
928 | } | ||
929 | |||
930 | static void text_select(t_gobj *z, t_glist *glist, int state) | ||
931 | { | ||
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")); | ||
938 | } | ||
939 | |||
940 | static void text_activate(t_gobj *z, t_glist *glist, int state) | ||
941 | { | ||
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); | ||
945 | } | ||
946 | |||
947 | static void text_delete(t_gobj *z, t_glist *glist) | ||
948 | { | ||
949 | t_text *x = (t_text *)z; | ||
950 | canvas_deletelinesfor(glist, x); | ||
951 | } | ||
952 | |||
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) | ||
956 | { | ||
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))); | ||
960 | } | ||
961 | |||
962 | static void text_vis(t_gobj *z, t_glist *glist, int vis) | ||
963 | { | ||
964 | t_text *x = (t_text *)z; | ||
965 | if (vis) | ||
966 | { | ||
967 | if (text_shouldvis(x, glist)) | ||
968 | { | ||
969 | t_rtext *y = glist_findrtext(glist, x); | ||
970 | if (x->te_type == T_ATOM) | ||
971 | glist_retext(glist, x); | ||
972 | text_drawborder(x, glist, rtext_gettag(y), | ||
973 | rtext_width(y), rtext_height(y), 1); | ||
974 | rtext_draw(y); | ||
975 | } | ||
976 | } | ||
977 | else | ||
978 | { | ||
979 | t_rtext *y = glist_findrtext(glist, x); | ||
980 | if (text_shouldvis(x, glist)) | ||
981 | { | ||
982 | text_eraseborder(x, glist, rtext_gettag(y)); | ||
983 | rtext_erase(y); | ||
984 | } | ||
985 | } | ||
986 | } | ||
987 | |||
988 | static int text_click(t_gobj *z, struct _glist *glist, | ||
989 | int xpix, int ypix, int shift, int alt, int dbl, int doit) | ||
990 | { | ||
991 | t_text *x = (t_text *)z; | ||
992 | if (x->te_type == T_OBJECT) | ||
993 | { | ||
994 | t_symbol *clicksym = gensym("click"); | ||
995 | if (zgetfn(&x->te_pd, clicksym)) | ||
996 | { | ||
997 | if (doit) | ||
998 | pd_vmess(&x->te_pd, clicksym, "fffff", | ||
999 | (double)xpix, (double)ypix, | ||
1000 | (double)shift, 0, (double)alt); | ||
1001 | return (1); | ||
1002 | } | ||
1003 | else return (0); | ||
1004 | } | ||
1005 | else if (x->te_type == T_ATOM) | ||
1006 | { | ||
1007 | if (doit) | ||
1008 | gatom_click((t_gatom *)x, (t_floatarg)xpix, (t_floatarg)ypix, | ||
1009 | (t_floatarg)shift, 0, (t_floatarg)alt); | ||
1010 | return (1); | ||
1011 | } | ||
1012 | else if (x->te_type == T_MESSAGE) | ||
1013 | { | ||
1014 | if (doit) | ||
1015 | message_click((t_message *)x, (t_floatarg)xpix, (t_floatarg)ypix, | ||
1016 | (t_floatarg)shift, 0, (t_floatarg)alt); | ||
1017 | return (1); | ||
1018 | } | ||
1019 | else return (0); | ||
1020 | } | ||
1021 | |||
1022 | void text_save(t_gobj *z, t_binbuf *b) | ||
1023 | { | ||
1024 | t_text *x = (t_text *)z; | ||
1025 | if (x->te_type == T_OBJECT) | ||
1026 | { | ||
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)))) | ||
1033 | { | ||
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); | ||
1037 | } | ||
1038 | else /* otherwise just save the text */ | ||
1039 | { | ||
1040 | binbuf_addv(b, "ssii", gensym("#X"), gensym("obj"), | ||
1041 | (t_int)x->te_xpix, (t_int)x->te_ypix); | ||
1042 | } | ||
1043 | binbuf_addbinbuf(b, x->te_binbuf); | ||
1044 | binbuf_addv(b, ";"); | ||
1045 | } | ||
1046 | else if (x->te_type == T_MESSAGE) | ||
1047 | { | ||
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, ";"); | ||
1052 | } | ||
1053 | else if (x->te_type == T_ATOM) | ||
1054 | { | ||
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, ";"); | ||
1068 | } | ||
1069 | else | ||
1070 | { | ||
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, ";"); | ||
1075 | } | ||
1076 | } | ||
1077 | |||
1078 | /* this one is for everyone but "gatoms"; it's imposed in m_class.c */ | ||
1079 | t_widgetbehavior text_widgetbehavior = | ||
1080 | { | ||
1081 | text_getrect, | ||
1082 | text_displace, | ||
1083 | text_select, | ||
1084 | text_activate, | ||
1085 | text_delete, | ||
1086 | text_vis, | ||
1087 | text_click, | ||
1088 | }; | ||
1089 | |||
1090 | static t_widgetbehavior gatom_widgetbehavior = | ||
1091 | { | ||
1092 | text_getrect, | ||
1093 | gatom_displace, | ||
1094 | text_select, | ||
1095 | text_activate, | ||
1096 | text_delete, | ||
1097 | gatom_vis, | ||
1098 | text_click, | ||
1099 | }; | ||
1100 | |||
1101 | /* -------------------- the "text" class ------------ */ | ||
1102 | |||
1103 | #ifdef MACOSX | ||
1104 | #define EXTRAPIX 2 | ||
1105 | #else | ||
1106 | #define EXTRAPIX 1 | ||
1107 | #endif | ||
1108 | |||
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) | ||
1112 | { | ||
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++) | ||
1116 | { | ||
1117 | int onset = x1 + (width - IOWIDTH) * i / nplus; | ||
1118 | if (firsttime) | ||
1119 | sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %so%d\n", | ||
1120 | glist_getcanvas(glist), | ||
1121 | onset, y2 - 1, | ||
1122 | onset + IOWIDTH, y2, | ||
1123 | tag, i); | ||
1124 | else | ||
1125 | sys_vgui(".x%x.c coords %so%d %d %d %d %d\n", | ||
1126 | glist_getcanvas(glist), tag, i, | ||
1127 | onset, y2 - 1, | ||
1128 | onset + IOWIDTH, y2); | ||
1129 | } | ||
1130 | n = obj_ninlets(ob); | ||
1131 | nplus = (n == 1 ? 1 : n-1); | ||
1132 | for (i = 0; i < n; i++) | ||
1133 | { | ||
1134 | int onset = x1 + (width - IOWIDTH) * i / nplus; | ||
1135 | if (firsttime) | ||
1136 | sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %si%d\n", | ||
1137 | glist_getcanvas(glist), | ||
1138 | onset, y1, | ||
1139 | onset + IOWIDTH, y1 + EXTRAPIX, | ||
1140 | tag, i); | ||
1141 | else | ||
1142 | sys_vgui(".x%x.c coords %si%d %d %d %d %d\n", | ||
1143 | glist_getcanvas(glist), tag, i, | ||
1144 | onset, y1, | ||
1145 | onset + IOWIDTH, y1 + EXTRAPIX); | ||
1146 | } | ||
1147 | } | ||
1148 | |||
1149 | void text_drawborder(t_text *x, t_glist *glist, | ||
1150 | char *tag, int width2, int height2, int firsttime) | ||
1151 | { | ||
1152 | t_object *ob; | ||
1153 | int x1, y1, x2, y2, width, height; | ||
1154 | text_getrect(&x->te_g, glist, &x1, &y1, &x2, &y2); | ||
1155 | width = x2 - x1; | ||
1156 | height = y2 - y1; | ||
1157 | if (x->te_type == T_OBJECT) | ||
1158 | { | ||
1159 | if (firsttime) | ||
1160 | sys_vgui(".x%x.c create line\ | ||
1161 | %d %d %d %d %d %d %d %d %d %d -tags %sR\n", | ||
1162 | glist_getcanvas(glist), | ||
1163 | x1, y1, x2, y1, x2, y2, x1, y2, x1, y1, tag); | ||
1164 | else | ||
1165 | sys_vgui(".x%x.c coords %sR\ | ||
1166 | %d %d %d %d %d %d %d %d %d %d\n", | ||
1167 | glist_getcanvas(glist), tag, | ||
1168 | x1, y1, x2, y1, x2, y2, x1, y2, x1, y1); | ||
1169 | } | ||
1170 | else if (x->te_type == T_MESSAGE) | ||
1171 | { | ||
1172 | if (firsttime) | ||
1173 | sys_vgui(".x%x.c create line\ | ||
1174 | %d %d %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n", | ||
1175 | glist_getcanvas(glist), | ||
1176 | x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2, | ||
1177 | x1, y2, x1, y1, | ||
1178 | tag); | ||
1179 | else | ||
1180 | sys_vgui(".x%x.c coords %sR\ | ||
1181 | %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", | ||
1182 | glist_getcanvas(glist), tag, | ||
1183 | x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2, | ||
1184 | x1, y2, x1, y1); | ||
1185 | } | ||
1186 | else if (x->te_type == T_ATOM) | ||
1187 | { | ||
1188 | if (firsttime) | ||
1189 | sys_vgui(".x%x.c create line\ | ||
1190 | %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n", | ||
1191 | glist_getcanvas(glist), | ||
1192 | x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1, | ||
1193 | tag); | ||
1194 | else | ||
1195 | sys_vgui(".x%x.c coords %sR\ | ||
1196 | %d %d %d %d %d %d %d %d %d %d %d %d\n", | ||
1197 | glist_getcanvas(glist), tag, | ||
1198 | x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1); | ||
1199 | } | ||
1200 | /* draw inlets/outlets */ | ||
1201 | |||
1202 | if (ob = pd_checkobject(&x->te_pd)) | ||
1203 | glist_drawiofor(glist, ob, firsttime, tag, x1, y1, x2, y2); | ||
1204 | } | ||
1205 | |||
1206 | void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag) | ||
1207 | { | ||
1208 | int i, n; | ||
1209 | n = obj_noutlets(ob); | ||
1210 | for (i = 0; i < n; i++) | ||
1211 | sys_vgui(".x%x.c delete %so%d\n", | ||
1212 | glist_getcanvas(glist), tag, i); | ||
1213 | n = obj_ninlets(ob); | ||
1214 | for (i = 0; i < n; i++) | ||
1215 | sys_vgui(".x%x.c delete %si%d\n", | ||
1216 | glist_getcanvas(glist), tag, i); | ||
1217 | } | ||
1218 | |||
1219 | void text_eraseborder(t_text *x, t_glist *glist, char *tag) | ||
1220 | { | ||
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); | ||
1225 | } | ||
1226 | |||
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. */ | ||
1229 | |||
1230 | void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize) | ||
1231 | { | ||
1232 | if (x->te_type == T_OBJECT) | ||
1233 | { | ||
1234 | t_binbuf *b = binbuf_new(); | ||
1235 | int natom1, natom2; | ||
1236 | t_atom *vec1, *vec2; | ||
1237 | binbuf_text(b, buf, bufsize); | ||
1238 | natom1 = binbuf_getnatom(x->te_binbuf); | ||
1239 | vec1 = binbuf_getvec(x->te_binbuf); | ||
1240 | natom2 = binbuf_getnatom(b); | ||
1241 | vec2 = binbuf_getvec(b); | ||
1242 | /* special case: if pd args change just pass the message on. */ | ||
1243 | if (natom1 >= 1 && natom2 >= 1 && vec1[0].a_type == A_SYMBOL | ||
1244 | && !strcmp(vec1[0].a_w.w_symbol->s_name, "pd") && | ||
1245 | vec2[0].a_type == A_SYMBOL | ||
1246 | && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd")) | ||
1247 | { | ||
1248 | typedmess(&x->te_pd, gensym("rename"), natom2-1, vec2+1); | ||
1249 | binbuf_free(x->te_binbuf); | ||
1250 | x->te_binbuf = b; | ||
1251 | } | ||
1252 | else /* normally, just destroy the old one and make a new one. */ | ||
1253 | { | ||
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)); | ||
1261 | } | ||
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(); | ||
1267 | } | ||
1268 | else binbuf_text(x->te_binbuf, buf, bufsize); | ||
1269 | } | ||
1270 | |||
1271 | void g_text_setup(void) | ||
1272 | { | ||
1273 | text_class = class_new(gensym("text"), 0, 0, sizeof(t_text), | ||
1274 | CLASS_NOINLET | CLASS_PATCHABLE, 0); | ||
1275 | |||
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); | ||
1283 | |||
1284 | class_addmethod(message_class, (t_method)message_click, gensym("click"), | ||
1285 | A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); | ||
1286 | class_addmethod(message_class, (t_method)message_set, gensym("set"), | ||
1287 | A_GIMME, 0); | ||
1288 | class_addmethod(message_class, (t_method)message_add, gensym("add"), | ||
1289 | A_GIMME, 0); | ||
1290 | class_addmethod(message_class, (t_method)message_add2, gensym("add2"), | ||
1291 | A_GIMME, 0); | ||
1292 | |||
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); | ||
1300 | |||
1301 | gatom_class = class_new(gensym("gatom"), 0, (t_method)gatom_free, | ||
1302 | sizeof(t_gatom), CLASS_NOINLET | CLASS_PATCHABLE, 0); | ||
1303 | class_addbang(gatom_class, gatom_bang); | ||
1304 | class_addfloat(gatom_class, gatom_float); | ||
1305 | class_addsymbol(gatom_class, gatom_symbol); | ||
1306 | class_addmethod(gatom_class, (t_method)gatom_set, gensym("set"), | ||
1307 | A_GIMME, 0); | ||
1308 | class_addmethod(gatom_class, (t_method)gatom_click, gensym("click"), | ||
1309 | A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); | ||
1310 | class_addmethod(gatom_class, (t_method)gatom_param, gensym("param"), | ||
1311 | A_GIMME, 0); | ||
1312 | class_setwidget(gatom_class, &gatom_widgetbehavior); | ||
1313 | class_setpropertiesfn(gatom_class, gatom_properties); | ||
1314 | } | ||
1315 | |||
1316 | |||
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. */ | ||
1320 | |||
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 */ | ||
1324 | |||
1325 | #include <stdlib.h> | ||
1326 | #include "m_pd.h" | ||
1327 | #include "m_imp.h" | ||
1328 | #include "s_stuff.h" | ||
1329 | #include "t_tk.h" | ||
1330 | #include "g_canvas.h" | ||
1331 | #include <stdio.h> | ||
1332 | #include <string.h> | ||
1333 | #include <math.h> | ||
1334 | |||
1335 | static t_class *text_class; | ||
1336 | static t_class *message_class; | ||
1337 | static t_class *gatom_class; | ||
1338 | static void text_vis(t_gobj *z, t_glist *glist, int vis); | ||
1339 | static void text_displace(t_gobj *z, t_glist *glist, | ||
1340 | int dx, int dy); | ||
1341 | static void text_getrect(t_gobj *z, t_glist *glist, | ||
1342 | int *xp1, int *yp1, int *xp2, int *yp2); | ||
1343 | |||
1344 | void canvas_startmotion(t_canvas *x); | ||
1345 | t_widgetbehavior text_widgetbehavior; | ||
1346 | |||
1347 | /* ----------------- the "text" object. ------------------ */ | ||
1348 | |||
1349 | /* add a "text" object (comment) to a glist. While this one goes for any glist, | ||
1350 | the other 3 below are for canvases only. (why?) This is called | ||
1351 | without args if invoked from the GUI; otherwise at least x and y | ||
1352 | are provided. */ | ||
1353 | |||
1354 | void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1355 | { | ||
1356 | t_text *x = (t_text *)pd_new(text_class); | ||
1357 | t_atom at; | ||
1358 | x->te_width = 0; /* don't know it yet. */ | ||
1359 | x->te_type = T_TEXT; | ||
1360 | x->te_binbuf = binbuf_new(); | ||
1361 | if (argc > 1) | ||
1362 | { | ||
1363 | x->te_xpix = atom_getfloatarg(0, argc, argv); | ||
1364 | x->te_ypix = atom_getfloatarg(1, argc, argv); | ||
1365 | if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2); | ||
1366 | else | ||
1367 | { | ||
1368 | SETSYMBOL(&at, gensym("comment")); | ||
1369 | binbuf_restore(x->te_binbuf, 1, &at); | ||
1370 | } | ||
1371 | glist_add(gl, &x->te_g); | ||
1372 | } | ||
1373 | else | ||
1374 | { | ||
1375 | int xpix, ypix; | ||
1376 | pd_vmess((t_pd *)glist_getcanvas(gl), gensym("editmode"), "i", 1); | ||
1377 | SETSYMBOL(&at, gensym("comment")); | ||
1378 | glist_noselect(gl); | ||
1379 | glist_getnextxy(gl, &xpix, &ypix); | ||
1380 | x->te_xpix = glist_pixelstox(gl, xpix-3); | ||
1381 | x->te_ypix = glist_pixelstoy(gl, ypix-3); | ||
1382 | binbuf_restore(x->te_binbuf, 1, &at); | ||
1383 | glist_add(gl, &x->te_g); | ||
1384 | glist_noselect(gl); | ||
1385 | glist_select(gl, &x->te_g); | ||
1386 | /* it would be nice to "activate" here, but then the second, | ||
1387 | "put-me-down" click changes the text selection, which is quite | ||
1388 | irritating, so I took this back out. It's OK in messages | ||
1389 | and objects though since there's no text in them at menu | ||
1390 | creation. */ | ||
1391 | /* gobj_activate(&x->te_g, gl, 1); */ | ||
1392 | canvas_startmotion(glist_getcanvas(gl)); | ||
1393 | } | ||
1394 | } | ||
1395 | |||
1396 | /* ----------------- the "object" object. ------------------ */ | ||
1397 | |||
1398 | extern t_pd *newest; | ||
1399 | void canvas_getargs(int *argcp, t_atom **argvp); | ||
1400 | |||
1401 | static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected, | ||
1402 | t_binbuf *b) | ||
1403 | { | ||
1404 | t_text *x; | ||
1405 | int argc; | ||
1406 | t_atom *argv; | ||
1407 | newest = 0; | ||
1408 | canvas_setcurrent((t_canvas *)gl); | ||
1409 | canvas_getargs(&argc, &argv); | ||
1410 | binbuf_eval(b, &pd_objectmaker, argc, argv); | ||
1411 | if (binbuf_getnatom(b)) | ||
1412 | { | ||
1413 | if (!newest) | ||
1414 | { | ||
1415 | binbuf_print(b); | ||
1416 | post("... couldn't create"); | ||
1417 | x = 0; | ||
1418 | } | ||
1419 | else if (!(x = pd_checkobject(newest))) | ||
1420 | { | ||
1421 | binbuf_print(b); | ||
1422 | post("... didn't return a patchable object"); | ||
1423 | } | ||
1424 | } | ||
1425 | else x = 0; | ||
1426 | if (!x) | ||
1427 | { | ||
1428 | |||
1429 | /* LATER make the color reflect this */ | ||
1430 | x = (t_text *)pd_new(text_class); | ||
1431 | } | ||
1432 | x->te_binbuf = b; | ||
1433 | x->te_xpix = xpix; | ||
1434 | x->te_ypix = ypix; | ||
1435 | x->te_width = 0; | ||
1436 | x->te_type = T_OBJECT; | ||
1437 | glist_add(gl, &x->te_g); | ||
1438 | if (selected) | ||
1439 | { | ||
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); | ||
1443 | } | ||
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); | ||
1449 | } | ||
1450 | |||
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. */ | ||
1454 | |||
1455 | void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1456 | { | ||
1457 | t_text *x; | ||
1458 | if (argc >= 2) | ||
1459 | { | ||
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); | ||
1464 | } | ||
1465 | else | ||
1466 | { | ||
1467 | t_binbuf *b = binbuf_new(); | ||
1468 | int xpix, ypix; | ||
1469 | pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); | ||
1470 | glist_noselect(gl); | ||
1471 | glist_getnextxy(gl, &xpix, &ypix); | ||
1472 | canvas_objtext(gl, xpix, ypix, 1, b); | ||
1473 | canvas_startmotion(glist_getcanvas(gl)); | ||
1474 | } | ||
1475 | } | ||
1476 | |||
1477 | /* make an object box for an object that's already there. */ | ||
1478 | |||
1479 | /* iemlib */ | ||
1480 | void canvas_iemguis(t_glist *gl, t_symbol *guiobjname) | ||
1481 | { | ||
1482 | t_atom at; | ||
1483 | t_binbuf *b = binbuf_new(); | ||
1484 | int xpix, ypix; | ||
1485 | |||
1486 | pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); | ||
1487 | glist_noselect(gl); | ||
1488 | SETSYMBOL(&at, guiobjname); | ||
1489 | binbuf_restore(b, 1, &at); | ||
1490 | glist_getnextxy(gl, &xpix, &ypix); | ||
1491 | canvas_objtext(gl, xpix, ypix, 1, b); | ||
1492 | canvas_startmotion(glist_getcanvas(gl)); | ||
1493 | } | ||
1494 | |||
1495 | void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1496 | { | ||
1497 | canvas_iemguis(gl, gensym("bng")); | ||
1498 | } | ||
1499 | |||
1500 | void canvas_toggle(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1501 | { | ||
1502 | canvas_iemguis(gl, gensym("tgl")); | ||
1503 | } | ||
1504 | |||
1505 | void canvas_vslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1506 | { | ||
1507 | canvas_iemguis(gl, gensym("vsl")); | ||
1508 | } | ||
1509 | |||
1510 | void canvas_hslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1511 | { | ||
1512 | canvas_iemguis(gl, gensym("hsl")); | ||
1513 | } | ||
1514 | |||
1515 | void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1516 | { | ||
1517 | canvas_iemguis(gl, gensym("hdl")); | ||
1518 | } | ||
1519 | |||
1520 | void canvas_vdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1521 | { | ||
1522 | canvas_iemguis(gl, gensym("vdl")); | ||
1523 | } | ||
1524 | |||
1525 | void canvas_hradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1526 | { | ||
1527 | canvas_iemguis(gl, gensym("hradio")); | ||
1528 | } | ||
1529 | |||
1530 | void canvas_vradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1531 | { | ||
1532 | canvas_iemguis(gl, gensym("vradio")); | ||
1533 | } | ||
1534 | |||
1535 | void canvas_vumeter(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1536 | { | ||
1537 | canvas_iemguis(gl, gensym("vu")); | ||
1538 | } | ||
1539 | |||
1540 | void canvas_mycnv(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1541 | { | ||
1542 | canvas_iemguis(gl, gensym("cnv")); | ||
1543 | } | ||
1544 | |||
1545 | void canvas_numbox(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1546 | { | ||
1547 | canvas_iemguis(gl, gensym("nbx")); | ||
1548 | } | ||
1549 | |||
1550 | /* iemlib */ | ||
1551 | |||
1552 | void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv) | ||
1553 | { | ||
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); | ||
1561 | } | ||
1562 | |||
1563 | /* ---------------------- the "message" text item ------------------------ */ | ||
1564 | |||
1565 | typedef struct _messresponder | ||
1566 | { | ||
1567 | t_pd mr_pd; | ||
1568 | t_outlet *mr_outlet; | ||
1569 | } t_messresponder; | ||
1570 | |||
1571 | typedef struct _message | ||
1572 | { | ||
1573 | t_text m_text; | ||
1574 | t_messresponder m_messresponder; | ||
1575 | t_glist *m_glist; | ||
1576 | t_clock *m_clock; | ||
1577 | } t_message; | ||
1578 | |||
1579 | static t_class *message_class, *messresponder_class; | ||
1580 | |||
1581 | static void messresponder_bang(t_messresponder *x) | ||
1582 | { | ||
1583 | outlet_bang(x->mr_outlet); | ||
1584 | } | ||
1585 | |||
1586 | static void messresponder_float(t_messresponder *x, t_float f) | ||
1587 | { | ||
1588 | outlet_float(x->mr_outlet, f); | ||
1589 | } | ||
1590 | |||
1591 | static void messresponder_symbol(t_messresponder *x, t_symbol *s) | ||
1592 | { | ||
1593 | outlet_symbol(x->mr_outlet, s); | ||
1594 | } | ||
1595 | |||
1596 | static void messresponder_list(t_messresponder *x, | ||
1597 | t_symbol *s, int argc, t_atom *argv) | ||
1598 | { | ||
1599 | outlet_list(x->mr_outlet, s, argc, argv); | ||
1600 | } | ||
1601 | |||
1602 | static void messresponder_anything(t_messresponder *x, | ||
1603 | t_symbol *s, int argc, t_atom *argv) | ||
1604 | { | ||
1605 | outlet_anything(x->mr_outlet, s, argc, argv); | ||
1606 | } | ||
1607 | |||
1608 | static void message_bang(t_message *x) | ||
1609 | { | ||
1610 | binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 0, 0); | ||
1611 | } | ||
1612 | |||
1613 | static void message_float(t_message *x, t_float f) | ||
1614 | { | ||
1615 | t_atom at; | ||
1616 | SETFLOAT(&at, f); | ||
1617 | binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at); | ||
1618 | } | ||
1619 | |||
1620 | static void message_symbol(t_message *x, t_symbol *s) | ||
1621 | { | ||
1622 | t_atom at; | ||
1623 | SETSYMBOL(&at, s); | ||
1624 | binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at); | ||
1625 | } | ||
1626 | |||
1627 | static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv) | ||
1628 | { | ||
1629 | binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, argc, argv); | ||
1630 | } | ||
1631 | |||
1632 | static void message_set(t_message *x, t_symbol *s, int argc, t_atom *argv) | ||
1633 | { | ||
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); | ||
1637 | } | ||
1638 | |||
1639 | static void message_add2(t_message *x, t_symbol *s, int argc, t_atom *argv) | ||
1640 | { | ||
1641 | binbuf_add(x->m_text.te_binbuf, argc, argv); | ||
1642 | glist_retext(x->m_glist, &x->m_text); | ||
1643 | } | ||
1644 | |||
1645 | static void message_add(t_message *x, t_symbol *s, int argc, t_atom *argv) | ||
1646 | { | ||
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); | ||
1650 | } | ||
1651 | |||
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) | ||
1655 | { | ||
1656 | message_float(x, 0); | ||
1657 | if (glist_isvisible(x->m_glist)) | ||
1658 | { | ||
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); | ||
1663 | } | ||
1664 | } | ||
1665 | |||
1666 | static void message_tick(t_message *x) | ||
1667 | { | ||
1668 | if (glist_isvisible(x->m_glist)) | ||
1669 | { | ||
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)); | ||
1673 | } | ||
1674 | } | ||
1675 | |||
1676 | static void message_free(t_message *x) | ||
1677 | { | ||
1678 | clock_free(x->m_clock); | ||
1679 | } | ||
1680 | |||
1681 | void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
1682 | { | ||
1683 | t_message *x = (t_message *)pd_new(message_class); | ||
1684 | x->m_messresponder.mr_pd = messresponder_class; | ||
1685 | x->m_messresponder.mr_outlet = outlet_new(&x->m_text, &s_float); | ||
1686 | x->m_text.te_width = 0; /* don't know it yet. */ | ||
1687 | x->m_text.te_type = T_MESSAGE; | ||
1688 | x->m_text.te_binbuf = binbuf_new(); | ||
1689 | x->m_glist = gl; | ||
1690 | x->m_clock = clock_new(x, (t_method)message_tick); | ||
1691 | if (argc > 1) | ||
1692 | { | ||
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); | ||
1697 | } | ||
1698 | else | ||
1699 | { | ||
1700 | int xpix, ypix; | ||
1701 | pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); | ||
1702 | glist_noselect(gl); | ||
1703 | glist_getnextxy(gl, &xpix, &ypix); | ||
1704 | x->m_text.te_xpix = xpix-3; | ||
1705 | x->m_text.te_ypix = ypix-3; | ||
1706 | glist_add(gl, &x->m_text.te_g); | ||
1707 | glist_noselect(gl); | ||
1708 | glist_select(gl, &x->m_text.te_g); | ||
1709 | gobj_activate(&x->m_text.te_g, gl, 1); | ||
1710 | canvas_startmotion(glist_getcanvas(gl)); | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1714 | /* ---------------------- the "atom" text item ------------------------ */ | ||
1715 | |||
1716 | #define ATOMBUFSIZE 40 | ||
1717 | #define ATOM_LABELLEFT 0 | ||
1718 | #define ATOM_LABELRIGHT 1 | ||
1719 | #define ATOM_LABELUP 2 | ||
1720 | #define ATOM_LABELDOWN 3 | ||
1721 | |||
1722 | typedef struct _gatom | ||
1723 | { | ||
1724 | t_text a_text; | ||
1725 | t_atom a_atom; /* this holds the value and the type */ | ||
1726 | t_glist *a_glist; /* owning glist */ | ||
1727 | t_float a_toggle; /* value to toggle to */ | ||
1728 | t_float a_draghi; /* high end of drag range */ | ||
1729 | t_float a_draglo; /* low end of drag range */ | ||
1730 | t_symbol *a_label; /* symbol to show as label next to box */ | ||
1731 | t_symbol *a_symfrom; /* "receive" name -- bind ourselvs to this */ | ||
1732 | t_symbol *a_symto; /* "send" name -- send to this on output */ | ||
1733 | char a_buf[ATOMBUFSIZE];/* string buffer for typing */ | ||
1734 | char a_shift; /* was shift key down when dragging started? */ | ||
1735 | char a_wherelabel; /* 0-3 for left, right, above, below */ | ||
1736 | t_symbol *a_expanded_to; /* a_symto after $0, $1, ... expansion */ | ||
1737 | } t_gatom; | ||
1738 | |||
1739 | /* prepend "-" as necessary to avoid empty strings, so we can | ||
1740 | use them in Pd messages. A more complete solution would be | ||
1741 | to introduce some quoting mechanism; but then we'd be much more | ||
1742 | complicated. */ | ||
1743 | static t_symbol *gatom_escapit(t_symbol *s) | ||
1744 | { | ||
1745 | if (!*s->s_name) | ||
1746 | return (gensym("-")); | ||
1747 | else if (*s->s_name == '-') | ||
1748 | { | ||
1749 | char shmo[100]; | ||
1750 | shmo[0] = '-'; | ||
1751 | strncpy(shmo+1, s->s_name, 99); | ||
1752 | shmo[99] = 0; | ||
1753 | return (gensym(shmo)); | ||
1754 | } | ||
1755 | else return (iemgui_dollar2raute(s)); | ||
1756 | } | ||
1757 | |||
1758 | /* undo previous operation: strip leading "-" if found. */ | ||
1759 | static t_symbol *gatom_unescapit(t_symbol *s) | ||
1760 | { | ||
1761 | if (*s->s_name == '-') | ||
1762 | return (gensym(s->s_name+1)); | ||
1763 | else return (iemgui_raute2dollar(s)); | ||
1764 | } | ||
1765 | |||
1766 | #if 0 /* ??? */ | ||
1767 | /* expand leading $0, $1, etc. in the symbol */ | ||
1768 | static t_symbol *gatom_realizedollar(t_gatom *x, t_symbol *s) | ||
1769 | { | ||
1770 | return (canvas_realizedollar(x->a_glist, s)); | ||
1771 | } | ||
1772 | #endif | ||
1773 | |||
1774 | static void gatom_retext(t_gatom *x, int senditup) | ||
1775 | { | ||
1776 | binbuf_clear(x->a_text.te_binbuf); | ||
1777 | binbuf_add(x->a_text.te_binbuf, 1, &x->a_atom); | ||
1778 | if (senditup) | ||
1779 | glist_retext(x->a_glist, &x->a_text); | ||
1780 | } | ||
1781 | |||
1782 | static void gatom_set(t_gatom *x, t_symbol *s, int argc, t_atom *argv) | ||
1783 | { | ||
1784 | t_atom oldatom = x->a_atom; | ||
1785 | int senditup = 0; | ||
1786 | if (!argc) return; | ||
1787 | if (x->a_atom.a_type == A_FLOAT) | ||
1788 | x->a_atom.a_w.w_float = atom_getfloat(argv), | ||
1789 | senditup = (x->a_atom.a_w.w_float != oldatom.a_w.w_float); | ||
1790 | else if (x->a_atom.a_type == A_SYMBOL) | ||
1791 | x->a_atom.a_w.w_symbol = atom_getsymbol(argv), | ||
1792 | senditup = (x->a_atom.a_w.w_symbol != oldatom.a_w.w_symbol); | ||
1793 | gatom_retext(x, senditup); | ||
1794 | x->a_buf[0] = 0; | ||
1795 | } | ||
1796 | |||
1797 | static void gatom_bang(t_gatom *x) | ||
1798 | { | ||
1799 | if (x->a_atom.a_type == A_FLOAT) | ||
1800 | { | ||
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) | ||
1804 | { | ||
1805 | if (x->a_symto == x->a_symfrom) | ||
1806 | pd_error(x, | ||
1807 | "%s: atom with same send/receive name (infinite loop)", | ||
1808 | x->a_symto->s_name); | ||
1809 | else pd_float(x->a_expanded_to->s_thing, x->a_atom.a_w.w_float); | ||
1810 | } | ||
1811 | } | ||
1812 | else if (x->a_atom.a_type == A_SYMBOL) | ||
1813 | { | ||
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) | ||
1817 | { | ||
1818 | if (x->a_symto == x->a_symfrom) | ||
1819 | pd_error(x, | ||
1820 | "%s: atom with same send/receive name (infinite loop)", | ||
1821 | x->a_symto->s_name); | ||
1822 | else pd_symbol(x->a_expanded_to->s_thing, x->a_atom.a_w.w_symbol); | ||
1823 | } | ||
1824 | } | ||
1825 | } | ||
1826 | |||
1827 | static void gatom_float(t_gatom *x, t_float f) | ||
1828 | { | ||
1829 | t_atom at; | ||
1830 | SETFLOAT(&at, f); | ||
1831 | gatom_set(x, 0, 1, &at); | ||
1832 | gatom_bang(x); | ||
1833 | } | ||
1834 | |||
1835 | static void gatom_clipfloat(t_gatom *x, t_float f) | ||
1836 | { | ||
1837 | if (x->a_draglo != 0 || x->a_draghi != 0) | ||
1838 | { | ||
1839 | if (f < x->a_draglo) | ||
1840 | f = x->a_draglo; | ||
1841 | if (f > x->a_draghi) | ||
1842 | f = x->a_draghi; | ||
1843 | } | ||
1844 | gatom_float(x, f); | ||
1845 | } | ||
1846 | |||
1847 | static void gatom_symbol(t_gatom *x, t_symbol *s) | ||
1848 | { | ||
1849 | t_atom at; | ||
1850 | SETSYMBOL(&at, s); | ||
1851 | gatom_set(x, 0, 1, &at); | ||
1852 | gatom_bang(x); | ||
1853 | } | ||
1854 | |||
1855 | static void gatom_motion(void *z, t_floatarg dx, t_floatarg dy) | ||
1856 | { | ||
1857 | t_gatom *x = (t_gatom *)z; | ||
1858 | if (dy == 0) return; | ||
1859 | if (x->a_atom.a_type == A_FLOAT) | ||
1860 | { | ||
1861 | if (x->a_shift) | ||
1862 | { | ||
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); | ||
1867 | } | ||
1868 | else | ||
1869 | { | ||
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); | ||
1876 | } | ||
1877 | } | ||
1878 | } | ||
1879 | |||
1880 | static void gatom_key(void *z, t_floatarg f) | ||
1881 | { | ||
1882 | t_gatom *x = (t_gatom *)z; | ||
1883 | int c = f; | ||
1884 | int len = strlen(x->a_buf); | ||
1885 | t_atom at; | ||
1886 | char sbuf[ATOMBUFSIZE + 4]; | ||
1887 | if (c == 0) | ||
1888 | { | ||
1889 | /* we're being notified that no more keys will come for this grab */ | ||
1890 | if (x->a_buf[0]) | ||
1891 | gatom_retext(x, 1); | ||
1892 | return; | ||
1893 | } | ||
1894 | else if (c == ' ') return; | ||
1895 | else if (c == '\b') | ||
1896 | { | ||
1897 | if (len > 0) | ||
1898 | x->a_buf[len-1] = 0; | ||
1899 | goto redraw; | ||
1900 | } | ||
1901 | else if (c == '\n') | ||
1902 | { | ||
1903 | if (x->a_atom.a_type == A_FLOAT) | ||
1904 | x->a_atom.a_w.w_float = atof(x->a_buf); | ||
1905 | else if (x->a_atom.a_type == A_SYMBOL) | ||
1906 | x->a_atom.a_w.w_symbol = gensym(x->a_buf); | ||
1907 | else bug("gatom_key"); | ||
1908 | gatom_bang(x); | ||
1909 | gatom_retext(x, 1); | ||
1910 | x->a_buf[0] = 0; | ||
1911 | } | ||
1912 | else if (len < (ATOMBUFSIZE-1)) | ||
1913 | { | ||
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')) | ||
1918 | { | ||
1919 | x->a_buf[len] = c; | ||
1920 | x->a_buf[len+1] = 0; | ||
1921 | goto redraw; | ||
1922 | } | ||
1923 | } | ||
1924 | return; | ||
1925 | redraw: | ||
1926 | /* LATER figure out how to avoid creating all these symbols! */ | ||
1927 | sprintf(sbuf, "%s...", x->a_buf); | ||
1928 | SETSYMBOL(&at, gensym(sbuf)); | ||
1929 | binbuf_clear(x->a_text.te_binbuf); | ||
1930 | binbuf_add(x->a_text.te_binbuf, 1, &at); | ||
1931 | glist_retext(x->a_glist, &x->a_text); | ||
1932 | } | ||
1933 | |||
1934 | static void gatom_click(t_gatom *x, | ||
1935 | t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, | ||
1936 | t_floatarg alt) | ||
1937 | { | ||
1938 | if (x->a_text.te_width == 1) | ||
1939 | { | ||
1940 | if (x->a_atom.a_type == A_FLOAT) | ||
1941 | gatom_float(x, (x->a_atom.a_w.w_float == 0)); | ||
1942 | } | ||
1943 | else | ||
1944 | { | ||
1945 | if (alt) | ||
1946 | { | ||
1947 | if (x->a_atom.a_type != A_FLOAT) return; | ||
1948 | if (x->a_atom.a_w.w_float != 0) | ||
1949 | { | ||
1950 | x->a_toggle = x->a_atom.a_w.w_float; | ||
1951 | gatom_float(x, 0); | ||
1952 | return; | ||
1953 | } | ||
1954 | else gatom_float(x, x->a_toggle); | ||
1955 | } | ||
1956 | x->a_shift = shift; | ||
1957 | x->a_buf[0] = 0; | ||
1958 | glist_grab(x->a_glist, &x->a_text.te_g, gatom_motion, gatom_key, | ||
1959 | xpos, ypos); | ||
1960 | } | ||
1961 | } | ||
1962 | |||
1963 | /* message back from dialog window */ | ||
1964 | static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv) | ||
1965 | { | ||
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)); | ||
1973 | |||
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) | ||
1978 | { | ||
1979 | canvas_deletelinesforio(x->a_glist, &x->a_text, | ||
1980 | x->a_text.te_inlet, 0); | ||
1981 | inlet_free(x->a_text.te_inlet); | ||
1982 | } | ||
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) | ||
1986 | { | ||
1987 | canvas_deletelinesforio(x->a_glist, &x->a_text, | ||
1988 | 0, x->a_text.te_outlet); | ||
1989 | outlet_free(x->a_text.te_outlet); | ||
1990 | } | ||
1991 | if (draglo >= draghi) | ||
1992 | draglo = draghi = 0; | ||
1993 | x->a_draglo = draglo; | ||
1994 | x->a_draghi = draghi; | ||
1995 | if (width < 0) | ||
1996 | width = 4; | ||
1997 | else if (width > 80) | ||
1998 | width = 80; | ||
1999 | x->a_text.te_width = width; | ||
2000 | x->a_wherelabel = ((int)wherelabel & 3); | ||
2001 | x->a_label = label; | ||
2002 | if (*x->a_symfrom->s_name) | ||
2003 | pd_unbind(&x->a_text.te_pd, | ||
2004 | canvas_realizedollar(x->a_glist, x->a_symfrom)); | ||
2005 | x->a_symfrom = symfrom; | ||
2006 | if (*x->a_symfrom->s_name) | ||
2007 | pd_bind(&x->a_text.te_pd, | ||
2008 | canvas_realizedollar(x->a_glist, x->a_symfrom)); | ||
2009 | x->a_symto = symto; | ||
2010 | x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto); | ||
2011 | gobj_vis(&x->a_text.te_g, x->a_glist, 1); | ||
2012 | |||
2013 | /* glist_retext(x->a_glist, &x->a_text); */ | ||
2014 | } | ||
2015 | |||
2016 | /* ---------------- gatom-specific widget functions --------------- */ | ||
2017 | static void gatom_getwherelabel(t_gatom *x, t_glist *glist, int *xp, int *yp) | ||
2018 | { | ||
2019 | int x1, y1, x2, y2, width, height; | ||
2020 | text_getrect(&x->a_text.te_g, glist, &x1, &y1, &x2, &y2); | ||
2021 | width = x2 - x1; | ||
2022 | height = y2 - y1; | ||
2023 | if (x->a_wherelabel == ATOM_LABELLEFT) | ||
2024 | { | ||
2025 | *xp = x1 - 3 - | ||
2026 | strlen(canvas_realizedollar(x->a_glist, x->a_label)->s_name) * | ||
2027 | sys_fontwidth(glist_getfont(glist)); | ||
2028 | *yp = y1 + 2; | ||
2029 | } | ||
2030 | else if (x->a_wherelabel == ATOM_LABELRIGHT) | ||
2031 | { | ||
2032 | *xp = x2 + 2; | ||
2033 | *yp = y1 + 2; | ||
2034 | } | ||
2035 | else if (x->a_wherelabel == ATOM_LABELUP) | ||
2036 | { | ||
2037 | *xp = x1 - 1; | ||
2038 | *yp = y1 - 1 - sys_fontheight(glist_getfont(glist));; | ||
2039 | } | ||
2040 | else | ||
2041 | { | ||
2042 | *xp = x1 - 1; | ||
2043 | *yp = y2 + 3; | ||
2044 | } | ||
2045 | } | ||
2046 | |||
2047 | static void gatom_displace(t_gobj *z, t_glist *glist, | ||
2048 | int dx, int dy) | ||
2049 | { | ||
2050 | t_gatom *x = (t_gatom*)z; | ||
2051 | text_displace(z, glist, dx, dy); | ||
2052 | sys_vgui(".x%x.c move %x.l %d %d\n", glist_getcanvas(glist), | ||
2053 | x, dx, dy); | ||
2054 | } | ||
2055 | |||
2056 | static void gatom_vis(t_gobj *z, t_glist *glist, int vis) | ||
2057 | { | ||
2058 | t_gatom *x = (t_gatom*)z; | ||
2059 | text_vis(z, glist, vis); | ||
2060 | if (*x->a_label->s_name) | ||
2061 | { | ||
2062 | if (vis) | ||
2063 | { | ||
2064 | int x1, y1; | ||
2065 | gatom_getwherelabel(x, glist, &x1, &y1); | ||
2066 | sys_vgui("pdtk_text_new .x%x.c %x.l %f %f {%s} %d %s\n", | ||
2067 | glist_getcanvas(glist), x, | ||
2068 | (double)x1, (double)y1, | ||
2069 | canvas_realizedollar(x->a_glist, x->a_label)->s_name, | ||
2070 | sys_hostfontsize(glist_getfont(glist)), | ||
2071 | "black"); | ||
2072 | } | ||
2073 | else sys_vgui(".x%x.c delete %x.l\n", glist_getcanvas(glist), x); | ||
2074 | } | ||
2075 | } | ||
2076 | |||
2077 | void canvas_atom(t_glist *gl, t_atomtype type, | ||
2078 | t_symbol *s, int argc, t_atom *argv) | ||
2079 | { | ||
2080 | t_gatom *x = (t_gatom *)pd_new(gatom_class); | ||
2081 | t_atom at; | ||
2082 | x->a_text.te_width = 0; /* don't know it yet. */ | ||
2083 | x->a_text.te_type = T_ATOM; | ||
2084 | x->a_text.te_binbuf = binbuf_new(); | ||
2085 | x->a_glist = gl; | ||
2086 | x->a_atom.a_type = type; | ||
2087 | x->a_toggle = 1; | ||
2088 | x->a_draglo = 0; | ||
2089 | x->a_draghi = 0; | ||
2090 | x->a_wherelabel = 0; | ||
2091 | x->a_label = &s_; | ||
2092 | x->a_symfrom = &s_; | ||
2093 | x->a_symto = x->a_expanded_to = &s_; | ||
2094 | if (type == A_FLOAT) | ||
2095 | { | ||
2096 | x->a_atom.a_w.w_float = 0; | ||
2097 | x->a_text.te_width = 5; | ||
2098 | SETFLOAT(&at, 0); | ||
2099 | } | ||
2100 | else | ||
2101 | { | ||
2102 | x->a_atom.a_w.w_symbol = &s_symbol; | ||
2103 | x->a_text.te_width = 10; | ||
2104 | SETSYMBOL(&at, &s_symbol); | ||
2105 | } | ||
2106 | binbuf_add(x->a_text.te_binbuf, 1, &at); | ||
2107 | if (argc > 1) | ||
2108 | /* create from file. x, y, width, low-range, high-range, flags, | ||
2109 | label, receive-name, send-name */ | ||
2110 | { | ||
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)); | ||
2126 | |||
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); | ||
2135 | } | ||
2136 | else | ||
2137 | { | ||
2138 | int xpix, ypix; | ||
2139 | outlet_new(&x->a_text, | ||
2140 | x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol); | ||
2141 | inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0); | ||
2142 | pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); | ||
2143 | glist_noselect(gl); | ||
2144 | glist_getnextxy(gl, &xpix, &ypix); | ||
2145 | x->a_text.te_xpix = xpix; | ||
2146 | x->a_text.te_ypix = ypix; | ||
2147 | glist_add(gl, &x->a_text.te_g); | ||
2148 | glist_noselect(gl); | ||
2149 | glist_select(gl, &x->a_text.te_g); | ||
2150 | canvas_startmotion(glist_getcanvas(gl)); | ||
2151 | } | ||
2152 | } | ||
2153 | |||
2154 | void canvas_floatatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
2155 | { | ||
2156 | canvas_atom(gl, A_FLOAT, s, argc, argv); | ||
2157 | } | ||
2158 | |||
2159 | void canvas_symbolatom(t_glist *gl, t_symbol *s, int argc, t_atom *argv) | ||
2160 | { | ||
2161 | canvas_atom(gl, A_SYMBOL, s, argc, argv); | ||
2162 | } | ||
2163 | |||
2164 | static void gatom_free(t_gatom *x) | ||
2165 | { | ||
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); | ||
2170 | } | ||
2171 | |||
2172 | static void gatom_properties(t_gobj *z, t_glist *owner) | ||
2173 | { | ||
2174 | t_gatom *x = (t_gatom *)z; | ||
2175 | char buf[200]; | ||
2176 | sprintf(buf, "pdtk_gatom_dialog %%s %d %g %g %d %s %s %s\n", | ||
2177 | x->a_text.te_width, x->a_draglo, x->a_draghi, | ||
2178 | x->a_wherelabel, gatom_escapit(x->a_label)->s_name, | ||
2179 | gatom_escapit(x->a_symfrom)->s_name, | ||
2180 | gatom_escapit(x->a_symto)->s_name); | ||
2181 | gfxstub_new(&x->a_text.te_pd, x, buf); | ||
2182 | } | ||
2183 | |||
2184 | |||
2185 | /* -------------------- widget behavior for text objects ------------ */ | ||
2186 | |||
2187 | static void text_getrect(t_gobj *z, t_glist *glist, | ||
2188 | int *xp1, int *yp1, int *xp2, int *yp2) | ||
2189 | { | ||
2190 | t_text *x = (t_text *)z; | ||
2191 | int width, height, iscomment = (x->te_type == T_TEXT); | ||
2192 | float x1, y1, x2, y2; | ||
2193 | |||
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. */ | ||
2196 | |||
2197 | if (x->te_type == T_ATOM && x->te_width > 0) | ||
2198 | { | ||
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 */ | ||
2203 | } | ||
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? */ | ||
2211 | |||
2212 | else if (glist->gl_editor && glist->gl_editor->e_rtext) | ||
2213 | { | ||
2214 | t_rtext *y = glist_findrtext(glist, x); | ||
2215 | width = rtext_width(y); | ||
2216 | height = rtext_height(y) - (iscomment << 1); | ||
2217 | } | ||
2218 | else width = height = 10; | ||
2219 | x1 = text_xpix(x, glist); | ||
2220 | y1 = text_ypix(x, glist); | ||
2221 | x2 = x1 + width; | ||
2222 | y2 = y1 + height; | ||
2223 | y1 += iscomment; | ||
2224 | *xp1 = x1; | ||
2225 | *yp1 = y1; | ||
2226 | *xp2 = x2; | ||
2227 | *yp2 = y2; | ||
2228 | } | ||
2229 | |||
2230 | static void text_displace(t_gobj *z, t_glist *glist, | ||
2231 | int dx, int dy) | ||
2232 | { | ||
2233 | t_text *x = (t_text *)z; | ||
2234 | x->te_xpix += dx; | ||
2235 | x->te_ypix += dy; | ||
2236 | if (glist_isvisible(glist)) | ||
2237 | { | ||
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); | ||
2243 | } | ||
2244 | } | ||
2245 | |||
2246 | static void text_select(t_gobj *z, t_glist *glist, int state) | ||
2247 | { | ||
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")); | ||
2254 | } | ||
2255 | |||
2256 | static void text_activate(t_gobj *z, t_glist *glist, int state) | ||
2257 | { | ||
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); | ||
2261 | } | ||
2262 | |||
2263 | static void text_delete(t_gobj *z, t_glist *glist) | ||
2264 | { | ||
2265 | t_text *x = (t_text *)z; | ||
2266 | canvas_deletelinesfor(glist, x); | ||
2267 | } | ||
2268 | |||
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) | ||
2272 | { | ||
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))); | ||
2276 | } | ||
2277 | |||
2278 | static void text_vis(t_gobj *z, t_glist *glist, int vis) | ||
2279 | { | ||
2280 | t_text *x = (t_text *)z; | ||
2281 | if (vis) | ||
2282 | { | ||
2283 | if (text_shouldvis(x, glist)) | ||
2284 | { | ||
2285 | t_rtext *y = glist_findrtext(glist, x); | ||
2286 | if (x->te_type == T_ATOM) | ||
2287 | glist_retext(glist, x); | ||
2288 | text_drawborder(x, glist, rtext_gettag(y), | ||
2289 | rtext_width(y), rtext_height(y), 1); | ||
2290 | rtext_draw(y); | ||
2291 | } | ||
2292 | } | ||
2293 | else | ||
2294 | { | ||
2295 | t_rtext *y = glist_findrtext(glist, x); | ||
2296 | if (text_shouldvis(x, glist)) | ||
2297 | { | ||
2298 | text_eraseborder(x, glist, rtext_gettag(y)); | ||
2299 | rtext_erase(y); | ||
2300 | } | ||
2301 | } | ||
2302 | } | ||
2303 | |||
2304 | static int text_click(t_gobj *z, struct _glist *glist, | ||
2305 | int xpix, int ypix, int shift, int alt, int dbl, int doit) | ||
2306 | { | ||
2307 | t_text *x = (t_text *)z; | ||
2308 | if (x->te_type == T_OBJECT) | ||
2309 | { | ||
2310 | t_symbol *clicksym = gensym("click"); | ||
2311 | if (zgetfn(&x->te_pd, clicksym)) | ||
2312 | { | ||
2313 | if (doit) | ||
2314 | pd_vmess(&x->te_pd, clicksym, "fffff", | ||
2315 | (double)xpix, (double)ypix, | ||
2316 | (double)shift, 0, (double)alt); | ||
2317 | return (1); | ||
2318 | } | ||
2319 | else return (0); | ||
2320 | } | ||
2321 | else if (x->te_type == T_ATOM) | ||
2322 | { | ||
2323 | if (doit) | ||
2324 | gatom_click((t_gatom *)x, (t_floatarg)xpix, (t_floatarg)ypix, | ||
2325 | (t_floatarg)shift, 0, (t_floatarg)alt); | ||
2326 | return (1); | ||
2327 | } | ||
2328 | else if (x->te_type == T_MESSAGE) | ||
2329 | { | ||
2330 | if (doit) | ||
2331 | message_click((t_message *)x, (t_floatarg)xpix, (t_floatarg)ypix, | ||
2332 | (t_floatarg)shift, 0, (t_floatarg)alt); | ||
2333 | return (1); | ||
2334 | } | ||
2335 | else return (0); | ||
2336 | } | ||
2337 | |||
2338 | void text_save(t_gobj *z, t_binbuf *b) | ||
2339 | { | ||
2340 | t_text *x = (t_text *)z; | ||
2341 | if (x->te_type == T_OBJECT) | ||
2342 | { | ||
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)))) | ||
2349 | { | ||
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); | ||
2353 | } | ||
2354 | else /* otherwise just save the text */ | ||
2355 | { | ||
2356 | binbuf_addv(b, "ssii", gensym("#X"), gensym("obj"), | ||
2357 | (t_int)x->te_xpix, (t_int)x->te_ypix); | ||
2358 | } | ||
2359 | binbuf_addbinbuf(b, x->te_binbuf); | ||
2360 | binbuf_addv(b, ";"); | ||
2361 | } | ||
2362 | else if (x->te_type == T_MESSAGE) | ||
2363 | { | ||
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, ";"); | ||
2368 | } | ||
2369 | else if (x->te_type == T_ATOM) | ||
2370 | { | ||
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, ";"); | ||
2384 | } | ||
2385 | else | ||
2386 | { | ||
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, ";"); | ||
2391 | } | ||
2392 | } | ||
2393 | |||
2394 | /* this one is for everyone but "gatoms"; it's imposed in m_class.c */ | ||
2395 | t_widgetbehavior text_widgetbehavior = | ||
2396 | { | ||
2397 | text_getrect, | ||
2398 | text_displace, | ||
2399 | text_select, | ||
2400 | text_activate, | ||
2401 | text_delete, | ||
2402 | text_vis, | ||
2403 | text_click, | ||
2404 | }; | ||
2405 | |||
2406 | static t_widgetbehavior gatom_widgetbehavior = | ||
2407 | { | ||
2408 | text_getrect, | ||
2409 | gatom_displace, | ||
2410 | text_select, | ||
2411 | text_activate, | ||
2412 | text_delete, | ||
2413 | gatom_vis, | ||
2414 | text_click, | ||
2415 | }; | ||
2416 | |||
2417 | /* -------------------- the "text" class ------------ */ | ||
2418 | |||
2419 | #ifdef MACOSX | ||
2420 | #define EXTRAPIX 2 | ||
2421 | #else | ||
2422 | #define EXTRAPIX 1 | ||
2423 | #endif | ||
2424 | |||
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) | ||
2428 | { | ||
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++) | ||
2432 | { | ||
2433 | int onset = x1 + (width - IOWIDTH) * i / nplus; | ||
2434 | if (firsttime) | ||
2435 | sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %so%d\n", | ||
2436 | glist_getcanvas(glist), | ||
2437 | onset, y2 - 1, | ||
2438 | onset + IOWIDTH, y2, | ||
2439 | tag, i); | ||
2440 | else | ||
2441 | sys_vgui(".x%x.c coords %so%d %d %d %d %d\n", | ||
2442 | glist_getcanvas(glist), tag, i, | ||
2443 | onset, y2 - 1, | ||
2444 | onset + IOWIDTH, y2); | ||
2445 | } | ||
2446 | n = obj_ninlets(ob); | ||
2447 | nplus = (n == 1 ? 1 : n-1); | ||
2448 | for (i = 0; i < n; i++) | ||
2449 | { | ||
2450 | int onset = x1 + (width - IOWIDTH) * i / nplus; | ||
2451 | if (firsttime) | ||
2452 | sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %si%d\n", | ||
2453 | glist_getcanvas(glist), | ||
2454 | onset, y1, | ||
2455 | onset + IOWIDTH, y1 + EXTRAPIX, | ||
2456 | tag, i); | ||
2457 | else | ||
2458 | sys_vgui(".x%x.c coords %si%d %d %d %d %d\n", | ||
2459 | glist_getcanvas(glist), tag, i, | ||
2460 | onset, y1, | ||
2461 | onset + IOWIDTH, y1 + EXTRAPIX); | ||
2462 | } | ||
2463 | } | ||
2464 | |||
2465 | void text_drawborder(t_text *x, t_glist *glist, | ||
2466 | char *tag, int width2, int height2, int firsttime) | ||
2467 | { | ||
2468 | t_object *ob; | ||
2469 | int x1, y1, x2, y2, width, height; | ||
2470 | text_getrect(&x->te_g, glist, &x1, &y1, &x2, &y2); | ||
2471 | width = x2 - x1; | ||
2472 | height = y2 - y1; | ||
2473 | if (x->te_type == T_OBJECT) | ||
2474 | { | ||
2475 | if (firsttime) | ||
2476 | sys_vgui(".x%x.c create line\ | ||
2477 | %d %d %d %d %d %d %d %d %d %d -tags %sR\n", | ||
2478 | glist_getcanvas(glist), | ||
2479 | x1, y1, x2, y1, x2, y2, x1, y2, x1, y1, tag); | ||
2480 | else | ||
2481 | sys_vgui(".x%x.c coords %sR\ | ||
2482 | %d %d %d %d %d %d %d %d %d %d\n", | ||
2483 | glist_getcanvas(glist), tag, | ||
2484 | x1, y1, x2, y1, x2, y2, x1, y2, x1, y1); | ||
2485 | } | ||
2486 | else if (x->te_type == T_MESSAGE) | ||
2487 | { | ||
2488 | if (firsttime) | ||
2489 | sys_vgui(".x%x.c create line\ | ||
2490 | %d %d %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n", | ||
2491 | glist_getcanvas(glist), | ||
2492 | x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2, | ||
2493 | x1, y2, x1, y1, | ||
2494 | tag); | ||
2495 | else | ||
2496 | sys_vgui(".x%x.c coords %sR\ | ||
2497 | %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", | ||
2498 | glist_getcanvas(glist), tag, | ||
2499 | x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2, | ||
2500 | x1, y2, x1, y1); | ||
2501 | } | ||
2502 | else if (x->te_type == T_ATOM) | ||
2503 | { | ||
2504 | if (firsttime) | ||
2505 | sys_vgui(".x%x.c create line\ | ||
2506 | %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n", | ||
2507 | glist_getcanvas(glist), | ||
2508 | x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1, | ||
2509 | tag); | ||
2510 | else | ||
2511 | sys_vgui(".x%x.c coords %sR\ | ||
2512 | %d %d %d %d %d %d %d %d %d %d %d %d\n", | ||
2513 | glist_getcanvas(glist), tag, | ||
2514 | x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1); | ||
2515 | } | ||
2516 | /* draw inlets/outlets */ | ||
2517 | |||
2518 | if (ob = pd_checkobject(&x->te_pd)) | ||
2519 | glist_drawiofor(glist, ob, firsttime, tag, x1, y1, x2, y2); | ||
2520 | } | ||
2521 | |||
2522 | void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag) | ||
2523 | { | ||
2524 | int i, n; | ||
2525 | n = obj_noutlets(ob); | ||
2526 | for (i = 0; i < n; i++) | ||
2527 | sys_vgui(".x%x.c delete %so%d\n", | ||
2528 | glist_getcanvas(glist), tag, i); | ||
2529 | n = obj_ninlets(ob); | ||
2530 | for (i = 0; i < n; i++) | ||
2531 | sys_vgui(".x%x.c delete %si%d\n", | ||
2532 | glist_getcanvas(glist), tag, i); | ||
2533 | } | ||
2534 | |||
2535 | void text_eraseborder(t_text *x, t_glist *glist, char *tag) | ||
2536 | { | ||
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); | ||
2541 | } | ||
2542 | |||
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. */ | ||
2545 | |||
2546 | void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize) | ||
2547 | { | ||
2548 | if (x->te_type == T_OBJECT) | ||
2549 | { | ||
2550 | t_binbuf *b = binbuf_new(); | ||
2551 | int natom1, natom2; | ||
2552 | t_atom *vec1, *vec2; | ||
2553 | binbuf_text(b, buf, bufsize); | ||
2554 | natom1 = binbuf_getnatom(x->te_binbuf); | ||
2555 | vec1 = binbuf_getvec(x->te_binbuf); | ||
2556 | natom2 = binbuf_getnatom(b); | ||
2557 | vec2 = binbuf_getvec(b); | ||
2558 | /* special case: if pd args change just pass the message on. */ | ||
2559 | if (natom1 >= 1 && natom2 >= 1 && vec1[0].a_type == A_SYMBOL | ||
2560 | && !strcmp(vec1[0].a_w.w_symbol->s_name, "pd") && | ||
2561 | vec2[0].a_type == A_SYMBOL | ||
2562 | && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd")) | ||
2563 | { | ||
2564 | typedmess(&x->te_pd, gensym("rename"), natom2-1, vec2+1); | ||
2565 | binbuf_free(x->te_binbuf); | ||
2566 | x->te_binbuf = b; | ||
2567 | } | ||
2568 | else /* normally, just destroy the old one and make a new one. */ | ||
2569 | { | ||
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)); | ||
2577 | } | ||
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(); | ||
2583 | } | ||
2584 | else binbuf_text(x->te_binbuf, buf, bufsize); | ||
2585 | } | ||
2586 | |||
2587 | void g_text_setup(void) | ||
2588 | { | ||
2589 | text_class = class_new(gensym("text"), 0, 0, sizeof(t_text), | ||
2590 | CLASS_NOINLET | CLASS_PATCHABLE, 0); | ||
2591 | |||
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); | ||
2599 | |||
2600 | class_addmethod(message_class, (t_method)message_click, gensym("click"), | ||
2601 | A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); | ||
2602 | class_addmethod(message_class, (t_method)message_set, gensym("set"), | ||
2603 | A_GIMME, 0); | ||
2604 | class_addmethod(message_class, (t_method)message_add, gensym("add"), | ||
2605 | A_GIMME, 0); | ||
2606 | class_addmethod(message_class, (t_method)message_add2, gensym("add2"), | ||
2607 | A_GIMME, 0); | ||
2608 | |||
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); | ||
2616 | |||
2617 | gatom_class = class_new(gensym("gatom"), 0, (t_method)gatom_free, | ||
2618 | sizeof(t_gatom), CLASS_NOINLET | CLASS_PATCHABLE, 0); | ||
2619 | class_addbang(gatom_class, gatom_bang); | ||
2620 | class_addfloat(gatom_class, gatom_float); | ||
2621 | class_addsymbol(gatom_class, gatom_symbol); | ||
2622 | class_addmethod(gatom_class, (t_method)gatom_set, gensym("set"), | ||
2623 | A_GIMME, 0); | ||
2624 | class_addmethod(gatom_class, (t_method)gatom_click, gensym("click"), | ||
2625 | A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); | ||
2626 | class_addmethod(gatom_class, (t_method)gatom_param, gensym("param"), | ||
2627 | A_GIMME, 0); | ||
2628 | class_setwidget(gatom_class, &gatom_widgetbehavior); | ||
2629 | class_setpropertiesfn(gatom_class, gatom_properties); | ||
2630 | } | ||
2631 | |||
2632 | |||