Newer
Older
/* Copyright (c) 1997-1999 Miller Puckette.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* changes by Thomas Musil IEM KUG Graz Austria 2001 */
/* the methods for calling the gui-objects from menu are implemented */
/* all changes are labeled with iemlib */
#include <stdlib.h>
#include "m_pd.h"
#include "m_imp.h"
#include "s_stuff.h"
#include "t_tk.h"
#include "g_canvas.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
Ivica Bukvic
committed
#include "g_undo.h"
#include "x_preset.h"
t_class *text_class;
static void text_vis(t_gobj *z, t_glist *glist, int vis);
static void text_displace(t_gobj *z, t_glist *glist,
int dx, int dy);
static void text_getrect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2);
void canvas_startmotion(t_canvas *x);
t_widgetbehavior text_widgetbehavior;
static char *invalid_fill = "\"#ffdddd\"";
extern void canvas_apply_setundo(t_canvas *x, t_gobj *y);
extern void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf, const char *name);
extern void *canvas_undo_set_create(t_canvas *x);
extern void canvas_undo_create(t_canvas *x, void *z, int action);
extern int we_are_undoing;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/* ----------------- the "text" object. ------------------ */
/* add a "text" object (comment) to a glist. While this one goes for any
glist, the other 3 below are for canvases only. (why?) This is called
without args if invoked from the GUI; otherwise at least x and y
are provided. */
void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
t_text *x = (t_text *)pd_new(text_class);
t_atom at;
x->te_width = 0; /* don't know it yet. */
x->te_type = T_TEXT;
x->te_binbuf = binbuf_new();
if (argc > 1)
{
x->te_xpix = atom_getfloatarg(0, argc, argv);
x->te_ypix = atom_getfloatarg(1, argc, argv);
if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2);
else
{
SETSYMBOL(&at, gensym("comment"));
binbuf_restore(x->te_binbuf, 1, &at);
}
glist_add(gl, &x->te_g);
}
else
{
int xpix, ypix;
pd_vmess((t_pd *)glist_getcanvas(gl), gensym("editmode"), "i", 1);
SETSYMBOL(&at, gensym("comment"));
glist_noselect(gl);
glist_getnextxy(gl, &xpix, &ypix);
x->te_xpix = xpix-1;
x->te_ypix = ypix-1;
binbuf_restore(x->te_binbuf, 1, &at);
glist_add(gl, &x->te_g);
glist_noselect(gl);
glist_select(gl, &x->te_g);
/* it would be nice to "activate" here, but then the second,
"put-me-down" click changes the text selection, which is quite
irritating, so I took this back out. It's OK in messages
and objects though since there's no text in them at menu
creation. */
/* gobj_activate(&x->te_g, gl, 1); */
if (!we_are_undoing)
canvas_undo_add(glist_getcanvas(gl), 9, "create",
(void *)canvas_undo_set_create(glist_getcanvas(gl)));
canvas_startmotion(glist_getcanvas(gl));
}
}
/* ----------------- the "object" object. ------------------ */
extern t_pd *newest;
void canvas_getargs(int *argcp, t_atom **argvp);
static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected,
t_binbuf *b)
{
//fprintf(stderr,"canvas_objtext\n");
Ivica Bukvic
committed
// for hiding arguments
t_atom *vec;
int len, i, hidden;
t_binbuf *hide;
newest = 0;
canvas_setcurrent((t_canvas *)gl);
canvas_getargs(&argc, &argv);
binbuf_eval(b, &pd_objectmaker, argc, argv);
if (binbuf_getnatom(b))
{
if (!newest)
{
binbuf_print(b);
post("... couldn't create");
x = 0;
}
else if (!(x = pd_checkobject(newest)))
{
binbuf_print(b);
post("... didn't return a patchable object");
}
}
else x = 0;
if (!x)
{
/* LATER make the color reflect this */
//fprintf(stderr,"creating blank object\n");
x = (t_text *)pd_new(text_class);
Ivica Bukvic
committed
/* special case: an object, like preset_hub, hides its arguments beyond the first n, so
we modify its binbuf here */
vec = binbuf_getvec(b);
len = binbuf_getnatom(b);
hidden = 0;
for (i = 0; i < len; i++) {
if (!strcmp("%hidden%", atom_getsymbol(&vec[i])->s_name)) {
//fprintf(stderr,"found hidden %d %s\n", i, atom_getsymbol(&vec[i])->s_name);
hidden = i;
break;
}
}
if (hidden) {
hide = binbuf_new();
binbuf_add(hide, hidden, vec);
binbuf_free(b);
b = hide;
}
/* done special case */
Ivica Bukvic
committed
x->te_xpix = xpix;
x->te_ypix = ypix;
x->te_width = 0;
x->te_type = T_OBJECT;
glist_add(gl, &x->te_g);
Ivica Bukvic
committed
if (selected)
{
/* this is called if we've been created from the menu. */
glist_select(gl, &x->te_g);
gobj_activate(&x->te_g, gl, 1);
}
if (pd_class(&x->ob_pd) == vinlet_class)
canvas_resortinlets(glist_getcanvas(gl));
if (pd_class(&x->ob_pd) == voutlet_class)
canvas_resortoutlets(glist_getcanvas(gl));
canvas_unsetcurrent((t_canvas *)gl);
// here we recreate data buffer inside previously created undo snapshot
//canvas_undo_create(glist_getcanvas(gl), glist_getcanvas(gl)->u_last->data, UNDO_FREE);
//glist_getcanvas(gl)->u_last->data = canvas_undo_set_create(glist_getcanvas(gl));
/*if (binbuf_getnatom(x->te_binbuf) && !we_are_undoing) {
fprintf(stderr,"canvas_objtext calls create undo\n");
//glist_select(gl, &x->te_g);
canvas_undo_add(glist_getcanvas(gl), 9, "create",
(void *)canvas_undo_set_create(glist_getcanvas(gl)));
}*/
if ( glist_isvisible( ((t_canvas *)gl) ) ) {
sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", glist_getcanvas(gl));
}
Miller Puckette
committed
extern int sys_noautopatch;
/* utility routine to figure out where to put a new text box from menu
and whether to connect to it automatically */
void canvas_howputnew(t_canvas *x, int *connectp, int *xpixp, int *ypixp,
int xpix, ypix, indx = 0, nobj = 0, n2, x1, x2, y1, y2;
if (x->gl_editor->e_selection &&
!x->gl_editor->e_selection->sel_next &&
!sys_noautopatch) {
selected = x->gl_editor->e_selection->sel_what;
t_object *ob = pd_checkobject(&selected->g_pd);
connectme = (obj_noutlets(ob) ? 1 : 0);
}*/
int connectme = (x->gl_editor->e_selection &&
!x->gl_editor->e_selection->sel_next && !sys_noautopatch);
t_gobj *g, *selected = x->gl_editor->e_selection->sel_what;
for (g = x->gl_list, nobj = 0; g; g = g->g_next, nobj++)
{
gobj_getrect(g, x, &x1, &y1, &x2, &y2);
indx = nobj;
*xpixp = x1;
*ypixp = y2 + 5;
}
glist_noselect(x);
/* search back for 'selected' and if it isn't on the list,
plan just to connect from the last item on the list. */
for (g = x->gl_list, n2 = 0; g; g = g->g_next, n2++)
{
if (g == selected)
{
indx = n2;
break;
}
else if (!g->g_next)
indx = nobj-1;
}
x->gl_editor->e_onmotion = MA_NONE;
sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
}
else
{
glist_getnextxy(x, xpixp, ypixp);
glist_noselect(x);
}
*connectp = connectme;
*indexp = indx;
*totalp = nobj;
}
/* object creation routine. These are called without any arguments if
they're invoked from the gui; when pasting or restoring from a file, we
get at least x and y. */
void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
//fprintf(stderr,"canvas_obj\n");
t_text *x;
if (argc >= 2)
{
t_binbuf *b = binbuf_new();
binbuf_restore(b, argc-2, argv+2);
canvas_objtext(gl, atom_getintarg(0, argc, argv),
atom_getintarg(1, argc, argv), 0, b);
}
/* JMZ: don't go into interactive mode in a closed canvas */
else if (!glist_isvisible(gl))
post("unable to create stub object in closed canvas!");
else
{
/* interactively create new obect */
int connectme, xpix, ypix, indx, nobj;
canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
canvas_objtext(gl, xpix, ypix, 1, b);
if (connectme) {
//fprintf(stderr,"canvas_obj calls canvas_connect\n");
}
else {
//fprintf(stderr,"canvas_obj calls canvas_startmotion\n");
canvas_startmotion(glist_getcanvas(gl));
}
Ivica Bukvic
committed
//canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
if (!we_are_undoing)
canvas_undo_add(glist_getcanvas(gl), 9, "create",
(void *)canvas_undo_set_create(glist_getcanvas(gl)));
extern void glist_setlastxy(t_glist *gl, int xval, int yval);
/* invoked from tcl/tk: abstraction_name x_offset y_offset */
void canvas_obj_abstraction_from_menu(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
//fprintf(stderr,"canvas_abstraction_from_menu\n");
t_text *x;
t_binbuf *b = binbuf_new();
binbuf_restore(b, 2, argv);
int connectme, xpix, ypix, indx, nobj;
canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
#ifdef PDL2ORK
if (sys_k12_mode)
pd_vmess (&gl->gl_pd, gensym("tooltips"), "i", 1);
#endif
canvas_objtext(gl, xpix+atom_getintarg(1, argc, argv), ypix+atom_getintarg(2, argc, argv), 1, b);
if (connectme) {
canvas_connect(gl, indx, 0, nobj, 0);
}
else {
canvas_startmotion(glist_getcanvas(gl));
}
canvas_undo_add(glist_getcanvas(gl), 9, "create",
(void *)canvas_undo_set_create(glist_getcanvas(gl)));
glist_setlastxy(glist_getcanvas(gl), xpix, ypix);
}
/* make an object box for an object that's already there. */
/* iemlib */
void canvas_iemguis(t_glist *gl, t_symbol *guiobjname)
{
//fprintf(stderr,"canvas_iemguis\n");
//int xpix, ypix;
if(!strcmp(guiobjname->s_name, "cnv"))
glist_noselect(gl);
int connectme, xpix, ypix, indx, nobj;
canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
/*compensate for the iemgui sliders' xyoffset in the case of autopatch */
if(connectme) {
if(!strcmp(guiobjname->s_name, "hsl"))
xpix = xpix + 3;
else if(!strcmp(guiobjname->s_name, "vsl"))
ypix = ypix + 2;
else if(!strcmp(guiobjname->s_name, "vu")) {
xpix = xpix + 1;
ypix = ypix + 2;
}
}
pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
glist_noselect(gl);
SETSYMBOL(&at, guiobjname);
binbuf_restore(b, 1, &at);
canvas_objtext(gl, xpix, ypix, 1, b);
if (connectme)
canvas_connect(gl, indx, 0, nobj, 0);
//glist_getnextxy(gl, &xpix, &ypix);
//canvas_objtext(gl, xpix, ypix, 1, b);
else canvas_startmotion(glist_getcanvas(gl));
Ivica Bukvic
committed
//canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
canvas_undo_add(glist_getcanvas(gl), 9, "create",
(void *)canvas_undo_set_create(glist_getcanvas(gl)));
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
}
void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("bng"));
}
void canvas_toggle(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("tgl"));
}
void canvas_vslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("vsl"));
}
void canvas_hslider(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("hsl"));
}
void canvas_hdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("hdl"));
}
void canvas_vdial(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("vdl"));
}
void canvas_hradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("hradio"));
}
void canvas_vradio(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("vradio"));
}
void canvas_vumeter(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("vu"));
}
void canvas_mycnv(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("cnv"));
}
void canvas_numbox(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
canvas_iemguis(gl, gensym("nbx"));
}
/* iemlib */
void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv)
{
x->te_width = 0; /* don't know it yet. */
x->te_type = T_OBJECT;
x->te_binbuf = binbuf_new();
x->te_xpix = atom_getfloatarg(0, argc, argv);
x->te_ypix = atom_getfloatarg(1, argc, argv);
if (argc > 2) binbuf_restore(x->te_binbuf, argc-2, argv+2);
glist_add(gl, &x->te_g);
}
/* ---------------------- the "message" text item ------------------------ */
typedef struct _messresponder
{
t_pd mr_pd;
t_outlet *mr_outlet;
} t_messresponder;
typedef struct _message
{
t_text m_text;
t_messresponder m_messresponder;
t_glist *m_glist;
t_clock *m_clock;
} t_message;
Ivica Bukvic
committed
static t_class *messresponder_class;
static void messresponder_bang(t_messresponder *x)
{
outlet_bang(x->mr_outlet);
}
static void messresponder_float(t_messresponder *x, t_float f)
{
outlet_float(x->mr_outlet, f);
}
static void messresponder_symbol(t_messresponder *x, t_symbol *s)
{
outlet_symbol(x->mr_outlet, s);
}
static void messresponder_blob(t_messresponder *x, t_blob *st)
{ /* MP 20070107 blob type */
outlet_blob(x->mr_outlet, st);
}
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
static void messresponder_list(t_messresponder *x,
t_symbol *s, int argc, t_atom *argv)
{
outlet_list(x->mr_outlet, s, argc, argv);
}
static void messresponder_anything(t_messresponder *x,
t_symbol *s, int argc, t_atom *argv)
{
outlet_anything(x->mr_outlet, s, argc, argv);
}
static void message_bang(t_message *x)
{
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 0, 0);
}
static void message_float(t_message *x, t_float f)
{
t_atom at;
SETFLOAT(&at, f);
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
}
static void message_symbol(t_message *x, t_symbol *s)
{
t_atom at;
SETSYMBOL(&at, s);
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
}
static void message_blob(t_message *x, t_blob *st)
{
t_atom at;
SETBLOB(&at, st);
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
}
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv)
{
binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, argc, argv);
}
static void message_set(t_message *x, t_symbol *s, int argc, t_atom *argv)
{
binbuf_clear(x->m_text.te_binbuf);
binbuf_add(x->m_text.te_binbuf, argc, argv);
glist_retext(x->m_glist, &x->m_text);
}
static void message_add2(t_message *x, t_symbol *s, int argc, t_atom *argv)
{
binbuf_add(x->m_text.te_binbuf, argc, argv);
glist_retext(x->m_glist, &x->m_text);
}
static void message_add(t_message *x, t_symbol *s, int argc, t_atom *argv)
{
binbuf_add(x->m_text.te_binbuf, argc, argv);
binbuf_addsemi(x->m_text.te_binbuf);
glist_retext(x->m_glist, &x->m_text);
}
static void message_addcomma(t_message *x)
{
t_atom a;
SETCOMMA(&a);
binbuf_add(x->m_text.te_binbuf, 1, &a);
glist_retext(x->m_glist, &x->m_text);
}
static void message_addsemi(t_message *x)
{
message_add(x, 0, 0, 0);
}
static void message_adddollar(t_message *x, t_floatarg f)
{
t_atom a;
int n = f;
if (n < 0)
n = 0;
SETDOLLAR(&a, n);
binbuf_add(x->m_text.te_binbuf, 1, &a);
glist_retext(x->m_glist, &x->m_text);
}
static void message_adddollsym(t_message *x, t_symbol *s)
{
t_atom a;
char buf[MAXPDSTRING];
buf[0] = '$';
strncpy(buf+1, s->s_name, MAXPDSTRING-2);
buf[MAXPDSTRING-1] = 0;
SETDOLLSYM(&a, gensym(buf));
binbuf_add(x->m_text.te_binbuf, 1, &a);
glist_retext(x->m_glist, &x->m_text);
}
static void message_click(t_message *x,
t_floatarg xpos, t_floatarg ypos, t_floatarg shift,
t_floatarg ctrl, t_floatarg alt)
{
message_float(x, 0);
if (glist_isvisible(x->m_glist))
{
t_rtext *y = glist_findrtext(x->m_glist, &x->m_text);
sys_vgui(".x%lx.c itemconfigure %sR -width 5\n",
glist_getcanvas(x->m_glist), rtext_gettag(y));
clock_delay(x->m_clock, 120);
}
}
static void message_tick(t_message *x)
{
if (glist_isvisible(x->m_glist))
{
t_rtext *y = glist_findrtext(x->m_glist, &x->m_text);
sys_vgui(".x%lx.c itemconfigure %sR -width 1\n",
glist_getcanvas(x->m_glist), rtext_gettag(y));
}
}
static void message_free(t_message *x)
{
clock_free(x->m_clock);
}
void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
//fprintf(stderr,"canvas_msg\n");
t_message *x = (t_message *)pd_new(message_class);
x->m_messresponder.mr_pd = messresponder_class;
x->m_messresponder.mr_outlet = outlet_new(&x->m_text, &s_float);
x->m_text.te_width = 0; /* don't know it yet. */
x->m_text.te_type = T_MESSAGE;
x->m_text.te_binbuf = binbuf_new();
x->m_glist = gl;
x->m_clock = clock_new(x, (t_method)message_tick);
if (argc > 1)
{
x->m_text.te_xpix = atom_getfloatarg(0, argc, argv);
x->m_text.te_ypix = atom_getfloatarg(1, argc, argv);
if (argc > 2) binbuf_restore(x->m_text.te_binbuf, argc-2, argv+2);
glist_add(gl, &x->m_text.te_g);
}
else if (!glist_isvisible(gl))
post("unable to create stub message in closed canvas!");
int connectme, xpix, ypix, indx, nobj;
canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
x->m_text.te_xpix = xpix;
x->m_text.te_ypix = ypix;
glist_add(gl, &x->m_text.te_g);
glist_noselect(gl);
glist_select(gl, &x->m_text.te_g);
gobj_activate(&x->m_text.te_g, gl, 1);
if (connectme)
canvas_connect(gl, indx, 0, nobj, 0);
else canvas_startmotion(glist_getcanvas(gl));
Ivica Bukvic
committed
//canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
canvas_undo_add(glist_getcanvas(gl), 9, "create",
(void *)canvas_undo_set_create(glist_getcanvas(gl)));
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
}
}
/* ---------------------- the "atom" text item ------------------------ */
#define ATOMBUFSIZE 40
#define ATOM_LABELLEFT 0
#define ATOM_LABELRIGHT 1
#define ATOM_LABELUP 2
#define ATOM_LABELDOWN 3
typedef struct _gatom
{
t_text a_text;
t_atom a_atom; /* this holds the value and the type */
t_glist *a_glist; /* owning glist */
t_float a_toggle; /* value to toggle to */
t_float a_draghi; /* high end of drag range */
t_float a_draglo; /* low end of drag range */
t_symbol *a_label; /* symbol to show as label next to box */
t_symbol *a_symfrom; /* "receive" name -- bind ourselvs to this */
t_symbol *a_symto; /* "send" name -- send to this on output */
char a_buf[ATOMBUFSIZE];/* string buffer for typing */
char a_shift; /* was shift key down when dragging started? */
char a_wherelabel; /* 0-3 for left, right, above, below */
t_symbol *a_expanded_to; /* a_symto after $0, $1, ... expansion */
} t_gatom;
/* prepend "-" as necessary to avoid empty strings, so we can
use them in Pd messages. A more complete solution would be
to introduce some quoting mechanism; but then we'd be much more
complicated. */
static t_symbol *gatom_escapit(t_symbol *s)
{
if (!*s->s_name)
return (gensym("-"));
else if (*s->s_name == '-')
{
char shmo[100];
shmo[0] = '-';
strncpy(shmo+1, s->s_name, 99);
shmo[99] = 0;
return (gensym(shmo));
}
else return (iemgui_dollar2raute(s));
}
/* undo previous operation: strip leading "-" if found. */
static t_symbol *gatom_unescapit(t_symbol *s)
{
if (*s->s_name == '-')
return (gensym(s->s_name+1));
else return (iemgui_raute2dollar(s));
}
static void gatom_redraw(t_gobj *client, t_glist *glist)
{
t_gatom *x = (t_gatom *)client;
glist_retext(x->a_glist, &x->a_text);
}
static void gatom_retext(t_gatom *x, int senditup)
{
binbuf_clear(x->a_text.te_binbuf);
binbuf_add(x->a_text.te_binbuf, 1, &x->a_atom);
if (senditup && glist_isvisible(x->a_glist))
sys_queuegui(x, x->a_glist, gatom_redraw);
}
static void gatom_set(t_gatom *x, t_symbol *s, int argc, t_atom *argv)
{
t_atom oldatom = x->a_atom;
int changed = 0;
if (!argc) return;
if (x->a_atom.a_type == A_FLOAT)
x->a_atom.a_w.w_float = atom_getfloat(argv),
changed = (x->a_atom.a_w.w_float != oldatom.a_w.w_float);
else if (x->a_atom.a_type == A_SYMBOL)
x->a_atom.a_w.w_symbol = atom_getsymbol(argv),
changed = (x->a_atom.a_w.w_symbol != oldatom.a_w.w_symbol);
if (changed)
gatom_retext(x, 1);
x->a_buf[0] = 0;
}
static void gatom_bang(t_gatom *x)
{
if (x->a_atom.a_type == A_FLOAT)
{
if (x->a_text.te_outlet)
outlet_float(x->a_text.te_outlet, x->a_atom.a_w.w_float);
if (*x->a_expanded_to->s_name && x->a_expanded_to->s_thing)
{
if (x->a_symto == x->a_symfrom)
pd_error(x,
"%s: atom with same send/receive name (infinite loop)",
x->a_symto->s_name);
else pd_float(x->a_expanded_to->s_thing, x->a_atom.a_w.w_float);
}
}
else if (x->a_atom.a_type == A_SYMBOL)
{
if (x->a_text.te_outlet)
outlet_symbol(x->a_text.te_outlet, x->a_atom.a_w.w_symbol);
if (*x->a_symto->s_name && x->a_expanded_to->s_thing)
{
if (x->a_symto == x->a_symfrom)
pd_error(x,
"%s: atom with same send/receive name (infinite loop)",
x->a_symto->s_name);
else pd_symbol(x->a_expanded_to->s_thing, x->a_atom.a_w.w_symbol);
}
}
}
static void gatom_float(t_gatom *x, t_float f)
{
t_atom at;
SETFLOAT(&at, f);
gatom_set(x, 0, 1, &at);
gatom_bang(x);
}
static void gatom_clipfloat(t_gatom *x, t_float f)
{
if (x->a_draglo != 0 || x->a_draghi != 0)
{
if (f < x->a_draglo)
f = x->a_draglo;
if (f > x->a_draghi)
f = x->a_draghi;
}
gatom_float(x, f);
}
static void gatom_symbol(t_gatom *x, t_symbol *s)
{
t_atom at;
SETSYMBOL(&at, s);
gatom_set(x, 0, 1, &at);
gatom_bang(x);
}
/* We need a list method because, since there's both an "inlet" and a
"nofirstin" flag, the standard list behavior gets confused. */
static void gatom_list(t_gatom *x, t_symbol *s, int argc, t_atom *argv)
{
if (!argc)
gatom_bang(x);
else if (argv->a_type == A_FLOAT)
gatom_float(x, argv->a_w.w_float);
else if (argv->a_type == A_SYMBOL)
gatom_symbol(x, argv->a_w.w_symbol);
else pd_error(x, "gatom_list: need float or symbol");
}
static void gatom_motion(void *z, t_floatarg dx, t_floatarg dy)
{
t_gatom *x = (t_gatom *)z;
if (dy == 0) return;
if (x->a_atom.a_type == A_FLOAT)
{
if (x->a_shift)
{
double nval = x->a_atom.a_w.w_float - 0.01 * dy;
double trunc = 0.01 * (floor(100. * nval + 0.5));
if (trunc < nval + 0.0001 && trunc > nval - 0.0001) nval = trunc;
gatom_clipfloat(x, nval);
}
else
{
double nval = x->a_atom.a_w.w_float - dy;
double trunc = 0.01 * (floor(100. * nval + 0.5));
if (trunc < nval + 0.0001 && trunc > nval - 0.0001) nval = trunc;
trunc = floor(nval + 0.5);
if (trunc < nval + 0.001 && trunc > nval - 0.001) nval = trunc;
gatom_clipfloat(x, nval);
}
}
}
static void gatom_key(void *z, t_floatarg f)
{
t_gatom *x = (t_gatom *)z;
int c = f;
int len = strlen(x->a_buf);
t_atom at;
char sbuf[ATOMBUFSIZE + 4];
if (c == 0)
{
/* we're being notified that no more keys will come for this grab */
if (x->a_buf[0])
gatom_retext(x, 1);
return;
}
else if (c == '\b')
{
if (len > 0)
x->a_buf[len-1] = 0;
goto redraw;
}
else if (c == '\n')
{
if (x->a_atom.a_type == A_FLOAT)
x->a_atom.a_w.w_float = atof(x->a_buf);
else if (x->a_atom.a_type == A_SYMBOL)
x->a_atom.a_w.w_symbol = gensym(x->a_buf);
else bug("gatom_key");
gatom_bang(x);
gatom_retext(x, 1);
x->a_buf[0] = 0;
}
else if (len < (ATOMBUFSIZE-1))
{
/* for numbers, only let reasonable characters through */
if ((x->a_atom.a_type == A_SYMBOL) ||
(c >= '0' && c <= '9' || c == '.' || c == '-'
|| c == 'e' || c == 'E'))
{
x->a_buf[len] = c;
x->a_buf[len+1] = 0;
goto redraw;
}
}
return;
redraw:
/* LATER figure out how to avoid creating all these symbols! */
sprintf(sbuf, "%s...", x->a_buf);
SETSYMBOL(&at, gensym(sbuf));
binbuf_clear(x->a_text.te_binbuf);
binbuf_add(x->a_text.te_binbuf, 1, &at);
glist_retext(x->a_glist, &x->a_text);
}
static void gatom_click(t_gatom *x,
t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl,
t_floatarg alt)
{
if (x->a_text.te_width == 1)
{
if (x->a_atom.a_type == A_FLOAT)
gatom_float(x, (x->a_atom.a_w.w_float == 0));
}
else
{
if (alt)
{
if (x->a_atom.a_type != A_FLOAT) return;
if (x->a_atom.a_w.w_float != 0)
{
x->a_toggle = x->a_atom.a_w.w_float;
gatom_float(x, 0);
return;
}
else gatom_float(x, x->a_toggle);
}
x->a_shift = shift;
x->a_buf[0] = 0;
glist_grab(x->a_glist, &x->a_text.te_g, gatom_motion, gatom_key,
xpos, ypos);
}
}
Ivica Bukvic
committed
EXTERN int glist_getindex(t_glist *x, t_gobj *y);
EXTERN int canvas_apply_restore_original_position(t_canvas *x, int pos);
/* message back from dialog window */
static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv)
{
canvas_apply_setundo(x->a_glist, (t_gobj *)x);
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
t_float width = atom_getfloatarg(0, argc, argv);
t_float draglo = atom_getfloatarg(1, argc, argv);
t_float draghi = atom_getfloatarg(2, argc, argv);
t_symbol *label = gatom_unescapit(atom_getsymbolarg(3, argc, argv));
t_float wherelabel = atom_getfloatarg(4, argc, argv);
t_symbol *symfrom = gatom_unescapit(atom_getsymbolarg(5, argc, argv));
t_symbol *symto = gatom_unescapit(atom_getsymbolarg(6, argc, argv));
gobj_vis(&x->a_text.te_g, x->a_glist, 0);
if (!*symfrom->s_name && *x->a_symfrom->s_name)
inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
else if (*symfrom->s_name && !*x->a_symfrom->s_name && x->a_text.te_inlet)
{
canvas_deletelinesforio(x->a_glist, &x->a_text,
x->a_text.te_inlet, 0);
inlet_free(x->a_text.te_inlet);
}
if (!*symto->s_name && *x->a_symto->s_name)
outlet_new(&x->a_text, 0);
else if (*symto->s_name && !*x->a_symto->s_name && x->a_text.te_outlet)
{
canvas_deletelinesforio(x->a_glist, &x->a_text,
0, x->a_text.te_outlet);
outlet_free(x->a_text.te_outlet);
}
if (draglo >= draghi)
draglo = draghi = 0;
x->a_draglo = draglo;
x->a_draghi = draghi;
if (width < 0)
width = 4;
else if (width > 80)
width = 80;
x->a_text.te_width = width;
x->a_wherelabel = ((int)wherelabel & 3);
x->a_label = label;
if (*x->a_symfrom->s_name)
pd_unbind(&x->a_text.te_pd,
canvas_realizedollar(x->a_glist, x->a_symfrom));
x->a_symfrom = symfrom;
if (*x->a_symfrom->s_name)
pd_bind(&x->a_text.te_pd,
canvas_realizedollar(x->a_glist, x->a_symfrom));
x->a_symto = symto;
x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto);
gobj_vis(&x->a_text.te_g, x->a_glist, 1);
gobj_select(&x->a_text.te_g, x->a_glist, 1);
Ivica Bukvic
committed
sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)x->a_glist);
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
/* glist_retext(x->a_glist, &x->a_text); */
}
/* ---------------- gatom-specific widget functions --------------- */
static void gatom_getwherelabel(t_gatom *x, t_glist *glist, int *xp, int *yp)
{
int x1, y1, x2, y2, width, height;
text_getrect(&x->a_text.te_g, glist, &x1, &y1, &x2, &y2);
width = x2 - x1;
height = y2 - y1;
if (x->a_wherelabel == ATOM_LABELLEFT)
{
*xp = x1 - 3 -
strlen(canvas_realizedollar(x->a_glist, x->a_label)->s_name) *
sys_fontwidth(glist_getfont(glist));
*yp = y1 + 2;
}
else if (x->a_wherelabel == ATOM_LABELRIGHT)
{
*xp = x2 + 2;
*yp = y1 + 2;
}
else if (x->a_wherelabel == ATOM_LABELUP)
{
*xp = x1 - 1;
*yp = y1 - 1 - sys_fontheight(glist_getfont(glist));;
}
else
{
*xp = x1 - 1;
*yp = y2 + 3;
}
}
static void gatom_displace(t_gobj *z, t_glist *glist,
int dx, int dy)
{
//fprintf(stderr,"gatom_displace\n");
t_gatom *x = (t_gatom*)z;
text_displace(z, glist, dx, dy);
if (glist_isvisible(glist)) {
sys_vgui(".x%lx.c move %lx.l %d %d\n", glist_getcanvas(glist),
x, dx, dy);
}
}
static void gatom_vis(t_gobj *z, t_glist *glist, int vis)
{
//fprintf(stderr,"gatom_vis\n");