Complete: Show All

Pavel Tsekov ptsekov at gmx.net
Fri Feb 18 15:57:29 UTC 2005


Hello,

On Wed, 26 Jan 2005, Thomas Zajic wrote:

> Hi,
>
> I just stumbled across another long-standing bug in mc again.
>
> With "Complete: Show All" enabled in F9->Options->Configuration, mc does
> not autocomplete paths or filenames when there's only one alternative.
>
> Eg. given a directory structure like "x/y/z" (with "y" being the only dir
> entry in "x", and "z" being the only dir entry in "y"), having "x" in one
> panel and some other directory in the other panel, mc stops autocompletion
> in "y" (or even "x", if "x" is the only file/directory in that panel) when
> trying to copy/move a file to "z".
>
> This works fine with "Complete: Show All" disabled.

Attached is a patch which solves the issue. Please, test.

In short this is what happend in the case that Thomas described:

Consider the following directory structure:

.../x/y/z

In MC (Complete: show all - enabled) go to 'x' and type 'Alt + C'
and then type 'Alt + Tab'.

1) The code detects that is must display any ambiguous matches
immediatly. In this case two calls to complete_engine () will
be made - the first one with the DO_INSERTION option and the
second one with the DO_QUERY option.

2) The first call get only one match - the 'y' dir. It displays
it, calls free_completions () (effectively leaving in->completions ==
0) and returns.

3) The second call is supposed to display a dialog with all matches
although in this particular case there aren't any other matches except
the 'y' dir. Still this call is made, it fills 'in->completions' and it
matches the 'y/z' dir. This match  is not displayed though since
complete_engine (..., DO_QUERY) is supposed to work with more than a
single match and the function returns but it doesn't clean
'in->completions'.

4) Further calls to complete () (i.e. if you press Alt + tab again) are
fooled by the fact that 'in->completions' is not empty and try to display
a list of ambiguous entries but obviously they fail silently.

A simple description of what is in the patch:

The first hunk is there just as precaution - if it happens so that
complete_engine () is passed the DO_QUERY flag but there aren't
multiple matches (this cannot happent with this patch, but just in
case). The second hunk prevents null pointer dereference which might
occur if complete_engine () is called with DO_QUERY set and there is
only one match. The third hunk simplifies (IMO) the complete () routine
and delegates the additional work required by the 'Complete: show all'
functionality to complete_engine ().

The second and the third hunks actually do fix the "Complete: show all"
issue.
-------------- next part --------------
Index: src/complete.c
===================================================================
RCS file: /cvsroot/mc/mc/src/complete.c,v
retrieving revision 1.54
diff -u -p -r1.54 complete.c
--- src/complete.c	8 Feb 2005 09:04:03 -0000	1.54
+++ src/complete.c	18 Feb 2005 15:20:05 -0000
@@ -921,7 +921,7 @@ complete_engine (WInput *in, int what_to
     	in->completions = try_complete (in->buffer, &start, &end, in->completion_flags);
     }
     if (in->completions){
-    	if (what_to_do & DO_INSERTION) {
+    	if (what_to_do & DO_INSERTION || ((what_to_do & DO_QUERY) && !in->completions[1])) {
     	    if (insert_text (in, in->completions [0], strlen (in->completions [0]))){
     	        if (in->completions [1])
     	    	    beep ();
@@ -930,11 +930,7 @@ complete_engine (WInput *in, int what_to
 	    } else
 	        beep ();
         }
-	/* FIXME: evil evil evil.  We do not go into the query completion engine
-	 * because we do not have a Gtk dialog for it.  Gtk-ted does not like
-	 * this; if we enable this code, it will crash.
-	 */
-    	if ((what_to_do & DO_QUERY) && in->completions [1]) {
+    	if ((what_to_do & DO_QUERY) && in->completions && in->completions [1]) {
     	    int maxlen = 0, i, count = 0;
     	    int x, y, w, h;
     	    int start_x, start_y;
@@ -999,11 +995,17 @@ complete_engine (WInput *in, int what_to
 
 void complete (WInput *in)
 {
+    int engine_flags;
+
     if (in->completions)
-    	while (complete_engine (in, DO_QUERY));
-    else if (show_all_if_ambiguous){
-    	complete_engine (in, DO_INSERTION);
-    	while (complete_engine (in, DO_QUERY));
-    } else
-    	complete_engine (in, DO_INSERTION);
+	engine_flags = DO_QUERY;
+    else
+    {
+	engine_flags = DO_INSERTION;
+
+	if (show_all_if_ambiguous)
+	    engine_flags |= DO_QUERY;
+    }
+
+    while (complete_engine (in, engine_flags));
 }


More information about the mc-devel mailing list