/* $Header: /home/yav/xpx/RCS/undo.c,v 1.11 1996/04/24 23:08:27 yav Exp $ * xpx undo * written by yav (UHD98984@pcvan.or.jp) */ #include #include "headers.h" #include "xpx.h" #include "work.h" #define PUBLIC_UNDO_C #include "extern.h" char rcsid_undo[] = "$Id: undo.c,v 1.11 1996/04/24 23:08:27 yav Exp $"; typedef struct { int x; int y; int c; } UNDOPTS; typedef union { int type; struct { int type; int x, y, w, h; unsigned char *img; } u_area; struct { int type; int n, pcol; UNDOPTS *pts; } u_plot; struct { int type; int top, n; COL *col; } u_color; } UNDOST; #define UNDO_AREA 0 #define UNDO_PLOT 1 #define UNDO_COLOR 2 #define UNDO_PLOT_MAX 128 int undo_cnt; static UNDOST *undotbl; int undo_init() { undotbl = (UNDOST *)malloc(sizeof(UNDOST)*MAXUNDO); if (undotbl == NULL) return 1; return undo_cnt = 0; } void free_undo_data(u) UNDOST *u; { switch(u->type) { case UNDO_AREA: free(u->u_area.img); break; case UNDO_PLOT: free(u->u_plot.pts); break; } } void kill_last_undo() { int i; free_undo_data(undotbl); for (i = 0; i < MAXUNDO-1; i++) *(undotbl+i) = *(undotbl+i+1); --undo_cnt; } void check_undo_overflow() { imgchanged = 1; if (undo_cnt >= MAXUNDO) { kill_last_undo(); imgchanged = 2; /* Cannot return starting data */ } } int undo_push_area(x, y, width, height) int x; int y; int width; int height; { int i; unsigned char *p; UNDOST *uu; reset_color_pushed(-1); check_undo_overflow(); if (x < 0) x = 0; if (y < 0) y = 0; if (x+width > imgmaxw) width = imgmaxw - x; if (y+height > imgmaxh) height = imgmaxh - y; if (width*height <= 0) { fprintf(stderr, "undo_push_area: malloc(%dx%d)??\n", width, height); return 0; } p = (unsigned char *)malloc(width*height); if (p == NULL) return 0; uu = undotbl + undo_cnt; uu->type = UNDO_AREA; uu->u_area.x = x; uu->u_area.y = y; uu->u_area.w = width; uu->u_area.h = height; uu->u_area.img = p; for (i = 0; i < height; i++) { memcpy(p, imgdata+(y+i)*imgmaxw+x, width); p += width; } undo_cnt++; edit_undo_update(); return undo_cnt; } int undo_push_plot(x, y, c, newcol) int x; int y; int c; int newcol; { UNDOPTS *p; UNDOST *uu; reset_color_pushed(-1); check_undo_overflow(); uu = undotbl + undo_cnt; if (undo_cnt && (uu-1)->type == UNDO_PLOT && (uu-1)->u_plot.pcol == newcol && (uu-1)->u_plot.n < UNDO_PLOT_MAX) { --uu; p = (UNDOPTS *)realloc(uu->u_plot.pts, sizeof(UNDOPTS)*(uu->u_plot.n + 1)); } else { undo_cnt++; uu->type = UNDO_PLOT; uu->u_plot.n = 0; uu->u_plot.pcol = newcol; p = (UNDOPTS *)malloc(sizeof(UNDOPTS)); } if (p == NULL) return 0; uu->u_plot.pts = p; p += uu->u_plot.n; p->x = x; p->y = y; p->c = c; uu->u_plot.n++; edit_undo_update(); return undo_cnt; } void undo_area(uu) UNDOST *uu; { int i; unsigned char *p; p = uu->u_area.img; for (i = 0; i < uu->u_area.h; i++) { memcpy(imgdata+(uu->u_area.y+i)*imgmaxw+uu->u_area.x, p, uu->u_area.w); p += uu->u_area.w; } free(uu->u_area.img); /* XImage update */ update_area(uu->u_area.x, uu->u_area.y, uu->u_area.w, uu->u_area.h); /* Window update */ area_update(uu->u_area.x, uu->u_area.y, uu->u_area.w, uu->u_area.h); } int undo_push_color(top, n) int top; int n; { COL *p; UNDOST *uu; check_undo_overflow(); p = (COL *)malloc(sizeof(COL) * n); if (p == NULL) return 0; uu = undotbl + undo_cnt; uu->type = UNDO_COLOR; uu->u_color.top = top; uu->u_color.n = n; uu->u_color.col = p; memcpy(p, color_buf+top, sizeof(COL)*n); undo_cnt++; edit_undo_update(); return undo_cnt; } void undo_plot(uu) UNDOST *uu; { int i, x0, y0, x1, y1; UNDOPTS *pos; pos = uu->u_plot.pts; x0 = x1 = pos->x; y0 = y1 = pos->y; for (i = 0; i < uu->u_plot.n; i++) { if (pos->x < x0) x0 = pos->x; if (pos->x > x1) x1 = pos->x; if (pos->y < y0) y0 = pos->y; if (pos->y > y1) y1 = pos->y; pos++; } pos = uu->u_plot.pts; i = uu->u_plot.n; while (i--) *(imgdata+(pos+i)->y*imgmaxw+(pos+i)->x) = (pos+i)->c; free(uu->u_plot.pts); update_area(x0, y0, x1-x0+1, y1-y0+1); /* XImage update */ area_update(x0, y0, x1-x0+1, y1-y0+1); /* Window update */ } void undo_color(uu) UNDOST *uu; { memcpy(color_buf+uu->u_color.top, uu->u_color.col, sizeof(COL)*uu->u_color.n); change_color(uu->u_color.top); free(uu->u_color.col); } int undo_pull() { UNDOST *uu; reset_color_pushed(-1); if (!undo_cnt) return 0; uu = undotbl + --undo_cnt; switch(uu->type) { case UNDO_AREA: undo_area(uu); break; case UNDO_PLOT: undo_plot(uu); break; case UNDO_COLOR: undo_color(uu); break; } edit_undo_update(); if (!undo_cnt && imgchanged == 1) { if (debug_mode) fprintf(stderr, "undo_pull: revert to the beginning\n"); colchanged = imgchanged = 0; } return undo_cnt; } int undo_clear() { while (undo_cnt) kill_last_undo(); edit_undo_update(); return 0; } /* End of file */