diff --git a/src/g_editor.c b/src/g_editor.c index 3436937fa2dde9a517820772bcf548b861c0fb51..3d0bb10bacf9d0b7a9301918fd7af72cd7ffb3b0 100644 --- a/src/g_editor.c +++ b/src/g_editor.c @@ -247,7 +247,7 @@ int glist_isselected(t_glist *x, t_gobj *y) /* call this for unselected objects only */ void glist_select(t_glist *x, t_gobj *y) { - fprintf(stderr,"glist_select\n"); + //fprintf(stderr,"glist_select\n"); if (x->gl_editor) { if (c_selection && c_selection != x) @@ -303,7 +303,7 @@ void glist_deselect(t_glist *x, t_gobj *y) //fprintf(stderr, "e_textedfor == fuddy\n"); if (x->gl_editor->e_textdirty) { - fprintf(stderr, "textdirty yes\n"); + //fprintf(stderr, "textdirty yes\n"); z = fuddy; canvas_stowconnections(glist_getcanvas(x)); glist_checkanddeselectall(x, y); @@ -354,7 +354,7 @@ void glist_deselect(t_glist *x, t_gobj *y) void glist_noselect(t_glist *x) { - fprintf(stderr,"glist_noselect\n"); + //fprintf(stderr,"glist_noselect\n"); if (x->gl_editor) { if (x->gl_editor->e_selection) { @@ -614,7 +614,7 @@ typedef struct _undo_cut /* at least one object is selected, we dynamically resize it later */ } t_undo_cut; -static void *canvas_undo_set_cut(t_canvas *x, int mode) +void *canvas_undo_set_cut(t_canvas *x, int mode) { t_undo_cut *buf; t_gobj *y; @@ -682,7 +682,7 @@ static void *canvas_undo_set_cut(t_canvas *x, int mode) return (buf); } -static void canvas_undo_cut(t_canvas *x, void *z, int action) +void canvas_undo_cut(t_canvas *x, void *z, int action) { //fprintf(stderr, "canvas_undo_cut canvas=%d buf=%d action=%d\n", (int)x, (int)z, action); t_undo_cut *buf = z; @@ -902,13 +902,23 @@ void canvas_undo_move(t_canvas *x, void *z, int action) typedef struct _undo_paste { - int u_index; /* index of first object pasted */ + int u_index; /* index of first object pasted */ + int u_sel_index; /* index of object selected at the time the other object was pasted (for autopatching) */ + t_binbuf *u_objectbuf; /* here we store actual copied data */ } t_undo_paste; void *canvas_undo_set_paste(t_canvas *x, int offset) { t_undo_paste *buf = (t_undo_paste *)getbytes(sizeof(*buf)); - buf->u_index = glist_getindex(x, 0) - offset; + buf->u_index = glist_getindex(x, 0) - offset; //do we need offset at all? + if (x->gl_editor->e_selection && !x->gl_editor->e_selection->sel_next) { + //if only one object is selected which will warrant autopatching + buf->u_sel_index = glist_getindex(x, x->gl_editor->e_selection->sel_what); + fprintf(stderr,"canvas_undo_set_paste selected object index %d\n", buf->u_sel_index); + } else { + buf->u_sel_index = -1; + } + buf->u_objectbuf = binbuf_duplicate(copy_binbuf); return (buf); } @@ -926,15 +936,23 @@ void canvas_undo_paste(t_canvas *x, void *z, int action) else if (action == UNDO_REDO) { t_selection *sel; - canvas_dopaste(x, copy_binbuf); + glist_noselect(x); + //if the pasted object is supposed to be autopatched + //then select the object it should be autopatched to + if (buf->u_sel_index > -1) + glist_select(x, glist_nth(x, buf->u_sel_index)); + canvas_dopaste(x, buf->u_objectbuf); /* if it was "duplicate" have to re-enact the displacement. */ if (canvas_undo_name && canvas_undo_name[0] == 'd') //for (sel = x->gl_editor->e_selection; sel; sel = sel->sel_next) // gobj_displace(sel->sel_what, x, 10, 10); canvas_paste_xyoffset(x); } - else if (action == UNDO_FREE) + else if (action == UNDO_FREE) { + if (buf->u_objectbuf) + binbuf_free(buf->u_objectbuf); t_freebytes(buf, sizeof(*buf)); + } } /* recursively check for abstractions to reload as result of a save. @@ -964,8 +982,9 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir, canvas_vis(glist_getcanvas(gl), 1); glist_noselect(gl); glist_select(gl, g); - canvas_setundo(gl, canvas_undo_cut, - canvas_undo_set_cut(gl, UCUT_CLEAR), "clear"); + //canvas_setundo(gl, canvas_undo_cut, + // canvas_undo_set_cut(gl, UCUT_CLEAR), "clear"); + canvas_undo_add(gl, 3, "clear", canvas_undo_set_cut(gl, UCUT_CLEAR)); canvas_doclear(gl); canvas_undo(gl); glist_noselect(gl); @@ -1454,6 +1473,8 @@ void canvas_canvas_setundo(t_canvas *x) /* --------- 9. create ----------- */ +extern t_pd *newest; + typedef struct _undo_create { int u_index; /* index of the created object object */ @@ -1471,7 +1492,7 @@ void *canvas_undo_set_create(t_canvas *x) 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); - fprintf(stderr,"buf->u_index=%d nnotsel=%d\n", buf->u_index, nnotsel); + //fprintf(stderr,"buf->u_index=%d nnotsel=%d\n", buf->u_index, nnotsel); buf->u_objectbuf = binbuf_new(); if (x->gl_list) { @@ -1479,7 +1500,7 @@ void *canvas_undo_set_create(t_canvas *x) { //if (glist_isselected(x, y)) { if (!y->g_next) { - fprintf(stderr,"undo_set_create: gobj_save\n"); + //fprintf(stderr,"undo_set_create: gobj_save\n"); gobj_save(y, buf->u_objectbuf); break; } @@ -1492,10 +1513,10 @@ void *canvas_undo_set_create(t_canvas *x) //int issel2 = glist_isselected(x, &t.tr_ob2->ob_g); issel1 = ( &t.tr_ob->ob_g == y ? 1 : 0); issel2 = ( &t.tr_ob2->ob_g == y ? 1 : 0); - fprintf(stderr,"undo_set_create linetraverser %d %d\n", issel1, issel2); + //fprintf(stderr,"undo_set_create linetraverser %d %d\n", issel1, issel2); if (issel1 != issel2) { - fprintf(stderr,"undo_set_create store connection\n"); + //fprintf(stderr,"undo_set_create store connection\n"); binbuf_addv(buf->u_reconnectbuf, "ssiiii;", gensym("#X"), gensym("connect"), (issel1 ? nnotsel : 0) @@ -1536,6 +1557,8 @@ void canvas_undo_create(t_canvas *x, void *z, int action) pd_bind(&x->gl_pd, gensym("#X")); binbuf_eval(buf->u_reconnectbuf, 0, 0, 0); pd_unbind(&x->gl_pd, gensym("#X")); + if (newest && pd_class(newest) == canvas_class) + canvas_loadbang((t_canvas *)newest); y = glist_nth(x, buf->u_index); glist_select(x, y); } @@ -1557,11 +1580,12 @@ void *canvas_undo_set_recreate(t_canvas *x, t_gobj *y) int issel1, issel2; t_undo_create *buf = (t_undo_create *)getbytes(sizeof(*buf)); - buf->u_index = glist_getindex(x, y); // - 1; TODO: do we still need a -1 here??? + buf->u_index = glist_getindex(x, y); int nnotsel= glist_selectionindex(x, 0, 0) - 1; // - 1 is a critical difference from the create - fprintf(stderr,"buf->u_index=%d nnotsel=%d\n", buf->u_index, nnotsel); + //fprintf(stderr,"buf->u_index=%d nnotsel=%d\n", buf->u_index, nnotsel); buf->u_objectbuf = binbuf_new(); - fprintf(stderr,"undo_set_create: gobj_save\n"); + //y = glist_nth(x, buf->u_index); + //fprintf(stderr,"undo_set_create: gobj_save\n"); gobj_save(y, buf->u_objectbuf); buf->u_reconnectbuf = binbuf_new(); @@ -1572,10 +1596,10 @@ void *canvas_undo_set_recreate(t_canvas *x, t_gobj *y) //int issel2 = glist_isselected(x, &t.tr_ob2->ob_g); issel1 = ( &t.tr_ob->ob_g == y ? 1 : 0); issel2 = ( &t.tr_ob2->ob_g == y ? 1 : 0); - fprintf(stderr,"undo_set_create linetraverser %d %d\n", issel1, issel2); + //fprintf(stderr,"undo_set_create linetraverser %d %d\n", issel1, issel2); if (issel1 != issel2) { - fprintf(stderr,"undo_set_create store connection\n"); + //fprintf(stderr,"undo_set_create store connection\n"); binbuf_addv(buf->u_reconnectbuf, "ssiiii;", gensym("#X"), gensym("connect"), (issel1 ? nnotsel : 0) @@ -1591,33 +1615,122 @@ void *canvas_undo_set_recreate(t_canvas *x, t_gobj *y) void canvas_undo_recreate(t_canvas *x, void *z, int action) { + //fprintf(stderr,"canvas_undo_recreate\n"); + t_undo_create *buf = z; - t_gobj *y; + t_gobj *y = glist_nth(x, buf->u_index); //fprintf(stderr,"canvas = %lx buf->u_index = %d\n", (t_int)x, buf->u_index); if (action == UNDO_UNDO || action == UNDO_REDO) { - /*TODO: copy new state of the current object - then cut the existing object - then paste old object - then free old data buffer and make it point to the new buffer - then reorder the object so that it is placed in the same order as the old one - - glist_noselect(x); - y = glist_nth(x, buf->u_index); - - + // first copy new state of the current object + t_linetraverser t; + t_outconnect *oc; + int issel1, issel2; + + t_undo_create *buf2 = (t_undo_create *)getbytes(sizeof(*buf)); + buf2->u_index = glist_getindex(x, y); + int nnotsel= glist_selectionindex(x, 0, 0) - 1; // - 1 is a critical difference from the create + //fprintf(stderr,"buf2->u_index=%d nnotsel=%d\n", buf2->u_index, nnotsel); + buf2->u_objectbuf = binbuf_new(); + //fprintf(stderr,"undo_set_recreate: gobj_save\n"); + gobj_save(y, buf2->u_objectbuf); + + buf2->u_reconnectbuf = binbuf_new(); + linetraverser_start(&t, x); + while (oc = linetraverser_next(&t)) + { + issel1 = ( &t.tr_ob->ob_g == y ? 1 : 0); + issel2 = ( &t.tr_ob2->ob_g == y ? 1 : 0); + //fprintf(stderr,"undo_set_recreate linetraverser %d %d\n", issel1, issel2); + if (issel1 != issel2) + { + //fprintf(stderr,"undo_set_recreate store connection\n"); + binbuf_addv(buf2->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); + } + } + // now then cut the existing object + glist_noselect(x); glist_select(x, y); canvas_doclear(x); + // then paste the old object 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")); + + // free the old data + binbuf_free(buf->u_objectbuf); + binbuf_free(buf->u_reconnectbuf); + t_freebytes(buf, sizeof(*buf)); + + // readjust pointer + // (this should probably belong into g_undo.c, but since it is a unique case, we'll let it be for the time being) + x->u_last->data = (void *)buf2; + buf = buf2; + + // reposition object to its original place + t_gobj *y_prev, *y_next; + //get the last object + y = glist_nth(x, glist_getindex(x, 0) - 1); + /*for (y = x->gl_list; y; y = y->g_next) + if (!y->g_next) + break;*/ + // first check if we are in the same position already + if (glist_getindex(x, y) != buf->u_index) { + //fprintf(stderr,"not in the right place\n"); + y_prev = glist_nth(x, buf->u_index-1); + y_next = glist_nth(x, buf->u_index); + //if the object is supposed to be first in the gl_list + if (buf->u_index == 0) { + if (y_prev && y_next) { + y_prev->g_next = y_next; + } + else if (y_prev && !y_next) + y_prev->g_next = NULL; + //now put the moved object at the beginning of the cue + y->g_next = glist_nth(x, 0); + x->gl_list = y; + } + //if the object is supposed to be at the current end of gl_list + //can this ever happen??? + /*else if (!glist_nth(x,buf->p_a[i])) { + + }*/ + //if the object is supposed to be in the middle of gl_list + else { + if (y_prev && y_next) { + y_prev->g_next = y_next; + } + else if (y_prev && !y_next) { + y_prev->g_next = NULL; + } + //now put the moved object in its right place + y_prev = glist_nth(x, buf->u_index-1); + y_next = glist_nth(x, buf->u_index); + + y_prev->g_next = y; + y->g_next = y_next; + } + } + + // send a loadbang + if (newest && pd_class(newest) == canvas_class) + canvas_loadbang((t_canvas *)newest); + + // select y = glist_nth(x, buf->u_index); glist_select(x, y); } @@ -1797,7 +1910,7 @@ void canvas_vis(t_canvas *x, t_floatarg f) int flag = (f != 0); if (x != glist_getcanvas(x) && glist_isvisible(glist_getcanvas(x))) { bug("canvas_vis"); - fprintf(stderr,"canvas_vis .x%lx .x%lx %f\n", (t_int)x, (t_int)glist_getcanvas(x), f); + //fprintf(stderr,"canvas_vis .x%lx .x%lx %f\n", (t_int)x, (t_int)glist_getcanvas(x), f); } if (flag) { @@ -3135,8 +3248,9 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av) /* send the key to the box's editor */ if (!x->gl_editor->e_textdirty) { - canvas_setundo(x, canvas_undo_cut, - canvas_undo_set_cut(x, UCUT_TEXT), "typing"); + //canvas_setundo(x, canvas_undo_cut, + // canvas_undo_set_cut(x, UCUT_TEXT), "typing"); + canvas_undo_add(x, 3, "typing", canvas_undo_set_cut(x, UCUT_TEXT)); } rtext_key(x->gl_editor->e_textedfor, (int)keynum, gotkeysym); @@ -3151,8 +3265,9 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av) canvas_clearline(x); else if (x->gl_editor->e_selection) { - canvas_setundo(x, canvas_undo_cut, - canvas_undo_set_cut(x, UCUT_CLEAR), "clear"); + //canvas_setundo(x, canvas_undo_cut, + // canvas_undo_set_cut(x, UCUT_CLEAR), "clear"); + canvas_undo_add(x, 3, "clear", canvas_undo_set_cut(x, UCUT_CLEAR)); canvas_doclear(x); } } @@ -3533,7 +3648,7 @@ void canvas_finderror(void *error_object) void canvas_stowconnections(t_canvas *x) { - fprintf(stderr,"canvas_stowconnections\n"); + //fprintf(stderr,"canvas_stowconnections\n"); t_gobj *selhead = 0, *seltail = 0, *nonhead = 0, *nontail = 0, *y, *y2; t_linetraverser t; t_outconnect *oc; @@ -3592,7 +3707,7 @@ void canvas_stowconnections(t_canvas *x) void canvas_restoreconnections(t_canvas *x) { - fprintf(stderr,"canvas_restoreconnections\n"); + //fprintf(stderr,"canvas_restoreconnections\n"); pd_bind(&x->gl_pd, gensym("#X")); binbuf_eval(x->gl_editor->e_connectbuf, 0, 0, 0); pd_unbind(&x->gl_pd, gensym("#X")); @@ -3838,8 +3953,9 @@ static void canvas_cut(t_canvas *x) /* else we are cutting objects */ else if (x->gl_editor && x->gl_editor->e_selection) { - canvas_setundo(x, canvas_undo_cut, - canvas_undo_set_cut(x, UCUT_CUT), "cut"); + //canvas_setundo(x, canvas_undo_cut, + // canvas_undo_set_cut(x, UCUT_CUT), "cut"); + canvas_undo_add(x, 3, "cut", canvas_undo_set_cut(x, UCUT_CUT)); canvas_copy(x); canvas_doclear(x); paste_xyoffset = 0; @@ -4002,7 +4118,6 @@ static void canvas_dopaste(t_canvas *x, t_binbuf *b) canvas_displaceselection(x, delta_x, delta_y); //reset canvas_undo_already_set_move canvas_undo_already_set_move = 0; - //TODO: now we need to update the undo queue which does not reflect these autopatching changes } //if we are pasting into a new window and this is not copied from external buffer OR //if we are copying from external buffer and the current canvas is not empty @@ -4011,6 +4126,10 @@ static void canvas_dopaste(t_canvas *x, t_binbuf *b) canvas_paste_atmouse(x); //fprintf(stderr,"doing a paste\n"); } + //else let's provide courtesy offset + else if (!copyfromexternalbuffer) { + canvas_paste_xyoffset(x); + } canvas_dirty(x, 1); /*if (!canvas_undo_name || canvas_undo_name[0] != 'd') { @@ -4044,7 +4163,7 @@ static void canvas_paste(t_canvas *x) { //canvas_setundo(x, canvas_undo_paste, canvas_undo_set_paste(x), // "paste"); - canvas_undo_add(x, 5, "paste", (void *)canvas_undo_set_paste(x, 1)); + canvas_undo_add(x, 5, "paste", (void *)canvas_undo_set_paste(x, 0)); canvas_dopaste(x, copy_binbuf); //canvas_paste_xyoffset(x); } diff --git a/src/g_text.c b/src/g_text.c index 00adeb8ef12f69e48702d1732f8b11957e7132a8..13aa139c1ff988d454b4e1eac0dffe6b1149677e 100644 --- a/src/g_text.c +++ b/src/g_text.c @@ -34,6 +34,7 @@ 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; /* ----------------- the "text" object. ------------------ */ @@ -80,6 +81,9 @@ void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv) 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)); } } @@ -88,7 +92,6 @@ void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv) extern t_pd *newest; void canvas_getargs(int *argcp, t_atom **argvp); -extern int we_are_undoing; static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected, t_binbuf *b) @@ -216,7 +219,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"); + //fprintf(stderr,"canvas_obj\n"); t_text *x; if (argc >= 2) { @@ -236,22 +239,18 @@ void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv) canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj); pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); canvas_objtext(gl, xpix, ypix, 1, b); - //t_undo_create *u_c = (t_undo_create *)glist_getcanvas(gl)->u_last->data; if (connectme) { - fprintf(stderr,"canvas_obj calls canvas_connect\n"); - //u_c->indx = indx; - //u_c->nobj = nobj; + //fprintf(stderr,"canvas_obj calls canvas_connect\n"); canvas_connect(gl, indx, 0, nobj, 0); } else { - fprintf(stderr,"canvas_obj calls canvas_startmotion\n"); - //u_c->indx = -1; - //u_c->nobj = -1; + //fprintf(stderr,"canvas_obj calls canvas_startmotion\n"); canvas_startmotion(glist_getcanvas(gl)); } //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))); + if (!we_are_undoing) + canvas_undo_add(glist_getcanvas(gl), 9, "create", + (void *)canvas_undo_set_create(glist_getcanvas(gl))); } } @@ -1801,12 +1800,16 @@ void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize) vec2[0].a_type == A_SYMBOL && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd")) { + //TODO: add rename undo typedmess(&x->te_pd, gensym("rename"), natom2-1, vec2+1); binbuf_free(x->te_binbuf); x->te_binbuf = b; } else /* normally, just destroy the old one and make a new one. */ { + //fprintf(stderr,"text_setto calls canvas_undo_add\n"); + canvas_undo_add(glist_getcanvas(glist), 10, "recreate", + (void *)canvas_undo_set_recreate(glist_getcanvas(glist), &x->te_g)); int xwas = x->te_xpix, ywas = x->te_ypix; canvas_eraselinesfor(glist, x); glist_delete(glist, &x->te_g); @@ -1815,10 +1818,6 @@ void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize) if (newest && pd_class(newest) == canvas_class) canvas_loadbang((t_canvas *)newest); canvas_restoreconnections(glist_getcanvas(glist)); - glist_select( - fprintf(stderr,"text_setto calls canvas_undo_add\n"); - canvas_undo_add(glist_getcanvas(glist), 10, "recreate", - (void *)canvas_undo_set_recreate(glist_getcanvas(glist), &x->te_g)); } /* if we made a new "pd" or changed a window name, update window list */ diff --git a/src/g_undo.c b/src/g_undo.c index 6bdc342a9060dc5e3c256d8155bd27cf459301a8..a1929ad66d017b6398ebf7c2ebb6e9722038472b 100644 --- a/src/g_undo.c +++ b/src/g_undo.c @@ -22,7 +22,7 @@ t_undo_action *canvas_undo_init(t_canvas *x) x->u_last = a; a->prev = NULL; a->name = "no"; - //sys_vgui("pdtk_undomenu .x%lx no no\n", (t_int)a->x); + sys_vgui("pdtk_undomenu .x%lx no no\n", (t_int)a->x); } else { if (x->u_last->next) { @@ -33,7 +33,7 @@ t_undo_action *canvas_undo_init(t_canvas *x) a->prev = x->u_last; x->u_last = a; } - fprintf(stderr,"canvas_undo_init\n"); + //fprintf(stderr,"canvas_undo_init\n"); return(a); } @@ -51,15 +51,15 @@ t_undo_action *canvas_undo_add(t_canvas *x, int type, const char *name, void *da void canvas_undo_undo(t_canvas *x) { - fprintf(stderr,"canvas_undo_undo\n"); if (x->u_queue && x->u_last != x->u_queue) { - fprintf(stderr,"do it\n"); we_are_undoing = 1; + fprintf(stderr,"canvas_undo_undo %d\n", x->u_last->type); glist_noselect(x); switch(x->u_last->type) { case 1: canvas_undo_connect(x, x->u_last->data, UNDO_UNDO); break; //connect case 2: canvas_undo_disconnect(x, x->u_last->data, UNDO_UNDO); break; //disconnect + case 3: canvas_undo_cut(x, x->u_last->data, UNDO_UNDO); break; //cut case 4: canvas_undo_move(x, x->u_last->data, UNDO_UNDO); break; //move case 5: canvas_undo_paste(x, x->u_last->data, UNDO_UNDO); break; //paste case 9: canvas_undo_create(x, x->u_last->data, UNDO_UNDO); break; //create @@ -80,16 +80,16 @@ void canvas_undo_undo(t_canvas *x) void canvas_undo_redo(t_canvas *x) { - fprintf(stderr,"canvas_undo_redo\n"); if (x->u_queue && x->u_last->next) { - fprintf(stderr,"do it\n"); we_are_undoing = 1; x->u_last = x->u_last->next; + fprintf(stderr,"canvas_undo_undo %d\n", x->u_last->type); glist_noselect(x); switch(x->u_last->type) { case 1: canvas_undo_connect(x, x->u_last->data, UNDO_REDO); break; //connect case 2: canvas_undo_disconnect(x, x->u_last->data, UNDO_REDO); break; //disconnect + case 3: canvas_undo_cut(x, x->u_last->data, UNDO_REDO); break; //cut case 4: canvas_undo_move(x, x->u_last->data, UNDO_REDO); break; //move case 5: canvas_undo_paste(x, x->u_last->data, UNDO_REDO); break; //paste case 9: canvas_undo_create(x, x->u_last->data, UNDO_REDO); break; //create @@ -118,6 +118,7 @@ void canvas_undo_rebranch(t_canvas *x) { case 1: canvas_undo_connect(x, a->data, UNDO_FREE); break; //connect case 2: canvas_undo_disconnect(x, a->data, UNDO_FREE); break; //disconnect + case 3: canvas_undo_cut(x, a->data, UNDO_FREE); break; //cut case 4: canvas_undo_move(x, a->data, UNDO_FREE); break; //move case 5: canvas_undo_paste(x, a->data, UNDO_FREE); break; //paste case 9: canvas_undo_create(x, a->data, UNDO_FREE); break; //create @@ -143,11 +144,11 @@ void canvas_undo_purge_abstraction_actions(t_canvas *x) void canvas_undo_free(t_canvas *x) { - fprintf(stderr,"canvas_undo_free"); + //fprintf(stderr,"canvas_undo_free"); if (x->u_queue) { t_undo_action *a; for(a = x->u_queue; a; a = a->next) { - fprintf(stderr,"."); + //fprintf(stderr,"."); switch(a->type) { case 1: canvas_undo_connect(x, a->data, UNDO_FREE); break; //connect @@ -162,6 +163,6 @@ void canvas_undo_free(t_canvas *x) freebytes(a, sizeof(*a)); } } - fprintf(stderr,"done!\n"); + //fprintf(stderr,"done!\n"); } diff --git a/src/g_undo.h b/src/g_undo.h index 8186c5b78d7e5cde3d30fc88ccf5b2a9e8c17ec2..13a135275cc13fd09e2fce742891854346df5338 100644 --- a/src/g_undo.h +++ b/src/g_undo.h @@ -26,16 +26,18 @@ by an undo) all undo actions (except for its deletion in the parent window shoul be purged since abstraction's state will now default to its original (saved) state. Types of undo data: -0 - init data (start of the queue) -1 - connect -2 - disconnect -3 - cut, clear & typing into objects -4 - motion, inclding "tidy up" and stretching -5 - paste & duplicate -6 - apply -7 - arrange (to front/back) -8 - canvas apply -9 - create +0 - init data (start of the queue) +1 - connect +2 - disconnect +3 - cut, clear & typing into objects +4 - motion, inclding "tidy up" and stretching +5 - paste & duplicate +6 - apply +7 - arrange (to front/back) +8 - canvas apply +9 - create +10 - recreate +11 - rename (TODO) */ struct _undo_action @@ -74,6 +76,11 @@ EXTERN void *canvas_undo_set_disconnect(t_canvas *x, int index1, int outno, int index2, int inno); EXTERN void canvas_undo_disconnect(t_canvas *x, void *z, int action); +/* --------- 3. cut -------------- */ + +EXTERN void *canvas_undo_set_cut(t_canvas *x, int mode); +EXTERN void canvas_undo_cut(t_canvas *x, void *z, int action); + /* --------- 4. move ------------- */ EXTERN void *canvas_undo_set_move(t_canvas *x, int selected); @@ -92,7 +99,7 @@ EXTERN void *canvas_undo_set_create(t_canvas *x); /* --------- 10. recreate -------- */ EXTERN void canvas_undo_recreate(t_canvas *x, void *z, int action); -EXTERN void *canvas_undo_set_recreate(t_canvas *x); +EXTERN void *canvas_undo_set_recreate(t_canvas *x, t_gobj *y); /* ------------------------------- */ diff --git a/src/pd.tk b/src/pd.tk index 2be7b968ff83868b037c2e1037c5b220ec6b75ee..d8d15b574013594989c6d8500b431fe5b1331d15 100644 --- a/src/pd.tk +++ b/src/pd.tk @@ -801,9 +801,9 @@ if {$pd_nt == 2} { } set pd_opendir $untitled_directory set pd_savedir $untitled_directory -set pd_undoaction no -set pd_redoaction no -set pd_undocanvas no +#set pd_undoaction no +#set pd_redoaction no +#set pd_undocanvas no ################ utility functions ######################### @@ -1573,19 +1573,21 @@ proc menu_really_close {name} { } proc menu_undo {name} { - global pd_undoaction - global pd_redoaction - global pd_undocanvas - if {$name == $pd_undocanvas && $pd_undoaction != "no"} { + #puts stderr "menu_undo $name\n" + #global pd_undoaction + #global pd_redoaction + #global pd_undocanvas + if {$::undo($name) != "no"} { pd [concat $name undo \;] } } proc menu_redo {name} { - global pd_undoaction - global pd_redoaction - global pd_undocanvas - if {$name == $pd_undocanvas && $pd_redoaction != "no"} { + #puts stderr "menu_redo $name\n" + #global pd_undoaction + #global pd_redoaction + #global pd_undocanvas + if {$::redo($name) != "no"} { pd [concat $name redo \;] } } @@ -1766,11 +1768,11 @@ proc menu_mycnv {name accel} { # correct edit menu, enabling or disabling undo/redo/cut/copy/paste proc menu_fixeditmenu {name} { catch { - # pdtk_post "fixeditmenu $name\n" + #puts stderr "fixeditmenu $name\n" - global pd_undoaction - global pd_redoaction - global pd_undocanvas + #global pd_undoaction + #global pd_redoaction + #global pd_undocanvas global global_selection global global_clipboard @@ -1800,15 +1802,15 @@ proc menu_fixeditmenu {name} { } # puts stderr [concat menu_fixeditmenu $name $pd_undocanvas $pd_undoaction] - if {$name == $pd_undocanvas && $pd_undoaction != "no"} { + if {$::undo($name) != "no"} { $name.m.edit entryconfigure "Undo*" -state normal \ - -label [concat "Undo " $pd_undoaction] + -label [concat "Undo " $::undo($name)] } else { $name.m.edit entryconfigure "Undo*" -state disabled -label "Undo" } - if {$name == $pd_undocanvas && $pd_redoaction != "no"} { + if {$::redo($name) != "no"} { $name.m.edit entryconfigure "Redo*" -state normal\ - -label [concat "Redo " $pd_redoaction] + -label [concat "Redo " $::redo($name)] } else { $name.m.edit entryconfigure "Redo*" -state disabled } @@ -1829,13 +1831,15 @@ proc menu_fixeditmenu {name} { # message from Pd to update the currently available undo/redo action proc pdtk_undomenu {name undoaction redoaction} { - global pd_undoaction - global pd_redoaction - global pd_undocanvas + #global pd_undoaction + #global pd_redoaction + #global pd_undocanvas # puts stderr [concat pdtk_undomenu $name $undoaction $redoaction] - set pd_undocanvas $name - set pd_undoaction $undoaction - set pd_redoaction $redoaction + #set pd_undocanvas $name + #set pd_undoaction $undoaction + #set pd_redoaction $redoaction + set ::undo($name) $undoaction + set ::redo($name) $redoaction if {$name != "nobody"} { # unpleasant way of avoiding a more unpleasant bug situation --atl 2002.11.25 menu_fixeditmenu $name @@ -1977,8 +1981,14 @@ proc pdtk_canvas_new {name width height geometry editable} { if {![info exists ::yscrollable($name)]} { set ::yscrollable($name) 0 } - if {![info exists ::update_tick($name)]} { - set ::update_tick($name) 0 + #if {![info exists ::update_tick($name)]} { + # set ::update_tick($name) 0 + #} + if {![info exists ::undo($name)]} { + set ::undo($name) no + } + if {![info exists ::redo($name)]} { + set ::redo($name) no } if {$::menu($name) == 1} { @@ -3015,7 +3025,7 @@ proc pdtk_canvas_getscroll {name} { set ::yscrollable($parentname) 0 } } - set ::update_tick([winfo parent $name]) 1 + #set ::update_tick([winfo parent $name]) 1 pdtk_canvas_checkgeometry [canvastosym $name] }