r287: Removed the DEFAULT_PIXMAP array - the new type system makes in unnecessary
[rox-filer/dt.git] / ROX-Filer / src / minibuffer.c
blobd758ecda9b29fd05b864dca1d98486da6e124db3
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2000, Thomas Leonard, <tal197@ecs.soton.ac.uk>.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* minibuffer.c - for handling the path entry box at the bottom */
24 #include "config.h"
26 #include <string.h>
27 #include <errno.h>
28 #include <ctype.h>
29 #include <glob.h>
30 #include <stdio.h>
32 #include <gtk/gtk.h>
33 #include <gdk/gdkkeysyms.h>
35 #include "collection.h"
36 #include "find.h"
37 #include "gui_support.h"
38 #include "support.h"
39 #include "minibuffer.h"
40 #include "filer.h"
41 #include "main.h"
42 #include "action.h"
44 static GList *shell_history = NULL;
46 /* Static prototypes */
47 static gint key_press_event(GtkWidget *widget,
48 GdkEventKey *event,
49 FilerWindow *filer_window);
50 static void changed(GtkEditable *mini, FilerWindow *filer_window);
51 static void find_next_match(FilerWindow *filer_window, char *pattern, int dir);
52 static gboolean matches(Collection *collection, int item, char *pattern);
53 static void search_in_dir(FilerWindow *filer_window, int dir);
54 static guchar *mini_contents(FilerWindow *filer_window);
55 static void show_help(FilerWindow *filer_window);
58 /****************************************************************
59 * EXTERNAL INTERFACE *
60 ****************************************************************/
63 /* Creates the minibuffer widgets, setting the appropriate fields
64 * in filer_window.
66 void create_minibuffer(FilerWindow *filer_window)
68 GtkWidget *hbox, *label, *mini, *help, *icon;
70 hbox = gtk_hbox_new(FALSE, 0);
72 icon = gtk_pixmap_new(im_help->pixmap, im_help->mask);
73 help = gtk_button_new();
74 gtk_container_add(GTK_CONTAINER(help), icon);
75 gtk_box_pack_start(GTK_BOX(hbox), help, FALSE, TRUE, 0);
76 gtk_signal_connect_object(GTK_OBJECT(help), "clicked",
77 GTK_SIGNAL_FUNC(show_help), (GtkObject *) filer_window);
79 label = gtk_label_new(NULL);
80 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 2);
82 mini = gtk_entry_new();
83 gtk_box_pack_start(GTK_BOX(hbox), mini, TRUE, TRUE, 0);
84 gtk_widget_set_style(mini, fixed_style);
85 gtk_signal_connect(GTK_OBJECT(mini), "key_press_event",
86 GTK_SIGNAL_FUNC(key_press_event), filer_window);
87 gtk_signal_connect(GTK_OBJECT(mini), "changed",
88 GTK_SIGNAL_FUNC(changed), filer_window);
90 filer_window->minibuffer = mini;
91 filer_window->minibuffer_label = label;
92 filer_window->minibuffer_area = hbox;
95 void minibuffer_show(FilerWindow *filer_window, MiniType mini_type)
97 Collection *collection;
98 GtkEntry *mini;
100 g_return_if_fail(filer_window != NULL);
101 g_return_if_fail(filer_window->minibuffer != NULL);
103 mini = GTK_ENTRY(filer_window->minibuffer);
105 filer_window->mini_type = MINI_NONE;
106 gtk_label_set_text(GTK_LABEL(filer_window->minibuffer_label),
107 mini_type == MINI_PATH ? _("Goto:") :
108 mini_type == MINI_SHELL ? _("Shell:") :
109 mini_type == MINI_RUN_ACTION ? _("Run Action:") :
110 mini_type == MINI_SELECT_IF ? _("Select If:") :
111 "?");
113 collection = filer_window->collection;
114 collection_move_cursor(collection, 0, 0); /* Turn the cursor on */
115 switch (mini_type)
117 case MINI_PATH:
118 filer_window->mini_cursor_base =
119 MAX(collection->cursor_item, 0);
120 gtk_entry_set_text(mini,
121 make_path(filer_window->path, "")->str);
122 break;
123 case MINI_SHELL:
124 case MINI_RUN_ACTION:
125 case MINI_SELECT_IF:
126 filer_window->mini_cursor_base = -1; /* History */
127 gtk_entry_set_text(mini, "");
128 break;
129 default:
130 g_warning("Bad minibuffer type\n");
131 return;
134 filer_window->mini_type = mini_type;
136 gtk_entry_set_position(mini, -1);
138 gtk_widget_show_all(filer_window->minibuffer_area);
140 gtk_window_set_focus(GTK_WINDOW(filer_window->window),
141 filer_window->minibuffer);
144 void minibuffer_hide(FilerWindow *filer_window)
146 filer_window->mini_type = MINI_NONE;
148 gtk_widget_hide(filer_window->minibuffer_area);
149 gtk_window_set_focus(GTK_WINDOW(filer_window->window),
150 GTK_WIDGET(filer_window->collection));
153 /* Insert this leafname at the cursor (replacing the selection, if any).
154 * Must be in SHELL or RUN_ACTION mode.
156 void minibuffer_add(FilerWindow *filer_window, guchar *leafname)
158 guchar *esc;
159 GtkEditable *edit = GTK_EDITABLE(filer_window->minibuffer);
160 GtkEntry *entry = GTK_ENTRY(edit);
161 int pos;
163 g_return_if_fail(filer_window->mini_type == MINI_SHELL ||
164 filer_window->mini_type == MINI_RUN_ACTION);
166 esc = shell_escape(leafname);
168 gtk_editable_delete_selection(edit);
169 pos = gtk_editable_get_position(edit);
171 if (pos > 0 && gtk_entry_get_text(entry)[pos - 1] != ' ')
172 gtk_editable_insert_text(edit, " ", 1, &pos);
174 gtk_editable_insert_text(edit, esc, strlen(esc), &pos);
175 gtk_editable_set_position(edit, pos);
177 g_free(esc);
181 /****************************************************************
182 * INTERNAL FUNCTIONS *
183 ****************************************************************/
185 static void show_help(FilerWindow *filer_window)
187 guchar *message;
189 gtk_widget_grab_focus(filer_window->minibuffer);
191 switch (filer_window->mini_type)
193 case MINI_PATH:
194 message = _("Enter the name of a file and I'll display "
195 "it for you. Press Tab to fill in the longest "
196 "match. Escape to close the minibuffer.");
197 break;
198 case MINI_SHELL:
199 message = _("Enter a shell command to execute. Click "
200 "on a file to add it to the buffer.");
201 break;
202 case MINI_RUN_ACTION:
203 message =
204 _("To set the run action for a file, either:\n"
205 "- Drag a file to an application directory (eg drag an image to the "
206 "Gimp), or\n" "- Enter a shell command which contains a \"$1\""
207 "where the name of the file should go (eg ` gimp \"$1\" ')");
208 break;
209 case MINI_SELECT_IF:
210 show_condition_help();
211 return;
212 default:
213 message = "?!?";
214 break;
217 delayed_error(PROJECT, message);
221 /* PATH ENTRY */
223 static void path_return_pressed(FilerWindow *filer_window, GdkEventKey *event)
225 Collection *collection = filer_window->collection;
226 int item = collection->cursor_item;
227 char *path, *pattern;
228 int flags = OPEN_FROM_MINI | OPEN_SAME_WINDOW;
230 path = gtk_entry_get_text(GTK_ENTRY(filer_window->minibuffer));
231 pattern = strrchr(path, '/');
232 if (pattern)
233 pattern++;
234 else
235 pattern = path;
237 if (item == -1 || item >= collection->number_of_items ||
238 !matches(collection, item, pattern))
240 gdk_beep();
241 return;
244 if ((event->state & GDK_SHIFT_MASK) != 0)
245 flags |= OPEN_SHIFT;
247 filer_openitem(filer_window, item, flags);
250 /* Use the cursor item to fill in the minibuffer.
251 * If there are multiple matches the fill in as much as possible and beep.
253 static void complete(FilerWindow *filer_window)
255 GtkEntry *entry;
256 Collection *collection = filer_window->collection;
257 int cursor = collection->cursor_item;
258 DirItem *item;
259 int shortest_stem = -1;
260 int current_stem;
261 int other;
262 guchar *text, *leaf;
264 if (cursor < 0 || cursor >= collection->number_of_items)
266 gdk_beep();
267 return;
270 entry = GTK_ENTRY(filer_window->minibuffer);
272 item = (DirItem *) collection->items[cursor].data;
274 text = gtk_entry_get_text(entry);
275 leaf = strrchr(text, '/');
276 if (!leaf)
278 gdk_beep();
279 return;
282 leaf++;
283 if (!matches(collection, cursor, leaf))
285 gdk_beep();
286 return;
289 current_stem = strlen(leaf);
291 /* Find the longest other match of this name. It it's longer than
292 * the currently entered text then complete only up to that length.
294 for (other = 0; other < collection->number_of_items; other++)
296 DirItem *other_item = (DirItem *) collection->items[other].data;
297 int stem = 0;
299 if (other == cursor)
300 continue;
302 while (other_item->leafname[stem] && item->leafname[stem])
304 if (other_item->leafname[stem] != item->leafname[stem])
305 break;
306 stem++;
309 /* stem is the index of the first difference */
310 if (stem >= current_stem &&
311 (shortest_stem == -1 || stem < shortest_stem))
312 shortest_stem = stem;
315 if (current_stem == shortest_stem)
316 gdk_beep();
317 else if (current_stem < shortest_stem)
319 guchar *extra;
321 extra = g_strndup(item->leafname + current_stem,
322 shortest_stem - current_stem);
323 gtk_entry_append_text(entry, extra);
324 g_free(extra);
325 gdk_beep();
327 else
329 GString *new;
331 new = make_path(filer_window->path, item->leafname);
333 if (item->base_type == TYPE_DIRECTORY &&
334 (item->flags & ITEM_FLAG_APPDIR) == 0)
335 g_string_append_c(new, '/');
337 gtk_entry_set_text(entry, new->str);
341 static void path_changed(GtkEditable *mini, FilerWindow *filer_window)
343 char *new, *slash;
344 char *path, *real;
346 new = gtk_entry_get_text(GTK_ENTRY(mini));
347 if (*new == '/')
348 new = g_strdup(new);
349 else
350 new = g_strdup_printf("/%s", new);
352 slash = strrchr(new, '/');
353 *slash = '\0';
355 if (*new == '\0')
356 path = "/";
357 else
358 path = new;
360 real = pathdup(path);
362 if (strcmp(real, filer_window->path) != 0)
364 struct stat info;
365 if (mc_stat(real, &info) == 0 && S_ISDIR(info.st_mode))
366 filer_change_to(filer_window, real, slash + 1);
367 else
368 gdk_beep();
370 else
372 Collection *collection = filer_window->collection;
373 int item;
375 find_next_match(filer_window, slash + 1, 0);
376 item = collection->cursor_item;
377 if (item != -1 && !matches(collection, item, slash + 1))
378 gdk_beep();
381 g_free(real);
382 g_free(new);
385 /* Find the next item in the collection that matches 'pattern'. Start from
386 * mini_cursor_base and loop at either end. dir is 1 for a forward search,
387 * -1 for backwards. 0 means forwards, but may stay the same.
389 * Does not automatically update mini_cursor_base.
391 static void find_next_match(FilerWindow *filer_window, char *pattern, int dir)
393 Collection *collection = filer_window->collection;
394 int base = filer_window->mini_cursor_base;
395 int item = base;
397 if (collection->number_of_items < 1)
398 return;
400 if (base < 0 || base>= collection->number_of_items)
401 filer_window->mini_cursor_base = base = 0;
405 /* Step to the next item */
406 item += dir;
408 if (item >= collection->number_of_items)
409 item = 0;
410 else if (item < 0)
411 item = collection->number_of_items - 1;
413 if (dir == 0)
414 dir = 1;
415 else if (item == base)
416 break; /* No (other) matches at all */
419 } while (!matches(collection, item, pattern));
421 collection_set_cursor_item(collection, item);
424 static gboolean matches(Collection *collection, int item_number, char *pattern)
426 DirItem *item = (DirItem *) collection->items[item_number].data;
428 return strncmp(item->leafname, pattern, strlen(pattern)) == 0;
431 /* Find next match and set base for future matches. */
432 static void search_in_dir(FilerWindow *filer_window, int dir)
434 char *path, *pattern;
436 path = gtk_entry_get_text(GTK_ENTRY(filer_window->minibuffer));
437 pattern = strrchr(path, '/');
438 if (pattern)
439 pattern++;
440 else
441 pattern = path;
443 filer_window->mini_cursor_base = filer_window->collection->cursor_item;
444 find_next_match(filer_window, pattern, dir);
445 filer_window->mini_cursor_base = filer_window->collection->cursor_item;
448 /* SHELL COMMANDS */
450 static void add_to_history(guchar *line)
452 guchar *last;
454 last = shell_history ? (guchar *) shell_history->data : NULL;
456 if (last && strcmp(last, line) == 0)
457 return; /* Duplicating last entry */
459 shell_history = g_list_prepend(shell_history, g_strdup(line));
462 static void shell_done(FilerWindow *filer_window)
464 if (filer_exists(filer_window))
465 filer_update_dir(filer_window, TRUE);
468 /* Given a list of matches, return the longest stem. g_free() the result.
469 * Special chars are escaped. If there is only a single (non-dir) match
470 * then a trailing space is added.
472 static guchar *best_match(FilerWindow *filer_window, glob_t *matches)
474 gchar *first = matches->gl_pathv[0];
475 int i;
476 int longest, path_len;
477 guchar *path, *tmp;
479 longest = strlen(first);
481 for (i = 1; i < matches->gl_pathc; i++)
483 int j;
484 guchar *m = matches->gl_pathv[i];
486 for (j = 0; j < longest; j++)
487 if (m[j] != first[j])
488 longest = j;
491 path_len = strlen(filer_window->path);
492 if (strncmp(filer_window->path, first, path_len) == 0 &&
493 first[path_len] == '/' && first[path_len + 1])
495 path = g_strndup(first + path_len + 1, longest - path_len - 1);
497 else
498 path = g_strndup(first, longest);
500 tmp = shell_escape(path);
501 g_free(path);
503 if (matches->gl_pathc == 1 && tmp[strlen(tmp) - 1] != '/')
505 path = g_strdup_printf("%s ", tmp);
506 g_free(tmp);
507 return path;
510 return tmp;
513 static void shell_tab(FilerWindow *filer_window)
515 int i;
516 guchar *entry;
517 guchar quote;
518 int pos;
519 GString *leaf;
520 glob_t matches;
521 int leaf_start;
523 entry = gtk_entry_get_text(GTK_ENTRY(filer_window->minibuffer));
524 pos = gtk_editable_get_position(GTK_EDITABLE(filer_window->minibuffer));
525 leaf = g_string_new(NULL);
527 quote = '\0';
528 for (i = 0; i < pos; i++)
530 guchar c = entry[i];
532 if (leaf->len == 0)
533 leaf_start = i;
535 if (c == ' ')
537 g_string_truncate(leaf, 0);
538 continue;
540 else if (c == '\\' && i + 1 < pos)
541 c = entry[++i];
542 else if (c == '"' || c == '\'')
544 guchar cc;
546 for (++i; i < pos; i++)
548 cc = entry[i];
550 if (cc == '\\' && i + 1 < pos)
551 cc = entry[++i];
552 else if (entry[i] == c)
553 break;
554 g_string_append_c(leaf, entry[i]);
556 continue;
559 g_string_append_c(leaf, c);
562 if (leaf->len == 0)
563 leaf_start = pos;
565 if (leaf->str[0] != '/')
567 g_string_prepend_c(leaf, '/');
568 g_string_prepend(leaf, filer_window->path);
571 g_string_append_c(leaf, '*');
573 if (glob(leaf->str,
574 #ifdef GLOB_TILDE
575 GLOB_TILDE |
576 #endif
577 GLOB_MARK, NULL, &matches) == 0)
579 if (matches.gl_pathc > 0)
581 guchar *best;
582 GtkEditable *edit =
583 GTK_EDITABLE(filer_window->minibuffer);
585 best = best_match(filer_window, &matches);
587 gtk_editable_delete_text(edit, leaf_start, pos);
588 gtk_editable_insert_text(edit, best, strlen(best),
589 &leaf_start);
590 gtk_editable_set_position(edit, leaf_start);
592 g_free(best);
594 if (matches.gl_pathc != 1)
595 gdk_beep();
597 globfree(&matches);
600 g_string_free(leaf, TRUE);
603 /* This is called from shell_return_pressed() so that the command is already
604 * in the history. Returns TRUE if the buffer should be closed.
606 gboolean set_run_action(FilerWindow *filer_window, guchar *command)
608 Collection *collection = filer_window->collection;
609 int n = collection->cursor_item;
610 DirItem *item;
611 guchar *path, *tmp;
612 FILE *file;
613 int error = 0, len;
615 if (!strchr(command, '$'))
617 show_help(filer_window);
618 return FALSE;
621 if (n < 0 || n >= collection->number_of_items)
623 delayed_error(PROJECT,
624 _("You must have the cursor on the item to use for '$1'."));
625 return FALSE;
628 item = (DirItem *) collection->items[n].data;
629 path = type_ask_which_action(item->mime_type->media_type,
630 item->mime_type->subtype);
632 if (!path)
633 return TRUE;
635 tmp = g_strdup_printf("#! /bin/sh\nexec %s\n", command);
636 len = strlen(tmp);
638 file = fopen(path, "wb");
639 if (fwrite(tmp, 1, len, file) < len)
640 error = errno;
641 if (fclose(file) && error == 0)
642 error = errno;
643 if (chmod(path, 0777))
644 error = errno;
646 if (error)
647 report_error(PROJECT, g_strerror(errno));
649 g_free(tmp);
651 return TRUE;
654 /* Either execute the command or make it the default run action */
655 static void shell_return_pressed(FilerWindow *filer_window)
657 GPtrArray *argv;
658 int i;
659 guchar *entry;
660 Collection *collection = filer_window->collection;
661 int child;
663 entry = mini_contents(filer_window);
665 if (!entry)
666 goto out;
668 add_to_history(entry);
670 if (filer_window->mini_type == MINI_RUN_ACTION)
672 if (set_run_action(filer_window, entry))
673 goto out;
674 else
675 return;
678 argv = g_ptr_array_new();
679 g_ptr_array_add(argv, "sh");
680 g_ptr_array_add(argv, "-c");
681 g_ptr_array_add(argv, entry);
682 g_ptr_array_add(argv, "sh");
684 for (i = 0; i < collection->number_of_items; i++)
686 DirItem *item = (DirItem *) collection->items[i].data;
687 if (collection->items[i].selected)
688 g_ptr_array_add(argv, item->leafname);
691 g_ptr_array_add(argv, NULL);
693 child = fork();
695 switch (child)
697 case -1:
698 delayed_error(PROJECT, _("Failed to create "
699 "child process"));
700 break;
701 case 0: /* Child */
702 dup2(to_error_log, STDOUT_FILENO);
703 close_on_exec(STDOUT_FILENO, FALSE);
704 dup2(to_error_log, STDERR_FILENO);
705 close_on_exec(STDERR_FILENO, FALSE);
706 if (chdir(filer_window->path))
707 g_printerr("chdir(%s) failed: %s\n",
708 filer_window->path,
709 g_strerror(errno));
710 execvp((char *) argv->pdata[0],
711 (char **) argv->pdata);
712 g_printerr("execvp(%s, ...) failed: %s\n",
713 (char *) argv->pdata[0],
714 g_strerror(errno));
715 _exit(0);
716 default:
717 on_child_death(child,
718 (CallbackFn) shell_done, filer_window);
719 break;
722 g_ptr_array_free(argv, TRUE);
724 out:
725 minibuffer_hide(filer_window);
728 /* Move through the shell history */
729 static void shell_recall(FilerWindow *filer_window, int dir)
731 guchar *command;
732 int pos = filer_window->mini_cursor_base;
734 pos += dir;
735 if (pos >= 0)
737 command = g_list_nth_data(shell_history, pos);
738 if (!command)
739 return;
741 else
742 command = "";
744 if (pos < -1)
745 pos = -1;
746 filer_window->mini_cursor_base = pos;
748 gtk_entry_set_text(GTK_ENTRY(filer_window->minibuffer), command);
751 /* SELECT IF */
753 static void select_return_pressed(FilerWindow *filer_window)
755 FindCondition *cond;
756 int i, n;
757 guchar *entry;
758 Collection *collection = filer_window->collection;
759 FindInfo info;
761 entry = mini_contents(filer_window);
763 if (!entry)
764 goto out;
766 add_to_history(entry);
768 cond = find_compile(entry);
769 if (!cond)
771 delayed_error(PROJECT, "Invalid Find condition");
772 return;
775 info.now = time(NULL);
776 info.prune = FALSE; /* (don't care) */
777 n = collection->number_of_items;
779 /* If an item at the start is selected then we could lose the
780 * primary selection after checking that item and then need to
781 * gain it again at the end. Therefore, if anything is selected
782 * then select the last item until the end of the search.
784 if (collection->number_selected)
785 collection_select_item(collection, n - 1);
787 for (i = 0; i < n; i++)
789 DirItem *item = (DirItem *) collection->items[i].data;
791 info.leaf = item->leafname;
792 info.fullpath = make_path(filer_window->path, info.leaf)->str;
794 if (lstat(info.fullpath, &info.stats) == 0 &&
795 find_test_condition(cond, &info))
796 collection_select_item(collection, i);
797 else
798 collection_unselect_item(collection, i);
801 find_condition_free(cond);
803 out:
804 minibuffer_hide(filer_window);
808 /* EVENT HANDLERS */
810 static gint key_press_event(GtkWidget *widget,
811 GdkEventKey *event,
812 FilerWindow *filer_window)
814 if (event->keyval == GDK_Escape)
816 if (filer_window->mini_type == MINI_SHELL)
818 guchar *line;
820 line = mini_contents(filer_window);
821 if (line)
822 add_to_history(line);
825 minibuffer_hide(filer_window);
826 return TRUE;
829 switch (filer_window->mini_type)
831 case MINI_PATH:
832 switch (event->keyval)
834 case GDK_Up:
835 search_in_dir(filer_window, -1);
836 break;
837 case GDK_Down:
838 search_in_dir(filer_window, 1);
839 break;
840 case GDK_Return:
841 path_return_pressed(filer_window,
842 event);
843 break;
844 case GDK_Tab:
845 complete(filer_window);
846 break;
847 default:
848 return FALSE;
850 break;
852 case MINI_SHELL:
853 case MINI_RUN_ACTION:
854 switch (event->keyval)
856 case GDK_Up:
857 shell_recall(filer_window, 1);
858 break;
859 case GDK_Down:
860 shell_recall(filer_window, -1);
861 break;
862 case GDK_Tab:
863 shell_tab(filer_window);
864 break;
865 case GDK_Return:
866 shell_return_pressed(filer_window);
867 break;
868 default:
869 return FALSE;
871 break;
872 case MINI_SELECT_IF:
873 switch (event->keyval)
875 case GDK_Up:
876 shell_recall(filer_window, 1);
877 break;
878 case GDK_Down:
879 shell_recall(filer_window, -1);
880 break;
881 case GDK_Tab:
882 return TRUE;
883 case GDK_Return:
884 select_return_pressed(filer_window);
885 break;
886 default:
887 return FALSE;
889 break;
890 default:
891 break;
894 gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event");
895 return TRUE;
898 static void changed(GtkEditable *mini, FilerWindow *filer_window)
900 switch (filer_window->mini_type)
902 case MINI_PATH:
903 path_changed(mini, filer_window);
904 return;
905 default:
906 break;
910 /* Returns a string (which must NOT be freed), or NULL if the buffer
911 * is blank (whitespace only).
913 static guchar *mini_contents(FilerWindow *filer_window)
915 guchar *entry, *c;
917 entry = gtk_entry_get_text(GTK_ENTRY(filer_window->minibuffer));
919 for (c = entry; *c; c++)
920 if (!isspace(*c))
921 return entry;
923 return NULL;