1 /* $Header: /home/yav/xpx/RCS/undo.c,v 1.11 1996/04/24 23:08:27 yav Exp $
2 * xpx undo
3 * written by yav (UHD98984@pcvan.or.jp)
4 */
5
6 #include <X11/Xlib.h>
7 #include "headers.h"
8 #include "xpx.h"
9 #include "work.h"
10 #define PUBLIC_UNDO_C
11 #include "extern.h"
12
13 char rcsid_undo[] = "$Id: undo.c,v 1.11 1996/04/24 23:08:27 yav Exp $";
14
15 typedef struct {
16 int x;
17 int y;
18 int c;
19 } UNDOPTS;
20
21 typedef union {
22 int type;
23 struct {
24 int type;
25 int x, y, w, h;
26 unsigned char *img;
27 } u_area;
28 struct {
29 int type;
30 int n, pcol;
31 UNDOPTS *pts;
32 } u_plot;
33 struct {
34 int type;
35 int top, n;
36 COL *col;
37 } u_color;
38 } UNDOST;
39
40 #define UNDO_AREA 0
41 #define UNDO_PLOT 1
42 #define UNDO_COLOR 2
43
44 #define UNDO_PLOT_MAX 128
45
46 int undo_cnt;
47 static UNDOST *undotbl;
48
undo_init()49 int undo_init()
50 {
51 undotbl = (UNDOST *)malloc(sizeof(UNDOST)*MAXUNDO);
52 if (undotbl == NULL)
53 return 1;
54 return undo_cnt = 0;
55 }
56
free_undo_data(u)57 void free_undo_data(u)
58 UNDOST *u;
59 {
60 switch(u->type) {
61 case UNDO_AREA:
62 free(u->u_area.img);
63 break;
64 case UNDO_PLOT:
65 free(u->u_plot.pts);
66 break;
67 }
68 }
69
kill_last_undo()70 void kill_last_undo()
71 {
72 int i;
73
74 free_undo_data(undotbl);
75 for (i = 0; i < MAXUNDO-1; i++)
76 *(undotbl+i) = *(undotbl+i+1);
77 --undo_cnt;
78 }
79
check_undo_overflow()80 void check_undo_overflow()
81 {
82 imgchanged = 1;
83 if (undo_cnt >= MAXUNDO) {
84 kill_last_undo();
85 imgchanged = 2; /* Cannot return starting data */
86 }
87 }
88
89
undo_push_area(x,y,width,height)90 int undo_push_area(x, y, width, height)
91 int x;
92 int y;
93 int width;
94 int height;
95 {
96 int i;
97 unsigned char *p;
98 UNDOST *uu;
99
100 reset_color_pushed(-1);
101 check_undo_overflow();
102 if (x < 0)
103 x = 0;
104 if (y < 0)
105 y = 0;
106 if (x+width > imgmaxw)
107 width = imgmaxw - x;
108 if (y+height > imgmaxh)
109 height = imgmaxh - y;
110 if (width*height <= 0) {
111 fprintf(stderr, "undo_push_area: malloc(%dx%d)??\n", width, height);
112 return 0;
113 }
114 p = (unsigned char *)malloc(width*height);
115 if (p == NULL)
116 return 0;
117 uu = undotbl + undo_cnt;
118 uu->type = UNDO_AREA;
119 uu->u_area.x = x;
120 uu->u_area.y = y;
121 uu->u_area.w = width;
122 uu->u_area.h = height;
123 uu->u_area.img = p;
124 for (i = 0; i < height; i++) {
125 memcpy(p, imgdata+(y+i)*imgmaxw+x, width);
126 p += width;
127 }
128 undo_cnt++;
129 edit_undo_update();
130 return undo_cnt;
131 }
132
undo_push_plot(x,y,c,newcol)133 int undo_push_plot(x, y, c, newcol)
134 int x;
135 int y;
136 int c;
137 int newcol;
138 {
139 UNDOPTS *p;
140 UNDOST *uu;
141
142 reset_color_pushed(-1);
143 check_undo_overflow();
144 uu = undotbl + undo_cnt;
145 if (undo_cnt &&
146 (uu-1)->type == UNDO_PLOT &&
147 (uu-1)->u_plot.pcol == newcol &&
148 (uu-1)->u_plot.n < UNDO_PLOT_MAX) {
149 --uu;
150 p = (UNDOPTS *)realloc(uu->u_plot.pts, sizeof(UNDOPTS)*(uu->u_plot.n + 1));
151 } else {
152 undo_cnt++;
153 uu->type = UNDO_PLOT;
154 uu->u_plot.n = 0;
155 uu->u_plot.pcol = newcol;
156 p = (UNDOPTS *)malloc(sizeof(UNDOPTS));
157 }
158 if (p == NULL)
159 return 0;
160 uu->u_plot.pts = p;
161 p += uu->u_plot.n;
162 p->x = x;
163 p->y = y;
164 p->c = c;
165 uu->u_plot.n++;
166 edit_undo_update();
167 return undo_cnt;
168 }
169
undo_area(uu)170 void undo_area(uu)
171 UNDOST *uu;
172 {
173 int i;
174 unsigned char *p;
175
176 p = uu->u_area.img;
177 for (i = 0; i < uu->u_area.h; i++) {
178 memcpy(imgdata+(uu->u_area.y+i)*imgmaxw+uu->u_area.x, p, uu->u_area.w);
179 p += uu->u_area.w;
180 }
181 free(uu->u_area.img);
182 /* XImage update */
183 update_area(uu->u_area.x, uu->u_area.y, uu->u_area.w, uu->u_area.h);
184 /* Window update */
185 area_update(uu->u_area.x, uu->u_area.y, uu->u_area.w, uu->u_area.h);
186 }
187
undo_push_color(top,n)188 int undo_push_color(top, n)
189 int top;
190 int n;
191 {
192 COL *p;
193 UNDOST *uu;
194
195 check_undo_overflow();
196 p = (COL *)malloc(sizeof(COL) * n);
197 if (p == NULL)
198 return 0;
199 uu = undotbl + undo_cnt;
200 uu->type = UNDO_COLOR;
201 uu->u_color.top = top;
202 uu->u_color.n = n;
203 uu->u_color.col = p;
204 memcpy(p, color_buf+top, sizeof(COL)*n);
205 undo_cnt++;
206 edit_undo_update();
207 return undo_cnt;
208 }
209
210
undo_plot(uu)211 void undo_plot(uu)
212 UNDOST *uu;
213 {
214 int i, x0, y0, x1, y1;
215 UNDOPTS *pos;
216
217 pos = uu->u_plot.pts;
218 x0 = x1 = pos->x;
219 y0 = y1 = pos->y;
220 for (i = 0; i < uu->u_plot.n; i++) {
221 if (pos->x < x0)
222 x0 = pos->x;
223 if (pos->x > x1)
224 x1 = pos->x;
225 if (pos->y < y0)
226 y0 = pos->y;
227 if (pos->y > y1)
228 y1 = pos->y;
229 pos++;
230 }
231 pos = uu->u_plot.pts;
232 i = uu->u_plot.n;
233 while (i--)
234 *(imgdata+(pos+i)->y*imgmaxw+(pos+i)->x) = (pos+i)->c;
235 free(uu->u_plot.pts);
236 update_area(x0, y0, x1-x0+1, y1-y0+1); /* XImage update */
237 area_update(x0, y0, x1-x0+1, y1-y0+1); /* Window update */
238 }
239
undo_color(uu)240 void undo_color(uu)
241 UNDOST *uu;
242 {
243 memcpy(color_buf+uu->u_color.top,
244 uu->u_color.col,
245 sizeof(COL)*uu->u_color.n);
246 change_color(uu->u_color.top);
247 free(uu->u_color.col);
248 }
249
undo_pull()250 int undo_pull()
251 {
252 UNDOST *uu;
253
254 reset_color_pushed(-1);
255 if (!undo_cnt)
256 return 0;
257 uu = undotbl + --undo_cnt;
258 switch(uu->type) {
259 case UNDO_AREA:
260 undo_area(uu);
261 break;
262 case UNDO_PLOT:
263 undo_plot(uu);
264 break;
265 case UNDO_COLOR:
266 undo_color(uu);
267 break;
268 }
269 edit_undo_update();
270 if (!undo_cnt && imgchanged == 1) {
271 if (debug_mode)
272 fprintf(stderr, "undo_pull: revert to the beginning\n");
273 colchanged = imgchanged = 0;
274 }
275 return undo_cnt;
276 }
277
undo_clear()278 int undo_clear()
279 {
280 while (undo_cnt)
281 kill_last_undo();
282 edit_undo_update();
283 return 0;
284 }
285
286 /* End of file */
287