]> git.saurik.com Git - wxWidgets.git/blobdiff - user/wxLayout/wxllist.cpp
Countless (some half-finished) optimisations.
[wxWidgets.git] / user / wxLayout / wxllist.cpp
index 5357810c50b822d588a8099b01e3bc7e958ad392..6e972e3ebceea49aabf39ccb4fafa856057130c9 100644 (file)
 #endif
 
 //#include "Mpch.h"
+
+
+#include "wx/wxprec.h"
+#ifdef __BORLANDC__
+#  pragma hdrstop
+#endif
+
 #ifdef M_PREFIX
 #   include "gui/wxllist.h"
 #else
 
 /// Use this character to estimate a cursor size when none is available.
 #define WXLO_CURSORCHAR   "E"
-
-/// Helper function, allows me to compare to wxPoints
+/** @name Helper functions */
+//@{
+/// allows me to compare to wxPoints
 bool operator ==(wxPoint const &p1, wxPoint const &p2)
 {
    return p1.x == p2.x && p1.y == p2.y;
 }
 
-/// Helper function, allows me to compare to wxPoints
+/// allows me to compare to wxPoints
 bool operator !=(wxPoint const &p1, wxPoint const &p2)
 {
    return p1.x != p2.x || p1.y != p2.y;
 }
 
+/// allows me to compare to wxPoints
+bool operator <=(wxPoint const &p1, wxPoint const &p2)
+{
+   return p1.y < p2.y || (p1.y == p2.y && p1.x <= p2.x);
+}
+
+/// grows a wxRect so that it includes the given point
+
+static
+void GrowRect(wxRect &r, const wxPoint & p)
+{
+   if(r.x > p.x)
+      r.x = p.x;
+   else if(r.x + r.width < p.x)
+      r.width = p.x - r.x;
+   
+   if(r.y > p.y)
+      r.y = p.y;
+   else if(r.y + r.height < p.y)
+      r.height = p.y - r.y;
+}
+
+/// returns true if the point is in the rectangle
+static
+bool Contains(const wxRect &r, const wxPoint &p)
+{
+   return r.x <= p.x && r.y <= p.y && (r.x+r.width) >= p.x && (r.y + r.height) >= p.y;
+}
+//@}
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 
@@ -186,7 +223,8 @@ wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap *icon)
 void
 wxLayoutObjectIcon::Draw(wxDC &dc, wxPoint const &coords)
 {
-   dc.DrawBitmap(*m_Icon, coords.x, coords.y-m_Icon->GetHeight());
+   dc.DrawBitmap(*m_Icon, coords.x, coords.y-m_Icon->GetHeight(),
+                 (m_Icon->GetMask() == NULL) ? FALSE : TRUE);
 }
 
 void
@@ -212,7 +250,7 @@ wxLayoutObjectIcon::GetSize(CoordType *top, CoordType *bottom) const
 
 wxLayoutObjectCmd::wxLayoutObjectCmd(int size, int family, int style, int
                                      weight, bool underline,
-                                     wxColour const *fg, wxColour const *bg)
+                                     wxColour &fg, wxColour &bg)
    
 {
    m_font = new wxFont(size,family,style,weight,underline);
@@ -248,12 +286,12 @@ wxLayoutObjectCmd::GetStyle(wxLayoutStyleInfo *si) const
    si->underline = m_font->GetUnderlined();
    si->weight = m_font->GetWeight();
 
-   si->fg_red = m_ColourFG->Red();
-   si->fg_green = m_ColourFG->Green();
-   si->fg_blue = m_ColourFG->Blue();
-   si->bg_red = m_ColourBG->Red();
-   si->bg_green = m_ColourBG->Green();
-   si->bg_blue = m_ColourBG->Blue();
+   si->fg_red = m_ColourFG.Red();
+   si->fg_green = m_ColourFG.Green();
+   si->fg_blue = m_ColourFG.Blue();
+   si->bg_red = m_ColourBG.Red();
+   si->bg_green = m_ColourBG.Green();
+   si->bg_blue = m_ColourBG.Blue();
 }
 
 void
@@ -261,10 +299,8 @@ wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint const & /* coords */)
 {
    wxASSERT(m_font);
    dc.SetFont(*m_font);
-   if(m_ColourFG)
-      dc.SetTextForeground(*m_ColourFG);
-   if(m_ColourBG)
-      dc.SetTextBackground(*m_ColourBG);
+   dc.SetTextForeground(m_ColourFG);
+   dc.SetTextBackground(m_ColourBG);
 }
 
 void
@@ -281,15 +317,15 @@ wxLayoutObjectCmd::Layout(wxDC &dc)
 
    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-wxLayoutLine::wxLayoutLine(wxLayoutLine *prev)
+wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
 {
    m_LineNumber = 0;
-   m_Height = 0;
+   m_Width = m_Height = 0;
    m_Length = 0;
    m_Dirty = true;
    m_Previous = prev;
    m_Next = NULL;
-   RecalculatePosition();
+   RecalculatePosition(llist);
    if(m_Previous)
    {
       m_LineNumber = m_Previous->GetLineNumber()+1;
@@ -301,7 +337,7 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev)
    {
       m_Next->m_Previous = this;
       m_Next->MoveLines(+1);
-      m_Next->RecalculatePositions(1);
+      m_Next->RecalculatePositions(1,llist);
    }
 }
 
@@ -311,33 +347,32 @@ wxLayoutLine::~wxLayoutLine()
 }
 
 wxPoint
-wxLayoutLine::RecalculatePosition(void)
+wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
 {
    if(m_Previous)
       m_Position = m_Previous->GetPosition() +
          wxPoint(0,m_Previous->GetHeight());
    else
       m_Position = wxPoint(0,0);
+   llist->SetUpdateRect(m_Position);
    return m_Position;
 }
 
 void
-wxLayoutLine::RecalculatePositions(int recurse)
+wxLayoutLine::RecalculatePositions(int recurse, wxLayoutList *llist)
 {
    wxASSERT(recurse >= 0);
    wxPoint pos = m_Position;
    CoordType height = m_Height;
    
 //   WXLO_TRACE("RecalculatePositions()");
-   RecalculatePosition();
+   RecalculatePosition(llist);
    if(m_Next)
    {
       if(recurse > 0)
-      {
-         if(m_Next) m_Next->RecalculatePositions(--recurse);
-      }
+         m_Next->RecalculatePositions(--recurse, llist);
       else if(pos != m_Position || m_Height != height)
-         if(m_Next) m_Next->RecalculatePositions();         
+         m_Next->RecalculatePositions(0, llist);         
    }
 }
 
@@ -346,28 +381,36 @@ wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const
 {
    wxASSERT(xpos >= 0);
    wxASSERT(offset);
-   wxLayoutObjectList::iterator i;
+   wxLayoutObjectList::iterator
+      i,
+      found = NULLIT;
    CoordType x = 0, len;
    
-
+   /* We search through the objects. As we don't like returning the
+      object that the cursor is behind, we just remember such an
+      object in "found" so we can return it if there is really no
+      further object following it. */
    for(i = m_ObjectList.begin(); i != NULLIT; i++)
    {
       len = (**i).GetLength();
       if( x <= xpos && xpos <= x + len )
       {
          *offset = xpos-x;
-         return i;
+         if(xpos == x + len) // is there another object behind?
+            found = i;
+         else  // we are really inside this object
+            return i;
       }
       x += (**i).GetLength();
    }
-   return NULLIT;
+   return found;  // ==NULL if really none found
 }
 
 wxLayoutObjectList::iterator
 wxLayoutLine::FindObjectScreen(wxDC &dc, CoordType xpos, CoordType *cxpos) const
 {
    wxASSERT(cxpos);
-   wxASSERT(xpos);
+   wxASSERT(cxpos);
    wxLayoutObjectList::iterator i;
    CoordType x = 0, cx = 0, width;
    
@@ -550,9 +593,9 @@ wxLayoutLine::DeleteWord(CoordType xpos)
          str = str.substr(offset,str.Length()-offset);
          // Find out how many positions we need to delete:
          // 1. eat leading space
-         while(isspace(str[count])) count++;
+         while(isspace(str.c_str()[count])) count++;
          // 2. eat the word itself:
-         while(isalnum(str[count])) count++;
+         while(isalnum(str.c_str()[count])) count++;
          // now delete it:
          wxASSERT(count+offset <= (size_t) (**i).GetLength());
          ((wxLayoutObjectText *)*i)->GetText().erase(offset,count);
@@ -564,14 +607,14 @@ wxLayoutLine::DeleteWord(CoordType xpos)
 }
 
 wxLayoutLine *
-wxLayoutLine::DeleteLine(bool update)
+wxLayoutLine::DeleteLine(bool update, wxLayoutList *llist)
 {
    if(m_Next) m_Next->m_Previous = m_Previous;
    if(m_Previous) m_Previous->m_Next = m_Next;
    if(update)
    {
       m_Next->MoveLines(-1);
-      m_Next->RecalculatePositions(1);
+      m_Next->RecalculatePositions(1, llist);
    }
    wxLayoutLine *next = m_Next;
    delete this;
@@ -579,7 +622,9 @@ wxLayoutLine::DeleteLine(bool update)
 }
 
 void
-wxLayoutLine::Draw(wxDC &dc, const wxPoint & offset) const
+wxLayoutLine::Draw(wxDC &dc,
+                   wxLayoutList *llist,
+                   const wxPoint & offset) const
 {
    wxLayoutObjectList::iterator i;
    wxPoint pos = offset;
@@ -595,7 +640,9 @@ wxLayoutLine::Draw(wxDC &dc, const wxPoint & offset) const
 }
 
 void
-wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
+wxLayoutLine::Layout(wxDC &dc,
+                     wxLayoutList *llist,
+                     wxPoint *cursorPos,
                      wxPoint *cursorSize,
                      int cx) 
 {
@@ -619,6 +666,7 @@ wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
    if(cursorPos)
    {
       *cursorPos = m_Position;
+      if(cursorSize) *cursorSize = wxPoint(0,0);
    }
    
    for(i = m_ObjectList.begin(); i != NULLIT; i++)
@@ -696,26 +744,19 @@ wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
    
    // tell next line about coordinate change
    if(m_Next && objHeight != oldHeight)
-      m_Next->RecalculatePositions();
+      m_Next->RecalculatePositions(0, llist);
 
+   // We need to check whether we found a valid cursor size:
    if(cursorPos)
    {
       // this might be the case if the cursor is at the end of the
       // line or on a command object:
       if(cursorSize->y < WXLO_MINIMUM_CURSOR_WIDTH)
       {
-         if(m_BaseLine > 0)
-         {
-            cursorSize->y = m_BaseLine;
-            if(cursorSize->x < WXLO_MINIMUM_CURSOR_WIDTH) cursorSize->x = WXLO_MINIMUM_CURSOR_WIDTH;
-         }
-         else // empty line
-         {
-            CoordType width, height, descent;
-            dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
-            cursorSize->x = width;
-            cursorSize->y = height;
-         }
+         CoordType width, height, descent;
+         dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
+         cursorSize->x = width;
+         cursorSize->y = height;
       }
       if(m_BaseLine >= cursorSize->y) // the normal case anyway
          cursorPos->y += m_BaseLine-cursorSize->y;
@@ -724,13 +765,13 @@ wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
 
 
 wxLayoutLine *
-wxLayoutLine::Break(CoordType xpos)
+wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
 {
    wxASSERT(xpos >= 0);
    
    if(xpos == 0)
    { // insert an empty line before this one
-      wxLayoutLine *prev = new wxLayoutLine(m_Previous);
+      wxLayoutLine *prev = new wxLayoutLine(m_Previous, llist);
       if(m_Previous == NULL)
       {  // We were in first line, need to link in new empty line
          // before this.
@@ -740,7 +781,7 @@ wxLayoutLine::Break(CoordType xpos)
       }
       MoveLines(+1);
       if(m_Next)
-         m_Next->RecalculatePositions(1);
+         m_Next->RecalculatePositions(1, llist);
       return this;
    }
    
@@ -748,10 +789,10 @@ wxLayoutLine::Break(CoordType xpos)
    wxLOiterator i = FindObject(xpos, &offset);
    if(i == NULLIT)
       // must be at the end of the line then
-      return new wxLayoutLine(this);
+      return new wxLayoutLine(this, llist);
    // split this line:
 
-   wxLayoutLine *newLine = new wxLayoutLine(this);
+   wxLayoutLine *newLine = new wxLayoutLine(this, llist);
    // split object at i:
    if((**i).GetType() == WXLO_TYPE_TEXT && offset != 0)
    {
@@ -776,13 +817,13 @@ wxLayoutLine::Break(CoordType xpos)
       m_ObjectList.remove(i); // remove without deleting it
    }
    if(m_Next)
-      m_Next->RecalculatePositions(2);
+      m_Next->RecalculatePositions(2, llist);
    return newLine;
 }
    
 
 void
-wxLayoutLine::MergeNextLine(void)
+wxLayoutLine::MergeNextLine(wxLayoutList *llist)
 {
    wxASSERT(GetNextLine());
    wxLayoutObjectList &list = GetNextLine()->m_ObjectList;
@@ -797,7 +838,7 @@ wxLayoutLine::MergeNextLine(void)
    wxLayoutLine *oldnext = GetNextLine();
    SetNext(GetNextLine()->GetNextLine());
    delete oldnext;
-   RecalculatePositions(1);
+   RecalculatePositions(1, llist);
 }
 
 CoordType
@@ -814,7 +855,7 @@ wxLayoutLine::GetWrapPosition(CoordType column)
       {
          do
          {
-            if( isspace(((wxLayoutObjectText*)*i)->GetText()[offset]))
+            if( isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
                return column;
             else
             {
@@ -867,25 +908,30 @@ wxLayoutList::wxLayoutList()
 {
    m_DefaultSetting = NULL;
    m_FirstLine = NULL;
+   m_ColourFG = *wxBLACK;
+   m_ColourBG = *wxWHITE;
+   InvalidateUpdateRect();
    Clear();
 }
 
 wxLayoutList::~wxLayoutList()
 {
    InternalClear();
+   m_FirstLine->DeleteLine(false, this);
 }
 
 void
 wxLayoutList::Empty(void)
 {
    while(m_FirstLine)
-      m_FirstLine = m_FirstLine->DeleteLine(false);
+      m_FirstLine = m_FirstLine->DeleteLine(false, this);
 
    m_CursorPos = wxPoint(0,0);
    m_CursorScreenPos = wxPoint(0,0);
    m_CursorSize = wxPoint(0,0);
-   m_FirstLine = new wxLayoutLine(NULL); // empty first line
+   m_FirstLine = new wxLayoutLine(NULL, this); // empty first line
    m_CursorLine = m_FirstLine;
+   InvalidateUpdateRect();
 }
 
 
@@ -902,8 +948,8 @@ wxLayoutList::InternalClear(void)
 
 void
 wxLayoutList::SetFont(int family, int size, int style, int weight,
-                      int underline, wxColour const *fg,
-                      wxColour const *bg)
+                      int underline, wxColour *fg,
+                      wxColour *bg)
 {
    if(family != -1)    m_FontFamily = family;
    if(size != -1)      m_FontPtSize = size;
@@ -911,8 +957,8 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
    if(weight != -1)    m_FontWeight = weight;
    if(underline != -1) m_FontUnderline = underline != 0;
 
-   if(fg != NULL)     m_ColourFG = fg;
-   if(bg != NULL)     m_ColourBG = bg;
+   if(fg != NULL)     m_ColourFG = *fg;
+   if(bg != NULL)     m_ColourBG = *bg;
    
    Insert(
       new wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,m_FontWeight,m_FontUnderline,
@@ -924,9 +970,9 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
                       int underline, char const *fg, char const *bg)
 
 {
-   wxColour const
-      * cfg = NULL,
-      * cbg = NULL;
+   wxColour
+      *cfg = NULL,
+      *cbg = NULL;
 
    if( fg )
       cfg = wxTheColourDatabase->FindColour(fg);
@@ -938,7 +984,7 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
 
 void
 wxLayoutList::Clear(int family, int size, int style, int weight,
-                    int /* underline */, char const *fg, char const *bg)
+                    int /* underline */, wxColour *fg, wxColour *bg)
 {
    InternalClear();
    
@@ -948,11 +994,11 @@ wxLayoutList::Clear(int family, int size, int style, int weight,
    m_FontFamily = family;
    m_FontStyle = style;
    m_FontWeight = weight;
-   m_ColourFG = wxTheColourDatabase->FindColour(fg);
-   m_ColourBG = wxTheColourDatabase->FindColour(bg);
+   if(fg) m_ColourFG = *fg;
+   if(bg) m_ColourBG = *bg;
 
-   if(! m_ColourFG) m_ColourFG = wxBLACK;
-   if(! m_ColourBG) m_ColourBG = wxWHITE;
+   m_ColourFG = *wxBLACK;
+   m_ColourBG = *wxWHITE;
    
    if(m_DefaultSetting)
       delete m_DefaultSetting;
@@ -968,6 +1014,8 @@ wxLayoutList::Clear(int family, int size, int style, int weight,
 bool
 wxLayoutList::MoveCursorTo(wxPoint const &p)
 {
+   SetUpdateRect(m_CursorScreenPos);
+   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
    wxLayoutLine *line = m_FirstLine;
    while(line && line->GetLineNumber() != p.y)
       line = line->GetNextLine();
@@ -993,6 +1041,9 @@ wxLayoutList::MoveCursorTo(wxPoint const &p)
 bool
 wxLayoutList::MoveCursorVertically(int n)
 {
+   SetUpdateRect(m_CursorScreenPos);
+   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+   bool rc;
    if(n  < 0) // move up
    {
       if(m_CursorLine == m_FirstLine) return false;
@@ -1006,13 +1057,13 @@ wxLayoutList::MoveCursorVertically(int n)
       {
          m_CursorLine = m_FirstLine;
          m_CursorPos.y = 0;
-         return false;
+         rc = false;
       }
       else
       {
          if(m_CursorPos.x > m_CursorLine->GetLength())
             m_CursorPos.x = m_CursorLine->GetLength();
-         return true;
+         rc = true;
       }
    }
    else // move down
@@ -1029,20 +1080,23 @@ wxLayoutList::MoveCursorVertically(int n)
       {
          m_CursorLine = last;
          m_CursorPos.y ++;
-         return false;
+         rc = false;
       }
       else
       {
          if(m_CursorPos.x > m_CursorLine->GetLength())
             m_CursorPos.x = m_CursorLine->GetLength();
-         return true;
+         rc = true;
       }
    }
+   return rc;
 }
 
 bool
 wxLayoutList::MoveCursorHorizontally(int n)
 {
+   SetUpdateRect(m_CursorScreenPos);
+   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
    int move;
    while(n < 0)
    {
@@ -1082,6 +1136,8 @@ bool
 wxLayoutList::Insert(wxString const &text)
 {
    wxASSERT(m_CursorLine);
+   SetUpdateRect(m_CursorScreenPos);
+   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
    m_CursorLine->Insert(m_CursorPos.x, text);
    m_CursorPos.x += text.Length();
    return true;
@@ -1091,6 +1147,8 @@ bool
 wxLayoutList::Insert(wxLayoutObject *obj)
 {
    wxASSERT(m_CursorLine);
+   SetUpdateRect(m_CursorScreenPos);
+   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
    m_CursorLine->Insert(m_CursorPos.x, obj);
    m_CursorPos.x += obj->GetLength();
    return true;
@@ -1100,9 +1158,10 @@ bool
 wxLayoutList::LineBreak(void)
 {
    wxASSERT(m_CursorLine);
-
    bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0);
-   m_CursorLine = m_CursorLine->Break(m_CursorPos.x);
+   SetUpdateRect(m_CursorScreenPos);
+   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+   m_CursorLine = m_CursorLine->Break(m_CursorPos.x, this);
    if(setFirst) // we were at beginning of first line
       m_FirstLine = m_CursorLine->GetPreviousLine();
    m_CursorPos.y++;
@@ -1123,6 +1182,8 @@ wxLayoutList::WrapLine(CoordType column)
       //else:
       CoordType newpos = m_CursorPos.x - xpos - 1;
       m_CursorPos.x = xpos;
+      SetUpdateRect(m_CursorScreenPos);
+      SetUpdateRect(m_CursorScreenPos+m_CursorSize);
       LineBreak();
       Delete(1); // delete the space
       m_CursorPos.x = newpos;
@@ -1134,6 +1195,8 @@ bool
 wxLayoutList::Delete(CoordType npos)
 {
    wxASSERT(m_CursorLine);
+   SetUpdateRect(m_CursorScreenPos);
+   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
    CoordType left;
    do
    {
@@ -1159,7 +1222,7 @@ wxLayoutList::Delete(CoordType npos)
             break; // cannot
          else
          {
-            m_CursorLine->MergeNextLine();
+            m_CursorLine->MergeNextLine(this);
             left--;
          }
       }
@@ -1173,6 +1236,8 @@ wxLayoutList::DeleteLines(int n)
 {
    wxASSERT(m_CursorLine);
    wxLayoutLine *line;
+   SetUpdateRect(m_CursorScreenPos);
+   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
    while(n > 0)
    {
       if(!m_CursorLine->GetNextLine())
@@ -1183,18 +1248,18 @@ wxLayoutList::DeleteLines(int n)
       }
       //else:
       line = m_CursorLine;
-      m_CursorLine = m_CursorLine->DeleteLine(true);
+      m_CursorLine = m_CursorLine->DeleteLine(true, this);
       n--;
       if(line == m_FirstLine) m_FirstLine = m_CursorLine;
       wxASSERT(m_FirstLine);
       wxASSERT(m_CursorLine);
    }
-   m_CursorLine->RecalculatePositions(2);
+   m_CursorLine->RecalculatePositions(2, this);
    return n;
 }
 
 void
-wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) const
+wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
 {
    wxLayoutLine *line = m_FirstLine;
 
@@ -1203,7 +1268,7 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) const
    m_DefaultSetting->Layout(dc);
    while(line)
    {
-      line->RecalculatePosition(); // so we don't need to do it all the time
+      line->RecalculatePosition(this); // so we don't need to do it all the time
       // little condition to speed up redrawing:
       if(bottom != -1 && line->GetPosition().y > bottom) break;
       line = line->GetNextLine();
@@ -1211,7 +1276,21 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) const
 }
 
 void
-wxLayoutList::Layout(wxDC &dc, CoordType bottom) const
+wxLayoutList::UpdateCursorScreenPos(wxDC &dc)
+{
+   wxASSERT(m_CursorLine);
+   m_CursorLine->Layout(dc, this, (wxPoint *)&m_CursorScreenPos, (wxPoint *)&m_CursorSize, m_CursorPos.x);
+}
+
+wxPoint
+wxLayoutList::GetCursorScreenPos(wxDC &dc)
+{
+   UpdateCursorScreenPos(dc);
+   return m_CursorScreenPos;
+}
+
+void
+wxLayoutList::Layout(wxDC &dc, CoordType bottom)
 {
    wxLayoutLine *line = m_FirstLine;
 
@@ -1221,40 +1300,50 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom) const
    while(line)
    {
       if(line == m_CursorLine)
-         line->Layout(dc, (wxPoint *)&m_CursorScreenPos, (wxPoint *)&m_CursorSize, m_CursorPos.x);
+         line->Layout(dc, this, (wxPoint *)&m_CursorScreenPos, (wxPoint *)&m_CursorSize, m_CursorPos.x);
       else
-         line->Layout(dc);
+         line->Layout(dc, this);
       // little condition to speed up redrawing:
       if(bottom != -1 && line->GetPosition().y > bottom) break;
       line = line->GetNextLine();
    }
+
+///FIXME: disabled for now
+#if 0
    // can only be 0 if we are on the first line and have no next line
    wxASSERT(m_CursorSize.x != 0 || (m_CursorLine &&
                                     m_CursorLine->GetNextLine() == NULL &&
                                     m_CursorLine == m_FirstLine));
+#endif
+   SetUpdateRect(m_CursorScreenPos);
+   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
 }
 
 void
 wxLayoutList::Draw(wxDC &dc, wxPoint const &offset,
-                   CoordType top, CoordType bottom) const
+                   CoordType top, CoordType bottom)
 {
    wxLayoutLine *line = m_FirstLine;
 
    Layout(dc, bottom);
    m_DefaultSetting->Draw(dc, wxPoint(0,0));
+   wxBrush brush(m_ColourBG, wxSOLID);
+   dc.SetBrush(brush);
+   
    while(line)
    {
       // only draw if between top and bottom:
       if((top == -1 || line->GetPosition().y >= top))
-         line->Draw(dc, offset);
+         line->Draw(dc, this, offset);
       // little condition to speed up redrawing:
-      if(bottom != -1 && line->GetPosition().y > bottom) break;
+      if(bottom != -1 && line->GetPosition().y + line->GetHeight() > bottom) break;
       line = line->GetNextLine();
    }
    // can only be 0 if we are on the first line and have no next line
    wxASSERT(m_CursorSize.x != 0 || (m_CursorLine &&
                                     m_CursorLine->GetNextLine() == NULL &&
                                     m_CursorLine == m_FirstLine));
+   InvalidateUpdateRect();
 }
 
 wxLayoutObject *
@@ -1271,7 +1360,7 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos, wxPoint *cursorPos)
       p = line->GetPosition();
       if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
          break;
-      line->Layout(dc);
+      line->Layout(dc, this);
       line = line->GetNextLine();
    }
    if(line == NULL) return NULL; // not found
@@ -1291,18 +1380,19 @@ wxLayoutList::GetSize(void) const
    if(! line)
       return wxPoint(0,0);
 
-   wxPoint max(0,0);
+   wxPoint maxPoint(0,0);
    
    // find last line:
    while(line)
    {
-      if(line->GetWidth() > max.x) max.x = line->GetWidth();
+      if(line->GetWidth() > maxPoint.x)
+          maxPoint.x = line->GetWidth();
       last = line;
       line = line->GetNextLine();
    }
 
-   max.y = last->GetPosition().y + last->GetHeight();
-   return max;
+   maxPoint.y = last->GetPosition().y + last->GetHeight();
+   return maxPoint;
 }
 
 void
@@ -1325,7 +1415,6 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
    dc.SetBrush(*wxBLACK_BRUSH);
    dc.SetLogicalFunction(wxXOR);
    dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
-   dc.SetLogicalFunction(wxXOR);
    if(active)
       dc.DrawRectangle(coords.x, coords.y, m_CursorSize.x,
                        m_CursorSize.y);
@@ -1333,9 +1422,47 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
       dc.DrawLine(coords.x, coords.y+m_CursorSize.y-1,
                   coords.x+m_CursorSize.x, coords.y+m_CursorSize.y-1);
    dc.SetLogicalFunction(wxCOPY);
-   dc.SetBrush(wxNullBrush);
+   //dc.SetBrush(wxNullBrush);
+}
+
+/** Called by the objects to update the update rectangle.
+    @param p a point to include in it
+*/
+void
+wxLayoutList::SetUpdateRect(const wxPoint &p)
+{
+   if(m_UpdateRectValid)
+      GrowRect(m_UpdateRect, p);
+   else
+   {
+      m_UpdateRect.x = p.x;
+      m_UpdateRect.y = p.y;
+      m_UpdateRect.width = 4; // large enough to avoid surprises from
+      m_UpdateRect.height = 4;// wxGTK :-)
+      m_UpdateRectValid = true;
+   }
 }
 
+void
+wxLayoutList::StartSelection(void)
+{
+   wxLogDebug("Starting selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y);
+   m_Selection.m_CursorA = m_CursorPos;
+}
+
+void
+wxLayoutList::EndSelection(void)
+{
+   wxLogDebug("Ending selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y);
+   m_Selection.m_CursorB = m_CursorPos;
+}
+
+bool
+wxLayoutList::IsSelected(const wxPoint &cursor)
+{
+   return m_Selection.m_CursorA <= cursor
+      && cursor <= m_Selection.m_CursorB;
+}
 
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
@@ -1437,21 +1564,17 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom,
    float scale = ScaleDC(&psdc);
 
    psdc.GetSize(&m_PageWidth, &m_PageHeight);
-   // This sets a left/top origin of 10% and 20%:
-   m_Offset = wxPoint(m_PageWidth/10, m_PageHeight/20);
+   // This sets a left/top origin of 15% and 20%:
+   m_Offset = wxPoint((15*m_PageWidth)/100, m_PageHeight/20);
 
    // This is the length of the printable area.
-   m_PrintoutHeight = m_PageHeight - (int) (m_PageHeight * 0.1);
+   m_PrintoutHeight = m_PageHeight - (int) (m_PageHeight * 0.15);
    m_PrintoutHeight = (int)( m_PrintoutHeight / scale); // we want to use the real paper height
    
    
-   m_NumOfPages = (int)( m_llist->GetSize().y / (float)(m_PrintoutHeight) + 0.5);
+   m_NumOfPages = 1 +
+      (int)( m_llist->GetSize().y / (float)(m_PrintoutHeight));
 
-   // This is a crude hack to get it right for very small
-   // printouts. No idea why this is required, I thought +0.5 would do 
-   // the job. :-(
-   if(m_NumOfPages == 0 && m_llist->GetSize().y > 0)
-      m_NumOfPages = 1;
    *minPage = 1;
    *maxPage = m_NumOfPages;