+ RECT rect;
+ ::GetClientRect(GetHwnd(), &rect);
+
+ COLORREF ref = wxColourToRGB(col);
+ 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 // Win16
+
+bool wxTextCtrl::AdjustSpaceLimit()
+{
+#ifndef __WIN16__
+ unsigned int limit = ::SendMessage(GetHwnd(), EM_GETLIMITTEXT, 0, 0);
+
+ // HACK: we try to automatically extend the limit for the amount of text
+ // to allow (interactively) entering more than 64Kb of text under
+ // Win9x but we shouldn't reset the text limit which was previously
+ // set explicitly with SetMaxLength()
+ //
+ // we could solve this by storing the limit we set in wxTextCtrl but
+ // to save space we prefer to simply test here the actual limit
+ // value: we consider that SetMaxLength() can only be called for
+ // values < 32Kb
+ if ( limit < 0x8000 )
+ {
+ // we've got more text than limit set by SetMaxLength()
+ return FALSE;
+ }
+
+ unsigned int len = ::GetWindowTextLength(GetHwnd());
+ if ( len >= limit )
+ {
+ limit = len + 0x8000; // 32Kb
+
+#if wxUSE_RICHEDIT
+ if ( IsRich() )
+ {
+ // as a nice side effect, this also allows passing limit > 64Kb
+ ::SendMessage(GetHwnd(), EM_EXLIMITTEXT, 0, limit);
+ }
+ else
+#endif // wxUSE_RICHEDIT
+ {
+ if ( limit > 0xffff )
+ {
+ // this will set it to a platform-dependent maximum (much more
+ // than 64Kb under NT)
+ limit = 0;
+ }
+
+ ::SendMessage(GetHwnd(), EM_LIMITTEXT, limit, 0);
+ }
+ }
+#endif // !Win16
+
+ // we changed the limit
+ return TRUE;
+}
+
+bool wxTextCtrl::AcceptsFocus() const
+{
+ // we don't want focus if we can't be edited
+ return IsEditable() && wxControl::AcceptsFocus();
+}
+
+wxSize wxTextCtrl::DoGetBestSize() const
+{
+ int cx, cy;
+ wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
+
+ int wText = DEFAULT_ITEM_WIDTH;
+
+ int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
+ if ( m_windowStyle & wxTE_MULTILINE )
+ {
+ hText *= wxMax(GetNumberOfLines(), 5);
+ }
+ //else: for single line control everything is ok
+
+ return wxSize(wText, hText);
+}
+
+// ----------------------------------------------------------------------------
+// standard handlers for standard edit menu events
+// ----------------------------------------------------------------------------
+
+void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
+{
+ Cut();
+}
+
+void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
+{
+ Copy();
+}
+
+void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
+{
+ Paste();
+}
+
+void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
+{
+ Undo();
+}
+
+void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
+{
+ Redo();
+}
+
+void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
+{
+ event.Enable( CanCut() );
+}
+
+void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
+{
+ event.Enable( CanCopy() );
+}
+
+void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
+{
+ event.Enable( CanPaste() );
+}
+
+void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
+{
+ event.Enable( CanUndo() );
+}
+
+void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
+{
+ event.Enable( CanRedo() );
+}
+
+// the rest of the file only deals with the rich edit controls
+#if wxUSE_RICHEDIT
+
+// ----------------------------------------------------------------------------
+// EN_LINK processing
+// ----------------------------------------------------------------------------
+
+bool wxTextCtrl::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM *result)
+{
+ NMHDR *hdr = (NMHDR* )lParam;
+ if ( hdr->code == EN_LINK )
+ {
+ ENLINK *enlink = (ENLINK *)hdr;
+
+ switch ( enlink->msg )
+ {
+ case WM_SETCURSOR:
+ // ok, so it is hardcoded - do we really nee to customize it?
+ ::SetCursor(GetHcursorOf(wxCursor(wxCURSOR_HAND)));
+ *result = TRUE;
+ break;
+ case WM_MOUSEMOVE:
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONUP:
+ case WM_RBUTTONDBLCLK:
+ // send a mouse event
+ {
+ static const wxEventType eventsMouse[] =
+ {
+ wxEVT_MOTION,
+ wxEVT_LEFT_DOWN,
+ wxEVT_LEFT_UP,
+ wxEVT_LEFT_DCLICK,
+ wxEVT_RIGHT_DOWN,
+ wxEVT_RIGHT_UP,
+ wxEVT_RIGHT_DCLICK,
+ };
+
+ // the event ids are consecutive
+ wxMouseEvent
+ evtMouse(eventsMouse[enlink->msg - WM_MOUSEMOVE]);
+
+ InitMouseEvent(evtMouse,
+ GET_X_LPARAM(enlink->lParam),
+ GET_Y_LPARAM(enlink->lParam),
+ enlink->wParam);
+
+ wxTextUrlEvent event(m_windowId, evtMouse,
+ enlink->chrg.cpMin,
+ enlink->chrg.cpMax);
+
+ InitCommandEvent(event);
+
+ *result = ProcessCommand(event);
+ }
+ break;
+ }
+
+ return TRUE;
+ }
+
+ // not processed
+ return FALSE;
+}
+
+// ----------------------------------------------------------------------------
+// colour setting for the rich edit controls
+// ----------------------------------------------------------------------------
+
+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;
+}
+
+// ----------------------------------------------------------------------------
+// styling support for rich edit controls
+// ----------------------------------------------------------------------------
+
+bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
+{
+ if ( !IsRich() )
+ {
+ // can't do it with normal text control
+ return FALSE;
+ }
+
+ // the richedit 1.0 doesn't handle setting background colour, so don't
+ // even try to do anything if it's the only thing we want to change
+ if ( m_verRichEdit == 1 && !style.HasFont() && !style.HasTextColour() )
+ {
+ // nothing to do: return TRUE if there was really nothing to do and
+ // FALSE if we failed to set bg colour
+ return !style.HasBackgroundColour();
+ }
+
+ // order the range if needed
+ if ( start > end )
+ {
+ long tmp = start;
+ start = end;
+ end = tmp;
+ }
+
+ // we can only change the format of the selection, so select the range we
+ // want and restore the old selection later
+ long startOld, endOld;
+ GetSelection(&startOld, &endOld);
+
+ // but do we really have to change the selection?
+ bool changeSel = start != startOld || end != endOld;
+
+ if ( changeSel )
+ {
+ DoSetSelection(start, end, FALSE /* don't scroll caret into view */);
+ }
+
+ // initialize CHARFORMAT struct
+#if wxUSE_RICHEDIT2
+ CHARFORMAT2 cf;
+#else
+ CHARFORMAT cf;
+#endif
+
+ wxZeroMemory(cf);
+
+ // we can't use CHARFORMAT2 with RichEdit 1.0, so pretend it is a simple
+ // CHARFORMAT in that case
+#if wxUSE_RICHEDIT2
+ if ( m_verRichEdit == 1 )
+ {
+ // this is the only thing the control is going to grok
+ cf.cbSize = sizeof(CHARFORMAT);
+ }
+ else
+#endif
+ {
+ // CHARFORMAT or CHARFORMAT2
+ cf.cbSize = sizeof(cf);
+ }
+
+ if ( style.HasFont() )
+ {
+ // VZ: CFM_CHARSET doesn't seem to do anything at all in RichEdit 2.0
+ // but using it doesn't seem to hurt neither so leaving it for now
+
+ cf.dwMask |= CFM_FACE | CFM_SIZE | CFM_CHARSET |
+ CFM_ITALIC | CFM_BOLD | CFM_UNDERLINE;
+
+ // fill in data from LOGFONT but recalculate lfHeight because we need
+ // the real height in twips and not the negative number which
+ // wxFillLogFont() returns (this is correct in general and works with
+ // the Windows font mapper, but not here)
+ LOGFONT lf;
+ wxFillLogFont(&lf, &style.GetFont());
+ cf.yHeight = 20*style.GetFont().GetPointSize(); // 1 pt = 20 twips
+ cf.bCharSet = lf.lfCharSet;
+ cf.bPitchAndFamily = lf.lfPitchAndFamily;
+ wxStrncpy( cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName) );
+
+ // also deal with underline/italic/bold attributes: note that we must
+ // always set CFM_ITALIC &c bits in dwMask, even if we don't set the
+ // style to allow clearing it
+ if ( lf.lfItalic )
+ {
+ cf.dwEffects |= CFE_ITALIC;
+ }
+
+ if ( lf.lfWeight == FW_BOLD )
+ {
+ cf.dwEffects |= CFE_BOLD;
+ }
+
+ if ( lf.lfUnderline )
+ {
+ cf.dwEffects |= CFE_UNDERLINE;
+ }
+
+ // strikeout fonts are not supported by wxWindows
+ }
+
+ if ( style.HasTextColour() )
+ {
+ cf.dwMask |= CFM_COLOR;
+ cf.crTextColor = wxColourToRGB(style.GetTextColour());
+ }
+
+#if wxUSE_RICHEDIT2
+ if ( m_verRichEdit != 1 && style.HasBackgroundColour() )
+ {
+ cf.dwMask |= CFM_BACKCOLOR;
+ cf.crBackColor = wxColourToRGB(style.GetBackgroundColour());
+ }
+#endif // wxUSE_RICHEDIT2
+
+ // do format the selection
+ bool ok = ::SendMessage(GetHwnd(), EM_SETCHARFORMAT,
+ SCF_SELECTION, (LPARAM)&cf) != 0;
+ if ( !ok )
+ {
+ wxLogDebug(_T("SendMessage(EM_SETCHARFORMAT, SCF_SELECTION) failed"));
+ }
+
+ if ( changeSel )
+ {
+ // restore the original selection
+ DoSetSelection(startOld, endOld, FALSE);
+ }
+
+ return ok;
+}
+
+// ----------------------------------------------------------------------------
+// wxRichEditModule
+// ----------------------------------------------------------------------------
+
+bool wxRichEditModule::OnInit()
+{
+ // don't do anything - we will load it when needed
+ return TRUE;
+}
+
+void wxRichEditModule::OnExit()
+{
+ for ( size_t i = 0; i < WXSIZEOF(ms_hRichEdit); i++ )
+ {
+ if ( ms_hRichEdit[i] )
+ {
+ ::FreeLibrary(ms_hRichEdit[i]);
+ }
+ }
+}
+
+/* static */
+bool wxRichEditModule::Load(int version)
+{
+ // we don't support loading richedit 3.0 as I don't know how to distinguish
+ // it from 2.0 anyhow
+ wxCHECK_MSG( version == 1 || version == 2, FALSE,
+ _T("incorrect richedit control version requested") );
+
+ // make it the index in the array
+ version--;
+
+ if ( ms_hRichEdit[version] == (HINSTANCE)-1 )
+ {
+ // we had already tried to load it and failed
+ return FALSE;
+ }
+
+ if ( ms_hRichEdit[version] )
+ {
+ // we've already got this one
+ return TRUE;
+ }
+
+ wxString dllname = version ? _T("riched20") : _T("riched32");
+ dllname += _T(".dll");
+
+ ms_hRichEdit[version] = ::LoadLibrary(dllname);
+
+ if ( !ms_hRichEdit[version] )
+ {
+ wxLogSysError(_("Could not load Rich Edit DLL '%s'"), dllname.c_str());
+
+ ms_hRichEdit[version] = (HINSTANCE)-1;
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#endif // wxUSE_RICHEDIT
+
+#endif // wxUSE_TEXTCTRL