New test.
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / Catalog.cs
index 8ec13851e3b5c71047362937b9194224f5c90afc..d835fec46245715b7fe3e8feaae6ab08d4e6cef0 100644 (file)
@@ -1,10 +1,12 @@
 //
 // Mono.Unix.Catalog.cs: Wrappers for the libintl library.
 //
-// Author:
+// Authors:
 //   Edd Dumbill (edd@usefulinc.com)
+//   Jonathan Pryor (jonpryor@vt.edu)
 //
 // (C) 2004 Edd Dumbill
+// (C) 2005-2006 Jonathan Pryor
 //
 // This file implements the low-level syscall interface to the POSIX
 // subsystem.
@@ -36,50 +38,99 @@ using System.Runtime.InteropServices;
 namespace Mono.Unix {
 
        public class Catalog {
-               [DllImport("libintl")]
+               private Catalog () {}
+
+               [DllImport("intl")]
                static extern IntPtr bindtextdomain (IntPtr domainname, IntPtr dirname);
-               [DllImport("libintl")]
+               [DllImport("intl")]
                static extern IntPtr bind_textdomain_codeset (IntPtr domainname,
                        IntPtr codeset);
-               [DllImport("libintl")]
+               [DllImport("intl")]
                static extern IntPtr textdomain (IntPtr domainname);
                
                public static void Init (String package, String localedir)
                {
-                       IntPtr ipackage = Marshal.StringToHGlobalAuto (package);
-                       IntPtr ilocaledir = Marshal.StringToHGlobalAuto (localedir);
-                       IntPtr iutf8 = Marshal.StringToHGlobalAuto ("UTF-8");
-                       bindtextdomain (ipackage, ilocaledir);
-                       bind_textdomain_codeset (ipackage, iutf8);
-                       textdomain (ipackage);
-                       Marshal.FreeHGlobal (ipackage);
-                       Marshal.FreeHGlobal (ilocaledir);
-                       Marshal.FreeHGlobal (iutf8);
+                       IntPtr ipackage, ilocaledir, iutf8;
+                       MarshalStrings (package, out ipackage, localedir, out ilocaledir, 
+                                       "UTF-8", out iutf8);
+                       try {
+                               if (bindtextdomain (ipackage, ilocaledir) == IntPtr.Zero)
+                                       throw new UnixIOException (Native.Errno.ENOMEM);
+                               if (bind_textdomain_codeset (ipackage, iutf8) == IntPtr.Zero)
+                                       throw new UnixIOException (Native.Errno.ENOMEM);
+                               if (textdomain (ipackage) == IntPtr.Zero)
+                                       throw new UnixIOException (Native.Errno.ENOMEM);
+                       }
+                       finally {
+                               UnixMarshal.FreeHeap (ipackage);
+                               UnixMarshal.FreeHeap (ilocaledir);
+                               UnixMarshal.FreeHeap (iutf8);
+                       }
+               }
+
+               private static void MarshalStrings (string s1, out IntPtr p1, 
+                               string s2, out IntPtr p2, string s3, out IntPtr p3)
+               {
+                       p1 = p2 = p3 = IntPtr.Zero;
+
+                       bool cleanup = true;
+
+                       try {
+                               p1 = UnixMarshal.StringToHeap (s1);
+                               p2 = UnixMarshal.StringToHeap (s2);
+                               if (s3 != null)
+                                       p3 = UnixMarshal.StringToHeap (s3);
+                               cleanup = false;
+                       }
+                       finally {
+                               if (cleanup) {
+                                       UnixMarshal.FreeHeap (p1);
+                                       UnixMarshal.FreeHeap (p2);
+                                       UnixMarshal.FreeHeap (p3);
+                               }
+                       }
                }
        
-               [DllImport("libintl")]
+               [DllImport("intl")]
                static extern IntPtr gettext (IntPtr instring);
                
                public static String GetString (String s)
                {
-                       IntPtr ints = Marshal.StringToHGlobalAuto (s);
-                       String t = Marshal.PtrToStringAuto (gettext (ints));
-                       Marshal.FreeHGlobal (ints);
-                       return t;
+                       IntPtr ints = UnixMarshal.StringToHeap (s);
+                       try {
+                               // gettext(3) returns the input pointer if no translation is found
+                               IntPtr r = gettext (ints);
+                               if (r != ints)
+                                       return UnixMarshal.PtrToStringUnix (r);
+                               return s;
+                       }
+                       finally {
+                               UnixMarshal.FreeHeap (ints);
+                       }
                }
        
-               [DllImport("libintl")]
+               [DllImport("intl")]
                static extern IntPtr ngettext (IntPtr singular, IntPtr plural, Int32 n);
                
                public static String GetPluralString (String s, String p, Int32 n)
                {
-                       IntPtr ints = Marshal.StringToHGlobalAuto (s);
-                       IntPtr intp = Marshal.StringToHGlobalAuto (p);
-                       String t = Marshal.PtrToStringAnsi (ngettext (ints, intp, n));
-                       Marshal.FreeHGlobal (ints);
-                       Marshal.FreeHGlobal (intp);
-                       return t;
+                       IntPtr ints, intp, _ignore;
+                       MarshalStrings (s, out ints, p, out intp, null, out _ignore);
+
+                       try {
+                               // ngettext(3) returns an input pointer if no translation is found
+                               IntPtr r = ngettext (ints, intp, n);
+                               if (r == ints)
+                                       return s;
+                               if (r == intp)
+                                       return p;
+                               return UnixMarshal.PtrToStringUnix (r); 
+                       }
+                       finally {
+                               UnixMarshal.FreeHeap (ints);
+                               UnixMarshal.FreeHeap (intp);
+                       }
                }
-       
        }
 }
+