X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/52a9e329880e977194c214f7761f40b67ac2a815..37c2a8dab05154b396e20a9de1de7a10adb2b88a:/src/msw/textctrl.cpp?ds=inline diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index 3b0c9572ea..f7c7cb3ada 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -199,9 +199,6 @@ BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo) EVT_UPDATE_UI(wxID_CLEAR, wxTextCtrl::OnUpdateDelete) EVT_UPDATE_UI(wxID_SELECTALL, wxTextCtrl::OnUpdateSelectAll) -#ifdef __WIN16__ - EVT_ERASE_BACKGROUND(wxTextCtrl::OnEraseBackground) -#endif EVT_SET_FOCUS(wxTextCtrl::OnSetFocus) END_EVENT_TABLE() @@ -637,6 +634,9 @@ void wxTextCtrl::SetValue(const wxString& value) if ( (value.length() > 0x400) || (value != GetValue()) ) { DoWriteText(value, FALSE /* not selection only */); + + // for compatibility, don't move the cursor when doing SetValue() + SetInsertionPoint(0); } else // same text { @@ -649,9 +649,6 @@ void wxTextCtrl::SetValue(const wxString& value) // mark the control as being not dirty - we changed its text, not the // user DiscardEdits(); - - // for compatibility, don't move the cursor when doing SetValue() - SetInsertionPoint(0); } #if wxUSE_RICHEDIT && (!wxUSE_UNICODE || wxUSE_UNICODE_MSLU) @@ -688,7 +685,7 @@ struct wxStreamOutData }; DWORD CALLBACK -wxRichEditStreamOut(DWORD dwCookie, BYTE *buf, LONG cb, LONG *pcb) +wxRichEditStreamOut(DWORD_PTR dwCookie, BYTE *buf, LONG cb, LONG *pcb) { *pcb = 0; @@ -822,13 +819,13 @@ wxTextCtrl::StreamOut(wxFontEncoding encoding, bool selectionOnly) const // decreased by wxRichEditStreamOut *(wchBuf.data() + data.len) = L'\0'; - // now convert to the given encoding (this is a lossful conversion but - // what else can we do) + // now convert to the given encoding (this is a possibly lossful + // conversion but what else can we do) wxCSConv conv(encoding); - size_t lenNeeded = conv.WC2MB(NULL, wchBuf, len); - if ( lenNeeded ) + size_t lenNeeded = conv.WC2MB(NULL, wchBuf, 0); + if ( lenNeeded++ ) { - conv.WC2MB(wxStringBuffer(out, lenNeeded), wchBuf, len); + conv.WC2MB(wxStringBuffer(out, lenNeeded), wchBuf, lenNeeded); } } @@ -1194,7 +1191,6 @@ void wxTextCtrl::DoSetSelection(long from, long to, bool scrollCaret) { HWND hWnd = GetHwnd(); -#ifdef __WIN32__ #if wxUSE_RICHEDIT if ( IsRich() ) { @@ -1250,10 +1246,23 @@ void wxTextCtrl::DoSetSelection(long from, long to, bool scrollCaret) } #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 +} + +// ---------------------------------------------------------------------------- +// Working with files +// ---------------------------------------------------------------------------- + +bool wxTextCtrl::LoadFile(const wxString& file) +{ + if ( wxTextCtrlBase::LoadFile(file) ) + { + // update the size limit if needed + AdjustSpaceLimit(); + + return TRUE; + } + + return FALSE; } // ---------------------------------------------------------------------------- @@ -1273,19 +1282,6 @@ void wxTextCtrl::Remove(long from, long to) Replace(from, to, wxEmptyString); } -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; @@ -1306,6 +1302,10 @@ int wxTextCtrl::GetNumberOfLines() const return (int)SendMessage(GetHwnd(), EM_GETLINECOUNT, (WPARAM)0, (LPARAM)0); } +// ---------------------------------------------------------------------------- +// Positions <-> coords +// ---------------------------------------------------------------------------- + long wxTextCtrl::XYToPosition(long x, long y) const { // This gets the char index for the _beginning_ of this line @@ -1353,6 +1353,99 @@ bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const return TRUE; } +wxTextCtrlHitTestResult +wxTextCtrl::HitTest(const wxPoint& pt, wxTextCoord *col, wxTextCoord *row) const +{ + // first get the position from Windows + LPARAM lParam; + +#if wxUSE_RICHEDIT + POINTL ptl; + if ( IsRich() ) + { + // for rich edit controls the position is passed iva the struct fields + ptl.x = pt.x; + ptl.y = pt.y; + lParam = (LPARAM)&ptl; + } + else +#endif // wxUSE_RICHEDIT + { + // for the plain ones, we are limited to 16 bit positions which are + // combined in a single 32 bit value + lParam = MAKELPARAM(pt.x, pt.y); + } + + LRESULT pos = SendMessage(GetHwnd(), EM_CHARFROMPOS, 0, lParam); + + if ( pos == -1 ) + { + // this seems to indicate an error... + return wxTE_HT_UNKNOWN; + } + +#if wxUSE_RICHEDIT + if ( !IsRich() ) +#endif // wxUSE_RICHEDIT + { + // for plain EDIT controls the higher word contains something else + pos = LOWORD(pos); + } + + + // next determine where it is relatively to our point: EM_CHARFROMPOS + // always returns the closest character but we need to be more precise, so + // double check that we really are where it pretends + POINTL ptReal; + +#if wxUSE_RICHEDIT + // FIXME: we need to distinguish between richedit 2 and 3 here somehow but + // we don't know how to do it + if ( IsRich() ) + { + SendMessage(GetHwnd(), EM_POSFROMCHAR, (WPARAM)&ptReal, pos); + } + else +#endif // wxUSE_RICHEDIT + { + LRESULT lRc = SendMessage(GetHwnd(), EM_POSFROMCHAR, pos, 0); + + if ( lRc == -1 ) + { + // this is apparently returned when pos corresponds to the last + // position + ptReal.x = + ptReal.y = 0; + } + else + { + ptReal.x = LOWORD(lRc); + ptReal.y = HIWORD(lRc); + } + } + + wxTextCtrlHitTestResult rc; + + if ( pt.y > ptReal.y + GetCharHeight() ) + rc = wxTE_HT_BELOW; + else if ( pt.x > ptReal.x + GetCharWidth() ) + rc = wxTE_HT_BEYOND; + else + rc = wxTE_HT_ON_TEXT; + + // finally translate to column/row + if ( !PositionToXY(pos, col, row) ) + { + wxFAIL_MSG( _T("PositionToXY() not expected to fail in HitTest()") ); + } + + return rc; +} + +// ---------------------------------------------------------------------------- +// +// ---------------------------------------------------------------------------- + void wxTextCtrl::ShowPosition(long pos) { HWND hWnd = GetHwnd(); @@ -1578,7 +1671,7 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) switch ( event.GetKeyCode() ) { case WXK_RETURN: - if ( !(m_windowStyle & wxTE_MULTILINE) ) + if ( !HasFlag(wxTE_MULTILINE) ) { wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); InitCommandEvent(event); @@ -1591,10 +1684,26 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) break; case WXK_TAB: - // always produce navigation event - even if we process TAB + // always produce navigation event -- even if we process TAB // ourselves the fact that we got here means that the user code - // decided to skip processing of this TAB - probably to let it + // decided to skip processing of this TAB -- probably to let it // do its default job. + + // ok, so this is getting absolutely ridiculous but I don't see + // any other way to fix this bug: when a multiline text control is + // inside a wxFrame, we need to generate the navigation event as + // otherwise nothing happens at all, but when the same control is + // created inside a dialog, IsDialogMessage() *does* switch focus + // all by itself and so if we do it here as well, it is advanced + // twice and goes to the next control... to prevent this from + // happening we're doing this ugly check, the logic being that if + // we don't have focus then it had been already changed to the next + // control + // + // the right thing to do would, of course, be to understand what + // the hell is IsDialogMessage() doing but this is beyond my feeble + // forces at the moment unfortunately + if ( FindFocus() == this ) { wxNavigationKeyEvent eventNav; eventNav.SetDirection(!event.ShiftDown()); @@ -1611,9 +1720,9 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) event.Skip(); } -long wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { - long lRc = wxTextCtrlBase::MSWWindowProc(nMsg, wParam, lParam); + WXLRESULT lRc = wxTextCtrlBase::MSWWindowProc(nMsg, wParam, lParam); if ( nMsg == WM_GETDLGCODE ) { @@ -1750,40 +1859,8 @@ WXHBRUSH wxTextCtrl::OnCtlColor(WXHDC pDC, WXHWND WXUNUSED(pWnd), WXUINT WXUNUSE return (WXHBRUSH)brush->GetResourceHandle(); } -// In WIN16, need to override normal erasing because -// Ctl3D doesn't use the wxWindows background colour. -#ifdef __WIN16__ -void wxTextCtrl::OnEraseBackground(wxEraseEvent& event) -{ - wxColour col(m_backgroundColour); - -#if wxUSE_CTL3D - if (m_useCtl3D) - col = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); -#endif - - RECT rect; - ::GetClientRect(GetHwnd(), &rect); - - COLORREF ref = wxColourToRGB(col); - HBRUSH hBrush = ::CreateSolidBrush(ref); - if ( !hBrush ) - wxLogLastError(wxT("CreateSolidBrush")); - - HDC hdc = (HDC)event.GetDC()->GetHDC(); - - int mode = ::SetMapMode(hdc, MM_TEXT); - - ::FillRect(hdc, &rect, hBrush); - ::DeleteObject(hBrush); - ::SetMapMode(hdc, mode); - -} -#endif // Win16 - bool wxTextCtrl::AdjustSpaceLimit() { -#ifndef __WIN16__ unsigned int limit = ::SendMessage(GetHwnd(), EM_GETLIMITTEXT, 0, 0); // HACK: we try to automatically extend the limit for the amount of text @@ -1825,7 +1902,6 @@ bool wxTextCtrl::AdjustSpaceLimit() ::SendMessage(GetHwnd(), EM_LIMITTEXT, limit, 0); } } -#endif // !Win16 // we changed the limit return TRUE; @@ -1846,13 +1922,17 @@ wxSize wxTextCtrl::DoGetBestSize() const int wText = DEFAULT_ITEM_WIDTH; - int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy); + int hText = cy; if ( m_windowStyle & wxTE_MULTILINE ) { hText *= wxMax(GetNumberOfLines(), 5); } //else: for single line control everything is ok + // we have to add the adjustments for the control height only once, not + // once per line, so do it after multiplication above + hText += EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy) - cy; + return wxSize(wText, hText); }