#include "init.h" #include #include #include #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; } } }