]> git.saurik.com Git - wxWidgets.git/commitdiff
wxTextCtrl::GetValue() lost (replaced with question marks) all characters not in...
authorVadim Zeitlin <vadim@wxwidgets.org>
Fri, 19 Sep 2003 22:21:48 +0000 (22:21 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Fri, 19 Sep 2003 22:21:48 +0000 (22:21 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23729 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/msw/textctrl.h
src/msw/textctrl.cpp

index 3d4c73fac8810f926bcd9767cba10c8d4ed24c6e..85debea9cfebe21ed009f4149214789e177a9b18 100644 (file)
@@ -54,6 +54,7 @@ All (GUI):
 wxMSW:
 
 - fixed wxTE_*WRAP styles handling
 wxMSW:
 
 - fixed wxTE_*WRAP styles handling
+- wxTextCtrl::GetValue() works with text in non default encoding
 
 wxGTK:
 
 
 wxGTK:
 
index 9fdc395d7f6a78cbf992f820c40956a9c0d326a0..2c66ed228e1ef75a2eb4aabe74ca4bd73a7fa354 100644 (file)
@@ -207,12 +207,13 @@ protected:
     // false if we hit the limit set by SetMaxLength() and so didn't change it
     bool AdjustSpaceLimit();
 
     // false if we hit the limit set by SetMaxLength() and so didn't change it
     bool AdjustSpaceLimit();
 
-#if wxUSE_RICHEDIT
+#if wxUSE_RICHEDIT && (!wxUSE_UNICODE || wxUSE_UNICODE_MSLU)
     // replace the selection or the entire control contents with the given text
     // in the specified encoding
     // replace the selection or the entire control contents with the given text
     // in the specified encoding
-    bool StreamIn(const wxString& value,
-                  wxFontEncoding encoding,
-                  bool selOnly);
+    bool StreamIn(const wxString& value, wxFontEncoding encoding, bool selOnly);
+
+    // get the contents of the control out as text in the given encoding
+    wxString StreamOut(wxFontEncoding encoding, bool selOnly = false) const;
 #endif // wxUSE_RICHEDIT
 
     // replace the contents of the selection or of the entire control with the
 #endif // wxUSE_RICHEDIT
 
     // replace the contents of the selection or of the entire control with the
index f70aa21b7cc4fe296a4af1c64489e5ad8a68cf6f..76f8e162d81c3e2c8fb39f5e2c36499aa9db9421 100644 (file)
 
 #endif // wxUSE_RICHEDIT
 
 
 #endif // wxUSE_RICHEDIT
 
-// ----------------------------------------------------------------------------
-// private functions
-// ----------------------------------------------------------------------------
-
-#if wxUSE_RICHEDIT
-
-DWORD CALLBACK wxRichEditStreamIn(DWORD dwCookie, BYTE *buf, LONG cb, LONG *pcb);
-
-#endif // wxUSE_RICHEDIT
-
 // ----------------------------------------------------------------------------
 // private classes
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // private classes
 // ----------------------------------------------------------------------------
@@ -537,6 +527,35 @@ wxString wxTextCtrl::GetRange(long from, long to) const
         int len = GetWindowTextLength(GetHwnd());
         if ( len > from )
         {
         int len = GetWindowTextLength(GetHwnd());
         if ( len > from )
         {
+            if ( to == -1 )
+                to = len;
+
+            // we must use EM_STREAMOUT if we don't want to lose all characters
+            // not representable in the current character set (EM_GETTEXTRANGE
+            // simply replaces them with question marks...)
+            //
+            // as EM_STREAMOUT only works for the entire controls contents (or
+            // just the selection but it's probably a bad idea to play games
+            // with selection here...), we can't use it unless we're called
+            // from GetValue(), i.e. we want to retrieve all text
+            if ( GetRichVersion() > 1 && (from == 0 && to >= len) )
+            {
+                wxFont font = m_defaultStyle.GetFont();
+                if ( !font.Ok() )
+                    font = GetFont();
+
+                if ( font.Ok() )
+                {
+                   wxFontEncoding encoding = font.GetEncoding();
+                   if ( encoding != wxFONTENCODING_SYSTEM )
+                   {
+                       str = StreamOut(encoding);
+                   }
+                }
+            }
+
+            // StreamOut() wasn't used or failed, try to do it in normal way
+            if ( str.empty() )
             {
                 // alloc one extra WORD as needed by the control
                 wxStringBuffer tmp(str, ++len);
             {
                 // alloc one extra WORD as needed by the control
                 wxStringBuffer tmp(str, ++len);
@@ -620,12 +639,17 @@ void wxTextCtrl::SetValue(const wxString& value)
 
 #if wxUSE_RICHEDIT && (!wxUSE_UNICODE || wxUSE_UNICODE_MSLU)
 
 
 #if wxUSE_RICHEDIT && (!wxUSE_UNICODE || wxUSE_UNICODE_MSLU)
 
-DWORD CALLBACK wxRichEditStreamIn(DWORD dwCookie, BYTE *buf, LONG cb, LONG *pcb)
+// TODO: using memcpy() would improve performance a lot for big amounts of text
+
+DWORD CALLBACK
+wxRichEditStreamIn(DWORD dwCookie, BYTE *buf, LONG cb, LONG *pcb)
 {
     *pcb = 0;
 
 {
     *pcb = 0;
 
+    const wchar_t ** const ppws = (const wchar_t **)dwCookie;
+
     wchar_t *wbuf = (wchar_t *)buf;
     wchar_t *wbuf = (wchar_t *)buf;
-    const wchar_t *wpc = *(const wchar_t **)dwCookie;
+    const wchar_t *wpc = *ppws;
     while ( cb && *wpc )
     {
         *wbuf++ = *wpc++;
     while ( cb && *wpc )
     {
         *wbuf++ = *wpc++;
@@ -634,25 +658,51 @@ DWORD CALLBACK wxRichEditStreamIn(DWORD dwCookie, BYTE *buf, LONG cb, LONG *pcb)
         (*pcb) += sizeof(wchar_t);
     }
 
         (*pcb) += sizeof(wchar_t);
     }
 
-    *(const wchar_t **)dwCookie = wpc;
+    *ppws = wpc;
+
+    return 0;
+}
+
+DWORD CALLBACK
+wxRichEditStreamOut(DWORD dwCookie, BYTE *buf, LONG cb, LONG *pcb)
+{
+    *pcb = 0;
+
+    wchar_t ** const ppws = (wchar_t **)dwCookie;
+
+    const wchar_t *wbuf = (const wchar_t *)buf;
+    wchar_t *wpc = *ppws;
+    while ( cb && *wpc )
+    {
+         *wpc++ = *wbuf++;
+
+        cb -= sizeof(wchar_t);
+        (*pcb) += sizeof(wchar_t);
+    }
+
+    *ppws = wpc;
 
     return 0;
 }
 
 
     return 0;
 }
 
+
 // from utils.cpp
 extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding);
 
 #if wxUSE_UNICODE_MSLU
 // from utils.cpp
 extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding);
 
 #if wxUSE_UNICODE_MSLU
-bool wxTextCtrl::StreamIn(const wxString& value,
-                          wxFontEncoding WXUNUSED(encoding),
-                          bool selectionOnly)
+    #define UNUSED_IF_MSLU(param)
+#else
+    #define UNUSED_IF_MSLU(param) param
+#endif
+
+bool
+wxTextCtrl::StreamIn(const wxString& value,
+                     wxFontEncoding UNUSED_IF_MSLU(encoding),
+                     bool selectionOnly)
 {
 {
+#if wxUSE_UNICODE_MSLU
     const wchar_t *wpc = value.c_str();
 #else // !wxUSE_UNICODE_MSLU
     const wchar_t *wpc = value.c_str();
 #else // !wxUSE_UNICODE_MSLU
-bool wxTextCtrl::StreamIn(const wxString& value,
-                          wxFontEncoding encoding,
-                          bool selectionOnly)
-{
     // we have to use EM_STREAMIN to force richedit control 2.0+ to show any
     // text in the non default charset -- otherwise it thinks it knows better
     // than we do and always shows it in the default one
     // we have to use EM_STREAMIN to force richedit control 2.0+ to show any
     // text in the non default charset -- otherwise it thinks it knows better
     // than we do and always shows it in the default one
@@ -716,6 +766,61 @@ bool wxTextCtrl::StreamIn(const wxString& value,
     return TRUE;
 }
 
     return TRUE;
 }
 
+#if !wxUSE_UNICODE_MSLU
+
+wxString
+wxTextCtrl::StreamOut(wxFontEncoding encoding, bool selectionOnly) const
+{
+    wxString out;
+
+    const int len = GetWindowTextLength(GetHwnd());
+
+#if wxUSE_WCHAR_T
+    wxWCharBuffer wchBuf(len);
+    wchar_t *wpc = wchBuf.data();
+#else
+    wchar_t *wchBuf = (wchar_t *)malloc((len + 1)*sizeof(wchar_t));
+    wchar_t *wpc = wchBuf;
+#endif
+
+    EDITSTREAM eds;
+    wxZeroMemory(eds);
+    eds.dwCookie = (DWORD)&wpc;
+    eds.pfnCallback = wxRichEditStreamOut;
+
+    ::SendMessage
+      (
+        GetHwnd(),
+        EM_STREAMOUT,
+        SF_TEXT | SF_UNICODE | (selectionOnly ? SFF_SELECTION : 0),
+        (LPARAM)&eds
+      );
+
+    if ( eds.dwError )
+    {
+        wxLogLastError(_T("EM_STREAMOUT"));
+    }
+    else // streamed out ok
+    {
+        // now convert to the given encoding (this is a lossful conversion but
+        // what else can we do)
+        wxCSConv conv(encoding);
+        size_t lenNeeded = conv.WC2MB(NULL, wchBuf, len);
+        if ( lenNeeded )
+        {
+            conv.WC2MB(wxStringBuffer(out, lenNeeded), wchBuf, len);
+        }
+    }
+
+#if !wxUSE_WCHAR_T
+    free(wchBuf);
+#endif // !wxUSE_WCHAR_T
+
+    return out;
+}
+
+#endif // !wxUSE_UNICODE_MSLU
+
 #endif // wxUSE_RICHEDIT
 
 void wxTextCtrl::WriteText(const wxString& value)
 #endif // wxUSE_RICHEDIT
 
 void wxTextCtrl::WriteText(const wxString& value)