source: mainline/uspace/app/bdsh/input.c@ 025759c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 025759c was 025759c, checked in by jirka <jirka@…>, 16 years ago

Word seek.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
2 * All rights reserved.
3 * Copyright (c) 2008, Jiri Svoboda - All Rights Reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * Neither the name of the original program's authors nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <io/console.h>
36#include <io/keycode.h>
37#include <io/style.h>
38#include <vfs/vfs.h>
39#include <errno.h>
40#include <bool.h>
41
42#include "config.h"
43#include "util.h"
44#include "scli.h"
45#include "input.h"
46#include "errors.h"
47#include "exec.h"
48
49typedef struct {
50 wchar_t buffer[INPUT_MAX];
51 int col0, row0;
52 int con_cols, con_rows;
53 int nc;
54 int pos;
55} tinput_t;
56
57typedef enum {
58 seek_backward = -1,
59 seek_forward = 1
60} seek_dir_t;
61
62static tinput_t tinput;
63
64static char *tinput_read(tinput_t *ti);
65
66/* Tokenizes input from console, sees if the first word is a built-in, if so
67 * invokes the built-in entry point (a[0]) passing all arguments in a[] to
68 * the handler */
69int tok_input(cliuser_t *usr)
70{
71 char *cmd[WORD_MAX];
72 int n = 0, i = 0;
73 int rc = 0;
74 char *tmp;
75
76 if (NULL == usr->line)
77 return CL_EFAIL;
78
79 tmp = str_dup(usr->line);
80
81 cmd[n] = strtok(tmp, " ");
82 while (cmd[n] && n < WORD_MAX) {
83 cmd[++n] = strtok(NULL, " ");
84 }
85
86 /* We have rubbish */
87 if (NULL == cmd[0]) {
88 rc = CL_ENOENT;
89 goto finit;
90 }
91
92 /* Its a builtin command ? */
93 if ((i = (is_builtin(cmd[0]))) > -1) {
94 rc = run_builtin(i, cmd, usr);
95 goto finit;
96 /* Its a module ? */
97 } else if ((i = (is_module(cmd[0]))) > -1) {
98 rc = run_module(i, cmd);
99 goto finit;
100 }
101
102 /* See what try_exec thinks of it */
103 rc = try_exec(cmd[0], cmd);
104
105finit:
106 if (NULL != usr->line) {
107 free(usr->line);
108 usr->line = (char *) NULL;
109 }
110 if (NULL != tmp)
111 free(tmp);
112
113 return rc;
114}
115
116static void tinput_display_tail(tinput_t *ti, int start, int pad)
117{
118 int i;
119
120 console_goto(fphone(stdout), ti->col0 + start, ti->row0);
121 printf("%ls", ti->buffer + start);
122 for (i = 0; i < pad; ++i)
123 putchar(' ');
124 fflush(stdout);
125}
126
127static void tinput_position_caret(tinput_t *ti)
128{
129 console_goto(fphone(stdout), ti->col0 + ti->pos, ti->row0);
130}
131
132static void tinput_insert_char(tinput_t *ti, wchar_t c)
133{
134 int i;
135
136 if (ti->nc == INPUT_MAX)
137 return;
138
139 if (ti->col0 + ti->nc >= ti->con_cols - 1)
140 return;
141
142 for (i = ti->nc; i > ti->pos; --i)
143 ti->buffer[i] = ti->buffer[i - 1];
144
145 ti->buffer[ti->pos] = c;
146 ti->pos += 1;
147 ti->nc += 1;
148 ti->buffer[ti->nc] = '\0';
149
150 tinput_display_tail(ti, ti->pos - 1, 0);
151 tinput_position_caret(ti);
152}
153
154static void tinput_backspace(tinput_t *ti)
155{
156 int i;
157
158 if (ti->pos == 0)
159 return;
160
161 for (i = ti->pos; i < ti->nc; ++i)
162 ti->buffer[i - 1] = ti->buffer[i];
163 ti->pos -= 1;
164 ti->nc -= 1;
165 ti->buffer[ti->nc] = '\0';
166
167 tinput_display_tail(ti, ti->pos, 1);
168 tinput_position_caret(ti);
169}
170
171static void tinput_delete(tinput_t *ti)
172{
173 if (ti->pos == ti->nc)
174 return;
175
176 ti->pos += 1;
177 tinput_backspace(ti);
178}
179
180static void tinput_seek_cell(tinput_t *ti, seek_dir_t dir)
181{
182 if (dir == seek_forward) {
183 if (ti->pos < ti->nc)
184 ti->pos += 1;
185 } else {
186 if (ti->pos > 0)
187 ti->pos -= 1;
188 }
189
190 tinput_position_caret(ti);
191}
192
193static void tinput_seek_word(tinput_t *ti, seek_dir_t dir)
194{
195 if (dir == seek_forward) {
196 if (ti->pos == ti->nc)
197 return;
198
199 while (1) {
200 ti->pos += 1;
201
202 if (ti->pos == ti->nc)
203 break;
204
205 if (ti->buffer[ti->pos - 1] == ' ' &&
206 ti->buffer[ti->pos] != ' ')
207 break;
208 }
209 } else {
210 if (ti->pos == 0)
211 return;
212
213 while (1) {
214 ti->pos -= 1;
215
216 if (ti->pos == 0)
217 break;
218
219 if (ti->buffer[ti->pos - 1] == ' ' &&
220 ti->buffer[ti->pos] != ' ')
221 break;
222 }
223
224 }
225
226 tinput_position_caret(ti);
227}
228
229static void tinput_seek_max(tinput_t *ti, seek_dir_t dir)
230{
231 if (dir == seek_backward)
232 ti->pos = 0;
233 else
234 ti->pos = ti->nc;
235
236 tinput_position_caret(ti);
237}
238
239static char *tinput_read(tinput_t *ti)
240{
241 console_event_t ev;
242 char *str;
243
244 fflush(stdout);
245
246 if (console_get_size(fphone(stdin), &ti->con_cols, &ti->con_rows) != EOK)
247 return NULL;
248 if (console_get_pos(fphone(stdin), &ti->col0, &ti->row0) != EOK)
249 return NULL;
250
251 ti->pos = 0;
252 ti->nc = 0;
253
254 while (true) {
255 fflush(stdout);
256 if (!console_get_event(fphone(stdin), &ev))
257 return NULL;
258
259 if (ev.type != KEY_PRESS)
260 continue;
261
262 if ((ev.mods & KM_CTRL) != 0 &&
263 (ev.mods & (KM_ALT | KM_SHIFT)) == 0) {
264 switch (ev.key) {
265 case KC_LEFT:
266 tinput_seek_word(ti, seek_backward);
267 break;
268 case KC_RIGHT:
269 tinput_seek_word(ti, seek_forward);
270 break;
271 }
272 }
273
274 if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
275 switch (ev.key) {
276 case KC_ENTER:
277 case KC_NENTER:
278 goto done;
279 case KC_BACKSPACE:
280 tinput_backspace(ti);
281 break;
282 case KC_DELETE:
283 tinput_delete(ti);
284 break;
285 case KC_LEFT:
286 tinput_seek_cell(ti, seek_backward);
287 break;
288 case KC_RIGHT:
289 tinput_seek_cell(ti, seek_forward);
290 break;
291 case KC_HOME:
292 tinput_seek_max(ti, seek_backward);
293 break;
294 case KC_END:
295 tinput_seek_max(ti, seek_forward);
296 break;
297 }
298 }
299
300 if (ev.c >= ' ') {
301 tinput_insert_char(ti, ev.c);
302 }
303 }
304
305done:
306 putchar('\n');
307
308 ti->buffer[ti->nc] = '\0';
309 str = malloc(STR_BOUNDS(ti->nc) + 1);
310 if (str == NULL)
311 return NULL;
312
313 wstr_nstr(str, ti->buffer, STR_BOUNDS(ti->nc) + 1);
314
315 return str;
316}
317
318void get_input(cliuser_t *usr)
319{
320 char *str;
321
322 fflush(stdout);
323 console_set_style(fphone(stdout), STYLE_EMPHASIS);
324 printf("%s", usr->prompt);
325 fflush(stdout);
326 console_set_style(fphone(stdout), STYLE_NORMAL);
327
328 str = tinput_read(&tinput);
329
330 /* Check for empty input. */
331 if (str_cmp(str, "") == 0) {
332 free(str);
333 return;
334 }
335
336 usr->line = str;
337 return;
338}
Note: See TracBrowser for help on using the repository browser.