Don't forget the new file
[xiph/unicode.git] / sushivision / undo.c
blob36697b64bb2e95031c71990028aaf0efea3eecd6
1 /*
3 * sushivision copyright (C) 2006-2007 Monty <monty@xiph.org>
5 * sushivision is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * sushivision is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with sushivision; see the file COPYING. If not, write to the
17 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define _GNU_SOURCE
23 #include <string.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include "internal.h"
29 int _sv_undo_level=0;
30 int _sv_undo_suspended=0;
31 sv_undo_t **_sv_undo_stack=NULL;
33 /* encapsulates some amount of common undo/redo infrastructure */
35 static void update_all_menus(){
36 int i;
37 if(_sv_panel_list){
38 for(i=0;i<_sv_panels;i++)
39 if(_sv_panel_list[i])
40 _sv_panel_update_menus(_sv_panel_list[i]);
44 void _sv_undo_suspend(){
45 _sv_undo_suspended++;
48 void _sv_undo_resume(){
49 _sv_undo_suspended--;
50 if(_sv_undo_suspended<0){
51 fprintf(stderr,"Internal error: undo suspend refcount count < 0\n");
52 _sv_undo_suspended=0;
56 void _sv_undo_pop(){
57 _sv_undo_t *u;
58 int i,j;
59 if(!_sv_undo_stack)
60 _sv_undo_stack = calloc(2,sizeof(*_sv_undo_stack));
62 if(_sv_undo_stack[_sv_undo_level]){
63 i=_sv_undo_level;
64 while(_sv_undo_stack[i]){
65 u = _sv_undo_stack[i];
67 if(u->dim_vals[0]) free(u->dim_vals[0]);
68 if(u->dim_vals[1]) free(u->dim_vals[1]);
69 if(u->dim_vals[2]) free(u->dim_vals[2]);
71 if(u->panels){
72 for(j=0;j<_sv_panels;j++){
73 _sv_panel_undo_t *pu = u->panels+j;
74 if(pu->mappings) free(pu->mappings);
75 if(pu->scale_vals[0]) free(pu->scale_vals[0]);
76 if(pu->scale_vals[1]) free(pu->scale_vals[1]);
77 if(pu->scale_vals[2]) free(pu->scale_vals[2]);
79 free(u->panels);
81 free(_sv_undo_stack[i]);
82 _sv_undo_stack[i]= NULL;
83 i++;
87 // alloc new undos
88 u = _sv_undo_stack[_sv_undo_level] = calloc(1,sizeof(*u));
89 u->panels = calloc(_sv_panels,sizeof(*u->panels));
90 u->dim_vals[0] = calloc(_sv_dimensions,sizeof(**u->dim_vals));
91 u->dim_vals[1] = calloc(_sv_dimensions,sizeof(**u->dim_vals));
92 u->dim_vals[2] = calloc(_sv_dimensions,sizeof(**u->dim_vals));
95 void _sv_undo_log(){
96 _sv_undo_t *u;
97 int i,j;
99 // log into a fresh entry; pop this level and all above it
100 _sv_undo_pop();
101 u = _sv_undo_stack[_sv_undo_level];
103 // save dim values
104 for(i=0;i<_sv_dimensions;i++){
105 sv_dim_t *d = _sv_dimension_list[i];
106 if(d){
107 u->dim_vals[0][i] = d->bracket[0];
108 u->dim_vals[1][i] = d->val;
109 u->dim_vals[2][i] = d->bracket[1];
113 // pass off panel population to panels
114 for(j=0;j<_sv_panels;j++)
115 if(_sv_panel_list[j])
116 _sv_panel_undo_log(_sv_panel_list[j], u->panels+j);
119 void _sv_undo_restore(){
120 int i;
121 _sv_undo_t *u = _sv_undo_stack[_sv_undo_level];
123 // dims
124 // need to happen first as setting dims can have side effect (like activating crosshairs)
125 for(i=0;i<_sv_dimensions;i++){
126 sv_dim_t *d = _sv_dimension_list[i];
127 if(d){
128 _sv_dim_set_thumb(d, 0, u->dim_vals[0][i]);
129 _sv_dim_set_thumb(d, 1, u->dim_vals[1][i]);
130 _sv_dim_set_thumb(d, 2, u->dim_vals[2][i]);
134 // panels
135 for(i=0;i<_sv_panels;i++){
136 sv_panel_t *p = _sv_panel_list[i];
137 if(p)
138 _sv_panel_undo_restore(_sv_panel_list[i],u->panels+i);
143 void _sv_undo_push(){
144 if(_sv_undo_suspended)return;
146 _sv_undo_log();
148 // realloc stack
149 _sv_undo_stack =
150 realloc(_sv_undo_stack,
151 (_sv_undo_level+3)*sizeof(*_sv_undo_stack));
152 _sv_undo_level++;
153 _sv_undo_stack[_sv_undo_level]=NULL;
154 _sv_undo_stack[_sv_undo_level+1]=NULL;
155 update_all_menus();
158 void _sv_undo_up(){
159 if(!_sv_undo_stack)return;
160 if(!_sv_undo_stack[_sv_undo_level])return;
161 if(!_sv_undo_stack[_sv_undo_level+1])return;
163 _sv_undo_level++;
164 _sv_undo_suspend();
165 _sv_undo_restore();
166 _sv_undo_resume();
167 update_all_menus();
170 void _sv_undo_down(){
171 if(!_sv_undo_stack)return;
172 if(!_sv_undo_level)return;
174 if(!_sv_undo_stack[_sv_undo_level+1])
175 _sv_undo_log();
176 _sv_undo_level--;
178 _sv_undo_suspend();
179 _sv_undo_restore();
180 _sv_undo_resume();
181 update_all_menus();
185 // load piggybacks off the undo infrastructure