* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-#include "config.h"
+#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#endif
-#include <glib.h> /* Include early to get G_OS_WIN32 and
- * G_WITH_CYGWIN */
+#include <glib.h> /* Include early to get G_OS_WIN32 etc */
-#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
+#if defined(G_PLATFORM_WIN32)
#include <ctype.h>
#define STRICT
#include <windows.h>
#undef STRICT
-#endif /* G_OS_WIN32 || G_WITH_CYGWIN */
+#endif /* G_PLATFORM_WIN32 */
#ifdef G_OS_WIN32
#include <winsock.h> /* For gethostname */
#endif
#include "gdk/gdkkeysyms.h"
+#include "gtkalias.h"
#include "gtkbutton.h"
#include "gtkcellrenderertext.h"
#include "gtkentry.h"
#include "gtkfilesel.h"
#include "gtkhbox.h"
#include "gtkhbbox.h"
+#include "gtkintl.h"
#include "gtklabel.h"
#include "gtkliststore.h"
#include "gtkmain.h"
#include "gtkvbox.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
-#include "gtkoptionmenu.h"
#include "gtkdialog.h"
#include "gtkmessagedialog.h"
-#include "gtkintl.h"
#include "gtkdnd.h"
#include "gtkeventbox.h"
+#undef GTK_DISABLE_DEPRECATED
+#include "gtkoptionmenu.h"
+#define GTK_DISABLE_DEPRECATED
+
#define WANT_HPANED 1
#include "gtkhpaned.h"
*/
struct _CompletionDirSent
{
+#ifndef G_PLATFORM_WIN32
ino_t inode;
time_t mtime;
dev_t device;
+#endif
gint entry_count;
struct _CompletionDirEntry *entries;
*/
static gchar* cmpl_reference_position (CompletionState* cmpl_state);
+#if 0
+/* This doesn't work currently and would require changes
+ * to fnmatch.c to get working.
+ */
/* backing up: if cmpl_completion_matches returns NULL, you may query
* the index of the last completable character into cmpl_updated_text.
*/
static gint cmpl_last_valid_char (CompletionState* cmpl_state);
+#endif
/* When the user selects a non-directory, call cmpl_completion_fullname
* to get the full name of the selected file.
*/
-static const gchar* cmpl_completion_fullname (const gchar*, CompletionState* cmpl_state);
+static gchar* cmpl_completion_fullname (const gchar*, CompletionState* cmpl_state);
/* Directory operations. */
static CompletionDir* open_ref_dir (gchar* text_to_complete,
gchar** remaining_text,
CompletionState* cmpl_state);
-#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
+#ifndef G_PLATFORM_WIN32
static gboolean check_dir (gchar *dir_name,
struct stat *result,
gboolean *stat_subdirs);
static gint correct_dir_fullname (CompletionDir* cmpl_dir);
static gint correct_parent (CompletionDir* cmpl_dir,
struct stat *sbuf);
-#ifndef G_OS_WIN32
+#ifndef G_PLATFORM_WIN32
static gchar* find_parent_dir_fullname (gchar* dirname);
#endif
static CompletionDir* attach_dir (CompletionDirSent* sent,
static void free_selected_names (GPtrArray *names);
-#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
-#define compare_filenames(a, b) strcmp(a, b)
+#ifndef G_PLATFORM_WIN32
+
+#define compare_utf8_filenames(a, b) strcmp(a, b)
+#define compare_sys_filenames(a, b) strcmp(a, b)
+
#else
-#define compare_filenames(a, b) g_ascii_strcasecmp(a, b)
-#endif
+static gint
+compare_utf8_filenames (const gchar *a,
+ const gchar *b)
+{
+ gchar *a_folded, *b_folded;
+ gint retval;
+
+ a_folded = g_utf8_strdown (a, -1);
+ b_folded = g_utf8_strdown (b, -1);
+
+ retval = strcmp (a_folded, b_folded);
+
+ g_free (a_folded);
+ g_free (b_folded);
+
+ return retval;
+}
+
+static gint
+compare_sys_filenames (const gchar *a,
+ const gchar *b)
+{
+ gchar *a_utf8, *b_utf8;
+ gint retval;
+
+ a_utf8 = g_filename_to_utf8 (a, -1, NULL, NULL, NULL);
+ b_utf8 = g_filename_to_utf8 (b, -1, NULL, NULL, NULL);
+
+ retval = compare_utf8_filenames (a_utf8, b_utf8);
+
+ g_free (a_utf8);
+ g_free (b_utf8);
+
+ return retval;
+}
+
+#endif
static GtkWindowClass *parent_class = NULL;
/*
* Take the path currently in the file selection
* entry field and translate as necessary from
- * a WIN32 style to CYGWIN32 style path. For
+ * a Win32 style to Cygwin style path. For
* instance translate:
* x:\somepath\file.jpg
* to:
g_object_class_install_property (gobject_class,
PROP_FILENAME,
g_param_spec_string ("filename",
- _("Filename"),
- _("The currently selected filename"),
+ P_("Filename"),
+ P_("The currently selected filename"),
NULL,
G_PARAM_READABLE | G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class,
PROP_SHOW_FILEOPS,
g_param_spec_boolean ("show_fileops",
- _("Show file operations"),
- _("Whether buttons for creating/manipulating files should be displayed"),
+ P_("Show file operations"),
+ P_("Whether buttons for creating/manipulating files should be displayed"),
FALSE,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class,
PROP_SELECT_MULTIPLE,
g_param_spec_boolean ("select_multiple",
- _("Select multiple"),
- _("Whether to allow multiple files to be selected"),
+ P_("Select multiple"),
+ P_("Whether to allow multiple files to be selected"),
FALSE,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
* directory path, then the requestor will open with that path as its
* current working directory.
*
+ * This has the consequence that in order to open the requestor with a
+ * working directory and an empty filename, @filename must have a trailing
+ * directory separator.
+ *
* The encoding of @filename is the on-disk encoding, which
* may not be UTF-8. See g_filename_from_utf8().
**/
text = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
if (text)
{
- sys_filename = g_filename_from_utf8 (cmpl_completion_fullname (text, filesel->cmpl_state), -1, NULL, NULL, NULL);
+ gchar *fullname = cmpl_completion_fullname (text, filesel->cmpl_state);
+ sys_filename = g_filename_from_utf8 (fullname, -1, NULL, NULL, NULL);
+ g_free (fullname);
if (!sys_filename)
return nothing;
strncpy (something, sys_filename, sizeof (something));
dialog = gtk_message_dialog_new (GTK_WINDOW (fs),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
+ GTK_BUTTONS_OK,
"%s", error_message);
/* yes, we free it */
goto out;
}
- if (mkdir (sys_full_path, 0755) < 0)
+ if (mkdir (sys_full_path, 0777) < 0)
{
buf = g_strdup_printf (_("Error creating folder \"%s\": %s\n"), dirname,
g_strerror (errno));
gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry,
TRUE, TRUE, 5);
GTK_WIDGET_SET_FLAGS (fs->fileop_entry, GTK_CAN_DEFAULT);
+ gtk_entry_set_activates_default (GTK_ENTRY (fs->fileop_entry), TRUE);
gtk_widget_show (fs->fileop_entry);
/* buttons */
- button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_widget_destroy),
dialog);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
- button, TRUE, TRUE, 0);
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_widget_grab_default (button);
- gtk_widget_show (button);
gtk_widget_grab_focus (fs->fileop_entry);
- button = gtk_button_new_with_mnemonic (_("C_reate"));
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("C_reate"), GTK_RESPONSE_OK);
gtk_widget_set_sensitive (button, FALSE);
g_signal_connect (button, "clicked",
G_CALLBACK (gtk_file_selection_create_dir_confirmed),
G_CALLBACK (gtk_file_selection_fileop_entry_changed),
button);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
- button, TRUE, TRUE, 0);
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_widget_show (button);
+ gtk_widget_grab_default (button);
gtk_widget_show (dialog);
}
GTK_WINDOW (fs)->modal ? GTK_DIALOG_MODAL : 0,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_NONE,
- _("Really delete file \"%s\" ?"), filename);
+ _("Really delete file \"%s\"?"), filename);
g_signal_connect (dialog, "destroy",
G_CALLBACK (gtk_file_selection_fileop_destroy),
gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry,
TRUE, TRUE, 5);
GTK_WIDGET_SET_FLAGS (fs->fileop_entry, GTK_CAN_DEFAULT);
+ gtk_entry_set_activates_default (GTK_ENTRY (fs->fileop_entry), TRUE);
gtk_widget_show (fs->fileop_entry);
gtk_entry_set_text (GTK_ENTRY (fs->fileop_entry), fs->fileop_file);
0, strlen (fs->fileop_file));
/* buttons */
- button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_widget_destroy),
dialog);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
- button, TRUE, TRUE, 0);
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_widget_grab_default (button);
- gtk_widget_show (button);
gtk_widget_grab_focus (fs->fileop_entry);
- button = gtk_button_new_with_mnemonic (_("_Rename"));
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("_Rename"), GTK_RESPONSE_OK);
g_signal_connect (button, "clicked",
G_CALLBACK (gtk_file_selection_rename_file_confirmed),
fs);
G_CALLBACK (gtk_file_selection_fileop_entry_changed),
button);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
- button, TRUE, TRUE, 0);
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_widget_show (button);
+ gtk_widget_grab_default (button);
gtk_widget_show (dialog);
}
g_free (filename);
}
-#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
+#ifdef G_PLATFORM_WIN32
static void
win32_gtk_add_drives_to_dir_list (GtkListStore *model)
while (*textPtr != '\0')
{
/* Ignore floppies (?) */
- if ((tolower (textPtr[0]) != 'a') && (tolower (textPtr[0]) != 'b'))
+ if (GetDriveType (textPtr) != DRIVE_REMOVABLE)
{
/* Build the actual displayable string */
g_snprintf (formatBuffer, sizeof (formatBuffer), "%c:\\", toupper (textPtr[0]));
gchar* sel_text;
gint did_recurse = FALSE;
gint possible_count = 0;
- gint selection_index = -1;
g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
poss = cmpl_next_completion (cmpl_state);
}
-#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
+#ifdef G_PLATFORM_WIN32
/* For Windows, add drives as potential selections */
win32_gtk_add_drives_to_dir_list (dir_model);
#endif
}
else
{
- selection_index = cmpl_last_valid_char (cmpl_state) -
- (strlen (rel_path) - strlen (rem_path));
if (fs->selection_entry)
gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), rem_path);
}
if (!did_recurse)
{
- if (fs->selection_entry)
- gtk_editable_set_position (GTK_EDITABLE (fs->selection_entry),
- selection_index);
+ if (fs->selection_entry && try_complete)
+ gtk_editable_set_position (GTK_EDITABLE (fs->selection_entry), -1);
if (fs->selection_entry)
{
/* A common case is selecting a range of files from top to bottom,
* so quickly check for that to avoid looping over the entire list
*/
- if (compare_filenames (g_ptr_array_index (old_names, old_names->len - 1),
- g_ptr_array_index (new_names, new_names->len - 1)) != 0)
+ if (compare_utf8_filenames (g_ptr_array_index (old_names, old_names->len - 1),
+ g_ptr_array_index (new_names, new_names->len - 1)) != 0)
index = new_names->len - 1;
else
{
*/
while (i < old_names->len && j < new_names->len)
{
- cmp = compare_filenames (g_ptr_array_index (old_names, i),
- g_ptr_array_index (new_names, j));
+ cmp = compare_utf8_filenames (g_ptr_array_index (old_names, i),
+ g_ptr_array_index (new_names, j));
if (cmp < 0)
{
i++;
* So search up from there.
*/
if (fs->last_selected &&
- compare_filenames (fs->last_selected,
- g_ptr_array_index (new_names, 0)) == 0)
+ compare_utf8_filenames (fs->last_selected,
+ g_ptr_array_index (new_names, 0)) == 0)
index = new_names->len - 1;
else
index = 0;
entry = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
if ((entry != NULL) && (fs->last_selected != NULL) &&
- (compare_filenames (entry, fs->last_selected) == 0))
+ (compare_utf8_filenames (entry, fs->last_selected) == 0))
gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");
}
selections[count++] = current;
- if (unselected_entry && compare_filenames (current, filename) == 0)
+ if (unselected_entry && compare_sys_filenames (current, filename) == 0)
unselected_entry = FALSE;
}
return cmpl_state->reference_dir->fullname;
}
+#if 0
+/* This doesn't work currently and would require changes
+ * to fnmatch.c to get working.
+ */
static gint
cmpl_last_valid_char (CompletionState *cmpl_state)
{
return cmpl_state->last_valid_char;
}
+#endif
-static const gchar*
+static gchar*
cmpl_completion_fullname (const gchar *text,
CompletionState *cmpl_state)
{
- static const char nothing[2] = "";
-
if (!cmpl_state_okay (cmpl_state))
{
- return nothing;
+ return g_strdup ("");
}
else if (g_path_is_absolute (text))
{
- strcpy (cmpl_state->updated_text, text);
+ return g_strdup (text);
}
#ifdef HAVE_PWD_H
else if (text[0] == '~')
dir = open_user_dir (text, cmpl_state);
- if (!dir)
+ if (dir)
{
- /* spencer says just return ~something, so
- * for now just do it. */
- strcpy (cmpl_state->updated_text, text);
- }
- else
- {
-
- strcpy (cmpl_state->updated_text, dir->fullname);
-
slash = strchr (text, G_DIR_SEPARATOR);
-
- if (slash)
- strcat (cmpl_state->updated_text, slash);
+
+ /* slash may be NULL, that works too */
+ return g_strconcat (dir->fullname, slash, NULL);
}
}
#endif
- else
- {
- strcpy (cmpl_state->updated_text, cmpl_state->reference_dir->fullname);
- if (cmpl_state->updated_text[strlen (cmpl_state->updated_text) - 1] != G_DIR_SEPARATOR)
- strcat (cmpl_state->updated_text, G_DIR_SEPARATOR_S);
- strcat (cmpl_state->updated_text, text);
- }
-
- return cmpl_state->updated_text;
+
+ return g_build_filename (cmpl_state->reference_dir->fullname,
+ text,
+ NULL);
}
/* The three completion selectors
/* Construction, deletion */
/**********************************************************************/
+/* Get the nearest parent of the current directory for which
+ * we can convert the filename into UTF-8. With paranoia.
+ * Returns "." when all goes wrong.
+ */
+static gchar *
+get_current_dir_utf8 (void)
+{
+ gchar *dir = g_get_current_dir ();
+ gchar *dir_utf8 = NULL;
+
+ while (TRUE)
+ {
+ gchar *last_slash;
+
+ dir_utf8 = g_filename_to_utf8 (dir, -1, NULL, NULL, NULL);
+ if (dir_utf8)
+ break;
+
+ last_slash = strrchr (dir, G_DIR_SEPARATOR);
+ if (!last_slash) /* g_get_current_dir() wasn't absolute! */
+ break;
+
+ if (last_slash + 1 == g_path_skip_root (dir)) /* Parent directory is a root directory */
+ {
+ if (last_slash[1] == '\0') /* Root misencoded! */
+ break;
+ else
+ last_slash[1] = '\0';
+ }
+ else
+ last_slash[0] = '\0';
+
+ g_assert (last_slash);
+ }
+
+ g_free (dir);
+
+ return dir_utf8 ? dir_utf8 : g_strdup (".");
+}
+
static CompletionState*
cmpl_init_state (void)
{
- gchar *sys_getcwd_buf;
gchar *utf8_cwd;
CompletionState *new_state;
new_state = g_new (CompletionState, 1);
- /* g_get_current_dir() returns a string in the "system" charset */
- sys_getcwd_buf = g_get_current_dir ();
- utf8_cwd = g_filename_to_utf8 (sys_getcwd_buf, -1, NULL, NULL, NULL);
- g_free (sys_getcwd_buf);
+ utf8_cwd = get_current_dir_utf8 ();
tryagain:
gchar **remaining_text,
CompletionState *cmpl_state)
{
+#ifdef HAVE_PWD_H
gchar* first_slash;
+#endif
PossibleCompletion *poss;
prune_memory_usage (cmpl_state);
p = strrchr (tmp, G_DIR_SEPARATOR);
if (p)
{
- if (p == tmp)
+ if (p + 1 == g_path_skip_root (tmp))
p++;
*p = '\0';
-
new_dir = open_dir (tmp, cmpl_state);
if (new_dir)
*remaining_text = text_to_complete +
- ((p == tmp + 1) ? (p - tmp) : (p + 1 - tmp));
+ ((p == g_path_skip_root (tmp)) ? (p - tmp) : (p + 1 - tmp));
}
else
{
/* If no possible candidates, use the cwd */
- gchar *sys_curdir = g_get_current_dir ();
- gchar *utf8_curdir = g_filename_to_utf8 (sys_curdir, -1, NULL, NULL, NULL);
-
- g_free (sys_curdir);
+ gchar *utf8_curdir = get_current_dir_utf8 ();
new_dir = open_dir (utf8_curdir, cmpl_state);
gchar *sys_dir_name;
sent = g_new (CompletionDirSent, 1);
+#ifndef G_PLATFORM_WIN32
sent->mtime = sbuf->st_mtime;
sent->inode = sbuf->st_ino;
sent->device = sbuf->st_dev;
-
+#endif
path = g_string_sized_new (2*MAXPATHLEN + 10);
sys_dir_name = g_filename_from_utf8 (dir_name, -1, NULL, NULL, NULL);
while ((dirent = g_dir_read_name (directory)) != NULL)
entry_count++;
-
entry_count += 2; /* For ".",".." */
sent->entries = g_new (CompletionDirEntry, entry_count);
|| !g_utf8_validate (sent->entries[n_entries].entry_name, -1, NULL))
{
gchar *escaped_str = g_strescape (dirent, NULL);
- g_message (_("The filename \"%s\" couldn't be converted to UTF-8 "
- "(try setting the environment variable G_BROKEN_FILENAMES): %s"),
+ g_message (_("The filename \"%s\" couldn't be converted to UTF-8. "
+ "(try setting the environment variable G_FILENAME_ENCODING): %s"),
escaped_str,
- error->message ? error->message : _("Invalid Utf-8"));
+ error->message ? error->message : _("Invalid UTF-8"));
g_free (escaped_str);
g_clear_error (&error);
continue;
return sent;
}
-#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
+#ifndef G_PLATFORM_WIN32
static gboolean
check_dir (gchar *dir_name,
open_dir (gchar *dir_name,
CompletionState *cmpl_state)
{
+#ifndef G_PLATFORM_WIN32
struct stat sbuf;
gboolean stat_subdirs;
- CompletionDirSent *sent;
GList* cdsl;
+#endif
+ CompletionDirSent *sent;
-#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
+#ifndef G_PLATFORM_WIN32
if (!check_dir (dir_name, &sbuf, &stat_subdirs))
return NULL;
cdsl = cdsl->next;
}
-#else
- stat_subdirs = TRUE;
-#endif
sent = open_new_dir (dir_name, &sbuf, stat_subdirs);
+#else
+ sent = open_new_dir (dir_name, NULL, TRUE);
+#endif
if (sent)
{
struct stat parbuf;
gchar *last_slash;
gchar *first_slash;
+#ifndef G_PLATFORM_WIN32
gchar *new_name;
+#endif
gchar *sys_filename;
gchar c = 0;
}
g_free (sys_filename);
-#ifndef G_OS_WIN32 /* No inode numbers on Win32 */
+#ifndef G_PLATFORM_WIN32 /* No inode numbers on Win32 */
if (parbuf.st_ino == sbuf->st_ino && parbuf.st_dev == sbuf->st_dev)
/* it wasn't a link */
return TRUE;
return TRUE;
}
-#ifndef G_OS_WIN32
+#ifndef G_PLATFORM_WIN32
static gchar*
find_parent_dir_fullname (gchar* dirname)
#endif
-#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
+#ifdef G_PLATFORM_WIN32
+/* FIXME: determine whether we should casefold all Unicode letters
+ * here, too (and in in first_diff_index() walk through the strings with
+ * g_utf8_next_char()), or if this folding isn't actually needed at
+ * all.
+ */
#define FOLD(c) (tolower(c))
#else
#define FOLD(c) (c)
for (i = 0; i < dir->sent->entry_count; i += 1)
{
if (dir->sent->entries[i].is_dir &&
- _gtk_fnmatch (pat_buf, dir->sent->entries[i].entry_name))
+ _gtk_fnmatch (pat_buf, dir->sent->entries[i].entry_name, TRUE))
{
if (found)
{
if (cmpl_state->updated_text_alloc < cmpl_len + 1)
{
+ cmpl_state->updated_text_alloc = 2*cmpl_len;
cmpl_state->updated_text =
(gchar*)g_realloc (cmpl_state->updated_text,
cmpl_state->updated_text_alloc);
- cmpl_state->updated_text_alloc = 2*cmpl_len;
}
if (cmpl_state->updated_text_len < 0)
{
if (dir->sent->entries[dir->cmpl_index].is_dir)
{
- if (_gtk_fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name))
+ if (_gtk_fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name, TRUE))
{
CompletionDir* new_dir;
append_completion_text (dir->sent->entries[dir->cmpl_index].entry_name, cmpl_state);
cmpl_state->the_completion.is_a_completion =
- _gtk_fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name);
+ _gtk_fnmatch (pat_buf, dir->sent->entries[dir->cmpl_index].entry_name, TRUE);
cmpl_state->the_completion.is_directory = dir->sent->entries[dir->cmpl_index].is_dir;
if (dir->sent->entries[dir->cmpl_index].is_dir)