g_text.c 95 KB
Newer Older
Miller Puckette's avatar
Miller Puckette committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* 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 "g_canvas.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
17 18
#include "g_undo.h"
#include "x_preset.h"
Miller Puckette's avatar
Miller Puckette committed
19

20 21
#include "s_utf8.h"

Miller Puckette's avatar
Miller Puckette committed
22
t_class *text_class;
23 24
t_class *message_class;
static t_class *gatom_class;
25
static t_class *dropdown_class;
Miller Puckette's avatar
Miller Puckette committed
26 27 28 29 30
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);
31 32
void canvas_howputnew(t_canvas *x, int *connectp, int *xpixp, int *ypixp,
    int *indexp, int *totalp);
Miller Puckette's avatar
Miller Puckette committed
33 34 35 36

void canvas_startmotion(t_canvas *x);
t_widgetbehavior text_widgetbehavior;

37
extern void canvas_displaceselection(t_canvas *x, int dx, int dy);
38
extern void canvas_apply_setundo(t_canvas *x, t_gobj *y);
39 40
extern void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf,
    const char *name);
41 42
extern void *canvas_undo_set_create(t_canvas *x);
extern void canvas_undo_create(t_canvas *x, void *z, int action);
43
extern int we_are_undoing;
44
extern void glob_preset_node_list_check_loc_and_update(void);
45
extern void glob_preset_node_list_seek_hub(void);
46

Miller Puckette's avatar
Miller Puckette committed
47 48 49 50 51 52 53 54 55
/* ----------------- 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)
{
56
    if (canvas_hasarray(gl)) return;
Miller Puckette's avatar
Miller Puckette committed
57 58 59 60
    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;
61
    x->te_iemgui = 0;
Miller Puckette's avatar
Miller Puckette committed
62 63 64 65 66
    x->te_binbuf = binbuf_new();
    if (argc > 1)
    {
        x->te_xpix = atom_getfloatarg(0, argc, argv);
        x->te_ypix = atom_getfloatarg(1, argc, argv);
67 68
        if (argc > 2)
        {
69 70
            binbuf_restore(x->te_binbuf, argc-2, argv+2);
        }
Miller Puckette's avatar
Miller Puckette committed
71 72 73 74 75 76 77 78 79
        else
        {
            SETSYMBOL(&at, gensym("comment"));
            binbuf_restore(x->te_binbuf, 1, &at);
        }
        glist_add(gl, &x->te_g);
    }
    else
    {
80
        //int xpix, ypix;
81 82
        int connectme, xpix, ypix, indx, nobj;
        canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
Miller Puckette's avatar
Miller Puckette committed
83 84 85
        pd_vmess((t_pd *)glist_getcanvas(gl), gensym("editmode"), "i", 1);
        SETSYMBOL(&at, gensym("comment"));
        glist_noselect(gl);
86 87 88
        //glist_getnextxy(gl, &xpix, &ypix);
        x->te_xpix = xpix;
        x->te_ypix = ypix;
Miller Puckette's avatar
Miller Puckette committed
89 90 91 92 93 94 95 96 97 98
        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); */
99 100 101
        if (!we_are_undoing)
            canvas_undo_add(glist_getcanvas(gl), 9, "create",
                (void *)canvas_undo_set_create(glist_getcanvas(gl)));
102 103
        if (connectme == 0)
        {
104
            canvas_displaceselection(glist_getcanvas(gl), -8, -8);
105 106
            canvas_startmotion(glist_getcanvas(gl));
        }
Miller Puckette's avatar
Miller Puckette committed
107
    }
108 109
    glob_preset_node_list_seek_hub();
    glob_preset_node_list_check_loc_and_update();
Miller Puckette's avatar
Miller Puckette committed
110 111 112 113 114
}

/* ----------------- the "object" object.  ------------------ */

extern t_pd *newest;
115
int scalar_in_a_box;
116
extern void glist_scalar(t_glist *canvas, t_symbol *s, int argc, t_atom *argv);
Miller Puckette's avatar
Miller Puckette committed
117 118
void canvas_getargs(int *argcp, t_atom **argvp);

119
static void canvas_objtext(t_glist *gl, int xpix, int ypix,
Jonathan Wilkes's avatar
Jonathan Wilkes committed
120
    int width, int selected, t_binbuf *b, int connectme)
Miller Puckette's avatar
Miller Puckette committed
121
{
122
    //fprintf(stderr,"canvas_objtext\n");
Miller Puckette's avatar
Miller Puckette committed
123 124 125
    t_text *x;
    int argc;
    t_atom *argv;
126

127 128 129 130
    // for hiding arguments
    t_atom *vec;
    int len, i, hidden;
    t_binbuf *hide;
131

Miller Puckette's avatar
Miller Puckette committed
132 133 134 135 136 137 138 139
    newest = 0;
    canvas_setcurrent((t_canvas *)gl);
    canvas_getargs(&argc, &argv);
    binbuf_eval(b, &pd_objectmaker, argc, argv);
    if (binbuf_getnatom(b))
    {
        if (!newest)
        {
140 141 142 143 144 145
            /* let's see if there's a scalar by this name... */
            t_atom *scalar_at = binbuf_getvec(b);
            if (scalar_at->a_type == A_SYMBOL)
            {
                t_symbol *templatesym = 
                    canvas_makebindsym(atom_getsymbol(scalar_at));
146 147 148 149
                t_template *tmpl = template_findbyname(templatesym);
                if (template_findbyname(templatesym) &&
                    template_cancreate(tmpl) &&
                    template_hasxy(tmpl))
150
                {
151 152
                    //post("Hmm, found a scalar from struct %s... ",
                    //    templatesym->s_name);
153 154 155 156 157 158 159 160
                    t_binbuf *scalarbuf = binbuf_new();
                    t_atom coords_at[2];
                    SETFLOAT(coords_at, (t_float)xpix);
                    SETFLOAT(coords_at+1, (t_float)ypix);
                    binbuf_add(scalarbuf, 1, scalar_at);
                    binbuf_add(scalarbuf, 2, coords_at);
                    binbuf_add(scalarbuf, binbuf_getnatom(b)-1, scalar_at+1);
                    t_atom *scalar_create_at = binbuf_getvec(scalarbuf);
161 162
                    glist_scalar(gl, gensym("scalar_from_canvas_objtext"),
                        binbuf_getnatom(b)+2, scalar_create_at);
163
                    binbuf_free(scalarbuf);
164
                    //binbuf_free(b);
165
                    canvas_unsetcurrent((t_canvas *)gl);
166
                    scalar_in_a_box = 1;
167 168 169
                    return;
                }
            }
Miller Puckette's avatar
Miller Puckette committed
170 171 172 173 174 175 176 177 178 179 180
            x = 0;
        }
        else if (!(x = pd_checkobject(newest)))
        {
            binbuf_print(b);
            post("... didn't return a patchable object");
        }
    }
    else x = 0;
    if (!x)
    {
181 182
        /* LATER make the color reflect this */
        x = (t_text *)pd_new(text_class);
183 184 185 186 187 188 189 190 191 192
        if (binbuf_getnatom(b))
        {
            int bufsize;
            char *buf;
            binbuf_gettext(b, &buf, &bufsize);
            buf = t_resizebytes(buf, bufsize, bufsize+1);
            buf[bufsize] = 0;
            pd_error(x, "couldn't create \"%s\"", buf);
            t_freebytes(buf, bufsize + 1);
        }
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
    }
    /* 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 */
217

Miller Puckette's avatar
Miller Puckette committed
218
    x->te_binbuf = b;
219

Miller Puckette's avatar
Miller Puckette committed
220 221
    x->te_xpix = xpix;
    x->te_ypix = ypix;
222
    x->te_width = width;
Miller Puckette's avatar
Miller Puckette committed
223
    x->te_type = T_OBJECT;
224 225 226 227
    /* let's see if iemgui objects did not already set the value to 1,
       otherwise set it explicitly to 0 */
    if (x->te_iemgui != 1)
        x->te_iemgui = 0;
Miller Puckette's avatar
Miller Puckette committed
228
    glist_add(gl, &x->te_g);
229

Miller Puckette's avatar
Miller Puckette committed
230 231
    if (selected)
    {
Jonathan Wilkes's avatar
Jonathan Wilkes committed
232 233 234
            /* this is called if we've been created from the menu. we use
               connectme to be able to tell the GUI the difference between
               a newly created floating object and an autopatched one. */
Miller Puckette's avatar
Miller Puckette committed
235
        glist_select(gl, &x->te_g);
236
        gobj_activate(&x->te_g, gl,
Jonathan Wilkes's avatar
Jonathan Wilkes committed
237
            connectme ? 1 : 2); // <-- hack to set floating mode for new obj box
Miller Puckette's avatar
Miller Puckette committed
238 239 240 241 242 243
    }
    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);
244 245 246 247

    glob_preset_node_list_seek_hub();
    glob_preset_node_list_check_loc_and_update();

248 249 250 251 252 253 254 255 256 257 258 259 260
    // 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) ) )
    {
261
        canvas_getscroll(glist_getcanvas(gl));
262
    }
Miller Puckette's avatar
Miller Puckette committed
263 264
}

265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286

extern int sys_autopatch_yoffset;
static int get_autopatch_yoffset(t_canvas *x)
{
    if (sys_autopatch_yoffset)
        return sys_autopatch_yoffset;
    else
    {
        int fontsize = glist_getfont(x);
        switch (fontsize)
        {
        case 8: return 8;
        case 10: return 8;
        case 12: return 9;
        case 16: return 10;
        case 24: return 13;
        case 36: return 18;
        }
        return 10;
    }
}

287
extern int sys_noautopatch;
288 289
extern t_gobj *glist_nth(t_glist *x, int n);
extern int glist_getindex(t_glist *x, t_gobj *y);
Miller Puckette's avatar
Miller Puckette committed
290 291
    /* utility routine to figure out where to put a new text box from menu
    and whether to connect to it automatically */
292
void canvas_howputnew(t_canvas *x, int *connectp, int *xpixp, int *ypixp,
Miller Puckette's avatar
Miller Puckette committed
293 294
    int *indexp, int *totalp)
{
Mathieu L Bouchard's avatar
Mathieu L Bouchard committed
295
    int indx = 0, nobj = 0, n2, x1, x2, y1, y2;
296

297 298 299
    /*
    int connectme = 0;
    if (x->gl_editor->e_selection &&
300
        !x->gl_editor->e_selection->sel_next &&
301 302 303 304 305 306
        !sys_noautopatch)
    {
        selected = x->gl_editor->e_selection->sel_what;
        t_object *ob = pd_checkobject(&selected->g_pd);
        connectme = (obj_noutlets(ob) ? 1 : 0);
    }*/
307
    int connectme = (x->gl_editor->e_selection &&
308
        !x->gl_editor->e_selection->sel_next);
Miller Puckette's avatar
Miller Puckette committed
309 310
    if (connectme)
    {
Miller Puckette's avatar
Miller Puckette committed
311
        t_gobj *g, *selected = x->gl_editor->e_selection->sel_what;
312 313 314
        t_text *t = (t_text *)selected;
        // if selected object has not yet been activated we need to recreate it first
        if (pd_class(&t->te_pd) == text_class && t->te_type != T_TEXT)
Miller Puckette's avatar
Miller Puckette committed
315
        {
316 317 318
            glist_noselect(x); // we do this to explicitly activate object
            glist_select(x, glist_nth(x, glist_getindex(x, 0)-1)); // then reselect it
            selected = x->gl_editor->e_selection->sel_what;
Miller Puckette's avatar
Miller Puckette committed
319
        }
320
        for (g = x->gl_list, nobj = 0; g; g = g->g_next, nobj++)
321
        {
322 323 324 325 326
            if (g == selected)
            {
                gobj_getrect(g, x, &x1, &y1, &x2, &y2);
                indx = nobj;
                *xpixp = x1;
327
                *ypixp = y2 + get_autopatch_yoffset(x);
328
            }
329
        }
Miller Puckette's avatar
Miller Puckette committed
330 331 332 333 334 335 336 337 338 339 340 341 342
        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;
        }
343
        x->gl_editor->e_onmotion = MA_NONE;
344
        canvas_getscroll(x);
Miller Puckette's avatar
Miller Puckette committed
345 346 347 348 349
    }
    else
    {
        glist_getnextxy(x, xpixp, ypixp);
        glist_noselect(x);
Miller Puckette's avatar
Miller Puckette committed
350
    }
351 352 353 354 355
    if (sys_noautopatch)
    {
        if (connectme == 1) connectme = -1;
        else connectme = 0;
    }
Miller Puckette's avatar
Miller Puckette committed
356 357 358 359 360
    *connectp = connectme;
    *indexp = indx;
    *totalp = nobj;
}

Miller Puckette's avatar
Miller Puckette committed
361
    /* object creation routine.  These are called without any arguments if
Miller Puckette's avatar
Miller Puckette committed
362 363
    they're invoked from the gui; when pasting or restoring from a file, we
    get at least x and y. */
Miller Puckette's avatar
Miller Puckette committed
364

365 366
EXTERN int connect_exception;

Miller Puckette's avatar
Miller Puckette committed
367 368
void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
369
    //fprintf(stderr,"canvas_obj\n");
370
    if (canvas_hasarray(gl)) return;
Miller Puckette's avatar
Miller Puckette committed
371 372 373 374 375
    if (argc >= 2)
    {
        t_binbuf *b = binbuf_new();
        binbuf_restore(b, argc-2, argv+2);
        canvas_objtext(gl, atom_getintarg(0, argc, argv),
Jonathan Wilkes's avatar
Jonathan Wilkes committed
376
            atom_getintarg(1, argc, argv), 0, 0, b, 0);
Miller Puckette's avatar
Miller Puckette committed
377
    }
Miller Puckette's avatar
Miller Puckette committed
378 379 380 381 382
        /* 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
    {
383
            /* interactively create new object */
Miller Puckette's avatar
Miller Puckette committed
384
        t_binbuf *b = binbuf_new();
Miller Puckette's avatar
Miller Puckette committed
385 386
        int connectme, xpix, ypix, indx, nobj;
        canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
Miller Puckette's avatar
Miller Puckette committed
387
        pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
388 389
        canvas_objtext(gl,
            connectme ? xpix : xpix - 8,
390
            connectme ? ypix : ypix - 8,
Jonathan Wilkes's avatar
Jonathan Wilkes committed
391
            0, 1, b, connectme);
392 393 394 395
        if (connectme == 1)
        {
            //fprintf(stderr,"canvas_obj calls canvas_connect\n");
            connect_exception = 1;
Miller Puckette's avatar
Miller Puckette committed
396
            canvas_connect(gl, indx, 0, nobj, 0);
397 398 399 400 401
            connect_exception = 0;
        }
        else if (connectme == 0)
        {
            //fprintf(stderr,"canvas_obj calls canvas_startmotion\n");
402
            //canvas_displaceselection(glist_getcanvas(gl), -8, -8);
403 404 405 406 407 408 409
            canvas_startmotion(glist_getcanvas(gl));
        }
        //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)));
Miller Puckette's avatar
Miller Puckette committed
410 411 412
    }
}

413 414 415
extern void glist_setlastxy(t_glist *gl, int xval, int yval);

/* invoked from tcl/tk: abstraction_name x_offset y_offset */
416 417
void canvas_obj_abstraction_from_menu(t_glist *gl, t_symbol *s,
    int argc, t_atom *argv)
418
{
419
    if (canvas_hasarray(gl)) return;
420
    //fprintf(stderr,"canvas_abstraction_from_menu\n");
421
    //t_text *x;
422
    t_gobj *y;
423 424

    t_binbuf *b = binbuf_new();
425
    binbuf_restore(b, 2, argv);
426 427 428
    int connectme, xpix, ypix, indx, nobj;
    canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
    pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
429
#ifdef PDL2ORK
430 431
    if (sys_k12_mode)
        pd_vmess (&gl->gl_pd, gensym("tooltips"), "i", 1);
432
#endif
433
    canvas_objtext(gl, xpix+atom_getintarg(1, argc, argv),
Jonathan Wilkes's avatar
Jonathan Wilkes committed
434
        ypix+atom_getintarg(2, argc, argv), 0, 1, b, 0);
435 436 437 438 439 440 441 442 443

    // the object is now the last on the glist so we locate it
    // and send it loadbang
    // we know we have at least one object since we just created one
    // so we don't check for y being valid
    y = gl->gl_list;
    while (y->g_next)
        y = y->g_next;
    canvas_loadbang((t_canvas *)y);
444

445 446
    if (connectme == 1)
    {
447
        canvas_connect(gl, indx, 0, nobj, 0);
448 449 450
    }
    else if (connectme == 0)
    {
451
        //glist_setlastxy(glist_getcanvas(gl), xpix, ypix);
452 453 454 455
        canvas_startmotion(glist_getcanvas(gl));
    }
    canvas_undo_add(glist_getcanvas(gl), 9, "create",
        (void *)canvas_undo_set_create(glist_getcanvas(gl)));
456 457
}

Miller Puckette's avatar
Miller Puckette committed
458 459 460 461 462
/* make an object box for an object that's already there. */

/* iemlib */
void canvas_iemguis(t_glist *gl, t_symbol *guiobjname)
{
463
    if (canvas_hasarray(gl)) return;
464
    //fprintf(stderr,"canvas_iemguis\n");
Miller Puckette's avatar
Miller Puckette committed
465 466
    t_atom at;
    t_binbuf *b = binbuf_new();
467 468
    //int xpix, ypix;

469
    if (!strcmp(guiobjname->s_name, "cnv"))
470
        glist_noselect(gl);
471

472
    int connectme, xpix, ypix, indx, nobj;
473

474 475
    canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);

476 477 478 479
    /* NOT NECESSARY ANY MORE: compensate for the iemgui sliders' xyoffset
       in case of autopatch
    if (connectme)
    {
480
        if (!strcmp(guiobjname->s_name, "hsl"))
481
            xpix = xpix + 3;
482
        else if (!strcmp(guiobjname->s_name, "vsl"))
483
            ypix = ypix + 2;
484
        else if (!strcmp(guiobjname->s_name, "vu"))
485 486 487 488 489 490
        {
            xpix = xpix + 1;
            ypix = ypix + 2;
        }
    }*/
    
Miller Puckette's avatar
Miller Puckette committed
491 492 493 494
    pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
    glist_noselect(gl);
    SETSYMBOL(&at, guiobjname);
    binbuf_restore(b, 1, &at);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
495
    canvas_objtext(gl, xpix, ypix, 0, 1, b, 0);
496
    if (connectme == 1)
497 498
        canvas_connect(gl, indx, 0, nobj, 0);
    //glist_getnextxy(gl, &xpix, &ypix);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
499
    //canvas_objtext(gl, xpix, ypix, 1, b, 0);
500 501
    else if (connectme == 0)
    {
502
        canvas_displaceselection(glist_getcanvas(gl), -8, -8);
503 504
        canvas_startmotion(glist_getcanvas(gl));
    }
505 506 507 508
    //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)));
Miller Puckette's avatar
Miller Puckette committed
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
}

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;
584
    t_glist *mr_glist;
Miller Puckette's avatar
Miller Puckette committed
585 586 587 588 589 590 591 592 593 594 595
    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;

596
t_class *messresponder_class;
Miller Puckette's avatar
Miller Puckette committed
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612

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);
}

613 614 615 616 617
/* MP 20070107 blob type */
//static void messresponder_blob(t_messresponder *x, t_blob *st)
//{
//    outlet_blob(x->mr_outlet, st);
//}
Hans-Christoph Steiner's avatar
Hans-Christoph Steiner committed
618

Miller Puckette's avatar
Miller Puckette committed
619 620 621 622 623 624 625 626 627 628 629 630
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);
}

631 632 633 634 635 636
/* get the glist cached in a message responder */
t_glist *messresponder_getglist(t_pd *x)
{
    return ((t_messresponder *)x)->mr_glist;
}

Miller Puckette's avatar
Miller Puckette committed
637 638
static void message_bang(t_message *x)
{
639 640
    /*  we do canvas_setcurrent/unsetcurrent to substitute canvas
        instance number for $0 */
Miller Puckette's avatar
Miller Puckette committed
641 642 643 644 645 646 647
    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);
648 649
    /*  we do canvas_setcurrent/unsetcurrent to substitute canvas
        instance number for $0 */
Miller Puckette's avatar
Miller Puckette committed
650 651 652 653 654 655 656
    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);
657 658
    /*  we do canvas_setcurrent/unsetcurrent to substitute canvas
        instance number for $0 */
Miller Puckette's avatar
Miller Puckette committed
659 660 661
    binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
}

Hans-Christoph Steiner's avatar
Hans-Christoph Steiner committed
662 663 664 665
static void message_blob(t_message *x, t_blob *st)
{
    t_atom at;
    SETBLOB(&at, st);
666 667
    /*  we do canvas_setcurrent/unsetcurrent to substitute canvas
        instance number for $0 */
Hans-Christoph Steiner's avatar
Hans-Christoph Steiner committed
668 669 670
    binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
}

Miller Puckette's avatar
Miller Puckette committed
671 672
static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv)
{
673 674 675
    // TODO: here and elsewhere in the message, do we want $0 to be parsed
    // into canvas instance? Makes sense since there is no such argument,
    // but will this break anything?
676 677
    /*  we do canvas_setcurrent/unsetcurrent to substitute canvas
        instance number for $0 */
Miller Puckette's avatar
Miller Puckette committed
678 679 680 681 682 683 684 685
    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);
686
    if (glist_isvisible(glist_getcanvas(x->m_glist)))
687
        canvas_getscroll(x->m_glist);
Miller Puckette's avatar
Miller Puckette committed
688 689 690 691 692 693
}

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);
694
    if (glist_isvisible(glist_getcanvas(x->m_glist)))
695
        canvas_getscroll(x->m_glist);
Miller Puckette's avatar
Miller Puckette committed
696 697 698 699 700 701 702
}

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);
703
    if (glist_isvisible(glist_getcanvas(x->m_glist)))
704
        canvas_getscroll(x->m_glist);
Miller Puckette's avatar
Miller Puckette committed
705 706 707 708 709 710 711 712
}

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);
713
    if (glist_isvisible(glist_getcanvas(x->m_glist)))
714
        canvas_getscroll(x->m_glist);
Miller Puckette's avatar
Miller Puckette committed
715 716 717 718 719
}

static void message_addsemi(t_message *x)
{
    message_add(x, 0, 0, 0);
720
    if (glist_isvisible(glist_getcanvas(x->m_glist)))
721
        canvas_getscroll(x->m_glist);
Miller Puckette's avatar
Miller Puckette committed
722 723 724 725 726 727 728 729 730 731 732
}

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);
733
    if (glist_isvisible(glist_getcanvas(x->m_glist)))
734
        canvas_getscroll(x->m_glist);
Miller Puckette's avatar
Miller Puckette committed
735 736 737 738 739 740 741 742 743 744 745 746
}

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);
747
    if (glist_isvisible(glist_getcanvas(x->m_glist)))
748
        canvas_getscroll(x->m_glist);
Miller Puckette's avatar
Miller Puckette committed
749 750 751 752 753 754 755 756 757 758
}

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);
759
        gui_vmess("gui_message_flash", "xsi",
760
            glist_getcanvas(x->m_glist), rtext_gettag(y), 1);
Miller Puckette's avatar
Miller Puckette committed
761 762 763 764 765 766 767 768 769
        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);
770
        gui_vmess("gui_message_flash", "xsi",
771
            glist_getcanvas(x->m_glist), rtext_gettag(y), 0);
Miller Puckette's avatar
Miller Puckette committed
772 773 774 775 776 777 778 779
    }
}

static void message_free(t_message *x)
{
    clock_free(x->m_clock);
}

780 781 782 783 784 785 786 787 788 789 790 791 792
t_pd *pd_mess_from_responder(t_pd *x)
{
    if (pd_class(x) == messresponder_class)
    {
        /* do pointer math to try to get to the container message struct */
        void *tmp = (void *)x - sizeof(t_text);
        /* if it looks like a message, it must be a message */
        if(((t_text *)tmp)->te_pd == message_class)
            return ((t_pd *)tmp);
    }
    return x;
}

Miller Puckette's avatar
Miller Puckette committed
793 794
void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
795
    if (canvas_hasarray(gl)) return;
796 797 798 799 800 801 802 803 804 805 806
    /*fprintf(stderr,"canvas_msg\n");
    int i = 0;
    while(i < argc)
    {
        if (argv[i].a_type == A_FLOAT)
            fprintf(stderr," %f", atom_getfloatarg(i, argc, argv));
        else
            fprintf(stderr," %s", atom_getsymbolarg(i, argc, argv)->s_name);
        i++;
    }
    fprintf(stderr,"\n");*/
Miller Puckette's avatar
Miller Puckette committed
807 808 809
    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);
810
    x->m_messresponder.mr_glist = gl;
Miller Puckette's avatar
Miller Puckette committed
811 812
    x->m_text.te_width = 0;                             /* don't know it yet. */
    x->m_text.te_type = T_MESSAGE;
813
    x->m_text.te_iemgui = 0;
Miller Puckette's avatar
Miller Puckette committed
814 815 816 817 818 819 820 821 822 823
    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);
    }
Miller Puckette's avatar
Miller Puckette committed
824 825
    else if (!glist_isvisible(gl))
        post("unable to create stub message in closed canvas!");
Miller Puckette's avatar
Miller Puckette committed
826 827
    else
    {
Miller Puckette's avatar
Miller Puckette committed
828 829 830
        int connectme, xpix, ypix, indx, nobj;
        canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
        
Miller Puckette's avatar
Miller Puckette committed
831
        pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
Miller Puckette's avatar
Miller Puckette committed
832 833
        x->m_text.te_xpix = xpix;
        x->m_text.te_ypix = ypix;
Miller Puckette's avatar
Miller Puckette committed
834 835 836
        glist_add(gl, &x->m_text.te_g);
        glist_noselect(gl);
        glist_select(gl, &x->m_text.te_g);
837
        gobj_activate(&x->m_text.te_g, gl,
838
            connectme ? 1 : 2); // <-- hack to signal we're a new message box
839
        if (connectme == 1)
Miller Puckette's avatar
Miller Puckette committed
840
            canvas_connect(gl, indx, 0, nobj, 0);
841 842
        else if (connectme == 0)
        {
843
            canvas_displaceselection(glist_getcanvas(gl), -8, -8);
844 845
            canvas_startmotion(glist_getcanvas(gl));
        }
846 847 848 849
        //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)));
Miller Puckette's avatar
Miller Puckette committed
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 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910
    }
}

/* ---------------------- 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);
}

911 912
    /* recolor option offers     0 ignore recolor
                                1 recolor */
913 914
static void gatom_retext(t_gatom *x, int senditup, int recolor)
{
915 916 917
    t_canvas *canvas = glist_getcanvas(x->a_glist);
    t_rtext *y = glist_findrtext(x->a_glist, &x->a_text);
    if (recolor)
user's avatar
user committed
918
    {
919
        gui_vmess("gui_gatom_activate", "xsi",
920
            canvas, rtext_gettag(y), 0);
user's avatar
user committed
921
    }
Miller Puckette's avatar
Miller Puckette committed
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
    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)
940 941 942 943 944 945
    {
        if (x->a_atom.a_type == A_FLOAT && x->a_text.te_width == 1)
            gatom_retext(x, 1, 1);
        else
            gatom_retext(x, 1, 0);
    }
Miller Puckette's avatar
Miller Puckette committed
946 947 948 949 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 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
    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)
{
1047
    //fprintf(stderr,"gatom_key %f\n", f);
Miller Puckette's avatar
Miller Puckette committed
1048 1049 1050 1051 1052 1053 1054 1055 1056
    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])
1057
            gatom_retext(x, 1, 1);
1058 1059
        else
            gatom_retext(x, 0, 1);
Miller Puckette's avatar
Miller Puckette committed
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
        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);
1076
        gatom_retext(x, 1, 0);
Miller Puckette's avatar
Miller Puckette committed
1077
        x->a_buf[0] = 0;
1078 1079 1080
        /* We want to keep grabbing the keyboard after hitting "Enter", so
           we're commenting the following out */
        //glist_grab(x->a_glist, 0, 0, 0, 0, 0);
Miller Puckette's avatar
Miller Puckette committed
1081 1082 1083 1084 1085 1086 1087 1088
    }
    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'))
        {
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
            /* the wchar could expand to up to 4 bytes, which
             * which might overrun our a_buf;
             * therefore we first expand into a temporary buffer, 
             * and only if the resulting utf8 string fits into a_buf
             * we apply it
             */
            char utf8[UTF8_MAXBYTES];
            int utf8len = u8_wc_toutf8(utf8, c);
            if((len+utf8len) < (ATOMBUFSIZE-1))
            {
                int j=0;
                for(j=0; j<utf8len; j++)
                    x->a_buf[len+j] = utf8[j];
                 
                x->a_buf[len+utf8len] = 0;
            }
Miller Puckette's avatar
Miller Puckette committed
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
            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);
            }
            else gatom_float(x, x->a_toggle);
1138 1139
            gatom_retext(x, 0, 1);
            return;
Miller Puckette's avatar
Miller Puckette committed
1140 1141 1142 1143 1144 1145 1146 1147
        }
        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);
    }
}

1148 1149 1150
EXTERN int glist_getindex(t_glist *x, t_gobj *y);
EXTERN int canvas_apply_restore_original_position(t_canvas *x, int pos);

Miller Puckette's avatar
Miller Puckette committed
1151 1152 1153
    /* message back from dialog window */
static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv)
{