]> git.saurik.com Git - wxWidgets.git/blobdiff - src/richtext/richtextctrl.cpp
Removed all outdated makefile.dos and their *.msc include.
[wxWidgets.git] / src / richtext / richtextctrl.cpp
index 8e8ec6227247268dbb7e41f90e33e0c02e9de72d..c312aed560f796ba1f02dcdc067ad60e08dd6cf7 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        richtext/richeditctrl.cpp
+// Name:        src/richtext/richeditctrl.cpp
 // Purpose:     A rich edit control
 // Author:      Julian Smart
 // Modified by:
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-  #pragma hdrstop
+    #pragma hdrstop
 #endif
 
-#ifndef WX_PRECOMP
-  #include "wx/wx.h"
-#endif
+#if wxUSE_RICHTEXT
 
-#include "wx/image.h"
+#include "wx/richtext/richtextctrl.h"
 
-#if wxUSE_RICHTEXT
+#ifndef WX_PRECOMP
+    #include "wx/settings.h"
+    #include "wx/menu.h"
+    #include "wx/intl.h"
+    #include "wx/log.h"
+    #include "wx/stopwatch.h"
+#endif
 
 #include "wx/textfile.h"
 #include "wx/ffile.h"
-#include "wx/settings.h"
 #include "wx/filename.h"
 #include "wx/dcbuffer.h"
-
-#include "wx/richtext/richtextctrl.h"
 #include "wx/arrimpl.cpp"
 
+// DLL options compatibility check:
+#include "wx/app.h"
+WX_CHECK_BUILD_OPTIONS("wxRichTextCtrl")
+
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_ITEM_SELECTED)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_ITEM_DESELECTED)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_LEFT_CLICK)
@@ -57,6 +62,7 @@ BEGIN_EVENT_TABLE( wxRichTextCtrl, wxScrolledWindow )
     EVT_PAINT(wxRichTextCtrl::OnPaint)
     EVT_ERASE_BACKGROUND(wxRichTextCtrl::OnEraseBackground)
     EVT_IDLE(wxRichTextCtrl::OnIdle)
+    EVT_SCROLLWIN(wxRichTextCtrl::OnScroll)
     EVT_LEFT_DOWN(wxRichTextCtrl::OnLeftClick)
     EVT_MOTION(wxRichTextCtrl::OnMoveMouse)
     EVT_LEFT_UP(wxRichTextCtrl::OnLeftUp)
@@ -103,17 +109,17 @@ wxRichTextCtrl::wxRichTextCtrl()
     Init();
 }
 
-wxRichTextCtrl::wxRichTextCtrl( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
+wxRichTextCtrl::wxRichTextCtrl( wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, long style)
 #if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
     : wxScrollHelper(this)
 #endif
 {
     Init();
-    Create(parent, id, pos, size, style);
+    Create(parent, id, value, pos, size, style);
 }
 
 /// Creation
-bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
+bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, long style)
 {
 #if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
     if (!wxTextCtrlBase::Create(parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE
@@ -151,13 +157,11 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos
     // Create a buffer
     RecreateBuffer(size);
 
-    wxCaret* caret = new wxCaret(this, wxRICHTEXT_DEFAULT_CARET_WIDTH, 16);
-    SetCaret(caret);
-    caret->Show();
-    PositionCaret();
-
     SetCursor(wxCursor(wxCURSOR_IBEAM));
 
+    if (!value.IsEmpty())
+        SetValue(value);
+
     return true;
 }
 
@@ -191,14 +195,14 @@ void wxRichTextCtrl::Freeze()
 }
 
 /// Call Thaw to refresh
-void wxRichTextCtrl::Thaw(bool refresh)
+void wxRichTextCtrl::Thaw()
 {
     m_freezeCount --;
 
-    if (m_freezeCount == 0 && refresh)
+    if (m_freezeCount == 0)
     {
         SetupScrollbars();
-        Refresh();
+        Refresh(false);
     }
 }
 
@@ -211,10 +215,12 @@ void wxRichTextCtrl::Clear()
     m_caretAtLineStart = false;
     m_selectionRange.SetRange(-2, -2);
 
+    SetScrollbars(0, 0, 0, 0, 0, 0);
+
     if (m_freezeCount == 0)
     {
         SetupScrollbars();
-        Refresh();
+        Refresh(false);
     }
     SendUpdateEvent();
 }
@@ -222,31 +228,41 @@ void wxRichTextCtrl::Clear()
 /// Painting
 void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
 {
-    wxBufferedPaintDC dc(this, m_bufferBitmap);
+    if (GetCaret())
+        GetCaret()->Hide();
 
-    PrepareDC(dc);
+    {
+        wxBufferedPaintDC dc(this, m_bufferBitmap);
+        //wxLogDebug(wxT("OnPaint"));
 
-    if (m_freezeCount > 0)
-        return;
+        PrepareDC(dc);
 
-    dc.SetFont(GetFont());
+        if (m_freezeCount > 0)
+            return;
 
-    // Paint the background
-    PaintBackground(dc);
+        dc.SetFont(GetFont());
 
-    wxRegion dirtyRegion = GetUpdateRegion();
+        // Paint the background
+        PaintBackground(dc);
 
-    wxRect drawingArea(GetLogicalPoint(wxPoint(0, 0)), GetClientSize());
-    wxRect availableSpace(GetClientSize());
-    if (GetBuffer().GetDirty())
-    {
-        GetBuffer().Layout(dc, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT);
-        GetBuffer().SetDirty(false);
-        SetupScrollbars();
-        PositionCaret();
+        wxRegion dirtyRegion = GetUpdateRegion();
+
+        wxRect drawingArea(GetLogicalPoint(wxPoint(0, 0)), GetClientSize());
+        wxRect availableSpace(GetClientSize());
+        if (GetBuffer().GetDirty())
+        {
+            GetBuffer().Layout(dc, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT);
+            GetBuffer().SetDirty(false);
+            SetupScrollbars();
+        }
+
+        GetBuffer().Draw(dc, GetBuffer().GetRange(), GetSelectionRange(), drawingArea, 0 /* descent */, 0 /* flags */);
     }
 
-    GetBuffer().Draw(dc, GetBuffer().GetRange(), GetSelectionRange(), drawingArea, 0 /* descent */, 0 /* flags */);
+    if (GetCaret())
+        GetCaret()->Show();
+
+    PositionCaret();
 }
 
 // Empty implementation, to prevent flicker
@@ -256,14 +272,21 @@ void wxRichTextCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
 
 void wxRichTextCtrl::OnSetFocus(wxFocusEvent& WXUNUSED(event))
 {
+    wxCaret* caret = new wxCaret(this, wxRICHTEXT_DEFAULT_CARET_WIDTH, 16);
+    SetCaret(caret);
+    caret->Show();
+    PositionCaret();
+
     if (!IsFrozen())
-        Refresh();
+        Refresh(false);
 }
 
 void wxRichTextCtrl::OnKillFocus(wxFocusEvent& WXUNUSED(event))
 {
+    SetCaret(NULL);
+
     if (!IsFrozen())
-        Refresh();
+        Refresh(false);
 }
 
 /// Left-click
@@ -376,7 +399,7 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event)
             SetDefaultStyleToCursorStyle();
 
             if (extendSel)
-                Refresh();
+                Refresh(false);
         }
     }
 }
@@ -418,13 +441,21 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
         event.GetKeyCode() == WXK_HOME ||
         event.GetKeyCode() == WXK_PAGEUP ||
         event.GetKeyCode() == WXK_PAGEDOWN ||
-        event.GetKeyCode() == WXK_PRIOR ||
-        event.GetKeyCode() == WXK_NEXT ||
         event.GetKeyCode() == WXK_END)
     {
-        Navigate(event.GetKeyCode(), flags);
+        KeyboardNavigate(event.GetKeyCode(), flags);
+        return;
     }
-    else if (event.GetKeyCode() == WXK_RETURN)
+
+    // all the other keys modify the controls contents which shouldn't be
+    // possible if we're read-only
+    if ( !IsEditable() )
+    {
+        event.Skip();
+        return;
+    }
+
+    if (event.GetKeyCode() == WXK_RETURN)
     {
         BeginBatchUndo(_("Insert Text"));
 
@@ -443,6 +474,8 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
 
         EndBatchUndo();
         SetDefaultStyleToCursorStyle();
+
+        ScrollIntoView(m_caretPosition, WXK_RIGHT);
     }
     else if (event.GetKeyCode() == WXK_BACK)
     {
@@ -472,6 +505,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
             SetDefaultStyleToCursorStyle();
         }
 
+        ScrollIntoView(m_caretPosition, WXK_LEFT);
     }
     else if (event.GetKeyCode() == WXK_DELETE)
     {
@@ -513,11 +547,8 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
         EndBatchUndo();
 
         SetDefaultStyleToCursorStyle();
+        ScrollIntoView(m_caretPosition, WXK_RIGHT);
     }
-#if 0
-    else
-        event.Skip();
-#endif
 }
 
 /// Delete content if there is a selection, e.g. when pressing a key.
@@ -571,10 +602,9 @@ Adding Shift does the above but starts/extends selection.
 
  */
 
-bool wxRichTextCtrl::Navigate(int keyCode, int flags)
+bool wxRichTextCtrl::KeyboardNavigate(int keyCode, int flags)
 {
     bool success = false;
-    Freeze();
 
     if (keyCode == WXK_RIGHT)
     {
@@ -604,11 +634,11 @@ bool wxRichTextCtrl::Navigate(int keyCode, int flags)
         else
             success = MoveDown(1, flags);
     }
-    else if (keyCode == WXK_PAGEUP || keyCode == WXK_PRIOR)
+    else if (keyCode == WXK_PAGEUP)
     {
         success = PageUp(1, flags);
     }
-    else if (keyCode == WXK_PAGEDOWN || keyCode == WXK_NEXT)
+    else if (keyCode == WXK_PAGEDOWN)
     {
         success = PageDown(1, flags);
     }
@@ -633,9 +663,6 @@ bool wxRichTextCtrl::Navigate(int keyCode, int flags)
         SetDefaultStyleToCursorStyle();
     }
 
-    // Only refresh if something changed
-    Thaw(success);
-
     return success;
 }
 
@@ -687,16 +714,16 @@ bool wxRichTextCtrl::ScrollIntoView(long position, int keyCode)
     int ppuX, ppuY;
     GetScrollPixelsPerUnit(& ppuX, & ppuY);
 
-    int startX, startY;
-    GetViewStart(& startX, & startY);
-    startX = 0;
-    startY = startY * ppuY;
+    int startXUnits, startYUnits;
+    GetViewStart(& startXUnits, & startYUnits);
+    int startY = startYUnits * ppuY;
 
-    int sx, sy;
+    int sx = 0, sy = 0;
     GetVirtualSize(& sx, & sy);
-    sx = 0;
+    int sxUnits = 0;
+    int syUnits = 0;
     if (ppuY != 0)
-        sy = sy/ppuY;
+        syUnits = sy/ppuY;
 
     wxRect rect = line->GetRect();
 
@@ -705,42 +732,72 @@ bool wxRichTextCtrl::ScrollIntoView(long position, int keyCode)
     wxSize clientSize = GetClientSize();
 
     // Going down
-    if (keyCode == WXK_DOWN || keyCode == WXK_RIGHT || keyCode == WXK_END || keyCode == WXK_NEXT || keyCode == WXK_PAGEDOWN)
+    if (keyCode == WXK_DOWN || keyCode == WXK_RIGHT || keyCode == WXK_END || keyCode == WXK_PAGEDOWN)
     {
         if ((rect.y + rect.height) > (clientSize.y + startY))
         {
             // Make it scroll so this item is at the bottom
             // of the window
             int y = rect.y - (clientSize.y - rect.height);
-            SetScrollbars(ppuX, ppuY, sx, sy, 0, (int) (0.5 + y/ppuY));
+            int yUnits = (int) (0.5 + ((float) y)/(float) ppuY);
+
+            // If we're still off the screen, scroll another line down
+            if ((rect.y + rect.height) > (clientSize.y + (yUnits*ppuY)))
+                yUnits ++;
+
+            if (startYUnits != yUnits)
+            {
+                SetScrollbars(ppuX, ppuY, sxUnits, syUnits, 0, yUnits);
+                scrolled = true;
+            }
         }
         else if (rect.y < startY)
         {
             // Make it scroll so this item is at the top
             // of the window
             int y = rect.y ;
-            SetScrollbars(ppuX, ppuY, sx, sy, 0, (int) (0.5 + y/ppuY));
+            int yUnits = (int) (0.5 + ((float) y)/(float) ppuY);
+
+            if (startYUnits != yUnits)
+            {
+                SetScrollbars(ppuX, ppuY, sxUnits, syUnits, 0, yUnits);
+                scrolled = true;
+            }
         }
-        scrolled = true;
     }
     // Going up
-    else if (keyCode == WXK_UP || keyCode == WXK_LEFT || keyCode == WXK_HOME || keyCode == WXK_PRIOR || keyCode == WXK_PAGEUP)
+    else if (keyCode == WXK_UP || keyCode == WXK_LEFT || keyCode == WXK_HOME || keyCode == WXK_PAGEUP )
     {
         if (rect.y < startY)
         {
             // Make it scroll so this item is at the top
             // of the window
             int y = rect.y ;
-            SetScrollbars(ppuX, ppuY, sx, sy, 0, (int) (0.5 + y/ppuY));
+            int yUnits = (int) (0.5 + ((float) y)/(float) ppuY);
+
+            if (startYUnits != yUnits)
+            {
+                SetScrollbars(ppuX, ppuY, sxUnits, syUnits, 0, yUnits);
+                scrolled = true;
+            }
         }
         else if ((rect.y + rect.height) > (clientSize.y + startY))
         {
             // Make it scroll so this item is at the bottom
             // of the window
             int y = rect.y - (clientSize.y - rect.height);
-            SetScrollbars(ppuX, ppuY, sx, sy, 0, (int) (0.5 + y/ppuY));
+            int yUnits = (int) (0.5 + ((float) y)/(float) ppuY);
+
+            // If we're still off the screen, scroll another line down
+            if ((rect.y + rect.height) > (clientSize.y + (yUnits*ppuY)))
+                yUnits ++;
+
+            if (startYUnits != yUnits)
+            {
+                SetScrollbars(ppuX, ppuY, sxUnits, syUnits, 0, yUnits);
+                scrolled = true;
+            }
         }
-        scrolled = true;
     }
     PositionCaret();
 
@@ -763,7 +820,7 @@ bool wxRichTextCtrl::IsPositionVisible(long pos) const
     startX = 0;
     startY = startY * ppuY;
 
-    int sx, sy;
+    int sx = 0, sy = 0;
     GetVirtualSize(& sx, & sy);
     sx = 0;
     if (ppuY != 0)
@@ -904,8 +961,8 @@ bool wxRichTextCtrl::MoveRight(int noPositions, int flags)
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh(); // TODO: optimize so that if we didn't change the selection, we don't refresh
+        if (extendSel)
+            Refresh(false);
         return true;
     }
     else
@@ -933,8 +990,8 @@ bool wxRichTextCtrl::MoveLeft(int noPositions, int flags)
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh();
+        if (extendSel)
+            Refresh(false);
         return true;
     }
     else
@@ -950,6 +1007,9 @@ bool wxRichTextCtrl::MoveUp(int noLines, int flags)
 /// Move up
 bool wxRichTextCtrl::MoveDown(int noLines, int flags)
 {
+    if (!GetCaret())
+        return false;
+
     long lineNumber = GetBuffer().GetVisibleLineNumber(m_caretPosition, true, m_caretAtLineStart);
     wxPoint pt = GetCaret()->GetPosition();
     long newLine = lineNumber + noLines;
@@ -1013,19 +1073,20 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags)
 
         long newSelEnd = newPos;
 
-        if (!ExtendSelection(m_caretPosition, newSelEnd, flags))
+        bool extendSel = ExtendSelection(m_caretPosition, newSelEnd, flags);
+        if (!extendSel)
             SelectNone();
 
         SetCaretPosition(newPos, caretLineStart);
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh();
+        if (extendSel)
+            Refresh(false);
         return true;
     }
-    else
-        return false;
+
+    return false;
 }
 
 /// Move to the end of the paragraph
@@ -1035,15 +1096,16 @@ bool wxRichTextCtrl::MoveToParagraphEnd(int flags)
     if (para)
     {
         long newPos = para->GetRange().GetEnd() - 1;
-        if (!ExtendSelection(m_caretPosition, newPos, flags))
+        bool extendSel = ExtendSelection(m_caretPosition, newPos, flags);
+        if (!extendSel)
             SelectNone();
 
         SetCaretPosition(newPos);
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh();
+        if (extendSel)
+            Refresh(false);
         return true;
     }
 
@@ -1057,15 +1119,16 @@ bool wxRichTextCtrl::MoveToParagraphStart(int flags)
     if (para)
     {
         long newPos = para->GetRange().GetStart() - 1;
-        if (!ExtendSelection(m_caretPosition, newPos, flags))
+        bool extendSel = ExtendSelection(m_caretPosition, newPos, flags);
+        if (!extendSel)
             SelectNone();
 
         SetCaretPosition(newPos);
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh();
+        if (extendSel)
+            Refresh(false);
         return true;
     }
 
@@ -1081,15 +1144,16 @@ bool wxRichTextCtrl::MoveToLineEnd(int flags)
     {
         wxRichTextRange lineRange = line->GetAbsoluteRange();
         long newPos = lineRange.GetEnd();
-        if (!ExtendSelection(m_caretPosition, newPos, flags))
+        bool extendSel = ExtendSelection(m_caretPosition, newPos, flags);
+        if (!extendSel)
             SelectNone();
 
         SetCaretPosition(newPos);
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh();
+        if (extendSel)
+            Refresh(false);
         return true;
     }
 
@@ -1105,7 +1169,8 @@ bool wxRichTextCtrl::MoveToLineStart(int flags)
         wxRichTextRange lineRange = line->GetAbsoluteRange();
         long newPos = lineRange.GetStart()-1;
 
-        if (!ExtendSelection(m_caretPosition, newPos, flags))
+        bool extendSel = ExtendSelection(m_caretPosition, newPos, flags);
+        if (!extendSel)
             SelectNone();
 
         wxRichTextParagraph* para = GetBuffer().GetParagraphForLine(line);
@@ -1114,8 +1179,8 @@ bool wxRichTextCtrl::MoveToLineStart(int flags)
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh();
+        if (extendSel)
+            Refresh(false);
         return true;
     }
 
@@ -1127,15 +1192,16 @@ bool wxRichTextCtrl::MoveHome(int flags)
 {
     if (m_caretPosition != -1)
     {
-        if (!ExtendSelection(m_caretPosition, -1, flags))
+        bool extendSel = ExtendSelection(m_caretPosition, -1, flags);
+        if (!extendSel)
             SelectNone();
 
         SetCaretPosition(-1);
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh();
+        if (extendSel)
+            Refresh(false);
         return true;
     }
     else
@@ -1149,15 +1215,16 @@ bool wxRichTextCtrl::MoveEnd(int flags)
 
     if (m_caretPosition != endPos)
     {
-        if (!ExtendSelection(m_caretPosition, endPos, flags))
+        bool extendSel = ExtendSelection(m_caretPosition, endPos, flags);
+        if (!extendSel)
             SelectNone();
 
         SetCaretPosition(endPos);
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh();
+        if (extendSel)
+            Refresh(false);
         return true;
     }
     else
@@ -1189,15 +1256,16 @@ bool wxRichTextCtrl::PageDown(int noPages, int flags)
             {
                 wxRichTextParagraph* para = GetBuffer().GetParagraphForLine(newLine);
 
-                if (!ExtendSelection(m_caretPosition, pos, flags))
+                bool extendSel = ExtendSelection(m_caretPosition, pos, flags);
+                if (!extendSel)
                     SelectNone();
 
                 SetCaretPosition(pos, para->GetRange().GetStart() != lineRange.GetStart());
                 PositionCaret();
                 SetDefaultStyleToCursorStyle();
 
-                if (!IsFrozen())
-                    Refresh();
+                if (extendSel)
+                    Refresh(false);
                 return true;
             }
         }
@@ -1287,15 +1355,16 @@ bool wxRichTextCtrl::WordLeft(int WXUNUSED(n), int flags)
     {
         wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(pos, true);
 
-        if (!ExtendSelection(m_caretPosition, pos, flags))
+        bool extendSel = ExtendSelection(m_caretPosition, pos, flags);
+        if (!extendSel)
             SelectNone();
 
         SetCaretPosition(pos, para->GetRange().GetStart() != pos);
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh();
+        if (extendSel)
+            Refresh(false);
         return true;
     }
 
@@ -1310,15 +1379,16 @@ bool wxRichTextCtrl::WordRight(int WXUNUSED(n), int flags)
     {
         wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(pos, true);
 
-        if (!ExtendSelection(m_caretPosition, pos, flags))
+        bool extendSel = ExtendSelection(m_caretPosition, pos, flags);
+        if (!extendSel)
             SelectNone();
 
         SetCaretPosition(pos, para->GetRange().GetStart() != pos);
         PositionCaret();
         SetDefaultStyleToCursorStyle();
 
-        if (!IsFrozen())
-            Refresh();
+        if (extendSel)
+            Refresh(false);
         return true;
     }
 
@@ -1334,7 +1404,7 @@ void wxRichTextCtrl::OnSize(wxSizeEvent& event)
         m_fullLayoutRequired = true;
         m_fullLayoutTime = wxGetLocalTimeMillis();
         m_fullLayoutSavedPosition = GetFirstVisiblePosition();
-        Layout(true /* onlyVisibleRect */);
+        LayoutContent(true /* onlyVisibleRect */);
     }
     else
         GetBuffer().Invalidate(wxRICHTEXT_ALL);
@@ -1356,11 +1426,18 @@ void wxRichTextCtrl::OnIdle(wxIdleEvent& event)
         m_fullLayoutTime = 0;
         GetBuffer().Invalidate(wxRICHTEXT_ALL);
         ShowPosition(m_fullLayoutSavedPosition);
-        Refresh();
+        Refresh(false);
     }
     event.Skip();
 }
 
+/// Scrolling
+void wxRichTextCtrl::OnScroll(wxScrollWinEvent& event)
+{
+    // Not used
+    event.Skip();
+}
+
 /// Set up scrollbars, e.g. after a resize
 void wxRichTextCtrl::SetupScrollbars(bool atTop)
 {
@@ -1375,19 +1452,20 @@ void wxRichTextCtrl::SetupScrollbars(bool atTop)
 
     // TODO: reimplement scrolling so we scroll by line, not by fixed number
     // of pixels. See e.g. wxVScrolledWindow for ideas.
-    int pixelsPerUnit = 5; // 10;
+    int pixelsPerUnit = 5;
     wxSize clientSize = GetClientSize();
 
     int maxHeight = GetBuffer().GetCachedSize().y;
 
-    int unitsY = maxHeight/pixelsPerUnit;
+    // Round up so we have at least maxHeight pixels
+    int unitsY = (int) (((float)maxHeight/(float)pixelsPerUnit) + 0.5);
 
     int startX = 0, startY = 0;
     if (!atTop)
         GetViewStart(& startX, & startY);
 
     int maxPositionX = 0; // wxMax(sz.x - clientSize.x, 0);
-    int maxPositionY = (wxMax(maxHeight - clientSize.y, 0))/pixelsPerUnit;
+    int maxPositionY = (int) ((((float)(wxMax((unitsY*pixelsPerUnit) - clientSize.y, 0)))/((float)pixelsPerUnit)) + 0.5);
 
     // Move to previous scroll position if
     // possible
@@ -1443,10 +1521,10 @@ bool wxRichTextCtrl::LoadFile(const wxString& filename, int type)
 
     DiscardEdits();
     SetInsertionPoint(0);
-    Layout();
+    LayoutContent();
     PositionCaret();
     SetupScrollbars(true);
-    Refresh();
+    Refresh(false);
     SendUpdateEvent();
 
     if (success)
@@ -1514,7 +1592,8 @@ void wxRichTextCtrl::SelectAll()
 /// Select none
 void wxRichTextCtrl::SelectNone()
 {
-    SetSelection(-2, -2);
+    if (!(GetSelectionRange() == wxRichTextRange(-2, -2)))
+        SetSelection(-2, -2);
     m_selectionAnchor = -2;
 }
 
@@ -1527,17 +1606,20 @@ wxString wxRichTextCtrl::GetStringSelection() const
 }
 
 // do the window-specific processing after processing the update event
+#if !wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
 void wxRichTextCtrl::DoUpdateWindowUI(wxUpdateUIEvent& event)
 {
-    if ( event.GetSetEnabled() )
-        Enable(event.GetEnabled());
+    // call inherited
+    wxWindowBase::DoUpdateWindowUI(event);
 
+    // update text
     if ( event.GetSetText() )
     {
         if ( event.GetText() != GetValue() )
             SetValue(event.GetText());
     }
 }
+#endif // !wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
 
 // ----------------------------------------------------------------------------
 // hit testing
@@ -1567,15 +1649,25 @@ wxRichTextCtrl::HitTest(const wxPoint& pt,
     wxClientDC dc((wxRichTextCtrl*) this);
     ((wxRichTextCtrl*)this)->PrepareDC(dc);
 
-    int hit = ((wxRichTextCtrl*)this)->GetBuffer().HitTest(dc, pt, *pos);
-    if (hit == wxRICHTEXT_HITTEST_BEFORE)
-        return wxTE_HT_BEFORE;
-    else if (hit == wxRICHTEXT_HITTEST_AFTER)
-        return wxTE_HT_BEYOND;
-    else if (hit == wxRICHTEXT_HITTEST_ON)
-        return wxTE_HT_ON_TEXT;
-    else
-        return wxTE_HT_UNKNOWN;
+    // Buffer uses logical position (relative to start of buffer)
+    // so convert
+    wxPoint pt2 = GetLogicalPoint(pt);
+
+    int hit = ((wxRichTextCtrl*)this)->GetBuffer().HitTest(dc, pt2, *pos);
+
+    switch ( hit )
+    {
+        case wxRICHTEXT_HITTEST_BEFORE:
+            return wxTE_HT_BEFORE;
+
+        case wxRICHTEXT_HITTEST_AFTER:
+            return wxTE_HT_BEYOND;
+
+        case wxRICHTEXT_HITTEST_ON:
+            return wxTE_HT_ON_TEXT;
+    }
+
+    return wxTE_HT_UNKNOWN;
 }
 
 // ----------------------------------------------------------------------------
@@ -1645,8 +1737,8 @@ bool wxRichTextCtrl::WriteImage(const wxImage& image, int bitmapType)
     wxImage image2 = image;
     if (imageBlock.MakeImageBlock(image2, bitmapType))
         return WriteImage(imageBlock);
-    else
-        return false;
+
+    return false;
 }
 
 bool wxRichTextCtrl::WriteImage(const wxString& filename, int bitmapType)
@@ -1656,8 +1748,8 @@ bool wxRichTextCtrl::WriteImage(const wxString& filename, int bitmapType)
     wxImage image;
     if (imageBlock.MakeImageBlock(filename, bitmapType, image, false))
         return WriteImage(imageBlock);
-    else
-        return false;
+
+    return false;
 }
 
 bool wxRichTextCtrl::WriteImage(const wxRichTextImageBlock& imageBlock)
@@ -1674,9 +1766,8 @@ bool wxRichTextCtrl::WriteImage(const wxBitmap& bitmap, int bitmapType)
         wxImage image = bitmap.ConvertToImage();
         if (image.Ok() && imageBlock.MakeImageBlock(image, bitmapType))
             return WriteImage(imageBlock);
-        else
-            return false;
     }
+
     return false;
 }
 
@@ -1708,8 +1799,8 @@ void wxRichTextCtrl::Cut()
         GetBuffer().CopyToClipboard(range);
 
         DeleteSelectedContent();
-        Layout();
-        Refresh();
+        LayoutContent();
+        Refresh(false);
     }
 }
 
@@ -1832,8 +1923,7 @@ void wxRichTextCtrl::DoSetSelection(long from, long to, bool WXUNUSED(scrollCare
 {
     m_selectionAnchor = from;
     m_selectionRange.SetRange(from, to);
-    if (!IsFrozen())
-        Refresh();
+    Refresh(false);
     PositionCaret();
 }
 
@@ -1861,9 +1951,9 @@ void wxRichTextCtrl::Remove(long from, long to)
         from,                           // New caret position
         this);
 
-    Layout();
+    LayoutContent();
     if (!IsFrozen())
-        Refresh();
+        Refresh(false);
 }
 
 bool wxRichTextCtrl::IsModified() const
@@ -1952,10 +2042,10 @@ bool wxRichTextCtrl::CanRedo() const
 }
 
 // ----------------------------------------------------------------------------
-// implemenation details
+// implementation details
 // ----------------------------------------------------------------------------
 
-void wxRichTextCtrl::Command(wxCommandEvent & event)
+void wxRichTextCtrl::Command(wxCommandEvent& event)
 {
     SetValue(event.GetString());
     GetEventHandler()->ProcessEvent(event);
@@ -2108,6 +2198,11 @@ bool wxRichTextCtrl::SetStyle(long start, long end, const wxTextAttrEx& style)
     return GetBuffer().SetStyle(wxRichTextRange(start, end), style);
 }
 
+bool wxRichTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
+{
+    return GetBuffer().SetStyle(wxRichTextRange(start, end), wxTextAttrEx(style));
+}
+
 bool wxRichTextCtrl::SetStyle(const wxRichTextRange& range, const wxRichTextAttr& style)
 {
     return GetBuffer().SetStyle(range, style);
@@ -2118,11 +2213,33 @@ bool wxRichTextCtrl::SetDefaultStyle(const wxTextAttrEx& style)
     return GetBuffer().SetDefaultStyle(style);
 }
 
+bool wxRichTextCtrl::SetDefaultStyle(const wxTextAttr& style)
+{
+    return GetBuffer().SetDefaultStyle(wxTextAttrEx(style));
+}
+
 const wxTextAttrEx& wxRichTextCtrl::GetDefaultStyleEx() const
 {
     return GetBuffer().GetDefaultStyle();
 }
 
+const wxTextAttr& wxRichTextCtrl::GetDefaultStyle() const
+{
+    return GetBuffer().GetDefaultStyle();
+}
+
+bool wxRichTextCtrl::GetStyle(long position, wxTextAttr& style) const
+{
+    wxTextAttrEx attr;
+    if (GetBuffer().GetStyle(position, attr))
+    {
+        style = attr;
+        return true;
+    }
+    else
+        return false;
+}
+
 bool wxRichTextCtrl::GetStyle(long position, wxTextAttrEx& style) const
 {
     return GetBuffer().GetStyle(position, style);
@@ -2171,14 +2288,21 @@ wxPoint wxRichTextCtrl::GetLogicalPoint(const wxPoint& ptPhysical) const
 /// Position the caret
 void wxRichTextCtrl::PositionCaret()
 {
+    if (!GetCaret())
+        return;
+
+    //wxLogDebug(wxT("PositionCaret"));
+
     wxRect caretRect;
     if (GetCaretPositionForIndex(GetCaretPosition(), caretRect))
     {
         wxPoint originalPt = caretRect.GetPosition();
         wxPoint pt = GetPhysicalPoint(originalPt);
-
-        GetCaret()->Move(pt);
-        GetCaret()->SetSize(caretRect.GetSize());
+        if (GetCaret()->GetPosition() != pt)
+        {
+            GetCaret()->Move(pt);
+            GetCaret()->SetSize(caretRect.GetSize());
+        }
     }
 }
 
@@ -2198,8 +2322,8 @@ bool wxRichTextCtrl::GetCaretPositionForIndex(long position, wxRect& rect)
         rect = wxRect(pt, wxSize(wxRICHTEXT_DEFAULT_CARET_WIDTH, height));
         return true;
     }
-    else
-        return false;
+
+    return false;
 }
 
 /// Gets the line for the visible caret position. If the caret is
@@ -2228,7 +2352,7 @@ wxRichTextLine* wxRichTextCtrl::GetVisibleLineForCaretPosition(long caretPositio
 bool wxRichTextCtrl::MoveCaret(long pos, bool showAtLineStart)
 {
     if (GetBuffer().GetDirty())
-        Layout();
+        LayoutContent();
 
     if (pos <= GetBuffer().GetRange().GetEnd())
     {
@@ -2244,7 +2368,7 @@ bool wxRichTextCtrl::MoveCaret(long pos, bool showAtLineStart)
 
 /// Layout the buffer: which we must do before certain operations, such as
 /// setting the caret position.
-bool wxRichTextCtrl::Layout(bool onlyVisibleRect)
+bool wxRichTextCtrl::LayoutContent(bool onlyVisibleRect)
 {
     if (GetBuffer().GetDirty() || onlyVisibleRect)
     {
@@ -2260,17 +2384,17 @@ bool wxRichTextCtrl::Layout(bool onlyVisibleRect)
             flags |= wxRICHTEXT_LAYOUT_SPECIFIED_RECT;
             availableSpace.SetPosition(GetLogicalPoint(wxPoint(0, 0)));
         }
-        
+
         wxClientDC dc(this);
         dc.SetFont(GetFont());
-        
+
         PrepareDC(dc);
-        
+
         GetBuffer().Defragment();
         GetBuffer().UpdateRanges();     // If items were deleted, ranges need recalculation
         GetBuffer().Layout(dc, availableSpace, flags);
         GetBuffer().SetDirty(false);
-        
+
         if (!IsFrozen())
             SetupScrollbars();
     }
@@ -2449,8 +2573,8 @@ bool wxRichTextCtrl::SetDefaultStyleToCursorStyle()
         SetDefaultStyle(attr);
         return true;
     }
-    else
-        return false;
+
+    return false;
 }
 
 /// Returns the first visible position in the current view
@@ -2465,4 +2589,3 @@ long wxRichTextCtrl::GetFirstVisiblePosition() const
 
 #endif
     // wxUSE_RICHTEXT
-