]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/textctrl.cpp
create the DIBs in correct (and not down up) line order
[wxWidgets.git] / src / msw / textctrl.cpp
index 34956b23ae9ecc207fd882622672d2183ff45222..53f74e07fde7877145cf65b840ad2d60d7bfdfd9 100644 (file)
@@ -5,8 +5,8 @@
 // Modified by:
 // Created:     04/01/98
 // RCS-ID:      $Id$
-// Copyright:   (c) Julian Smart and Markus Holzem
-// Licence:     wxWindows license
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 #include <stdlib.h>
 #include <sys/types.h>
 
-#if wxUSE_RICHEDIT && (!defined(__GNUWIN32_OLD__) || defined(__CYGWIN10__))
+#if wxUSE_RICHEDIT
+
+// old mingw32 has richedit stuff directly in windows.h and doesn't have
+// richedit.h at all
+#if !defined(__GNUWIN32_OLD__) || defined(__CYGWIN10__)
     #include <richedit.h>
 #endif
 
 
 // Watcom C++ doesn't define this
 #ifndef SCF_ALL
-#define SCF_ALL 0x0004
+    #define SCF_ALL 0x0004
 #endif
 
+#endif // wxUSE_RICHEDIT
+
 // ----------------------------------------------------------------------------
 // private functions
 // ----------------------------------------------------------------------------
@@ -277,8 +283,6 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
         // have we managed to load any richedit version?
         if ( !s_errorGiven )
         {
-            msStyle |= ES_AUTOVSCROLL;
-
             m_verRichEdit = verRichEdit;
             if ( m_verRichEdit == 1 )
             {
@@ -397,9 +401,7 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
 
     long msStyle = wxControl::MSWGetStyle(style, exstyle);
 
-    // default styles
-    msStyle |= ES_LEFT;
-
+    // styles which we alaways add by default
     if ( style & wxTE_MULTILINE )
     {
         wxASSERT_MSG( !(style & wxTE_PROCESS_ENTER),
@@ -407,7 +409,18 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
 
         msStyle |= ES_MULTILINE | ES_WANTRETURN;
         if ( !(style & wxTE_NO_VSCROLL) )
-            msStyle |= WS_VSCROLL;
+        {
+            // always adjust the vertical scrollbar automatically if we have it
+            msStyle |= WS_VSCROLL | ES_AUTOVSCROLL;
+
+            // we have to use this style for the rich edit controls because
+            // without it the vertical scrollbar never appears at all in
+            // richedit 3.0 because of our ECO_NOHIDESEL hack (search for it)
+            if ( style & wxTE_RICH2 )
+            {
+                msStyle |= ES_DISABLENOSCROLL;
+            }
+        }
 
         style |= wxTE_PROCESS_ENTER;
     }
@@ -418,8 +431,12 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
         msStyle |= ES_AUTOHSCROLL;
     }
 
+    // styles which we add depending on the specified wxWindows styles
     if ( style & wxHSCROLL )
-        msStyle |= WS_HSCROLL | ES_AUTOHSCROLL;
+    {
+        // automatically scroll the control horizontally as necessary
+        msStyle |= WS_HSCROLL;// | ES_AUTOHSCROLL;
+    }
 
     if ( style & wxTE_READONLY )
         msStyle |= ES_READONLY;
@@ -427,23 +444,25 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
     if ( style & wxTE_PASSWORD )
         msStyle |= ES_PASSWORD;
 
-    if ( style & wxTE_AUTO_SCROLL )
-        msStyle |= ES_AUTOHSCROLL;
-
     if ( style & wxTE_NOHIDESEL )
         msStyle |= ES_NOHIDESEL;
 
+    // note that we can't do do "& wxTE_LEFT" as wxTE_LEFT == 0
     if ( style & wxTE_CENTRE )
         msStyle |= ES_CENTER;
-
-    if ( style & wxTE_RIGHT )
+    else if ( style & wxTE_RIGHT )
         msStyle |= ES_RIGHT;
+    else
+        msStyle |= ES_LEFT; // ES_LEFT if 0 as well but for consistency...
 
     return msStyle;
 }
 
 void wxTextCtrl::SetWindowStyleFlag(long style)
 {
+    if ( (style & wxBORDER_MASK) == wxBORDER_DEFAULT )
+        style |= wxBORDER_SUNKEN;
+
 #if wxUSE_RICHEDIT
     // we have to deal with some styles separately because they can't be
     // changed by simply calling SetWindowLong(GWL_STYLE) but can be changed
@@ -582,15 +601,6 @@ DWORD CALLBACK wxRichEditStreamIn(DWORD dwCookie, BYTE *buf, LONG cb, LONG *pcb)
 
 extern long wxEncodingToCodepage(wxFontEncoding encoding); // from utils.cpp
 
-#ifdef __WXWINE__
-bool wxTextCtrl::StreamIn(const wxString& value,
-                          wxFontEncoding WXUNUSED(encoding),
-                          bool selectionOnly)
-{
-    return FALSE;
-}
-#else // !__WXWINE__
-
 #if wxUSE_UNICODE_MSLU
 bool wxTextCtrl::StreamIn(const wxString& value,
                           wxFontEncoding WXUNUSED(encoding),
@@ -647,11 +657,13 @@ bool wxTextCtrl::StreamIn(const wxString& value,
         m_suppressNextUpdate = TRUE;
     }
 
-    if ( !::SendMessage(GetHwnd(), EM_STREAMIN,
-                        SF_TEXT |
-                        SF_UNICODE |
-                        (selectionOnly ? SFF_SELECTION : 0),
-                        (LPARAM)&eds) || eds.dwError )
+    ::SendMessage(GetHwnd(), EM_STREAMIN,
+                  SF_TEXT |
+                  SF_UNICODE |
+                  (selectionOnly ? SFF_SELECTION : 0),
+                  (LPARAM)&eds);
+
+    if ( eds.dwError )
     {
         wxLogLastError(_T("EM_STREAMIN"));
     }
@@ -663,8 +675,6 @@ bool wxTextCtrl::StreamIn(const wxString& value,
     return TRUE;
 }
 
-#endif // __WXWINE__/!__WXWINE__
 #endif // wxUSE_RICHEDIT
 
 void wxTextCtrl::WriteText(const wxString& value)
@@ -702,7 +712,7 @@ void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly)
         }
 #endif // wxUSE_UNICODE_MSLU
 
-#if !wxUSE_UNICODE && !defined(__WXWINE__)
+#if !wxUSE_UNICODE
         // next check if the text we're inserting must be shown in a non
         // default charset -- this only works for RichEdit > 1.0
         if ( GetRichVersion() > 1 )
@@ -753,7 +763,10 @@ void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly)
 #endif // wxUSE_RICHEDIT
            )
         {
-            SendUpdateEvent();
+            // Windows already sends an update event for single-line
+            // controls.
+            if ( m_windowStyle & wxTE_MULTILINE )
+                SendUpdateEvent();
         }
     }
 
@@ -787,7 +800,11 @@ void wxTextCtrl::Clear()
         // rich edit controls send EN_UPDATE from WM_SETTEXT handler themselves
         // but the normal ones don't -- make Clear() behaviour consistent by
         // always sending this event
-        SendUpdateEvent();
+
+        // Windows already sends an update event for single-line
+        // controls.
+        if ( m_windowStyle & wxTE_MULTILINE )
+            SendUpdateEvent();
     }
 }
 
@@ -897,6 +914,14 @@ void wxTextCtrl::SetInsertionPoint(long pos)
 
 void wxTextCtrl::SetInsertionPointEnd()
 {
+    // we must not do anything if the caret is already there because calling
+    // SetInsertionPoint() thaws the controls if Freeze() had been called even
+    // if it doesn't actually move the caret anywhere and so the simple fact of
+    // doing it results in horrible flicker when appending big amounts of text
+    // to the control in a few chunks (see DoAddText() test in the text sample)
+    if ( GetInsertionPoint() == GetLastPosition() )
+        return;
+
     long pos;
 
 #if wxUSE_RICHEDIT
@@ -1016,7 +1041,44 @@ void wxTextCtrl::DoSetSelection(long from, long to, bool scrollCaret)
 
     if ( scrollCaret )
     {
+#if wxUSE_RICHEDIT
+        // richedit 3.0 (i.e. the version living in riched20.dll distributed
+        // with Windows 2000 and beyond) doesn't honour EM_SCROLLCARET when
+        // emulating richedit 2.0 unless the control has focus or ECO_NOHIDESEL
+        // option is set (but it does work ok in richedit 1.0 mode...)
+        //
+        // so to make it work we either need to give focus to it here which
+        // will probably create many problems (dummy focus events; window
+        // containing the text control being brought to foreground
+        // unexpectedly; ...) or to temporarily set ECO_NOHIDESEL which may
+        // create other problems too -- and in fact it does because if we turn
+        // on/off this style while appending the text to the control, the
+        // vertical scrollbar never appears in it even if we append tons of
+        // text and to work around this the only solution I found was to use
+        // ES_DISABLENOSCROLL
+        //
+        // this is very ugly but I don't see any other way to make this work
+        if ( GetRichVersion() > 1 )
+        {
+            if ( !HasFlag(wxTE_NOHIDESEL) )
+            {
+                ::SendMessage(GetHwnd(), EM_SETOPTIONS,
+                              ECOOP_OR, ECO_NOHIDESEL);
+            }
+            //else: everything is already ok
+        }
+#endif // wxUSE_RICHEDIT
+
         SendMessage(hWnd, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);
+
+#if wxUSE_RICHEDIT
+        // restore ECO_NOHIDESEL if we changed it
+        if ( GetRichVersion() > 1 && !HasFlag(wxTE_NOHIDESEL) )
+        {
+            ::SendMessage(GetHwnd(), EM_SETOPTIONS,
+                          ECOOP_AND, ~ECO_NOHIDESEL);
+        }
+#endif // wxUSE_RICHEDIT
     }
 #else // Win16
     // WPARAM is 0: selection is scrolled into view
@@ -1301,7 +1363,7 @@ bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* pMsg)
 
 void wxTextCtrl::OnChar(wxKeyEvent& event)
 {
-    switch ( event.KeyCode() )
+    switch ( event.GetKeyCode() )
     {
         case WXK_RETURN:
             if ( !(m_windowStyle & wxTE_MULTILINE) )
@@ -1564,8 +1626,10 @@ bool wxTextCtrl::AdjustSpaceLimit()
 
 bool wxTextCtrl::AcceptsFocus() const
 {
-    // we don't want focus if we can't be edited
-    return IsEditable() && wxControl::AcceptsFocus();
+    // we don't want focus if we can't be edited unless we're a multiline
+    // control because then it might be still nice to get focus from keyboard
+    // to be able to scroll it without mouse
+    return (IsEditable() || IsMultiLine()) && wxControl::AcceptsFocus();
 }
 
 wxSize wxTextCtrl::DoGetBestSize() const
@@ -1699,7 +1763,6 @@ void wxTextCtrl::OnRightClick(wxMouseEvent& event)
 
 bool wxTextCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 {
-#ifndef __WXWINE__
     NMHDR *hdr = (NMHDR* )lParam;
     switch ( hdr->code )
     {
@@ -1786,7 +1849,6 @@ bool wxTextCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
             }
             return TRUE;
     }
-#endif
     
     // not processed, leave it to the base class
     return wxTextCtrlBase::MSWOnNotify(idCtrl, lParam, result);
@@ -1844,9 +1906,6 @@ bool wxTextCtrl::SetForegroundColour(const wxColour& colour)
 
 bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
 {
-#ifdef __WXWINE__
-    return FALSE;
-#else
     if ( !IsRich() )
     {
         // can't do it with normal text control
@@ -1976,7 +2035,6 @@ bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
     }
 
     return ok;
-#endif
 }
 
 bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)