diff --git a/TODO b/TODO index f7e67231f8..5a8e28c746 100644 --- a/TODO +++ b/TODO @@ -1,13 +1,18 @@ All +! wxThemeSettings +! actions/wxInputHandler? + * problem with lbox horz scrolling: the focus rect isn't drawn entirely... * write sample testing all listbox styles/events -* text ctrl horz scrolling ++ text ctrl horz scrolling * text ctrl wxTE_XXX styles support MSW GTK +* listbox scrolling leaves unpainted areas + + check/radio box remains pressed in win32 mode + wxCheckListBox::HitTest doesn't work (clicking the check) diff --git a/configure.in b/configure.in index e7b81074bd..81f9cbb5f3 100644 --- a/configure.in +++ b/configure.in @@ -3519,6 +3519,7 @@ fi if test "$wxUSE_CLIPBOARD" = "yes"; then AC_DEFINE(wxUSE_CLIPBOARD) + AC_DEFINE(wxUSE_DATAOBJ) fi if test "$wxUSE_DRAG_AND_DROP" = "yes" ; then diff --git a/distrib/msw/tmake/filelist.txt b/distrib/msw/tmake/filelist.txt index 820c16f577..b347b2e766 100644 --- a/distrib/msw/tmake/filelist.txt +++ b/distrib/msw/tmake/filelist.txt @@ -337,13 +337,13 @@ button.cpp R checkbox.cpp R checklst.cpp R choice.cpp R -clipbrd.cpp R +clipbrd.cpp R L colour.cpp R L combobox.cpp R control.cpp R cursor.cpp R L data.cpp R L -dataobj.cpp R +dataobj.cpp R L dc.cpp R L dcclient.cpp R L dcmemory.cpp R L @@ -379,7 +379,7 @@ statline.cpp R stattext.cpp R tbargtk.cpp R textctrl.cpp R -timer.cpp R +timer.cpp R L tooltip.cpp R utilsgtk.cpp R L utilsres.cpp R diff --git a/include/wx/caret.h b/include/wx/caret.h index 9e0f3d3ea8..07e06afeea 100644 --- a/include/wx/caret.h +++ b/include/wx/caret.h @@ -196,5 +196,31 @@ private: #include "wx/generic/caret.h" #endif // platform +// ---------------------------------------------------------------------------- +// wxCaretSuspend: a simple class which hides the caret in its ctor and +// restores it in the dtor, this should be used when drawing on the screen to +// avoid overdrawing the caret +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxCaretSuspend +{ +public: + wxCaretSuspend(wxWindow *win) + { + m_caret = win->GetCaret(); + if ( m_caret ) + m_caret->Hide(); + } + + ~wxCaretSuspend() + { + if ( m_caret ) + m_caret->Show(); + } + +private: + wxCaret *m_caret; +}; + #endif // _WX_CARET_H_BASE_ diff --git a/include/wx/generic/caret.h b/include/wx/generic/caret.h index 9b2340de44..173e80a37b 100644 --- a/include/wx/generic/caret.h +++ b/include/wx/generic/caret.h @@ -73,6 +73,12 @@ private: // GTK specific initialization void InitGeneric(); + // the bitmap holding the part of window hidden by the caret when it was + // at (m_xOld, m_yOld) + wxBitmap m_bmpUnderCaret; + int m_xOld, + m_yOld; + wxCaretTimer m_timer; bool m_blinkedOut, // TRUE => caret hidden right now m_hasFocus; // TRUE => our window has focus diff --git a/include/wx/scrolwin.h b/include/wx/scrolwin.h index 0da445f5f4..6c032db884 100644 --- a/include/wx/scrolwin.h +++ b/include/wx/scrolwin.h @@ -82,7 +82,7 @@ public: virtual void OnDraw(wxDC& WXUNUSED(dc)) { } // change the DC origin according to the scroll position. - void DoPrepareDC(wxDC& dc); + virtual void DoPrepareDC(wxDC& dc); // the methods to be called from the window event handlers void HandleOnScroll(wxScrollWinEvent& event); diff --git a/include/wx/statbmp.h b/include/wx/statbmp.h index c4e2c512c7..cc1c517e88 100644 --- a/include/wx/statbmp.h +++ b/include/wx/statbmp.h @@ -38,7 +38,7 @@ public: virtual bool AcceptsFocus() const { return FALSE; } protected: - virtual wxSize DoGetBestSize() const; + virtual wxSize DoGetBestClientSize() const; }; #if defined(__WXUNIVERSAL__) diff --git a/include/wx/univ/colschem.h b/include/wx/univ/colschem.h index bb134417be..9d855b4a5f 100644 --- a/include/wx/univ/colschem.h +++ b/include/wx/univ/colschem.h @@ -80,7 +80,8 @@ typedef wxColourScheme wxColorScheme; // retrieve the default colour from the theme or the given scheme #define wxSCHEME_COLOUR(scheme, what) scheme->Get(wxColorScheme::what) -#define wxTHEME_COLOUR(what) wxSCHEME_COLOUR(wxTheme::Get(), what) +#define wxTHEME_COLOUR(what) \ + wxSCHEME_COLOUR(wxTheme::Get()->GetColourScheme(), what) // get the background colour for the window in the current theme #define wxTHEME_BG_COLOUR(win) \ diff --git a/include/wx/univ/renderer.h b/include/wx/univ/renderer.h index 96af94c061..9d97294885 100644 --- a/include/wx/univ/renderer.h +++ b/include/wx/univ/renderer.h @@ -32,6 +32,7 @@ class WXDLLEXPORT wxDC; class WXDLLEXPORT wxCheckListBox; class WXDLLEXPORT wxListBox; class WXDLLEXPORT wxScrollBar; +class WXDLLEXPORT wxTextCtrl; class WXDLLEXPORT wxWindow; #include "wx/string.h" @@ -97,15 +98,6 @@ public: int indexAccel = -1, wxRect *rectBounds = NULL) = 0; - // draw a line of the text ctrl optionally highlighting the characters in - // the given range - virtual void DrawTextLine(wxDC& dc, - const wxString& text, - const wxRect &rect, - int selStart = -1, - int selEnd = -1, - int flags = 0) = 0; - // draw the border and optionally return the rectangle containing the // region inside the border virtual void DrawBorder(wxDC& dc, @@ -234,6 +226,14 @@ public: virtual wxSize GetRadioBitmapSize() const = 0; virtual wxCoord GetCheckItemMargin() const = 0; + // convert between text rectangle and client rectangle for text controls: + // by default, the former is equal to the latter, but it can be made + // smaller to leave margins around text + virtual wxRect GetTextTotalArea(const wxTextCtrl *text, + const wxRect& rect) = 0; + virtual wxRect GetTextClientArea(const wxTextCtrl *text, + const wxRect& rect) = 0; + // virtual dtor for any base class virtual ~wxRenderer(); @@ -300,13 +300,6 @@ public: wxRect *rectBounds = NULL) { m_renderer->DrawButtonLabel(dc, label, image, rect, flags, align, indexAccel, rectBounds); } - virtual void DrawTextLine(wxDC& dc, - const wxString& text, - const wxRect &rect, - int selStart = -1, - int selEnd = -1, - int flags = 0) - { m_renderer->DrawTextLine(dc, text, rect, flags); } virtual void DrawBorder(wxDC& dc, wxBorder border, const wxRect& rect, @@ -410,6 +403,11 @@ public: virtual wxCoord GetCheckItemMargin() const { return m_renderer->GetCheckItemMargin(); } + virtual wxRect GetTextTotalArea(const wxTextCtrl *text, const wxRect& rect) + { return m_renderer->GetTextTotalArea(text, rect); } + virtual wxRect GetTextClientArea(const wxTextCtrl *text, const wxRect& rect) + { return m_renderer->GetTextClientArea(text, rect); } + protected: wxRenderer *m_renderer; }; @@ -428,7 +426,6 @@ public: // operations void DrawLabel(const wxBitmap& bitmap = wxNullBitmap, wxCoord marginX = 0, wxCoord marginY = 0); - void DrawTextLine(const wxString& text, int selStart = -1, int selEnd = -1); void DrawItems(const wxListBox *listbox, size_t itemFirst, size_t itemLast); void DrawCheckItems(const wxCheckListBox *listbox, diff --git a/include/wx/univ/statbmp.h b/include/wx/univ/statbmp.h index b3b045a4bc..7579b0b887 100644 --- a/include/wx/univ/statbmp.h +++ b/include/wx/univ/statbmp.h @@ -64,7 +64,6 @@ public: wxIcon GetIcon() const; private: - virtual wxSize DoGetBestClientSize() const; virtual void DoDraw(wxControlRenderer *renderer); // the bitmap which we show diff --git a/include/wx/univ/textctrl.h b/include/wx/univ/textctrl.h index 21025ab817..5638af05c3 100644 --- a/include/wx/univ/textctrl.h +++ b/include/wx/univ/textctrl.h @@ -53,6 +53,8 @@ class WXDLLEXPORT wxCaret; // mouse selection #define wxACTION_TEXT_ANCHOR_SEL _T("anchorsel") #define wxACTION_TEXT_EXTEND_SEL _T("extendsel") +#define wxACTION_TEXT_SEL_WORD _T("wordsel") +#define wxACTION_TEXT_SEL_LINE _T("linesel") // ---------------------------------------------------------------------------- // wxTextCtrl @@ -156,6 +158,7 @@ public: // caret stuff virtual void ShowCaret(bool show = TRUE); void HideCaret() { ShowCaret(FALSE); } + wxCoord GetCaretPosition() const; // in pixels // helpers for cursor movement long GetWordStart() const; @@ -165,10 +168,25 @@ public: bool HasSelection() const { return m_selStart != -1; } void ClearSelection(); void RemoveSelection(); + wxString GetSelectionText() const; + + // find the character at this position, return TRUE if the character is + // really there or FALSE if it the position is beyond the end of line/text + // and the returned character is the last one + bool HitTest(const wxPoint& pt, long *col, long *row) const; + + // scroll the window horizontally + void ScrollText(wxCoord x); + + // adjust the DC for horz text control scrolling too + virtual void DoPrepareDC(wxDC& dc); // implementation only from now on // ------------------------------- + // override this to take into account our scrollbar-less scrolling + virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const; + // set the right colours virtual bool IsContainerWindow() const { return TRUE; } virtual wxBorder GetDefaultBorder() const { return wxBORDER_SUNKEN; } @@ -180,6 +198,10 @@ public: protected: // draw the text + void DrawTextLine(wxDC& dc, const wxRect& rect, + const wxString& text, + long selStart, long selEnd); + virtual void DoDraw(wxControlRenderer *renderer); // calc the size from the text extent @@ -191,11 +213,31 @@ protected: // common part of all ctors void Init(); - // is this a single-line control? + // more readable flag testing methods bool IsSingleLine() const { return !(GetWindowStyle() & wxTE_MULTILINE); } + bool IsPassword() const { return (GetWindowStyle() & wxTE_PASSWORD) != 0; } + + // get the extent (width) of the text + wxCoord GetTextWidth(const wxString& text) const; + + // refresh the text in the given range (in client coords) of this line + void RefreshLine(long line, wxCoord from, wxCoord to); + + // get the text to show: either the text itself or the text replaced with + // starts for wxTE_PASSWORD control + wxString GetTextToShow(const wxString& text) const; + + // get the start and end of the selection for this line: if the line is + // outside the selection, both will be -1 and FALSE will be returned + bool GetSelectedPartOfLine(long line, int *start, int *end) const; + + // update the text rect: the zone inside our client rect (its coords are + // client coords) which contains the text + void UpdateTextRect(); // event handlers void OnChar(wxKeyEvent& event); + void OnSize(wxSizeEvent& event); private: // the value (may be only part of it for the multiline controls) @@ -215,6 +257,13 @@ private: bool m_isModified:1, m_isEditable:1; + // the rectangle (in client coordinates) to draw text inside + wxRect m_rectText; + + // for the controls without horz scrollbar: the offset by which the window + // is scrolled to the right + wxCoord m_ofsHorz; + DECLARE_EVENT_TABLE() DECLARE_DYNAMIC_CLASS(wxTextCtrl) }; diff --git a/samples/univ/univ.cpp b/samples/univ/univ.cpp index 0c42c527ea..80bccab9a2 100644 --- a/samples/univ/univ.cpp +++ b/samples/univ/univ.cpp @@ -214,6 +214,7 @@ bool MyUnivApp::OnInit() #ifdef DEBUG_LISTBOX wxLog::AddTraceMask(_T("listbox")); #endif + wxLog::AddTraceMask(_T("text")); return TRUE; } diff --git a/setup.h.in b/setup.h.in index e453172d7d..f370bde502 100644 --- a/setup.h.in +++ b/setup.h.in @@ -563,6 +563,10 @@ * Use clipboard */ #define wxUSE_CLIPBOARD 0 +/* + * Use wxDataObject + */ +#define wxUSE_DATAOBJ 0 /* * Use tooltips */ diff --git a/src/common/ctrlcmn.cpp b/src/common/ctrlcmn.cpp index 8ff69b938f..6f73dfb776 100644 --- a/src/common/ctrlcmn.cpp +++ b/src/common/ctrlcmn.cpp @@ -125,7 +125,7 @@ void wxControlBase::InitCommandEvent(wxCommandEvent& event) const #if wxUSE_STATBMP -wxSize wxStaticBitmapBase::DoGetBestSize() const +wxSize wxStaticBitmapBase::DoGetBestClientSize() const { wxBitmap bmp = GetBitmap(); if ( bmp.Ok() ) diff --git a/src/generic/caret.cpp b/src/generic/caret.cpp index 7ccba3ffdf..8110dea83b 100644 --- a/src/generic/caret.cpp +++ b/src/generic/caret.cpp @@ -33,6 +33,7 @@ #ifndef WX_PRECOMP #include "wx/window.h" #include "wx/dcclient.h" + #include "wx/dcmemory.h" #endif //WX_PRECOMP #include "wx/caret.h" @@ -91,6 +92,10 @@ void wxCaret::InitGeneric() { m_hasFocus = TRUE; m_blinkedOut = FALSE; + + m_xOld = + m_yOld = -1; + m_bmpUnderCaret.Create(m_width, m_height); } wxCaret::~wxCaret() @@ -98,7 +103,8 @@ wxCaret::~wxCaret() if ( IsVisible() ) { // stop blinking - m_timer.Stop(); + if ( m_timer.IsRunning() ) + m_timer.Stop(); } } @@ -108,7 +114,9 @@ wxCaret::~wxCaret() void wxCaret::DoShow() { - m_timer.Start(GetBlinkTime()); + int blinkTime = GetBlinkTime(); + if ( blinkTime ) + m_timer.Start(blinkTime); m_blinkedOut = TRUE; Blink(); @@ -126,11 +134,20 @@ void wxCaret::DoHide() void wxCaret::DoMove() { - if ( IsVisible() && !m_blinkedOut ) + if ( IsVisible() ) { - Blink(); + if ( !m_blinkedOut ) + { + // hide it right now and it will be shown the next time it blinks + Blink(); + + // but if the caret is not blinking, we should blink it back into + // visibility manually + if ( !m_timer.IsRunning() ) + Blink(); + } } - //else: will be shown at the correct location next time it blinks + //else: will be shown at the correct location when it is shown } // ---------------------------------------------------------------------------- @@ -153,10 +170,14 @@ void wxCaret::OnKillFocus() // the caret must be shown - otherwise, if it is hidden now, it will // stay so until the focus doesn't return because it won't blink any // more - m_blinkedOut = FALSE; - } - Refresh(); + // hide it first if it isn't hidden ... + if ( !m_blinkedOut ) + Blink(); + + // .. and show it in the new style + Blink(); + } } // ---------------------------------------------------------------------------- @@ -172,20 +193,41 @@ void wxCaret::Blink() void wxCaret::Refresh() { - if ( !m_blinkedOut ) + wxClientDC dcWin(GetWindow()); + wxMemoryDC dcMem; + dcMem.SelectObject(m_bmpUnderCaret); + if ( m_blinkedOut ) { - wxClientDC dc(GetWindow()); - DoDraw(&dc); + // restore the old image + dcWin.Blit(m_xOld, m_yOld, m_width, m_height, + &dcMem, 0, 0); + m_xOld = + m_yOld = -1; } else { - // FIXME can't be less efficient than this... we probably should use - // backing store for the caret instead of leaving all the burden - // of correct refresh logic handling to the user code + if ( m_xOld == -1 && m_yOld == -1 ) + { + // save the part we're going to overdraw - // NB: +1 is needed! - wxRect rect(m_x, m_y, m_width + 1, m_height + 1); - GetWindow()->Refresh(FALSE, &rect); + int x = m_x, + y = m_y; +#if defined(__WXGTK__) && !defined(__WX_DC_BLIT_FIXED__) + wxPoint pt = dcWin.GetDeviceOrigin(); + x += pt.x; + y += pt.y; +#endif // broken wxGTK wxDC::Blit + dcMem.Blit(0, 0, m_width, m_height, + &dcWin, x, y); + + m_xOld = m_x; + m_yOld = m_y; + } + //else: we already saved the image below the caret, don't do it any + // more + + // and draw the caret there + DoDraw(&dcWin); } } @@ -193,19 +235,14 @@ void wxCaret::DoDraw(wxDC *dc) { dc->SetPen( *wxBLACK_PEN ); - // VZ: Robert's code for I-shaped caret - this is nice but doesn't look - // at all the same as the MSW version and I don't know how to indicate - // that the window has focus or not with such caret -#if 0 - dc->DrawLine( m_x, m_y, m_x+m_width, m_y ); - dc->DrawLine( m_x, m_y+m_height, m_x+m_width, m_y+m_height ); - dc->DrawLine( m_x+(m_width/2), m_y, m_x+(m_width/2), m_y+m_height ); -// dc->DrawLine( m_x+(m_width/2)+1, m_y, m_x+(m_width/2)+1, m_y+m_height ); -#else // 1 - if ( m_hasFocus ) - dc->SetBrush( *wxBLACK_BRUSH ); - dc->DrawRectangle( m_x, m_y, m_width, m_height ); -#endif // 0/1 + dc->SetBrush(*(m_hasFocus ? wxBLACK_BRUSH : wxTRANSPARENT_BRUSH)); + dc->SetPen(*wxBLACK_PEN); + + // VZ: unfortunately, the rectangle comes out a pixel smaller when this is + // done under wxGTK - no idea why + //dc->SetLogicalFunction(wxINVERT); + + dc->DrawRectangle(m_x, m_y, m_width, m_height); } #endif // wxUSE_CARET diff --git a/src/generic/laywin.cpp b/src/generic/laywin.cpp index 3e8df62f23..2c569b01dd 100644 --- a/src/generic/laywin.cpp +++ b/src/generic/laywin.cpp @@ -24,7 +24,6 @@ #endif #ifndef WX_PRECOMP -#include "wx/wx.h" #include "wx/mdi.h" #endif diff --git a/src/generic/scrolwin.cpp b/src/generic/scrolwin.cpp index da08db1170..e6258d7af4 100644 --- a/src/generic/scrolwin.cpp +++ b/src/generic/scrolwin.cpp @@ -480,8 +480,9 @@ void wxScrollHelper::AdjustScrollbars() void wxScrollHelper::DoPrepareDC(wxDC& dc) { - dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine, - -m_yScrollPosition * m_yScrollPixelsPerLine ); + wxPoint pt = dc.GetDeviceOrigin(); + dc.SetDeviceOrigin( pt.x - m_xScrollPosition * m_xScrollPixelsPerLine, + pt.y - m_yScrollPosition * m_yScrollPixelsPerLine ); dc.SetUserScale( m_scaleX, m_scaleY ); } diff --git a/src/generic/treelay.cpp b/src/generic/treelay.cpp index 947d53e6ac..a012d76432 100644 --- a/src/generic/treelay.cpp +++ b/src/generic/treelay.cpp @@ -21,7 +21,6 @@ #endif #ifndef WX_PRECOMP -#include "wx/wx.h" #endif #if wxUSE_TREELAYOUT diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index 87ee3bdcb3..3943bb2296 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -73,15 +73,15 @@ static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } #include "gdk/gdkprivate.h" -void gdk_wx_draw_bitmap (GdkDrawable *drawable, - GdkGC *gc, - GdkDrawable *src, - gint xsrc, - gint ysrc, - gint xdest, - gint ydest, - gint width, - gint height) +void gdk_wx_draw_bitmap(GdkDrawable *drawable, + GdkGC *gc, + GdkDrawable *src, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) { gint src_width, src_height; #ifndef __WXGTK20__ @@ -1068,9 +1068,12 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, } } -bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, - wxDC *source, wxCoord xsrc, wxCoord ysrc, - int logical_func, bool useMask ) +bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, + wxCoord width, wxCoord height, + wxDC *source, + wxCoord xsrc, wxCoord ysrc, + int logical_func, + bool useMask ) { /* this is the nth try to get this utterly useless function to work. it now completely ignores the scaling or translation @@ -1083,6 +1086,12 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he if (!m_window) return FALSE; +#if 0 + // transform the source DC coords to the device ones + xsrc = XLOG2DEV(xsrc); + ysrc = YLOG2DEV(ysrc); +#endif + wxClientDC *srcDC = (wxClientDC*)source; wxMemoryDC *memDC = (wxMemoryDC*)source; @@ -2213,13 +2222,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC) wxPaintDC::wxPaintDC( wxWindow *win ) : wxClientDC( win ) { -#ifdef __WXUNIVERSAL__ - wxPoint ptOrigin = win->GetClientAreaOrigin(); - SetDeviceOrigin(ptOrigin.x, ptOrigin.y); - wxSize size = win->GetClientSize(); - SetClippingRegion(wxPoint(0, 0), size); -#endif // __WXUNIVERSAL__ - #if USE_PAINT_REGION if (!win->m_clipPaintRegion) return; @@ -2245,13 +2247,19 @@ wxPaintDC::wxPaintDC( wxWindow *win ) IMPLEMENT_DYNAMIC_CLASS(wxClientDC,wxWindowDC) wxClientDC::wxClientDC() - : wxWindowDC() + : wxWindowDC() { } wxClientDC::wxClientDC( wxWindow *win ) - : wxWindowDC( win ) + : wxWindowDC( win ) { +#ifdef __WXUNIVERSAL__ + wxPoint ptOrigin = win->GetClientAreaOrigin(); + SetDeviceOrigin(ptOrigin.x, ptOrigin.y); + wxSize size = win->GetClientSize(); + SetClippingRegion(wxPoint(0, 0), size); +#endif // __WXUNIVERSAL__ } // ---------------------------------------------------------------------------- diff --git a/src/gtk/files.lst b/src/gtk/files.lst index 9708c4099e..1beb2ff38e 100644 --- a/src/gtk/files.lst +++ b/src/gtk/files.lst @@ -1,4 +1,4 @@ -# This file was automatically generated by tmake at 14:01, 2000/08/11 +# This file was automatically generated by tmake at 18:07, 2000/09/19 # DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE GTK.T! ALL_SOURCES = \ generic/busyinfo.cpp \ @@ -976,9 +976,11 @@ GUI_LOWLEVEL_OBJS = \ app.o \ bitmap.o \ brush.o \ + clipbrd.o \ colour.o \ cursor.o \ data.o \ + dataobj.o \ dc.o \ dcclient.o \ dcmemory.o \ @@ -993,7 +995,7 @@ GUI_LOWLEVEL_OBJS = \ pen.o \ region.o \ settings.o \ - timer.o \ + timer.o \ utilsgtk.o \ win_gtk.o \ window.o @@ -1002,9 +1004,11 @@ GUI_LOWLEVEL_DEPS = \ app.d \ bitmap.d \ brush.d \ + clipbrd.d \ colour.d \ cursor.d \ data.d \ + dataobj.d \ dc.d \ dcclient.d \ dcmemory.d \ @@ -1019,7 +1023,7 @@ GUI_LOWLEVEL_DEPS = \ pen.d \ region.d \ settings.d \ - timer.d \ + timer.d \ utilsgtk.d \ win_gtk.d \ window.d diff --git a/src/gtk1/dcclient.cpp b/src/gtk1/dcclient.cpp index 87ee3bdcb3..3943bb2296 100644 --- a/src/gtk1/dcclient.cpp +++ b/src/gtk1/dcclient.cpp @@ -73,15 +73,15 @@ static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } #include "gdk/gdkprivate.h" -void gdk_wx_draw_bitmap (GdkDrawable *drawable, - GdkGC *gc, - GdkDrawable *src, - gint xsrc, - gint ysrc, - gint xdest, - gint ydest, - gint width, - gint height) +void gdk_wx_draw_bitmap(GdkDrawable *drawable, + GdkGC *gc, + GdkDrawable *src, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) { gint src_width, src_height; #ifndef __WXGTK20__ @@ -1068,9 +1068,12 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, } } -bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, - wxDC *source, wxCoord xsrc, wxCoord ysrc, - int logical_func, bool useMask ) +bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, + wxCoord width, wxCoord height, + wxDC *source, + wxCoord xsrc, wxCoord ysrc, + int logical_func, + bool useMask ) { /* this is the nth try to get this utterly useless function to work. it now completely ignores the scaling or translation @@ -1083,6 +1086,12 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he if (!m_window) return FALSE; +#if 0 + // transform the source DC coords to the device ones + xsrc = XLOG2DEV(xsrc); + ysrc = YLOG2DEV(ysrc); +#endif + wxClientDC *srcDC = (wxClientDC*)source; wxMemoryDC *memDC = (wxMemoryDC*)source; @@ -2213,13 +2222,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC) wxPaintDC::wxPaintDC( wxWindow *win ) : wxClientDC( win ) { -#ifdef __WXUNIVERSAL__ - wxPoint ptOrigin = win->GetClientAreaOrigin(); - SetDeviceOrigin(ptOrigin.x, ptOrigin.y); - wxSize size = win->GetClientSize(); - SetClippingRegion(wxPoint(0, 0), size); -#endif // __WXUNIVERSAL__ - #if USE_PAINT_REGION if (!win->m_clipPaintRegion) return; @@ -2245,13 +2247,19 @@ wxPaintDC::wxPaintDC( wxWindow *win ) IMPLEMENT_DYNAMIC_CLASS(wxClientDC,wxWindowDC) wxClientDC::wxClientDC() - : wxWindowDC() + : wxWindowDC() { } wxClientDC::wxClientDC( wxWindow *win ) - : wxWindowDC( win ) + : wxWindowDC( win ) { +#ifdef __WXUNIVERSAL__ + wxPoint ptOrigin = win->GetClientAreaOrigin(); + SetDeviceOrigin(ptOrigin.x, ptOrigin.y); + wxSize size = win->GetClientSize(); + SetClippingRegion(wxPoint(0, 0), size); +#endif // __WXUNIVERSAL__ } // ---------------------------------------------------------------------------- diff --git a/src/gtk1/files.lst b/src/gtk1/files.lst index 9708c4099e..1beb2ff38e 100644 --- a/src/gtk1/files.lst +++ b/src/gtk1/files.lst @@ -1,4 +1,4 @@ -# This file was automatically generated by tmake at 14:01, 2000/08/11 +# This file was automatically generated by tmake at 18:07, 2000/09/19 # DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE GTK.T! ALL_SOURCES = \ generic/busyinfo.cpp \ @@ -976,9 +976,11 @@ GUI_LOWLEVEL_OBJS = \ app.o \ bitmap.o \ brush.o \ + clipbrd.o \ colour.o \ cursor.o \ data.o \ + dataobj.o \ dc.o \ dcclient.o \ dcmemory.o \ @@ -993,7 +995,7 @@ GUI_LOWLEVEL_OBJS = \ pen.o \ region.o \ settings.o \ - timer.o \ + timer.o \ utilsgtk.o \ win_gtk.o \ window.o @@ -1002,9 +1004,11 @@ GUI_LOWLEVEL_DEPS = \ app.d \ bitmap.d \ brush.d \ + clipbrd.d \ colour.d \ cursor.d \ data.d \ + dataobj.d \ dc.d \ dcclient.d \ dcmemory.d \ @@ -1019,7 +1023,7 @@ GUI_LOWLEVEL_DEPS = \ pen.d \ region.d \ settings.d \ - timer.d \ + timer.d \ utilsgtk.d \ win_gtk.d \ window.d diff --git a/src/univ/checklst.cpp b/src/univ/checklst.cpp index ee8e301e3b..8c8e524819 100644 --- a/src/univ/checklst.cpp +++ b/src/univ/checklst.cpp @@ -215,7 +215,8 @@ bool wxStdCheckListboxInputHandler::HandleMouse(wxControl *control, wxCheckListBox *lbox = wxStaticCast(control, wxCheckListBox); int x, y; - const wxPoint& pt = event.GetPosition(); + wxPoint pt = event.GetPosition(); + pt -= control->GetClientAreaOrigin(); lbox->CalcUnscrolledPosition(pt.x, pt.y, &x, &y); wxRenderer *renderer = lbox->GetRenderer(); diff --git a/src/univ/files.lst b/src/univ/files.lst index 20c255bfe9..e897d14e98 100644 --- a/src/univ/files.lst +++ b/src/univ/files.lst @@ -15,12 +15,13 @@ UNIVOBJS = \ statbox.o \ statline.o \ stattext.o \ - textctrl.o \ theme.o \ gtk.o \ winuniv.o \ win32.o +# textctrl.o \ + UNIVDEPS = \ bmpbuttn.d \ button.d \ diff --git a/src/univ/listbox.cpp b/src/univ/listbox.cpp index 9def6eb3b9..2ae8af949f 100644 --- a/src/univ/listbox.cpp +++ b/src/univ/listbox.cpp @@ -524,15 +524,20 @@ void wxListBox::DoDraw(wxControlRenderer *renderer) PrepareDC(dc); dc.SetFont(GetFont()); - // get the items which must be redrawn - wxCoord lineHeight = GetLineHeight(); + // get the update rect wxRegion rgnUpdate = GetUpdateRegion(); rgnUpdate.Intersect(GetClientRect()); wxRect rectUpdate = rgnUpdate.GetBox(); + wxPoint ptOrigin = GetClientAreaOrigin(); + rectUpdate.x -= ptOrigin.x; + rectUpdate.y -= ptOrigin.y; int yTop, yBottom; CalcUnscrolledPosition(0, rectUpdate.GetTop(), NULL, &yTop); CalcUnscrolledPosition(0, rectUpdate.GetBottom(), NULL, &yBottom); + + // get the items which must be redrawn + wxCoord lineHeight = GetLineHeight(); size_t itemFirst = yTop / lineHeight, itemLast = (yBottom + lineHeight - 1) / lineHeight, itemMax = m_strings.GetCount(); @@ -934,8 +939,10 @@ wxStdListboxInputHandler::wxStdListboxInputHandler(wxInputHandler *handler, int wxStdListboxInputHandler::HitTest(const wxListBox *lbox, const wxMouseEvent& event) { + wxPoint pt = event.GetPosition(); + pt -= lbox->GetClientAreaOrigin(); int y; - lbox->CalcUnscrolledPosition(0, event.GetPosition().y, NULL, &y); + lbox->CalcUnscrolledPosition(0, pt.y, NULL, &y); int item = y / lbox->GetLineHeight(); return (item >= 0) && (item < lbox->GetCount()) ? item : -1; diff --git a/src/univ/renderer.cpp b/src/univ/renderer.cpp index 715191e7d2..63cb3aa07b 100644 --- a/src/univ/renderer.cpp +++ b/src/univ/renderer.cpp @@ -456,7 +456,8 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar, { wxRect rectUpdate = rgnUpdate.GetBox(); - wxLogTrace(_T("scroll"), _T("%s redraw: update box is (%d, %d)-(%d, %d)"), + wxLogTrace(_T("scrollbar"), + _T("%s redraw: update box is (%d, %d)-(%d, %d)"), scrollbar->IsVertical() ? _T("vert") : _T("horz"), rectUpdate.GetLeft(), rectUpdate.GetTop(), @@ -477,7 +478,7 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar, if ( rgnUpdate.Contains(rectBar) ) { - wxLogTrace(_T("scroll"), + wxLogTrace(_T("scrollbar"), _T("drawing bar part %d at (%d, %d)-(%d, %d)"), nBar + 1, rectBar.GetLeft(), @@ -507,7 +508,7 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar, wxRect rectArrow = m_renderer->GetScrollbarRect(scrollbar, elem); if ( rgnUpdate.Contains(rectArrow) ) { - wxLogTrace(_T("scroll"), + wxLogTrace(_T("scrollbar"), _T("drawing arrow %d at (%d, %d)-(%d, %d)"), nArrow + 1, rectArrow.GetLeft(), @@ -529,7 +530,8 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar, wxRect rectThumb = m_renderer->GetScrollbarRect(scrollbar, elem); if ( rectThumb.width && rectThumb.height && rgnUpdate.Contains(rectThumb) ) { - wxLogTrace(_T("scroll"), _T("drawing thumb at (%d, %d)-(%d, %d)"), + wxLogTrace(_T("scrollbar"), + _T("drawing thumb at (%d, %d)-(%d, %d)"), rectThumb.GetLeft(), rectThumb.GetTop(), rectThumb.GetRight(), @@ -630,12 +632,3 @@ void wxControlRenderer::DoDrawItems(const wxListBox *lbox, } } -void wxControlRenderer::DrawTextLine(const wxString& text, - int selStart, int selEnd) -{ - m_dc.SetFont(m_window->GetFont()); - m_dc.SetTextForeground(m_window->GetForegroundColour()); - - m_renderer->DrawTextLine(m_dc, text, m_rect, selStart, selEnd, - m_window->GetStateFlags()); -} diff --git a/src/univ/statbmp.cpp b/src/univ/statbmp.cpp index b10c04ae6a..ec00a57086 100644 --- a/src/univ/statbmp.cpp +++ b/src/univ/statbmp.cpp @@ -102,11 +102,6 @@ wxIcon wxStaticBitmap::GetIcon() const // drawing // ---------------------------------------------------------------------------- -wxSize wxStaticBitmap::DoGetBestClientSize() const -{ - return wxStaticBitmapBase::DoGetBestSize(); -} - void wxStaticBitmap::DoDraw(wxControlRenderer *renderer) { wxControl::DoDraw(renderer); diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index fba555a6da..a39bad8a68 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -30,6 +30,10 @@ #if wxUSE_TEXTCTRL #ifndef WX_PRECOMP + #include "wx/log.h" + + #include "wx/clipbrd.h" + #include "wx/dcclient.h" #include "wx/validate.h" #include "wx/textctrl.h" @@ -39,6 +43,7 @@ #include "wx/univ/inphand.h" #include "wx/univ/renderer.h" +#include "wx/univ/colschem.h" #include "wx/univ/theme.h" // ============================================================================ @@ -47,6 +52,7 @@ BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) EVT_CHAR(OnChar) + EVT_SIZE(OnSize) END_EVENT_TABLE() IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) @@ -64,7 +70,7 @@ void wxTextCtrl::Init() m_isModified = FALSE; m_isEditable = TRUE; - m_caret = (wxCaret *)NULL; + m_ofsHorz = 0; } bool wxTextCtrl::Create(wxWindow *parent, @@ -83,15 +89,17 @@ bool wxTextCtrl::Create(wxWindow *parent, } // FIXME use renderer - wxCaret *caret = new wxCaret(this, 2, GetCharHeight()); + wxCaret *caret = new wxCaret(this, 1, GetCharHeight()); + caret->SetBlinkTime(0); SetCaret(caret); - caret->Show(); SetCursor(wxCURSOR_IBEAM); SetValue(value); SetBestSize(size); + caret->Show(); + return TRUE; } @@ -122,6 +130,10 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text) wxCHECK_RET( from >= 0 && to >= 0 && from <= to && to <= GetLastPosition(), _T("invalid range in wxTextCtrl::Replace") ); + // remember the line width as we may need to refresh beyond the end of the + // new text if the text shrinks + wxCoord widthOld = GetTextWidth(m_value); + // replace the part of the text with the new value wxString valueNew(m_value, (size_t)from); valueNew += text; @@ -138,8 +150,12 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text) // for selection anchor) ClearSelection(); - // FIXME shouldn't refresh everything of course - Refresh(); + // refresh to the end of the line + wxCoord start = GetTextWidth(m_value.Left((size_t)from)); + wxCoord end = GetTextWidth(m_value); + RefreshLine(0, start, wxMax(end, widthOld)); + + // and the affected parts of the next line (TODO) } void wxTextCtrl::Remove(long from, long to) @@ -158,6 +174,9 @@ void wxTextCtrl::Remove(long from, long to) void wxTextCtrl::WriteText(const wxString& text) { + // replace the selection with the new text + RemoveSelection(); + Replace(m_curPos, m_curPos, text); } @@ -174,7 +193,7 @@ void wxTextCtrl::AppendText(const wxString& text) void wxTextCtrl::SetInsertionPoint(long pos) { wxCHECK_RET( pos >= 0 && pos <= GetLastPosition(), - _T("insertion poitn position out of range") ); + _T("insertion point position out of range") ); if ( pos != m_curPos ) { @@ -186,6 +205,34 @@ void wxTextCtrl::SetInsertionPoint(long pos) { m_curLine = 0; m_curRow = m_curPos; + + // the current position should always be shown, scroll the window + // for this if necessary + wxCoord x = GetCaretPosition(); + + static const wxCoord MARGIN = 3; + if ( x < wxMax(0, m_ofsHorz + MARGIN) ) + { + // scroll backwards + ScrollText(x - MARGIN); + } + else + { + wxCoord width = m_rectText.width; + if ( !width ) + { + // if we are called from the ctor, m_rectText is not + // initialized yet, so do it now + UpdateTextRect(); + width = m_rectText.width; + } + + if ( x > m_ofsHorz + width - MARGIN ) + { + // scroll forward + ScrollText(x - width + MARGIN); + } + } } else // multi line { @@ -232,6 +279,26 @@ void wxTextCtrl::GetSelection(long* from, long* to) const *to = m_selEnd; } +wxString wxTextCtrl::GetSelectionText() const +{ + wxString sel; + + if ( HasSelection() ) + { + if ( IsSingleLine() ) + { + sel = wxString(m_value.c_str() + m_selStart, + m_value.c_str() + m_selEnd); + } + else + { + wxFAIL_MSG(_T("unimplemented for multi line")); + } + } + + return sel; +} + void wxTextCtrl::SetSelection(long from, long to) { if ( from == -1 || to == -1 ) @@ -255,6 +322,10 @@ void wxTextCtrl::SetSelection(long from, long to) m_selStart = from; m_selEnd = to; + wxLogTrace(_T("text"), _T("Selection range is %ld-%ld"), + m_selStart, m_selEnd); + + // FIXME: shouldn't refresh everything Refresh(); } //else: nothing to do @@ -263,12 +334,17 @@ void wxTextCtrl::SetSelection(long from, long to) void wxTextCtrl::ClearSelection() { - m_selStart = - m_selEnd = -1; + if ( HasSelection() ) + { + m_selStart = + m_selEnd = -1; + // FIXME: shouldn't refresh everything + Refresh(); + } + + // the anchor should be moved even if there was no selection previously m_selAnchor = m_curPos; - - Refresh(); } void wxTextCtrl::RemoveSelection() @@ -279,6 +355,60 @@ void wxTextCtrl::RemoveSelection() Remove(m_selStart, m_selEnd); } +bool wxTextCtrl::GetSelectedPartOfLine(long line, int *start, int *end) const +{ + if ( start ) + *start = -1; + if ( end ) + *end = -1; + + if ( !HasSelection() ) + { + // no selection at all, hence no selection in this line + return FALSE; + } + + long lineStart, colStart; + PositionToXY(m_selStart, &colStart, &lineStart); + if ( lineStart > line ) + { + // this line is entirely above the selection + return FALSE; + } + + long lineEnd, colEnd; + PositionToXY(m_selEnd, &colEnd, &lineEnd); + if ( lineEnd < line ) + { + // this line is entirely below the selection + return FALSE; + } + + if ( line == lineStart ) + { + if ( start ) + *start = colStart; + if ( end ) + *end = lineEnd == lineStart ? colEnd : GetLineLength(line); + } + else if ( line == lineEnd ) + { + if ( start ) + *start = lineEnd == lineStart ? colStart : 0; + if ( end ) + *end = colEnd; + } + else // the line is entirely inside the selection + { + if ( start ) + *start = 0; + if ( end ) + *end = GetLineLength(line); + } + + return TRUE; +} + // ---------------------------------------------------------------------------- // flags // ---------------------------------------------------------------------------- @@ -304,6 +434,7 @@ void wxTextCtrl::SetEditable(bool editable) { m_isEditable = editable; + // the appearance of the control might have changed Refresh(); } } @@ -378,8 +509,11 @@ bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const { if ( IsSingleLine() ) { + if ( pos > GetLastPosition() ) + return FALSE; + if ( x ) - *x = m_curPos; + *x = pos; if ( y ) *y = 0; @@ -431,6 +565,11 @@ long wxTextCtrl::GetWordStart() const if ( m_curPos == -1 || m_curPos == 0 ) return 0; + // it shouldn't be possible to learn where the word starts in the password + // text entry zone + if ( IsPassword() ) + return 0; + // start at the previous position const wxChar *p0 = m_value.c_str(); const wxChar *p = p0 + m_curPos - 1; @@ -455,6 +594,11 @@ long wxTextCtrl::GetWordEnd() const if ( m_curPos == -1 ) return 0; + // it shouldn't be possible to learn where the word ends in the password + // text entry zone + if ( IsPassword() ) + return GetLastPosition(); + // start at the current position const wxChar *p0 = m_value.c_str(); const wxChar *p = p0 + m_curPos; @@ -480,19 +624,41 @@ long wxTextCtrl::GetWordEnd() const void wxTextCtrl::Copy() { - wxFAIL_MSG(_T("not implemented")); +#if wxUSE_CLIPBOARD + if ( HasSelection() ) + { + wxClipboardLocker clipLock; + + wxString text = GetTextToShow(GetSelectionText()); + wxTextDataObject *data = new wxTextDataObject(text); + wxTheClipboard->SetData(data); + } +#endif // wxUSE_CLIPBOARD } void wxTextCtrl::Cut() { - wxFAIL_MSG(_T("not implemented")); + if ( HasSelection() ) + { + Copy(); + + RemoveSelection(); + } } void wxTextCtrl::Paste() { - wxFAIL_MSG(_T("not implemented")); -} +#if wxUSE_CLIPBOARD + wxClipboardLocker clipLock; + wxTextDataObject data; + if ( wxTheClipboard->IsSupported(data.GetFormat()) + && wxTheClipboard->GetData(data) ) + { + WriteText(data.GetText()); + } +#endif // wxUSE_CLIPBOARD +} void wxTextCtrl::Undo() { @@ -522,7 +688,7 @@ bool wxTextCtrl::CanRedo() const wxSize wxTextCtrl::DoGetBestClientSize() const { wxCoord w, h; - GetTextExtent(GetLineText(0), &w, &h); + GetTextExtent(GetTextToShow(GetLineText(0)), &w, &h); int wChar = GetCharWidth(), hChar = GetCharHeight(); @@ -532,27 +698,383 @@ wxSize wxTextCtrl::DoGetBestClientSize() const if ( h < hChar ) h = hChar; - w += 2*wChar; - h += hChar / 2; + wxRect rectText; + rectText.width = w; + rectText.height = h; + wxRect rectTotal = GetRenderer()->GetTextTotalArea(this, rectText); + return wxSize(rectTotal.width, rectTotal.height); +} - return wxSize(w, h); +void wxTextCtrl::UpdateTextRect() +{ + m_rectText = GetRenderer()-> + GetTextClientArea(this, + wxRect(wxPoint(0, 0), GetClientSize())); +} + +void wxTextCtrl::OnSize(wxSizeEvent& event) +{ + UpdateTextRect(); + + event.Skip(); +} + +wxCoord wxTextCtrl::GetTextWidth(const wxString& text) const +{ + wxCoord w; + GetTextExtent(GetTextToShow(text), &w, NULL); + return w; +} + +bool wxTextCtrl::HitTest(const wxPoint& pos, long *colOut, long *rowOut) const +{ + // is the point in the text area or to the right or below it? + bool inside = TRUE; + + int x, y; + wxPoint pt = GetClientAreaOrigin(); + pt += m_rectText.GetPosition(); + CalcUnscrolledPosition(pos.x - pt.x, pos.y - pt.y, &x, &y); + + // row calculation is simple as we assume that all lines have the same + // height + int row = y / GetCharHeight(); + int rowMax = GetNumberOfLines() - 1; + if ( row > rowMax ) + { + // clicking below the text is the same as clicking on the last line + row = rowMax; + + inside = FALSE; + } + else if ( row < 0 ) + { + row = 0; + + inside = FALSE; + } + + // if the line is empty, the column can only be the first one + wxString line = GetTextToShow(GetLineText(row)); + int col; + wxTextCtrl *self = wxConstCast(this, wxTextCtrl); + wxClientDC dc(self); + dc.SetFont(GetFont()); + self->DoPrepareDC(dc); + + wxCoord width; + dc.GetTextExtent(line, &width, NULL); + if ( x >= width ) + { + // clicking beyond the end of line is equivalent to clicking at + // the end of it + col = line.length(); + + inside = FALSE; + } + else if ( x < 0 ) + { + col = 0; + + inside = FALSE; + } + else // we're inside the line + { + // now calculate the column: first, approximate it with fixed-width + // value and then calculate the correct value iteratively: note that + // we use the first character of the line instead of (average) + // GetCharWidth(): it is common to have lines of dashes, for example, + // and this should give us much better approximation in such case + dc.GetTextExtent(line[0], &width, NULL); + col = x / width; + + // matchDir is -1 if we must move left, +1 to move right and 0 when + // we're exactly on the character we need + int matchDir = 0; + for ( ;; ) + { + // check that we didn't go beyond the line boundary + if ( col < 0 ) + { + col = 0; + break; + } + if ( (size_t)col > line.length() ) + { + col = line.length(); + break; + } + + wxString strBefore(line, (size_t)col); + dc.GetTextExtent(strBefore, &width, NULL); + if ( width >= x ) + { + if ( matchDir == 1 ) + { + // we were going to the right and, finally, moved beyond + // the original position: so the current is the next after + // the correct one + col--; + + break; + } + else if ( matchDir == 0 ) + { + // we just started iterating, now we know that we should + // move to the left + matchDir = -1; + } + //else: we are still to the right of the target, continue + } + else // width < x + { + // same logic as above ... + if ( matchDir == -1 ) + { + // ... except that we don't need to back track + break; + } + else if ( matchDir == 0 ) + { + // go to the right + matchDir = 1; + } + } + + // this is not supposed to happen + wxASSERT_MSG( matchDir, _T("logic error in wxTextCtrl::HitTest") ); + + if ( matchDir == 1 ) + col++; + else + col--; + } + } + + if ( colOut ) + *colOut = col; + if ( rowOut ) + *rowOut = row; + + return inside; +} + +// ---------------------------------------------------------------------------- +// scrolling +// ---------------------------------------------------------------------------- + +void wxTextCtrl::ScrollText(wxCoord x) +{ + // never scroll beyond the left border + wxCoord ofsHorz = x > 0 ? x : 0; + if ( ofsHorz != m_ofsHorz ) + { + // NB1: to scroll to the right, offset must be negative, hence the + // order of operands + int dx = m_ofsHorz - ofsHorz; + + // NB2: ScrollWindow() calls Refresh() which results in a call to + // DoDraw(), so we must update m_ofsHorz before calling it + m_ofsHorz = ofsHorz; + + ScrollWindow(dx, 0, &m_rectText); + } +} + +void wxTextCtrl::CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const +{ + wxScrollHelper::CalcUnscrolledPosition(x + m_ofsHorz, y, xx, yy); +} + +void wxTextCtrl::DoPrepareDC(wxDC& dc) +{ + // adjust the DC origin if the text is shifted + if ( m_ofsHorz ) + { + wxPoint pt = dc.GetDeviceOrigin(); + dc.SetDeviceOrigin(pt.x - m_ofsHorz, pt.y); + } +} + +// ---------------------------------------------------------------------------- +// refresh +// ---------------------------------------------------------------------------- + +void wxTextCtrl::RefreshLine(long line, wxCoord from, wxCoord to) +{ + wxCoord h = GetCharHeight(); + wxRect rect; + wxPoint pt = GetClientAreaOrigin() + m_rectText.GetPosition(); + rect.x = pt.x + from; + rect.y = pt.y + line*h; + rect.width = to - from + 1; + rect.height = h; + + wxLogTrace(_T("text"), _T("Refreshing (%d, %d)-(%d, %d)"), + rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); + + Refresh(TRUE, &rect); } // ---------------------------------------------------------------------------- // drawing // ---------------------------------------------------------------------------- +wxString wxTextCtrl::GetTextToShow(const wxString& text) const +{ + wxString textShown; + if ( IsPassword() ) + textShown = wxString(_T('*'), text.length()); + else + textShown = text; + + return textShown; +} + +void wxTextCtrl::DrawTextLine(wxDC& dc, const wxRect& rect, + const wxString& text, + long selStart, long selEnd) +{ + if ( selStart == -1 ) + { + // just draw it as is + dc.DrawText(text, rect.x, rect.y); + } + else // we have selection + { + wxCoord width, + x = rect.x; + + // draw the part before selection + wxString s(text, (size_t)selStart); + if ( !s.empty() ) + { + dc.DrawText(s, x, rect.y); + + dc.GetTextExtent(s, &width, NULL); + x += width; + } + + // draw the selection itself + s = wxString(text.c_str() + selStart, text.c_str() + selEnd); + if ( !s.empty() ) + { + wxColour colFg = dc.GetTextForeground(); + dc.SetTextForeground(wxTHEME_COLOUR(HIGHLIGHT_TEXT)); + dc.SetTextBackground(wxTHEME_COLOUR(HIGHLIGHT)); + dc.SetBackgroundMode(wxSOLID); + + dc.DrawText(s, x, rect.y); + dc.GetTextExtent(s, &width, NULL); + x += width; + + dc.SetBackgroundMode(wxTRANSPARENT); + dc.SetTextForeground(colFg); + } + + // draw the final part + s = text.c_str() + selEnd; + if ( !s.empty() ) + { + dc.DrawText(s, x, rect.y); + } + } +} + +// TODO: don't redraw the parts of line which are not visible because they're +// outside the window (because of horz scrolling) void wxTextCtrl::DoDraw(wxControlRenderer *renderer) { - if ( IsSingleLine() ) + wxCaretSuspend cs(this); + + wxDC& dc = renderer->GetDC(); + dc.SetFont(GetFont()); + dc.SetTextForeground(GetForegroundColour()); + DoPrepareDC(dc); + + // calculate the lines which must be redrawn + wxRegion rgnUpdate = GetUpdateRegion(); + wxRect rectTextArea = m_rectText; + wxPoint pt = GetClientAreaOrigin(); + rectTextArea.x += pt.x; + rectTextArea.y += pt.y; + rgnUpdate.Intersect(rectTextArea); + wxRect rectUpdate = rgnUpdate.GetBox(); + + pt = rectUpdate.GetPosition(); + long colStart, lineStart; + (void)HitTest(pt, &colStart, &lineStart); + + long colEnd, lineEnd; + pt.x += rectUpdate.width; + pt.y += rectUpdate.height; + (void)HitTest(pt, &colEnd, &lineEnd); + + wxLogTrace(_T("text"), _T("Redrawing positions (%ld, %ld)-(%ld, %ld)"), + colStart, lineStart, colEnd, lineEnd); + + // prepare for drawing + wxRect rectText; + rectText.x = m_rectText.x; + rectText.width = m_rectText.width; + rectText.height = GetCharHeight(); + rectText.y = m_rectText.y + lineStart*rectText.height; + + wxString text; + int selStart, selEnd; + + // draw the part of the first line + GetSelectedPartOfLine(lineStart, &selStart, &selEnd); + wxString textLine = GetLineText(lineStart); + text = textLine.c_str() + colStart; + if ( lineEnd == lineStart ) { - // just redraw everything - renderer->DrawTextLine(m_value, (int)m_selStart, (int)m_selEnd); + text.Truncate(colEnd - colStart + 1); } - else + + rectText.x += GetTextWidth(textLine.Left(colStart)); + rectText.width = GetTextWidth(text); + DrawTextLine(dc, rectText, GetTextToShow(text), selStart, selEnd); + rectText.y += rectText.height; + + wxLogTrace(_T("text"), _T("Start line: positions %ld-%ld redrawn."), + colStart, + lineEnd == lineStart ? colEnd : GetLineLength(lineStart)); + + // all intermediate lines must be redrawn completely + rectText.x = m_rectText.x; + rectText.width = m_rectText.width; + for ( long line = lineStart + 1; line < lineEnd; line++ ) { - // TODO + GetSelectedPartOfLine(line, &selStart, &selEnd); + + DrawTextLine(dc, rectText, GetTextToShow(GetLineText(line)), + selStart, selEnd); + rectText.y += rectText.height; + + wxLogTrace(_T("text"), _T("Middle line %ld entirely redrawn."), line); } + + // and draw the part of the last line if it hadn't been drawn yet + if ( lineEnd != lineStart ) + { + GetSelectedPartOfLine(lineEnd, &selStart, &selEnd); + text = GetLineText(lineEnd).Left(colEnd); + + rectText.y += rectText.height; + DrawTextLine(dc, rectText, GetTextToShow(text), + selStart, selEnd); + + wxLogTrace(_T("text"), _T("End line: positions 0-%ld redrawn."), + colEnd); + } +} + +wxCoord wxTextCtrl::GetCaretPosition() const +{ + wxString textBeforeCaret(GetLineText(m_curLine), (size_t)m_curRow); + + return GetTextWidth(textBeforeCaret); } void wxTextCtrl::ShowCaret(bool show) @@ -562,16 +1084,9 @@ void wxTextCtrl::ShowCaret(bool show) { caret->Show(show); - if ( caret->IsVisible() ) - { - // position it correctly - wxString textBeforeCaret(m_value, (size_t)m_curPos); - wxCoord x; - GetTextExtent(textBeforeCaret, &x, NULL); - - // FIXME: use renderer - caret->Move(x + 3, 3); - } + // position it correctly + caret->Move(m_rectText.x + GetCaretPosition() - m_ofsHorz, + m_rectText.y + m_curLine*GetCharHeight()); } } @@ -635,14 +1150,15 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig, { if ( !strArg.empty() ) { - // replace the selection with the new text - RemoveSelection(); - WriteText(strArg); textChanged = TRUE; } } + else if ( action == wxACTION_TEXT_SEL_WORD ) + { + SetSelection(GetWordStart(), GetWordEnd()); + } else if ( action == wxACTION_TEXT_ANCHOR_SEL ) { newPos = numArg; @@ -651,6 +1167,18 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig, { SetSelection(m_selAnchor, numArg); } + else if ( action == wxACTION_TEXT_COPY ) + { + Copy(); + } + else if ( action == wxACTION_TEXT_CUT ) + { + Cut(); + } + else if ( action == wxACTION_TEXT_PASTE ) + { + Paste(); + } else { return wxControl::PerformAction(action, numArg, strArg); @@ -719,7 +1247,7 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) if ( !event.HasModifiers() ) { int keycode = event.GetKeyCode(); - if ( keycode != WXK_DELETE && keycode != WXK_BACK ) + if ( keycode < 255 && keycode != WXK_DELETE && keycode != WXK_BACK ) { PerformAction(wxACTION_TEXT_INSERT, -1, (wxChar)keycode); @@ -745,105 +1273,8 @@ wxStdTextCtrlInputHandler::wxStdTextCtrlInputHandler(wxInputHandler *inphand) long wxStdTextCtrlInputHandler::HitTest(const wxTextCtrl *text, const wxPoint& pos) { - int x, y; - text->CalcUnscrolledPosition(pos.x, pos.y, &x, &y); - - // row calculation is simple as we assume that all lines have the same - // height - int row = y / text->GetCharHeight(); - int rowMax = text->GetNumberOfLines() - 1; - if ( row > rowMax ) - { - // clicking below the text is the same as clicking on the last line - row = rowMax; - } - - // if the line is empty, the column can only be the first one - wxString line = text->GetLineText(row); - int col; - wxClientDC dc(wxConstCast(text, wxTextCtrl)); - dc.SetFont(text->GetFont()); - - wxCoord width; - dc.GetTextExtent(line, &width, NULL); - if ( x >= width ) - { - // clicking beyond the end of line is equivalent to clicking at - // the end of it - col = line.length(); - } - else // we're inside the line - { - // now calculate the column: first, approximate it with fixed-width - // value and then calculate the correct value iteratively: note that - // we use the first character of the line instead of (average) - // GetCharWidth(): it is common to have lines of dashes, for example, - // and this should give us much better approximation in such case - dc.GetTextExtent(line[0], &width, NULL); - col = x / width; - - // matchDir is -1 if we must move left, +1 to move right and 0 when - // we're exactly on the character we need - int matchDir = 0; - for ( ;; ) - { - // check that we didn't go beyond the line boundary - if ( col < 0 ) - { - col = 0; - break; - } - if ( col > line.length() ) - { - col = line.length(); - break; - } - - wxString strBefore(line, (size_t)col); - dc.GetTextExtent(strBefore, &width, NULL); - if ( width >= x ) - { - if ( matchDir == 1 ) - { - // we were going to the right and, finally, moved beyond - // the original position: so the current is the next after - // the correct one - col--; - - break; - } - else if ( matchDir == 0 ) - { - // we just started iterating, now we know that we should - // move to the left - matchDir = -1; - } - //else: we are still to the right of the target, continue - } - else // width < x - { - // same logic as above ... - if ( matchDir == -1 ) - { - // ... except that we don't need to back track - break; - } - else if ( matchDir == 0 ) - { - // go to the right - matchDir = 1; - } - } - - // this is not supposed to happen - wxASSERT_MSG( matchDir, _T("logic error in wxTextCtrl::HitTest") ); - - if ( matchDir == 1 ) - col++; - else - col--; - } - } + long col, row; + (void)text->HitTest(pos, &col, &row); return text->XYToPosition(col, row); } @@ -899,6 +1330,24 @@ bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control, // reset the action as it could be already set to one of the // prefixes action = wxACTION_NONE; + + if ( ctrlDown ) + { + switch ( keycode ) + { + case 'C': + action = wxACTION_TEXT_COPY; + break; + + case 'V': + action = wxACTION_TEXT_PASTE; + break; + + case 'X': + action = wxACTION_TEXT_CUT; + break; + } + } } if ( action != wxACTION_NONE ) @@ -933,7 +1382,8 @@ bool wxStdTextCtrlInputHandler::HandleMouse(wxControl *control, } else if ( event.LeftDClick() ) { - // TODO: select the word the cursor is on + // select the word the cursor is on + control->PerformAction(wxACTION_TEXT_SEL_WORD); } else if ( event.LeftUp() ) { diff --git a/src/univ/themes/gtk.cpp b/src/univ/themes/gtk.cpp index 34d7747977..52b0348053 100644 --- a/src/univ/themes/gtk.cpp +++ b/src/univ/themes/gtk.cpp @@ -72,12 +72,6 @@ public: int alignment = wxALIGN_LEFT | wxALIGN_TOP, int indexAccel = -1, wxRect *rectBounds = NULL); - virtual void DrawTextLine(wxDC& dc, - const wxString& text, - const wxRect &rect, - int selStart = -1, - int selEnd = -1, - int flags = 0); virtual void DrawBorder(wxDC& dc, wxBorder border, const wxRect& rect, @@ -159,6 +153,13 @@ public: virtual wxCoord GetCheckItemMargin() const { return 2; } + virtual wxRect GetTextTotalArea(const wxTextCtrl *text, + const wxRect& rect) + { wxRect rectTotal = rect; rectTotal.Inflate(10); return rectTotal; } + virtual wxRect GetTextClientArea(const wxTextCtrl *text, + const wxRect& rect) + { wxRect rectText = rect; rectText.Inflate(-10); return rectText; } + // helpers for "wxBitmap wxColourScheme::Get()" void DrawCheckBitmap(wxDC& dc, const wxRect& rect); void DrawUncheckBitmap(wxDC& dc, const wxRect& rect, bool isPressed); @@ -680,8 +681,11 @@ void wxGTKRenderer::DrawBorder(wxDC& dc, switch ( border ) { case wxBORDER_SUNKEN: - DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); - DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey); + for ( int width = 0; width < 10; width++ ) + { + DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); + DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey); + } break; case wxBORDER_STATIC: @@ -689,7 +693,8 @@ void wxGTKRenderer::DrawBorder(wxDC& dc, break; case wxBORDER_RAISED: - DrawRaisedBorder(dc, &rect); + for ( int width = 0; width < 10; width++ ) + DrawRaisedBorder(dc, &rect); break; case wxBORDER_DOUBLE: @@ -722,7 +727,7 @@ wxRect wxGTKRenderer::GetBorderDimensions(wxBorder border) const { case wxBORDER_RAISED: case wxBORDER_SUNKEN: - width = 2; + width = 20; break; case wxBORDER_SIMPLE: @@ -913,59 +918,6 @@ void wxGTKRenderer::DrawButtonLabel(wxDC& dc, dc.DrawLabel(label, image, rect, alignment, indexAccel, rectBounds); } -void wxGTKRenderer::DrawTextLine(wxDC& dc, - const wxString& text, - const wxRect &rect, - int selStart, - int selEnd, - int flags) -{ - if ( selStart == -1 ) - { - // just draw it as is - dc.DrawText(text, rect.x, rect.y); - } - else // we have selection - { - wxCoord width, - x = rect.x; - - // draw the part before selection - wxString s(text, (size_t)selStart); - if ( !s.empty() ) - { - dc.DrawText(s, x, rect.y); - - dc.GetTextExtent(s, &width, NULL); - x += width; - } - - // draw the selection itself - s = wxString(text.c_str() + selStart, text.c_str() + selEnd); - if ( !s.empty() ) - { - wxColour colFg = dc.GetTextForeground(); - dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT)); - dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT)); - dc.SetBackgroundMode(wxSOLID); - - dc.DrawText(s, x, rect.y); - dc.GetTextExtent(s, &width, NULL); - x += width; - - dc.SetBackgroundMode(wxTRANSPARENT); - dc.SetTextForeground(colFg); - } - - // draw the final part - s = text.c_str() + selEnd; - if ( !s.empty() ) - { - dc.DrawText(s, x, rect.y); - } - } -} - void wxGTKRenderer::DrawItem(wxDC& dc, const wxString& label, const wxRect& rect, @@ -1077,7 +1029,9 @@ void wxGTKRenderer::DrawRadioBitmap(wxDC& dc, wxCoord yMid = (y + yBottom) / 2; - + // this looks ugly when the background colour of the control is not the + // same ours - radiobox is not transparent as it should be +#if 0 // first fill the middle: as FloodFill() is not implemented on all // platforms, this is the only thing to do wxColour colBg = flags & wxCONTROL_CURRENT @@ -1086,6 +1040,7 @@ void wxGTKRenderer::DrawRadioBitmap(wxDC& dc, dc.SetBrush(wxBrush(colBg, wxSOLID)); dc.SetPen(*wxTRANSPARENT_PEN); dc.DrawRectangle(rect); +#endif // 0 // then draw the upper half dc.SetPen(flags & wxCONTROL_CHECKED ? m_penDarkGrey : m_penHighlight); @@ -1277,7 +1232,10 @@ void wxGTKRenderer::DrawRadioButton(wxDC& dc, bitmap.Create(rect.width, rect.height); wxMemoryDC dc; dc.SelectObject(bitmap); + dc.SetBackground(*wxLIGHT_GREY_BRUSH); + dc.Clear(); DrawRadioBitmap(dc, rect, flags); + bitmap.SetMask(new wxMask(bitmap, *wxLIGHT_GREY)); } DoDrawCheckOrRadioBitmap(dc, label, bitmap, rectTotal, diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index b6dfdea898..61fa2cd563 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -89,12 +89,6 @@ public: int alignment = wxALIGN_LEFT | wxALIGN_TOP, int indexAccel = -1, wxRect *rectBounds = NULL); - virtual void DrawTextLine(wxDC& dc, - const wxString& text, - const wxRect &rect, - int selStart = -1, - int selEnd = -1, - int flags = 0); virtual void DrawBorder(wxDC& dc, wxBorder border, const wxRect& rect, @@ -174,6 +168,13 @@ public: virtual wxCoord GetCheckItemMargin() const { return 0; } + virtual wxRect GetTextTotalArea(const wxTextCtrl *text, + const wxRect& rect) + { return rect; } + virtual wxRect GetTextClientArea(const wxTextCtrl *text, + const wxRect& rect) + { return rect; } + protected: // common part of DrawLabel() and DrawItem() void DrawFocusRect(wxDC& dc, const wxRect& rect); @@ -1393,16 +1394,6 @@ void wxWin32Renderer::DrawButtonLabel(wxDC& dc, } } -void wxWin32Renderer::DrawTextLine(wxDC& dc, - const wxString& text, - const wxRect &rect, - int selStart, - int selEnd, - int flags) -{ - dc.DrawText(text, rect.x + 2, rect.y + 1); -} - // ---------------------------------------------------------------------------- // (check)listbox items // ---------------------------------------------------------------------------- diff --git a/src/univ/winuniv.cpp b/src/univ/winuniv.cpp index 132ec1f86a..95a70c77d2 100644 --- a/src/univ/winuniv.cpp +++ b/src/univ/winuniv.cpp @@ -164,7 +164,10 @@ void wxWindow::OnErase(wxEraseEvent& event) rectCorner.SetRight(size.x - rectBorder.width); rectCorner.SetBottom(size.y - rectBorder.height); - m_renderer->DrawScrollCorner(*event.GetDC(), rectCorner); + if ( GetUpdateRegion().Contains(rectCorner) ) + { + m_renderer->DrawScrollCorner(*event.GetDC(), rectCorner); + } } } @@ -201,11 +204,7 @@ void wxWindow::OnPaint(wxPaintEvent& event) bool wxWindow::DoDrawBackground(wxDC& dc) { - wxRect rect; - wxSize size = GetSize(); // full, not client only - rect.width = size.x; - rect.height = size.y; - + wxRect rect = GetUpdateRegion().GetBox(); if ( GetBackgroundBitmap().Ok() ) { // get the bitmap and the flags @@ -246,9 +245,15 @@ void wxWindow::DoDrawBorder(wxDC& dc) rect.height -= scrollbar->GetSize().y; } - // draw outline - m_renderer->DrawBorder(dc, GetBorder(), - rect, GetStateFlags(), &rect); + // draw outline unless the update region is enitrely inside it in which + // case we don't need to do it +#if 0 // doesn't seem to work, why? + if ( wxRegion(rect).Contains(GetUpdateRegion().GetBox()) != wxInRegion ) +#endif + { + m_renderer->DrawBorder(dc, GetBorder(), + rect, GetStateFlags(), &rect); + } } void wxWindow::DoDraw(wxControlRenderer *renderer) @@ -371,11 +376,17 @@ void wxWindow::DoGetClientSize(int *width, int *height) const wxSize size = GetSize(); + bool inside = m_renderer->AreScrollbarsInsideBorder(); + if ( width ) { + // in any case, take account of the scrollbar if ( m_scrollbarVert ) *width -= size.x - m_scrollbarVert->GetPosition().x; - else + + // if we don't have scrollbar or if it is outside the border (and not + // blended into it), take account of the right border as well + if ( !m_scrollbarVert || !inside ) *width -= rectBorder.width; *width -= rectBorder.x; @@ -385,7 +396,8 @@ void wxWindow::DoGetClientSize(int *width, int *height) const { if ( m_scrollbarHorz ) *height -= size.y - m_scrollbarHorz->GetPosition().y; - else + + if ( !m_scrollbarHorz || !inside ) *height -= rectBorder.height; *height -= rectBorder.y; @@ -402,15 +414,16 @@ void wxWindow::DoSetClientSize(int width, int height) // and the scrollbars (as they may be offset into the border, use the // scrollbar position, not size - this supposes that PositionScrollbars() // had been called before) + bool inside = m_renderer->AreScrollbarsInsideBorder(); wxSize size = GetSize(); if ( m_scrollbarVert ) width += size.x - m_scrollbarVert->GetPosition().x; - else + if ( !m_scrollbarVert || !inside ) width += rectBorder.width; if ( m_scrollbarHorz ) height += size.y - m_scrollbarHorz->GetPosition().y; - else + if ( !m_scrollbarHorz || !inside ) height += rectBorder.height; wxWindowNative::DoSetClientSize(width, height); @@ -551,8 +564,6 @@ int wxWindow::GetScrollRange(int orient) const void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) { - wxASSERT_MSG( !rect, _T("scrolling only part of window not implemented") ); - if ( !dx && !dy ) { // nothing to do @@ -561,27 +572,30 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) // calculate the part of the window which we can just redraw in the new // location - wxSize sizeTotal = GetClientSize(); + wxSize sizeTotal = rect ? rect->GetSize() : GetClientSize(); - wxLogTrace(_T("scroll"), _T("window is %dx%d, scroll by %d, %d"), + wxLogTrace(_T("scroll"), _T("rect is %dx%d, scroll by %d, %d"), sizeTotal.x, sizeTotal.y, dx, dy); - wxPoint ptSource, ptDest, ptOrigin; - ptSource = - ptDest = - ptOrigin = GetClientAreaOrigin(); + wxPoint ptSource, ptDest; + if ( rect ) + ptDest = rect->GetPosition(); wxSize size; - size.x = sizeTotal.x - abs(dx) - 1; - size.y = sizeTotal.y - abs(dy) - 1; + size.x = sizeTotal.x - abs(dx); + size.y = sizeTotal.y - abs(dy); if ( size.x <= 0 || size.y <= 0 ) { // just redraw everything as nothing of the displayed image will stay wxLogTrace(_T("scroll"), _T("refreshing everything")); - Refresh(); + Refresh(TRUE, rect); } else // move the part which doesn't change to the new location { + wxPoint ptOrigin = GetClientAreaOrigin(); + if ( rect ) + ptOrigin += rect->GetPosition(); + // note that when we scroll the canvas in some direction we move the // block which doesn't need to be refreshed in the opposite direction @@ -612,7 +626,12 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) wxBitmap bmp(size.x, size.y); wxMemoryDC dcMem; dcMem.SelectObject(bmp); - dcMem.Blit(wxPoint(0, 0), size, &dc, ptSource); + + dcMem.Blit(wxPoint(0, 0), size, &dc, ptSource +#if defined(__WXGTK__) && !defined(__WX_DC_BLIT_FIXED__) + + ptOrigin +#endif // broken wxGTK wxDC::Blit + ); dc.Blit(ptDest, size, &dcMem, wxPoint(0, 0)); wxLogTrace(_T("scroll"), @@ -647,7 +666,8 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) rect.height = sizeTotal.y; wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"), - rect.x, rect.y, rect.GetRight(), rect.GetBottom()); + rect.x, rect.y, + rect.GetRight() + 1, rect.GetBottom() + 1); Refresh(TRUE /* erase bkgnd */, &rect); } @@ -669,7 +689,8 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect) rect.width = sizeTotal.x; wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"), - rect.x, rect.y, rect.GetRight(), rect.GetBottom()); + rect.x, rect.y, + rect.GetRight() + 1, rect.GetBottom() + 1); Refresh(TRUE /* erase bkgnd */, &rect); }