Changes in uspace/app/bdsh/input.c [bc77bfa:3041fef1] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/input.c
rbc77bfa r3041fef1 36 36 #include <io/keycode.h> 37 37 #include <io/style.h> 38 #include <io/color.h>39 38 #include <vfs/vfs.h> 40 #include <clipboard.h>41 #include <macros.h>42 39 #include <errno.h> 43 40 #include <assert.h> … … 53 50 #define HISTORY_LEN 10 54 51 55 /** Text input field. */56 52 typedef struct { 57 /** Buffer holding text currently being edited */ 58 wchar_t buffer[INPUT_MAX + 1]; 59 /** Screen coordinates of the top-left corner of the text field */ 53 wchar_t buffer[INPUT_MAX]; 60 54 int col0, row0; 61 /** Screen dimensions */62 55 int con_cols, con_rows; 63 /** Number of characters in @c buffer */64 56 int nc; 65 /** Caret position within buffer */66 57 int pos; 67 /** Selection mark position within buffer */ 68 int sel_start; 69 70 /** History (dynamically allocated strings) */ 58 71 59 char *history[1 + HISTORY_LEN]; 72 /** Number of entries in @c history, not counting [0] */73 60 int hnum; 74 /** Current position in history */75 61 int hpos; 76 /** Exit flag */77 bool done;78 62 } tinput_t; 79 63 80 /** Seek direction */81 64 typedef enum { 82 65 seek_backward = -1, … … 87 70 88 71 static char *tinput_read(tinput_t *ti); 89 static void tinput_insert_string(tinput_t *ti, const char *str);90 static void tinput_sel_get_bounds(tinput_t *ti, int *sa, int *sb);91 static bool tinput_sel_active(tinput_t *ti);92 static void tinput_sel_all(tinput_t *ti);93 static void tinput_sel_delete(tinput_t *ti);94 static void tinput_key_ctrl(tinput_t *ti, console_event_t *ev);95 static void tinput_key_shift(tinput_t *ti, console_event_t *ev);96 static void tinput_key_ctrl_shift(tinput_t *ti, console_event_t *ev);97 static void tinput_key_unmod(tinput_t *ti, console_event_t *ev);98 static void tinput_pre_seek(tinput_t *ti, bool shift_held);99 static void tinput_post_seek(tinput_t *ti, bool shift_held);100 72 101 73 /* Tokenizes input from console, sees if the first word is a built-in, if so … … 151 123 static void tinput_display_tail(tinput_t *ti, int start, int pad) 152 124 { 153 static wchar_t dbuf[INPUT_MAX + 1]; 154 int sa, sb; 155 int i, p; 156 157 tinput_sel_get_bounds(ti, &sa, &sb); 125 int i; 158 126 159 127 console_goto(fphone(stdout), (ti->col0 + start) % ti->con_cols, 160 128 ti->row0 + (ti->col0 + start) / ti->con_cols); 161 console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); 162 163 p = start; 164 if (p < sa) { 165 memcpy(dbuf, ti->buffer + p, (sa - p) * sizeof(wchar_t)); 166 dbuf[sa - p] = '\0'; 167 printf("%ls", dbuf); 168 p = sa; 169 } 170 171 if (p < sb) { 172 fflush(stdout); 173 console_set_color(fphone(stdout), COLOR_BLACK, COLOR_RED, 0); 174 memcpy(dbuf, ti->buffer + p, 175 (sb - p) * sizeof(wchar_t)); 176 dbuf[sb - p] = '\0'; 177 printf("%ls", dbuf); 178 p = sb; 179 } 180 181 fflush(stdout); 182 console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0); 183 184 if (p < ti->nc) { 185 memcpy(dbuf, ti->buffer + p, 186 (ti->nc - p) * sizeof(wchar_t)); 187 dbuf[ti->nc - p] = '\0'; 188 printf("%ls", dbuf); 189 } 190 129 printf("%ls", ti->buffer + start); 191 130 for (i = 0; i < pad; ++i) 192 131 putchar(' '); … … 212 151 width = ti->col0 + ti->nc; 213 152 rows = (width / ti->con_cols) + 1; 214 153 215 154 /* Update row0 if the screen scrolled. */ 216 155 if (ti->row0 + rows > ti->con_rows) … … 241 180 ti->nc += 1; 242 181 ti->buffer[ti->nc] = '\0'; 243 ti->sel_start = ti->pos;244 182 245 183 tinput_display_tail(ti, ti->pos - 1, 0); … … 248 186 } 249 187 250 static void tinput_ insert_string(tinput_t *ti, const char *str)188 static void tinput_backspace(tinput_t *ti) 251 189 { 252 190 int i; 253 int new_width, new_height;254 int ilen;255 wchar_t c;256 size_t off;257 258 ilen = min((ssize_t) str_length(str), INPUT_MAX - ti->nc);259 if (ilen == 0)260 return;261 262 new_width = ti->col0 + ti->nc + ilen;263 new_height = (new_width / ti->con_cols) + 1;264 if (new_height >= ti->con_rows)265 return; /* Disallow text longer than 1 page for now. */266 267 for (i = ti->nc - 1; i >= ti->pos; --i)268 ti->buffer[i + ilen] = ti->buffer[i];269 270 off = 0; i = 0;271 while (i < ilen) {272 c = str_decode(str, &off, STR_NO_LIMIT);273 if (c == '\0')274 break;275 276 /* Filter out non-printable chars. */277 if (c < 32)278 c = 32;279 280 ti->buffer[ti->pos + i] = c;281 ++i;282 }283 284 ti->pos += ilen;285 ti->nc += ilen;286 ti->buffer[ti->nc] = '\0';287 ti->sel_start = ti->pos;288 289 tinput_display_tail(ti, ti->pos - ilen, 0);290 tinput_update_origin(ti);291 tinput_position_caret(ti);292 }293 294 static void tinput_backspace(tinput_t *ti)295 {296 int i;297 298 if (tinput_sel_active(ti)) {299 tinput_sel_delete(ti);300 return;301 }302 191 303 192 if (ti->pos == 0) … … 309 198 ti->nc -= 1; 310 199 ti->buffer[ti->nc] = '\0'; 311 ti->sel_start = ti->pos;312 200 313 201 tinput_display_tail(ti, ti->pos, 1); … … 317 205 static void tinput_delete(tinput_t *ti) 318 206 { 319 if (tinput_sel_active(ti)) {320 tinput_sel_delete(ti);321 return;322 }323 324 207 if (ti->pos == ti->nc) 325 208 return; 326 209 327 210 ti->pos += 1; 328 ti->sel_start = ti->pos;329 330 211 tinput_backspace(ti); 331 212 } 332 213 333 static void tinput_seek_cell(tinput_t *ti, seek_dir_t dir, bool shift_held) 334 { 335 tinput_pre_seek(ti, shift_held); 336 214 static void tinput_seek_cell(tinput_t *ti, seek_dir_t dir) 215 { 337 216 if (dir == seek_forward) { 338 217 if (ti->pos < ti->nc) … … 343 222 } 344 223 345 tinput_post_seek(ti, shift_held); 346 } 347 348 static void tinput_seek_word(tinput_t *ti, seek_dir_t dir, bool shift_held) 349 { 350 tinput_pre_seek(ti, shift_held); 351 224 tinput_position_caret(ti); 225 } 226 227 static void tinput_seek_word(tinput_t *ti, seek_dir_t dir) 228 { 352 229 if (dir == seek_forward) { 353 230 if (ti->pos == ti->nc) … … 381 258 } 382 259 383 tinput_post_seek(ti, shift_held); 384 } 385 386 static void tinput_seek_vertical(tinput_t *ti, seek_dir_t dir, bool shift_held) 387 { 388 tinput_pre_seek(ti, shift_held); 389 260 tinput_position_caret(ti); 261 } 262 263 static void tinput_seek_vertical(tinput_t *ti, seek_dir_t dir) 264 { 390 265 if (dir == seek_forward) { 391 266 if (ti->pos + ti->con_cols <= ti->nc) … … 396 271 } 397 272 398 tinput_post_seek(ti, shift_held); 399 } 400 401 static void tinput_seek_max(tinput_t *ti, seek_dir_t dir, bool shift_held) 402 { 403 tinput_pre_seek(ti, shift_held); 404 273 tinput_position_caret(ti); 274 } 275 276 static void tinput_seek_max(tinput_t *ti, seek_dir_t dir) 277 { 405 278 if (dir == seek_backward) 406 279 ti->pos = 0; … … 408 281 ti->pos = ti->nc; 409 282 410 tinput_post_seek(ti, shift_held);411 }412 413 static void tinput_pre_seek(tinput_t *ti, bool shift_held)414 {415 if (tinput_sel_active(ti) && !shift_held) {416 /* Unselect and redraw. */417 ti->sel_start = ti->pos;418 tinput_display_tail(ti, 0, 0);419 tinput_position_caret(ti);420 }421 }422 423 static void tinput_post_seek(tinput_t *ti, bool shift_held)424 {425 if (shift_held) {426 /* Selecting text. Need redraw. */427 tinput_display_tail(ti, 0, 0);428 } else {429 /* Shift not held. Keep selection empty. */430 ti->sel_start = ti->pos;431 }432 283 tinput_position_caret(ti); 433 284 } … … 460 311 ti->nc = wstr_length(ti->buffer); 461 312 ti->pos = ti->nc; 462 ti->sel_start = ti->pos;463 }464 465 static void tinput_sel_get_bounds(tinput_t *ti, int *sa, int *sb)466 {467 if (ti->sel_start < ti->pos) {468 *sa = ti->sel_start;469 *sb = ti->pos;470 } else {471 *sa = ti->pos;472 *sb = ti->sel_start;473 }474 }475 476 static bool tinput_sel_active(tinput_t *ti)477 {478 return ti->sel_start != ti->pos;479 }480 481 static void tinput_sel_all(tinput_t *ti)482 {483 ti->sel_start = 0;484 ti->pos = ti->nc;485 tinput_display_tail(ti, 0, 0);486 tinput_position_caret(ti);487 }488 489 static void tinput_sel_delete(tinput_t *ti)490 {491 int sa, sb;492 493 tinput_sel_get_bounds(ti, &sa, &sb);494 if (sa == sb)495 return;496 497 memmove(ti->buffer + sa, ti->buffer + sb,498 (ti->nc - sb) * sizeof(wchar_t));499 ti->pos = ti->sel_start = sa;500 ti->nc -= (sb - sa);501 ti->buffer[ti->nc] = '\0';502 503 tinput_display_tail(ti, sa, sb - sa);504 tinput_position_caret(ti);505 }506 507 static void tinput_sel_copy_to_cb(tinput_t *ti)508 {509 int sa, sb;510 wchar_t tmp_c;511 char *str;512 513 tinput_sel_get_bounds(ti, &sa, &sb);514 515 if (sb < ti->nc) {516 tmp_c = ti->buffer[sb];517 ti->buffer[sb] = '\0';518 }519 520 str = wstr_to_astr(ti->buffer + sa);521 522 if (sb < ti->nc)523 ti->buffer[sb] = tmp_c;524 525 if (str == NULL)526 goto error;527 528 if (clipboard_put_str(str) != EOK)529 goto error;530 531 free(str);532 return;533 error:534 return;535 /* TODO: Give the user some warning. */536 }537 538 static void tinput_paste_from_cb(tinput_t *ti)539 {540 char *str;541 int rc;542 543 rc = clipboard_get_str(&str);544 if (rc != EOK || str == NULL)545 return; /* TODO: Give the user some warning. */546 547 tinput_insert_string(ti, str);548 free(str);549 313 } 550 314 … … 573 337 } 574 338 575 /** Initialize text input field.576 *577 * Must be called before using the field. It clears the history.578 */579 339 static void tinput_init(tinput_t *ti) 580 340 { … … 584 344 } 585 345 586 /** Read in one line of input. */587 346 static char *tinput_read(tinput_t *ti) 588 347 { … … 597 356 return NULL; 598 357 599 ti->pos = ti->sel_start =0;358 ti->pos = 0; 600 359 ti->nc = 0; 601 360 ti->buffer[0] = '\0'; 602 ti->done = false; 603 604 while (!ti->done) { 361 362 while (true) { 605 363 fflush(stdout); 606 364 if (!console_get_event(fphone(stdin), &ev)) 607 365 return NULL; 608 366 609 367 if (ev.type != KEY_PRESS) 610 368 continue; … … 612 370 if ((ev.mods & KM_CTRL) != 0 && 613 371 (ev.mods & (KM_ALT | KM_SHIFT)) == 0) { 614 tinput_key_ctrl(ti, &ev); 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; 385 } 615 386 } 616 387 617 if ((ev.mods & KM_SHIFT) != 0 && 618 (ev.mods & (KM_CTRL | KM_ALT)) == 0) { 619 tinput_key_shift(ti, &ev); 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 } 620 418 } 621 419 622 if ((ev.mods & KM_CTRL) != 0 &&623 (ev.mods & KM_SHIFT) != 0 &&624 (ev.mods & KM_ALT) == 0) {625 tinput_key_ctrl_shift(ti, &ev);626 }627 628 if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {629 tinput_key_unmod(ti, &ev);630 }631 632 420 if (ev.c >= ' ') { 633 tinput_sel_delete(ti);634 421 tinput_insert_char(ti, ev.c); 635 422 } 636 423 } 637 424 425 done: 638 426 ti->pos = ti->nc; 639 427 tinput_position_caret(ti); … … 647 435 648 436 return str; 649 }650 651 static void tinput_key_ctrl(tinput_t *ti, console_event_t *ev)652 {653 switch (ev->key) {654 case KC_LEFT:655 tinput_seek_word(ti, seek_backward, false);656 break;657 case KC_RIGHT:658 tinput_seek_word(ti, seek_forward, false);659 break;660 case KC_UP:661 tinput_seek_vertical(ti, seek_backward, false);662 break;663 case KC_DOWN:664 tinput_seek_vertical(ti, seek_forward, false);665 break;666 case KC_X:667 tinput_sel_copy_to_cb(ti);668 tinput_sel_delete(ti);669 break;670 case KC_C:671 tinput_sel_copy_to_cb(ti);672 break;673 case KC_V:674 tinput_sel_delete(ti);675 tinput_paste_from_cb(ti);676 break;677 case KC_A:678 tinput_sel_all(ti);679 break;680 default:681 break;682 }683 }684 685 static void tinput_key_ctrl_shift(tinput_t *ti, console_event_t *ev)686 {687 switch (ev->key) {688 case KC_LEFT:689 tinput_seek_word(ti, seek_backward, true);690 break;691 case KC_RIGHT:692 tinput_seek_word(ti, seek_forward, true);693 break;694 case KC_UP:695 tinput_seek_vertical(ti, seek_backward, true);696 break;697 case KC_DOWN:698 tinput_seek_vertical(ti, seek_forward, true);699 break;700 default:701 break;702 }703 }704 705 static void tinput_key_shift(tinput_t *ti, console_event_t *ev)706 {707 switch (ev->key) {708 case KC_LEFT:709 tinput_seek_cell(ti, seek_backward, true);710 break;711 case KC_RIGHT:712 tinput_seek_cell(ti, seek_forward, true);713 break;714 case KC_UP:715 tinput_seek_vertical(ti, seek_backward, true);716 break;717 case KC_DOWN:718 tinput_seek_vertical(ti, seek_forward, true);719 break;720 case KC_HOME:721 tinput_seek_max(ti, seek_backward, true);722 break;723 case KC_END:724 tinput_seek_max(ti, seek_forward, true);725 break;726 default:727 break;728 }729 }730 731 static void tinput_key_unmod(tinput_t *ti, console_event_t *ev)732 {733 switch (ev->key) {734 case KC_ENTER:735 case KC_NENTER:736 ti->done = true;737 break;738 case KC_BACKSPACE:739 tinput_backspace(ti);740 break;741 case KC_DELETE:742 tinput_delete(ti);743 break;744 case KC_LEFT:745 tinput_seek_cell(ti, seek_backward, false);746 break;747 case KC_RIGHT:748 tinput_seek_cell(ti, seek_forward, false);749 break;750 case KC_HOME:751 tinput_seek_max(ti, seek_backward, false);752 break;753 case KC_END:754 tinput_seek_max(ti, seek_forward, false);755 break;756 case KC_UP:757 tinput_history_seek(ti, +1);758 break;759 case KC_DOWN:760 tinput_history_seek(ti, -1);761 break;762 default:763 break;764 }765 437 } 766 438
Note:
See TracChangeset
for help on using the changeset viewer.