[前][次][番号順一覧][スレッド一覧]

ruby-changes:8235

From: suke <ko1@a...>
Date: Sun, 12 Oct 2008 18:08:10 +0900 (JST)
Subject: [ruby-changes:8235] Ruby:r19763 (trunk): * ext/win32ole/win32ole.c (set_ole_codepage, ole_cp2encoding,

suke	2008-10-12 18:06:45 +0900 (Sun, 12 Oct 2008)

  New Revision: 19763

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=19763

  Log:
    * ext/win32ole/win32ole.c (set_ole_codepage, ole_cp2encoding,
      ole_wc2mb, ole_vstr2wc, ole_mb2wc): support CP51932 (only mswin32).
    
    * test/win32ole/test_win32ole.rb: ditto.

  Modified files:
    trunk/ChangeLog
    trunk/ext/win32ole/win32ole.c
    trunk/test/win32ole/test_win32ole.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 19762)
+++ ChangeLog	(revision 19763)
@@ -1,3 +1,10 @@
+Sun Oct 12 18:00:18 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* ext/win32ole/win32ole.c (set_ole_codepage, ole_cp2encoding,
+	  ole_wc2mb, ole_vstr2wc, ole_mb2wc): support CP51932 (only mswin32).
+
+	* test/win32ole/test_win32ole.rb: ditto.
+
 Sun Oct 12 12:03:38 2008  Koichi Sasada  <ko1@a...>
 
 	* vm.c, vm_insnhelper.h (ruby_vm_redefined_flag): apply optimization
Index: ext/win32ole/win32ole.c
===================================================================
--- ext/win32ole/win32ole.c	(revision 19762)
+++ ext/win32ole/win32ole.c	(revision 19763)
@@ -23,6 +23,7 @@
 #include <ocidl.h>
 #include <olectl.h>
 #include <ole2.h>
+#include <mlang.h>
 #include <stdlib.h>
 #include <math.h>
 #ifdef HAVE_STDARG_PROTOTYPES
@@ -118,7 +119,7 @@
 
 #define WC2VSTR(x) ole_wc2vstr((x), TRUE)
 
-#define WIN32OLE_VERSION "1.3.4"
+#define WIN32OLE_VERSION "1.3.5"
 
 typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
     (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
@@ -207,6 +208,7 @@
 static IMessageFilterVtbl message_filter;
 static IMessageFilter imessage_filter = { &message_filter };
 static IMessageFilter* previous_filter;
+static IMultiLanguage2 *pIMultiLanguage2 = NULL;
 
 struct oledata {
     IDispatch *pDispatch;
@@ -267,6 +269,7 @@
 static VALUE date2time_str(double date);
 static rb_encoding *ole_cp2encoding(UINT cp);
 static UINT ole_encoding2cp(rb_encoding *enc);
+static void load_conv_function51932();
 static UINT ole_init_cp();
 static char *ole_wc2mb(LPWSTR pw);
 static VALUE ole_hresult2msg(HRESULT hr);
@@ -956,6 +959,57 @@
     return CP_ACP;
 }
 
+static void
+load_conv_function51932()
+{
+    HRESULT hr;
+    void *p;
+    if (!pIMultiLanguage2) {
+#ifdef _MSC_VER
+	hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
+		              &IID_IMultiLanguage2, &p);
+#else
+	/* 
+	 * unfortunately, fail to link IID_IMultiLanguage2 on Cygwin or mingw32.
+	 */
+	hr = E_FAIL;
+#endif
+	if (FAILED(hr)) {
+	    rb_raise(eWIN32OLERuntimeError, "fail to load convert function for CP51932");
+	}
+	pIMultiLanguage2 = p;
+    }
+}
+
+static void
+set_ole_codepage(UINT cp)
+{
+    if (code_page_installed(cp)) {
+        cWIN32OLE_cp = cp;
+    } else {
+        switch(cp) {
+        case CP_ACP:
+        case CP_OEMCP:
+        case CP_MACCP:
+        case CP_THREAD_ACP:
+        case CP_SYMBOL:
+        case CP_UTF7:
+        case CP_UTF8:
+        case 51932:
+            cWIN32OLE_cp = cp;
+            if (cp == 51932) {
+                load_conv_function51932();
+            }
+            break;
+        default:
+            rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage.");
+            break;
+        }
+    }
+    cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
+}
+
+
 static UINT
 ole_init_cp()
 {
@@ -966,9 +1020,7 @@
 	encdef = rb_default_external_encoding();
     }
     cp = ole_encoding2cp(encdef);
-    if (code_page_installed(cp)) {
-        cWIN32OLE_cp = cp;
-    }
+    set_ole_codepage(cp);
     return cp;
 }
 
@@ -1018,8 +1070,10 @@
 	  case CP_SYMBOL:
 	  case CP_UTF7:
 	  case CP_UTF8:
-	    // nothing ToDo
 	    break;
+	  case 51932:  
+	    load_conv_function51932();
+	    break;
 	  default:
             rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage.");
             break;
@@ -1036,8 +1090,26 @@
 static char *
 ole_wc2mb(LPWSTR pw)
 {
-    int size;
     LPSTR pm;
+    HRESULT hr;
+    int size = 0;
+    DWORD dw = 0;
+    if (cWIN32OLE_cp == 51932) {
+	load_conv_function51932();
+	hr = pIMultiLanguage2->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage2,
+		&dw, cWIN32OLE_cp, pw, NULL, NULL, &size);
+	if (FAILED(hr)) {
+            ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp);
+	}
+	pm = ALLOC_N(char, size + 1);
+	hr = pIMultiLanguage2->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage2,
+		&dw, cWIN32OLE_cp, pw, NULL, pm, &size);
+	if (FAILED(hr)) {
+            ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp);
+	}
+	pm[size] = '\0';
+        return pm;
+    }
     size = WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, NULL, 0, NULL, NULL);
     if (size) {
         pm = ALLOC_N(char, size + 1);    
@@ -1230,15 +1302,20 @@
     free(pole);
 }
 
+
 static LPWSTR
 ole_vstr2wc(VALUE vstr)
 {
     rb_encoding *enc;
     int cp;
-    int size;
+    int size = 0;
     LPWSTR pw;
+    int len = 0;
+    DWORD dw = 0;
+    HRESULT hr;
     st_data_t data;
     enc = rb_enc_get(vstr);
+
     if (st_lookup(enc2cp_table, (st_data_t)enc, &data)) {
         cp = data;
     } else {
@@ -1250,23 +1327,62 @@
             cp == CP_THREAD_ACP ||
             cp == CP_SYMBOL ||
             cp == CP_UTF7 ||
-            cp == CP_UTF8 ) {
+            cp == CP_UTF8 ||
+            cp == 51932) {
             st_insert(enc2cp_table, (st_data_t)enc, (st_data_t)cp);
         } else {
             rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc));
         }
     }
-    size = MultiByteToWideChar(cp, 0, StringValuePtr(vstr), -1, NULL, 0);
-    pw = SysAllocStringLen(NULL, size - 1);
-    MultiByteToWideChar(cp, 0, StringValuePtr(vstr), -1, pw, size);
+    if (cp == 51932) {
+	load_conv_function51932();
+	len = RSTRING_LEN(vstr);
+	size = 0;
+	hr = pIMultiLanguage2->lpVtbl->ConvertStringToUnicode(pIMultiLanguage2,
+		&dw, cp, RSTRING_PTR(vstr), &len, NULL, &size);
+	if (FAILED(hr)) {
+            ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
+	}
+	pw = SysAllocStringLen(NULL, size);
+	len = RSTRING_LEN(vstr);
+	hr = pIMultiLanguage2->lpVtbl->ConvertStringToUnicode(pIMultiLanguage2,
+		&dw, cp, RSTRING_PTR(vstr), &len, pw, &size);
+	if (FAILED(hr)) {
+            ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
+	}
+	return pw;
+    }
+    size = MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), NULL, 0);
+    pw = SysAllocStringLen(NULL, size);
+    MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), pw, size);
     return pw;
 }
 
 static LPWSTR
 ole_mb2wc(char *pm, int len)
 {
-    int size;
+    int size = 0;
     LPWSTR pw;
+    HRESULT hr;
+    DWORD dw = 0;
+    int n = len;
+
+    if (cWIN32OLE_cp == 51932) {
+	load_conv_function51932();
+	size = 0;
+	hr = pIMultiLanguage2->lpVtbl->ConvertStringToUnicode(pIMultiLanguage2,
+		&dw, cWIN32OLE_cp, pm, &n, NULL, &size);
+	if (FAILED(hr)) {
+            ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp);
+	}
+	pw = SysAllocStringLen(NULL, size);
+	hr = pIMultiLanguage2->lpVtbl->ConvertStringToUnicode(pIMultiLanguage2,
+		&dw, cWIN32OLE_cp, pm, &n, pw, &size);
+	if (FAILED(hr)) {
+            ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp);
+	}
+	return pw;
+    }
     size = MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, NULL, 0);
     pw = SysAllocStringLen(NULL, size - 1);
     MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, pw, size);
@@ -2924,26 +3040,7 @@
 fole_s_set_code_page(VALUE self, VALUE vcp)
 {
     UINT cp = FIX2INT(vcp);
-
-    if (code_page_installed(cp)) {
-        cWIN32OLE_cp = cp;
-    } else {
-        switch(cp) {
-        case CP_ACP:
-        case CP_OEMCP:
-        case CP_MACCP:
-        case CP_THREAD_ACP:
-        case CP_SYMBOL:
-        case CP_UTF7:
-        case CP_UTF8:
-            cWIN32OLE_cp = cp;
-            break;
-        default:
-            rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage.");
-            break;
-        }
-    }
-    cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
+    set_ole_codepage(cp);
     /*
      * Should this method return old codepage?
      */
@@ -3102,7 +3199,6 @@
     OLECHAR *pBuf;
     IDispatch *pDispatch;
     void *p;
-
     rb_secure(4);
     rb_call_super(0, 0);
     rb_scan_args(argc, argv, "11*", &svr_name, &host, &others);
@@ -9041,5 +9137,7 @@
     init_enc2cp();
     atexit((void (*)(void))free_enc2cp);
     ole_init_cp();
+    /*
     cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
+    */
 }
Index: test/win32ole/test_win32ole.rb
===================================================================
--- test/win32ole/test_win32ole.rb	(revision 19762)
+++ test/win32ole/test_win32ole.rb	(revision 19763)
@@ -361,6 +361,30 @@
       end
     end
 
+    def test_cp51932
+      cp = WIN32OLE.codepage
+      begin
+        obj = WIN32OLE_VARIANT.new([0x3042].pack("U*").force_encoding("UTF-8"))
+        # mswin32 ruby only supports CP51932 
+        if /mswin/ =~ RUBY_PLATFORM
+          begin
+            WIN32OLE.codepage = 51932
+          rescue
+          end
+          if WIN32OLE.codepage == 51932
+            assert_equal("\xA4\xA2".force_encoding("CP51932"), obj.value)
+          end
+        else
+          # cygwin, mingw32 ruby does not support CP51932
+          assert_raise(WIN32OLERuntimeError) {
+            WIN32OLE.codepage = 51932
+          }
+        end
+      ensure
+        WIN32OLE.codepage = cp
+      end
+    end
+
     def test_s_locale
       assert_equal(WIN32OLE::LOCALE_SYSTEM_DEFAULT, WIN32OLE.locale)
     end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]