Simplified, hopefully cleaner
[iomenu.git] / input.c
blobd5e163dd677d127f47cf9afb4e01622f1b280bdc
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <termios.h>
7 #include "main.h"
11 * Listen for the user input and call the appropriate functions.
13 void
14 input_get(Buffer *buffer, int offset, int tty_fd, Opt *opt)
16 FILE *tty_fp = fopen("/dev/tty", "r");
18 /* receive one character at a time from the terminal */
19 struct termios termio_old = set_terminal(tty_fd);
21 /* get input char by char from the keyboard. */
22 while (input_key(fgetc(tty_fp), buffer, opt)) {
23 draw_screen(buffer, offset, tty_fd, opt);
26 /* resets the terminal to the previous state. */
27 tcsetattr(tty_fd, TCSANOW, &termio_old);
29 fclose(tty_fp);
33 * Perform action associated with key
35 int
36 input_key(char key, Buffer *buffer, Opt *opt)
38 if (key == opt->validate_key) {
39 action_print_selection(buffer, opt);
40 return FALSE;
43 switch (key) {
45 case CONTROL('C'):
46 draw_clear(opt->lines);
47 return FALSE;
49 case CONTROL('U'):
50 buffer->input[0] = '\0';
51 buffer->current = buffer->first;
52 filter_lines(buffer, opt);
53 action_jump(buffer, BOTH, opt);
54 break;
56 case CONTROL('W'):
57 action_remove_word_input(buffer);
58 filter_lines(buffer, opt);
59 break;
61 case 127:
62 case CONTROL('H'): /* backspace */
63 buffer->input[strlen(buffer->input) - 1] = '\0';
64 filter_lines(buffer, opt);
66 if (!buffer->current->matches) {
67 action_jump(buffer, BOTH, opt);
69 break;
71 case CONTROL('N'):
72 action_jump(buffer, NEXT, opt);
73 break;
75 case CONTROL('P'):
76 action_jump(buffer, PREV, opt);
77 break;
79 case CONTROL('I'): /* tab */
80 strcpy(buffer->input, buffer->current->content);
81 filter_lines(buffer, opt);
82 break;
84 case CONTROL('M'):
85 case CONTROL('J'): /* enter */
86 action_print_selection(buffer, opt);
87 return FALSE;
89 default:
90 action_add_character(buffer, key, opt);
93 return TRUE;
97 * Set the current line to the next/previous/closest matching line.
99 void
100 action_jump(Buffer *buffer, int direction, Opt *opt)
102 Line * line = buffer->current;
104 if (direction == BOTH) {
105 line = matching_next(buffer->current);
106 line = (line) ? line : matching_prev(buffer->current);
107 } else if (direction == NEXT) {
108 line = matching_next(line);
109 } else if (direction == PREV) {
110 line = matching_prev(line);
113 buffer->current = (line) ? line : buffer->current;
115 if (opt->print_numbers)
116 action_print_selection(buffer, opt);
120 * Send the selection to stdout.
122 void
123 action_print_selection(Buffer *buffer, Opt *opt)
125 fputs("\r\033[K", stderr);
127 if (opt->print_numbers) {
128 printf("%d\n", buffer->current->number);
129 } else {
130 if (opt->complete) {
131 puts(buffer->input);
132 } else {
133 puts(buffer->current->content);
139 * Remove the last word from the buffer's input
141 void
142 action_remove_word_input(Buffer *buffer)
144 size_t length = strlen(buffer->input) - 1;
145 int i;
147 for (i = length; i >= 0 && isspace(buffer->input[i]); i--) {
148 buffer->input[i] = '\0';
151 length = strlen(buffer->input) - 1;
152 for (i = length; i >= 0 && !isspace(buffer->input[i]); i--) {
153 buffer->input[i] = '\0';
158 * Add a character to the buffer input and filter lines again.
160 void
161 action_add_character(Buffer *buffer, char key, Opt *opt)
163 size_t length = strlen(buffer->input);
165 if (isprint(key)) {
166 buffer->input[length] = key;
167 buffer->input[length + 1] = '\0';
170 filter_lines(buffer, opt);
172 if (!buffer->current->matches) {
173 action_jump(buffer, BOTH, opt);
176 if (!buffer->current->matches) {
177 buffer->current = buffer->empty;