+ return CanCopy() && IsEditable();
+}
+
+bool wxTextCtrl::CanPaste() const
+{
+ if ( !IsEditable() )
+ return FALSE;
+
+#if wxUSE_RICHEDIT
+ if ( IsRich() )
+ {
+ UINT cf = 0; // 0 == any format
+
+ return ::SendMessage(GetHwnd(), EM_CANPASTE, cf, 0) != 0;
+ }
+#endif // wxUSE_RICHEDIT
+
+ // Standard edit control: check for straight text on clipboard
+ if ( !::OpenClipboard(GetHwndOf(wxTheApp->GetTopWindow())) )
+ return FALSE;
+
+ bool isTextAvailable = ::IsClipboardFormatAvailable(CF_TEXT) != 0;
+ ::CloseClipboard();
+
+ return isTextAvailable;
+}
+
+// ----------------------------------------------------------------------------
+// Accessors
+// ----------------------------------------------------------------------------
+
+void wxTextCtrl::SetEditable(bool editable)
+{
+ HWND hWnd = GetHwnd();
+ SendMessage(hWnd, EM_SETREADONLY, (WPARAM)!editable, (LPARAM)0L);
+}
+
+void wxTextCtrl::SetInsertionPoint(long pos)
+{
+ DoSetSelection(pos, pos);
+}
+
+void wxTextCtrl::SetInsertionPointEnd()
+{
+ long pos;
+
+#if wxUSE_RICHEDIT
+ if ( m_verRichEdit == 1 )
+ {
+ // we don't have to waste time calling GetLastPosition() in this case
+ pos = -1;
+ }
+ else // !RichEdit 1.0
+#endif // wxUSE_RICHEDIT
+ {
+ pos = GetLastPosition();
+ }
+
+ SetInsertionPoint(pos);
+}
+
+long wxTextCtrl::GetInsertionPoint() const
+{
+#if wxUSE_RICHEDIT
+ if ( IsRich() )
+ {
+ CHARRANGE range;
+ range.cpMin = 0;
+ range.cpMax = 0;
+ SendMessage(GetHwnd(), EM_EXGETSEL, 0, (LPARAM) &range);
+ return range.cpMin;
+ }
+#endif // wxUSE_RICHEDIT
+
+ DWORD Pos = (DWORD)SendMessage(GetHwnd(), EM_GETSEL, 0, 0L);
+ return Pos & 0xFFFF;
+}
+
+long wxTextCtrl::GetLastPosition() const
+{
+ int numLines = GetNumberOfLines();
+ long posStartLastLine = XYToPosition(0, numLines - 1);
+
+ long lenLastLine = GetLengthOfLineContainingPos(posStartLastLine);
+
+ return posStartLastLine + lenLastLine;
+}
+
+// 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 ( IsRich() )
+ {
+ CHARRANGE charRange;
+ ::SendMessage(GetHwnd(), EM_EXGETSEL, 0, (LPARAM) &charRange);
+
+ *from = charRange.cpMin;
+ *to = charRange.cpMax;
+ }
+ else
+#endif // !wxUSE_RICHEDIT
+ {
+ DWORD dwStart, dwEnd;
+ ::SendMessage(GetHwnd(), EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
+
+ *from = dwStart;
+ *to = dwEnd;
+ }
+}
+
+bool wxTextCtrl::IsEditable() const
+{
+ // strangely enough, we may be called before the control is created: our
+ // own Create() calls MSWGetStyle() which calls AcceptsFocus() which calls
+ // us
+ if ( !m_hWnd )
+ return TRUE;
+
+ long style = ::GetWindowLong(GetHwnd(), GWL_STYLE);
+
+ return (style & ES_READONLY) == 0;
+}
+
+// ----------------------------------------------------------------------------
+// selection
+// ----------------------------------------------------------------------------
+
+void wxTextCtrl::SetSelection(long from, long to)
+{
+ // if from and to are both -1, it means (in wxWindows) that all text should
+ // be selected - translate into Windows convention
+ if ( (from == -1) && (to == -1) )
+ {
+ from = 0;
+ to = -1;
+ }
+
+ DoSetSelection(from, to);
+}
+
+void wxTextCtrl::DoSetSelection(long from, long to, bool scrollCaret)
+{
+ HWND hWnd = GetHwnd();
+
+#ifdef __WIN32__
+#if wxUSE_RICHEDIT
+ if ( IsRich() )
+ {
+ CHARRANGE range;
+ range.cpMin = from;
+ range.cpMax = to;
+ SendMessage(hWnd, EM_EXSETSEL, 0, (LPARAM) &range);
+ }
+ else
+#endif // wxUSE_RICHEDIT
+ {
+ SendMessage(hWnd, EM_SETSEL, (WPARAM)from, (LPARAM)to);
+ }
+
+ if ( scrollCaret )
+ {
+ SendMessage(hWnd, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);
+ }
+#else // Win16
+ // WPARAM is 0: selection is scrolled into view
+ SendMessage(hWnd, EM_SETSEL, (WPARAM)0, (LPARAM)MAKELONG(from, to));
+#endif // Win32/16
+}
+
+// ----------------------------------------------------------------------------
+// Editing
+// ----------------------------------------------------------------------------
+
+void wxTextCtrl::Replace(long from, long to, const wxString& value)
+{
+ // Set selection and remove it
+ DoSetSelection(from, to, FALSE /* don't scroll caret into view */);
+
+ SendMessage(GetHwnd(), EM_REPLACESEL,
+#ifdef __WIN32__
+ TRUE,
+#else
+ FALSE,
+#endif
+ (LPARAM)value.c_str());
+}
+
+void wxTextCtrl::Remove(long from, long to)
+{
+ Replace(from, to, _T(""));
+}
+
+bool wxTextCtrl::LoadFile(const wxString& file)
+{
+ if ( wxTextCtrlBase::LoadFile(file) )
+ {
+ // update the size limit if needed
+ AdjustSpaceLimit();
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+bool wxTextCtrl::IsModified() const
+{
+ return SendMessage(GetHwnd(), EM_GETMODIFY, 0, 0) != 0;
+}
+
+// Makes 'unmodified'
+void wxTextCtrl::DiscardEdits()
+{
+ SendMessage(GetHwnd(), EM_SETMODIFY, FALSE, 0L);
+}
+
+int wxTextCtrl::GetNumberOfLines() const
+{
+ return (int)SendMessage(GetHwnd(), EM_GETLINECOUNT, (WPARAM)0, (LPARAM)0);
+}
+
+long wxTextCtrl::XYToPosition(long x, long y) const
+{
+ // This gets the char index for the _beginning_ of this line
+ long charIndex = SendMessage(GetHwnd(), EM_LINEINDEX, (WPARAM)y, (LPARAM)0);
+
+ return charIndex + x;
+}
+
+bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
+{
+ HWND hWnd = GetHwnd();
+
+ // This gets the line number containing the character
+ long lineNo;
+#if wxUSE_RICHEDIT
+ if ( IsRich() )
+ {
+ lineNo = SendMessage(hWnd, EM_EXLINEFROMCHAR, 0, (LPARAM)pos);
+ }
+ else
+#endif // wxUSE_RICHEDIT
+ {
+ lineNo = SendMessage(hWnd, EM_LINEFROMCHAR, (WPARAM)pos, 0);
+ }
+
+ if ( lineNo == -1 )
+ {
+ // no such line
+ return FALSE;
+ }
+
+ // This gets the char index for the _beginning_ of this line
+ long charIndex = SendMessage(hWnd, EM_LINEINDEX, (WPARAM)lineNo, (LPARAM)0);
+ if ( charIndex == -1 )
+ {
+ return FALSE;
+ }
+
+ // The X position must therefore be the different between pos and charIndex
+ if ( x )
+ *x = pos - charIndex;
+ if ( y )
+ *y = lineNo;
+
+ return TRUE;