diff --git a/ChangeLog b/ChangeLog index 5e4d28355..9dc395872 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,11 @@ (inspired by a patch from Yura Siamashka). * src/plugindata.h, src/plugins.c: Add document_set_text_changed() to the plugin API. + * src/main.c, src/utils.c, src/utils.h, src/win32.c, src/win32.h: + Fix crashes on Windows when configuration directory could not be + created. + Fix problems when configuration directory path contains special + characters. 2007-11-02 Nick Treleaven diff --git a/src/main.c b/src/main.c index 75a45c580..24c855877 100644 --- a/src/main.c +++ b/src/main.c @@ -500,7 +500,7 @@ static gint setup_config_dir() app->configdir = utils_get_locale_from_utf8(app->configdir); g_free(tmp); - mkdir_result = utils_make_settings_dir(app->configdir, app->datadir, app->docdir); + mkdir_result = utils_make_settings_dir(); if (mkdir_result != 0) { if (! dialogs_show_question( diff --git a/src/utils.c b/src/utils.c index 838c2ccd9..6bdff5d52 100644 --- a/src/utils.c +++ b/src/utils.c @@ -727,26 +727,33 @@ gchar *utils_get_hostname() } -gint utils_make_settings_dir(const gchar *dir, const gchar *data_dir, const gchar *doc_dir) +gint utils_make_settings_dir() { - gint error_nr = 0; + gint saved_errno = 0; gchar *conf_file = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "geany.conf", NULL); - gchar *filedefs_dir = g_strconcat(dir, G_DIR_SEPARATOR_S, + gchar *filedefs_dir = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, GEANY_FILEDEFS_SUBDIR, G_DIR_SEPARATOR_S, NULL); - gchar *templates_dir = g_strconcat(dir, G_DIR_SEPARATOR_S, + gchar *templates_dir = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, GEANY_TEMPLATES_SUBDIR, G_DIR_SEPARATOR_S, NULL); - if (! g_file_test(dir, G_FILE_TEST_EXISTS)) + if (! g_file_test(app->configdir, G_FILE_TEST_EXISTS)) { - geany_debug("creating config directory %s", dir); - error_nr = utils_mkdir(dir, FALSE); + geany_debug("creating config directory %s", app->configdir); + saved_errno = utils_mkdir(app->configdir, FALSE); } - if (error_nr == 0 && ! g_file_test(conf_file, G_FILE_TEST_EXISTS)) - { // try to write geany.conf - error_nr = access(app->configdir, W_OK); + if (saved_errno == 0 && ! g_file_test(conf_file, G_FILE_TEST_EXISTS)) + { // check whether geany.conf can be written +#ifdef G_OS_WIN32 + // use _waccess on Windows, access() doesn't accept special characters + saved_errno = win32_check_write_permission(app->configdir); +#else + access(app->configdir, R_OK | W_OK); +#endif + saved_errno = errno; } + #ifdef G_OS_WIN32 # define DIR_SEP "\\" // on Windows we need an additional dir separator #else @@ -754,21 +761,21 @@ gint utils_make_settings_dir(const gchar *dir, const gchar *data_dir, const gcha #endif // make subdir for filetype definitions - if (error_nr == 0) + if (saved_errno == 0) { - gchar *filedefs_readme = g_strconcat(dir, G_DIR_SEPARATOR_S, GEANY_FILEDEFS_SUBDIR, - G_DIR_SEPARATOR_S, "filetypes.README", NULL); + gchar *filedefs_readme = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, + GEANY_FILEDEFS_SUBDIR, G_DIR_SEPARATOR_S, "filetypes.README", NULL); if (! g_file_test(filedefs_dir, G_FILE_TEST_EXISTS)) { - error_nr = utils_mkdir(filedefs_dir, FALSE); + saved_errno = utils_mkdir(filedefs_dir, FALSE); } - if (error_nr == 0 && ! g_file_test(filedefs_readme, G_FILE_TEST_EXISTS)) + if (saved_errno == 0 && ! g_file_test(filedefs_readme, G_FILE_TEST_EXISTS)) { gchar *text = g_strconcat( -"Copy files from ", data_dir, " to this directory to overwrite " +"Copy files from ", app->datadir, " to this directory to overwrite " "them. To use the defaults, just delete the file in this directory.\nFor more information read " -"the documentation (in ", doc_dir, DIR_SEP "index.html or visit " GEANY_HOMEPAGE ").", NULL); +"the documentation (in ", app->docdir, DIR_SEP "index.html or visit " GEANY_HOMEPAGE ").", NULL); utils_write_file(filedefs_readme, text); g_free(text); } @@ -776,20 +783,20 @@ gint utils_make_settings_dir(const gchar *dir, const gchar *data_dir, const gcha } // make subdir for template files - if (error_nr == 0) + if (saved_errno == 0) { - gchar *templates_readme = g_strconcat(dir, G_DIR_SEPARATOR_S, GEANY_TEMPLATES_SUBDIR, - G_DIR_SEPARATOR_S, "templates.README", NULL); + gchar *templates_readme = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, + GEANY_TEMPLATES_SUBDIR, G_DIR_SEPARATOR_S, "templates.README", NULL); if (! g_file_test(templates_dir, G_FILE_TEST_EXISTS)) { - error_nr = utils_mkdir(templates_dir, FALSE); + saved_errno = utils_mkdir(templates_dir, FALSE); } - if (error_nr == 0 && ! g_file_test(templates_readme, G_FILE_TEST_EXISTS)) + if (saved_errno == 0 && ! g_file_test(templates_readme, G_FILE_TEST_EXISTS)) { gchar *text = g_strconcat( "There are several template files in this directory. For these templates you can use wildcards.\n\ -For more information read the documentation (in ", doc_dir, DIR_SEP "index.html or visit " GEANY_HOMEPAGE ").", +For more information read the documentation (in ", app->docdir, DIR_SEP "index.html or visit " GEANY_HOMEPAGE ").", NULL); utils_write_file(templates_readme, text); g_free(text); @@ -801,7 +808,7 @@ For more information read the documentation (in ", doc_dir, DIR_SEP "index.html g_free(templates_dir); g_free(conf_file); - return error_nr; + return saved_errno; } diff --git a/src/utils.h b/src/utils.h index 71a3e89dd..323cc4be4 100644 --- a/src/utils.h +++ b/src/utils.h @@ -97,7 +97,7 @@ gchar utils_brace_opposite(gchar ch); gchar *utils_get_hostname(); -gint utils_make_settings_dir(const gchar *dir, const gchar *data_dir, const gchar *doc_dir); +gint utils_make_settings_dir(); gboolean utils_string_replace_all(GString *str, const gchar *needle, const gchar *replace); diff --git a/src/win32.c b/src/win32.c index f13aadfa9..16acbc9dd 100644 --- a/src/win32.c +++ b/src/win32.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -492,6 +493,7 @@ gboolean win32_message_dialog(GtkWidget *parent, GtkMessageType type, const gcha gint rc; guint t; const gchar *title; + HWND parent_hwnd = NULL; static wchar_t w_msg[512]; static wchar_t w_title[512]; @@ -528,11 +530,13 @@ gboolean win32_message_dialog(GtkWidget *parent, GtkMessageType type, const gcha MultiByteToWideChar(CP_UTF8, 0, msg, -1, w_msg, G_N_ELEMENTS(w_msg)); MultiByteToWideChar(CP_UTF8, 0, title, -1, w_title, G_N_ELEMENTS(w_title)); - // display the message box - if (parent == NULL) - parent = app->window; + if (parent != NULL) + parent_hwnd = GDK_WINDOW_HWND(parent->window); + else if (app->window != NULL) + parent_hwnd = GDK_WINDOW_HWND(app->window->window); - rc = MessageBoxW(GDK_WINDOW_HWND(parent->window), w_msg, w_title, t); + // display the message box + rc = MessageBoxW(parent_hwnd, w_msg, w_title, t); if (type == GTK_MESSAGE_QUESTION && rc != IDYES) ret = FALSE; @@ -541,18 +545,32 @@ gboolean win32_message_dialog(GtkWidget *parent, GtkMessageType type, const gcha } +/* Little wrapper for _waccess(), returns errno or 0 if there was no error */ +gint win32_check_write_permission(const gchar *dir) +{ + static wchar_t w_dir[512]; + MultiByteToWideChar(CP_UTF8, 0, app->configdir, -1, w_dir, sizeof w_dir); + _waccess(w_dir, R_OK | W_OK); + return errno; +} + + /* Special dialog to ask for an action when closing an unsaved file */ gint win32_message_dialog_unsaved(const gchar *msg) { static wchar_t w_msg[512]; static wchar_t w_title[512]; + HWND parent_hwnd = NULL; gint ret; // convert the Unicode chars to wide chars MultiByteToWideChar(CP_UTF8, 0, msg, -1, w_msg, G_N_ELEMENTS(w_msg)); MultiByteToWideChar(CP_UTF8, 0, _("Question"), -1, w_title, G_N_ELEMENTS(w_title)); - ret = MessageBoxW(GDK_WINDOW_HWND(app->window->window), w_msg, w_title, MB_YESNOCANCEL | MB_ICONQUESTION); + if (app->window != NULL) + parent_hwnd = GDK_WINDOW_HWND(app->window->window); + + ret = MessageBoxW(parent_hwnd, w_msg, w_title, MB_YESNOCANCEL | MB_ICONQUESTION); switch(ret) { case IDYES: ret = GTK_RESPONSE_YES; break; diff --git a/src/win32.h b/src/win32.h index e8430f009..a1ec28f65 100644 --- a/src/win32.h +++ b/src/win32.h @@ -53,4 +53,6 @@ gchar *win32_show_project_open_dialog(const gchar *title, const gchar *initial_d * The selected folder name is returned. */ gchar *win32_show_project_folder_dialog(const gchar *title, const gchar *initial_dir); +gint win32_check_write_permission(const gchar *dir); + #endif