+ /* skip commands with arguments if line have commands delimiters */
+ /* ';' ';;' '&' '|' '&&' '||' but `>&' `<&' `>|' */
+ for (i = 0; int_buf[i]; i++) {
+ c = int_buf[i];
+ c2 = int_buf[i + 1];
+ j = i ? int_buf[i - 1] : -1;
+ command_mode = 0;
+ if (c == ';' || c == '&' || c == '|') {
+ command_mode = 1 + (c == c2);
+ if (c == '&') {
+ if (j == '>' || j == '<')
+ command_mode = 0;
+ } else if (c == '|' && j == '>')
+ command_mode = 0;
+ }
+ if (command_mode) {
+ collapse_pos(0, i + command_mode);
+ i = -1; /* hack incremet */
+ }
+ }
+ /* collapse `command...` */
+ for (i = 0; int_buf[i]; i++)
+ if (int_buf[i] == '`') {
+ for (j = i + 1; int_buf[j]; j++)
+ if (int_buf[j] == '`') {
+ collapse_pos(i, j + 1);
+ j = 0;
+ break;
+ }
+ if (j) {
+ /* not found close ` - command mode, collapse all previous */
+ collapse_pos(0, i + 1);
+ break;
+ } else
+ i--; /* hack incremet */
+ }
+
+ /* collapse (command...(command...)...) or {command...{command...}...} */
+ c = 0; /* "recursive" level */
+ c2 = 0;
+ for (i = 0; int_buf[i]; i++)
+ if (int_buf[i] == '(' || int_buf[i] == '{') {
+ if (int_buf[i] == '(')
+ c++;
+ else
+ c2++;
+ collapse_pos(0, i + 1);
+ i = -1; /* hack incremet */
+ }
+ for (i = 0; pos_buf[i] >= 0 && (c > 0 || c2 > 0); i++)
+ if ((int_buf[i] == ')' && c > 0) || (int_buf[i] == '}' && c2 > 0)) {
+ if (int_buf[i] == ')')
+ c--;
+ else
+ c2--;
+ collapse_pos(0, i + 1);
+ i = -1; /* hack incremet */
+ }
+
+ /* skip first not quote space */
+ for (i = 0; int_buf[i]; i++)
+ if (int_buf[i] != ' ')
+ break;
+ if (i)
+ collapse_pos(0, i);
+
+ /* set find mode for completion */
+ command_mode = FIND_EXE_ONLY;
+ for (i = 0; int_buf[i]; i++)
+ if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') {
+ if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY
+ && matchBuf[pos_buf[0]]=='c'
+ && matchBuf[pos_buf[1]]=='d' )
+ command_mode = FIND_DIR_ONLY;
+ else {
+ command_mode = FIND_FILE_ONLY;
+ break;
+ }
+ }
+ /* "strlen" */
+ for (i = 0; int_buf[i]; i++);
+ /* find last word */
+ for (--i; i >= 0; i--) {
+ c = int_buf[i];
+ if (c == ' ' || c == '<' || c == '>' || c == '|' || c == '&') {
+ collapse_pos(0, i + 1);
+ break;
+ }
+ }
+ /* skip first not quoted '\'' or '"' */
+ for (i = 0; int_buf[i] == '\'' || int_buf[i] == '"'; i++);
+ /* collapse quote or unquote // or /~ */
+ while ((int_buf[i] & ~QUOT) == '/' &&
+ ((int_buf[i + 1] & ~QUOT) == '/'
+ || (int_buf[i + 1] & ~QUOT) == '~')) {
+ i++;
+ }
+
+ /* set only match and destroy quotes */
+ j = 0;
+ for (c = 0; pos_buf[i] >= 0; i++) {
+ matchBuf[c++] = matchBuf[pos_buf[i]];
+ j = pos_buf[i] + 1;
+ }
+ matchBuf[c] = 0;
+ /* old lenght matchBuf with quotes symbols */
+ *len_with_quotes = j ? j - pos_buf[0] : 0;
+
+ return command_mode;
+}
+
+
+static void input_tab(int *lastWasTab)
+{
+ /* Do TAB completion */
+ static int num_matches;
+ static char **matches;
+
+ if (lastWasTab == 0) { /* free all memory */