/////////////////////////////////////////////////////////////////////////////
-// Name: textctrl.cpp
+// Name: msw/textctrl.cpp
// Purpose: wxTextCtrl
// Author: Julian Smart
// Modified by:
#include "wx/app.h"
#endif
+#include "wx/module.h"
+
#if wxUSE_CLIPBOARD
#include "wx/clipbrd.h"
#endif
# include <fstream>
#endif
-#if wxUSE_RICHEDIT && (!defined(__GNUWIN32__) || defined(wxUSE_NORLANDER_HEADERS))
+#if wxUSE_RICHEDIT && !defined(__GNUWIN32_OLD__)
#include <richedit.h>
#endif
EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
+#ifdef __WIN16__
+ EVT_ERASE_BACKGROUND(wxTextCtrl::OnEraseBackground)
+#endif
END_EVENT_TABLE()
if ( parent )
parent->AddChild(this);
- // set colours
- SetupColours();
-
// translate wxWin style flags to MSW ones, checking for consistency while
// doing it
- long msStyle = ES_LEFT | WS_VISIBLE | WS_CHILD | WS_TABSTOP;
+ long msStyle = ES_LEFT | WS_VISIBLE | WS_CHILD | WS_TABSTOP /* | WS_CLIPSIBLINGS */ ;
if ( m_windowStyle & wxTE_MULTILINE )
{
wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
- wxT("wxTE_PROCESS_ENTER style is ignored for multiline "
- "text controls (they always process it)") );
+ wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
msStyle |= ES_MULTILINE | ES_WANTRETURN;
if ((m_windowStyle & wxTE_NO_VSCROLL) == 0)
if (m_windowStyle & wxTE_READONLY)
msStyle |= ES_READONLY;
- if (m_windowStyle & wxHSCROLL)
- msStyle |= (WS_HSCROLL | ES_AUTOHSCROLL);
if (m_windowStyle & wxTE_PASSWORD) // hidden input
msStyle |= ES_PASSWORD;
+ if (m_windowStyle & wxTE_AUTO_SCROLL)
+ msStyle |= ES_AUTOHSCROLL;
+
+
// we always want the characters and the arrows
m_lDlgCode = DLGC_WANTCHARS | DLGC_WANTARROWS;
// done)
if ( !wxRichEditModule::Load() )
{
- wxLogError(_("Impossible to create a rich edit control, "
- "using simple text control instead. Please "
- "reinstall riched32.dll"));
+ wxLogError(_("Impossible to create a rich edit control, using simple text control instead. Please reinstall riched32.dll"));
s_errorGiven = TRUE;
}
#ifndef RICHEDIT_CLASS
wxString RICHEDIT_CLASS;
RICHEDIT_CLASS.Printf(_T("RichEdit%d0"), ver);
-#ifdef wxUSE_UNICODE
+#if wxUSE_UNICODE
RICHEDIT_CLASS += _T('W');
#else // ANSI
RICHEDIT_CLASS += _T('A');
// might be -1 in which case we should use the default values (and
// SetSize called below takes care of it)
m_hWnd = (WXHWND)::CreateWindowEx(exStyle,
- windowClass,
+ windowClass.c_str(),
NULL,
msStyle,
0, 0, 0, 0,
}
#endif
+ // set colours
+ SetupColours();
+
SetSize(pos.x, pos.y, size.x, size.y);
return TRUE;
void wxTextCtrl::SetupColours()
{
- // FIXME why is bg colour not inherited from parent?
- SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW));
+ wxColour bkgndColour;
+// if (IsEditable() || (m_windowStyle & wxTE_MULTILINE))
+ bkgndColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW);
+// else
+// bkgndColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
+
+ SetBackgroundColour(bkgndColour);
SetForegroundColour(GetParent()->GetForegroundColour());
}
{
wxString str;
- int len = GetWindowTextLength(GetHwnd()) + 1;
- wxChar *p = str.GetWriteBuf(len);
+ int len = GetWindowTextLength(GetHwnd());
+ if ( len )
+ {
+ // alloc one extra WORD as needed by the control
+ wxChar *p = str.GetWriteBuf(++len);
- TEXTRANGE textRange;
- textRange.chrg.cpMin = 0;
- textRange.chrg.cpMax = -1;
- textRange.lpstrText = p;
+ TEXTRANGE textRange;
+ textRange.chrg.cpMin = 0;
+ textRange.chrg.cpMax = -1;
+ textRange.lpstrText = p;
- (void)SendMessage(GetHwnd(), EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
+ (void)SendMessage(GetHwnd(), EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
- // believe it or not, but EM_GETTEXTRANGE uses just CR ('\r') for the
- // newlines which is neither Unix nor Windows style (Win95 with
- // riched20.dll shows this behaviour) - convert it to something
- // reasonable
- for ( ; *p; p++ )
- {
- if ( *p == _T('\r') )
- *p = _T('\n');
- }
+ // believe it or not, but EM_GETTEXTRANGE uses just CR ('\r') for
+ // the newlines which is neither Unix nor Windows style (Win95 with
+ // riched20.dll shows this behaviour) - convert it to something
+ // reasonable
+ for ( ; *p; p++ )
+ {
+ if ( *p == _T('\r') )
+ *p = _T('\n');
+ }
- str.UngetWriteBuf();
+ str.UngetWriteBuf();
+ }
+ //else: no text at all, leave the string empty
return str;
}
{
wxString valueDos = wxTextFile::Translate(value, wxTextFileType_Dos);
- SetWindowText(GetHwnd(), valueDos);
+ SetWindowText(GetHwnd(), valueDos.c_str());
+
+ // for compatibility with the GTK and because it is more logical, we
+ // move the cursor to the end of the text after SetValue()
+
+ // GRG, Jun/2000: Changed this back after a lot of discussion
+ // in the lists. wxWindows 2.2 will have a set of flags to
+ // customize this behaviour.
+ //SetInsertionPointEnd();
AdjustSpaceLimit();
}
// Can copy if there's a selection
long from, to;
GetSelection(& from, & to);
- return (from != to);
+ return (from != to) ;
}
bool wxTextCtrl::CanCut() const
// Can cut if there's a selection
long from, to;
GetSelection(& from, & to);
- return (from != to);
+ return (from != to) && (IsEditable());
}
bool wxTextCtrl::CanPaste() const
SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(pos, pos));
#endif // Win32/16
- static const char *nothing = "";
+ static const wxChar *nothing = _T("");
SendMessage(hWnd, EM_REPLACESEL, 0, (LPARAM)nothing);
}
wxString wxTextCtrl::GetLineText(long lineNo) const
{
size_t len = (size_t)GetLineLength(lineNo) + 1;
- char *buf = (char *)malloc(len);
- *(WORD *)buf = len;
- int noChars = (int)SendMessage(GetHwnd(), EM_GETLINE, lineNo, (LPARAM)buf);
- buf[noChars] = 0;
- wxString str(buf);
+ // there must be at least enough place for the length WORD in the
+ // buffer
+ len += sizeof(WORD);
+
+ wxString str;
+ wxChar *buf = str.GetWriteBuf(len);
- free(buf);
+ *(WORD *)buf = (WORD)len;
+ len = (size_t)::SendMessage(GetHwnd(), EM_GETLINE, lineNo, (LPARAM)buf);
+ buf[len] = 0;
+
+ str.UngetWriteBuf(len);
return str;
}
if ( !(m_windowStyle & wxTE_MULTILINE) )
{
wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
- event.SetEventObject( this );
+ InitCommandEvent(event);
+ event.SetString(GetValue());
if ( GetEventHandler()->ProcessEvent(event) )
return;
}
// 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 eventNav;
eventNav.SetDirection(!event.ShiftDown());
- eventNav.SetWindowChange(FALSE);
+ eventNav.SetWindowChange(event.ControlDown());
eventNav.SetEventObject(this);
- if ( GetEventHandler()->ProcessEvent(eventNav) )
+ if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
return;
}
break;
-
- default:
- event.Skip();
- return;
}
- // don't just call event.Skip() because this will cause TABs and ENTERs
- // be passed upwards and we don't always want this - instead process it
- // right here
-
- // FIXME
+ // no, we didn't process it
event.Skip();
}
case EN_CHANGE:
{
wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
- wxString val(GetValue());
- if ( !val.IsNull() )
- event.m_commandString = WXSTRINGCAST val;
- event.SetEventObject( this );
+ InitCommandEvent(event);
+ event.SetString(GetValue());
ProcessCommand(event);
}
break;
case EN_ERRSPACE:
case EN_HSCROLL:
case EN_VSCROLL:
+ return FALSE;
default:
return FALSE;
}
return TRUE;
}
+WXHBRUSH wxTextCtrl::OnCtlColor(WXHDC pDC, WXHWND WXUNUSED(pWnd), WXUINT WXUNUSED(nCtlColor),
+ WXUINT WXUNUSED(message),
+ WXWPARAM WXUNUSED(wParam),
+ WXLPARAM WXUNUSED(lParam))
+{
+#if wxUSE_CTL3D
+ if ( m_useCtl3D )
+ {
+ HBRUSH hbrush = Ctl3dCtlColorEx(message, wParam, lParam);
+ return (WXHBRUSH) hbrush;
+ }
+#endif // wxUSE_CTL3D
+
+ HDC hdc = (HDC)pDC;
+ if (GetParent()->GetTransparentBackground())
+ SetBkMode(hdc, TRANSPARENT);
+ else
+ SetBkMode(hdc, OPAQUE);
+
+ wxColour colBack = GetBackgroundColour();
+
+ if (!IsEnabled() && (GetWindowStyle() & wxTE_MULTILINE) == 0)
+ colBack = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
+
+ ::SetBkColor(hdc, wxColourToRGB(colBack));
+ ::SetTextColor(hdc, wxColourToRGB(GetForegroundColour()));
+
+ wxBrush *brush = wxTheBrushList->FindOrCreateBrush(colBack, wxSOLID);
+
+ return (WXHBRUSH)brush->GetResourceHandle();
+}
+
+// In WIN16, need to override normal erasing because
+// Ctl3D doesn't use the wxWindows background colour.
+#ifdef __WIN16__
+void wxTextCtrl::OnEraseBackground(wxEraseEvent& event)
+{
+ wxColour col(m_backgroundColour);
+
+#if wxUSE_CTL3D
+ if (m_useCtl3D)
+ col = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW);
+#endif
+
+ RECT rect;
+ ::GetClientRect(GetHwnd(), &rect);
+
+ COLORREF ref = PALETTERGB(col.Red(),
+ col.Green(),
+ col.Blue());
+ HBRUSH hBrush = ::CreateSolidBrush(ref);
+ if ( !hBrush )
+ wxLogLastError(wxT("CreateSolidBrush"));
+
+ HDC hdc = (HDC)event.GetDC()->GetHDC();
+
+ int mode = ::SetMapMode(hdc, MM_TEXT);
+
+ ::FillRect(hdc, &rect, hBrush);
+ ::DeleteObject(hBrush);
+ ::SetMapMode(hdc, mode);
+
+}
+#endif
+
void wxTextCtrl::AdjustSpaceLimit()
{
#ifndef __WIN16__
int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
if ( m_windowStyle & wxTE_MULTILINE )
{
- hText *= wxMin(GetNumberOfLines(), 5);
+ hText *= wxMax(GetNumberOfLines(), 5);
}
//else: for single line control everything is ok
// standard handlers for standard edit menu events
// ----------------------------------------------------------------------------
-void wxTextCtrl::OnCut(wxCommandEvent& event)
+void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
{
Cut();
}
-void wxTextCtrl::OnCopy(wxCommandEvent& event)
+void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
{
Copy();
}
-void wxTextCtrl::OnPaste(wxCommandEvent& event)
+void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
{
Paste();
}
-void wxTextCtrl::OnUndo(wxCommandEvent& event)
+void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
{
Undo();
}
-void wxTextCtrl::OnRedo(wxCommandEvent& event)
+void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
{
Redo();
}
event.Enable( CanRedo() );
}
+// ----------------------------------------------------------------------------
+// colour setting for the rich edit controls
+// ----------------------------------------------------------------------------
+
+#if wxUSE_RICHEDIT
+
+// Watcom C++ doesn't define this
+#ifndef SCF_ALL
+#define SCF_ALL 0x0004
+#endif
+
+bool wxTextCtrl::SetBackgroundColour(const wxColour& colour)
+{
+ if ( !wxTextCtrlBase::SetBackgroundColour(colour) )
+ {
+ // colour didn't really change
+ return FALSE;
+ }
+
+ if ( IsRich() )
+ {
+ // rich edit doesn't use WM_CTLCOLOR, hence we need to send
+ // EM_SETBKGNDCOLOR additionally
+ ::SendMessage(GetHwnd(), EM_SETBKGNDCOLOR, 0, wxColourToRGB(colour));
+ }
+
+ return TRUE;
+}
+
+bool wxTextCtrl::SetForegroundColour(const wxColour& colour)
+{
+ if ( !wxTextCtrlBase::SetForegroundColour(colour) )
+ {
+ // colour didn't really change
+ return FALSE;
+ }
+
+ if ( IsRich() )
+ {
+ // change the colour of everything
+ CHARFORMAT cf;
+ wxZeroMemory(cf);
+ cf.cbSize = sizeof(cf);
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = wxColourToRGB(colour);
+ ::SendMessage(GetHwnd(), EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+ }
+
+ return TRUE;
+}
+
+#endif // wxUSE_RICHEDIT
+
// ----------------------------------------------------------------------------
// wxRichEditModule
// ----------------------------------------------------------------------------