git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@20255 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1391 lines
39 KiB
C++
1391 lines
39 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: textctrl.cpp
|
|
// Purpose: wxTextCtrl
|
|
// Author: David Webster
|
|
// Modified by:
|
|
// Created: 10/17/99
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) David Webster
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// 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
|
|
|
|
#if wxUSE_CLIPBOARD
|
|
#include "wx/app.h"
|
|
#include "wx/clipbrd.h"
|
|
#endif
|
|
|
|
#include "wx/textfile.h"
|
|
|
|
#include "wx/os2/private.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
|
|
#if wxUSE_IOSTREAMH
|
|
# include <fstream.h>
|
|
#else
|
|
# include <fstream>
|
|
#endif
|
|
|
|
#if !defined(MLE_INDEX)
|
|
#define MLE_INDEX 0
|
|
#define MLE_RGB 1
|
|
#endif
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// event tables and other macros
|
|
// ----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
|
|
|
|
BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
|
|
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
|
|
)
|
|
{
|
|
HWND hParent;
|
|
int nTempy;
|
|
|
|
//
|
|
// 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;
|
|
|
|
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.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 - 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::SetValue(
|
|
const wxString& rsValue
|
|
)
|
|
{
|
|
//
|
|
// 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::WriteText(
|
|
const wxString& rsValue
|
|
)
|
|
{
|
|
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
|
|
|
|
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()
|
|
{
|
|
long 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
|
|
|
|
long 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();
|
|
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);
|
|
}
|
|
|
|
//
|
|
// 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
|
|
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();
|
|
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::SetSelection(
|
|
long lFrom
|
|
, long lTo
|
|
)
|
|
{
|
|
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
|
|
|
|
bool wxTextCtrl::LoadFile(
|
|
const wxString& rsFile
|
|
)
|
|
{
|
|
if ( wxTextCtrlBase::LoadFile(rsFile) )
|
|
{
|
|
//
|
|
// Update the size limit if needed
|
|
//
|
|
AdjustSpaceLimit();
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
} // end of wxTextCtrl::LoadFile
|
|
|
|
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
|
|
|
|
//
|
|
// 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
|
|
{
|
|
HWND hWnd = GetHwnd();
|
|
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 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 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;
|
|
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()
|
|
{
|
|
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 hWnd
|
|
, WXUINT uCtlColor
|
|
, WXUINT uMessage
|
|
, WXWPARAM wParam
|
|
, WXLPARAM lParam
|
|
)
|
|
{
|
|
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;
|
|
|
|
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.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
|
|
|
|
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:
|
|
{
|
|
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
|
|
|
|
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* pEfd;
|
|
WNDPARAMS vParams;
|
|
|
|
vParams.fsStatus = WPM_CBCTLDATA;
|
|
vParams.cbCtlData = sizeof(ENTRYFDATA);
|
|
|
|
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
|
|
{
|
|
//
|
|
// 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;
|
|
|
|
wxGetCharSize(GetHWND(), &nCx, &nCy, (wxFont*)&GetFont());
|
|
|
|
int wText = DEFAULT_ITEM_WIDTH;
|
|
int hText = (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& rEvent
|
|
)
|
|
{
|
|
Cut();
|
|
} // end of wxTextCtrl::OnCut
|
|
|
|
void wxTextCtrl::OnCopy(
|
|
wxCommandEvent& rEvent
|
|
)
|
|
{
|
|
Copy();
|
|
} // end of wxTextCtrl::OnCopy
|
|
|
|
void wxTextCtrl::OnPaste(
|
|
wxCommandEvent& rEvent
|
|
)
|
|
{
|
|
Paste();
|
|
} // end of wxTextCtrl::OnPaste
|
|
|
|
void wxTextCtrl::OnUndo(
|
|
wxCommandEvent& rEvent
|
|
)
|
|
{
|
|
Undo();
|
|
} // end of wxTextCtrl::OnUndo
|
|
|
|
void wxTextCtrl::OnRedo(
|
|
wxCommandEvent& rEvent
|
|
)
|
|
{
|
|
Redo();
|
|
} // end of wxTextCtrl::OnRedo
|
|
|
|
void wxTextCtrl::OnDelete(
|
|
wxCommandEvent& rEvent
|
|
)
|
|
{
|
|
long lFrom;
|
|
long lTo;
|
|
|
|
GetSelection( &lFrom
|
|
,&lTo
|
|
);
|
|
if (lFrom != -1 && lTo != -1)
|
|
Remove( lFrom
|
|
,lTo
|
|
);
|
|
} // end of wxTextCtrl::OnDelete
|
|
|
|
void wxTextCtrl::OnSelectAll(
|
|
wxCommandEvent& 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;
|
|
long 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& 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
|
|
|