[geany/geany] 26adca: Windows: Convert generated batch script into system codepage

Enrico Tröger git-noreply at geany.org
Sun Nov 13 13:55:40 UTC 2016


Branch:      refs/heads/master
Author:      Enrico Tröger <enrico.troeger at uvena.de>
Committer:   Enrico Tröger <enrico.troeger at uvena.de>
Date:        Sun, 13 Nov 2016 13:55:40 UTC
Commit:      26adcabd694014328f61b3ca5fe0d5be610849c0
             https://github.com/geany/geany/commit/26adcabd694014328f61b3ca5fe0d5be610849c0

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).


More information about the Commits mailing list