Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
lpan committed Aug 15, 2017
1 parent cc10321 commit 72a3778
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 42 deletions.
158 changes: 126 additions & 32 deletions src/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,45 @@
#include "commands.h"
#include "controller.h"

command_queue_t *init_command_queue(void) {
command_queue_t *cq = malloc(sizeof(command_queue_t));
cq->head = NULL;
cq->last = NULL;
cq->current = NULL;
history_stack_t *init_history_stack(void) {
history_stack_t *hs = malloc(sizeof(history_stack_t));
hs->top = NULL;
hs->bottom = NULL;

return cq;
return hs;
}

void destroy_command_queue(command_queue_t *cq) {
free(cq);
}
future_queue_t *init_future_queue(void) {
future_queue_t *fq = malloc(sizeof(future_queue_t));
fq->front = NULL;
fq->back = NULL;

void append_command(command_queue_t *cq, COMMAND_TYPE t, COMMAND_PAYLOAD p) {
command_t *c = malloc(sizeof(command_t));
c->type = t;
c->payload = p;
c->next = NULL;
c->prev = NULL;
return fq;
}

assert((!cq->head && !cq->last) || (cq->head && cq->last));
void destroy_history_stack(history_stack_t *hs) {
command_t *c = hs->bottom, *tmp;

// when cq is empty
if (!cq->head && !cq->last) {
cq->head = c;
cq->last = c;
return;
while (c) {
tmp = c;
c = c->next;
free(tmp);
}
free(hs);
}

void destroy_future_queue(future_queue_t *fq) {
command_t *c = fq->front, *tmp;

c->prev = cq->last;
cq->last->next = c;
cq->last = c;
while (c) {
tmp = c;
c = c->next;
free(tmp);
}
free(fq);
}

void dispatch_command(command_t *c, state_t *st) {
static void dispatch_command(state_t *st, command_t *c) {
switch (c->type) {
case HANDLE_MOVE:
handle_move(st, c->payload.d);
Expand Down Expand Up @@ -69,16 +73,106 @@ void dispatch_command(command_t *c, state_t *st) {
}
}

void replay_til_current(command_queue_t *cq, state_t *st) {
command_t *c = cq->head;
static command_t *init_command(COMMAND_TYPE t, COMMAND_PAYLOAD p) {
command_t *c = malloc(sizeof(command_t));
c->type = t;
c->payload = p;
c->next = NULL;
c->prev = NULL;
return c;
}

while (c) {
dispatch_command(c, st);
// -------------------------
// -- History Stack methods
// -------------------------
static void append_command(history_stack_t *hs, command_t *c) {
// assert valid state
assert((!hs->top && !hs->bottom) || (hs->top && hs->bottom));

if (c == cq->current) {
break;
}
// when hs is empty
if (!hs->top && !hs->bottom) {
hs->top = c;
hs->bottom = c;
return c;
}

c->prev = hs->top;
hs->top->next = c;
hs->top = c;
return c;
}

static command_t *pop_command(history_stack_t *hs) {
assert((!hs->top && !hs->bottom) || (hs->top && hs->bottom));

if (!hs->top && !hs->bottom) {
return NULL;
}

command_t *popped = hs->top;

// if there is only one command in stack
if (popped->prev == NULL) {
hs->top = NULL;
hs->bottom = NULL;
}

popped->prev->next = NULL;
popped->prev = NULL;
return popped;
}


// -------------------------
// -- Future Queue methods
// -------------------------
static void queue_command(future_queue_t *fq, command_t *c) {
assert((!fq->front && !fq->back) || (fq->front && fq->back));

if (!fq->front && !fq->back) {
fq->front = c;
fq->back = c;
return;
}

c->prev = fq->back;
fq->back->next = c;
fq->back = c;
}


// -------------------------
// -- Public methods
// -------------------------

void replay_history(state_t *st) {
history_stack_t *hs = st->hs;
command_t *c = hs->bottom;

while (c) {
dispatch_command(st, c);
c = c->next;
}
}

/*
* 1. create command
* 2. push it to stack
* 3. execute the command against state
*/
void apply_command(state_t *st, COMMAND_TYPE t, COMMAND_PAYLOAD p) {
command_t *c = init_command(t, p);
append_command(st->hs, c);
dispatch_command(st, c);
}

/*
* 1. pop history stack
* 2. push the result from 1. to future queue
* 3. replay_history()
*/
void undo_command(state_t *st) {
command_t *c = pop_command(st->hs);
queue_command(st->fq, c);
replay_history(st);
}
28 changes: 18 additions & 10 deletions src/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,28 @@ typedef struct command {
struct command *prev;
} command_t;

typedef struct command_queue {
struct command *head;
struct command *last;
struct command *current;
} command_queue_t;
typedef struct history_stack {
struct command *bottom;
struct command *top;
} history_stack_t;

command_queue_t *init_command_queue(void);
typedef struct future_queue {
struct command *front;
struct command *back;
} future_queue_t;

void destroy_command_queue(command_queue_t *cq);
future_queue_t *init_future_queue(void);

void append_command(command_queue_t *cq, COMMAND_TYPE t, COMMAND_PAYLOAD p);
history_stack_t *init_history_stack(void);

void dispatch_command(command_t *c, state_t *st);
void destroy_future_queue(future_queue_t *fq);

void replay_til_current(command_queue_t *cq, state_t *st);
void destroy_history_stack(history_stack_t *hs);

void apply_command(state_t *st, COMMAND_TYPE t, COMMAND_PAYLOAD p);

void undo_command(state_t *st);

void replay_history(state_t *st);

#endif
3 changes: 3 additions & 0 deletions src/state.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ state_t *init_state(const char *filename) {
st->buf = init_buffer(filename);
st->scr = init_screen(LINES);

st->hs = init_history_stack();
st->fq = init_future_queue();

st->prev_key = '\0';

update_state(st);
Expand Down
4 changes: 4 additions & 0 deletions src/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdlib.h>
#include "screen.h"
#include "buffer.h"
#include "commands.h"

struct window;

Expand All @@ -21,6 +22,9 @@ typedef struct state {
buffer_t *buf;
screen_t *scr;

history_stack_t *hs;
future_queue_t *fq;

size_t cx, cy;
size_t top_row;

Expand Down

0 comments on commit 72a3778

Please sign in to comment.