X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2432b92dd7a837db13d3938a56c1959decd03203..20e85460c40ebc4dcc9577928771adb264cc998f:/src/msw/textctrl.cpp?ds=sidebyside diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index abf6eaf5f6..bfb35eaa50 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -39,12 +39,9 @@ #include #if wxUSE_IOSTREAMH -#include +# include #else -#include -# ifdef _MSC_VER - using namespace std; -# endif +# include #endif #include @@ -56,7 +53,7 @@ #if defined(__BORLANDC__) && !defined(__WIN32__) #include #else -#ifndef __GNUWIN32__ +#if !defined(__GNUWIN32__) && !defined(__SALFORDC__) #include #endif #define farmalloc malloc @@ -66,8 +63,8 @@ #include -#if defined(__WIN95__) && !defined(__GNUWIN32__) -#include +#if wxUSE_RICHEDIT && !defined(__GNUWIN32__) + #include #endif #if !USE_SHARED_LIBRARY @@ -78,17 +75,17 @@ BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) EVT_DROP_FILES(wxTextCtrl::OnDropFiles) EVT_ERASE_BACKGROUND(wxTextCtrl::OnEraseBackground) END_EVENT_TABLE() - -#endif +#endif // USE_SHARED_LIBRARY // Text item -wxTextCtrl::wxTextCtrl(void) +wxTextCtrl::wxTextCtrl() #ifndef NO_TEXT_WINDOW_STREAM - :streambuf() + : streambuf() #endif { - m_fileName = ""; +#if wxUSE_RICHEDIT m_isRich = FALSE; +#endif } bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, @@ -98,7 +95,6 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, const wxValidator& validator, const wxString& name) { - m_fileName = ""; SetName(name); SetValidator(validator); if (parent) parent->AddChild(this); @@ -122,24 +118,15 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, int width = size.x; int height = size.y; -#ifdef __WIN32__ - WXHGLOBAL m_globalHandle = 0; -#else - // Obscure method from the MS Developer's Network Disk for - // using global memory instead of the local heap, which - // runs out far too soon. Solves the problem with - // failing to appear. - - // Doesn't seem to work for Win95, so removing. - m_globalHandle=0; -// if ((wxGetOsVersion() != wxWINDOWS_NT) && (wxGetOsVersion() != wxWIN95)) -// m_globalHandle = (WXHGLOBAL) GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, -// 256L); -#endif - long msStyle = ES_LEFT | WS_VISIBLE | WS_CHILD | WS_TABSTOP; if (m_windowStyle & wxTE_MULTILINE) - msStyle |= ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL ; // WS_BORDER + { + wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER), + "wxTE_PROCESS_ENTER style is ignored for multiline controls" ); + + msStyle |= ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL ; // WS_BORDER + m_windowStyle |= wxTE_PROCESS_ENTER; + } else msStyle |= ES_AUTOHSCROLL ; @@ -151,8 +138,9 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, if (m_windowStyle & wxTE_PASSWORD) // hidden input msStyle |= ES_PASSWORD; - char *windowClass = "EDIT"; -#if defined(__WIN95__) + const char *windowClass = "EDIT"; + +#if wxUSE_RICHEDIT if ( m_windowStyle & wxTE_MULTILINE ) { msStyle |= ES_AUTOVSCROLL; @@ -160,19 +148,19 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, windowClass = "RichEdit" ; } else -#endif m_isRich = FALSE; +#endif bool want3D; WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ; // If we're in Win95, and we want a simple 2D border, // then make it an EDIT control instead. -#if defined(__WIN95__) +#if wxUSE_RICHEDIT if (m_windowStyle & wxSIMPLE_BORDER) { windowClass = "EDIT"; - m_isRich = FALSE; + m_isRich = FALSE; } #endif @@ -184,11 +172,11 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, m_hWnd = (WXHWND)::CreateWindowEx(exStyle, windowClass, NULL, msStyle, 0, 0, 0, 0, (HWND) ((wxWindow*)parent)->GetHWND(), (HMENU)m_windowId, - m_globalHandle ? (HINSTANCE) m_globalHandle : wxGetInstance(), NULL); + wxGetInstance(), NULL); wxCHECK_MSG( m_hWnd, FALSE, "Failed to create text ctrl" ); -#if CTL3D +#if wxUSE_CTL3D if ( want3D ) { Ctl3dSubclassCtl((HWND)m_hWnd); @@ -196,7 +184,7 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, } #endif -#if defined(__WIN95__) +#if wxUSE_RICHEDIT if (m_isRich) { // Have to enable events @@ -230,23 +218,29 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, } // Make sure the window style (etc.) reflects the HWND style (roughly) -void wxTextCtrl::AdoptAttributesFromHWND(void) +void wxTextCtrl::AdoptAttributesFromHWND() { wxWindow::AdoptAttributesFromHWND(); HWND hWnd = (HWND) GetHWND(); long style = GetWindowLong((HWND) hWnd, GWL_STYLE); - char buf[256]; + // retrieve the style to see whether this is an edit or richedit ctrl +#if wxUSE_RICHEDIT + char buf[256]; #ifndef __WIN32__ GetClassName((HWND) hWnd, buf, 256); #else #ifdef UNICODE GetClassNameW((HWND) hWnd, buf, 256); +#else +#ifdef __TWIN32__ + GetClassName((HWND) hWnd, buf, 256); #else GetClassNameA((HWND) hWnd, buf, 256); #endif +#endif #endif wxString str(buf); @@ -256,6 +250,7 @@ void wxTextCtrl::AdoptAttributesFromHWND(void) m_isRich = FALSE; else m_isRich = TRUE; +#endif if (style & ES_MULTILINE) m_windowStyle |= wxTE_MULTILINE; @@ -267,13 +262,13 @@ void wxTextCtrl::AdoptAttributesFromHWND(void) m_windowStyle |= wxTE_PROCESS_ENTER; } -void wxTextCtrl::SetupColours(void) +void wxTextCtrl::SetupColours() { SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); SetForegroundColour(GetParent()->GetForegroundColour()); } -wxString wxTextCtrl::GetValue(void) const +wxString wxTextCtrl::GetValue() const { int length = GetWindowTextLength((HWND) GetHWND()); char *s = new char[length+1]; @@ -316,7 +311,7 @@ void wxTextCtrl::SetValue(const wxString& value) SetWindowText((HWND) GetHWND(), (const char *)value); } -void wxTextCtrl::SetSize(int x, int y, int width, int height, int sizeFlags) +void wxTextCtrl::DoSetSize(int x, int y, int width, int height, int sizeFlags) { int currentX, currentY; GetPosition(¤tX, ¤tY); @@ -335,7 +330,7 @@ void wxTextCtrl::SetSize(int x, int y, int width, int height, int sizeFlags) int cx; // button font dimensions int cy; - wxGetCharSize(GetHWND(), &cx, &cy, & GetFont()); + wxGetCharSize(GetHWND(), &cx, &cy, & this->GetFont()); int control_width, control_height, control_x, control_y; @@ -366,19 +361,19 @@ void wxTextCtrl::SetSize(int x, int y, int width, int height, int sizeFlags) } // Clipboard operations -void wxTextCtrl::Copy(void) +void wxTextCtrl::Copy() { HWND hWnd = (HWND) GetHWND(); SendMessage(hWnd, WM_COPY, 0, 0L); } -void wxTextCtrl::Cut(void) +void wxTextCtrl::Cut() { HWND hWnd = (HWND) GetHWND(); SendMessage(hWnd, WM_CUT, 0, 0L); } -void wxTextCtrl::Paste(void) +void wxTextCtrl::Paste() { HWND hWnd = (HWND) GetHWND(); SendMessage(hWnd, WM_PASTE, 0, 0L); @@ -394,7 +389,7 @@ void wxTextCtrl::SetInsertionPoint(long pos) { HWND hWnd = (HWND) GetHWND(); #ifdef __WIN32__ -#if defined(__WIN95__) +#if wxUSE_RICHEDIT if ( m_isRich) { CHARRANGE range; @@ -416,15 +411,15 @@ void wxTextCtrl::SetInsertionPoint(long pos) SendMessage(hWnd, EM_REPLACESEL, 0, (LPARAM)nothing); } -void wxTextCtrl::SetInsertionPointEnd(void) +void wxTextCtrl::SetInsertionPointEnd() { long pos = GetLastPosition(); SetInsertionPoint(pos); } -long wxTextCtrl::GetInsertionPoint(void) const +long wxTextCtrl::GetInsertionPoint() const { -#if defined(__WIN95__) +#if wxUSE_RICHEDIT if (m_isRich) { CHARRANGE range; @@ -439,7 +434,7 @@ long wxTextCtrl::GetInsertionPoint(void) const return Pos&0xFFFF; } -long wxTextCtrl::GetLastPosition(void) const +long wxTextCtrl::GetLastPosition() const { HWND hWnd = (HWND) GetHWND(); @@ -458,6 +453,7 @@ long wxTextCtrl::GetLastPosition(void) const void wxTextCtrl::Replace(long from, long to, const wxString& value) { +#if wxUSE_CLIPBOARD HWND hWnd = (HWND) GetHWND(); long fromChar = from; long toChar = to; @@ -475,6 +471,9 @@ void wxTextCtrl::Replace(long from, long to, const wxString& value) // Paste into edit control SendMessage(hWnd, WM_PASTE, (WPARAM)0, (LPARAM)0L); +#else + wxFAIL_MSG("wxTextCtrl::Replace not implemented if wxUSE_CLIPBOARD is 0."); +#endif } void wxTextCtrl::Remove(long from, long to) @@ -535,9 +534,16 @@ bool wxTextCtrl::LoadFile(const wxString& file) // positions as signed shorts. Now load in one chunk... // Note use of 'farmalloc' as in Borland 3.1 'size_t' is 16-bits... +#ifdef __SALFORDC__ + struct _stat stat_buf; + if (stat((char*) (const char*) file, &stat_buf) < 0) + return FALSE; +#else struct stat stat_buf; if (stat(file, &stat_buf) < 0) return FALSE; +#endif + // char *tmp_buffer = (char*)farmalloc(stat_buf.st_size+1); // This may need to be a bigger buffer than the file size suggests, // if it's a UNIX file. Give it an extra 1000 just in case. @@ -570,16 +576,19 @@ bool wxTextCtrl::LoadFile(const wxString& file) // Returns TRUE if succeeds. bool wxTextCtrl::SaveFile(const wxString& file) { - wxString theFile(file); - if (theFile == "") - theFile = m_fileName; - if (theFile == "") - return FALSE; - m_fileName = theFile; + wxString theFile(file); - ofstream output((char*) (const char*) theFile); - if (output.bad()) - return FALSE; + if (theFile == "") + theFile = m_fileName; + + if (theFile == "") + return FALSE; + + m_fileName = theFile; + + ofstream output((char*) (const char*) theFile); + if (output.bad()) + return FALSE; // This will only save 64K max unsigned long nbytes = SendMessage((HWND) GetHWND(), WM_GETTEXTLENGTH, 0, 0); @@ -587,13 +596,13 @@ bool wxTextCtrl::SaveFile(const wxString& file) SendMessage((HWND) GetHWND(), WM_GETTEXT, (WPARAM)(nbytes+1), (LPARAM)tmp_buffer); char *pstr = tmp_buffer; - // Convert \r\n to just \n - while (*pstr) - { - if (*pstr != '\r') - output << *pstr; - pstr++; - } + // Convert \r\n to just \n + while (*pstr) + { + if (*pstr != '\r') + output << *pstr; + pstr++; + } farfree(tmp_buffer); SendMessage((HWND) GetHWND(), EM_SETMODIFY, FALSE, 0L); @@ -624,19 +633,24 @@ void wxTextCtrl::WriteText(const wxString& text) delete[] newtext; } -void wxTextCtrl::Clear(void) +void wxTextCtrl::AppendText(const wxString& text) +{ + SetInsertionPointEnd(); + WriteText(text); +} + +void wxTextCtrl::Clear() { -// SendMessage((HWND) GetHWND(), WM_SETTEXT, 0, (LPARAM)""); SetWindowText((HWND) GetHWND(), ""); } -bool wxTextCtrl::IsModified(void) const +bool wxTextCtrl::IsModified() const { return (SendMessage((HWND) GetHWND(), EM_GETMODIFY, 0, 0) != 0); } // Makes 'unmodified' -void wxTextCtrl::DiscardEdits(void) +void wxTextCtrl::DiscardEdits() { SendMessage((HWND) GetHWND(), EM_SETMODIFY, FALSE, 0L); } @@ -646,7 +660,7 @@ void wxTextCtrl::DiscardEdits(void) * */ -int wxTextCtrl::GetNumberOfLines(void) const +int wxTextCtrl::GetNumberOfLines() const { return (int)SendMessage((HWND) GetHWND(), EM_GETLINECOUNT, (WPARAM)0, (LPARAM)0); } @@ -694,11 +708,6 @@ void wxTextCtrl::ShowPosition(long pos) int linesToScroll = specifiedLineLineNo - currentLineLineNo; -/* - wxDebugMsg("Caret line: %d; Current visible line: %d; Specified line: %d; lines to scroll: %d\n", - currentLineLineNo1, currentLineLineNo, specifiedLineLineNo, linesToScroll); -*/ - if (linesToScroll != 0) (void)SendMessage(hWnd, EM_LINESCROLL, (WPARAM)0, (LPARAM)MAKELPARAM(linesToScroll, 0)); } @@ -747,7 +756,7 @@ void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event) // or when "endl" is output (Borland 4.5) //========================================================================= // Class declaration using multiple inheritance doesn't work properly for -// Borland. See note in wb_text.h. +// Borland. See note in textctrl.h. #ifndef NO_TEXT_WINDOW_STREAM int wxTextCtrl::overflow(int c) { @@ -803,7 +812,7 @@ int wxTextCtrl::overflow(int c) txt[plen] = (char)c; // append c txt[plen+xtra] = '\0'; // append '\0' or overwrite c // If the put area already contained \0, output will be truncated there - WriteText(txt); + AppendText(txt); delete[] txt; } @@ -833,7 +842,7 @@ int wxTextCtrl::overflow(int c) //========================================================================= // called then "endl" is output (gcc) or then explicit sync is done (Borland) //========================================================================= -int wxTextCtrl::sync(void) +int wxTextCtrl::sync() { // Verify that there are no characters in get area if ( gptr() && gptr() < egptr() ) @@ -860,7 +869,7 @@ int wxTextCtrl::sync(void) //========================================================================= // Should not be called by a "ostream". Used by a "istream" //========================================================================= -int wxTextCtrl::underflow(void) +int wxTextCtrl::underflow() { return EOF; } @@ -868,15 +877,15 @@ int wxTextCtrl::underflow(void) wxTextCtrl& wxTextCtrl::operator<<(const wxString& s) { - WriteText(s); - return *this; + AppendText(s); + return *this; } wxTextCtrl& wxTextCtrl::operator<<(float f) { wxString str; str.Printf("%.2f", f); - WriteText(str); + AppendText(str); return *this; } @@ -884,7 +893,7 @@ wxTextCtrl& wxTextCtrl::operator<<(double d) { wxString str; str.Printf("%.2f", d); - WriteText(str); + AppendText(str); return *this; } @@ -892,7 +901,7 @@ wxTextCtrl& wxTextCtrl::operator<<(int i) { wxString str; str.Printf("%d", i); - WriteText(str); + AppendText(str); return *this; } @@ -900,7 +909,7 @@ wxTextCtrl& wxTextCtrl::operator<<(long i) { wxString str; str.Printf("%ld", i); - WriteText(str); + AppendText(str); return *this; } @@ -910,14 +919,14 @@ wxTextCtrl& wxTextCtrl::operator<<(const char c) buf[0] = c; buf[1] = 0; - WriteText(buf); + AppendText(buf); return *this; } WXHBRUSH wxTextCtrl::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, WXUINT message, WXWPARAM wParam, WXLPARAM lParam) { -#if CTL3D +#if wxUSE_CTL3D if ( m_useCtl3D ) { HBRUSH hbrush = Ctl3dCtlColorEx(message, wParam, lParam); @@ -944,51 +953,85 @@ WXHBRUSH wxTextCtrl::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, void wxTextCtrl::OnChar(wxKeyEvent& event) { - // Fix by Marcel Rasche to allow Alt-Ctrl insertion of special characters - switch(event.KeyCode()) - { - case '{': - case '}': - case '[': - case ']': - case '|': - case '~': - case '\\': - { - char c=(char)event.KeyCode(); - *this << c; - } - break; - } - if ( (event.KeyCode() == WXK_RETURN) && (m_windowStyle & wxPROCESS_ENTER)) - { - wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); - event.SetEventObject( this ); - if ( GetEventHandler()->ProcessEvent(event) ) - return; - } - else if ( event.KeyCode() == WXK_TAB ) { - wxNavigationKeyEvent event; - event.SetDirection(!(::GetKeyState(VK_SHIFT) & 0x100)); - event.SetWindowChange(FALSE); - event.SetEventObject(this); - - if ( GetEventHandler()->ProcessEvent(event) ) - return; - } + 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: + { +/* Oh yes it will, because we also specify DLGC_WANTCHARS + wxASSERT_MSG( m_windowStyle & wxTE_PROCESS_ENTER, + "this text ctrl should never receive return" ); +*/ - event.Skip(); + if ( (m_windowStyle & wxTE_MULTILINE) == 0 ) + { + wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); + event.SetEventObject( this ); + if ( GetEventHandler()->ProcessEvent(event) ) + return; + } + //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 + // this key combo for himself) + // + // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is + // handled by Windows + if ( event.ShiftDown() || !(m_windowStyle & wxTE_PROCESS_TAB) ) + { + wxNavigationKeyEvent eventNav; + eventNav.SetDirection(!event.ShiftDown()); + eventNav.SetWindowChange(FALSE); + eventNav.SetEventObject(this); + + if ( GetEventHandler()->ProcessEvent(eventNav) ) + return; + } + break; + } + + // 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 + Default(); +// event.Skip(); } long wxTextCtrl::MSWGetDlgCode() { - long lRc = DLGC_WANTCHARS | DLGC_WANTARROWS; - if ( m_windowStyle & wxPROCESS_ENTER ) - lRc |= DLGC_WANTMESSAGE; - else if ( m_windowStyle & wxTE_MULTILINE ) - lRc |= DLGC_WANTMESSAGE; - - return lRc; + // we always want the characters and the arrows + long lRc = 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 ) + lRc |= DLGC_WANTMESSAGE; + if ( m_windowStyle & wxTE_PROCESS_TAB ) + lRc |= DLGC_WANTTAB; + + return lRc; } void wxTextCtrl::OnEraseBackground(wxEraseEvent& event) @@ -1089,7 +1132,7 @@ bool wxTextCtrl::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) // For Rich Edit controls. Do we need it? #if 0 -#if defined(__WIN95__) +#if wxUSE_RICHEDIT bool wxTextCtrl::MSWNotify(WXWPARAM wParam, WXLPARAM lParam) { wxCommandEvent event(0, m_windowId);