Files
degvi/KeyCommand.c
2013-02-10 23:54:06 +09:00

256 lines
5.8 KiB
C

#include "init.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "KeyCommand.h"
KeyCommandEntry KeyCommandEntry_create(int type, int keyChar)
{
KeyCommandEntry this;
this = malloc(sizeof(struct KeyCommandEntry_struct));
if (this == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
this->type = type;
this->keyChar = keyChar;
return this;
}
void KeyCommandEntry_destroy(KeyCommandEntry this)
{
if (this == NULL) {
return;
}
free(this);
}
int KeyCommandEntry_type(KeyCommandEntry this)
{
return this->type;
}
int KeyCommandEntry_keyChar(KeyCommandEntry this)
{
return this->keyChar;
}
KeyCommandTable KeyCommandTable_create(void)
{
KeyCommandTable this;
this = malloc(sizeof(struct KeyCommandTable_struct));
if (this == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
this->maxSize = 0;
this->size = 0;
this->entries = NULL;
return this;
}
void KeyCommandTable_destroy(KeyCommandTable this)
{
int i;
if (this == NULL) {
return;
}
for (i = 0; i < this->size; i++) {
KeyCommandEntry_destroy(*(this->entries + i));
}
free(this->entries);
free(this);
}
void KeyCommandTable_add(KeyCommandTable this, int type, int keyChar)
{
KeyCommandEntry entry;
if (this->size + 1 > this->maxSize) {
this->maxSize += KEY_COMMAND_TABLE_BUFFER_INCREMENT_SIZE;
this->entries = realloc(this->entries, sizeof(KeyCommandEntry) * (this->maxSize));
if (this->entries == NULL) {
fprintf(stderr, "realloc failed\n");
exit(EXIT_FAILURE);
}
}
entry = KeyCommandEntry_create(type, keyChar);
*(this->entries + this->size) = entry;
this->size++;
}
KeyCommandEntry KeyCommandTable_find(KeyCommandTable this, int keyChar)
{
int i;
for (i = 0; i < this->size; i++) {
KeyCommandEntry entry;
entry = *(this->entries + i);
if (entry->keyChar == keyChar) {
return entry;
}
}
return NULL;
}
void KeyCommandTable_setup(KeyCommandTable this)
{
KeyCommandTable_add(this, KeyCommandEntry_type_edit, '\f');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, ':');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, 'i');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, 'a');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, 'I');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, 'A');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, 'o');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, 'O');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, 'x');
KeyCommandTable_add(this, KeyCommandEntry_type_double, 'd');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, 'J');
KeyCommandTable_add(this, KeyCommandEntry_type_double, 'y');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, 'p');
KeyCommandTable_add(this, KeyCommandEntry_type_edit, 'P');
KeyCommandTable_add(this, KeyCommandEntry_type_motion, '0');
KeyCommandTable_add(this, KeyCommandEntry_type_motion, '$');
KeyCommandTable_add(this, KeyCommandEntry_type_motion, 'G');
KeyCommandTable_add(this, KeyCommandEntry_type_motion, 'h');
KeyCommandTable_add(this, KeyCommandEntry_type_motion, 'j');
KeyCommandTable_add(this, KeyCommandEntry_type_motion, 'k');
KeyCommandTable_add(this, KeyCommandEntry_type_motion, 'l');
KeyCommandTable_add(this, KeyCommandEntry_type_double, 'Z');
}
KeyCommand KeyCommand_create(KeyCommandTable table)
{
KeyCommand this;
this = malloc(sizeof(struct KeyCommand_struct));
if (this == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
this->table = table;
KeyCommand_reset(this);
return this;
}
void KeyCommand_destroy(KeyCommand this)
{
if (this == NULL) {
return;
}
free(this);
}
void KeyCommand_reset(KeyCommand this)
{
this->state = KeyCommand_state_initialized;
this->count1 = 0;
this->edit = 0;
this->count2 = 0;
this->motion = 0;
}
int KeyCommand_read(KeyCommand this, char c)
{
KeyCommandEntry entry;
if (c == 0x1b) {
this->state = KeyCommand_state_canceled;
return KEY_COMMAND_CANCELED;
}
if (this->state == KeyCommand_state_request_mark) {
this->mark = c;
this->state = KeyCommand_state_finished;
return KEY_COMMAND_FINISHED;
}
if (c >= '0' && c <= '9') {
switch (this->state) {
default:
assert(0);
case KeyCommand_state_initialized:
if (c == '0') {
break;
}
this->count1 = c - '0';
this->state = KeyCommand_state_count1;
return KEY_COMMAND_SWALLOWED;
case KeyCommand_state_count1:
this->count1 = this->count1 * 10 + (c - '0');
return KEY_COMMAND_SWALLOWED;
case KeyCommand_state_edit:
if (c == '0') {
break;
}
this->count2 = c - '0';
this->state = KeyCommand_state_count2;
return KEY_COMMAND_SWALLOWED;
case KeyCommand_state_count2:
this->count2 = this->count2 * 10 + (c - '0');
return KEY_COMMAND_SWALLOWED;
}
}
entry = KeyCommandTable_find(this->table, c);
if (entry == NULL) {
this->state = KeyCommand_state_error;
return KEY_COMMAND_ERROR;
}
switch (KeyCommandEntry_type(entry)) {
default:
assert(0);
case KeyCommandEntry_type_edit:
if (this->state == KeyCommand_state_edit) {
this->state = KeyCommand_state_error;
return KEY_COMMAND_ERROR;
}
this->edit = c;
this->state = KeyCommand_state_finished;
return KEY_COMMAND_FINISHED;
case KeyCommandEntry_type_edit_with_motion:
if (this->state == KeyCommand_state_edit) {
this->state = KeyCommand_state_error;
return KEY_COMMAND_ERROR;
}
this->edit = c;
this->state = KeyCommand_state_edit;
return KEY_COMMAND_SWALLOWED;
case KeyCommandEntry_type_motion:
this->motion = c;
this->state = KeyCommand_state_finished;
return KEY_COMMAND_FINISHED;
case KeyCommandEntry_type_double:
if (this->state != KeyCommand_state_edit) {
this->edit = c;
this->state = KeyCommand_state_edit;
return KEY_COMMAND_SWALLOWED;
} else {
this->motion = c;
this->state = KeyCommand_state_finished;
return KEY_COMMAND_FINISHED;
}
}
}