///////////////////////////////////////////////////////////////////////////// // Name: src/os2/textctrl.cpp // Purpose: wxTextCtrl // Author: David Webster // Modified by: // Created: 10/17/99 // RCS-ID: $Id: textctrl.cpp 41739 2006-10-08 17:46:12Z VZ $ // Copyright: (c) David Webster // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #include "wx/textctrl.h" #ifndef WX_PRECOMP #include "wx/scrolwin.h" #include "wx/settings.h" #include "wx/brush.h" #include "wx/utils.h" #include "wx/log.h" #include "wx/app.h" #endif #if wxUSE_CLIPBOARD #include "wx/clipbrd.h" #endif #include "wx/textfile.h" #include "wx/os2/private.h" #include #include #include #if wxUSE_IOSTREAMH # include #else # include #endif #if !defined(MLE_INDEX) #define MLE_INDEX 0 #define MLE_RGB 1 #endif // ---------------------------------------------------------------------------- // event tables and other macros // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase) BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase) EVT_CHAR(wxTextCtrl::OnChar) EVT_DROP_FILES(wxTextCtrl::OnDropFiles) EVT_MENU(wxID_CUT, wxTextCtrl::OnCut) EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy) EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste) EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo) EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo) EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut) EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy) EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste) EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo) EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo) END_EVENT_TABLE() // ============================================================================ // implementation // ============================================================================ // ---------------------------------------------------------------------------- // creation // ---------------------------------------------------------------------------- wxTextCtrl::wxTextCtrl() { } wxTextCtrl::~wxTextCtrl() { } bool wxTextCtrl::Create( wxWindow* pParent , wxWindowID vId , const wxString& rsValue , const wxPoint& rPos , const wxSize& rSize , long lStyle , const wxValidator& rValidator , const wxString& rsName ) { // // Base initialization // if ( !CreateBase( pParent ,vId ,rPos ,rSize ,lStyle ,rValidator ,rsName )) return false; wxPoint vPos = rPos; // The OS/2 position SWP vSwp; if (pParent ) { pParent->AddChild(this); } m_windowStyle = lStyle; m_bIsMLE = false; m_bSkipUpdate = false; long lSstyle = WS_VISIBLE | WS_TABSTOP; // // Single and multiline edit fields are two different controls in PM // if ( m_windowStyle & wxTE_MULTILINE ) { lSstyle |= MLS_BORDER | MLS_WORDWRAP; m_bIsMLE = true; if ((m_windowStyle & wxTE_NO_VSCROLL) == 0) lSstyle |= MLS_VSCROLL; if (m_windowStyle & wxHSCROLL) lSstyle |= MLS_HSCROLL; if (m_windowStyle & wxTE_READONLY) lSstyle |= MLS_READONLY; } else { lSstyle |= ES_LEFT | ES_AUTOSCROLL | ES_MARGIN; if (m_windowStyle & wxHSCROLL) lSstyle |= ES_AUTOSCROLL; if (m_windowStyle & wxTE_READONLY) lSstyle |= ES_READONLY; if (m_windowStyle & wxTE_PASSWORD) // hidden input lSstyle |= ES_UNREADABLE; } if (m_bIsMLE) { m_hWnd = (WXHWND)::WinCreateWindow( (HWND)GetHwndOf(pParent) // Parent window handle ,WC_MLE // Window class ,(PSZ)rsValue.c_str() // Initial Text ,(ULONG)lSstyle // Style flags ,(LONG)0 // X pos of origin ,(LONG)0 // Y pos of origin ,(LONG)0 // field width ,(LONG)0 // field height ,(HWND)GetHwndOf(pParent) // owner window handle (same as parent ,HWND_TOP // initial z position ,(ULONG)vId // Window identifier ,NULL // no control data ,NULL // no Presentation parameters ); } else { m_hWnd = (WXHWND)::WinCreateWindow( (HWND)GetHwndOf(pParent) // Parent window handle ,WC_ENTRYFIELD // Window class ,(PSZ)rsValue.c_str() // Initial Text ,(ULONG)lSstyle // Style flags ,(LONG)0 // X pos of origin ,(LONG)0 // Y pos of origin ,(LONG)0 // field width ,(LONG)0 // field height ,(HWND)GetHwndOf(pParent) // owner window handle (same as parent ,HWND_TOP // initial z position ,(ULONG)vId // Window identifier ,NULL // no control data ,NULL // no Presentation parameters ); } if (m_hWnd == 0) { return false; } SubclassWin(GetHWND()); // // Set font, position, size and initial value // wxFont* pTextFont = new wxFont( 8 ,wxMODERN ,wxNORMAL ,wxNORMAL ); SetFont(*pTextFont); if (!rsValue.empty()) { SetValue(rsValue); } SetupColours(); // // If X and/or Y are not zero the difference is the compensation value // for margins for OS/2 controls. // ::WinQueryWindowPos(m_hWnd, &vSwp); SetXComp(vSwp.x); SetYComp(vSwp.y); SetSize( vPos.x - GetXComp() ,vPos.y - GetYComp() ,rSize.x ,rSize.y ); delete pTextFont; return true; } // end of wxTextCtrl::Create // // Make sure the window style (etc.) reflects the HWND style (roughly) // void wxTextCtrl::AdoptAttributesFromHWND() { HWND hWnd = GetHwnd(); LONG lStyle = ::WinQueryWindowULong(hWnd, QWL_STYLE); wxWindow::AdoptAttributesFromHWND(); if (m_bIsMLE) { m_windowStyle |= wxTE_MULTILINE; if (lStyle & MLS_READONLY) m_windowStyle |= wxTE_READONLY; } else { if (lStyle & ES_UNREADABLE) m_windowStyle |= wxTE_PASSWORD; if (lStyle & ES_READONLY) m_windowStyle |= wxTE_READONLY; } } // end of wxTextCtrl::AdoptAttributesFromHWND WXDWORD wxTextCtrl::OS2GetStyle( long lStyle , WXDWORD* pdwExstyle ) const { // // Default border for the text controls is the sunken one // if ((lStyle & wxBORDER_MASK) == wxBORDER_DEFAULT ) { lStyle |= wxBORDER_SUNKEN; } long dwStyle = wxControl::OS2GetStyle( lStyle ,pdwExstyle ); dwStyle = WS_VISIBLE | WS_TABSTOP; // // Single and multiline edit fields are two different controls in PM // if ( m_windowStyle & wxTE_MULTILINE ) { dwStyle |= MLS_BORDER | MLS_WORDWRAP; if ((m_windowStyle & wxTE_NO_VSCROLL) == 0) dwStyle |= MLS_VSCROLL; if (m_windowStyle & wxHSCROLL) dwStyle |= MLS_HSCROLL; if (m_windowStyle & wxTE_READONLY) dwStyle |= MLS_READONLY; } else { dwStyle |= ES_LEFT | ES_AUTOSCROLL | ES_MARGIN; if (m_windowStyle & wxHSCROLL) dwStyle |= ES_AUTOSCROLL; if (m_windowStyle & wxTE_READONLY) dwStyle |= ES_READONLY; if (m_windowStyle & wxTE_PASSWORD) // hidden input dwStyle |= ES_UNREADABLE; } return dwStyle; } // end of wxTextCtrl::OS2GetStyle void wxTextCtrl::SetWindowStyleFlag( long lStyle ) { wxControl::SetWindowStyleFlag(lStyle); } // end of wxTextCtrl::SetWindowStyleFlag void wxTextCtrl::SetupColours() { wxColour vBkgndColour; vBkgndColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); SetBackgroundColour(vBkgndColour); SetForegroundColour(GetParent()->GetForegroundColour()); if (m_bIsMLE) { ::WinSendMsg( GetHwnd() ,MLM_SETTEXTCOLOR ,(MPARAM)GetParent()->GetForegroundColour().GetPixel() ,(MPARAM)MLE_RGB ); } } // end of wxTextCtrl::SetupColours // ---------------------------------------------------------------------------- // set/get the controls text // ---------------------------------------------------------------------------- wxString wxTextCtrl::GetValue() const { wxString sStr = wxGetWindowText(GetHWND()); char* zStr = (char*)sStr.c_str(); for ( ; *zStr; zStr++ ) { // // this will replace \r\n with just \n // if (*zStr == '\n') *zStr = '\0'; if (*zStr == '\r') *zStr = '\n'; } return sStr; } // end of wxTextCtrl::GetValue void wxTextCtrl::DoSetValue( const wxString& rsValue, int flags ) { // // If the text is long enough, it's faster to just set it instead of first // comparing it with the old one (chances are that it will be different // anyhow, this comparison is there to avoid flicker for small single-line // edit controls mostly) // if ((rsValue.length() > 0x400) || (rsValue != GetValue())) { if ( flags & SetValue_SendEvent ) m_bSkipUpdate = true; ::WinSetWindowText(GetHwnd(), (PSZ)rsValue.c_str()); AdjustSpaceLimit(); } } // end of wxTextCtrl::SetValue void wxTextCtrl::WriteText( const wxString& rsValue ) { if (m_bIsMLE) ::WinSendMsg(GetHwnd(), MLM_INSERT, MPARAM((PCHAR)rsValue.c_str()), MPARAM(0)); else ::WinSetWindowText(GetHwnd(), (PSZ)rsValue.c_str()); AdjustSpaceLimit(); } // end of wxTextCtrl::WriteText void wxTextCtrl::AppendText( const wxString& rsText ) { SetInsertionPointEnd(); WriteText(rsText); } // end of wxTextCtrl::AppendText void wxTextCtrl::Clear() { ::WinSetWindowText(GetHwnd(), ""); } // end of wxTextCtrl::Clear bool wxTextCtrl::EmulateKeyPress( const wxKeyEvent& rEvent ) { SetFocus(); return(wxTextCtrlBase::EmulateKeyPress(rEvent)); } // end of wxTextCtrl::EmulateKeyPress // ---------------------------------------------------------------------------- // Clipboard operations // ---------------------------------------------------------------------------- void wxTextCtrl::Copy() { if (CanCopy()) { HWND hWnd = GetHwnd(); if (m_bIsMLE) ::WinSendMsg(hWnd, MLM_COPY, 0, 0); else ::WinSendMsg(hWnd, EM_COPY, 0, 0); } } // end of wxTextCtrl::Copy void wxTextCtrl::Cut() { if (CanCut()) { HWND hWnd = GetHwnd(); if (m_bIsMLE) ::WinSendMsg(hWnd, MLM_CUT, 0, 0); else ::WinSendMsg(hWnd, EM_CUT, 0, 0); } } // end of wxTextCtrl::Cut void wxTextCtrl::Paste() { if (CanPaste()) { HWND hWnd = GetHwnd(); ::WinSendMsg(hWnd, EM_PASTE, 0, 0); } } // end of wxTextCtrl::Paste bool wxTextCtrl::CanCopy() const { // // Can copy if there's a selection // long lFrom = 0L; long lTo = 0L; GetSelection(&lFrom, &lTo); return (lFrom != lTo); } // end of wxTextCtrl::CanCopy bool wxTextCtrl::CanCut() const { // // Can cut if there's a selection // long lFrom = 0L; long lTo = 0L; GetSelection(&lFrom, &lTo); return (lFrom != lTo); } // end of wxTextCtrl::CanCut bool wxTextCtrl::CanPaste() const { bool bIsTextAvailable = false; if (!IsEditable()) return false; // // Check for straight text on clipboard // if (::WinOpenClipbrd(vHabmain)) { bIsTextAvailable = (::WinQueryClipbrdData(vHabmain, CF_TEXT) != 0); ::WinCloseClipbrd(vHabmain); } return bIsTextAvailable; } // end of wxTextCtrl::CanPaste // ---------------------------------------------------------------------------- // Accessors // ---------------------------------------------------------------------------- void wxTextCtrl::SetEditable( bool bEditable ) { HWND hWnd = GetHwnd(); if (m_bIsMLE) ::WinSendMsg(hWnd, MLM_SETREADONLY, MPFROMLONG(!bEditable), (MPARAM)0); else ::WinSendMsg(hWnd, EM_SETREADONLY, MPFROMLONG(!bEditable), (MPARAM)0); } // end of wxTextCtrl::SetEditable void wxTextCtrl::SetInsertionPoint( long lPos ) { HWND hWnd = GetHwnd(); if (m_bIsMLE) ::WinSendMsg(hWnd, MLM_SETSEL, (MPARAM)lPos, (MPARAM)lPos); else ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lPos, (USHORT)lPos), (MPARAM)0); } // end of wxTextCtrl::SetInsertionPoint void wxTextCtrl::SetInsertionPointEnd() { wxTextPos lPos = GetLastPosition(); // // We must not do anything if the caret is already there because calling // SetInsertionPoint() thaws the controls if Freeze() had been called even // if it doesn't actually move the caret anywhere and so the simple fact of // doing it results in horrible flicker when appending big amounts of text // to the control in a few chunks (see DoAddText() test in the text sample) // if (GetInsertionPoint() == GetLastPosition()) return; SetInsertionPoint(lPos); } // end of wxTextCtrl::SetInsertionPointEnd long wxTextCtrl::GetInsertionPoint() const { WXDWORD dwPos = 0L; if (m_bIsMLE) dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), MLM_QUERYSEL, (MPARAM)MLFQS_MINSEL, 0); else { dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), EM_QUERYSEL, 0, 0); dwPos = SHORT1FROMMP((MPARAM)dwPos); // the first 16 bit value is the min pos } return (dwPos & 0xFFFF); } // end of wxTextCtrl::GetInsertionPoint wxTextPos wxTextCtrl::GetLastPosition() const { HWND hWnd = GetHwnd(); long lCharIndex; long lLineLength; if (m_bIsMLE) { lCharIndex = 0; // // This just gets the total text length. The last will be this value // lLineLength = (long)::WinSendMsg(hWnd, MLM_QUERYTEXTLENGTH, 0, 0); } else { WNDPARAMS vParams; lCharIndex = 0; vParams.fsStatus = WPM_CCHTEXT; if (::WinSendMsg( GetHwnd() ,WM_QUERYWINDOWPARAMS ,&vParams ,0 )) { lLineLength = (long)vParams.cchText; } else lLineLength = 0; } return(lCharIndex + lLineLength); } // end of wxTextCtrl::GetLastPosition // If the return values from and to are the same, there is no // selection. void wxTextCtrl::GetSelection( long* plFrom , long* plTo ) const { WXDWORD dwPos; if (m_bIsMLE) dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), MLM_QUERYSEL, (MPARAM)MLFQS_MINSEL, 0); else { dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), EM_QUERYSEL, 0, 0); } *plFrom = SHORT1FROMMP((MPARAM)dwPos); // the first 16 bit value is the min pos *plTo = SHORT2FROMMP((MPARAM)dwPos); // the first 16 bit value is the min pos } // end of wxTextCtrl::GetSelection bool wxTextCtrl::IsEditable() const { if (m_bIsMLE) return((bool)LONGFROMMR(::WinSendMsg(GetHwnd(), MLM_QUERYREADONLY, 0, 0))); else return((bool)LONGFROMMR(::WinSendMsg(GetHwnd(), EM_QUERYREADONLY, 0, 0))); } // end of wxTextCtrl::IsEditable // ---------------------------------------------------------------------------- // Editing // ---------------------------------------------------------------------------- void wxTextCtrl::Replace( long lFrom, long lTo, const wxString& rsValue ) { #if wxUSE_CLIPBOARD HWND hWnd = GetHwnd(); // // Set selection and remove it // if (m_bIsMLE) { ::WinSendMsg(hWnd, MLM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0); ::WinSendMsg(hWnd, MLM_CUT, 0, 0); } else { ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0); ::WinSendMsg(hWnd, EM_CUT, 0, 0); } // // Now replace with 'value', by pasting. // wxSetClipboardData(wxDF_TEXT, (wxObject *) (const wxChar *)rsValue, 0, 0); // Paste into edit control if (m_bIsMLE) ::WinSendMsg(hWnd, MLM_PASTE, (MPARAM)0, (MPARAM)0); else ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0); #else wxUnusedVar(lFrom); wxUnusedVar(lTo); wxUnusedVar(rsValue); wxFAIL_MSG("wxTextCtrl::Replace not implemented if wxUSE_CLIPBOARD is 0."); #endif } // end of wxTextCtrl::Replace void wxTextCtrl::Remove( long lFrom , long lTo ) { HWND hWnd = GetHwnd(); if (m_bIsMLE) { ::WinSendMsg(hWnd, MLM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0); ::WinSendMsg(hWnd, MLM_CUT, 0, 0); } else { ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0); ::WinSendMsg(hWnd, EM_CUT, 0, 0); } } // end of wxTextCtrl::Remove void wxTextCtrl::SetSelection( long lFrom , long lTo ) { HWND hWnd = GetHwnd(); long lFromChar = lFrom; long lToChar = lTo; // // If from and to are both -1, it means (in wxWidgets) that all text should // be selected. Translate into Windows convention // if ((lFrom == -1L) && (lTo == -1L)) { lFromChar = 0L; lToChar = -1L; } if (m_bIsMLE) ::WinSendMsg(hWnd, MLM_SETSEL, (MPARAM)lFromChar, (MPARAM)lToChar); else ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFromChar, (USHORT)lToChar), (MPARAM)0); } // end of wxTextCtrl::SetSelection bool wxTextCtrl::DoLoadFile( const wxString& rsFile, int fileType ) { if ( wxTextCtrlBase::DoLoadFile(rsFile, fileType) ) { // // Update the size limit if needed // AdjustSpaceLimit(); return true; } return false; } // end of wxTextCtrl::DoLoadFile bool wxTextCtrl::IsModified() const { bool bRc; if (m_bIsMLE) bRc = (bool)LONGFROMMR(::WinSendMsg(GetHwnd(), MLM_QUERYCHANGED, 0, 0)); else bRc = (bool)LONGFROMMR(::WinSendMsg(GetHwnd(), EM_QUERYCHANGED, 0, 0)); return bRc; } // end of wxTextCtrl::IsModified void wxTextCtrl::MarkDirty() { if (m_bIsMLE) ::WinSendMsg(GetHwnd(), MLM_SETCHANGED, MPFROMLONG(TRUE), 0); else // EM controls do not have a SETCHANGED, what can we do?? wxFAIL_MSG( _T("not implemented") ); } // // Makes 'unmodified' // void wxTextCtrl::DiscardEdits() { if (m_bIsMLE) ::WinSendMsg(GetHwnd(), MLM_SETCHANGED, MPFROMLONG(FALSE), 0); else // // EM controls do not have a SETCHANGED but issuing a query should reset it // ::WinSendMsg(GetHwnd(), EM_QUERYCHANGED, 0, 0); } // end of wxTextCtrl::DiscardEdits int wxTextCtrl::GetNumberOfLines() const { int nNumLines; if (m_bIsMLE) nNumLines = (int)::WinSendMsg(GetHwnd(), MLM_QUERYLINECOUNT, 0, 0); else nNumLines = 1; return nNumLines; } // end of wxTextCtrl::GetNumberOfLines long wxTextCtrl::XYToPosition( long lX , long lY ) const { long lCharIndex = 0L; long lLen; if (m_bIsMLE) { lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0); lCharIndex = ((lLen * lY) + lX); } else lCharIndex = lX; return lCharIndex; } // end of wxTextCtrl::XYToPosition bool wxTextCtrl::PositionToXY( long lPos , long* plX , long* plY ) const { HWND hWnd = GetHwnd(); long nLineNo = -1; long lCharIndex = 0; if (m_bIsMLE) nLineNo = (long)::WinSendMsg(hWnd, MLM_LINEFROMCHAR, (MPARAM)lPos, 0); else nLineNo = 0; if (nLineNo == -1) { // no such line return false; } // // This gets the char index for the _beginning_ of this line // long lLineWidth; if (m_bIsMLE) { lLineWidth = (long)::WinSendMsg(hWnd, MLM_QUERYLINELENGTH, (MPARAM)0, (MPARAM)0); lCharIndex = (nLineNo + 1) * lLineWidth; } else { WNDPARAMS vParams; vParams.fsStatus = WPM_CCHTEXT; if (::WinSendMsg( hWnd ,WM_QUERYWINDOWPARAMS ,&vParams ,0 )) { lCharIndex = vParams.cchText; } else lCharIndex = 32; } if (lCharIndex == -1) { return false; } // // The X position must therefore be the difference between pos and charIndex // if (plX) *plX = lPos - lCharIndex; if (plY) *plY = nLineNo; return true; } // end of wxTextCtrl::PositionToXY void wxTextCtrl::ShowPosition( long WXUNUSED(lPos) ) { HWND hWnd = GetHwnd(); long lCurrentLineLineNo = 0L; // To scroll to a position, we pass the number of lines and characters // to scroll *by*. This means that we need to: // (1) Find the line position of the current line. // (2) Find the line position of pos. // (3) Scroll by (pos - current). // For now, ignore the horizontal scrolling. // // Is this where scrolling is relative to - the line containing the caret? // Or is the first visible line??? Try first visible line. // if (m_bIsMLE) { // // In PM this is the actual char position // lCurrentLineLineNo = (long)::WinSendMsg(hWnd, MLM_QUERYFIRSTCHAR, (MPARAM)0, (MPARAM)0); // // This will cause a scroll to the selected position // ::WinSendMsg(hWnd, MLM_SETSEL, (MPARAM)lCurrentLineLineNo, (MPARAM)lCurrentLineLineNo); } } // end of wxTextCtrl::ShowPosition int wxTextCtrl::GetLineLength( long WXUNUSED(lLineNo) ) const { long lLen = 0L; if (m_bIsMLE) { lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0); } else { WNDPARAMS vParams; vParams.fsStatus = WPM_CCHTEXT; if (::WinSendMsg( GetHwnd() ,WM_QUERYWINDOWPARAMS ,&vParams ,0 )) { lLen = vParams.cchText; } else lLen = 32; } return lLen; } // end ofwxTextCtrl::GetLineLength wxString wxTextCtrl::GetLineText( long lLineNo ) const { long lLen = (long)GetLineLength((long)lLineNo) + 1; wxString sStr; wxChar* zBuf; // // There must be at least enough place for the length WORD in the // buffer // lLen += sizeof(WORD); zBuf = new wxChar[lLen]; if (m_bIsMLE) { long lIndex; long lBuflen; long lCopied; lLen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYLINELENGTH, 0, 0); lIndex = lLen * lLineNo; ::WinSendMsg(GetHwnd(), MLM_SETSEL, (MPARAM)lIndex, (MPARAM)lIndex); ::WinSendMsg(GetHwnd(), MLM_SETIMPORTEXPORT, MPFROMP(zBuf), MPFROMSHORT((USHORT)WXSIZEOF(zBuf))); lBuflen = (long)::WinSendMsg(GetHwnd(), MLM_QUERYFORMATTEXTLENGTH, MPFROMLONG(lIndex), MPFROMLONG(-1)); lCopied = (long)::WinSendMsg(GetHwnd(), MLM_EXPORT, MPFROMP(&lIndex), MPFROMP(&lBuflen)); zBuf[lCopied] = '\0'; } else { WNDPARAMS vParams; vParams.fsStatus = WPM_CCHTEXT; if (::WinSendMsg( GetHwnd() ,WM_QUERYWINDOWPARAMS ,&vParams ,0 )) memcpy((char*)zBuf, vParams.pszText, vParams.cchText); zBuf[vParams.cchText] = '\0'; } sStr = zBuf; delete [] zBuf; return sStr; } // end of wxTextCtrl::GetLineText // ---------------------------------------------------------------------------- // Undo/redo // ---------------------------------------------------------------------------- void wxTextCtrl::Undo() { if (CanUndo()) { if (m_bIsMLE) ::WinSendMsg(GetHwnd(), MLM_UNDO, 0, 0); // Simple entryfields cannot be undone } } // end of wxTextCtrl::Undo void wxTextCtrl::Redo() { if (CanRedo()) { if (m_bIsMLE) ::WinSendMsg(GetHwnd(), MLM_UNDO, 0, 0); // Simple entryfields cannot be undone } } // end of wxTextCtrl::Redo bool wxTextCtrl::CanUndo() const { bool bOk; if (m_bIsMLE) bOk = (::WinSendMsg(GetHwnd(), MLM_QUERYUNDO, 0, 0) != 0); else bOk = false; // can't undo regular edit fields in PM return bOk; } // end of wxTextCtrl::CanUndo bool wxTextCtrl::CanRedo() const { bool bOk; if (m_bIsMLE) bOk = (::WinSendMsg(GetHwnd(), MLM_QUERYUNDO, 0, 0) != 0); else bOk = false; // can't undo regular edit fields in PM return bOk; } // end of wxTextCtrl::CanRedo // ---------------------------------------------------------------------------- // implemenation details // ---------------------------------------------------------------------------- void wxTextCtrl::Command( wxCommandEvent& rEvent ) { SetValue(rEvent.GetString()); ProcessCommand (rEvent); } // end of wxTextCtrl::Command void wxTextCtrl::OnDropFiles( wxDropFilesEvent& rEvent ) { // By default, load the first file into the text window. if (rEvent.GetNumberOfFiles() > 0) { LoadFile(rEvent.GetFiles()[0]); } } // end of wxTextCtrl::OnDropFiles WXHBRUSH wxTextCtrl::OnCtlColor( WXHDC hWxDC, WXHWND WXUNUSED(hWnd), WXUINT WXUNUSED(uCtlColor), WXUINT WXUNUSED(uMessage), WXWPARAM WXUNUSED(wParam), WXLPARAM WXUNUSED(lParam) ) { HPS hPS = (HPS)hWxDC; wxColour vColBack = GetBackgroundColour(); wxColour vColFore = GetForegroundColour(); wxBrush* pBackgroundBrush = wxTheBrushList->FindOrCreateBrush( vColBack, wxSOLID ); if (m_bUseCtl3D) { HBRUSH hBrush = NULLHANDLE; return hBrush; } if (GetParent()->GetTransparentBackground()) ::GpiSetBackMix(hPS, BM_LEAVEALONE); else ::GpiSetBackMix(hPS, BM_OVERPAINT); if (!IsEnabled() && (GetWindowStyle() & wxTE_MULTILINE) == 0) vColBack = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); ::GpiSetBackColor(hPS, vColBack.GetPixel()); ::GpiSetColor(hPS, vColFore.GetPixel()); return (WXHBRUSH)pBackgroundBrush->GetResourceHandle(); } // end of wxTextCtrl::OnCtlColor bool wxTextCtrl::OS2ShouldPreProcessMessage( WXMSG* pMsg ) { return wxControl::OS2ShouldPreProcessMessage(pMsg); } // end of wxTextCtrl::OS2ShouldPreProcessMessage void wxTextCtrl::OnChar( wxKeyEvent& rEvent ) { switch (rEvent.GetKeyCode()) { case WXK_RETURN: if ( !(m_windowStyle & wxTE_MULTILINE) ) { wxCommandEvent vEvent(wxEVT_COMMAND_TEXT_ENTER, m_windowId); vEvent.SetEventObject(this); if ( GetEventHandler()->ProcessEvent(vEvent)) return; } //else: multiline controls need Enter for themselves break; case WXK_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 // do its default job. // // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is // handled by Windows { wxNavigationKeyEvent vEventNav; vEventNav.SetDirection(!rEvent.ShiftDown()); vEventNav.SetWindowChange(false); vEventNav.SetEventObject(this); if ( GetEventHandler()->ProcessEvent(vEventNav) ) return; } break; } rEvent.Skip(); } // end of wxTextCtrl::OnChar bool wxTextCtrl::OS2Command( WXUINT uParam , WXWORD WXUNUSED(vId) ) { switch (uParam) { case EN_SETFOCUS: case EN_KILLFOCUS: { wxFocusEvent vEvent( uParam == EN_KILLFOCUS ? wxEVT_KILL_FOCUS : wxEVT_SET_FOCUS ,m_windowId ); vEvent.SetEventObject(this); GetEventHandler()->ProcessEvent(vEvent); } break; case EN_CHANGE: { if (m_bSkipUpdate) { m_bSkipUpdate = false; break; } wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED ,m_windowId ); InitCommandEvent(vEvent); ProcessCommand(vEvent); } break; case EN_OVERFLOW: // // The text size limit has been hit - increase it // AdjustSpaceLimit(); break; case EN_SCROLL: case EN_INSERTMODETOGGLE: case EN_MEMERROR: return false; default: return false; } // // Processed // return true; } // end of wxTextCtrl::OS2Command void wxTextCtrl::AdjustSpaceLimit() { unsigned int uLen = 0; unsigned int uLimit = 0; uLen = ::WinQueryWindowTextLength(GetHwnd()); if (m_bIsMLE) { uLimit = (unsigned int)::WinSendMsg( GetHwnd() ,MLM_QUERYTEXTLIMIT ,0 ,0 ); } else { ENTRYFDATA Efd; WNDPARAMS vParams; vParams.fsStatus = WPM_CBCTLDATA; vParams.pCtlData = &Efd; vParams.cbCtlData = sizeof(ENTRYFDATA); if (::WinSendMsg( GetHwnd() ,WM_QUERYWINDOWPARAMS ,&vParams ,0 )) uLimit = (unsigned int)Efd.cchEditLimit; else uLimit = 32; //PM's default } if (uLen >= uLimit) { uLimit = uLen + 0x8000; // 32Kb if (uLimit > 0xffff) { uLimit = 0L; } if (m_bIsMLE) ::WinSendMsg(GetHwnd(), MLM_SETTEXTLIMIT, MPFROMLONG(uLimit), 0); else ::WinSendMsg(GetHwnd(), EM_SETTEXTLIMIT, MPFROMSHORT(uLimit), 0); } } // end of wxTextCtrl::AdjustSpaceLimit bool wxTextCtrl::AcceptsFocus() const { // // We don't want focus if we can't be edited unless we're a multiline // control because then it might be still nice to get focus from keyboard // to be able to scroll it without mouse // return (IsEditable() || IsMultiLine()) && wxControl::AcceptsFocus(); } // end of wxTextCtrl::Command wxSize wxTextCtrl::DoGetBestSize() const { int nCx; int nCy; wxFont vFont = (wxFont)GetFont(); wxGetCharSize(GetHWND(), &nCx, &nCy, &vFont); int wText = DEFAULT_ITEM_WIDTH; int hText = (int)(EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy) * .8); if (m_windowStyle & wxTE_MULTILINE) { hText *= wxMax(GetNumberOfLines(), 5); } //else: for single line control everything is ok return wxSize(wText, hText); } // end of wxTextCtrl::DoGetBestSize // ---------------------------------------------------------------------------- // standard handlers for standard edit menu events // ---------------------------------------------------------------------------- void wxTextCtrl::OnCut( wxCommandEvent& WXUNUSED(rEvent) ) { Cut(); } // end of wxTextCtrl::OnCut void wxTextCtrl::OnCopy( wxCommandEvent& WXUNUSED(rEvent) ) { Copy(); } // end of wxTextCtrl::OnCopy void wxTextCtrl::OnPaste( wxCommandEvent& WXUNUSED(rEvent) ) { Paste(); } // end of wxTextCtrl::OnPaste void wxTextCtrl::OnUndo( wxCommandEvent& WXUNUSED(rEvent) ) { Undo(); } // end of wxTextCtrl::OnUndo void wxTextCtrl::OnRedo( wxCommandEvent& WXUNUSED(rEvent) ) { Redo(); } // end of wxTextCtrl::OnRedo void wxTextCtrl::OnDelete( wxCommandEvent& WXUNUSED(rEvent) ) { long lFrom, lTo; GetSelection( &lFrom, &lTo ); if (lFrom != -1 && lTo != -1) Remove( lFrom, lTo ); } // end of wxTextCtrl::OnDelete void wxTextCtrl::OnSelectAll( wxCommandEvent& WXUNUSED(rEvent) ) { SetSelection(-1, -1); } // end of wxTextCtrl::OnSelectAll void wxTextCtrl::OnUpdateCut( wxUpdateUIEvent& rEvent ) { rEvent.Enable(CanCut()); } // end of wxTextCtrl::OnUpdateCut void wxTextCtrl::OnUpdateCopy( wxUpdateUIEvent& rEvent ) { rEvent.Enable(CanCopy()); } // end of wxTextCtrl::OnUpdateCopy void wxTextCtrl::OnUpdatePaste( wxUpdateUIEvent& rEvent ) { rEvent.Enable(CanPaste()); } // end of wxTextCtrl::OnUpdatePaste void wxTextCtrl::OnUpdateUndo( wxUpdateUIEvent& rEvent ) { rEvent.Enable(CanUndo()); } // end of wxTextCtrl::OnUpdateUndo void wxTextCtrl::OnUpdateRedo( wxUpdateUIEvent& rEvent ) { rEvent.Enable(CanRedo()); } // end of wxTextCtrl::OnUpdateRedo void wxTextCtrl::OnUpdateDelete( wxUpdateUIEvent& rEvent ) { long lFrom, lTo; GetSelection( &lFrom, &lTo ); rEvent.Enable( lFrom != -1L && lTo != -1L && lFrom != lTo && IsEditable()) ; } // end of wxTextCtrl::OnUpdateDelete void wxTextCtrl::OnUpdateSelectAll( wxUpdateUIEvent& rEvent ) { rEvent.Enable(GetLastPosition() > 0); } // end of wxTextCtrl::OnUpdateSelectAll bool wxTextCtrl::SetBackgroundColour( const wxColour& rColour ) { if (m_bIsMLE) ::WinSendMsg(GetHwnd(), MLM_SETBACKCOLOR, (MPARAM)rColour.GetPixel(), MLE_INDEX); return true; } // end of wxTextCtrl::SetBackgroundColour bool wxTextCtrl::SetForegroundColour( const wxColour& rColour ) { if (m_bIsMLE) ::WinSendMsg(GetHwnd(), MLM_SETTEXTCOLOR, (MPARAM)rColour.GetPixel(), MLE_INDEX); return true; } // end of wxTextCtrl::SetForegroundColour bool wxTextCtrl::SetStyle( long lStart, long lEnd, const wxTextAttr& WXUNUSED(rStyle) ) { HWND hWnd = GetHwnd(); if (lStart > lEnd) { long lTmp = lStart; lStart = lEnd; lEnd = lTmp; } // // We can only change the format of the selection, so select the range we // want and restore the old selection later // long lStartOld, lEndOld; GetSelection( &lStartOld, &lEndOld ); // // But do we really have to change the selection? // bool bChangeSel = lStart != lStartOld || lEnd != lEndOld; if (bChangeSel) { if (m_bIsMLE) ::WinSendMsg(hWnd, MLM_SETSEL, MPFROM2SHORT((USHORT)lStart, (USHORT)lEnd), 0); else ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lStart, (USHORT)lEnd), 0); } // // TODO:: finish this part // return true; } // end of wxTextCtrl::SetStyle