aboutsummaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-07-12 02:50:35 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-07-12 02:50:35 +0200
commit044b18083b4380f158002ed7c00c52d362c9632c (patch)
treea2bd5c55c1be886890e82e9916b32990ff718b18 /libbb/lineedit.c
parent1302892a14e8660b1f577f2cde710103c366d413 (diff)
downloadbusybox-w32-044b18083b4380f158002ed7c00c52d362c9632c.tar.gz
busybox-w32-044b18083b4380f158002ed7c00c52d362c9632c.tar.bz2
busybox-w32-044b18083b4380f158002ed7c00c52d362c9632c.zip
lineedit+unicode: make TAB completion work again
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c85
1 files changed, 57 insertions, 28 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 6e836d83e..8b7ff4f8e 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -115,6 +115,9 @@ struct lineedit_statics {
115 115
116 unsigned cursor; 116 unsigned cursor;
117 unsigned command_len; 117 unsigned command_len;
118 /* *int* maxsize: we want x in "if (x > S.maxsize)"
119 * to _not_ be promoted to unsigned */
120 int maxsize;
118 CHAR_T *command_ps; 121 CHAR_T *command_ps;
119 122
120 const char *cmdedit_prompt; 123 const char *cmdedit_prompt;
@@ -389,12 +392,12 @@ static void put_prompt(void)
389/* draw prompt, editor line, and clear tail */ 392/* draw prompt, editor line, and clear tail */
390static void redraw(int y, int back_cursor) 393static void redraw(int y, int back_cursor)
391{ 394{
392 if (y > 0) /* up to start y */ 395 if (y > 0) /* up to start y */
393 printf("\033[%dA", y); 396 printf("\033[%uA", y);
394 bb_putchar('\r'); 397 bb_putchar('\r');
395 put_prompt(); 398 put_prompt();
396 input_end(); /* rewrite */ 399 input_end(); /* rewrite */
397 printf("\033[J"); /* erase after cursor */ 400 printf("\033[J"); /* erase after cursor */
398 input_backward(back_cursor); 401 input_backward(back_cursor);
399} 402}
400 403
@@ -687,7 +690,7 @@ static void exe_n_cwd_tab_completion(char *command, int type)
687 memmove(pos_buf+(is), pos_buf+(in), (MAX_LINELEN+1-(is)-(in)) * sizeof(pos_buf[0])); \ 690 memmove(pos_buf+(is), pos_buf+(in), (MAX_LINELEN+1-(is)-(in)) * sizeof(pos_buf[0])); \
688} while (0) 691} while (0)
689 692
690static int find_match(char *matchBuf, int *len_with_quotes) 693static NOINLINE int find_match(char *matchBuf, int *len_with_quotes)
691{ 694{
692 int i, j; 695 int i, j;
693 int command_mode; 696 int command_mode;
@@ -922,12 +925,19 @@ static void input_tab(smallint *lastWasTab)
922#define matchBuf (S.input_tab__matchBuf) 925#define matchBuf (S.input_tab__matchBuf)
923 int find_type; 926 int find_type;
924 int recalc_pos; 927 int recalc_pos;
928#if ENABLE_FEATURE_ASSUME_UNICODE
929 /* cursor pos in command converted to multibyte form */
930 int cursor_mb;
931#endif
925 932
926 *lastWasTab = TRUE; /* flop trigger */ 933 *lastWasTab = TRUE; /* flop trigger */
927 934
928 /* Make a local copy of the string -- 935 /* Make a local copy of the string --
929 * up to the position of the cursor */ 936 * up to the position of the cursor */
930 save_string(matchBuf, cursor + 1); 937 save_string(matchBuf, cursor + 1);
938#if ENABLE_FEATURE_ASSUME_UNICODE
939 cursor_mb = strlen(matchBuf);
940#endif
931 tmp = matchBuf; 941 tmp = matchBuf;
932 942
933 find_type = find_match(matchBuf, &recalc_pos); 943 find_type = find_match(matchBuf, &recalc_pos);
@@ -939,7 +949,7 @@ static void input_tab(smallint *lastWasTab)
939 /* If the word starts with `~' and there is no slash in the word, 949 /* If the word starts with `~' and there is no slash in the word,
940 * then try completing this word as a username. */ 950 * then try completing this word as a username. */
941 if (state->flags & USERNAME_COMPLETION) 951 if (state->flags & USERNAME_COMPLETION)
942 if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0) 952 if (matchBuf[0] == '~' && strchr(matchBuf, '/') == NULL)
943 username_tab_completion(matchBuf, NULL); 953 username_tab_completion(matchBuf, NULL);
944#endif 954#endif
945 /* Try to match any executable in our path and everything 955 /* Try to match any executable in our path and everything
@@ -965,18 +975,20 @@ static void input_tab(smallint *lastWasTab)
965 num_matches = n + 1; 975 num_matches = n + 1;
966 } 976 }
967 /* Did we find exactly one match? */ 977 /* Did we find exactly one match? */
968 if (!matches || num_matches > 1) { 978 if (!matches || num_matches > 1) { /* no */
969 beep(); 979 beep();
970 if (!matches) 980 if (!matches)
971 return; /* not found */ 981 return; /* not found */
972 /* find minimal match */ 982 /* find minimal match */
973 tmp1 = xstrdup(matches[0]); 983 tmp1 = xstrdup(matches[0]);
974 for (tmp = tmp1; *tmp; tmp++) 984 for (tmp = tmp1; *tmp; tmp++) {
975 for (len_found = 1; len_found < num_matches; len_found++) 985 for (len_found = 1; len_found < num_matches; len_found++) {
976 if (matches[len_found][(tmp - tmp1)] != *tmp) { 986 if (matches[len_found][tmp - tmp1] != *tmp) {
977 *tmp = '\0'; 987 *tmp = '\0';
978 break; 988 break;
979 } 989 }
990 }
991 }
980 if (*tmp1 == '\0') { /* have unique */ 992 if (*tmp1 == '\0') { /* have unique */
981 free(tmp1); 993 free(tmp1);
982 return; 994 return;
@@ -994,29 +1006,44 @@ static void input_tab(smallint *lastWasTab)
994 tmp[len_found+1] = '\0'; 1006 tmp[len_found+1] = '\0';
995 } 1007 }
996 } 1008 }
1009
997 len_found = strlen(tmp); 1010 len_found = strlen(tmp);
998 /* have space to placed match? */
999 if ((len_found - strlen(matchBuf) + command_len) < MAX_LINELEN) {
1000 /* before word for match */
1001//TODO:
1002#if !ENABLE_FEATURE_ASSUME_UNICODE 1011#if !ENABLE_FEATURE_ASSUME_UNICODE
1003 command_ps[cursor - recalc_pos] = '\0'; 1012 /* have space to place the match? */
1004 /* save tail line */ 1013 /* The result consists of three parts with these lengths: */
1014 /* (cursor - recalc_pos) + len_found + (command_len - cursor) */
1015 /* it simplifies into: */
1016 if ((int)(len_found + command_len - recalc_pos) < S.maxsize) {
1017 /* save tail */
1005 strcpy(matchBuf, command_ps + cursor); 1018 strcpy(matchBuf, command_ps + cursor);
1006 /* add match */ 1019 /* add match and tail */
1007 strcat(command_ps, tmp); 1020 sprintf(&command_ps[cursor - recalc_pos], "%s%s", tmp, matchBuf);
1008 /* add tail */
1009 strcat(command_ps, matchBuf);
1010 /* back to begin word for match */
1011 input_backward(recalc_pos);
1012 /* new pos */
1013 recalc_pos = cursor + len_found;
1014 /* new len */
1015 command_len = strlen(command_ps); 1021 command_len = strlen(command_ps);
1016 /* write out the matched command */ 1022 /* new pos */
1017#endif 1023 recalc_pos = cursor - recalc_pos + len_found;
1024 /* write out the matched command */
1018 redraw(cmdedit_y, command_len - recalc_pos); 1025 redraw(cmdedit_y, command_len - recalc_pos);
1019 } 1026 }
1027#else
1028 {
1029 char command[MAX_LINELEN];
1030 int len = save_string(command, sizeof(command));
1031 /* have space to place the match? */
1032 /* (cursor_mb - recalc_pos) + len_found + (len - cursor_mb) */
1033 if ((int)(len_found + len - recalc_pos) < MAX_LINELEN) {
1034 /* save tail */
1035 strcpy(matchBuf, command + cursor_mb);
1036 /* where do we want to have cursor after all? */
1037 strcpy(&command[cursor_mb - recalc_pos], tmp);
1038 len = load_string(command, S.maxsize);
1039 /* add match and tail */
1040 sprintf(&command[cursor_mb - recalc_pos], "%s%s", tmp, matchBuf);
1041 command_len = load_string(command, S.maxsize);
1042 /* write out the matched command */
1043 redraw(cmdedit_y, command_len - len);
1044 }
1045 }
1046#endif
1020 free(tmp); 1047 free(tmp);
1021#undef matchBuf 1048#undef matchBuf
1022 } else { 1049 } else {
@@ -1024,7 +1051,8 @@ static void input_tab(smallint *lastWasTab)
1024 * just hit TAB again, print a list of all the 1051 * just hit TAB again, print a list of all the
1025 * available choices... */ 1052 * available choices... */
1026 if (matches && num_matches > 0) { 1053 if (matches && num_matches > 0) {
1027 int sav_cursor = cursor; /* change goto_new_line() */ 1054 /* changed by goto_new_line() */
1055 int sav_cursor = cursor;
1028 1056
1029 /* Go to the next line */ 1057 /* Go to the next line */
1030 goto_new_line(); 1058 goto_new_line();
@@ -1641,6 +1669,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1641// FIXME: audit & improve this 1669// FIXME: audit & improve this
1642 if (maxsize > MAX_LINELEN) 1670 if (maxsize > MAX_LINELEN)
1643 maxsize = MAX_LINELEN; 1671 maxsize = MAX_LINELEN;
1672 S.maxsize = maxsize;
1644 1673
1645 /* With null flags, no other fields are ever used */ 1674 /* With null flags, no other fields are ever used */
1646 state = st ? st : (line_input_t*) &const_int_0; 1675 state = st ? st : (line_input_t*) &const_int_0;