Changeset fbcfc4da in mainline for uspace/app/bdsh/input.c
- Timestamp:
- 2009-12-03T19:25:17Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9510be2
- Parents:
- cb3d641a (diff), 22e6802 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/input.c
rcb3d641a rfbcfc4da 38 38 #include <vfs/vfs.h> 39 39 #include <errno.h> 40 #include <assert.h> 40 41 #include <bool.h> 41 42 … … 47 48 #include "exec.h" 48 49 49 static void read_line(char *, int); 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); 50 72 51 73 /* Tokenizes input from console, sees if the first word is a built-in, if so … … 99 121 } 100 122 101 static void read_line(char *buffer, int n) 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) 102 347 { 103 348 console_event_t ev; 104 size_t offs, otmp; 105 wchar_t dec; 106 107 offs = 0; 349 char *str; 350 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 108 362 while (true) { 109 363 fflush(stdout); 110 364 if (!console_get_event(fphone(stdin), &ev)) 111 return ;365 return NULL; 112 366 113 367 if (ev.type != KEY_PRESS) 114 368 continue; 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 of122 * 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');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; 131 385 } 132 continue;133 386 } 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 134 420 if (ev.c >= ' ') { 135 if (chr_encode(ev.c, buffer, &offs, n - 1) == EOK) 136 putchar(ev.c); 421 tinput_insert_char(ti, ev.c); 137 422 } 138 423 } 424 425 done: 426 ti->pos = ti->nc; 427 tinput_position_caret(ti); 139 428 putchar('\n'); 140 buffer[offs] = '\0'; 141 } 142 143 /* TODO: 144 * Implement something like editline() / readline(), if even 145 * just for command history and making arrows work. */ 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; 437 } 438 146 439 void get_input(cliuser_t *usr) 147 440 { 148 char line[INPUT_MAX];441 char *str; 149 442 150 443 fflush(stdout); … … 154 447 console_set_style(fphone(stdout), STYLE_NORMAL); 155 448 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) 449 str = tinput_read(&tinput); 450 451 /* Check for empty input. */ 452 if (str_cmp(str, "") == 0) { 453 free(str); 159 454 return; 160 usr->line = str_dup(line); 161 455 } 456 457 usr->line = str; 162 458 return; 163 459 } 164 460 461 void input_init(void) 462 { 463 tinput_init(&tinput); 464 }
Note:
See TracChangeset
for help on using the changeset viewer.