return NULL;
}
-gchar *filesel_select_file_open(const gchar *title, const gchar *path)
+/* This function handles calling GetOpenFilename(), using
+ * global static variable o.
+ * It expects o.lpstrFile to point to an already allocated buffer,
+ * of size at least MAXPATHLEN. */
+static const gboolean _file_open_dialog(const gchar *path, const gchar *title,
+ const gchar *filter, const gboolean multi)
{
gboolean ret;
- gchar *str;
- gunichar2 *path16, *title16;
- glong conv_items;
+ gunichar2 *path16 = NULL;
+ gunichar2 *title16 = NULL;
+ gunichar2 *filter16 = NULL;
+ gunichar2 *win_filter16 = NULL;
+ glong conv_items, sz;
GError *error = NULL;
WinChooserCtx *ctx;
#ifdef USE_PTHREAD
/* Path needs to be converted to UTF-16, so that the native chooser
* can understand it. */
- path16 = g_utf8_to_utf16(path, -1, NULL, &conv_items, &error);
+ path16 = g_utf8_to_utf16(path ? path : "",
+ -1, NULL, NULL, &error);
if (error != NULL) {
alertpanel_error(_("Could not convert file path to UTF-16:\n\n%s"),
error->message);
debug_print("file path '%s' conversion to UTF-16 failed\n", path);
g_error_free(error);
- return NULL;
+ error = NULL;
+ return FALSE;
}
/* Chooser dialog title needs to be UTF-16 as well. */
- title16 = g_utf8_to_utf16(title, -1, NULL, NULL, &error);
+ title16 = g_utf8_to_utf16(title ? title : "",
+ -1, NULL, NULL, &error);
if (error != NULL) {
debug_print("dialog title '%s' conversion to UTF-16 failed\n", title);
g_error_free(error);
+ error = NULL;
}
o.lStructSize = sizeof(OPENFILENAME);
o.lpstrFilter = NULL;
o.lpstrCustomFilter = NULL;
o.nFilterIndex = 0;
- o.lpstrFile = g_malloc0(MAXPATHLEN);
o.nMaxFile = MAXPATHLEN;
o.lpstrFileTitle = NULL;
o.lpstrInitialDir = path16;
o.lpstrTitle = title16;
- o.Flags = OFN_LONGNAMES;
-
- ctx = g_new0(WinChooserCtx, 1);
- ctx->data = &o;
- ctx->done = FALSE;
-
-#ifdef USE_PTHREAD
- if (pthread_create(&pt, PTHREAD_CREATE_JOINABLE, threaded_GetOpenFileName,
- (void *)ctx) != 0) {
- debug_print("Couldn't run in a thread, continuing unthreaded.\n");
- threaded_GetOpenFileName(ctx);
- } else {
- while (!ctx->done) {
- claws_do_idle();
- }
- pthread_join(pt, NULL);
- }
- ret = ctx->return_value;
-#else
- debug_print("No threads available, continuing unthreaded.\n");
- ret = GetOpenFileName(&o);
-#endif
-
- g_free(path16);
- g_free(title16);
- g_free(ctx);
-
- if (!ret) {
- g_free(o.lpstrFile);
- return NULL;
- }
-
- /* Now convert the returned file path back from UTF-16. */
- str = g_utf16_to_utf8(o.lpstrFile, o.nMaxFile, NULL, NULL, &error);
- if (error != NULL) {
- alertpanel_error(_("Could not convert file path back to UTF-8:\n\n%s"),
- error->message);
- debug_print("returned file path conversion to UTF-8 failed\n");
- g_error_free(error);
- }
-
- g_free(o.lpstrFile);
- return str;
-}
-
-/* TODO: Allow selecting of multiple files with OFN_ALLOWMULTISELECT
- * flag and parsing the long string with returned file names. */
-GList *filesel_select_multiple_files_open(const gchar *title)
-{
- GList *file_list = NULL;
- gchar *ret = filesel_select_file_open(title, NULL);
-
- if (ret != NULL)
- file_list = g_list_append(file_list, ret);
-
- return file_list;
-}
-
-gchar *filesel_select_file_open_with_filter(const gchar *title, const gchar *path,
- const gchar *filter)
-{
- gboolean ret;
- gchar *str;
- gchar *win_filter16 = NULL;
- gunichar2 *path16, *title16, *filter16;
- glong conv_items;
- guint sz;
- GError *error = NULL;
- WinChooserCtx *ctx;
-#ifdef USE_PTHREAD
- pthread_t pt;
-#endif
-
- /* Path needs to be converted to UTF-16, so that the native chooser
- * can understand it. */
- path16 = g_utf8_to_utf16(path, -1, NULL, NULL, &error);
- if (error != NULL) {
- alertpanel_error(_("Could not convert file path to UTF-16:\n\n%s"),
- error->message);
- debug_print("file path '%s' conversion to UTF-16 failed\n", path);
- g_error_free(error);
- return NULL;
- }
-
- /* Chooser dialog title needs to be UTF-16 as well. */
- title16 = g_utf8_to_utf16(title, -1, NULL, NULL, &error);
- if (error != NULL) {
- debug_print("dialog title '%s' conversion to UTF-16 failed\n", title);
- g_error_free(error);
- }
-
- o.lStructSize = sizeof(OPENFILENAME);
- if (focus_window != NULL)
- o.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(focus_window));
+ if (multi)
+ o.Flags = OFN_LONGNAMES | OFN_EXPLORER | OFN_ALLOWMULTISELECT;
else
- o.hwndOwner = NULL;
- o.lpstrFilter = NULL;
- o.lpstrCustomFilter = NULL;
- o.nFilterIndex = 0;
- o.lpstrFile = g_malloc0(MAXPATHLEN);
- o.nMaxFile = MAXPATHLEN;
- o.lpstrFileTitle = NULL;
- o.lpstrInitialDir = path16;
- o.lpstrTitle = title16;
- o.Flags = OFN_LONGNAMES;
+ o.Flags = OFN_LONGNAMES | OFN_EXPLORER;
if (filter != NULL && strlen(filter) > 0) {
debug_print("Setting filter '%s'\n", filter);
if (error != NULL) {
debug_print("dialog title '%s' conversion to UTF-16 failed\n", title);
g_error_free(error);
+ error = NULL;
}
o.lpstrFilter = (LPCTSTR)win_filter16;
o.nFilterIndex = 1;
#endif
g_free(win_filter16);
- g_free(path16);
+ if (path16 != NULL) {
+ g_free(path16);
+ }
g_free(title16);
g_free(ctx);
- if (!ret) {
+ return ret;
+}
+
+gchar *filesel_select_file_open_with_filter(const gchar *title, const gchar *path,
+ const gchar *filter)
+{
+ gchar *str = NULL;
+ GError *error = NULL;
+
+ o.lpstrFile = g_malloc0(MAXPATHLEN);
+ if (!_file_open_dialog(path, title, filter, FALSE)) {
g_free(o.lpstrFile);
return NULL;
}
return str;
}
-/* TODO: Allow selecting of multiple files with OFN_ALLOWMULTISELECT
- * flag and parsing the long string with returned file names. */
GList *filesel_select_multiple_files_open_with_filter(const gchar *title,
const gchar *path, const gchar *filter)
{
GList *file_list = NULL;
- gchar *ret = filesel_select_file_open_with_filter(title, path, filter);
+ gchar *str = NULL;
+ gchar *dir = NULL;
+ gunichar2 *f;
+ GError *error = NULL;
+ glong n, items_read;
+
+ o.lpstrFile = g_malloc0(MAXPATHLEN);
+ if (!_file_open_dialog(path, title, filter, TRUE)) {
+ g_free(o.lpstrFile);
+ return NULL;
+ }
+
+ /* Now convert the returned directory and file names back from UTF-16.
+ * The content of o.lpstrFile is:
+ * "directory0file0file0...0file00" for multiple files selected,
+ * "fullfilepath0" for single file. */
+ str = g_utf16_to_utf8(o.lpstrFile, -1, &items_read, NULL, &error);
+ g_free(o.lpstrFile);
+
+ if (error != NULL) {
+ alertpanel_error(_("Could not convert file path back to UTF-8:\n\n%s"),
+ error->message);
+ debug_print("returned file path conversion to UTF-8 failed\n");
+ g_error_free(error);
+ return NULL;
+ }
+
+ /* The part before the first null char is always a full path. If it is
+ * a path to a file, then only this one file has been selected,
+ * and we can bail out early. */
+ if (g_file_test(str, G_FILE_TEST_IS_REGULAR)) {
+ debug_print("Selected one file: '%s'\n", str);
+ file_list = g_list_append(file_list, g_strdup(str));
+ g_free(str);
+ return file_list;
+ }
+
+ /* So the path was to a directory. We need to parse more after
+ * the fist null char, until we get to two null chars in a row. */
+ dir = g_strdup(str);
+ g_free(str);
+ debug_print("Selected multiple files in dir '%s'\n", dir);
+
+ n = items_read + 1;
+ f = &o.lpstrFile[n];
+ while (items_read > 0) {
+ str = g_utf16_to_utf8(f, -1, &items_read, NULL, &error);
+ if (error != NULL) {
+ alertpanel_error(_("Could not convert file path back to UTF-8:\n\n%s"),
+ error->message);
+ debug_print("returned file path conversion to UTF-8 failed\n");
+ g_error_free(error);
+ return NULL;
+ }
+
+ if (items_read > 0) {
+ debug_print("selected file '%s'\n", str);
+ file_list = g_list_append(file_list,
+ g_strconcat(dir, G_DIR_SEPARATOR_S, str, NULL));
+ }
+
+ n += items_read + 1;
+ f = &o.lpstrFile[n];
+ }
+
+
+
- if (ret != NULL)
- file_list = g_list_append(file_list, ret);
return file_list;
}
+gchar *filesel_select_file_open(const gchar *title, const gchar *path)
+{
+ return filesel_select_file_open_with_filter(title, path, NULL);
+}
+
+GList *filesel_select_multiple_files_open(const gchar *title, const gchar *path)
+{
+ return filesel_select_multiple_files_open_with_filter(title, path, NULL);
+}
+
gchar *filesel_select_file_save(const gchar *title, const gchar *path)
{
gboolean ret;
#endif
/* Find the filename part, if any */
- if (path[strlen(path)-1] == G_DIR_SEPARATOR) {
+ if (path == NULL || path[strlen(path)-1] == G_DIR_SEPARATOR) {
filename = "";
} else if ((filename = strrchr(path, G_DIR_SEPARATOR)) != NULL) {
filename++;
o.lpstrFileTitle = NULL;
o.lpstrInitialDir = path16;
o.lpstrTitle = title16;
- o.Flags = OFN_LONGNAMES;
+ o.Flags = OFN_LONGNAMES | OFN_EXPLORER;
ctx = g_new0(WinChooserCtx, 1);
ctx->data = &o;
/* Path needs to be converted to UTF-16, so that the native chooser
* can understand it. */
- path16 = g_utf8_to_utf16(path, -1, NULL, &conv_items, &error);
+ path16 = g_utf8_to_utf16(path ? path : "",
+ -1, NULL, &conv_items, &error);
if (error != NULL) {
alertpanel_error(_("Could not convert file path to UTF-16:\n\n%s"),
error->message);
}
/* Chooser dialog title needs to be UTF-16 as well. */
- title16 = g_utf8_to_utf16(title, -1, NULL, NULL, &error);
+ title16 = g_utf8_to_utf16(title ? title : "",
+ -1, NULL, NULL, &error);
if (error != NULL) {
debug_print("dialog title '%s' conversion to UTF-16 failed\n", title);
g_error_free(error);