1 exit status on control + C
[iomenu.git] / input.c
blobbc095dbbdc00ddb8f7e517e0d2ee00d70d4d2a85
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <termios.h>
7 #include "input.h"
8 #include "util.h"
9 #include "draw.h"
10 #include "buffer.h"
13 * Listen for the user input and call the appropriate functions.
15 void
16 input_get(Buffer *buffer, int offset, int tty_fd, Opt *opt)
18 FILE *tty_fp = fopen("/dev/tty", "r");
20 /* receive one character at a time from the terminal */
21 struct termios termio_old = set_terminal(tty_fd);
23 /* get input char by char from the keyboard. */
24 while (input_key(fgetc(tty_fp), buffer, opt)) {
25 draw_screen(buffer, offset, tty_fd, opt);
28 /* resets the terminal to the previous state. */
29 tcsetattr(tty_fd, TCSANOW, &termio_old);
31 fclose(tty_fp);
35 * Perform action associated with key
37 int
38 input_key(char key, Buffer *buffer, Opt *opt)
40 if (key == opt->validate_key) {
41 action_print_selection(buffer, opt);
42 return FALSE;
45 switch (key) {
47 case CONTROL('C'):
48 draw_clear();
49 exit(EXIT_FAILURE);
50 break; /* never reached */
52 case CONTROL('U'):
53 buffer->input[0] = '\0';
54 buffer->current = buffer->first;
55 filter_lines(buffer, opt);
56 break;
58 case CONTROL('W'):
59 action_remove_word_input(buffer);
60 filter_lines(buffer, opt);
61 break;
63 case 127:
64 case CONTROL('H'): /* backspace */
65 buffer->input[strlen(buffer->input) - 1] = '\0';
66 filter_lines(buffer, opt);
68 if (!buffer->current->matches) {
69 action_jump(buffer, BOTH, opt);
71 break;
73 case CONTROL('N'):
74 action_jump(buffer, NEXT, opt);
75 break;
77 case CONTROL('P'):
78 action_jump(buffer, PREV, opt);
79 break;
81 case CONTROL('I'): /* tab */
82 strcpy(buffer->input, buffer->current->content);
83 filter_lines(buffer, opt);
84 break;
86 case CONTROL('M'):
87 case CONTROL('J'): /* enter */
88 action_print_selection(buffer, opt);
89 return FALSE;
91 default:
92 action_add_character(buffer, key, opt);
95 return TRUE;
99 * Set the current line to the next/previous/closest matching line.
101 void
102 action_jump(Buffer *buffer, int direction, Opt *opt)
104 Line * line = buffer->current;
106 if (direction == BOTH) {
107 line = matching_next(buffer->current);
108 line = (line) ? line : matching_prev(buffer->current);
109 } else if (direction == NEXT) {
110 line = matching_next(line);
111 } else if (direction == PREV) {
112 line = matching_prev(line);
115 buffer->current = (line) ? line : buffer->current;
117 if (opt->print_numbers)
118 action_print_selection(buffer, opt);
122 * Send the selection to stdout.
124 void
125 action_print_selection(Buffer *buffer, Opt *opt)
127 fputs("\r\033[K", stderr);
129 if (opt->print_numbers) {
130 printf("%d\n", buffer->current->number);
131 } else {
132 if (opt->complete_mode) {
133 puts(buffer->input);
134 } else {
135 puts(buffer->current->content);
141 * Remove the last word from the buffer's input
143 void
144 action_remove_word_input(Buffer *buffer)
146 size_t length = strlen(buffer->input) - 1;
147 int i;
149 for (i = length; i >= 0 && isspace(buffer->input[i]); i--) {
150 buffer->input[i] = '\0';
153 length = strlen(buffer->input) - 1;
154 for (i = length; i >= 0 && !isspace(buffer->input[i]); i--) {
155 buffer->input[i] = '\0';
160 * Add a character to the buffer input and filter lines again.
162 void
163 action_add_character(Buffer *buffer, char key, Opt *opt)
165 size_t length = strlen(buffer->input);
167 if (isprint(key)) {
168 buffer->input[length] = key;
169 buffer->input[length + 1] = '\0';
172 filter_lines(buffer, opt);
174 if (!buffer->current->matches) {
175 action_jump(buffer, BOTH, opt);
178 if (!buffer->current->matches) {
179 buffer->current = buffer->empty;