Branch: refs/heads/master Author: Enrico Tröger enrico.troeger@uvena.de Committer: Enrico Tröger enrico.troeger@uvena.de Date: Sun, 13 Nov 2016 13:55:40 UTC Commit: 26adcabd694014328f61b3ca5fe0d5be610849c0 https://github.com/geany/geany/commit/26adcabd694014328f61b3ca5fe0d5be610849...
Log Message: ----------- Windows: Convert generated batch script into system codepage
Instead of fiddling with the "chcp" command in the generated batch script on Windows, convert the whole script content into the system codepage before executing it.
Modified Paths: -------------- src/build.c src/spawn.c src/win32.c src/win32.h
Modified: src/build.c 15 lines changed, 8 insertions(+), 7 deletions(-) =================================================================== @@ -1070,7 +1070,7 @@ static gchar *build_create_shellscript(const gchar *working_dir, const gchar *cm gboolean success = TRUE; #ifdef G_OS_WIN32 gchar *expanded_cmd; - guint codepage; + gchar *utf8_script_content; #else gchar *escaped_dir; #endif @@ -1080,16 +1080,17 @@ static gchar *build_create_shellscript(const gchar *working_dir, const gchar *cm close(fd);
#ifdef G_OS_WIN32 - /* We set the console codepage to UTF-8 (65001) before changing the working directory - * because the working directory is in UTF-8 encoding. - * Then we reset it again to the default value before executing the command. */ - codepage = win32_get_console_codepage(); /* Expand environment variables like %blah%. */ expanded_cmd = win32_expand_environment_variables(cmd); str = g_strdup_printf( - "chcp 65001 > nul\ncd "%s"\nchcp %u > nul\n\n%s\n\n%s\ndel "%%0"\n\npause\n", - working_dir, codepage, expanded_cmd, (autoclose) ? "" : "pause"); + "cd "%s"\n\n\n%s\n\n%s\ndel "%%0"\n\npause\n", + working_dir, expanded_cmd, (autoclose) ? "" : "pause"); g_free(expanded_cmd); + /* Convert script content into system codepage */ + utf8_script_content = win32_convert_to_system_codepage(str, error); + if (utf8_script_content == NULL) + return NULL; + SETPTR(str, utf8_script_content); #else escaped_dir = g_shell_quote(working_dir); str = g_strdup_printf(
Modified: src/spawn.c 129 lines changed, 80 insertions(+), 49 deletions(-) =================================================================== @@ -522,10 +522,9 @@ static gboolean spawn_async_with_pipes(const gchar *working_directory, const gch #ifdef G_OS_WIN32 GString *command; GArray *environment; - GError *gerror = NULL; - gchar *locale_working_directory; - gchar *locale_command; - gchar *failure; + gchar *locale_working_directory = NULL; + gchar *locale_command = NULL; + gboolean success = TRUE;
if (command_line) { @@ -565,67 +564,99 @@ static gboolean spawn_async_with_pipes(const gchar *working_directory, const gch g_message("full spawn command line: %s", command->str); #endif
- while (envp && *envp) + while (envp && *envp && success) { - g_array_append_vals(environment, *envp, strlen(*envp) + 1); + gsize locale_entry_len; + gchar *locale_entry; + + if (g_utf8_validate(*envp, -1, NULL)) + { + /* TODO: better error message */ + locale_entry = g_locale_from_utf8(*envp, -1, NULL, &locale_entry_len, error); + } + else + { + locale_entry_len = strlen(*envp); + locale_entry = g_memdup(*envp, locale_entry_len + 1); + } + + if (! locale_entry) + success = FALSE; + else + { + /* copy the entry, including NUL terminator */ + g_array_append_vals(environment, locale_entry, locale_entry_len + 1); + g_free(locale_entry); + } + envp++; }
- // convert working directory into locale encoding - if (g_utf8_validate(working_directory, -1, NULL)) + /* convert working directory into locale encoding */ + if (success && working_directory) { - locale_working_directory = g_locale_from_utf8(working_directory, -1, NULL, NULL, &gerror); - if (gerror) { - /* TODO use the code below post-1.28 as it introduces a new string - gchar *msg = g_strdup_printf( - _("Failed to convert working directory into locale encoding: %s"), gerror->message); - g_set_error_literal(error, gerror->domain, gerror->code, msg); - */ - g_set_error_literal(error, gerror->domain, gerror->code, gerror->message); - g_error_free(gerror); - g_string_free(command, TRUE); - g_array_free(environment, TRUE); - g_free(locale_working_directory); - /*g_free(msg);*/ - return FALSE; + if (g_utf8_validate(working_directory, -1, NULL)) + { + GError *gerror = NULL; + + locale_working_directory = g_locale_from_utf8(working_directory, -1, NULL, NULL, &gerror); + if (! locale_working_directory) + { + /* TODO use the code below post-1.28 as it introduces a new string + g_set_error(error, gerror->domain, gerror->code, + _("Failed to convert working directory into locale encoding: %s"), gerror->message); + */ + g_propagate_error(error, gerror); + success = FALSE; + } } + else + locale_working_directory = g_strdup(working_directory); } - // convert command into locale encoding - if (g_utf8_validate(command->str, -1, NULL)) + /* convert command into locale encoding */ + if (success) { - locale_command = g_locale_from_utf8(command->str, -1, NULL, NULL, &gerror); - if (gerror) { - /* TODO use the code below post-1.28 as it introduces a new string - gchar *msg = g_strdup_printf( - _("Failed to convert command into locale encoding: %s"), gerror->message); - g_set_error_literal(error, gerror->domain, gerror->code, msg); - */ - g_set_error_literal(error, gerror->domain, gerror->code, gerror->message); - g_error_free(gerror); - g_string_free(command, TRUE); - g_array_free(environment, TRUE); - g_free(locale_working_directory); - g_free(locale_command); - /*g_free(msg);*/ - return FALSE; + if (g_utf8_validate(command->str, -1, NULL)) + { + GError *gerror = NULL; + + locale_command = g_locale_from_utf8(command->str, -1, NULL, NULL, &gerror); + if (! locale_command) + { + /* TODO use the code below post-1.28 as it introduces a new string + g_set_error(error, gerror->domain, gerror->code, + _("Failed to convert command into locale encoding: %s"), gerror->message); + */ + g_propagate_error(error, gerror); + success = FALSE; + } + } + else + locale_command = g_strdup(command->str); + } + + if (success) + { + gchar *failure; + + failure = spawn_create_process_with_pipes(locale_command, locale_working_directory, + envp ? environment->data : NULL, child_pid, stdin_fd, stdout_fd, stderr_fd); + + if (failure) + { + g_set_error_literal(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, failure); + g_free(failure); } + + success = failure == NULL; } - failure = spawn_create_process_with_pipes(locale_command, locale_working_directory, - envp ? environment->data : NULL, child_pid, stdin_fd, stdout_fd, stderr_fd);
g_string_free(command, TRUE); g_array_free(environment, TRUE); g_free(locale_working_directory); g_free(locale_command);
- if (failure) - { - g_set_error_literal(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, failure); - g_free(failure); - return FALSE; - } - - return TRUE; + return success; #else /* G_OS_WIN32 */ int cl_argc; char **full_argv;
Modified: src/win32.c 22 lines changed, 20 insertions(+), 2 deletions(-) =================================================================== @@ -1034,14 +1034,32 @@ gchar *win32_get_user_config_dir(void)
/* Retrieve the console codepage - * In case GetConsoleOutputCP() returns 0 (i.e. the application doesn't have an own console window + * In case GetConsoleCP() returns 0 (i.e. the application doesn't have an own console window * fallback to GetOEMCP(). */ guint win32_get_console_codepage(void) { - guint codepage = GetConsoleOutputCP(); + guint codepage = GetConsoleCP(); if (codepage == 0) codepage = GetOEMCP(); return codepage; }
+ +/* Convert a string into the system's default codepage, this is different from the + * locale (e.g. default codepage is 850 but locale is CP1252). + * This assumes the input string is encoded as UTF-8, otherwise a copy of + * the input string is returned. */ +gchar *win32_convert_to_system_codepage(const gchar *str, GError **error) +{ + if (g_utf8_validate(str, -1, NULL)) + { + guint codepage_code = win32_get_console_codepage(); + gchar codepage[8] = { 0 }; + g_snprintf(codepage, G_N_ELEMENTS(codepage), "%u", codepage_code); + return g_convert(str, -1, codepage, "utf-8", NULL, NULL, error); + } + else + return g_strdup(str); +} + #endif
Modified: src/win32.h 2 lines changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -70,6 +70,8 @@ gchar *win32_get_user_config_dir(void);
guint win32_get_console_codepage(void);
+gchar *win32_convert_to_system_codepage(const gchar *str, GError **error); + G_END_DECLS
#endif /* G_OS_WIN32 */
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).