forked from KolibriOS/kolibrios
126 lines
2.4 KiB
C
126 lines
2.4 KiB
C
|
// Actions history
|
||
|
|
||
|
#define MAX_ACTIONS_COUNT 10
|
||
|
|
||
|
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] = malloc(image.columns * image.rows);
|
||
|
|
||
|
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 (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 (nextAction >= MAX_ACTIONS_COUNT)
|
||
|
nextAction = nextAction % MAX_ACTIONS_COUNT;
|
||
|
|
||
|
if (isEmpty())
|
||
|
return;
|
||
|
else {
|
||
|
if (nextAction != tail) {
|
||
|
restoreState(nextAction);
|
||
|
DrawCanvas();
|
||
|
}
|
||
|
|
||
|
if (nextAction != tail)
|
||
|
currentIndex = nextAction;
|
||
|
}
|
||
|
}
|