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