diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-09-14 11:41:16 +1000 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-09-14 11:41:16 +1000 |
commit | 743d85e7d1c2a721baf020b9d79f45f0df2420a9 (patch) | |
tree | 9e551b726ac2bf9fd8eafb2764e7237f352bb429 /libbb/lineedit.c | |
parent | 87911f4fcd86f7abc0aefba8e9cbec2ac9d127e4 (diff) | |
parent | c7f95d23f6bc7e17a3b79decf83eb362b389e53a (diff) | |
download | busybox-w32-743d85e7d1c2a721baf020b9d79f45f0df2420a9.tar.gz busybox-w32-743d85e7d1c2a721baf020b9d79f45f0df2420a9.tar.bz2 busybox-w32-743d85e7d1c2a721baf020b9d79f45f0df2420a9.zip |
Merge branch 'origin/master' (early part)
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r-- | libbb/lineedit.c | 320 |
1 files changed, 214 insertions, 106 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 9a04c38bf..f7faf4639 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -42,14 +42,10 @@ | |||
42 | #include "libbb.h" | 42 | #include "libbb.h" |
43 | #include "unicode.h" | 43 | #include "unicode.h" |
44 | 44 | ||
45 | /* FIXME: obsolete CONFIG item? */ | ||
46 | #define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0 | ||
47 | |||
48 | #ifdef TEST | 45 | #ifdef TEST |
49 | # define ENABLE_FEATURE_EDITING 0 | 46 | # define ENABLE_FEATURE_EDITING 0 |
50 | # define ENABLE_FEATURE_TAB_COMPLETION 0 | 47 | # define ENABLE_FEATURE_TAB_COMPLETION 0 |
51 | # define ENABLE_FEATURE_USERNAME_COMPLETION 0 | 48 | # define ENABLE_FEATURE_USERNAME_COMPLETION 0 |
52 | # define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0 | ||
53 | #endif | 49 | #endif |
54 | 50 | ||
55 | 51 | ||
@@ -66,9 +62,13 @@ | |||
66 | #endif | 62 | #endif |
67 | 63 | ||
68 | 64 | ||
65 | #define SEQ_CLEAR_TILL_END_OF_SCREEN "\033[J" | ||
66 | //#define SEQ_CLEAR_TILL_END_OF_LINE "\033[K" | ||
67 | |||
68 | |||
69 | #undef CHAR_T | 69 | #undef CHAR_T |
70 | #if ENABLE_UNICODE_SUPPORT | 70 | #if ENABLE_UNICODE_SUPPORT |
71 | # define BB_NUL L'\0' | 71 | # define BB_NUL ((wchar_t)0) |
72 | # define CHAR_T wchar_t | 72 | # define CHAR_T wchar_t |
73 | static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); } | 73 | static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); } |
74 | # if ENABLE_FEATURE_EDITING_VI | 74 | # if ENABLE_FEATURE_EDITING_VI |
@@ -92,6 +92,14 @@ static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } | |||
92 | #endif | 92 | #endif |
93 | 93 | ||
94 | 94 | ||
95 | # if ENABLE_UNICODE_PRESERVE_BROKEN | ||
96 | # define unicode_mark_raw_byte(wc) ((wc) | 0x20000000) | ||
97 | # define unicode_is_raw_byte(wc) ((wc) & 0x20000000) | ||
98 | # else | ||
99 | # define unicode_is_raw_byte(wc) 0 | ||
100 | # endif | ||
101 | |||
102 | |||
95 | enum { | 103 | enum { |
96 | /* We use int16_t for positions, need to limit line len */ | 104 | /* We use int16_t for positions, need to limit line len */ |
97 | MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN < 0x7ff0 | 105 | MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN < 0x7ff0 |
@@ -208,42 +216,107 @@ static size_t load_string(const char *src, int maxsize) | |||
208 | ssize_t len = mbstowcs(command_ps, src, maxsize - 1); | 216 | ssize_t len = mbstowcs(command_ps, src, maxsize - 1); |
209 | if (len < 0) | 217 | if (len < 0) |
210 | len = 0; | 218 | len = 0; |
211 | command_ps[len] = L'\0'; | 219 | command_ps[len] = 0; |
212 | return len; | 220 | return len; |
213 | } | 221 | } |
214 | static size_t save_string(char *dst, int maxsize) | 222 | static unsigned save_string(char *dst, unsigned maxsize) |
215 | { | 223 | { |
224 | # if !ENABLE_UNICODE_PRESERVE_BROKEN | ||
216 | ssize_t len = wcstombs(dst, command_ps, maxsize - 1); | 225 | ssize_t len = wcstombs(dst, command_ps, maxsize - 1); |
217 | if (len < 0) | 226 | if (len < 0) |
218 | len = 0; | 227 | len = 0; |
219 | dst[len] = '\0'; | 228 | dst[len] = '\0'; |
220 | return len; | 229 | return len; |
230 | # else | ||
231 | unsigned dstpos = 0; | ||
232 | unsigned srcpos = 0; | ||
233 | |||
234 | maxsize--; | ||
235 | while (dstpos < maxsize) { | ||
236 | wchar_t wc; | ||
237 | int n = srcpos; | ||
238 | while ((wc = command_ps[srcpos]) != 0 | ||
239 | && !unicode_is_raw_byte(wc) | ||
240 | ) { | ||
241 | srcpos++; | ||
242 | } | ||
243 | command_ps[srcpos] = 0; | ||
244 | n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos); | ||
245 | if (n < 0) /* should not happen */ | ||
246 | break; | ||
247 | dstpos += n; | ||
248 | if (wc == 0) /* usually is */ | ||
249 | break; | ||
250 | /* We do have invalid byte here! */ | ||
251 | command_ps[srcpos] = wc; /* restore it */ | ||
252 | srcpos++; | ||
253 | if (dstpos == maxsize) | ||
254 | break; | ||
255 | dst[dstpos++] = (char) wc; | ||
256 | } | ||
257 | dst[dstpos] = '\0'; | ||
258 | return dstpos; | ||
259 | # endif | ||
221 | } | 260 | } |
222 | /* I thought just fputwc(c, stdout) would work. But no... */ | 261 | /* I thought just fputwc(c, stdout) would work. But no... */ |
223 | static void BB_PUTCHAR(wchar_t c) | 262 | static void BB_PUTCHAR(wchar_t c) |
224 | { | 263 | { |
225 | char buf[MB_CUR_MAX + 1]; | 264 | char buf[MB_CUR_MAX + 1]; |
226 | mbstate_t mbst = { 0 }; | 265 | mbstate_t mbst = { 0 }; |
227 | ssize_t len = wcrtomb(buf, c, &mbst); | 266 | ssize_t len; |
228 | 267 | ||
268 | len = wcrtomb(buf, c, &mbst); | ||
229 | if (len > 0) { | 269 | if (len > 0) { |
230 | buf[len] = '\0'; | 270 | buf[len] = '\0'; |
231 | fputs(buf, stdout); | 271 | fputs(buf, stdout); |
232 | } | 272 | } |
233 | } | 273 | } |
234 | #else | 274 | # if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS |
275 | static wchar_t adjust_width_and_validate_wc(unsigned *width_adj, wchar_t wc) | ||
276 | # else | ||
277 | static wchar_t adjust_width_and_validate_wc(wchar_t wc) | ||
278 | # define adjust_width_and_validate_wc(width_adj, wc) \ | ||
279 | ((*(width_adj))++, adjust_width_and_validate_wc(wc)) | ||
280 | # endif | ||
281 | { | ||
282 | int w = 1; | ||
283 | |||
284 | if (unicode_status == UNICODE_ON) { | ||
285 | if (wc > CONFIG_LAST_SUPPORTED_WCHAR) { | ||
286 | /* note: also true for unicode_is_raw_byte(wc) */ | ||
287 | goto subst; | ||
288 | } | ||
289 | w = wcwidth(wc); | ||
290 | if ((ENABLE_UNICODE_COMBINING_WCHARS && w < 0) | ||
291 | || (!ENABLE_UNICODE_COMBINING_WCHARS && w <= 0) | ||
292 | || (!ENABLE_UNICODE_WIDE_WCHARS && w > 1) | ||
293 | ) { | ||
294 | subst: | ||
295 | w = 1; | ||
296 | wc = CONFIG_SUBST_WCHAR; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | # if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS | ||
301 | *width_adj += w; | ||
302 | #endif | ||
303 | return wc; | ||
304 | } | ||
305 | #else /* !UNICODE */ | ||
235 | static size_t load_string(const char *src, int maxsize) | 306 | static size_t load_string(const char *src, int maxsize) |
236 | { | 307 | { |
237 | safe_strncpy(command_ps, src, maxsize); | 308 | safe_strncpy(command_ps, src, maxsize); |
238 | return strlen(command_ps); | 309 | return strlen(command_ps); |
239 | } | 310 | } |
240 | # if ENABLE_FEATURE_TAB_COMPLETION | 311 | # if ENABLE_FEATURE_TAB_COMPLETION |
241 | static void save_string(char *dst, int maxsize) | 312 | static void save_string(char *dst, unsigned maxsize) |
242 | { | 313 | { |
243 | safe_strncpy(dst, command_ps, maxsize); | 314 | safe_strncpy(dst, command_ps, maxsize); |
244 | } | 315 | } |
245 | # endif | 316 | # endif |
246 | # define BB_PUTCHAR(c) bb_putchar(c) | 317 | # define BB_PUTCHAR(c) bb_putchar(c) |
318 | /* Should never be called: */ | ||
319 | int adjust_width_and_validate_wc(unsigned *width_adj, int wc); | ||
247 | #endif | 320 | #endif |
248 | 321 | ||
249 | 322 | ||
@@ -251,38 +324,35 @@ static void save_string(char *dst, int maxsize) | |||
251 | * Advance cursor on screen. If we reached right margin, scroll text up | 324 | * Advance cursor on screen. If we reached right margin, scroll text up |
252 | * and remove terminal margin effect by printing 'next_char' */ | 325 | * and remove terminal margin effect by printing 'next_char' */ |
253 | #define HACK_FOR_WRONG_WIDTH 1 | 326 | #define HACK_FOR_WRONG_WIDTH 1 |
254 | #if HACK_FOR_WRONG_WIDTH | 327 | static void put_cur_glyph_and_inc_cursor(void) |
255 | static void cmdedit_set_out_char(void) | ||
256 | #define cmdedit_set_out_char(next_char) cmdedit_set_out_char() | ||
257 | #else | ||
258 | static void cmdedit_set_out_char(int next_char) | ||
259 | #endif | ||
260 | { | 328 | { |
261 | CHAR_T c = command_ps[cursor]; | 329 | CHAR_T c = command_ps[cursor]; |
330 | unsigned width = 0; | ||
331 | int ofs_to_right; | ||
262 | 332 | ||
263 | if (c == BB_NUL) { | 333 | if (c == BB_NUL) { |
264 | /* erase character after end of input string */ | 334 | /* erase character after end of input string */ |
265 | c = ' '; | 335 | c = ' '; |
336 | } else { | ||
337 | /* advance cursor only if we aren't at the end yet */ | ||
338 | cursor++; | ||
339 | if (unicode_status == UNICODE_ON) { | ||
340 | IF_UNICODE_WIDE_WCHARS(width = cmdedit_x;) | ||
341 | c = adjust_width_and_validate_wc(&cmdedit_x, c); | ||
342 | IF_UNICODE_WIDE_WCHARS(width = cmdedit_x - width;) | ||
343 | } else { | ||
344 | cmdedit_x++; | ||
345 | } | ||
266 | } | 346 | } |
267 | #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT | 347 | |
268 | /* Display non-printable characters in reverse */ | 348 | ofs_to_right = cmdedit_x - cmdedit_termw; |
269 | if (!BB_isprint(c)) { | 349 | if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right <= 0) { |
270 | if (c >= 128) | 350 | /* c fits on this line */ |
271 | c -= 128; | ||
272 | if (c < ' ') | ||
273 | c += '@'; | ||
274 | if (c == 127) | ||
275 | c = '?'; | ||
276 | printf("\033[7m%c\033[0m", c); | ||
277 | } else | ||
278 | #endif | ||
279 | { | ||
280 | BB_PUTCHAR(c); | 351 | BB_PUTCHAR(c); |
281 | } | 352 | } |
282 | if (++cmdedit_x >= cmdedit_termw) { | 353 | |
283 | /* terminal is scrolled down */ | 354 | if (ofs_to_right >= 0) { |
284 | cmdedit_y++; | 355 | /* we go to the next line */ |
285 | cmdedit_x = 0; | ||
286 | #if HACK_FOR_WRONG_WIDTH | 356 | #if HACK_FOR_WRONG_WIDTH |
287 | /* This works better if our idea of term width is wrong | 357 | /* This works better if our idea of term width is wrong |
288 | * and it is actually wider (often happens on serial lines). | 358 | * and it is actually wider (often happens on serial lines). |
@@ -293,55 +363,83 @@ static void cmdedit_set_out_char(int next_char) | |||
293 | * this will break things: there will be one extra empty line */ | 363 | * this will break things: there will be one extra empty line */ |
294 | puts("\r"); /* + implicit '\n' */ | 364 | puts("\r"); /* + implicit '\n' */ |
295 | #else | 365 | #else |
296 | /* Works ok only if cmdedit_termw is correct */ | 366 | /* VT-10x terminals don't wrap cursor to next line when last char |
297 | /* destroy "(auto)margin" */ | 367 | * on the line is printed - cursor stays "over" this char. |
298 | bb_putchar(next_char); | 368 | * Need to print _next_ char too (first one to appear on next line) |
369 | * to make cursor move down to next line. | ||
370 | */ | ||
371 | /* Works ok only if cmdedit_termw is correct. */ | ||
372 | c = command_ps[cursor]; | ||
373 | if (c == BB_NUL) | ||
374 | c = ' '; | ||
375 | BB_PUTCHAR(c); | ||
299 | bb_putchar('\b'); | 376 | bb_putchar('\b'); |
300 | #endif | 377 | #endif |
378 | cmdedit_y++; | ||
379 | if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) { | ||
380 | width = 0; | ||
381 | } else { /* ofs_to_right > 0 */ | ||
382 | /* wide char c didn't fit on prev line */ | ||
383 | BB_PUTCHAR(c); | ||
384 | } | ||
385 | cmdedit_x = width; | ||
301 | } | 386 | } |
302 | // Huh? What if command_ps[cursor] == BB_NUL (we are at the end already?) | ||
303 | cursor++; | ||
304 | } | 387 | } |
305 | 388 | ||
306 | /* Move to end of line (by printing all chars till the end) */ | 389 | /* Move to end of line (by printing all chars till the end) */ |
307 | static void input_end(void) | 390 | static void put_till_end_and_adv_cursor(void) |
308 | { | 391 | { |
309 | while (cursor < command_len) | 392 | while (cursor < command_len) |
310 | cmdedit_set_out_char(' '); | 393 | put_cur_glyph_and_inc_cursor(); |
311 | } | 394 | } |
312 | 395 | ||
313 | /* Go to the next line */ | 396 | /* Go to the next line */ |
314 | static void goto_new_line(void) | 397 | static void goto_new_line(void) |
315 | { | 398 | { |
316 | input_end(); | 399 | put_till_end_and_adv_cursor(); |
317 | if (cmdedit_x) | 400 | if (cmdedit_x != 0) |
318 | bb_putchar('\n'); | 401 | bb_putchar('\n'); |
319 | } | 402 | } |
320 | 403 | ||
321 | 404 | static void beep(void) | |
322 | static void out1str(const char *s) | ||
323 | { | 405 | { |
324 | if (s) | 406 | bb_putchar('\007'); |
325 | fputs(s, stdout); | ||
326 | } | 407 | } |
327 | 408 | ||
328 | static void beep(void) | 409 | static void put_prompt(void) |
329 | { | 410 | { |
330 | bb_putchar('\007'); | 411 | unsigned w; |
412 | |||
413 | fputs(cmdedit_prompt, stdout); | ||
414 | fflush_all(); | ||
415 | cursor = 0; | ||
416 | w = cmdedit_termw; /* read volatile var once */ | ||
417 | cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */ | ||
418 | cmdedit_x = cmdedit_prmt_len % w; | ||
331 | } | 419 | } |
332 | 420 | ||
333 | /* Move back one character */ | 421 | /* Move back one character */ |
334 | /* (optimized for slow terminals) */ | 422 | /* (optimized for slow terminals) */ |
335 | static void input_backward(unsigned num) | 423 | static void input_backward(unsigned num) |
336 | { | 424 | { |
337 | int count_y; | ||
338 | |||
339 | if (num > cursor) | 425 | if (num > cursor) |
340 | num = cursor; | 426 | num = cursor; |
341 | if (!num) | 427 | if (num == 0) |
342 | return; | 428 | return; |
343 | cursor -= num; | 429 | cursor -= num; |
344 | 430 | ||
431 | if ((ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS) | ||
432 | && unicode_status == UNICODE_ON | ||
433 | ) { | ||
434 | /* correct NUM to be equal to _screen_ width */ | ||
435 | int n = num; | ||
436 | num = 0; | ||
437 | while (--n >= 0) | ||
438 | adjust_width_and_validate_wc(&num, command_ps[cursor + n]); | ||
439 | if (num == 0) | ||
440 | return; | ||
441 | } | ||
442 | |||
345 | if (cmdedit_x >= num) { | 443 | if (cmdedit_x >= num) { |
346 | cmdedit_x -= num; | 444 | cmdedit_x -= num; |
347 | if (num <= 4) { | 445 | if (num <= 4) { |
@@ -361,38 +459,61 @@ static void input_backward(unsigned num) | |||
361 | } | 459 | } |
362 | 460 | ||
363 | /* Need to go one or more lines up */ | 461 | /* Need to go one or more lines up */ |
364 | num -= cmdedit_x; | 462 | if (ENABLE_UNICODE_WIDE_WCHARS) { |
365 | { | 463 | /* With wide chars, it is hard to "backtrack" |
366 | unsigned w = cmdedit_termw; /* volatile var */ | 464 | * and reliably figure out where to put cursor. |
367 | count_y = 1 + (num / w); | 465 | * Example (<> is a wide char; # is an ordinary char, _ cursor): |
368 | cmdedit_y -= count_y; | 466 | * |prompt: <><> | |
369 | cmdedit_x = w * count_y - num; | 467 | * |<><><><><><> | |
468 | * |_ | | ||
469 | * and user presses left arrow. num = 1, cmdedit_x = 0, | ||
470 | * We need to go up one line, and then - how do we know that | ||
471 | * we need to go *10* positions to the right? Because | ||
472 | * |prompt: <>#<>| | ||
473 | * |<><><>#<><><>| | ||
474 | * |_ | | ||
475 | * in this situation we need to go *11* positions to the right. | ||
476 | * | ||
477 | * A simpler thing to do is to redraw everything from the start | ||
478 | * up to new cursor position (which is already known): | ||
479 | */ | ||
480 | unsigned sv_cursor; | ||
481 | /* go to 1st column; go up to first line */ | ||
482 | printf("\r" "\033[%uA", cmdedit_y); | ||
483 | cmdedit_y = 0; | ||
484 | sv_cursor = cursor; | ||
485 | put_prompt(); /* sets cursor to 0 */ | ||
486 | while (cursor < sv_cursor) | ||
487 | put_cur_glyph_and_inc_cursor(); | ||
488 | } else { | ||
489 | int lines_up; | ||
490 | unsigned width; | ||
491 | /* num = chars to go back from the beginning of current line: */ | ||
492 | num -= cmdedit_x; | ||
493 | width = cmdedit_termw; /* read volatile var once */ | ||
494 | /* num=1...w: one line up, w+1...2w: two, etc: */ | ||
495 | lines_up = 1 + (num - 1) / width; | ||
496 | cmdedit_x = (width * cmdedit_y - num) % width; | ||
497 | cmdedit_y -= lines_up; | ||
498 | /* go to 1st column; go up */ | ||
499 | printf("\r" "\033[%uA", lines_up); | ||
500 | /* go to correct column. | ||
501 | * xterm, konsole, Linux VT interpret 0 as 1 below! wow. | ||
502 | * need to *make sure* we skip it if cmdedit_x == 0 */ | ||
503 | if (cmdedit_x) | ||
504 | printf("\033[%uC", cmdedit_x); | ||
370 | } | 505 | } |
371 | /* go to 1st column; go up; go to correct column */ | ||
372 | printf("\r" "\033[%dA" "\033[%dC", count_y, cmdedit_x); | ||
373 | } | ||
374 | |||
375 | static void put_prompt(void) | ||
376 | { | ||
377 | unsigned w; | ||
378 | |||
379 | out1str(cmdedit_prompt); | ||
380 | fflush_all(); | ||
381 | cursor = 0; | ||
382 | w = cmdedit_termw; /* read volatile var once */ | ||
383 | cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */ | ||
384 | cmdedit_x = cmdedit_prmt_len % w; | ||
385 | } | 506 | } |
386 | 507 | ||
387 | /* draw prompt, editor line, and clear tail */ | 508 | /* draw prompt, editor line, and clear tail */ |
388 | static void redraw(int y, int back_cursor) | 509 | static void redraw(int y, int back_cursor) |
389 | { | 510 | { |
390 | if (y > 0) /* up to start y */ | 511 | if (y > 0) /* up y lines */ |
391 | printf("\033[%uA", y); | 512 | printf("\033[%uA", y); |
392 | bb_putchar('\r'); | 513 | bb_putchar('\r'); |
393 | put_prompt(); | 514 | put_prompt(); |
394 | input_end(); /* rewrite */ | 515 | put_till_end_and_adv_cursor(); |
395 | printf("\033[J"); /* erase after cursor */ | 516 | printf(SEQ_CLEAR_TILL_END_OF_SCREEN); |
396 | input_backward(back_cursor); | 517 | input_backward(back_cursor); |
397 | } | 518 | } |
398 | 519 | ||
@@ -426,8 +547,9 @@ static void input_delete(int save) | |||
426 | * simplified into (command_len - j) */ | 547 | * simplified into (command_len - j) */ |
427 | (command_len - j) * sizeof(command_ps[0])); | 548 | (command_len - j) * sizeof(command_ps[0])); |
428 | command_len--; | 549 | command_len--; |
429 | input_end(); /* rewrite new line */ | 550 | put_till_end_and_adv_cursor(); |
430 | cmdedit_set_out_char(' '); /* erase char */ | 551 | /* Last char is still visible, erase it (and more) */ |
552 | printf(SEQ_CLEAR_TILL_END_OF_SCREEN); | ||
431 | input_backward(cursor - j); /* back to old pos cursor */ | 553 | input_backward(cursor - j); /* back to old pos cursor */ |
432 | } | 554 | } |
433 | 555 | ||
@@ -445,7 +567,7 @@ static void put(void) | |||
445 | (command_len - cursor + 1) * sizeof(command_ps[0])); | 567 | (command_len - cursor + 1) * sizeof(command_ps[0])); |
446 | memcpy(command_ps + cursor, delbuf, j * sizeof(command_ps[0])); | 568 | memcpy(command_ps + cursor, delbuf, j * sizeof(command_ps[0])); |
447 | command_len += j; | 569 | command_len += j; |
448 | input_end(); /* rewrite new line */ | 570 | put_till_end_and_adv_cursor(); |
449 | input_backward(cursor - ocursor - j + 1); /* at end of new text */ | 571 | input_backward(cursor - ocursor - j + 1); /* at end of new text */ |
450 | } | 572 | } |
451 | #endif | 573 | #endif |
@@ -463,7 +585,7 @@ static void input_backspace(void) | |||
463 | static void input_forward(void) | 585 | static void input_forward(void) |
464 | { | 586 | { |
465 | if (cursor < command_len) | 587 | if (cursor < command_len) |
466 | cmdedit_set_out_char(command_ps[cursor + 1]); | 588 | put_cur_glyph_and_inc_cursor(); |
467 | } | 589 | } |
468 | 590 | ||
469 | #if ENABLE_FEATURE_TAB_COMPLETION | 591 | #if ENABLE_FEATURE_TAB_COMPLETION |
@@ -721,21 +843,13 @@ static NOINLINE int find_match(char *matchBuf, int *len_with_quotes) | |||
721 | } | 843 | } |
722 | 844 | ||
723 | /* mask \+symbol and convert '\t' to ' ' */ | 845 | /* mask \+symbol and convert '\t' to ' ' */ |
724 | for (i = j = 0; matchBuf[i]; i++, j++) | 846 | for (i = j = 0; matchBuf[i]; i++, j++) { |
725 | if (matchBuf[i] == '\\') { | 847 | if (matchBuf[i] == '\\') { |
726 | collapse_pos(j, j + 1); | 848 | collapse_pos(j, j + 1); |
727 | int_buf[j] |= QUOT; | 849 | int_buf[j] |= QUOT; |
728 | i++; | 850 | i++; |
729 | #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT | ||
730 | if (matchBuf[i] == '\t') /* algorithm equivalent */ | ||
731 | int_buf[j] = ' ' | QUOT; | ||
732 | #endif | ||
733 | } | 851 | } |
734 | #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT | 852 | } |
735 | else if (matchBuf[i] == '\t') | ||
736 | int_buf[j] = ' '; | ||
737 | #endif | ||
738 | |||
739 | /* mask "symbols" or 'symbols' */ | 853 | /* mask "symbols" or 'symbols' */ |
740 | c2 = 0; | 854 | c2 = 0; |
741 | for (i = 0; int_buf[i]; i++) { | 855 | for (i = 0; int_buf[i]; i++) { |
@@ -1509,7 +1623,7 @@ static void ask_terminal(void) | |||
1509 | pfd.events = POLLIN; | 1623 | pfd.events = POLLIN; |
1510 | if (safe_poll(&pfd, 1, 0) == 0) { | 1624 | if (safe_poll(&pfd, 1, 0) == 0) { |
1511 | S.sent_ESC_br6n = 1; | 1625 | S.sent_ESC_br6n = 1; |
1512 | out1str("\033" "[6n"); | 1626 | fputs("\033" "[6n", stdout); |
1513 | fflush_all(); /* make terminal see it ASAP! */ | 1627 | fflush_all(); /* make terminal see it ASAP! */ |
1514 | } | 1628 | } |
1515 | } | 1629 | } |
@@ -1727,13 +1841,11 @@ static int lineedit_read_key(char *read_key_buffer) | |||
1727 | pushback: | 1841 | pushback: |
1728 | /* Invalid sequence. Save all "bad bytes" except first */ | 1842 | /* Invalid sequence. Save all "bad bytes" except first */ |
1729 | read_key_ungets(read_key_buffer, unicode_buf + 1, unicode_idx - 1); | 1843 | read_key_ungets(read_key_buffer, unicode_buf + 1, unicode_idx - 1); |
1730 | /* | 1844 | # if !ENABLE_UNICODE_PRESERVE_BROKEN |
1731 | * ic = unicode_buf[0] sounds even better, but currently | ||
1732 | * this does not work: wchar_t[] -> char[] conversion | ||
1733 | * when lineedit finishes mangles such "raw bytes" | ||
1734 | * (by misinterpreting them as unicode chars): | ||
1735 | */ | ||
1736 | ic = CONFIG_SUBST_WCHAR; | 1845 | ic = CONFIG_SUBST_WCHAR; |
1846 | # else | ||
1847 | ic = unicode_mark_raw_byte(unicode_buf[0]); | ||
1848 | # endif | ||
1737 | } else { | 1849 | } else { |
1738 | /* Valid unicode char, return its code */ | 1850 | /* Valid unicode char, return its code */ |
1739 | ic = wc; | 1851 | ic = wc; |
@@ -1925,7 +2037,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1925 | case CTRL('E'): | 2037 | case CTRL('E'): |
1926 | vi_case('$'|VI_CMDMODE_BIT:) | 2038 | vi_case('$'|VI_CMDMODE_BIT:) |
1927 | /* Control-e -- End of line */ | 2039 | /* Control-e -- End of line */ |
1928 | input_end(); | 2040 | put_till_end_and_adv_cursor(); |
1929 | break; | 2041 | break; |
1930 | case CTRL('F'): | 2042 | case CTRL('F'): |
1931 | vi_case('l'|VI_CMDMODE_BIT:) | 2043 | vi_case('l'|VI_CMDMODE_BIT:) |
@@ -1954,12 +2066,12 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1954 | /* Control-k -- clear to end of line */ | 2066 | /* Control-k -- clear to end of line */ |
1955 | command_ps[cursor] = BB_NUL; | 2067 | command_ps[cursor] = BB_NUL; |
1956 | command_len = cursor; | 2068 | command_len = cursor; |
1957 | printf("\033[J"); | 2069 | printf(SEQ_CLEAR_TILL_END_OF_SCREEN); |
1958 | break; | 2070 | break; |
1959 | case CTRL('L'): | 2071 | case CTRL('L'): |
1960 | vi_case(CTRL('L')|VI_CMDMODE_BIT:) | 2072 | vi_case(CTRL('L')|VI_CMDMODE_BIT:) |
1961 | /* Control-l -- clear screen */ | 2073 | /* Control-l -- clear screen */ |
1962 | printf("\033[H"); | 2074 | printf("\033[H"); /* cursor to top,left */ |
1963 | redraw(0, command_len - cursor); | 2075 | redraw(0, command_len - cursor); |
1964 | break; | 2076 | break; |
1965 | #if MAX_HISTORY > 0 | 2077 | #if MAX_HISTORY > 0 |
@@ -2010,7 +2122,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2010 | vi_cmdmode = 0; | 2122 | vi_cmdmode = 0; |
2011 | break; | 2123 | break; |
2012 | case 'A'|VI_CMDMODE_BIT: | 2124 | case 'A'|VI_CMDMODE_BIT: |
2013 | input_end(); | 2125 | put_till_end_and_adv_cursor(); |
2014 | vi_cmdmode = 0; | 2126 | vi_cmdmode = 0; |
2015 | break; | 2127 | break; |
2016 | case 'x'|VI_CMDMODE_BIT: | 2128 | case 'x'|VI_CMDMODE_BIT: |
@@ -2170,7 +2282,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2170 | input_backward(cursor); | 2282 | input_backward(cursor); |
2171 | break; | 2283 | break; |
2172 | case KEYCODE_END: | 2284 | case KEYCODE_END: |
2173 | input_end(); | 2285 | put_till_end_and_adv_cursor(); |
2174 | break; | 2286 | break; |
2175 | 2287 | ||
2176 | default: | 2288 | default: |
@@ -2230,7 +2342,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2230 | /* We are at the end, append */ | 2342 | /* We are at the end, append */ |
2231 | command_ps[cursor] = ic; | 2343 | command_ps[cursor] = ic; |
2232 | command_ps[cursor + 1] = BB_NUL; | 2344 | command_ps[cursor + 1] = BB_NUL; |
2233 | cmdedit_set_out_char(' '); | 2345 | put_cur_glyph_and_inc_cursor(); |
2234 | if (unicode_bidi_isrtl(ic)) | 2346 | if (unicode_bidi_isrtl(ic)) |
2235 | input_backward(1); | 2347 | input_backward(1); |
2236 | } else { | 2348 | } else { |
@@ -2243,8 +2355,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2243 | /* is right-to-left char, or neutral one (e.g. comma) was just added to rtl text? */ | 2355 | /* is right-to-left char, or neutral one (e.g. comma) was just added to rtl text? */ |
2244 | if (!isrtl_str()) | 2356 | if (!isrtl_str()) |
2245 | sc++; /* no */ | 2357 | sc++; /* no */ |
2246 | /* rewrite from cursor */ | 2358 | put_till_end_and_adv_cursor(); |
2247 | input_end(); | ||
2248 | /* to prev x pos + 1 */ | 2359 | /* to prev x pos + 1 */ |
2249 | input_backward(cursor - sc); | 2360 | input_backward(cursor - sc); |
2250 | } | 2361 | } |
@@ -2345,9 +2456,6 @@ int main(int argc, char **argv) | |||
2345 | "% "; | 2456 | "% "; |
2346 | #endif | 2457 | #endif |
2347 | 2458 | ||
2348 | #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT | ||
2349 | setlocale(LC_ALL, ""); | ||
2350 | #endif | ||
2351 | while (1) { | 2459 | while (1) { |
2352 | int l; | 2460 | int l; |
2353 | l = read_line_input(prompt, buff); | 2461 | l = read_line_input(prompt, buff); |