+ 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 )
+ {
+#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
+ 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,