diff --git a/src/g_editor.c b/src/g_editor.c index 38a4cbf28dd48534ee0a96cd11e17c402db0f8d1..80b484e67ef1eeb581c5b34843ed7a1c83db513d 100644 --- a/src/g_editor.c +++ b/src/g_editor.c @@ -431,6 +431,8 @@ static const char *canvas_undo_name; void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf, const char *name) { + //fprintf(stderr,"canvas_setundo %lx\n", (t_int)x); + int hadone = 0; /* blow away the old undo information. In one special case the old undo info is re-used; if so we shouldn't free it here. */ @@ -1318,6 +1320,86 @@ void canvas_canvas_setundo(t_canvas *x) canvas_setundo(x, canvas_undo_canvas_apply, canvas_undo_set_canvas(x), "apply"); } +/* --------- 8. create ----------- */ + +typedef struct _undo_create +{ + int u_index; /* index of the created object object */ + t_binbuf *u_objectbuf; /* the object cleared or typed into */ + t_binbuf *u_reconnectbuf; /* connections into and out of object */ +} t_undo_create; + +void *canvas_undo_set_create(t_canvas *x) +{ + t_gobj *y, *last; + t_linetraverser t; + t_outconnect *oc; + + t_undo_create *buf = (t_undo_create *)getbytes(sizeof(*buf)); + buf->u_index = glist_getindex(x, 0) - 1; + int nnotsel= glist_selectionindex(x, 0, 0); + + buf->u_objectbuf = binbuf_new(); + for (y = x->gl_list; y; y = y->g_next) + { + if (glist_isselected(x, y)) { + //fprintf(stderr,"saving object\n"); + gobj_save(y, buf->u_objectbuf); + } + } + buf->u_reconnectbuf = binbuf_new(); + linetraverser_start(&t, x); + while (oc = linetraverser_next(&t)) + { + int issel1 = glist_isselected(x, &t.tr_ob->ob_g); + int issel2 = glist_isselected(x, &t.tr_ob2->ob_g); + if (issel1 != issel2) + { + binbuf_addv(buf->u_reconnectbuf, "ssiiii;", + gensym("#X"), gensym("connect"), + (issel1 ? nnotsel : 0) + + glist_selectionindex(x, &t.tr_ob->ob_g, issel1), + t.tr_outno, + (issel2 ? nnotsel : 0) + + glist_selectionindex(x, &t.tr_ob2->ob_g, issel2), + t.tr_inno); + } + } + return (buf); +} + +void canvas_undo_create(t_canvas *x, void *z, int action) +{ + t_undo_create *buf = z; + t_gobj *y; + + //fprintf(stderr,"canvas = %lx buf->u_index = %d\n", (t_int)x, buf->u_index); + + if (action == UNDO_UNDO) + { + glist_noselect(x); + y = glist_nth(x, buf->u_index); + glist_select(x, y); + canvas_doclear(x); + } + else if (action == UNDO_REDO) + { + pd_bind(&x->gl_pd, gensym("#X")); + binbuf_eval(buf->u_objectbuf, 0, 0, 0); + pd_unbind(&x->gl_pd, gensym("#X")); + pd_bind(&x->gl_pd, gensym("#X")); + binbuf_eval(buf->u_reconnectbuf, 0, 0, 0); + pd_unbind(&x->gl_pd, gensym("#X")); + y = glist_nth(x, buf->u_index); + glist_select(x, y); + } + else if (action == UNDO_FREE) { + binbuf_free(buf->u_objectbuf); + binbuf_free(buf->u_reconnectbuf); + t_freebytes(buf, sizeof(*buf)); + } +} + /* ------------------------ event handling ------------------------ */ static char *cursorlist[] = { @@ -3229,49 +3311,31 @@ void canvas_restoreconnections(t_canvas *x) static t_binbuf *canvas_docopy(t_canvas *x) { - //fprintf(stderr,"docopy\n"); + //fprintf(stderr,"canvas_docopy\n"); t_gobj *y, *last; t_linetraverser t; t_outconnect *oc; t_binbuf *b = binbuf_new(); - //int c = 0; for (y = x->gl_list; y; y = y->g_next) { if (glist_isselected(x, y)) { - //c++; - //fprintf(stderr, "saving object num %d\n", c); - //fprintf(stderr, "saving object >.x%lx<\n", (t_int)y); - /* introduce redundant comment to avoid recreation of old abstractions - with the same canvas id which results in all commands being registered - multiple times--apparently after much searching it appears that this - is yet another bug in tcl/tk which means that canvas tries to do some - kind of caching behind the curtains resulting in objects not always - having unique ids, contrary to tcl/tk's canvas man page */ - /*if (c==1) { - binbuf_addv(b, "ssiis;", gensym("#X"), gensym("text"), - (int)((t_text *)y)->te_xpix-30, (int)((t_text *)y)->te_ypix-30, gensym("tcltksucks")); - }*/ + //fprintf(stderr,"saving object\n"); gobj_save(y, b); } } - //fprintf(stderr,"done saving objects\n"); linetraverser_start(&t, x); - //c = 0; while (oc = linetraverser_next(&t)) { + //fprintf(stderr,"found some lines %d %d\n", glist_isselected(x, &t.tr_ob->ob_g), glist_isselected(x, &t.tr_ob2->ob_g)); if (glist_isselected(x, &t.tr_ob->ob_g) && glist_isselected(x, &t.tr_ob2->ob_g)) { - //fprintf(stderr, "lines need to be copied\n"); - //c = 1; + //fprintf(stderr,"saving lines leading into selected object\n"); binbuf_addv(b, "ssiiii;", gensym("#X"), gensym("connect"), glist_selectionindex(x, &t.tr_ob->ob_g, 1), t.tr_outno, glist_selectionindex(x, &t.tr_ob2->ob_g, 1), t.tr_inno); -// glist_selectionindex(x, &t.tr_ob->ob_g, 1)+1, t.tr_outno, -// glist_selectionindex(x, &t.tr_ob2->ob_g, 1)+1, t.tr_inno); } } - //if (!c) fprintf(stderr, "no lines copied\n"); return (b); } @@ -3290,7 +3354,7 @@ static void canvas_copyfromexternalbuffer(t_canvas *x, t_symbol *s, int ac, t_at binbuf_add(copy_binbuf, ac, av); binbuf_addsemi(copy_binbuf); } else { - //probably should resize window size here... + //probably should resize window size and position here... //fprintf(stderr,"ignoring canvas\n"); } } diff --git a/src/g_graph.c b/src/g_graph.c index 3ac48c68ac35fa8bf38ac6b41da882e459f011b9..fdf21f25e6f7f24b52a184ab7ca8b159b318432b 100644 --- a/src/g_graph.c +++ b/src/g_graph.c @@ -29,17 +29,27 @@ void canvas_drawredrect(t_canvas *x, int doit); void glist_add(t_glist *x, t_gobj *y) { - t_object *ob; + //fprintf(stderr,"glist_add %lx %d\n", (t_int)x, (x->gl_editor ? 1 : 0)); + t_object *ob; y->g_next = 0; + int index = 0; + if (!x->gl_list) x->gl_list = y; else { t_gobj *y2; - for (y2 = x->gl_list; y2->g_next; y2 = y2->g_next); + for (y2 = x->gl_list; y2->g_next; y2 = y2->g_next) + index++; y2->g_next = y; } - if (x->gl_editor && (ob = pd_checkobject(&y->g_pd))) + if (x->gl_editor && (ob = pd_checkobject(&y->g_pd))) { rtext_new(x, ob); + //let's now set up create undo + //glist_select(x, y); + //canvas_setundo(x, canvas_undo_create, canvas_undo_set_create(x, index), + // "create"); + //glist_noselect(x); + } if (x->gl_editor && x->gl_isgraph && !x->gl_goprect && pd_checkobject(&y->g_pd)) { diff --git a/src/g_text.c b/src/g_text.c index 0ff6a3980e6c0aa3f06484f6916fabc791319e08..b40af744621302c064b06341bd83fbb91cf0939c 100644 --- a/src/g_text.c +++ b/src/g_text.c @@ -30,7 +30,10 @@ t_widgetbehavior text_widgetbehavior; static char *invalid_fill = "\"#ffdddd\""; -EXTERN void canvas_apply_setundo(t_canvas *x, t_gobj *y); +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); /* ----------------- the "text" object. ------------------ */ @@ -89,7 +92,7 @@ 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,"objtext\n"); + //fprintf(stderr,"canvas_objtext\n"); t_text *x; int argc; t_atom *argv; @@ -202,6 +205,7 @@ void canvas_howputnew(t_canvas *x, int *connectp, int *xpixp, int *ypixp, 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) { @@ -224,6 +228,7 @@ void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv) if (connectme) canvas_connect(gl, indx, 0, nobj, 0); else canvas_startmotion(glist_getcanvas(gl)); + canvas_setundo(gl, canvas_undo_create, canvas_undo_set_create(gl), "create"); } } @@ -265,6 +270,7 @@ void canvas_iemguis(t_glist *gl, t_symbol *guiobjname) //glist_getnextxy(gl, &xpix, &ypix); //canvas_objtext(gl, xpix, ypix, 1, b); else canvas_startmotion(glist_getcanvas(gl)); + canvas_setundo(gl, canvas_undo_create, canvas_undo_set_create(gl), "create"); } void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv) @@ -535,6 +541,7 @@ void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv) if (connectme) canvas_connect(gl, indx, 0, nobj, 0); else canvas_startmotion(glist_getcanvas(gl)); + canvas_setundo(gl, canvas_undo_create, canvas_undo_set_create(gl), "create"); } } @@ -921,6 +928,7 @@ static void gatom_vis(t_gobj *z, t_glist *glist, int vis) void canvas_atom(t_glist *gl, t_atomtype type, t_symbol *s, int argc, t_atom *argv) { + //fprintf(stderr,"canvas_atom\n"); t_gatom *x = (t_gatom *)pd_new(gatom_class); t_atom at; x->a_text.te_width = 0; /* don't know it yet. */ @@ -993,6 +1001,7 @@ void canvas_atom(t_glist *gl, t_atomtype type, if (connectme) canvas_connect(gl, indx, 0, nobj, 0); else canvas_startmotion(glist_getcanvas(gl)); + canvas_setundo(gl, canvas_undo_create, canvas_undo_set_create(gl), "create"); } }