#define MAX_ACTIONS_COUNT 15 struct _ActionsHistory { dword stack[MAX_ACTIONS_COUNT]; dword head; dword tail; dword currentIndex; void init(); bool isEmpty(); void saveCurrentState(); void restoreState(dword index); void undoLastAction(); void redoLastAction(); }; void _ActionsHistory::init() { dword i; head = tail = 0; currentIndex = -1; for (i = 0; i < MAX_ACTIONS_COUNT; i++) { stack[i] = free(stack[i]); stack[i] = malloc(image.columns * image.rows * 4); } saveCurrentState(); } bool _ActionsHistory::isEmpty() { if (head == tail) return true; else return false; } void _ActionsHistory::saveCurrentState() { dword addr, offset; int r, c; tail = currentIndex + 1; if (tail >= MAX_ACTIONS_COUNT) tail = tail % MAX_ACTIONS_COUNT; addr = stack[tail]; for (r = 0; r < image.rows; r++) { for (c = 0; c < image.columns; c++) { offset = calc(image.columns * r + c) * 4; ESDWORD[addr + offset] = image.get_pixel(r, c); } } currentIndex = tail; tail = calc(tail + 1) % 10; if (tail == head) head = calc(head + 1) % 10; } void _ActionsHistory::restoreState(dword index) { dword addr, offset; int r, c; addr = stack[index]; for (r = 0; r < image.rows; r++) { for (c = 0; c < image.columns; c++) { offset = calc(image.columns * r + c) * 4; image.set_pixel(r, c, ESDWORD[addr + offset]); } } } void _ActionsHistory::undoLastAction() { dword previousAction; if (!is_selection_moving()) { // Если вышли за левую границу, перемещаемся в конец массива if (currentIndex == 0) { previousAction = MAX_ACTIONS_COUNT - 1; } else { previousAction = currentIndex - 1; } if (isEmpty()) return; else { if (currentIndex != head) { restoreState(previousAction); DrawCanvas(); } if (currentIndex != head) currentIndex = previousAction; } } } void _ActionsHistory::redoLastAction() { dword nextAction = calc(currentIndex + 1); if (!is_selection_moving()) { // Если вышли за левую границу, возвращаемся в начало if (nextAction >= MAX_ACTIONS_COUNT) nextAction = nextAction % MAX_ACTIONS_COUNT; if (isEmpty()) return; else { if (nextAction != tail) { restoreState(nextAction); DrawCanvas(); } if (nextAction != tail) currentIndex = nextAction; } } }