Newer
Older
#include "m_pd.h"
#include "g_canvas.h"
#include <stdio.h>
Ivica Bukvic
committed
#include "g_undo.h"
/* used for canvas_objtext to differentiate between objects being created
by user vs. those (re)created by the undo/redo actions */
int we_are_undoing = 0;
extern const char *canvas_undo_name;
Ivica Bukvic
committed
extern void glob_preset_node_list_seek_hub(void);
t_undo_action *canvas_undo_init(t_canvas *x)
{
t_undo_action *a = (t_undo_action *)getbytes(sizeof(*a));
a->type = 0;
a->x = x;
a->next = NULL;
Ivica Bukvic
committed
if (!x->u_queue)
{
//this is the first init
x->u_queue = a;
x->u_last = a;
a->prev = NULL;
a->name = "no";
sys_vgui("pdtk_undomenu .x%lx no no\n", (t_int)a->x);
}
else
{
if (x->u_last->next)
{
//we need to rebranch first then add the new action
canvas_undo_rebranch(x);
}
x->u_last->next = a;
a->prev = x->u_last;
x->u_last = a;
}
//fprintf(stderr,"canvas_undo_init\n");
return(a);
}
t_undo_action *canvas_undo_add(t_canvas *x, int type, const char *name,
void *data)
{
//fprintf(stderr,"canvas_undo_add %d\n", type);
t_undo_action *a = canvas_undo_init(x);
a->type = type;
a->data = (void *)data;
a->name = (char *)name;
canvas_undo_name = name;
Ivica Bukvic
committed
sys_vgui("pdtk_undomenu .x%lx %s no\n", x, a->name);
}
void canvas_undo_undo(t_canvas *x)
{
int dspwas = canvas_suspend_dsp();
if (x->u_queue && x->u_last != x->u_queue)
{
we_are_undoing = 1;
//fprintf(stderr,"canvas_undo_undo %d\n", x->u_last->type);
glist_noselect(x);
canvas_undo_name = x->u_last->name;
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 6: canvas_undo_apply(x, x->u_last->data, UNDO_UNDO); break; //apply
case 7: canvas_undo_arrange(x, x->u_last->data, UNDO_UNDO); break; //arrange
case 8: canvas_undo_canvas_apply(x, x->u_last->data, UNDO_UNDO); break; //canvas apply
case 9: canvas_undo_create(x, x->u_last->data, UNDO_UNDO); break; //create
case 10:canvas_undo_recreate(x, x->u_last->data, UNDO_UNDO); break; //recreate
case 11:canvas_undo_font(x, x->u_last->data, UNDO_UNDO); break; //font
default:
error("canvas_undo_undo: unsupported undo command %d", x->u_last->type);
}
x->u_last = x->u_last->prev;
char *undo_action = x->u_last->name;
char *redo_action = x->u_last->next->name;
we_are_undoing = 0;
/* here we call updating of all unpaired hubs and nodes since
their regular call will fail in case their position needed
to be updated by undo/redo first to reflect the old one */
glob_preset_node_list_seek_hub();
glob_preset_node_list_check_loc_and_update();
if (glist_isvisible(x) && glist_istoplevel(x))
{
sys_vgui("pdtk_undomenu .x%lx %s %s\n",
x, undo_action, redo_action);
Mathieu L Bouchard
committed
canvas_getscroll(x);
}
canvas_dirty(x, 1);
}
canvas_resume_dsp(dspwas);
}
void canvas_undo_redo(t_canvas *x)
{
int dspwas = canvas_suspend_dsp();
if (x->u_queue && x->u_last->next)
{
we_are_undoing = 1;
x->u_last = x->u_last->next;
//fprintf(stderr,"canvas_undo_redo %d\n", x->u_last->type);
glist_noselect(x);
canvas_undo_name = x->u_last->name;
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 6: canvas_undo_apply(x, x->u_last->data, UNDO_REDO); break; //apply
case 7: canvas_undo_arrange(x, x->u_last->data, UNDO_REDO); break; //arrange
case 8: canvas_undo_canvas_apply(x, x->u_last->data, UNDO_REDO); break; //canvas apply
case 9: canvas_undo_create(x, x->u_last->data, UNDO_REDO); break; //create
case 10:canvas_undo_recreate(x, x->u_last->data, UNDO_REDO); break; //recreate
case 11:canvas_undo_font(x, x->u_last->data, UNDO_REDO); break; //font
default:
error("canvas_undo_redo: unsupported redo command %d", x->u_last->type);
}
char *undo_action = x->u_last->name;
char *redo_action = (x->u_last->next ? x->u_last->next->name : "no");
we_are_undoing = 0;
/* here we call updating of all unpaired hubs and nodes since their
regular call will fail in case their position needed to be updated
by undo/redo first to reflect the old one */
glob_preset_node_list_seek_hub();
glob_preset_node_list_check_loc_and_update();
if (glist_isvisible(x) && glist_istoplevel(x))
{
sys_vgui("pdtk_undomenu .x%lx %s %s\n",
x, undo_action, redo_action);
Mathieu L Bouchard
committed
canvas_getscroll(x);
}
canvas_dirty(x, 1);
}
canvas_resume_dsp(dspwas);
}
void canvas_undo_rebranch(t_canvas *x)
{
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
int dspwas = canvas_suspend_dsp();
t_undo_action *a1, *a2;
//fprintf(stderr,"canvas_undo_rebranch");
if (x->u_last->next)
{
a1 = x->u_last->next;
while(a1)
{
//fprintf(stderr,".");
switch(a1->type)
{
case 1: canvas_undo_connect(x, a1->data, UNDO_FREE); break; //connect
case 2: canvas_undo_disconnect(x, a1->data, UNDO_FREE); break; //disconnect
case 3: canvas_undo_cut(x, a1->data, UNDO_FREE); break; //cut
case 4: canvas_undo_move(x, a1->data, UNDO_FREE); break; //move
case 5: canvas_undo_paste(x, a1->data, UNDO_FREE); break; //paste
case 6: canvas_undo_apply(x, a1->data, UNDO_FREE); break; //apply
case 7: canvas_undo_arrange(x, a1->data, UNDO_FREE); break; //arrange
case 8: canvas_undo_canvas_apply(x, a1->data, UNDO_FREE); break; //canvas apply
case 9: canvas_undo_create(x, a1->data, UNDO_FREE); break; //create
case 10:canvas_undo_recreate(x, a1->data, UNDO_FREE); break; //recreate
case 11:canvas_undo_font(x, a1->data, UNDO_FREE); break; //font
default:
error("canvas_undo_rebranch: unsupported undo command %d", a1->type);
}
a2 = a1->next;
freebytes(a1, sizeof(*a1));
a1 = a2;
}
}
canvas_resume_dsp(dspwas);
//fprintf(stderr,"done!\n");
}
void canvas_undo_check_canvas_pointers(t_canvas *x)
{
/* currently unnecessary unless we decide to implement one central undo
for all patchers */
}
void canvas_undo_purge_abstraction_actions(t_canvas *x)
{
/* currently unnecessary unless we decide to implement one central undo
for all patchers */
}
void canvas_undo_free(t_canvas *x)
{
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
int dspwas = canvas_suspend_dsp();
t_undo_action *a1, *a2;
//fprintf(stderr,"canvas_undo_free");
if (x->u_queue)
{
a1 = x->u_queue;
while(a1)
{
//fprintf(stderr,".");
switch(a1->type)
{
case 0: break; //init
case 1: canvas_undo_connect(x, a1->data, UNDO_FREE); break; //connect
case 2: canvas_undo_disconnect(x, a1->data, UNDO_FREE); break; //disconnect
case 3: canvas_undo_cut(x, a1->data, UNDO_FREE); break; //cut
case 4: canvas_undo_move(x, a1->data, UNDO_FREE); break; //move
case 5: canvas_undo_paste(x, a1->data, UNDO_FREE); break; //paste
case 6: canvas_undo_apply(x, a1->data, UNDO_FREE); break; //apply
case 7: canvas_undo_arrange(x, a1->data, UNDO_FREE); break; //arrange
case 8: canvas_undo_canvas_apply(x, a1->data, UNDO_FREE); break; //canvas apply
case 9: canvas_undo_create(x, a1->data, UNDO_FREE); break; //create
case 10:canvas_undo_recreate(x, a1->data, UNDO_FREE); break; //recreate
case 11:canvas_undo_font(x, a1->data, UNDO_FREE); break; //font
default:
error("canvas_undo_free: unsupported undo command %d", a1->type);
}
a2 = a1->next;
freebytes(a1, sizeof(*a1));
a1 = a2;
}
}
canvas_resume_dsp(dspwas);
//fprintf(stderr,"done!\n");