diff --git a/ChangeLog b/ChangeLog index 3566486fe..daf484ce7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-11-30 Mike Kestner + + * generator/Method.cs: support win32_utf8_variant attribute on methods. + * glib/*.cs: support win32 utf8 variant methods. + * gtk/*.custom: support win32 utf8 variant methods. + * gtk/Gtk.metadata: mark some win32_utf8_variant methods. + [Fixes #550961] Adapted from a patch by Tor Lillqvist. + 2009-11-28 Mike Kestner * glib/GException.cs: add Code and Domain props to expose the GError diff --git a/generator/Method.cs b/generator/Method.cs index 516faa7bd..3f47e9b8c 100644 --- a/generator/Method.cs +++ b/generator/Method.cs @@ -34,6 +34,7 @@ namespace GtkSharp.Generation { private string call; private bool is_get, is_set; private bool deprecated = false; + private bool win32_utf8_variant = false; public Method (XmlElement elem, ClassBase container_type) : base (elem, container_type) { @@ -44,10 +45,19 @@ namespace GtkSharp.Generation { deprecated = attr == "1" || attr == "true"; } + if (elem.HasAttribute ("win32_utf8_variant")) { + string attr = elem.GetAttribute ("win32_utf8_variant"); + win32_utf8_variant = attr == "1" || attr.ToLower () == "true"; + } + if (Name == "GetType") Name = "GetGType"; } + public bool HasWin32Utf8Variant { + get { return win32_utf8_variant; } + } + public bool IsDeprecated { get { return deprecated; @@ -191,6 +201,15 @@ namespace GtkSharp.Generation { else sw.WriteLine("\t\tstatic extern " + Safety + retval.MarshalType + " " + CName + "(" + import_sig + ");"); sw.WriteLine(); + + if (HasWin32Utf8Variant) { + sw.WriteLine("\t\t[DllImport(\"" + LibraryName + "\")]"); + if (retval.MarshalType.StartsWith ("[return:")) + sw.WriteLine("\t\t" + retval.MarshalType + " static extern " + Safety + retval.CSType + " " + CName + "_utf8(" + import_sig + ");"); + else + sw.WriteLine("\t\tstatic extern " + Safety + retval.MarshalType + " " + CName + "_utf8(" + import_sig + ");"); + sw.WriteLine(); + } } public void Generate (GenerationInfo gen_info, ClassBase implementor) @@ -271,12 +290,31 @@ namespace GtkSharp.Generation { Body.InitAccessor (sw, Signature, indent); Body.Initialize(gen_info, is_get, is_set, indent); - sw.Write(indent + "\t\t\t"); - if (retval.IsVoid) - sw.WriteLine(CName + call + ";"); - else { - sw.WriteLine(retval.MarshalType + " raw_ret = " + CName + call + ";"); - sw.WriteLine(indent + "\t\t\t" + retval.CSType + " ret = " + retval.FromNative ("raw_ret") + ";"); + if (HasWin32Utf8Variant) { + if (!retval.IsVoid) + sw.WriteLine(indent + "\t\t\t" + retval.MarshalType + " raw_ret;"); + sw.WriteLine(indent + "\t\t\t" + "if (Environment.OSVersion.Platform == PlatformID.Win32NT ||"); + sw.WriteLine(indent + "\t\t\t" + " Environment.OSVersion.Platform == PlatformID.Win32S ||"); + sw.WriteLine(indent + "\t\t\t" + " Environment.OSVersion.Platform == PlatformID.Win32Windows ||"); + sw.WriteLine(indent + "\t\t\t" + " Environment.OSVersion.Platform == PlatformID.WinCE)"); + if (retval.IsVoid) { + sw.WriteLine(indent + "\t\t\t\t" + CName + "_utf8" + call + ";"); + sw.WriteLine(indent + "\t\t\t" + "else"); + sw.WriteLine(indent + "\t\t\t\t" + CName + call + ";"); + } else { + sw.WriteLine(indent + "\t\t\t\traw_ret = " + CName + "_utf8" + call + ";"); + sw.WriteLine(indent + "\t\t\t" + "else"); + sw.WriteLine(indent + "\t\t\t\traw_ret = " + CName + call + ";"); + sw.WriteLine(indent + "\t\t\t" + retval.CSType + " ret = " + retval.FromNative ("raw_ret") + ";"); + } + } else { + sw.Write(indent + "\t\t\t"); + if (retval.IsVoid) + sw.WriteLine(CName + call + ";"); + else { + sw.WriteLine(retval.MarshalType + " raw_ret = " + CName + call + ";"); + sw.WriteLine(indent + "\t\t\t" + retval.CSType + " ret = " + retval.FromNative ("raw_ret") + ";"); + } } if (!IsStatic && implementor != null) diff --git a/glib/FileUtils.cs b/glib/FileUtils.cs index 00e421543..e48ef8288 100644 --- a/glib/FileUtils.cs +++ b/glib/FileUtils.cs @@ -30,14 +30,22 @@ namespace GLib { [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] extern static bool g_file_get_contents (IntPtr filename, out IntPtr contents, out int length, out IntPtr error); + [DllImport("libglib-2.0-0.dll")] + extern static bool g_file_get_contents_utf8 (IntPtr filename, out IntPtr contents, out int length, out IntPtr error); + public static string GetFileContents (string filename) { int length; IntPtr contents, error; IntPtr native_filename = Marshaller.StringToPtrGStrdup (filename); - if (!g_file_get_contents (native_filename, out contents, out length, out error)) - throw new GException (error); + if (Global.IsWindowsPlatform) { + if (!g_file_get_contents_utf8 (native_filename, out contents, out length, out error)) + throw new GException (error); + } else { + if (!g_file_get_contents (native_filename, out contents, out length, out error)) + throw new GException (error); + } Marshaller.Free (native_filename); return Marshaller.Utf8PtrToString (contents); diff --git a/glib/Global.cs b/glib/Global.cs index 918d48d2a..427fbe881 100644 --- a/glib/Global.cs +++ b/glib/Global.cs @@ -31,6 +31,20 @@ namespace GLib { //this is a static class private Global () {} + internal static bool IsWindowsPlatform { + get { + switch (Environment.OSVersion.Platform) { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + case PlatformID.WinCE: + return true; + default: + return false; + } + } + } + public static string ProgramName { get { return GLib.Marshaller.PtrToStringGFree(g_get_prgname()); diff --git a/glib/IOChannel.cs b/glib/IOChannel.cs index 0db0e3160..45673990d 100644 --- a/glib/IOChannel.cs +++ b/glib/IOChannel.cs @@ -73,7 +73,11 @@ namespace GLib { IntPtr native_filename = Marshaller.StringToPtrGStrdup (filename); IntPtr native_mode = Marshaller.StringToPtrGStrdup (mode); IntPtr error; - handle = g_io_channel_new_file(native_filename, native_mode, out error); + + if (Global.IsWindowsPlatform) + handle = g_io_channel_new_file_utf8(native_filename, native_mode, out error); + else + handle = g_io_channel_new_file(native_filename, native_mode, out error); Marshaller.Free (native_filename); Marshaller.Free (native_mode); if (error != IntPtr.Zero) throw new GException (error); @@ -325,6 +329,9 @@ namespace GLib { [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr g_io_channel_new_file (IntPtr filename, IntPtr mode, out IntPtr error); + [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr g_io_channel_new_file_utf8 (IntPtr filename, IntPtr mode, out IntPtr error); + [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern int g_io_channel_error_quark (); diff --git a/glib/Marshaller.cs b/glib/Marshaller.cs index a3e7654ad..8cf8385f9 100644 --- a/glib/Marshaller.cs +++ b/glib/Marshaller.cs @@ -49,12 +49,21 @@ namespace GLib { [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr g_filename_to_utf8 (IntPtr mem, int len, IntPtr read, out IntPtr written, out IntPtr error); + [DllImport("libglib-2.0-0.dll")] + static extern IntPtr g_filename_to_utf8_utf8 (IntPtr mem, int len, IntPtr read, out IntPtr written, out IntPtr error); + public static string FilenamePtrToString (IntPtr ptr) { if (ptr == IntPtr.Zero) return null; IntPtr dummy, error; - IntPtr utf8 = g_filename_to_utf8 (ptr, -1, IntPtr.Zero, out dummy, out error); + IntPtr utf8; + + if (Global.IsWindowsPlatform) + utf8 = g_filename_to_utf8_utf8 (ptr, -1, IntPtr.Zero, out dummy, out error); + else + utf8 = g_filename_to_utf8 (ptr, -1, IntPtr.Zero, out dummy, out error); + if (error != IntPtr.Zero) throw new GLib.GException (error); return Utf8PtrToString (utf8); @@ -117,6 +126,9 @@ namespace GLib { [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr g_filename_from_utf8 (IntPtr mem, int len, IntPtr read, out IntPtr written, out IntPtr error); + [DllImport("libglib-2.0-0.dll")] + static extern IntPtr g_filename_from_utf8_utf8 (IntPtr mem, int len, IntPtr read, out IntPtr written, out IntPtr error); + public static IntPtr StringToFilenamePtr (string str) { if (str == null) @@ -124,7 +136,14 @@ namespace GLib { IntPtr dummy, error; IntPtr utf8 = StringToPtrGStrdup (str); - IntPtr result = g_filename_from_utf8 (utf8, -1, IntPtr.Zero, out dummy, out error); + + IntPtr result; + + if (Global.IsWindowsPlatform) + result = g_filename_from_utf8_utf8 (utf8, -1, IntPtr.Zero, out dummy, out error); + else + result = g_filename_from_utf8 (utf8, -1, IntPtr.Zero, out dummy, out error); + g_free (utf8); if (error != IntPtr.Zero) throw new GException (error); diff --git a/glib/Spawn.cs b/glib/Spawn.cs index 808a02737..72c9a6b8d 100644 --- a/glib/Spawn.cs +++ b/glib/Spawn.cs @@ -113,6 +113,9 @@ namespace GLib { [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern bool g_spawn_async (IntPtr dir, IntPtr[] argv, IntPtr[] envp, int flags, SpawnChildSetupFuncNative func, IntPtr data, out int pid, out IntPtr error); + [DllImport ("libglib-2.0-0.dll")] + static extern bool g_spawn_async_utf8 (IntPtr dir, IntPtr[] argv, IntPtr[] envp, int flags, SpawnChildSetupFuncNative func, IntPtr data, out int pid, out IntPtr error); + public static bool SpawnAsync (string working_directory, string[] argv, string[] envp, SpawnFlags flags, SpawnChildSetupFunc child_setup, out Process child_process) { int pid; @@ -121,7 +124,13 @@ namespace GLib { IntPtr[] native_argv = Marshaller.StringArrayToNullTermPointer (argv); IntPtr[] native_envp = Marshaller.StringArrayToNullTermPointer (envp); SpawnChildSetupWrapper wrapper = new SpawnChildSetupWrapper (child_setup); - bool result = g_spawn_async (native_dir, native_argv, native_envp, (int) flags, wrapper.NativeCallback, wrapper.Data, out pid, out error); + bool result; + + if (Global.IsWindowsPlatform) + result = g_spawn_async_utf8 (native_dir, native_argv, native_envp, (int) flags, wrapper.NativeCallback, wrapper.Data, out pid, out error); + else + result = g_spawn_async (native_dir, native_argv, native_envp, (int) flags, wrapper.NativeCallback, wrapper.Data, out pid, out error); + child_process = new Process (pid); Marshaller.Free (native_dir); Marshaller.Free (native_argv); @@ -133,6 +142,9 @@ namespace GLib { [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern bool g_spawn_async_with_pipes (IntPtr dir, IntPtr[] argv, IntPtr[] envp, int flags, SpawnChildSetupFuncNative func, IntPtr data, out int pid, IntPtr stdin, IntPtr stdout, IntPtr stderr, out IntPtr error); + [DllImport ("libglib-2.0-0.dll")] + static extern bool g_spawn_async_with_pipes_utf8 (IntPtr dir, IntPtr[] argv, IntPtr[] envp, int flags, SpawnChildSetupFuncNative func, IntPtr data, out int pid, IntPtr stdin, IntPtr stdout, IntPtr stderr, out IntPtr error); + public static bool SpawnAsyncWithPipes (string working_directory, string[] argv, string[] envp, SpawnFlags flags, SpawnChildSetupFunc child_setup, out Process child_process, ref int stdin, ref int stdout, ref int stderr) { int pid; @@ -144,7 +156,13 @@ namespace GLib { IntPtr in_ptr = stdin == IgnorePipe ? IntPtr.Zero : Marshal.AllocHGlobal (4); IntPtr out_ptr = stdout == IgnorePipe ? IntPtr.Zero : Marshal.AllocHGlobal (4); IntPtr err_ptr = stderr == IgnorePipe ? IntPtr.Zero : Marshal.AllocHGlobal (4); - bool result = g_spawn_async_with_pipes (native_dir, native_argv, native_envp, (int) flags, wrapper.NativeCallback, wrapper.Data, out pid, in_ptr, out_ptr, err_ptr, out error); + bool result; + + if (Global.IsWindowsPlatform) + result = g_spawn_async_with_pipes_utf8 (native_dir, native_argv, native_envp, (int) flags, wrapper.NativeCallback, wrapper.Data, out pid, in_ptr, out_ptr, err_ptr, out error); + else + result = g_spawn_async_with_pipes (native_dir, native_argv, native_envp, (int) flags, wrapper.NativeCallback, wrapper.Data, out pid, in_ptr, out_ptr, err_ptr, out error); + child_process = new Process (pid); if (in_ptr != IntPtr.Zero) { stdin = Marshal.ReadInt32 (in_ptr); @@ -168,6 +186,9 @@ namespace GLib { [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern bool g_spawn_sync (IntPtr dir, IntPtr[] argv, IntPtr[] envp, int flags, SpawnChildSetupFuncNative func, IntPtr data, out IntPtr stdout, out IntPtr stderr, out int exit_status, out IntPtr error); + [DllImport ("libglib-2.0-0.dll")] + static extern bool g_spawn_sync_utf8 (IntPtr dir, IntPtr[] argv, IntPtr[] envp, int flags, SpawnChildSetupFuncNative func, IntPtr data, out IntPtr stdout, out IntPtr stderr, out int exit_status, out IntPtr error); + public static bool SpawnSync (string working_directory, string[] argv, string[] envp, SpawnFlags flags, SpawnChildSetupFunc child_setup, out string stdout, out string stderr, out int exit_status) { IntPtr native_stdout, native_stderr, error; @@ -175,7 +196,13 @@ namespace GLib { IntPtr[] native_argv = Marshaller.StringArrayToNullTermPointer (argv); IntPtr[] native_envp = Marshaller.StringArrayToNullTermPointer (envp); SpawnChildSetupWrapper wrapper = new SpawnChildSetupWrapper (child_setup); - bool result = g_spawn_sync (native_dir, native_argv, native_envp, (int) flags, wrapper.NativeCallback, wrapper.Data, out native_stdout, out native_stderr, out exit_status, out error); + bool result; + + if (Global.IsWindowsPlatform) + result = g_spawn_sync (native_dir, native_argv, native_envp, (int) flags, wrapper.NativeCallback, wrapper.Data, out native_stdout, out native_stderr, out exit_status, out error); + else + result = g_spawn_sync (native_dir, native_argv, native_envp, (int) flags, wrapper.NativeCallback, wrapper.Data, out native_stdout, out native_stderr, out exit_status, out error); + Marshaller.Free (native_dir); Marshaller.Free (native_argv); Marshaller.Free (native_envp); @@ -188,11 +215,20 @@ namespace GLib { [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern bool g_spawn_command_line_async (IntPtr cmdline, out IntPtr error); + [DllImport ("libglib-2.0-0.dll")] + static extern bool g_spawn_command_line_async_utf8 (IntPtr cmdline, out IntPtr error); + public static bool SpawnCommandLineAsync (string command_line) { IntPtr error; IntPtr native_cmd = Marshaller.StringToPtrGStrdup (command_line); - bool result = g_spawn_command_line_async (native_cmd, out error); + bool result; + + if (Global.IsWindowsPlatform) + result = g_spawn_command_line_async_utf8 (native_cmd, out error); + else + result = g_spawn_command_line_async (native_cmd, out error); + Marshaller.Free (native_cmd); if (error != IntPtr.Zero) throw new GLib.GException (error); return result; @@ -201,11 +237,20 @@ namespace GLib { [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern bool g_spawn_command_line_sync (IntPtr cmdline, out IntPtr stdout, out IntPtr stderr, out int exit_status, out IntPtr error); + [DllImport ("libglib-2.0-0.dll")] + static extern bool g_spawn_command_line_sync_utf8 (IntPtr cmdline, out IntPtr stdout, out IntPtr stderr, out int exit_status, out IntPtr error); + public static bool SpawnCommandLineSync (string command_line, out string stdout, out string stderr, out int exit_status) { IntPtr error, native_stdout, native_stderr; IntPtr native_cmd = Marshaller.StringToPtrGStrdup (command_line); - bool result = g_spawn_command_line_sync (native_cmd, out native_stdout, out native_stderr, out exit_status, out error); + bool result; + + if (Global.IsWindowsPlatform) + result = g_spawn_command_line_sync_utf8 (native_cmd, out native_stdout, out native_stderr, out exit_status, out error); + else + result = g_spawn_command_line_sync (native_cmd, out native_stdout, out native_stderr, out exit_status, out error); + Marshaller.Free (native_cmd); stdout = Marshaller.PtrToStringGFree (native_stdout); stderr = Marshaller.PtrToStringGFree (native_stderr); diff --git a/gtk/FileSelection.custom b/gtk/FileSelection.custom index 53740acc2..2f301c3d3 100644 --- a/gtk/FileSelection.custom +++ b/gtk/FileSelection.custom @@ -36,15 +36,30 @@ public class FSButton : Gtk.Button { } } -[DllImport ("libgtk-win32-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] +[DllImport("libgtk-win32-2.0-0.dll")] static extern IntPtr gtk_file_selection_get_selections (IntPtr handle); -[DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] +[DllImport("libgtk-win32-2.0-0.dll")] +static extern IntPtr gtk_file_selection_get_selections_utf8 (IntPtr handle); + +[DllImport("libglib-2.0-0.dll")] static extern void g_strfreev (IntPtr handle); public string[] Selections { get { - IntPtr strv = gtk_file_selection_get_selections (Handle); + IntPtr strv; + + switch (Environment.OSVersion.Platform) { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + case PlatformID.WinCE: + strv = gtk_file_selection_get_selections_utf8 (Handle); + break; + default: + strv = gtk_file_selection_get_selections (Handle); + break; + } System.Collections.ArrayList result = new System.Collections.ArrayList (); diff --git a/gtk/Gtk.metadata b/gtk/Gtk.metadata index 09fccae48..7d2f893f9 100644 --- a/gtk/Gtk.metadata +++ b/gtk/Gtk.metadata @@ -13,10 +13,13 @@ 1 1 1 + true 1 1 1 1 + true + true GtkPaperSize* true true @@ -105,7 +108,10 @@ async 1 1 + true 1 + true + true 1 1 1 @@ -152,11 +158,15 @@ SelectRegion 1 1 + true gfilename* + true gfilename* + true true gfilename* true + true gfilename* const-gfilename* const-gfilename* @@ -166,6 +176,7 @@ GetFilters GtkFileFilter* true + true GetShortcutFolders true gfilename* @@ -174,6 +185,12 @@ gchar* true true + true + true + true + true + true + true GetFilenames gfilename* true @@ -227,6 +244,8 @@ modifier call call + true + true MapChanged accel_path accel_key @@ -391,8 +410,11 @@ GtkButton* GtkEntry* GtkLabel* + true const-gfilename* + true 1 + true const-gfilename* gfilename* GtkButton* @@ -410,8 +432,10 @@ 1 IsChildDetached 1 + true 1 1 + true 1 gchar* true @@ -421,6 +445,8 @@ true true LookupIcon + true + true 1 ActivateItem 1 @@ -451,6 +477,7 @@ 1 1 pixbuf_animation + true file true 1 @@ -462,6 +489,7 @@ out out SetAnimation + true SetFile SetPixbuf out @@ -774,6 +802,7 @@ SetEnableGridLines ScrollAdjustmentsSet 1 + true 1 1 ScrollAdjustmentsSet @@ -847,7 +876,9 @@ 1 GtkWindow* true + true 1 + true 1 1 DefaultActivated diff --git a/gtk/IconTheme.custom b/gtk/IconTheme.custom index 17cc02c3d..46809d6f4 100644 --- a/gtk/IconTheme.custom +++ b/gtk/IconTheme.custom @@ -46,9 +46,29 @@ [DllImport ("libgtk-win32-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern void gtk_icon_theme_set_search_path(IntPtr raw, IntPtr[] path, int n_elements); + [DllImport ("libgtk-win32-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] + static extern void gtk_icon_theme_get_search_path_utf8(IntPtr raw, out IntPtr path, out int n_elements); + + [DllImport ("libgtk-win32-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] + static extern void gtk_icon_theme_set_search_path_utf8(IntPtr raw, IntPtr[] path, int n_elements); + [DllImport ("libglib-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern void g_strfreev (IntPtr mem); + bool IsWindowsPlatform { + get { + switch (Environment.OSVersion.Platform) { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + case PlatformID.WinCE: + return true; + default: + return false; + } + } + } + public string[] SearchPath { get { string[] retval; @@ -56,7 +76,11 @@ unsafe { int length; IntPtr raw_ret; - gtk_icon_theme_get_search_path (Handle, out raw_ret, out length); + if (IsWindowsPlatform) + gtk_icon_theme_get_search_path_utf8 (Handle, out raw_ret, out length); + else + gtk_icon_theme_get_search_path (Handle, out raw_ret, out length); + int size = Marshal.SizeOf (typeof (IntPtr)); retval = new string[length]; for (int i = 0, j = 0; i < length; i++, j += size) { @@ -74,7 +98,12 @@ IntPtr[] native_path = new IntPtr [cnt_path]; for (int i = 0; i < cnt_path; i++) native_path [i] = GLib.Marshaller.StringToPtrGStrdup (value[i]); - gtk_icon_theme_set_search_path (Handle, native_path, native_path.Length); + + if (IsWindowsPlatform) + gtk_icon_theme_set_search_path_utf8 (Handle, native_path, native_path.Length); + else + gtk_icon_theme_set_search_path (Handle, native_path, native_path.Length); + for (int i = 0; i < native_path.Length; i++) GLib.Marshaller.Free (native_path[i]); }