Changes in uspace/app/bdsh/input.c [3041fef1:ef8bcc6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/input.c
r3041fef1 ref8bcc6 38 38 #include <vfs/vfs.h> 39 39 #include <errno.h> 40 #include <assert.h>41 40 #include <bool.h> 42 41 … … 48 47 #include "exec.h" 49 48 50 #define HISTORY_LEN 10 51 52 typedef struct { 53 wchar_t buffer[INPUT_MAX]; 54 int col0, row0; 55 int con_cols, con_rows; 56 int nc; 57 int pos; 58 59 char *history[1 + HISTORY_LEN]; 60 int hnum; 61 int hpos; 62 } tinput_t; 63 64 typedef enum { 65 seek_backward = -1, 66 seek_forward = 1 67 } seek_dir_t; 68 69 static tinput_t tinput; 70 71 static char *tinput_read(tinput_t *ti); 49 static void read_line(char *, int); 72 50 73 51 /* Tokenizes input from console, sees if the first word is a built-in, if so … … 121 99 } 122 100 123 static void tinput_display_tail(tinput_t *ti, int start, int pad) 124 { 125 int i; 126 127 console_goto(fphone(stdout), (ti->col0 + start) % ti->con_cols, 128 ti->row0 + (ti->col0 + start) / ti->con_cols); 129 printf("%ls", ti->buffer + start); 130 for (i = 0; i < pad; ++i) 131 putchar(' '); 132 fflush(stdout); 133 } 134 135 static char *tinput_get_str(tinput_t *ti) 136 { 137 return wstr_to_astr(ti->buffer); 138 } 139 140 static void tinput_position_caret(tinput_t *ti) 141 { 142 console_goto(fphone(stdout), (ti->col0 + ti->pos) % ti->con_cols, 143 ti->row0 + (ti->col0 + ti->pos) / ti->con_cols); 144 } 145 146 /** Update row0 in case the screen could have scrolled. */ 147 static void tinput_update_origin(tinput_t *ti) 148 { 149 int width, rows; 150 151 width = ti->col0 + ti->nc; 152 rows = (width / ti->con_cols) + 1; 153 154 /* Update row0 if the screen scrolled. */ 155 if (ti->row0 + rows > ti->con_rows) 156 ti->row0 = ti->con_rows - rows; 157 } 158 159 static void tinput_insert_char(tinput_t *ti, wchar_t c) 160 { 161 int i; 162 int new_width, new_height; 163 164 if (ti->nc == INPUT_MAX) 165 return; 166 167 new_width = ti->col0 + ti->nc + 1; 168 if (new_width % ti->con_cols == 0) { 169 /* Advancing to new line. */ 170 new_height = (new_width / ti->con_cols) + 1; 171 if (new_height >= ti->con_rows) 172 return; /* Disallow text longer than 1 page for now. */ 173 } 174 175 for (i = ti->nc; i > ti->pos; --i) 176 ti->buffer[i] = ti->buffer[i - 1]; 177 178 ti->buffer[ti->pos] = c; 179 ti->pos += 1; 180 ti->nc += 1; 181 ti->buffer[ti->nc] = '\0'; 182 183 tinput_display_tail(ti, ti->pos - 1, 0); 184 tinput_update_origin(ti); 185 tinput_position_caret(ti); 186 } 187 188 static void tinput_backspace(tinput_t *ti) 189 { 190 int i; 191 192 if (ti->pos == 0) 193 return; 194 195 for (i = ti->pos; i < ti->nc; ++i) 196 ti->buffer[i - 1] = ti->buffer[i]; 197 ti->pos -= 1; 198 ti->nc -= 1; 199 ti->buffer[ti->nc] = '\0'; 200 201 tinput_display_tail(ti, ti->pos, 1); 202 tinput_position_caret(ti); 203 } 204 205 static void tinput_delete(tinput_t *ti) 206 { 207 if (ti->pos == ti->nc) 208 return; 209 210 ti->pos += 1; 211 tinput_backspace(ti); 212 } 213 214 static void tinput_seek_cell(tinput_t *ti, seek_dir_t dir) 215 { 216 if (dir == seek_forward) { 217 if (ti->pos < ti->nc) 218 ti->pos += 1; 219 } else { 220 if (ti->pos > 0) 221 ti->pos -= 1; 222 } 223 224 tinput_position_caret(ti); 225 } 226 227 static void tinput_seek_word(tinput_t *ti, seek_dir_t dir) 228 { 229 if (dir == seek_forward) { 230 if (ti->pos == ti->nc) 231 return; 232 233 while (1) { 234 ti->pos += 1; 235 236 if (ti->pos == ti->nc) 237 break; 238 239 if (ti->buffer[ti->pos - 1] == ' ' && 240 ti->buffer[ti->pos] != ' ') 241 break; 242 } 243 } else { 244 if (ti->pos == 0) 245 return; 246 247 while (1) { 248 ti->pos -= 1; 249 250 if (ti->pos == 0) 251 break; 252 253 if (ti->buffer[ti->pos - 1] == ' ' && 254 ti->buffer[ti->pos] != ' ') 255 break; 256 } 257 258 } 259 260 tinput_position_caret(ti); 261 } 262 263 static void tinput_seek_vertical(tinput_t *ti, seek_dir_t dir) 264 { 265 if (dir == seek_forward) { 266 if (ti->pos + ti->con_cols <= ti->nc) 267 ti->pos = ti->pos + ti->con_cols; 268 } else { 269 if (ti->pos - ti->con_cols >= 0) 270 ti->pos = ti->pos - ti->con_cols; 271 } 272 273 tinput_position_caret(ti); 274 } 275 276 static void tinput_seek_max(tinput_t *ti, seek_dir_t dir) 277 { 278 if (dir == seek_backward) 279 ti->pos = 0; 280 else 281 ti->pos = ti->nc; 282 283 tinput_position_caret(ti); 284 } 285 286 static void tinput_history_insert(tinput_t *ti, char *str) 287 { 288 int i; 289 290 if (ti->hnum < HISTORY_LEN) { 291 ti->hnum += 1; 292 } else { 293 if (ti->history[HISTORY_LEN] != NULL) 294 free(ti->history[HISTORY_LEN]); 295 } 296 297 for (i = ti->hnum; i > 1; --i) 298 ti->history[i] = ti->history[i - 1]; 299 300 ti->history[1] = str_dup(str); 301 302 if (ti->history[0] != NULL) { 303 free(ti->history[0]); 304 ti->history[0] = NULL; 305 } 306 } 307 308 static void tinput_set_str(tinput_t *ti, char *str) 309 { 310 str_to_wstr(ti->buffer, INPUT_MAX, str); 311 ti->nc = wstr_length(ti->buffer); 312 ti->pos = ti->nc; 313 } 314 315 static void tinput_history_seek(tinput_t *ti, int offs) 316 { 317 int pad; 318 319 if (ti->hpos + offs < 0 || ti->hpos + offs > ti->hnum) 320 return; 321 322 if (ti->history[ti->hpos] != NULL) { 323 free(ti->history[ti->hpos]); 324 ti->history[ti->hpos] = NULL; 325 } 326 327 ti->history[ti->hpos] = tinput_get_str(ti); 328 ti->hpos += offs; 329 330 pad = ti->nc - str_length(ti->history[ti->hpos]); 331 if (pad < 0) pad = 0; 332 333 tinput_set_str(ti, ti->history[ti->hpos]); 334 tinput_display_tail(ti, 0, pad); 335 tinput_update_origin(ti); 336 tinput_position_caret(ti); 337 } 338 339 static void tinput_init(tinput_t *ti) 340 { 341 ti->hnum = 0; 342 ti->hpos = 0; 343 ti->history[0] = NULL; 344 } 345 346 static char *tinput_read(tinput_t *ti) 101 static void read_line(char *buffer, int n) 347 102 { 348 103 console_event_t ev; 349 char *str; 104 size_t offs, otmp; 105 wchar_t dec; 350 106 351 fflush(stdout); 352 353 if (console_get_size(fphone(stdin), &ti->con_cols, &ti->con_rows) != EOK) 354 return NULL; 355 if (console_get_pos(fphone(stdin), &ti->col0, &ti->row0) != EOK) 356 return NULL; 357 358 ti->pos = 0; 359 ti->nc = 0; 360 ti->buffer[0] = '\0'; 361 107 offs = 0; 362 108 while (true) { 363 109 fflush(stdout); 364 110 if (!console_get_event(fphone(stdin), &ev)) 365 return NULL;111 return; 366 112 367 113 if (ev.type != KEY_PRESS) 368 114 continue; 369 370 if ( (ev.mods & KM_CTRL) != 0 &&371 (ev.mods & (KM_ALT | KM_SHIFT)) == 0) {372 switch (ev.key) {373 case KC_LEFT:374 tinput_seek_word(ti, seek_backward);375 break;376 case KC_RIGHT:377 tinput_seek_word(ti, seek_forward);378 break;379 case KC_UP:380 tinput_seek_vertical(ti, seek_backward);381 break;382 case KC_DOWN:383 tinput_seek_vertical(ti, seek_forward);384 break;115 116 if (ev.key == KC_ENTER || ev.key == KC_NENTER) 117 break; 118 if (ev.key == KC_BACKSPACE) { 119 if (offs > 0) { 120 /* 121 * Back up until we reach valid start of 122 * character. 123 */ 124 while (offs > 0) { 125 --offs; otmp = offs; 126 dec = str_decode(buffer, &otmp, n); 127 if (dec != U_SPECIAL) 128 break; 129 } 130 putchar('\b'); 385 131 } 132 continue; 386 133 } 387 388 if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {389 switch (ev.key) {390 case KC_ENTER:391 case KC_NENTER:392 goto done;393 case KC_BACKSPACE:394 tinput_backspace(ti);395 break;396 case KC_DELETE:397 tinput_delete(ti);398 break;399 case KC_LEFT:400 tinput_seek_cell(ti, seek_backward);401 break;402 case KC_RIGHT:403 tinput_seek_cell(ti, seek_forward);404 break;405 case KC_HOME:406 tinput_seek_max(ti, seek_backward);407 break;408 case KC_END:409 tinput_seek_max(ti, seek_forward);410 break;411 case KC_UP:412 tinput_history_seek(ti, +1);413 break;414 case KC_DOWN:415 tinput_history_seek(ti, -1);416 break;417 }418 }419 420 134 if (ev.c >= ' ') { 421 tinput_insert_char(ti, ev.c); 135 if (chr_encode(ev.c, buffer, &offs, n - 1) == EOK) 136 putchar(ev.c); 422 137 } 423 138 } 424 425 done:426 ti->pos = ti->nc;427 tinput_position_caret(ti);428 139 putchar('\n'); 429 430 str = tinput_get_str(ti); 431 if (str_cmp(str, "") != 0) 432 tinput_history_insert(ti, str); 433 434 ti->hpos = 0; 435 436 return str; 140 buffer[offs] = '\0'; 437 141 } 438 142 143 /* TODO: 144 * Implement something like editline() / readline(), if even 145 * just for command history and making arrows work. */ 439 146 void get_input(cliuser_t *usr) 440 147 { 441 char *str;148 char line[INPUT_MAX]; 442 149 443 150 fflush(stdout); … … 447 154 console_set_style(fphone(stdout), STYLE_NORMAL); 448 155 449 str = tinput_read(&tinput); 156 read_line(line, INPUT_MAX); 157 /* Make sure we don't have rubbish or a C/R happy user */ 158 if (str_cmp(line, "") == 0 || str_cmp(line, "\n") == 0) 159 return; 160 usr->line = str_dup(line); 450 161 451 /* Check for empty input. */452 if (str_cmp(str, "") == 0) {453 free(str);454 return;455 }456 457 usr->line = str;458 162 return; 459 163 } 460 164 461 void input_init(void)462 {463 tinput_init(&tinput);464 }
Note:
See TracChangeset
for help on using the changeset viewer.