256 lines
5.8 KiB
C
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;
|
|
}
|
|
}
|
|
}
|