From 4960aa901f2d001f55d94565e45131075d4c45d8 Mon Sep 17 00:00:00 2001 From: Ivica Ico Bukvic <ico@vt.edu> Date: Fri, 9 Dec 2011 13:50:10 -0500 Subject: [PATCH] added proper repositioning of objects after they have been cut/deleted followed by an undo/redo which always places them at the end and thus makes redoing of cut buggy as it originally relied on whatever selection one had as opposed to the proper original selection. --- src/g_editor.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/src/g_editor.c b/src/g_editor.c index 56603795f..f8e24f44a 100644 --- a/src/g_editor.c +++ b/src/g_editor.c @@ -601,6 +601,9 @@ typedef struct _undo_cut t_binbuf *u_reconnectbuf; /* connections into and out of object */ t_binbuf *u_redotextbuf; /* buffer to paste back for redo if TEXT */ int u_mode; /* from flags above */ + int n_obj; /* number of selected objects to be cut */ + int p_a[1]; /* array of original glist positions of selected objects */ + /* 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) @@ -610,7 +613,9 @@ static void *canvas_undo_set_cut(t_canvas *x, int mode) t_linetraverser t; t_outconnect *oc; int nnotsel= glist_selectionindex(x, 0, 0); - buf = (t_undo_cut *)getbytes(sizeof(*buf)); + int nsel = glist_selectionindex(x, 0, 1); + buf = (t_undo_cut *)getbytes(sizeof(*buf) + sizeof(buf->p_a[0]) * (nsel - 1)); + buf->n_obj = nsel; buf->u_mode = mode; buf->u_redotextbuf = 0; @@ -647,6 +652,25 @@ static void *canvas_undo_set_cut(t_canvas *x, int mode) { buf->u_objectbuf = canvas_docopy(x); } + + //instantiate num_obj and fill array of positions of selected objects + if (mode == UCUT_CUT || mode == UCUT_CLEAR) + { + int i = 0, j = 0; + if (x->gl_list) { + for (y = x->gl_list; y; y = y->g_next) + { + if (glist_isselected(x, y)) { + buf->p_a[i] = j; + i++; + } + j++; + } + } + //for (i = 0; i < buf->n_obj; i++) + // fprintf(stderr,"%d position = %d\n", i, buf->p_a[i]); + } + return (buf); } @@ -689,12 +713,70 @@ static void canvas_undo_cut(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")); + + //now reposition objects to their original locations + if (mode == UCUT_CUT || mode == UCUT_CLEAR) { + //fprintf(stderr,"reordering\n"); + int i = 0; + int paste_pos = glist_getindex(x,0) - buf->n_obj; //location of the first newly pasted object + //fprintf(stderr,"paste_pos %d\n", paste_pos); + t_gobj *y_prev, *y, *y_next; + for (i = 0; i < buf->n_obj; i++) { + //first check if we are in the same position already + if (paste_pos+i != buf->p_a[i]) { + //fprintf(stderr,"not in the right place\n"); + y_prev = glist_nth(x, paste_pos-1+i); + y = glist_nth(x, paste_pos+i); + y_next = glist_nth(x, paste_pos+1+i); + //if the object is supposed to be first in of gl_list + if (buf->p_a[i] == 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->p_a[i]-1); + y_next = glist_nth(x, buf->p_a[i]); + + y_prev->g_next = y; + y->g_next = y_next; + } + } + canvas_redraw(x); + } + } } else if (action == UNDO_REDO) { //fprintf(stderr,"UNDO_REDO\n"); - if (mode == UCUT_CUT || mode == UCUT_CLEAR) + if (mode == UCUT_CUT || mode == UCUT_CLEAR) { + //we can't just blindly do clear here when the user may have + //unselected things between undo and redo, so first let's select + //the right stuff + glist_noselect(x); + int i = 0; + for (i = 0; i < buf->n_obj; i++) + glist_select(x, glist_nth(x, buf->p_a[i])); canvas_doclear(x); + } else if (mode == UCUT_TEXT) { t_gobj *y1, *y2; @@ -717,7 +799,7 @@ static void canvas_undo_cut(t_canvas *x, void *z, int action) binbuf_free(buf->u_reconnectbuf); if (buf->u_redotextbuf) binbuf_free(buf->u_redotextbuf); - if (buf != NULL) t_freebytes(buf, sizeof(*buf)); + if (buf != NULL) t_freebytes(buf, sizeof(*buf) + sizeof(buf->p_a[0]) * (buf->n_obj-1)); } } -- GitLab