X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0e320a79f187558effb04d92020b470372bbe456..ae1daed0739bf3c60b5bff4fbda823be2ee67872:/src/os2/textctrl.cpp?ds=sidebyside diff --git a/src/os2/textctrl.cpp b/src/os2/textctrl.cpp index 720e6082be..c663907618 100644 --- a/src/os2/textctrl.cpp +++ b/src/os2/textctrl.cpp @@ -1,40 +1,65 @@ ///////////////////////////////////////////////////////////////////////////// // Name: textctrl.cpp // Purpose: wxTextCtrl -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "textctrl.h" +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP + #include "wx/textctrl.h" + #include "wx/scrolwin.h" + #include "wx/settings.h" + #include "wx/brush.h" + #include "wx/utils.h" + #include "wx/log.h" #endif -#include -#include -#include +#if wxUSE_CLIPBOARD + #include "wx/app.h" + #include "wx/clipbrd.h" +#endif + +#include "wx/textfile.h" -#include "wx/textctrl.h" -#include "wx/settings.h" -#include "wx/filefn.h" -#include "wx/utils.h" +#include "wx/os2/private.h" -#if defined(__BORLANDC__) && !defined(__WIN32__) -#include +#include +#include +#include + +#if wxUSE_IOSTREAMH +# include #else -#ifndef __GNUWIN32__ -#include +# include #endif + +#if !defined(MLE_INDEX) +#define MLE_INDEX 0 +#define MLE_RGB 1 #endif -#if !USE_SHARED_LIBRARY + +// ---------------------------------------------------------------------------- +// event tables and other macros +// ---------------------------------------------------------------------------- + IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) - EVT_DROP_FILES(wxTextCtrl::OnDropFiles) + 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) @@ -47,512 +72,1255 @@ BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo) EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo) END_EVENT_TABLE() -#endif -// Text item + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// creation +// ---------------------------------------------------------------------------- + wxTextCtrl::wxTextCtrl() -#ifndef NO_TEXT_WINDOW_STREAM - :streambuf() -#endif { - m_fileName = ""; } -bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, - const wxString& value, - const wxPoint& pos, - const wxSize& size, long style, - const wxValidator& validator, - const wxString& name) +bool wxTextCtrl::Create( + wxWindow* pParent +, wxWindowID vId +, const wxString& rsValue +, const wxPoint& rPos +, const wxSize& rSize +, long lStyle +#if wxUSE_VALIDATORS +, const wxValidator& rValidator +#endif +, const wxString& rsName +) { - m_fileName = ""; - SetName(name); - SetValidator(validator); - if (parent) parent->AddChild(this); + HWND hParent; + int nTempy; + // + // Base initialization + // + if ( !CreateBase( pParent + ,vId + ,rPos + ,rSize + ,lStyle +#if wxUSE_VALIDATORS + ,rValidator +#endif + ,rsName + )) + return FALSE; + + wxPoint vPos = rPos; // The OS/2 position + SWP vSwp; + + if (pParent ) + { + pParent->AddChild(this); + } + + m_windowStyle = lStyle; - m_windowStyle = style; + long lSstyle = WS_VISIBLE | WS_TABSTOP; - if ( id == -1 ) - m_windowId = (int)NewControlId(); + // + // 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 - m_windowId = id; + { + 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( 10 + ,wxMODERN + ,wxNORMAL + ,wxNORMAL + ); + SetFont(*pTextFont); + if (!rsValue.IsEmpty()) + { + 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 + ,vPos.y + ,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 { - // TODO - return wxString(""); -} + 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'; + } + sStr = zStr; + return sStr; +} // end of wxTextCtrl::GetValue -void wxTextCtrl::SetValue(const wxString& value) +void wxTextCtrl::SetValue( + const wxString& rsValue +) { - // TODO -} + // + // 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())) + { + ::WinSetWindowText(GetHwnd(), rsValue.c_str()); + AdjustSpaceLimit(); + } +} // end of wxTextCtrl::SetValue -void wxTextCtrl::SetSize(int x, int y, int width, int height, int sizeFlags) +void wxTextCtrl::WriteText( + const wxString& rsValue +) { - // TODO -} + if (m_bIsMLE) + ::WinSendMsg(GetHwnd(), MLM_INSERT, MPARAM((PCHAR)rsValue.c_str()), MPARAM(0)); + else + ::WinSetWindowText(GetHwnd(), 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 +// ---------------------------------------------------------------------------- // Clipboard operations +// ---------------------------------------------------------------------------- + void wxTextCtrl::Copy() { - // TODO -} + 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() { - // TODO -} + 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() { - // TODO -} + if (CanPaste()) + { + HWND hWnd = GetHwnd(); -void wxTextCtrl::SetEditable(bool editable) -{ - // TODO -} + ::WinSendMsg(hWnd, EM_PASTE, 0, 0); + } +} // end of wxTextCtrl::Paste -void wxTextCtrl::SetInsertionPoint(long pos) +bool wxTextCtrl::CanCopy() const { - // TODO -} + // + // Can copy if there's a selection + // + long lFrom = 0L; + long lTo = 0L; -void wxTextCtrl::SetInsertionPointEnd() -{ - long pos = GetLastPosition(); - SetInsertionPoint(pos); -} + GetSelection(&lFrom, &lTo); + return (lFrom != lTo); +} // end of wxTextCtrl::CanCopy -long wxTextCtrl::GetInsertionPoint() const +bool wxTextCtrl::CanCut() const { - // TODO - return 0; -} + // + // Can cut if there's a selection + // + long lFrom = 0L; + long lTo = 0L; -long wxTextCtrl::GetLastPosition() const + GetSelection(&lFrom, &lTo); + return (lFrom != lTo); +} // end of wxTextCtrl::CanCut + +bool wxTextCtrl::CanPaste() const { - // TODO - return 0; -} + bool bIsTextAvailable = FALSE; + + if (!IsEditable()) + return FALSE; -void wxTextCtrl::Replace(long from, long to, const wxString& value) + // + // 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 +) { - // TODO -} + 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::Remove(long from, long to) +void wxTextCtrl::SetInsertionPoint( + long lPos +) { - // TODO -} + 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::SetSelection(long from, long to) +void wxTextCtrl::SetInsertionPointEnd() { - // TODO -} + long lPos = GetLastPosition(); -bool wxTextCtrl::LoadFile(const wxString& file) + SetInsertionPoint(lPos); +} // end of wxTextCtrl::SetInsertionPointEnd + +long wxTextCtrl::GetInsertionPoint() const { - if (!wxFileExists(file)) - return FALSE; + WXDWORD dwPos = 0L; - m_fileName = file; + 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 - Clear(); +long wxTextCtrl::GetLastPosition() const +{ + HWND hWnd = GetHwnd(); + long lCharIndex; + long lLineLength; - ifstream input((char*) (const char*) file, ios::nocreate | ios::in); + if (m_bIsMLE) + { + lCharIndex = 0; - if (!input.bad()) + // + // This just gets the total text length. The last will be this value + // + lLineLength = (long)::WinSendMsg(hWnd, MLM_QUERYTEXTLENGTH, 0, 0); + } + else { - struct stat stat_buf; - if (stat(file, &stat_buf) < 0) - return FALSE; - // 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. - char *tmp_buffer = (char*)malloc((size_t)(stat_buf.st_size+1+1000)); - long no_lines = 0; - long pos = 0; - while (!input.eof() && input.peek() != EOF) + WNDPARAMS vParams; + + lCharIndex = 0; + vParams.fsStatus = WPM_CCHTEXT; + if (::WinSendMsg( GetHwnd() + ,WM_QUERYWINDOWPARAMS + ,&vParams + ,0 + )) { - input.getline(wxBuffer, 500); - int len = strlen(wxBuffer); - wxBuffer[len] = 13; - wxBuffer[len+1] = 10; - wxBuffer[len+2] = 0; - strcpy(tmp_buffer+pos, wxBuffer); - pos += strlen(wxBuffer); - no_lines++; - } - - // TODO add line + lLineLength = (long)vParams.cchText; + } + else + lLineLength = 0; + } + return(lCharIndex + lLineLength); +} // end of wxTextCtrl::GetLastPosition - free(tmp_buffer); +// If the return values from and to are the same, there is no +// selection. +void wxTextCtrl::GetSelection( + long* plFrom +, long* plTo +) const +{ + WXDWORD dwPos; - return TRUE; + if (m_bIsMLE) + dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), MLM_QUERYSEL, (MPARAM)MLFQS_MINSEL, 0); + else + { + dwPos = (WXDWORD)::WinSendMsg(GetHwnd(), EM_QUERYSEL, 0, 0); } - return FALSE; -} + *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 -// If file is null, try saved file name first -// Returns TRUE if succeeds. -bool wxTextCtrl::SaveFile(const wxString& file) +bool wxTextCtrl::IsEditable() const { - wxString theFile(file); - if (theFile == "") - theFile = m_fileName; - if (theFile == "") - return FALSE; - m_fileName = theFile; - - ofstream output((char*) (const char*) theFile); - if (output.bad()) - return FALSE; + 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(); + long lFromChar = lFrom; + long lToChar = lTo; + + // + // 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); + } - // TODO get and save text + // + // Now replace with 'value', by pasting. + // + wxSetClipboardData(wxDF_TEXT, (wxObject *) (const wxChar *)rsValue, 0, 0); - return FALSE; -} + // 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 + wxFAIL_MSG("wxTextCtrl::Replace not implemented if wxUSE_CLIPBOARD is 0."); +#endif +} // end of wxTextCtrl::Replace -void wxTextCtrl::WriteText(const wxString& text) +void wxTextCtrl::Remove( + long lFrom +, long lTo +) { - // TODO write text to control -} + HWND hWnd = GetHwnd(); + long lFromChar = lFrom; + long lToChar = lTo; + + 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::AppendText(const wxString& text) +void wxTextCtrl::SetSelection( + long lFrom +, long lTo +) { - // TODO append text to control -} + HWND hWnd = GetHwnd(); + long lFromChar = lFrom; + long lToChar = lTo; + + // + // If from and to are both -1, it means (in wxWindows) 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 -void wxTextCtrl::Clear() +bool wxTextCtrl::LoadFile( + const wxString& rsFile +) { - // TODO -} + if ( wxTextCtrlBase::LoadFile(rsFile) ) + { + // + // Update the size limit if needed + // + AdjustSpaceLimit(); + return TRUE; + } + return FALSE; +} // end of wxTextCtrl::LoadFile bool wxTextCtrl::IsModified() const { - // TODO - return FALSE; -} + 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 + +// // Makes 'unmodified' +// void wxTextCtrl::DiscardEdits() { - // TODO -} + 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 { - // TODO - return 0; -} + int nNumLines; -long wxTextCtrl::XYToPosition(long x, long y) const + 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 { - // TODO - return 0; -} + HWND hWnd = GetHwnd(); + long lCharIndex = 0L; + long lLen; -void wxTextCtrl::PositionToXY(long pos, long *x, long *y) const + 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 { - // TODO -} + HWND hWnd = GetHwnd(); + long nLineNo = -1; + long lCharIndex = 0; -void wxTextCtrl::ShowPosition(long pos) -{ - // TODO -} + if (m_bIsMLE) + nLineNo = (long)::WinSendMsg(hWnd, MLM_LINEFROMCHAR, (MPARAM)lPos, 0); + else + nLineNo = 0; -int wxTextCtrl::GetLineLength(long lineNo) const -{ - // TODO - return 0; -} + if (nLineNo == -1) + { + // no such line + return FALSE; + } -wxString wxTextCtrl::GetLineText(long lineNo) const -{ - // TODO - return wxString(""); -} + // + // This gets the char index for the _beginning_ of this line + // + long lLineWidth; -bool wxTextCtrl::CanCopy() const -{ - // Can copy if there's a selection - long from, to; - GetSelection(& from, & to); - return (from != to) ; -} + 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; + } -bool wxTextCtrl::CanCut() const + 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 lPos +) { - // Can cut if there's a selection - long from, to; - GetSelection(& from, & to); - return (from != to) ; -} + 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 -bool wxTextCtrl::CanPaste() const +int wxTextCtrl::GetLineLength( + long lLineNo +) const { - return IsEditable() ; -} + 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; + char* zBuf; + + // + // There must be at least enough place for the length WORD in the + // buffer + // + lLen += sizeof(WORD); + zBuf = new char[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)sizeof(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(zBuf, vParams.pszText, vParams.cchText); + zBuf[vParams.cchText] = '\0'; + } + sStr = zBuf; + delete [] zBuf; + return sStr; +} // end of wxTextCtrl::GetLineText + +// ---------------------------------------------------------------------------- // Undo/redo +// ---------------------------------------------------------------------------- + void wxTextCtrl::Undo() { - // TODO -} + if (CanUndo()) + { + if (m_bIsMLE) + ::WinSendMsg(GetHwnd(), MLM_UNDO, 0, 0); + // Simple entryfields cannot be undone + } +} // end of wxTextCtrl::Undo void wxTextCtrl::Redo() { - // TODO -} + if (CanRedo()) + { + if (m_bIsMLE) + ::WinSendMsg(GetHwnd(), MLM_UNDO, 0, 0); + // Simple entryfields cannot be undone + } +} // end of wxTextCtrl::Redo bool wxTextCtrl::CanUndo() const { - // TODO - return FALSE; -} + 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 { - // TODO - return FALSE; -} + bool bOk; -// If the return values from and to are the same, there is no -// selection. -void wxTextCtrl::GetSelection(long* from, long* to) const -{ - // TODO - *from = 0; - *to = 0; -} + 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 -bool wxTextCtrl::IsEditable() const -{ - // TODO - return FALSE; -} +// ---------------------------------------------------------------------------- +// implemenation details +// ---------------------------------------------------------------------------- -void wxTextCtrl::Command(wxCommandEvent & event) +void wxTextCtrl::Command( + wxCommandEvent& rEvent +) { - SetValue (event.GetString()); - ProcessCommand (event); -} + SetValue(rEvent.GetString()); + ProcessCommand (rEvent); +} // end of wxTextCtrl::Command -void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event) +void wxTextCtrl::OnDropFiles( + wxDropFilesEvent& rEvent +) { // By default, load the first file into the text window. - if (event.GetNumberOfFiles() > 0) + if (rEvent.GetNumberOfFiles() > 0) { - LoadFile(event.GetFiles()[0]); + LoadFile(rEvent.GetFiles()[0]); } -} - -// The streambuf code was partly taken from chapter 3 by Jerry Schwarz of -// AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers - -//========================================================================= -// Called then the buffer is full (gcc 2.6.3) -// 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. -#ifndef NO_TEXT_WINDOW_STREAM -int wxTextCtrl::overflow(int c) -{ - // Make sure there is a holding area - if ( allocate()==EOF ) - { - wxError("Streambuf allocation failed","Internal error"); - return EOF; - } - - // Verify that there are no characters in get area - if ( gptr() && gptr() < egptr() ) - { - wxError("Who's trespassing my get area?","Internal error"); - return EOF; - } - - // Reset get area - setg(0,0,0); - - // Make sure there is a put area - if ( ! pptr() ) - { -/* This doesn't seem to be fatal so comment out error message */ -// wxError("Put area not opened","Internal error"); - setp( base(), base() ); - } - - // Determine how many characters have been inserted but no consumed - int plen = pptr() - pbase(); - - // Now Jerry relies on the fact that the buffer is at least 2 chars - // long, but the holding area "may be as small as 1" ??? - // And we need an additional \0, so let's keep this inefficient but - // safe copy. - - // If c!=EOF, it is a character that must also be comsumed - int xtra = c==EOF? 0 : 1; - - // Write temporary C-string to wxTextWindow - { - char *txt = new char[plen+xtra+1]; - memcpy(txt, pbase(), plen); - 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 - AppendText(txt); - delete[] txt; - } - - // Reset put area - setp(pbase(), epptr()); - -#if defined(__WATCOMC__) - return __NOT_EOF; -#elif defined(zapeof) // HP-UX (all cfront based?) - return zapeof(c); -#else - return c!=EOF ? c : 0; // this should make everybody happy -#endif -} - -//========================================================================= -// called then "endl" is output (gcc) or then explicit sync is done (Borland) -//========================================================================= -int wxTextCtrl::sync() -{ - // Verify that there are no characters in get area - if ( gptr() && gptr() < egptr() ) - { - wxError("Who's trespassing my get area?","Internal error"); - return EOF; - } - - if ( pptr() && pptr() > pbase() ) return overflow(EOF); - - return 0; -/* OLD CODE - int len = pptr() - pbase(); - char *txt = new char[len+1]; - strncpy(txt, pbase(), len); - txt[len] = '\0'; - (*this) << txt; - setp(pbase(), epptr()); - delete[] txt; - return 0; -*/ -} - -//========================================================================= -// Should not be called by a "ostream". Used by a "istream" -//========================================================================= -int wxTextCtrl::underflow() +} // end of wxTextCtrl::OnDropFiles + +WXHBRUSH wxTextCtrl::OnCtlColor( + WXHDC hWxDC +, WXHWND hWnd +, WXUINT uCtlColor +, WXUINT uMessage +, WXWPARAM wParam +, WXLPARAM lParam +) { - return EOF; -} -#endif + HPS hPS = (HPS)hWxDC; + wxBrush* pBrush = NULL; + wxColour vColBack = GetBackgroundColour(); + wxColour vColFore = GetForegroundColour(); + wxBrush* pBackgroundBrush = wxTheBrushList->FindOrCreateBrush( GetBackgroundColour() + ,wxSOLID + ); + + if (m_bUseCtl3D) + { + HBRUSH hBrush = NULLHANDLE; -wxTextCtrl& wxTextCtrl::operator<<(const wxString& s) + 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 +) { - AppendText(s); - return *this; -} + return wxControl::OS2ShouldPreProcessMessage(pMsg); +} // end of wxTextCtrl::OS2ShouldPreProcessMessage -wxTextCtrl& wxTextCtrl::operator<<(float f) +void wxTextCtrl::OnChar( + wxKeyEvent& rEvent +) { - wxString str; - str.Printf("%.2f", f); - AppendText(str); - return *this; -} + switch (rEvent.KeyCode()) + { + 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 -wxTextCtrl& wxTextCtrl::operator<<(double d) +bool wxTextCtrl::OS2Command( + WXUINT uParam +, WXWORD WXUNUSED(vId) +) { - wxString str; - str.Printf("%.2f", d); - AppendText(str); - return *this; -} + 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: + { + wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED + ,m_windowId + ); + + InitCommandEvent(vEvent); + vEvent.SetString((char*)GetValue().c_str()); + 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 -wxTextCtrl& wxTextCtrl::operator<<(int i) +void wxTextCtrl::AdjustSpaceLimit() { - wxString str; - str.Printf("%d", i); - AppendText(str); - return *this; -} + 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* pEfd; + WNDPARAMS vParams; + + vParams.fsStatus = WPM_CBCTLDATA; + vParams.cbCtlData = sizeof(ENTRYFDATA); -wxTextCtrl& wxTextCtrl::operator<<(long i) + if (::WinSendMsg( GetHwnd() + ,WM_QUERYWINDOWPARAMS + ,&vParams + ,0 + )) + { + pEfd = (ENTRYFDATA*)vParams.pCtlData; + uLimit = (unsigned int)pEfd->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, MPFROMLONG(uLimit), 0); + } +} // end of wxTextCtrl::AdjustSpaceLimit + +bool wxTextCtrl::AcceptsFocus() const { - wxString str; - str.Printf("%ld", i); - AppendText(str); - return *this; -} + // + // We don't want focus if we can't be edited + // + return IsEditable() && wxControl::AcceptsFocus(); +} // end of wxTextCtrl::Command -wxTextCtrl& wxTextCtrl::operator<<(const char c) +wxSize wxTextCtrl::DoGetBestSize() const { - char buf[2]; + int nCx; + int nCy; - buf[0] = c; - buf[1] = 0; - AppendText(buf); - return *this; -} + wxGetCharSize(GetHWND(), &nCx, &nCy, (wxFont*)&GetFont()); + + int wText = DEFAULT_ITEM_WIDTH; + int hText = (EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy) * .8); -void wxTextCtrl::OnCut(wxCommandEvent& event) + 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& rEvent +) { Cut(); -} +} // end of wxTextCtrl::OnCut -void wxTextCtrl::OnCopy(wxCommandEvent& event) +void wxTextCtrl::OnCopy( + wxCommandEvent& rEvent +) { Copy(); -} +} // end of wxTextCtrl::OnCopy -void wxTextCtrl::OnPaste(wxCommandEvent& event) +void wxTextCtrl::OnPaste( + wxCommandEvent& rEvent +) { Paste(); -} +} // end of wxTextCtrl::OnPaste -void wxTextCtrl::OnUndo(wxCommandEvent& event) +void wxTextCtrl::OnUndo( + wxCommandEvent& rEvent +) { Undo(); -} +} // end of wxTextCtrl::OnUndo -void wxTextCtrl::OnRedo(wxCommandEvent& event) +void wxTextCtrl::OnRedo( + wxCommandEvent& rEvent +) { Redo(); -} +} // end of wxTextCtrl::OnRedo -void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event) +void wxTextCtrl::OnUpdateCut( + wxUpdateUIEvent& rEvent +) { - event.Enable( CanCut() ); -} + rEvent.Enable(CanCut()); +} // end of wxTextCtrl::OnUpdateCut -void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event) +void wxTextCtrl::OnUpdateCopy( + wxUpdateUIEvent& rEvent +) { - event.Enable( CanCopy() ); -} + rEvent.Enable(CanCopy()); +} // end of wxTextCtrl::OnUpdateCopy -void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event) +void wxTextCtrl::OnUpdatePaste( + wxUpdateUIEvent& rEvent +) { - event.Enable( CanPaste() ); -} + rEvent.Enable(CanPaste()); +} // end of wxTextCtrl::OnUpdatePaste -void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event) +void wxTextCtrl::OnUpdateUndo( + wxUpdateUIEvent& rEvent +) { - event.Enable( CanUndo() ); -} + rEvent.Enable(CanUndo()); +} // end of wxTextCtrl::OnUpdateUndo -void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event) +void wxTextCtrl::OnUpdateRedo( + wxUpdateUIEvent& rEvent +) { - event.Enable( CanRedo() ); -} + rEvent.Enable(CanRedo()); +} // end of wxTextCtrl::OnUpdateRedo + +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& 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; + long 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 +