/* Do TAB completion */ static void input_tab(int *lastWasTab) { if (!(state->flags & TAB_COMPLETION)) return; if (!*lastWasTab) { char *tmp, *tmp1; int len_found; char matchBuf[MAX_LINELEN]; int find_type; int recalc_pos; *lastWasTab = TRUE; /* flop trigger */ /* Make a local copy of the string -- up * to the position of the cursor */ tmp = strncpy(matchBuf, command_ps, cursor); tmp[cursor] = '\0'; find_type = find_match(matchBuf, &recalc_pos); /* Free up any memory already allocated */ free_tab_completion_data(); #if ENABLE_FEATURE_USERNAME_COMPLETION /* If the word starts with `~' and there is no slash in the word, * then try completing this word as a username. */ if (state->flags & USERNAME_COMPLETION) if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0) username_tab_completion(matchBuf, NULL); #endif /* Try to match any executable in our path and everything * in the current working directory */ if (!matches) exe_n_cwd_tab_completion(matchBuf, find_type); /* Sort, then remove any duplicates found */ if (matches) { int i, n = 0; qsort(matches, num_matches, sizeof(char*), match_compare); for (i = 0; i < num_matches - 1; ++i) { if (matches[i] && matches[i+1]) { /* paranoia */ if (strcmp(matches[i], matches[i+1]) == 0) { free(matches[i]); matches[i] = NULL; /* paranoia */ } else { matches[n++] = matches[i]; } } } matches[n] = matches[i]; num_matches = n + 1; } /* Did we find exactly one match? */ if (!matches || num_matches > 1) { beep(); if (!matches) return; /* not found */ /* find minimal match */ // ash: yet another failure in trying to achieve "we don't die on OOM" tmp1 = xstrdup(matches[0]); for (tmp = tmp1; *tmp; tmp++) for (len_found = 1; len_found < num_matches; len_found++) if (matches[len_found][(tmp - tmp1)] != *tmp) { *tmp = '\0'; break; } if (*tmp1 == '\0') { /* have unique */ free(tmp1); return; } tmp = add_quote_for_spec_chars(tmp1); free(tmp1); } else { /* one match */ tmp = add_quote_for_spec_chars(matches[0]); /* for next completion current found */ *lastWasTab = FALSE; len_found = strlen(tmp); if (tmp[len_found-1] != '/') { tmp[len_found] = ' '; tmp[len_found+1] = '\0'; } } len_found = strlen(tmp); /* have space to placed match? */ if ((len_found - strlen(matchBuf) + command_len) < MAX_LINELEN) { /* before word for match */ command_ps[cursor - recalc_pos] = 0; /* save tail line */ strcpy(matchBuf, command_ps + cursor); /* add match */ strcat(command_ps, tmp); /* add tail */ strcat(command_ps, matchBuf); /* back to begin word for match */ input_backward(recalc_pos); /* new pos */ recalc_pos = cursor + len_found; /* new len */ command_len = strlen(command_ps); /* write out the matched command */ redraw(cmdedit_y, command_len - recalc_pos); } free(tmp); } else { /* Ok -- the last char was a TAB. Since they * just hit TAB again, print a list of all the * available choices... */ if (matches && num_matches > 0) { int sav_cursor = cursor; /* change goto_new_line() */ /* Go to the next line */ goto_new_line(); showfiles(); redraw(0, command_len - sav_cursor); } } }
static void input_tab(int *lastWasTab) { /* Do TAB completion */ if (lastWasTab == 0) { /* free all memory */ if (matches) { while (num_matches > 0) free(matches[--num_matches]); free(matches); matches = (char **) NULL; free(add_char_to_match); add_char_to_match = NULL; } return; } if (! *lastWasTab) { char *tmp, *tmp1; int len_found; char matchBuf[BUFSIZ]; int find_type; int recalc_pos; *lastWasTab = TRUE; /* flop trigger */ /* Make a local copy of the string -- up * to the position of the cursor */ tmp = strncpy(matchBuf, command_ps, cursor); tmp[cursor] = 0; find_type = find_match(matchBuf, &recalc_pos); /* Free up any memory already allocated */ input_tab(0); #ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION /* If the word starts with `~' and there is no slash in the word, * then try completing this word as a username. */ if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0) username_tab_completion(matchBuf, NULL); if (!matches) #endif /* Try to match any executable in our path and everything * in the current working directory that matches. */ exe_n_cwd_tab_completion(matchBuf, find_type); /* Remove duplicate found and sort */ if(matches) { int i, j, n, srt; /* bubble */ n = num_matches; for(i=0; i<(n-1); i++) for(j=i+1; j<n; j++) if(matches[i]!=NULL && matches[j]!=NULL) { srt = strcmp(matches[i], matches[j]); if(srt == 0) { free(matches[j]); matches[j]=0; } else if(srt > 0) { tmp1 = matches[i]; matches[i] = matches[j]; matches[j] = tmp1; srt = add_char_to_match[i]; add_char_to_match[i] = add_char_to_match[j]; add_char_to_match[j] = srt; } } j = n; n = 0; for(i=0; i<j; i++) if(matches[i]) { matches[n]=matches[i]; add_char_to_match[n]=add_char_to_match[i]; n++; } num_matches = n; } /* Did we find exactly one match? */ if (!matches || num_matches > 1) { beep(); if (!matches) return; /* not found */ /* find minimal match */ tmp1 = bb_xstrdup(matches[0]); for (tmp = tmp1; *tmp; tmp++) for (len_found = 1; len_found < num_matches; len_found++) if (matches[len_found][(tmp - tmp1)] != *tmp) { *tmp = 0; break; } if (*tmp1 == 0) { /* have unique */ free(tmp1); return; } tmp = add_quote_for_spec_chars(tmp1, 0); free(tmp1); } else { /* one match */ tmp = add_quote_for_spec_chars(matches[0], add_char_to_match[0]); /* for next completion current found */ *lastWasTab = FALSE; } len_found = strlen(tmp); /* have space to placed match? */ if ((len_found - strlen(matchBuf) + len) < BUFSIZ) { /* before word for match */ command_ps[cursor - recalc_pos] = 0; /* save tail line */ strcpy(matchBuf, command_ps + cursor); /* add match */ strcat(command_ps, tmp); /* add tail */ strcat(command_ps, matchBuf); /* back to begin word for match */ input_backward(recalc_pos); /* new pos */ recalc_pos = cursor + len_found; /* new len */ len = strlen(command_ps); /* write out the matched command */ redraw(cmdedit_y, len - recalc_pos); } free(tmp); } else { /* Ok -- the last char was a TAB. Since they * just hit TAB again, print a list of all the * available choices... */ if (matches && num_matches > 0) { int sav_cursor = cursor; /* change goto_new_line() */ /* Go to the next line */ goto_new_line(); showfiles(); redraw(0, len - sav_cursor); } } }