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.
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));
 }
_______________________________________________
Mc-devel mailing list
http://mail.gnome.org/mailman/listinfo/mc-devel

Reply via email to