]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/textctrl.cpp
More key event work. Added SetDetectableAutoRepeat.
[wxWidgets.git] / src / msw / textctrl.cpp
index bfb35eaa50dd0757b10b00cc22ccd5c66ad60f9d..8a4f405bd46ff55914601496cf5639e670b0bdf3 100644 (file)
 #endif
 
 #if !USE_SHARED_LIBRARY
 #endif
 
 #if !USE_SHARED_LIBRARY
+
 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
 
 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
   EVT_CHAR(wxTextCtrl::OnChar)
   EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
   EVT_ERASE_BACKGROUND(wxTextCtrl::OnEraseBackground)
 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
 
 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
   EVT_CHAR(wxTextCtrl::OnChar)
   EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
   EVT_ERASE_BACKGROUND(wxTextCtrl::OnEraseBackground)
+
+  EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
+  EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
+  EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
+  EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
+  EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
+
+  EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
+  EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
+  EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
+  EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
+  EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
 END_EVENT_TABLE()
 END_EVENT_TABLE()
+
 #endif // USE_SHARED_LIBRARY
 
 // Text item
 #endif // USE_SHARED_LIBRARY
 
 // Text item
@@ -363,20 +377,29 @@ void wxTextCtrl::DoSetSize(int x, int y, int width, int height, int sizeFlags)
 // Clipboard operations
 void wxTextCtrl::Copy()
 {
 // Clipboard operations
 void wxTextCtrl::Copy()
 {
-  HWND hWnd = (HWND) GetHWND();
-  SendMessage(hWnd, WM_COPY, 0, 0L);
+    if (CanCopy())
+    {
+        HWND hWnd = (HWND) GetHWND();
+        SendMessage(hWnd, WM_COPY, 0, 0L);
+    }
 }
 
 void wxTextCtrl::Cut()
 {
 }
 
 void wxTextCtrl::Cut()
 {
-  HWND hWnd = (HWND) GetHWND();
-  SendMessage(hWnd, WM_CUT, 0, 0L);
+    if (CanCut())
+    {
+        HWND hWnd = (HWND) GetHWND();
+        SendMessage(hWnd, WM_CUT, 0, 0L);
+    }
 }
 
 void wxTextCtrl::Paste()
 {
 }
 
 void wxTextCtrl::Paste()
 {
-  HWND hWnd = (HWND) GetHWND();
-  SendMessage(hWnd, WM_PASTE, 0, 0L);
+    if (CanPaste())
+    {
+        HWND hWnd = (HWND) GetHWND();
+        SendMessage(hWnd, WM_PASTE, 0, 0L);
+    }
 }
 
 void wxTextCtrl::SetEditable(bool editable)
 }
 
 void wxTextCtrl::SetEditable(bool editable)
@@ -443,7 +466,7 @@ long wxTextCtrl::GetLastPosition() const
 
     // This gets the char index for the _beginning_ of the last line
     int charIndex = (int)SendMessage(hWnd, EM_LINEINDEX, (WPARAM)(noLines-1), (LPARAM)0L);
 
     // This gets the char index for the _beginning_ of the last line
     int charIndex = (int)SendMessage(hWnd, EM_LINEINDEX, (WPARAM)(noLines-1), (LPARAM)0L);
-    
+
     // Get number of characters in the last line. We'll add this to the character
     // index for the last line, 1st position.
     int lineLength = (int)SendMessage(hWnd, EM_LINELENGTH, (WPARAM)charIndex, (LPARAM)0L);
     // Get number of characters in the last line. We'll add this to the character
     // index for the last line, 1st position.
     int lineLength = (int)SendMessage(hWnd, EM_LINELENGTH, (WPARAM)charIndex, (LPARAM)0L);
@@ -457,7 +480,7 @@ void wxTextCtrl::Replace(long from, long to, const wxString& value)
     HWND hWnd = (HWND) GetHWND();
     long fromChar = from;
     long toChar = to;
     HWND hWnd = (HWND) GetHWND();
     long fromChar = from;
     long toChar = to;
-    
+
     // Set selection and remove it
 #ifdef __WIN32__
     SendMessage(hWnd, EM_SETSEL, fromChar, toChar);
     // Set selection and remove it
 #ifdef __WIN32__
     SendMessage(hWnd, EM_SETSEL, fromChar, toChar);
@@ -481,7 +504,7 @@ void wxTextCtrl::Remove(long from, long to)
     HWND hWnd = (HWND) GetHWND();
     long fromChar = from;
     long toChar = to;
     HWND hWnd = (HWND) GetHWND();
     long fromChar = from;
     long toChar = to;
-    
+
     // Cut all selected text
 #ifdef __WIN32__
     SendMessage(hWnd, EM_SETSEL, fromChar, toChar);
     // Cut all selected text
 #ifdef __WIN32__
     SendMessage(hWnd, EM_SETSEL, fromChar, toChar);
@@ -504,7 +527,7 @@ void wxTextCtrl::SetSelection(long from, long to)
       fromChar = 0;
       toChar = -1;
     }
       fromChar = 0;
       toChar = -1;
     }
-    
+
 #ifdef __WIN32__
     SendMessage(hWnd, EM_SETSEL, (WPARAM)fromChar, (LPARAM)toChar);
     SendMessage(hWnd, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);
 #ifdef __WIN32__
     SendMessage(hWnd, EM_SETSEL, (WPARAM)fromChar, (LPARAM)toChar);
     SendMessage(hWnd, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);
@@ -659,7 +682,7 @@ void wxTextCtrl::DiscardEdits()
  * Some of the following functions are yet to be implemented
  *
  */
  * Some of the following functions are yet to be implemented
  *
  */
+
 int wxTextCtrl::GetNumberOfLines() const
 {
     return (int)SendMessage((HWND) GetHWND(), EM_GETLINECOUNT, (WPARAM)0, (LPARAM)0);
 int wxTextCtrl::GetNumberOfLines() const
 {
     return (int)SendMessage((HWND) GetHWND(), EM_GETLINECOUNT, (WPARAM)0, (LPARAM)0);
@@ -705,11 +728,11 @@ void wxTextCtrl::ShowPosition(long pos)
     int currentLineLineNo = (int)SendMessage(hWnd, EM_GETFIRSTVISIBLELINE, (WPARAM)0, (LPARAM)0L);
 
     int specifiedLineLineNo = (int)SendMessage(hWnd, EM_LINEFROMCHAR, (WPARAM)pos, (LPARAM)0L);
     int currentLineLineNo = (int)SendMessage(hWnd, EM_GETFIRSTVISIBLELINE, (WPARAM)0, (LPARAM)0L);
 
     int specifiedLineLineNo = (int)SendMessage(hWnd, EM_LINEFROMCHAR, (WPARAM)pos, (LPARAM)0L);
-    
+
     int linesToScroll = specifiedLineLineNo - currentLineLineNo;
 
     if (linesToScroll != 0)
     int linesToScroll = specifiedLineLineNo - currentLineLineNo;
 
     if (linesToScroll != 0)
-      (void)SendMessage(hWnd, EM_LINESCROLL, (WPARAM)0, (LPARAM)MAKELPARAM(linesToScroll, 0));
+      (void)SendMessage(hWnd, EM_LINESCROLL, (WPARAM)0, (LPARAM)linesToScroll);
 }
 
 int wxTextCtrl::GetLineLength(long lineNo) const
 }
 
 int wxTextCtrl::GetLineLength(long lineNo) const
@@ -729,10 +752,104 @@ wxString wxTextCtrl::GetLineText(long lineNo) const
   return wxString(wxBuffer);
 }
 
   return wxString(wxBuffer);
 }
 
-/*
- * Text item
- */
+bool wxTextCtrl::CanCopy() const
+{
+    // Can copy if there's a selection
+    long from, to;
+    GetSelection(& from, & to);
+    return (from != to) ;
+}
+
+bool wxTextCtrl::CanCut() const
+{
+    // Can cut if there's a selection
+    long from, to;
+    GetSelection(& from, & to);
+    return (from != to) ;
+}
+
+bool wxTextCtrl::CanPaste() const
+{
+#if wxUSE_RICHEDIT
+    if (m_isRich)
+    {
+        int dataFormat = 0; // 0 == any format
+        return (::SendMessage( (HWND) GetHWND(), EM_CANPASTE, (WPARAM) (UINT) dataFormat, 0) != 0);
+    }
+#endif
+    if (!IsEditable())
+        return FALSE;
+
+    // Standard edit control: check for straight text on clipboard
+    bool isTextAvailable = FALSE;
+    if (::OpenClipboard((HWND) wxTheApp->GetTopWindow()->GetHWND()))
+    {
+        isTextAvailable = (::IsClipboardFormatAvailable(CF_TEXT) != 0);
+        ::CloseClipboard();
+    }
+    return isTextAvailable;
+}
+
+// Undo/redo
+void wxTextCtrl::Undo()
+{
+    if (CanUndo())
+    {
+        ::SendMessage((HWND) GetHWND(), EM_UNDO, 0, 0);
+    }
+}
+
+void wxTextCtrl::Redo()
+{
+    if (CanRedo())
+    {
+        // Same as Undo, since Undo undoes the undo, i.e. a redo.
+        ::SendMessage((HWND) GetHWND(), EM_UNDO, 0, 0);
+    }
+}
+
+bool wxTextCtrl::CanUndo() const
+{
+    return (::SendMessage((HWND) GetHWND(), EM_CANUNDO, 0, 0) != 0);
+}
+
+bool wxTextCtrl::CanRedo() const
+{
+    return (::SendMessage((HWND) GetHWND(), EM_CANUNDO, 0, 0) != 0);
+}
+
+// If the return values from and to are the same, there is no
+// selection.
+void wxTextCtrl::GetSelection(long* from, long* to) const
+{
+#if wxUSE_RICHEDIT
+    if (m_isRich)
+    {
+        CHARRANGE charRange;
+        ::SendMessage((HWND) GetHWND(), EM_EXGETSEL, 0, (LPARAM) (CHARRANGE*) & charRange);
+
+        *from = charRange.cpMin;
+        *to = charRange.cpMax;
+
+        return;
+    }
+#endif
+    DWORD dwStart, dwEnd;
+    WPARAM wParam = (WPARAM) (DWORD*) & dwStart; // receives starting position
+    LPARAM lParam = (LPARAM) (DWORD*) & dwEnd;   // receives ending position
+
+    ::SendMessage((HWND) GetHWND(), EM_GETSEL, wParam, lParam);
+
+    *from = dwStart;
+    *to = dwEnd;
+}
+
+bool wxTextCtrl::IsEditable() const
+{
+    long style = ::GetWindowLong((HWND) GetHWND(), GWL_STYLE);
+    return ((style & ES_READONLY) == 0);
+}
+
 void wxTextCtrl::Command(wxCommandEvent & event)
 {
   SetValue (event.GetString());
 void wxTextCtrl::Command(wxCommandEvent & event)
 {
   SetValue (event.GetString());
@@ -752,7 +869,7 @@ void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
 // AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers
 
 //=========================================================================
 // AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers
 
 //=========================================================================
-// Called then the buffer is full (gcc 2.6.3) 
+// Called then the buffer is full (gcc 2.6.3)
 // or when "endl" is output (Borland 4.5)
 //=========================================================================
 // Class declaration using multiple inheritance doesn't work properly for
 // or when "endl" is output (Borland 4.5)
 //=========================================================================
 // Class declaration using multiple inheritance doesn't work properly for
@@ -770,7 +887,7 @@ int wxTextCtrl::overflow(int c)
     return EOF;
   }
 #endif
     return EOF;
   }
 #endif
-  
+
   // Verify that there are no characters in get area
   if ( gptr() && gptr() < egptr() )
   {
   // Verify that there are no characters in get area
   if ( gptr() && gptr() < egptr() )
   {
@@ -955,28 +1072,8 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
 {
     switch( event.KeyCode() )
     {
 {
     switch( event.KeyCode() )
     {
-        // Fix by Marcel Rasche to allow Alt-Ctrl insertion of special characters
-        case '{':
-        case '}':
-        case '[':
-        case ']':
-        case '|':
-        case '~':
-        case '\\':
-            {
-                char c = (char)event.KeyCode();
-                WriteText(c);
-            }
-            break;
-
         case WXK_RETURN:
         case WXK_RETURN:
-        {
-/* Oh yes it will, because we also specify DLGC_WANTCHARS
-            wxASSERT_MSG( m_windowStyle & wxTE_PROCESS_ENTER,
-                          "this text ctrl should never receive return" );
-*/
-
-            if ( (m_windowStyle & wxTE_MULTILINE) == 0 )
+            if ( !(m_windowStyle & wxTE_MULTILINE) )
             {
                 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
                 event.SetEventObject( this );
             {
                 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
                 event.SetEventObject( this );
@@ -986,7 +1083,7 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
             //else: multiline controls need Enter for themselves
 
             break;
             //else: multiline controls need Enter for themselves
 
             break;
-        }
+
         case WXK_TAB:
             // only produce navigation event if we don't process TAB ourself or
             // if it's a Shift-Tab keypress (we assume nobody will ever need
         case WXK_TAB:
             // only produce navigation event if we don't process TAB ourself or
             // if it's a Shift-Tab keypress (we assume nobody will ever need
@@ -1000,13 +1097,17 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
                 eventNav.SetDirection(!event.ShiftDown());
                 eventNav.SetWindowChange(FALSE);
                 eventNav.SetEventObject(this);
                 eventNav.SetDirection(!event.ShiftDown());
                 eventNav.SetWindowChange(FALSE);
                 eventNav.SetEventObject(this);
-    
+
                 if ( GetEventHandler()->ProcessEvent(eventNav) )
                     return;
             }
             break;
                 if ( GetEventHandler()->ProcessEvent(eventNav) )
                     return;
             }
             break;
+
+        default:
+            event.Skip();
+            return;
     }
     }
-    
+
     // don't just call event.Skip() because this will cause TABs and ENTERs
     // be passed upwards and we don't always want this - instead process it
     // right here
     // don't just call event.Skip() because this will cause TABs and ENTERs
     // be passed upwards and we don't always want this - instead process it
     // right here
@@ -1030,7 +1131,7 @@ long wxTextCtrl::MSWGetDlgCode()
         lRc |= DLGC_WANTMESSAGE;
     if ( m_windowStyle & wxTE_PROCESS_TAB )
         lRc |= DLGC_WANTTAB;
         lRc |= DLGC_WANTMESSAGE;
     if ( m_windowStyle & wxTE_PROCESS_TAB )
         lRc |= DLGC_WANTTAB;
-    
+
     return lRc;
 }
 
     return lRc;
 }
 
@@ -1133,7 +1234,7 @@ bool wxTextCtrl::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
 // For Rich Edit controls. Do we need it?
 #if 0
 #if wxUSE_RICHEDIT
 // For Rich Edit controls. Do we need it?
 #if 0
 #if wxUSE_RICHEDIT
-bool wxTextCtrl::MSWNotify(WXWPARAM wParam, WXLPARAM lParam)
+bool wxTextCtrl::MSWOnNotify(WXWPARAM wParam, WXLPARAM lParam)
 {
   wxCommandEvent event(0, m_windowId);
   int eventType = 0;
 {
   wxCommandEvent event(0, m_windowId);
   int eventType = 0;
@@ -1142,7 +1243,7 @@ bool wxTextCtrl::MSWNotify(WXWPARAM wParam, WXLPARAM lParam)
   {
     // Insert case code here
     default :
   {
     // Insert case code here
     default :
-      return wxControl::MSWNotify(wParam, lParam);
+      return wxControl::MSWOnNotify(wParam, lParam);
       break;
   }
 
       break;
   }
 
@@ -1157,3 +1258,53 @@ bool wxTextCtrl::MSWNotify(WXWPARAM wParam, WXLPARAM lParam)
 #endif
 #endif
 
 #endif
 #endif
 
+void wxTextCtrl::OnCut(wxCommandEvent& event)
+{
+    Cut();
+}
+
+void wxTextCtrl::OnCopy(wxCommandEvent& event)
+{
+    Copy();
+}
+
+void wxTextCtrl::OnPaste(wxCommandEvent& event)
+{
+    Paste();
+}
+
+void wxTextCtrl::OnUndo(wxCommandEvent& event)
+{
+    Undo();
+}
+
+void wxTextCtrl::OnRedo(wxCommandEvent& event)
+{
+    Redo();
+}
+
+void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
+{
+    event.Enable( CanCut() );
+}
+
+void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
+{
+    event.Enable( CanCopy() );
+}
+
+void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
+{
+    event.Enable( CanPaste() );
+}
+
+void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
+{
+    event.Enable( CanUndo() );
+}
+
+void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
+{
+    event.Enable( CanRedo() );
+}
+