X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a5aa80862cb50928bd879f7d42df49622f6e8cae..a7c8e710e944fc12a81a19d06fe415a92e86bb13:/src/msw/textctrl.cpp diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index b19e84b06f..e9bbcc1ad5 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -195,59 +195,8 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, if ( parent ) parent->AddChild(this); - // translate wxWin style flags to MSW ones, checking for consistency while - // doing it - long msStyle = ES_LEFT | WS_TABSTOP; - - if ( m_windowStyle & wxCLIP_SIBLINGS ) - msStyle |= WS_CLIPSIBLINGS; - - if ( m_windowStyle & wxTE_MULTILINE ) - { - wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER), - wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") ); - - msStyle |= ES_MULTILINE | ES_WANTRETURN; - if ((m_windowStyle & wxTE_NO_VSCROLL) == 0) - msStyle |= WS_VSCROLL; - m_windowStyle |= wxTE_PROCESS_ENTER; - } - else // !multiline - { - // there is really no reason to not have this style for single line - // text controls - msStyle |= ES_AUTOHSCROLL; - } - - if ( m_windowStyle & wxHSCROLL ) - msStyle |= WS_HSCROLL | ES_AUTOHSCROLL; - - if ( m_windowStyle & wxTE_READONLY ) - msStyle |= ES_READONLY; - - if ( m_windowStyle & wxTE_PASSWORD ) - msStyle |= ES_PASSWORD; - - if ( m_windowStyle & wxTE_AUTO_SCROLL ) - msStyle |= ES_AUTOHSCROLL; - - if ( m_windowStyle & wxTE_NOHIDESEL ) - msStyle |= ES_NOHIDESEL; - - // we always want the characters and the arrows - m_lDlgCode = DLGC_WANTCHARS | DLGC_WANTARROWS; - - // we may have several different cases: - // 1. normal case: both TAB and ENTER are used for dialog navigation - // 2. ctrl which wants TAB for itself: ENTER is used to pass to the next - // control in the dialog - // 3. ctrl which wants ENTER for itself: TAB is used for dialog navigation - // 4. ctrl which wants both TAB and ENTER: Ctrl-ENTER is used to pass to - // the next control - if ( m_windowStyle & wxTE_PROCESS_ENTER ) - m_lDlgCode |= DLGC_WANTMESSAGE; - if ( m_windowStyle & wxTE_PROCESS_TAB ) - m_lDlgCode |= DLGC_WANTTAB; + // translate wxWin style flags to MSW ones + WXDWORD msStyle = MSWGetCreateWindowFlags(); // do create the control - either an EDIT or RICHEDIT wxString windowClass = wxT("EDIT"); @@ -406,6 +355,74 @@ void wxTextCtrl::AdoptAttributesFromHWND() m_windowStyle |= wxTE_PROCESS_ENTER; } +WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const +{ + // default border for the text controls is the sunken one + if ( (style & wxBORDER_MASK) == wxBORDER_DEFAULT ) + { + style |= wxBORDER_SUNKEN; + } + + long msStyle = wxControl::MSWGetStyle(style, exstyle); + + // default styles + msStyle |= ES_LEFT; + + if ( style & wxTE_MULTILINE ) + { + wxASSERT_MSG( !(style & wxTE_PROCESS_ENTER), + wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") ); + + msStyle |= ES_MULTILINE | ES_WANTRETURN; + if ( !(style & wxTE_NO_VSCROLL) ) + msStyle |= WS_VSCROLL; + + style |= wxTE_PROCESS_ENTER; + } + else // !multiline + { + // there is really no reason to not have this style for single line + // text controls + msStyle |= ES_AUTOHSCROLL; + } + + if ( style & wxHSCROLL ) + msStyle |= WS_HSCROLL | ES_AUTOHSCROLL; + + if ( style & wxTE_READONLY ) + msStyle |= ES_READONLY; + + if ( style & wxTE_PASSWORD ) + msStyle |= ES_PASSWORD; + + if ( style & wxTE_AUTO_SCROLL ) + msStyle |= ES_AUTOHSCROLL; + + if ( style & wxTE_NOHIDESEL ) + msStyle |= ES_NOHIDESEL; + + return msStyle; +} + +void wxTextCtrl::SetWindowStyleFlag(long style) +{ +#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 + // using richedit-specific EM_SETOPTIONS + if ( IsRich() && + ((style & wxTE_NOHIDESEL) != (GetWindowStyle() & wxTE_NOHIDESEL)) ) + { + bool set = (style & wxTE_NOHIDESEL) != 0; + + ::SendMessage(GetHwnd(), EM_SETOPTIONS, set ? ECOOP_OR : ECOOP_AND, + set ? ECO_NOHIDESEL : ~ECO_NOHIDESEL); + } +#endif // wxUSE_RICHEDIT + + wxControl::SetWindowStyleFlag(style); +} + // ---------------------------------------------------------------------------- // set/get the controls text // ---------------------------------------------------------------------------- @@ -493,11 +510,7 @@ void wxTextCtrl::SetValue(const wxString& value) // edit controls mostly) if ( (value.length() > 0x400) || (value != GetValue()) ) { - // it is simpler to do this but it could be more efficient to reproduce - // WriteText() logic here - Clear(); - - WriteText(value); + DoWriteText(value, FALSE /* not selection only */); // mark the control as being not dirty - we changed its text, not the // user @@ -529,14 +542,18 @@ DWORD CALLBACK wxRichEditStreamIn(DWORD dwCookie, BYTE *buf, LONG cb, LONG *pcb) return 0; } -extern long wxEncodingToCodepage(wxFontEncoding encoding); // from strconv.cpp +extern long wxEncodingToCodepage(wxFontEncoding encoding); // from utils.cpp #if wxUSE_UNICODE_MSLU -bool wxTextCtrl::StreamIn(const wxString& value, wxFontEncoding WXUNUSED(encoding)) +bool wxTextCtrl::StreamIn(const wxString& value, + wxFontEncoding WXUNUSED(encoding), + bool selectionOnly) { const wchar_t *wpc = value.c_str(); -#else -bool wxTextCtrl::StreamIn(const wxString& value, wxFontEncoding encoding) +#else // !wxUSE_UNICODE_MSLU +bool wxTextCtrl::StreamIn(const wxString& value, + wxFontEncoding encoding, + bool selectionOnly) { // we have to use EM_STREAMIN to force richedit control 2.0+ to show any // text in the non default charset - otherwise it thinks it knows better @@ -552,9 +569,15 @@ bool wxTextCtrl::StreamIn(const wxString& value, wxFontEncoding encoding) // next translate to Unicode using this code page int len = ::MultiByteToWideChar(codepage, 0, value, -1, NULL, 0); + +#if wxUSE_WCHAR_T wxWCharBuffer wchBuf(len); +#else + wchar_t *wchBuf = (wchar_t *)malloc((len + 1)*sizeof(wchar_t)); +#endif + if ( !::MultiByteToWideChar(codepage, 0, value, -1, - (wchar_t *)wchBuf.data(), len) ) + (wchar_t *)(const wchar_t *)wchBuf, len) ) { wxLogLastError(_T("MultiByteToWideChar")); } @@ -570,20 +593,29 @@ bool wxTextCtrl::StreamIn(const wxString& value, wxFontEncoding encoding) eds.pfnCallback = (EDITSTREAMCALLBACK)wxRichEditStreamIn; if ( !::SendMessage(GetHwnd(), EM_STREAMIN, - SF_TEXT | SF_UNICODE | SFF_SELECTION, + SF_TEXT | + SF_UNICODE | + (selectionOnly ? SFF_SELECTION : 0), (LPARAM)&eds) || eds.dwError ) { wxLogLastError(_T("EM_STREAMIN")); - - return FALSE; } +#if !wxUSE_WCHAR_T + free(wchBuf); +#endif // !wxUSE_WCHAR_T + return TRUE; } #endif // wxUSE_RICHEDIT void wxTextCtrl::WriteText(const wxString& value) +{ + DoWriteText(value); +} + +void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly) { wxString valueDos; if ( m_windowStyle & wxTE_MULTILINE ) @@ -607,9 +639,9 @@ void wxTextCtrl::WriteText(const wxString& value) #if wxUSE_UNICODE_MSLU // RichEdit doesn't have Unicode version of EM_REPLACESEL on Win9x, // but EM_STREAMIN works - if ( wxGetOsVersion() == wxWIN95 && GetRichVersion() > 1 ) + if ( wxUsingUnicowsDll() && GetRichVersion() > 1 ) { - done = StreamIn(valueDos, wxFONTENCODING_SYSTEM); + done = StreamIn(valueDos, wxFONTENCODING_SYSTEM, selectionOnly); } #endif // wxUSE_UNICODE_MSLU @@ -627,7 +659,7 @@ void wxTextCtrl::WriteText(const wxString& value) wxFontEncoding encoding = font.GetEncoding(); if ( encoding != wxFONTENCODING_SYSTEM ) { - done = StreamIn(valueDos, encoding); + done = StreamIn(valueDos, encoding, selectionOnly); } } } @@ -637,6 +669,11 @@ void wxTextCtrl::WriteText(const wxString& value) if ( !done ) #endif // wxUSE_RICHEDIT { + if ( !selectionOnly ) + { + SetSelection(-1, -1); + } + ::SendMessage(GetHwnd(), EM_REPLACESEL, 0, (LPARAM)valueDos.c_str()); } @@ -807,6 +844,12 @@ void wxTextCtrl::GetSelection(long* from, long* to) const 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; @@ -1082,7 +1125,7 @@ bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* pMsg) // usual preprocessing for them if ( msg->message == WM_KEYDOWN ) { - WORD vkey = msg->wParam; + WORD vkey = (WORD) msg->wParam; if ( (HIWORD(msg->lParam) & KF_ALTDOWN) == KF_ALTDOWN ) { if ( vkey == VK_BACK ) @@ -1153,6 +1196,32 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) event.Skip(); } +long wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +{ + // we always want the characters and the arrows + if ( nMsg == WM_GETDLGCODE ) + { + // we always want the chars and the arrows + long lDlgCode = DLGC_WANTCHARS | DLGC_WANTARROWS; + + // we may have several different cases: + // 1. normal case: both TAB and ENTER are used for dialog navigation + // 2. ctrl which wants TAB for itself: ENTER is used to pass to the next + // control in the dialog + // 3. ctrl which wants ENTER for itself: TAB is used for dialog navigation + // 4. ctrl which wants both TAB and ENTER: Ctrl-ENTER is used to pass to + // the next control + if ( m_windowStyle & wxTE_PROCESS_ENTER ) + lDlgCode |= DLGC_WANTMESSAGE; + if ( m_windowStyle & wxTE_PROCESS_TAB ) + lDlgCode |= DLGC_WANTTAB; + + return lDlgCode; + } + + return wxTextCtrlBase::MSWWindowProc(nMsg, wParam, lParam); +} + bool wxTextCtrl::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) { switch (param) @@ -1406,7 +1475,7 @@ void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event) // EN_LINK processing // ---------------------------------------------------------------------------- -bool wxTextCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) +bool wxTextCtrl::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM *result) { NMHDR *hdr = (NMHDR* )lParam; if ( hdr->code == EN_LINK ) @@ -1661,7 +1730,7 @@ bool wxRichEditModule::OnInit() void wxRichEditModule::OnExit() { - for ( int i = 0; i < WXSIZEOF(ms_hRichEdit); i++ ) + for ( size_t i = 0; i < WXSIZEOF(ms_hRichEdit); i++ ) { if ( ms_hRichEdit[i] ) { @@ -1681,18 +1750,18 @@ bool wxRichEditModule::Load(int version) // make it the index in the array version--; - if ( ms_hRichEdit[version] ) - { - // we've already got this one - return TRUE; - } - if ( ms_hRichEdit[version] == (HINSTANCE)-1 ) { // we had already tried to load it and failed return FALSE; } + if ( ms_hRichEdit[version] ) + { + // we've already got this one + return TRUE; + } + wxString dllname = version ? _T("riched20") : _T("riched32"); dllname += _T(".dll");