diff options
Diffstat (limited to 'readline.c')
-rw-r--r-- | readline.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/readline.c b/readline.c new file mode 100644 index 0000000..c36b19a --- /dev/null +++ b/readline.c @@ -0,0 +1,153 @@ +#include "readline.h" +#include "shell.h" + +#include <stdlib.h> +#include <string.h> /* memmove */ +#include <stdio.h> + +void readline_create_array(struct readline_type *readline) +{ + readline->arr = calloc(initial_size, 1); + readline->cursor_pos = 0; + readline->last_element_index = -1; + readline->considered_index = 0; + readline->allocation_size = initial_size; +} + +static void readline_copy_array(struct readline_type *readline, char *new_arr) +{ + int i; + for(i = 0; i <= readline->last_element_index; ++i) + new_arr[i] = readline->arr[i]; +} + +static void readline_allocate_memory(struct readline_type *readline) +{ + char *new_arr = calloc(readline->allocation_size * 2, 1); + readline_copy_array(readline, new_arr); + free(readline->arr); + readline->arr = new_arr; + readline->allocation_size *= 2; +} + +static void readline_reprint_modified_part(struct readline_type *readline, + int begin_idx) +{ + int i, counter; + for(i = begin_idx, counter = 0; i <= readline->last_element_index; + ++i, ++counter) + putchar(readline->arr[i]); + + /* return cursor to previous position */ + for( ; counter != 0; --counter) + putchar('\b'); + fflush(stdout); +} + +void readline_add_char(struct readline_type *readline, int ch) +{ + char *begin_arr; + int size; + + if(readline->last_element_index+1 == readline->allocation_size) + readline_allocate_memory(readline); + /* insert in middle position */ + if(readline->cursor_pos - 1 != readline->last_element_index) { + begin_arr = readline->arr + readline->cursor_pos; + size = readline->last_element_index - readline->cursor_pos + 1; + memmove(begin_arr+1, begin_arr, size); + readline->arr[readline->cursor_pos] = ch; + ++readline->last_element_index; + readline_reprint_modified_part(readline, readline->cursor_pos + 1); + } else { + ++readline->last_element_index; + readline->arr[readline->last_element_index] = ch; + } + ++readline->cursor_pos; +} + +void readline_reset_array(struct readline_type *readline) +{ + readline->last_element_index = -1; + readline->cursor_pos = 0; +} + +void readline_clear(struct readline_type *readline) +{ + free(readline->arr); + readline->arr = NULL; +} + +void readline_print(struct readline_type *readline) +{ + int i; + for(i = 0; i <= readline->last_element_index; ++i) + putchar(readline->arr[i]); + readline->cursor_pos = readline->last_element_index + 1; + fflush(stdout); +} + +enum keys readline_detect_arrow_keys(int ch) +{ + char next_ch; + if(ch == esc) { + next_ch = getchar(); + if(next_ch != '[') + return unknown_key; + next_ch = getchar(); + + switch(next_ch) { + case left_arrow: + return left_arrow; + case right_arrow: + return right_arrow; + case up_arrow: + return up_arrow; + case down_arrow: + return down_arrow; + default: + return unknown_key; + } + } + return none; +} + +void readline_move_along(struct readline_type *readline, enum keys found_key) +{ + switch(found_key) { + case left_arrow: + if(readline->cursor_pos > 0) { + putchar('\b'); + fflush(stdout); + --readline->cursor_pos; + } + break; + case right_arrow: + if(readline->cursor_pos <= readline->last_element_index) { + putchar(readline->arr[readline->cursor_pos]); + fflush(stdout); + ++readline->cursor_pos; + } + break; + default: + ; + } +} + +void readline_character_deletion(struct readline_type *readline) +{ + char *begin_arr; + int size; + + if(readline->cursor_pos > 0) { + putchar('\b'); + fflush(stdout); + begin_arr = readline->arr + readline->cursor_pos; + size = readline->last_element_index - readline->cursor_pos + 1; + memmove(begin_arr-1, begin_arr, size); + readline->arr[readline->last_element_index] = ' '; + readline_reprint_modified_part(readline, readline->cursor_pos - 1); + --readline->last_element_index; + --readline->cursor_pos; + } +} |