]> git.saurik.com Git - wxWidgets.git/blobdiff - user/wxLayout/wxllist.cpp
MSW fixes for wxLayout, part II: now breaking and merging line works too.
[wxWidgets.git] / user / wxLayout / wxllist.cpp
index b39029807adac62958837e68ba1e70aa47335519..f0e15342f63cedf6ecd51dcb442677ecb501d2f6 100644 (file)
@@ -7,37 +7,45 @@
  *******************************************************************/
 
 /*
  *******************************************************************/
 
 /*
-  
+
  */
  */
+
 #ifdef __GNUG__
 #ifdef __GNUG__
-#pragma implementation "wxllist.h"
+    #pragma implementation "wxllist.h"
 #endif
 
 #endif
 
-#include "Mpch.h"
-
+#include <wx/wxprec.h>
 
 
-#include "wx/wxprec.h"
 #ifdef __BORLANDC__
 #  pragma hdrstop
 #endif
 
 #ifdef __BORLANDC__
 #  pragma hdrstop
 #endif
 
+#include "Mpch.h"
+
 #ifdef M_BASEDIR
 #   include "gui/wxllist.h"
 #ifdef M_BASEDIR
 #   include "gui/wxllist.h"
+#   include "gui/wxlparser.h"
 #   define  SHOW_SELECTIONS 1
 #else
 #   include "wxllist.h"
 #   define  SHOW_SELECTIONS 1
 #else
 #   include "wxllist.h"
+#   include "wxlparser.h"
 #   define SHOW_SELECTIONS 1
 #endif
 
 #ifndef USE_PCH
 #   define SHOW_SELECTIONS 1
 #endif
 
 #ifndef USE_PCH
-#   include   "iostream.h"
-#   include   <wx/dc.h>
-#   include   <wx/dcps.h>
-#   include   <wx/print.h>
-#   include   <wx/log.h>
+#   include <iostream.h>
+
+#   include <wx/dc.h>
+#   include <wx/dcps.h>
+#   include <wx/print.h>
+#   include <wx/log.h>
+#   include <wx/filefn.h>
 #endif
 
 #endif
 
+#ifdef WXLAYOUT_USE_CARET
+#   include <wx/caret.h>
+#endif // WXLAYOUT_USE_CARET
+
 #include <ctype.h>
 
 /// This should never really get created
 #include <ctype.h>
 
 /// This should never really get created
 
 #ifdef WXLAYOUT_DEBUG
 
 
 #ifdef WXLAYOUT_DEBUG
 
-#  define   TypewxString(t)        g_aTypewxStrings[t]
+#  define   TypeString(t)      g_aTypeStrings[t]
 #  define   WXLO_DEBUG(x)      wxLogDebug x
 
 #  define   WXLO_DEBUG(x)      wxLogDebug x
 
-   static const char *g_aTypewxStrings[] = 
-   { 
+   static const char *g_aTypeStrings[] =
+   {
       "invalid", "text", "cmd", "icon"
    };
    void
    wxLayoutObject::Debug(void)
    {
       "invalid", "text", "cmd", "icon"
    };
    void
    wxLayoutObject::Debug(void)
    {
-      WXLO_DEBUG(("%s",g_aTypewxStrings[GetType()])); 
+      WXLO_DEBUG(("%s",g_aTypeStrings[GetType()]));
    }
    }
-#else 
-#  define   TypewxString(t)        ""
-#  define   WXLO_DEBUG(x)      
+#else
+#  define   TypeString(t)        ""
+#  define   WXLO_DEBUG(x)
 #endif
 
 #endif
 
+// FIXME under MSW, this constant is needed to make the thing properly redraw
+//       itself - I don't know where the size calculation error is and I can't
+//       waste time looking for it right now. Search for occurences of
+//       MSW_CORRECTION to find all the places where I did it.
+#ifdef __WXMSW__
+   static const int MSW_CORRECTION = 5;
+#else
+   static const int MSW_CORRECTION = 0;
+#endif
 
 /// Cursors smaller than this disappear in XOR drawing mode
 #define WXLO_MINIMUM_CURSOR_WIDTH   4
 
 /// Cursors smaller than this disappear in XOR drawing mode
 #define WXLO_MINIMUM_CURSOR_WIDTH   4
 #define WXLO_CURSORCHAR   "E"
 /** @name Helper functions */
 //@{
 #define WXLO_CURSORCHAR   "E"
 /** @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;
-}
-
-/// 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)
 {
 /// allows me to compare to wxPoints
 bool operator <=(wxPoint const &p1, wxPoint const &p2)
 {
@@ -97,7 +102,7 @@ void GrowRect(wxRect &r, CoordType x, CoordType y)
       r.x = x;
    else if(r.x + r.width < x)
       r.width = x - r.x;
       r.x = x;
    else if(r.x + r.width < x)
       r.width = x - r.x;
-   
+
    if(r.y > y)
       r.y = y;
    else if(r.y + r.height < y)
    if(r.y > y)
       r.y = y;
    else if(r.y + r.height < y)
@@ -117,7 +122,46 @@ bool Contains(const wxRect &r, const wxPoint &p)
 
 //@}
 
 
 //@}
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+
+void ReadString(wxString &to, wxString &from)
+{
+   to = "";
+   const char *cptr = from.c_str();
+   while(*cptr && *cptr != '\n')
+      to += *cptr++;
+   if(*cptr) cptr++;
+   from = cptr;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+   wxLayoutObject
+
+   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* static */
+wxLayoutObject *
+wxLayoutObject::Read(wxString &istr)
+{
+   wxString tmp;
+   ReadString(tmp, istr);
+   int type = -1;
+   sscanf(tmp.c_str(),"%d", &type);
+
+   switch(type)
+   {
+   case WXLO_TYPE_TEXT:
+      return wxLayoutObjectText::Read(istr);
+   case WXLO_TYPE_CMD:
+      return wxLayoutObjectCmd::Read(istr);
+   case WXLO_TYPE_ICON:
+      return wxLayoutObjectIcon::Read(istr);
+   default:
+      return NULL;
+   }
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
    wxLayoutObjectText
 
 
    wxLayoutObjectText
 
@@ -144,6 +188,23 @@ wxLayoutObjectText::Copy(void)
    return obj;
 }
 
    return obj;
 }
 
+
+void
+wxLayoutObjectText::Write(wxString &ostr)
+{
+   ostr << (int) WXLO_TYPE_TEXT << '\n'
+        << m_Text << '\n';
+}
+/* static */
+wxLayoutObjectText *
+wxLayoutObjectText::Read(wxString &istr)
+{
+   wxString text;
+   ReadString(text, istr);
+
+   return new wxLayoutObjectText(text);
+}
+
 wxPoint
 wxLayoutObjectText::GetSize(CoordType *top, CoordType *bottom) const
 {
 wxPoint
 wxLayoutObjectText::GetSize(CoordType *top, CoordType *bottom) const
 {
@@ -157,7 +218,7 @@ wxLayoutObjectText::Draw(wxDC &dc, wxPoint const &coords,
                          wxLayoutList *wxllist,
                          CoordType begin, CoordType end)
 {
                          wxLayoutList *wxllist,
                          CoordType begin, CoordType end)
 {
-   if(begin == -1)
+   if( end <= 0)
       dc.DrawText(m_Text, coords.x, coords.y-m_Top);
    else
    {
       dc.DrawText(m_Text, coords.x, coords.y-m_Top);
    else
    {
@@ -167,7 +228,11 @@ wxLayoutObjectText::Draw(wxDC &dc, wxPoint const &coords,
          xpos = coords.x,
          ypos = coords.y-m_Top;
       long width, height, descent;
          xpos = coords.x,
          ypos = coords.y-m_Top;
       long width, height, descent;
-      
+
+      if(begin < 0) begin = 0;
+      if( end > (signed)m_Text.Length() )
+         end = m_Text.Length();
+
       str = m_Text.Mid(0, begin);
       dc.DrawText(str, xpos, ypos);
       dc.GetTextExtent(str, &width, &height, &descent);
       str = m_Text.Mid(0, begin);
       dc.DrawText(str, xpos, ypos);
       dc.GetTextExtent(str, &width, &height, &descent);
@@ -194,30 +259,62 @@ wxLayoutObjectText::GetOffsetScreen(wxDC &dc, CoordType xpos) const
       height, descent = 0l;
 
    if(xpos == 0) return 0; // easy
       height, descent = 0l;
 
    if(xpos == 0) return 0; // easy
-   
+
    while(width < xpos && offs < maxlen)
    {
       dc.GetTextExtent(m_Text.substr(0,offs),
                        &width, &height, &descent);
       offs++;
    }
    while(width < xpos && offs < maxlen)
    {
       dc.GetTextExtent(m_Text.substr(0,offs),
                        &width, &height, &descent);
       offs++;
    }
-   /* We have to substract 1 to compensate for the offs++, and another 
+   /* We have to substract 1 to compensate for the offs++, and another
       one because we don't want to position the cursor behind the
       object what we clicked on, but before - otherwise it looks
       funny. */
       one because we don't want to position the cursor behind the
       object what we clicked on, but before - otherwise it looks
       funny. */
-   return (xpos > 2) ? offs-2 : 0;  
+   return (xpos > 2) ? offs-2 : 0;
 }
 
 void
 }
 
 void
-wxLayoutObjectText::Layout(wxDC &dc)
+wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
 {
    long descent = 0l;
 
 {
    long descent = 0l;
 
-   dc.GetTextExtent(m_Text,&m_Width, &m_Height, &descent);
+   // now this is done in wxLayoutLine::Layout(), but this code might be
+   // reenabled later - in principle, it's more efficient
+#if 0
+   CoordType widthOld = m_Width,
+             heightOld = m_Height;
+#endif // 0
+
+   dc.GetTextExtent(m_Text, &m_Width, &m_Height, &descent);
+
+#if 0
+   if ( widthOld != m_Width || heightOld != m_Height )
+   {
+      // as the text length changed, it must be refreshed
+      wxLayoutLine *line = GetLine();
+
+      wxCHECK_RET( line, "wxLayoutObjectText can't refresh itself" );
+
+      // as our size changed, we need to repaint the part which was appended
+      wxPoint position(line->GetPosition());
+
+      // this is not the most efficient way (we repaint the whole line), but
+      // it's not too slow and is *simple*
+      if ( widthOld < m_Width )
+         widthOld = m_Width;
+      if ( heightOld < m_Height )
+         heightOld = m_Height;
+
+      llist->SetUpdateRect(position.x + widthOld + MSW_CORRECTION,
+                           position.y + heightOld + MSW_CORRECTION);
+   }
+#endif // 0
+
    m_Bottom = descent;
    m_Top = m_Height - m_Bottom;
 }
 
    m_Bottom = descent;
    m_Top = m_Height - m_Bottom;
 }
 
+
 #ifdef WXLAYOUT_DEBUG
 void
 wxLayoutObjectText::Debug(void)
 #ifdef WXLAYOUT_DEBUG
 void
 wxLayoutObjectText::Debug(void)
@@ -227,7 +324,7 @@ wxLayoutObjectText::Debug(void)
 }
 #endif
 
 }
 #endif
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
    wxLayoutObjectIcon
 
 
    wxLayoutObjectIcon
 
@@ -238,6 +335,38 @@ wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap const &icon)
    m_Icon = new wxBitmap(icon);
 }
 
    m_Icon = new wxBitmap(icon);
 }
 
+
+void
+wxLayoutObjectIcon::Write(wxString &ostr)
+{
+   /* Exports icon through a temporary file. */
+
+   wxString file = wxGetTempFileName("wxloexport");
+
+   ostr << WXLO_TYPE_ICON << '\n'
+        << file << '\n';
+   m_Icon->SaveFile(file, WXLO_BITMAP_FORMAT);
+}
+/* static */
+wxLayoutObjectIcon *
+wxLayoutObjectIcon::Read(wxString &istr)
+{
+   wxString file;
+   ReadString(file, istr);
+
+   if(! wxFileExists(file))
+      return NULL;
+   wxLayoutObjectIcon *obj = new wxLayoutObjectIcon;
+
+   if(!obj->m_Icon->LoadFile(file, WXLO_BITMAP_FORMAT))
+   {
+      delete obj;
+      return NULL;
+   }
+   else
+      return obj;
+}
+
 wxLayoutObject *
 wxLayoutObjectIcon::Copy(void)
 {
 wxLayoutObject *
 wxLayoutObjectIcon::Copy(void)
 {
@@ -262,7 +391,7 @@ wxLayoutObjectIcon::Draw(wxDC &dc, wxPoint const &coords,
 }
 
 void
 }
 
 void
-wxLayoutObjectIcon::Layout(wxDC & /* dc */)
+wxLayoutObjectIcon::Layout(wxDC & /* dc */, class wxLayoutList * )
 {
 }
 
 {
 }
 
@@ -276,56 +405,160 @@ wxLayoutObjectIcon::GetSize(CoordType *top, CoordType *bottom) const
 
 
 
 
 
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
 
-   wxLayoutObjectIcon
+   wxLayoutObjectCmd
 
    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 
    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-wxLayoutObjectCmd::wxLayoutObjectCmd(int size, int family, int style, int
-                                     weight, bool underline,
-                                     wxColour &fg, wxColour &bg)
-   
+
+wxLayoutStyleInfo::wxLayoutStyleInfo(int ifamily,
+                                     int isize,
+                                     int istyle,
+                                     int iweight,
+                                     int iul,
+                                     wxColour *fg,
+                                     wxColour *bg)
+{
+   family = ifamily; size = isize;
+   style = istyle; weight = iweight;
+   underline = iul != 0;
+   if(fg)
+   {
+      m_fg = *fg;
+      m_fg_valid = TRUE;
+   }
+   else
+      m_fg = *wxBLACK;
+   if(bg)
+   {
+      m_bg = *bg;
+      m_bg_valid = TRUE;
+   }
+   else
+      m_bg = *wxWHITE;
+}
+
+#define COPY_SI_(what) if(right.what != -1) what = right.what;
+
+wxLayoutStyleInfo &
+wxLayoutStyleInfo::operator=(const wxLayoutStyleInfo &right)
+{
+   COPY_SI_(family);
+   COPY_SI_(style);
+   COPY_SI_(size);
+   COPY_SI_(weight);
+   COPY_SI_(underline);
+   if(right.m_fg_valid) m_fg = right.m_fg;
+   if(right.m_bg_valid) m_bg = right.m_bg;
+   return *this;
+}
+
+wxLayoutObjectCmd::wxLayoutObjectCmd(int family, int size, int style, int
+                                     weight, int underline,
+                                     wxColour *fg, wxColour *bg)
+
 {
 {
-   m_font = new wxFont(size,family,style,weight,underline);
-   m_ColourFG = fg;
-   m_ColourBG = bg;
+   m_StyleInfo = new wxLayoutStyleInfo(family, size,style,weight,underline,fg,bg);
 }
 
 wxLayoutObject *
 wxLayoutObjectCmd::Copy(void)
 {
 }
 
 wxLayoutObject *
 wxLayoutObjectCmd::Copy(void)
 {
-   wxLayoutStyleInfo si;
-   GetStyle(&si);
-   
    wxLayoutObjectCmd *obj = new wxLayoutObjectCmd(
    wxLayoutObjectCmd *obj = new wxLayoutObjectCmd(
-      si.size, si.family, si.style, si.weight, si.underline,
-      m_ColourFG, m_ColourBG);
+      m_StyleInfo->size,
+      m_StyleInfo->family,
+      m_StyleInfo->style,
+      m_StyleInfo->weight,
+      m_StyleInfo->underline,
+      m_StyleInfo->m_fg_valid ?
+      &m_StyleInfo->m_fg : NULL,
+      m_StyleInfo->m_bg_valid ?
+      &m_StyleInfo->m_bg : NULL);
    obj->SetUserData(m_UserData);
    return obj;
 }
 
    obj->SetUserData(m_UserData);
    return obj;
 }
 
+void
+wxLayoutObjectCmd::Write(wxString &ostr)
+{
+   ostr << WXLO_TYPE_CMD << '\n'
+        << m_StyleInfo->size << '\n'
+        << m_StyleInfo->family << '\n'
+        << m_StyleInfo->style << '\n'
+        << m_StyleInfo->weight << '\n'
+        << m_StyleInfo->underline << '\n'
+        << m_StyleInfo->m_fg_valid << '\n'
+        << m_StyleInfo->m_bg_valid << '\n';
+   if(m_StyleInfo->m_fg_valid)
+   {
+      ostr << m_StyleInfo->m_fg.Red() << '\n'
+           << m_StyleInfo->m_fg.Green() << '\n'
+           << m_StyleInfo->m_fg.Blue() << '\n';
+   }
+   if(m_StyleInfo->m_bg_valid)
+   {
+      ostr << m_StyleInfo->m_bg.Red() << '\n'
+           << m_StyleInfo->m_bg.Green() << '\n'
+           << m_StyleInfo->m_bg.Blue() << '\n';
+   }
+}
+/* static */
+wxLayoutObjectCmd *
+wxLayoutObjectCmd::Read(wxString &istr)
+{
+   wxLayoutObjectCmd *obj = new wxLayoutObjectCmd;
+
+   wxString tmp;
+   ReadString(tmp, istr);
+   sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->size);
+   ReadString(tmp, istr);
+   sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->family);
+   ReadString(tmp, istr);
+   sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->style);
+   ReadString(tmp, istr);
+   sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->weight);
+   ReadString(tmp, istr);
+   sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->underline);
+   ReadString(tmp, istr);
+   sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->m_fg_valid);
+   ReadString(tmp, istr);
+   sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->m_bg_valid);
+   if(obj->m_StyleInfo->m_fg_valid)
+   {
+      int red, green, blue;
+      ReadString(tmp, istr);
+      sscanf(tmp.c_str(),"%d", &red);
+      ReadString(tmp, istr);
+      sscanf(tmp.c_str(),"%d", &green);
+      ReadString(tmp, istr);
+      sscanf(tmp.c_str(),"%d", &blue);
+      obj->m_StyleInfo->m_fg = wxColour(red, green, blue);
+   }
+   if(obj->m_StyleInfo->m_bg_valid)
+   {
+      int red, green, blue;
+      ReadString(tmp, istr);
+      sscanf(tmp.c_str(),"%d", &red);
+      ReadString(tmp, istr);
+      sscanf(tmp.c_str(),"%d", &green);
+      ReadString(tmp, istr);
+      sscanf(tmp.c_str(),"%d", &blue);
+      obj->m_StyleInfo->m_bg = wxColour(red, green, blue);
+   }
+   return obj;
+}
+
 
 wxLayoutObjectCmd::~wxLayoutObjectCmd()
 {
 
 wxLayoutObjectCmd::~wxLayoutObjectCmd()
 {
-   delete m_font;
+   delete m_StyleInfo;
 }
 
 }
 
-void
-wxLayoutObjectCmd::GetStyle(wxLayoutStyleInfo *si) const
+wxLayoutStyleInfo *
+wxLayoutObjectCmd::GetStyle(void) const
 {
 {
-   si->size = m_font->GetPointSize();
-   si->family = m_font->GetFamily();
-   si->style = m_font->GetStyle();
-   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();
+   return m_StyleInfo;
 }
 
 void
 }
 
 void
@@ -333,23 +566,19 @@ wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint const & /* coords */,
                         wxLayoutList *wxllist,
                         CoordType begin, CoordType /* len */)
 {
                         wxLayoutList *wxllist,
                         CoordType begin, CoordType /* len */)
 {
-   wxASSERT(m_font);
-   dc.SetFont(*m_font);
-   dc.SetTextForeground(m_ColourFG);
-   dc.SetTextBackground(m_ColourBG);
-   if(wxllist)
-      wxllist->SetColour_Internal(&m_ColourFG,& m_ColourBG);
+   wxASSERT(m_StyleInfo);
+   wxllist->ApplyStyle(m_StyleInfo, dc);
 }
 
 void
 }
 
 void
-wxLayoutObjectCmd::Layout(wxDC &dc)
+wxLayoutObjectCmd::Layout(wxDC &dc, class wxLayoutList * llist)
 {
    // this get called, so that recalculation uses right font sizes
 {
    // this get called, so that recalculation uses right font sizes
-   Draw(dc, wxPoint(0,0), NULL);
+   Draw(dc, wxPoint(0,0), llist);
 }
 
 
 }
 
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
    The wxLayoutLine object
 
 
    The wxLayoutLine object
 
@@ -360,7 +589,7 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
    m_LineNumber = 0;
    m_Width = m_Height = 0;
    m_Length = 0;
    m_LineNumber = 0;
    m_Width = m_Height = 0;
    m_Length = 0;
-   m_Dirty = true;
+   MarkDirty(0);
    m_Previous = prev;
    m_Next = NULL;
    RecalculatePosition(llist);
    m_Previous = prev;
    m_Next = NULL;
    RecalculatePosition(llist);
@@ -369,7 +598,6 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
       m_LineNumber = m_Previous->GetLineNumber()+1;
       m_Next = m_Previous->GetNextLine();
       m_Previous->m_Next = this;
       m_LineNumber = m_Previous->GetLineNumber()+1;
       m_Next = m_Previous->GetNextLine();
       m_Previous->m_Next = this;
-      m_Height = m_Previous->GetHeight();
    }
    if(m_Next)
    {
    }
    if(m_Next)
    {
@@ -387,22 +615,44 @@ wxLayoutLine::~wxLayoutLine()
 wxPoint
 wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
 {
 wxPoint
 wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
 {
+   wxASSERT(m_Previous || GetLineNumber() == 0);
+
+   wxPoint posOld(m_Position);
+
    if(m_Previous)
    if(m_Previous)
-      m_Position = m_Previous->GetPosition() +
-         wxPoint(0,m_Previous->GetHeight());
+   {
+      m_Position = m_Previous->GetPosition();
+      m_Position.y += m_Previous->GetHeight();
+   }
    else
       m_Position = wxPoint(0,0);
    else
       m_Position = wxPoint(0,0);
-   llist->SetUpdateRect(m_Position);
+
+   if ( m_Position != posOld )
+   {
+       // the whole line moved and must be repainted
+       llist->SetUpdateRect(m_Position);
+       llist->SetUpdateRect(m_Position.x + GetWidth() + MSW_CORRECTION,
+                            m_Position.y + GetHeight() + MSW_CORRECTION);
+       llist->SetUpdateRect(posOld);
+       llist->SetUpdateRect(posOld.x + GetWidth() + MSW_CORRECTION,
+                            posOld.y + GetHeight() + MSW_CORRECTION);
+   }
+
    return m_Position;
 }
 
 void
 wxLayoutLine::RecalculatePositions(int recurse, wxLayoutList *llist)
 {
    return m_Position;
 }
 
 void
 wxLayoutLine::RecalculatePositions(int recurse, wxLayoutList *llist)
 {
+   //FIXME: is this really needed? We run Layout() anyway.
+   // Recursing here, drives computation time up exponentially, as
+   // each line will cause all following lines to be recalculated.
+   // Yes, or linenumbers go wrong.
+
    wxASSERT(recurse >= 0);
    wxPoint pos = m_Position;
    CoordType height = m_Height;
    wxASSERT(recurse >= 0);
    wxPoint pos = m_Position;
    CoordType height = m_Height;
-   
+
 //   WXLO_TRACE("RecalculatePositions()");
    RecalculatePosition(llist);
    if(m_Next)
 //   WXLO_TRACE("RecalculatePositions()");
    RecalculatePosition(llist);
    if(m_Next)
@@ -410,7 +660,7 @@ wxLayoutLine::RecalculatePositions(int recurse, wxLayoutList *llist)
       if(recurse > 0)
          m_Next->RecalculatePositions(--recurse, llist);
       else if(pos != m_Position || m_Height != height)
       if(recurse > 0)
          m_Next->RecalculatePositions(--recurse, llist);
       else if(pos != m_Position || m_Height != height)
-         m_Next->RecalculatePositions(0, llist);         
+         m_Next->RecalculatePositions(0, llist);
    }
 }
 
    }
 }
 
@@ -423,7 +673,7 @@ wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const
       i,
       found = NULLIT;
    CoordType x = 0, len;
       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
    /* 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
@@ -453,15 +703,13 @@ wxLayoutLine::FindObjectScreen(wxDC &dc,
    wxASSERT(cxpos);
    wxLayoutObjectList::iterator i;
    CoordType x = 0, cx = 0, width;
    wxASSERT(cxpos);
    wxLayoutObjectList::iterator i;
    CoordType x = 0, cx = 0, width;
-   
+
    for(i = m_ObjectList.begin(); i != NULLIT; i++)
    {
    for(i = m_ObjectList.begin(); i != NULLIT; i++)
    {
-      (**i).Layout(dc);
       width = (**i).GetWidth();
       if( x <= xpos && xpos <= x + width )
       {
          *cxpos = cx + (**i).GetOffsetScreen(dc, xpos-x);
       width = (**i).GetWidth();
       if( x <= xpos && xpos <= x + width )
       {
          *cxpos = cx + (**i).GetOffsetScreen(dc, xpos-x);
-         WXLO_DEBUG(("wxLayoutLine::FindObjectScreen: cursor xpos = %ld", *cxpos));
          if(found) *found = true;
          return i;
       }
          if(found) *found = true;
          return i;
       }
@@ -474,11 +722,46 @@ wxLayoutLine::FindObjectScreen(wxDC &dc,
    return m_ObjectList.tail();
 }
 
    return m_ObjectList.tail();
 }
 
+/** Finds text in this line.
+    @param needle the text to find
+    @param xpos the position where to start the search
+    @return the cursoor coord where it was found or -1
+*/
+CoordType
+wxLayoutLine::FindText(const wxString &needle, CoordType xpos) const
+{
+   int
+      cpos = 0,
+      relpos = -1;
+   wxString const *text;
+
+   for(wxLOiterator i = m_ObjectList.begin(); i != m_ObjectList.end(); i++)
+   {
+      if(cpos >= xpos) // search from here!
+      {
+         if((**i).GetType() == WXLO_TYPE_TEXT)
+         {
+            text = & ((wxLayoutObjectText*)(*i))->GetText();
+            relpos = text->Find(needle);
+            if(relpos >= cpos-xpos) // -1 if not found
+            {
+               return cpos+relpos;
+            }
+         }
+         cpos += (**i).GetLength();
+      }
+   }
+   return -1; // not found
+}
+
 bool
 wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
 {
    wxASSERT(xpos >= 0);
    wxASSERT(obj != NULL);
 bool
 wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
 {
    wxASSERT(xpos >= 0);
    wxASSERT(obj != NULL);
+
+   MarkDirty(xpos);
+
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i == NULLIT)
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i == NULLIT)
@@ -528,11 +811,14 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
    m_ObjectList.insert(i,new wxLayoutObjectText(left));
    return true;
 }
    m_ObjectList.insert(i,new wxLayoutObjectText(left));
    return true;
 }
-   
+
 bool
 bool
-wxLayoutLine::Insert(CoordType xpos, wxString text)
+wxLayoutLine::Insert(CoordType xpos, const wxString& text)
 {
    wxASSERT(xpos >= 0);
 {
    wxASSERT(xpos >= 0);
+
+   MarkDirty(xpos);
+
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i != NULLIT && (**i).GetType() == WXLO_TYPE_TEXT)
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i != NULLIT && (**i).GetType() == WXLO_TYPE_TEXT)
@@ -540,11 +826,14 @@ wxLayoutLine::Insert(CoordType xpos, wxString text)
       wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
       tobj->GetText().insert(offset, text);
       m_Length += text.Length();
       wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
       tobj->GetText().insert(offset, text);
       m_Length += text.Length();
-
-      return true;
    }
    else
    }
    else
-      return Insert(xpos, new wxLayoutObjectText(text));
+   {
+      if ( !Insert(xpos, new wxLayoutObjectText(text)) )
+         return false;
+   }
+
+   return true;
 }
 
 CoordType
 }
 
 CoordType
@@ -554,6 +843,7 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
 
    wxASSERT(xpos >= 0);
    wxASSERT(npos >= 0);
 
    wxASSERT(xpos >= 0);
    wxASSERT(npos >= 0);
+   MarkDirty(xpos);
    wxLOiterator i = FindObject(xpos, &offset);
    while(npos > 0)
    {
    wxLOiterator i = FindObject(xpos, &offset);
    while(npos > 0)
    {
@@ -584,7 +874,7 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
          {
             if(xpos == GetLength())
                return npos;
          {
             if(xpos == GetLength())
                return npos;
-            else 
+            else
             {  // at    the end of an object
                // move to    begin of next object:
                i++; offset = 0;
             {  // at    the end of an object
                // move to    begin of next object:
                i++; offset = 0;
@@ -599,6 +889,7 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
             ((wxLayoutObjectText *)(*i))->GetText().Remove(offset,max);
       }
    }
             ((wxLayoutObjectText *)(*i))->GetText().Remove(offset,max);
       }
    }
+
    return npos;
 }
 
    return npos;
 }
 
@@ -607,6 +898,7 @@ wxLayoutLine::DeleteWord(CoordType xpos)
 {
    wxASSERT(xpos >= 0);
    CoordType offset;
 {
    wxASSERT(xpos >= 0);
    CoordType offset;
+   MarkDirty(xpos);
 
    wxLOiterator i = FindObject(xpos, &offset);
 
 
    wxLOiterator i = FindObject(xpos, &offset);
 
@@ -615,7 +907,7 @@ wxLayoutLine::DeleteWord(CoordType xpos)
       if(i == NULLIT) return false;
       if((**i).GetType() != WXLO_TYPE_TEXT)
       {
       if(i == NULLIT) return false;
       if((**i).GetType() != WXLO_TYPE_TEXT)
       {
-         // This should only happen when at end of line, behind a non-text 
+         // This should only happen when at end of line, behind a non-text
          // object:
          if(offset == (**i).GetLength()) return false;
          m_Length -= (**i).GetLength(); // -1
          // object:
          if(offset == (**i).GetLength()) return false;
          m_Length -= (**i).GetLength(); // -1
@@ -643,7 +935,7 @@ wxLayoutLine::DeleteWord(CoordType xpos)
          ((wxLayoutObjectText *)*i)->GetText().erase(offset,count);
          m_Length -= count;
          return true;
          ((wxLayoutObjectText *)*i)->GetText().erase(offset,count);
          m_Length -= count;
          return true;
-      }      
+      }
    }
    wxASSERT(0); // we should never arrive here
 }
    }
    wxASSERT(0); // we should never arrive here
 }
@@ -671,13 +963,17 @@ wxLayoutLine::Draw(wxDC &dc,
    wxLayoutObjectList::iterator i;
    wxPoint pos = offset;
    pos = pos + GetPosition();
    wxLayoutObjectList::iterator i;
    wxPoint pos = offset;
    pos = pos + GetPosition();
-   
+
    pos.y += m_BaseLine;
 
    CoordType xpos = 0; // cursorpos, lenght of line
 
    CoordType from, to, tempto;
    pos.y += m_BaseLine;
 
    CoordType xpos = 0; // cursorpos, lenght of line
 
    CoordType from, to, tempto;
+   //FIXME This doesn't work yet, needs updating afterr default
+   //settings for list or a wxLayoutObjectCmd have changed:
+   //llist->ApplyStyle(&((wxLayoutLine *)this)->m_StyleInfo, dc);
    int highlight = llist->IsSelected(this, &from, &to);
    int highlight = llist->IsSelected(this, &from, &to);
+//   WXLO_DEBUG(("highlight=%d",  highlight ));
    if(highlight == 1) // we need to draw the whole line inverted!
       llist->StartHighlighting(dc);
    else
    if(highlight == 1) // we need to draw the whole line inverted!
       llist->StartHighlighting(dc);
    else
@@ -689,20 +985,7 @@ wxLayoutLine::Draw(wxDC &dc,
       {
          // parts of the line need highlighting
          tempto = xpos+(**i).GetLength();
       {
          // parts of the line need highlighting
          tempto = xpos+(**i).GetLength();
-         if(tempto >= from && xpos <= to)
-         {
-            tempto = to-xpos;
-            if(tempto > (**i).GetLength())
-               tempto = (**i).GetLength();
-            CoordType tmp = from-xpos;
-            if(tmp < 0) tmp = 0;
-            (**i).Draw(dc, pos, llist, from-xpos, tempto);
-         }
-         else
-         {
-            llist->EndHighlighting(dc); // FIXME! inefficient
-            (**i).Draw(dc, pos, llist);
-         }
+         (**i).Draw(dc, pos, llist, from-xpos, to-xpos);
       }
       else
          (**i).Draw(dc, pos, llist);
       }
       else
          (**i).Draw(dc, pos, llist);
@@ -716,23 +999,32 @@ wxLayoutLine::Layout(wxDC &dc,
                      wxLayoutList *llist,
                      wxPoint *cursorPos,
                      wxPoint *cursorSize,
                      wxLayoutList *llist,
                      wxPoint *cursorPos,
                      wxPoint *cursorSize,
-                     int cx) 
+                     int cx)
 {
    wxLayoutObjectList::iterator i;
 
 {
    wxLayoutObjectList::iterator i;
 
+   // when a line becomes dirty, we redraw it from the place where it was
+   // changed till the end of line (because the following wxLayoutObjects are
+   // moved when the preceding one changes) - calculate the update rectangle.
+   CoordType updateTop = m_Position.y,
+             updateLeft = -1,
+             updateWidth = m_Width,
+             updateHeight = m_Height;
+
    CoordType
    CoordType
-      oldHeight = m_Height;
-   CoordType
-      topHeight, bottomHeight;  // above and below baseline
+      topHeight = 0,
+      bottomHeight = 0;  // above and below baseline
    CoordType
    CoordType
-      objHeight = 0,
-      objTopHeight, objBottomHeight;
+      objTopHeight, objBottomHeight; // above and below baseline
    CoordType
       len, count = 0;
    CoordType
       len, count = 0;
-   m_Height = 0; m_BaseLine = 0;
+
+   CoordType heightOld = m_Height;
+
+   m_Height = 0;
    m_Width = 0;
    m_Width = 0;
-   topHeight = 0; bottomHeight = 0;
-   wxPoint size;
+   m_BaseLine = 0;
+
    bool cursorFound = false;
 
    if(cursorPos)
    bool cursorFound = false;
 
    if(cursorPos)
@@ -740,27 +1032,32 @@ wxLayoutLine::Layout(wxDC &dc,
       *cursorPos = m_Position;
       if(cursorSize) *cursorSize = wxPoint(0,0);
    }
       *cursorPos = m_Position;
       if(cursorSize) *cursorSize = wxPoint(0,0);
    }
-   
+
+   //FIXME This doesn't work yet, needs updating afterr default
+   //settings for list or a wxLayoutObjectCmd have changed:
+   //llist->ApplyStyle(&m_StyleInfo, dc);
    for(i = m_ObjectList.begin(); i != NULLIT; i++)
    {
    for(i = m_ObjectList.begin(); i != NULLIT; i++)
    {
-      (**i).Layout(dc);
-      size = (**i).GetSize(&objTopHeight, &objBottomHeight);
+      wxLayoutObject *obj = *i;
+      obj->Layout(dc, llist);
+      wxPoint sizeObj = obj->GetSize(&objTopHeight, &objBottomHeight);
 
       if(cursorPos && ! cursorFound)
 
       if(cursorPos && ! cursorFound)
-      {  // we need to check whether the text cursor is here
-         len = (**i).GetLength();
+      {
+         // we need to check whether the text cursor is here
+         len = obj->GetLength();
          if(count <= cx && count+len > cx)
          {
          if(count <= cx && count+len > cx)
          {
-            if((**i).GetType() == WXLO_TYPE_TEXT)
+            if(obj->GetType() == WXLO_TYPE_TEXT)
             {
                len = cx - count; // pos in object
                CoordType width, height, descent;
             {
                len = cx - count; // pos in object
                CoordType width, height, descent;
-               dc.GetTextExtent((*(wxLayoutObjectText*)*i).GetText().substr(0,len), 
+               dc.GetTextExtent((*(wxLayoutObjectText*)*i).GetText().substr(0,len),
                                 &width, &height, &descent);
                cursorPos->x += width;
                cursorPos->y = m_Position.y;
                wxString str;
                                 &width, &height, &descent);
                cursorPos->x += width;
                cursorPos->y = m_Position.y;
                wxString str;
-               if(len < (**i).GetLength())
+               if(len < obj->GetLength())
                   str = (*(wxLayoutObjectText*)*i).GetText().substr(len,1);
                else
                   str = WXLO_CURSORCHAR;
                   str = (*(wxLayoutObjectText*)*i).GetText().substr(len,1);
                else
                   str = WXLO_CURSORCHAR;
@@ -768,15 +1065,16 @@ wxLayoutLine::Layout(wxDC &dc,
                wxASSERT(cursorSize);
                // Just in case some joker inserted an empty string object:
                if(width == 0) width = WXLO_MINIMUM_CURSOR_WIDTH;
                wxASSERT(cursorSize);
                // Just in case some joker inserted an empty string object:
                if(width == 0) width = WXLO_MINIMUM_CURSOR_WIDTH;
-               if(height == 0) height = objHeight;
+               if(height == 0) height = sizeObj.y;
                cursorSize->x = width;
                cursorSize->y = height;
                cursorFound = true; // no more checks
             }
                cursorSize->x = width;
                cursorSize->y = height;
                cursorFound = true; // no more checks
             }
-            else 
-            { // on some other object
+            else
+            {
+               // on some other object
                CoordType top, bottom; // unused
                CoordType top, bottom; // unused
-               *cursorSize = (**i).GetSize(&top,&bottom);
+               *cursorSize = obj->GetSize(&top,&bottom);
                cursorPos->y = m_Position.y;
                cursorFound = true; // no more checks
             }
                cursorPos->y = m_Position.y;
                cursorFound = true; // no more checks
             }
@@ -784,39 +1082,59 @@ wxLayoutLine::Layout(wxDC &dc,
          else
          {
             count += len;
          else
          {
             count += len;
-            cursorPos->x += (**i).GetWidth();
+            cursorPos->x += obj->GetWidth();
          }
       } // cursor finding
          }
       } // cursor finding
-      objHeight = size.y;
-      m_Width += size.x;
-      if(objHeight > m_Height) m_Height = objHeight;
-      if(objTopHeight > topHeight) topHeight = objTopHeight;
-      if(objBottomHeight > bottomHeight) bottomHeight = objBottomHeight;
-   }
-   if(topHeight + bottomHeight > m_Height) m_Height =
-                                              topHeight+bottomHeight;
+
+      m_Width += sizeObj.x;
+      if(sizeObj.y > m_Height)
+      {
+         m_Height = sizeObj.y;
+      }
+
+      if(objTopHeight > topHeight)
+         topHeight = objTopHeight;
+      if(objBottomHeight > bottomHeight)
+         bottomHeight = objBottomHeight;
+   }
+
+   if ( IsDirty() )
+   {
+      if ( updateHeight < m_Height )
+         updateHeight = m_Height;
+      if ( updateWidth < m_Width )
+         updateWidth = m_Width;
+
+      // update all line if we don't know where to start from
+      if ( updateLeft == -1 )
+          updateLeft = 0;
+
+      llist->SetUpdateRect(updateLeft, updateTop);
+      llist->SetUpdateRect(updateLeft + updateWidth + MSW_CORRECTION,
+                           updateTop + updateHeight + MSW_CORRECTION);
+   }
+
+   if(topHeight + bottomHeight > m_Height)
+   {
+      m_Height = topHeight+bottomHeight;
+   }
+
    m_BaseLine = topHeight;
 
    if(m_Height == 0)
    {
    m_BaseLine = topHeight;
 
    if(m_Height == 0)
    {
-      if(GetPreviousLine()) // empty line
-      {
-         m_Height = GetPreviousLine()->GetHeight();
-         m_BaseLine = GetPreviousLine()->m_BaseLine;
-      }
-      else
-      {
-            CoordType width, height, descent;
-            dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
-            m_Height = height;
-            m_BaseLine = m_Height - descent;
-      }
+      CoordType width, height, descent;
+      dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
+      m_Height = height;
+      m_BaseLine = m_Height - descent;
    }
 
    }
 
-   
    // tell next line about coordinate change
    // tell next line about coordinate change
-   if(m_Next && objHeight != oldHeight)
+   if(m_Next && m_Height != heightOld)
+   {
+      // FIXME isn't this done in RecalculatePositions() below anyhow?
       m_Next->RecalculatePositions(0, llist);
       m_Next->RecalculatePositions(0, llist);
+   }
 
    // We need to check whether we found a valid cursor size:
    if(cursorPos)
 
    // We need to check whether we found a valid cursor size:
    if(cursorPos)
@@ -833,6 +1151,10 @@ wxLayoutLine::Layout(wxDC &dc,
       if(m_BaseLine >= cursorSize->y) // the normal case anyway
          cursorPos->y += m_BaseLine-cursorSize->y;
    }
       if(m_BaseLine >= cursorSize->y) // the normal case anyway
          cursorPos->y += m_BaseLine-cursorSize->y;
    }
+
+   RecalculatePositions(1, llist);
+
+   MarkClean();
 }
 
 
 }
 
 
@@ -840,8 +1162,13 @@ wxLayoutLine *
 wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
 {
    wxASSERT(xpos >= 0);
 wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
 {
    wxASSERT(xpos >= 0);
-   
-   if(xpos == 0)
+
+   MarkDirty(xpos);
+
+   /* If we are at the begin of a line, we want to move all other
+      lines down and stay with the cursor where we are. However, if we
+      are in an empty line, we want to move down with it. */
+   if(xpos == 0 && GetLength() > 0)
    { // insert an empty line before this one
       wxLayoutLine *prev = new wxLayoutLine(m_Previous, llist);
       if(m_Previous == NULL)
    { // insert an empty line before this one
       wxLayoutLine *prev = new wxLayoutLine(m_Previous, llist);
       if(m_Previous == NULL)
@@ -849,14 +1176,13 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
          // before this.
          prev->m_Next = this;
          m_Previous = prev;
          // before this.
          prev->m_Next = this;
          m_Previous = prev;
-         m_Previous->m_Height = GetHeight(); // this is a wild guess
+         m_Previous->m_Height = 0; // this is a wild guess
       }
       }
-      MoveLines(+1);
       if(m_Next)
          m_Next->RecalculatePositions(1, llist);
       if(m_Next)
          m_Next->RecalculatePositions(1, llist);
-      return this;
+      return m_Previous;
    }
    }
-   
+
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i == NULLIT)
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i == NULLIT)
@@ -879,38 +1205,81 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
       i++; // don't move this object to the new list
    }
    else
       i++; // don't move this object to the new list
    }
    else
+   {
       if(offset > 0)
          i++; // move objects from here to new list
       if(offset > 0)
          i++; // move objects from here to new list
+   }
 
    while(i != m_ObjectList.end())
    {
 
    while(i != m_ObjectList.end())
    {
-      newLine->Append(*i);
-      m_Length -= (**i).GetLength();
+      wxLayoutObject *obj = *i;
+      newLine->Append(obj);
+      m_Length -= obj->GetLength();
+
       m_ObjectList.remove(i); // remove without deleting it
    }
    if(m_Next)
       m_Next->RecalculatePositions(2, llist);
    return newLine;
 }
       m_ObjectList.remove(i); // remove without deleting it
    }
    if(m_Next)
       m_Next->RecalculatePositions(2, llist);
    return newLine;
 }
-   
+
 
 void
 wxLayoutLine::MergeNextLine(wxLayoutList *llist)
 {
 
 void
 wxLayoutLine::MergeNextLine(wxLayoutList *llist)
 {
-   wxASSERT(GetNextLine());
+   wxCHECK_RET(GetNextLine(),"wxLayout internal error: no next line to merge");
    wxLayoutObjectList &list = GetNextLine()->m_ObjectList;
    wxLOiterator i;
    wxLayoutObjectList &list = GetNextLine()->m_ObjectList;
    wxLOiterator i;
-   
+
+   MarkDirty(GetWidth());
+
+   wxLayoutObject *last = NULL;
    for(i = list.begin(); i != list.end();)
    {
    for(i = list.begin(); i != list.end();)
    {
-      Append(*i);
-      list.remove(i); // remove without deleting it
+      wxLayoutObject *current = *i;
+
+      // merge text objects together for efficiency
+      if ( last && last->GetType() == WXLO_TYPE_TEXT &&
+                   current->GetType() == WXLO_TYPE_TEXT )
+      {
+         wxLayoutObjectText *textObj = (wxLayoutObjectText *)last;
+         wxString text(textObj->GetText());
+         text += ((wxLayoutObjectText *)current)->GetText();
+         textObj->SetText(text);
+
+         list.erase(i); // remove and delete it
+      }
+      else
+      {
+         // just append the object "as was"
+         Append(current);
+
+         list.remove(i); // remove without deleting it
+      }
    }
    wxASSERT(list.empty());
    }
    wxASSERT(list.empty());
+
    wxLayoutLine *oldnext = GetNextLine();
    wxLayoutLine *oldnext = GetNextLine();
-   SetNext(GetNextLine()->GetNextLine());
+   wxLayoutLine *nextLine = oldnext->GetNextLine();
+   SetNext(nextLine);
+   if ( nextLine )
+   {
+      nextLine->MoveLines(-1);
+   }
+   else
+   {
+       // this is now done in Delete(), but if this function is ever called
+       // from elsewhere, we might have to move refresh code back here (in
+       // order not to duplicate it)
+#if 0
+       wxPoint pos(oldnext->GetPosition());
+       llist->SetUpdateRect(pos);
+       llist->SetUpdateRect(pos.x + oldnext->GetWidth() + MSW_CORRECTION,
+                            pos.y + oldnext->GetHeight() + MSW_CORRECTION);
+#endif // 0
+   }
+
    delete oldnext;
    delete oldnext;
-   RecalculatePositions(1, llist);
 }
 
 CoordType
 }
 
 CoordType
@@ -920,7 +1289,7 @@ wxLayoutLine::GetWrapPosition(CoordType column)
    wxLOiterator i = FindObject(column, &offset);
    if(i == NULLIT) return -1; // cannot wrap
 
    wxLOiterator i = FindObject(column, &offset);
    if(i == NULLIT) return -1; // cannot wrap
 
-   // go backwards through the list and look for space in text objects 
+   // go backwards through the list and look for space in text objects
    do
    {
       if((**i).GetType() == WXLO_TYPE_TEXT)
    do
    {
       if((**i).GetType() == WXLO_TYPE_TEXT)
@@ -968,7 +1337,7 @@ wxLayoutLine::GetWrapPosition(CoordType column)
    pos -= (**i).GetLength();
    return pos; // in front of it
 }
    pos -= (**i).GetLength();
    return pos; // in front of it
 }
-   
+
 
 #ifdef WXLAYOUT_DEBUG
 void
 
 #ifdef WXLAYOUT_DEBUG
 void
@@ -979,7 +1348,10 @@ wxLayoutLine::Debug(void)
    WXLO_DEBUG(("Line %ld, Pos (%ld,%ld), Height %ld",
               (long int) GetLineNumber(),
               (long int) pos.x, (long int) pos.y,
    WXLO_DEBUG(("Line %ld, Pos (%ld,%ld), Height %ld",
               (long int) GetLineNumber(),
               (long int) pos.x, (long int) pos.y,
-              (long int) GetHeight()));
+               (long int) GetHeight()));
+   if(m_ObjectList.begin() != NULLIT)
+      (**m_ObjectList.begin()).Debug();
+
 }
 #endif
 
 }
 #endif
 
@@ -991,12 +1363,13 @@ wxLayoutLine::Copy(wxLayoutList *llist,
    CoordType firstOffset, lastOffset;
 
    if(to == -1) to = GetLength();
    CoordType firstOffset, lastOffset;
 
    if(to == -1) to = GetLength();
-   
+   if(from == to) return;
+
    wxLOiterator first = FindObject(from, &firstOffset);
    wxLOiterator last  = FindObject(to, &lastOffset);
 
    // Common special case: only one object
    wxLOiterator first = FindObject(from, &firstOffset);
    wxLOiterator last  = FindObject(to, &lastOffset);
 
    // Common special case: only one object
-   if( *first == *last )
+   if( first != NULLIT && last != NULLIT && *first == *last )
    {
       if( (**first).GetType() == WXLO_TYPE_TEXT )
       {
    {
       if( (**first).GetType() == WXLO_TYPE_TEXT )
       {
@@ -1015,7 +1388,7 @@ wxLayoutLine::Copy(wxLayoutList *llist,
       }
    }
 
       }
    }
 
-   // If we reach here, we can safely copy the whole first object from 
+   // If we reach here, we can safely copy the whole first object from
    // the firstOffset position on:
    if((**first).GetType() == WXLO_TYPE_TEXT && firstOffset != 0)
    {
    // the firstOffset position on:
    if((**first).GetType() == WXLO_TYPE_TEXT && firstOffset != 0)
    {
@@ -1026,7 +1399,7 @@ wxLayoutLine::Copy(wxLayoutList *llist,
    else if(firstOffset == 0)
       llist->Insert( (**first).Copy() );
    // else nothing to copy :-(
    else if(firstOffset == 0)
       llist->Insert( (**first).Copy() );
    // else nothing to copy :-(
-   
+
    // Now we copy all objects before the last one:
    wxLOiterator i = first; i++;
    for( ; i != last; i++)
    // Now we copy all objects before the last one:
    wxLOiterator i = first; i++;
    for( ; i != last; i++)
@@ -1046,18 +1419,20 @@ wxLayoutLine::Copy(wxLayoutList *llist,
    }
 }
 
    }
 }
 
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-   
+
    The wxLayoutList object
    The wxLayoutList object
-   
+
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 wxLayoutList::wxLayoutList()
 {
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 wxLayoutList::wxLayoutList()
 {
-   m_DefaultSetting = NULL;
+#ifdef WXLAYOUT_USE_CARET
+   m_caret = NULL;
+#endif // WXLAYOUT_USE_CARET
+
    m_FirstLine = NULL;
    m_FirstLine = NULL;
-   m_ColourFG = *wxBLACK;
-   m_ColourBG = *wxWHITE;
    InvalidateUpdateRect();
    Clear();
 }
    InvalidateUpdateRect();
    Clear();
 }
@@ -1087,11 +1462,20 @@ void
 wxLayoutList::InternalClear(void)
 {
    Empty();
 wxLayoutList::InternalClear(void)
 {
    Empty();
-   if(m_DefaultSetting)
-   {
-      delete m_DefaultSetting;
-      m_DefaultSetting = NULL;
-   }
+   m_Selection.m_selecting = false;
+   m_Selection.m_valid = false;
+
+   m_DefaultSetting.family = wxSWISS;
+   m_DefaultSetting.size = WXLO_DEFAULTFONTSIZE;
+   m_DefaultSetting.style = wxNORMAL;
+   m_DefaultSetting.weight = wxNORMAL;
+   m_DefaultSetting.underline = 0;
+   m_DefaultSetting.m_fg_valid = TRUE;
+   m_DefaultSetting.m_fg = *wxBLACK;
+   m_DefaultSetting.m_bg_valid = TRUE;
+   m_DefaultSetting.m_bg = *wxWHITE;
+
+   m_CurrentSetting = m_DefaultSetting;
 }
 
 void
 }
 
 void
@@ -1099,18 +1483,21 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
                       int underline, wxColour *fg,
                       wxColour *bg)
 {
                       int underline, wxColour *fg,
                       wxColour *bg)
 {
-   if(family != -1)    m_FontFamily = family;
-   if(size != -1)      m_FontPtSize = size;
-   if(style != -1)     m_FontStyle = style;
-   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(family != -1)    m_CurrentSetting.family = family;
+   if(size != -1)      m_CurrentSetting.size = size;
+   if(style != -1)     m_CurrentSetting.style = style;
+   if(weight != -1)    m_CurrentSetting.weight = weight;
+   if(underline != -1) m_CurrentSetting.underline = underline != 0;
+   if(fg) m_CurrentSetting.m_fg = *fg;
+   if(bg) m_CurrentSetting.m_bg = *bg;
    Insert(
    Insert(
-      new wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,m_FontWeight,m_FontUnderline,
-                            m_ColourFG, m_ColourBG));
+      new wxLayoutObjectCmd(
+         m_CurrentSetting.family,
+         m_CurrentSetting.size,
+         m_CurrentSetting.style,
+         m_CurrentSetting.weight,
+         m_CurrentSetting.underline,
+         fg, bg));
 }
 
 void
 }
 
 void
@@ -1126,47 +1513,48 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
       cfg = wxTheColourDatabase->FindColour(fg);
    if( bg )
       cbg = wxTheColourDatabase->FindColour(bg);
       cfg = wxTheColourDatabase->FindColour(fg);
    if( bg )
       cbg = wxTheColourDatabase->FindColour(bg);
-   
+
    SetFont(family,size,style,weight,underline,cfg,cbg);
 }
 
 void
 wxLayoutList::Clear(int family, int size, int style, int weight,
    SetFont(family,size,style,weight,underline,cfg,cbg);
 }
 
 void
 wxLayoutList::Clear(int family, int size, int style, int weight,
-                    int /* underline */, wxColour *fg, wxColour *bg)
+                    int underline, wxColour *fg, wxColour *bg)
 {
    InternalClear();
 {
    InternalClear();
-   
-   // set defaults
-   m_FontPtSize = size;
-   m_FontUnderline = false;
-   m_FontFamily = family;
-   m_FontStyle = style;
-   m_FontWeight = weight;
-   if(fg)
-      m_ColourFG = *fg;
-   else
-      m_ColourFG = *wxBLACK;
-   if(bg)
-      m_ColourBG = *bg;
-   else
-      m_ColourBG = *wxWHITE;
-      
-   if(m_DefaultSetting)
-      delete m_DefaultSetting;
-
-   m_DefaultSetting = new
-      wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,
-                        m_FontWeight,m_FontUnderline,
-                        m_ColourFG, m_ColourBG);
+   m_DefaultSetting = wxLayoutStyleInfo(family, size, style, weight,
+                                        underline, fg, bg);
+   m_CurrentSetting = m_DefaultSetting;
 }
 
 }
 
+wxPoint
+wxLayoutList::FindText(const wxString &needle, const wxPoint &cpos) const
+{
+   int xpos;
+
+   wxLayoutLine *line;
+   for(line = m_FirstLine;
+       line;
+       line = line->GetNextLine())
+   {
+      if(line->GetLineNumber() >= cpos.y)
+      {
+         xpos = line->FindText(needle,
+                               (line->GetLineNumber() == cpos.y) ?
+                               cpos.x : 0);
+         if(xpos != -1)
+            return wxPoint(xpos, line->GetLineNumber());
+      }
+   }
+   return wxPoint(-1,-1);
+}
 
 
 bool
 wxLayoutList::MoveCursorTo(wxPoint const &p)
 {
 
 
 bool
 wxLayoutList::MoveCursorTo(wxPoint const &p)
 {
-   SetUpdateRect(m_CursorScreenPos);
-   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+   AddCursorPosToUpdateRect();
+
    wxLayoutLine *line = m_FirstLine;
    while(line && line->GetLineNumber() != p.y)
       line = line->GetNextLine();
    wxLayoutLine *line = m_FirstLine;
    while(line && line->GetLineNumber() != p.y)
       line = line->GetNextLine();
@@ -1188,12 +1576,12 @@ wxLayoutList::MoveCursorTo(wxPoint const &p)
    }
    return false;
 }
    }
    return false;
 }
-   
+
 bool
 wxLayoutList::MoveCursorVertically(int n)
 {
 bool
 wxLayoutList::MoveCursorVertically(int n)
 {
-   SetUpdateRect(m_CursorScreenPos);
-   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+   AddCursorPosToUpdateRect();
+
    bool rc;
    if(n  < 0) // move up
    {
    bool rc;
    if(n  < 0) // move up
    {
@@ -1246,8 +1634,8 @@ wxLayoutList::MoveCursorVertically(int n)
 bool
 wxLayoutList::MoveCursorHorizontally(int n)
 {
 bool
 wxLayoutList::MoveCursorHorizontally(int n)
 {
-   SetUpdateRect(m_CursorScreenPos);
-   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+   AddCursorPosToUpdateRect();
+
    int move;
    while(n < 0)
    {
    int move;
    while(n < 0)
    {
@@ -1287,10 +1675,20 @@ bool
 wxLayoutList::Insert(wxString const &text)
 {
    wxASSERT(m_CursorLine);
 wxLayoutList::Insert(wxString const &text)
 {
    wxASSERT(m_CursorLine);
-   SetUpdateRect(m_CursorScreenPos);
-   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
-   m_CursorLine->Insert(m_CursorPos.x, text);
+   wxASSERT_MSG( text.Find('\n') == wxNOT_FOUND, "use wxLayoutImportText!" );
+
+   if ( !text )
+       return true;
+
+   AddCursorPosToUpdateRect();
+
+   if ( !m_CursorLine->Insert(m_CursorPos.x, text) )
+      return false;
+
    m_CursorPos.x += text.Length();
    m_CursorPos.x += text.Length();
+
+   m_CursorLine->RecalculatePositions(0, this);
+
    return true;
 }
 
    return true;
 }
 
@@ -1298,25 +1696,70 @@ bool
 wxLayoutList::Insert(wxLayoutObject *obj)
 {
    wxASSERT(m_CursorLine);
 wxLayoutList::Insert(wxLayoutObject *obj)
 {
    wxASSERT(m_CursorLine);
-   SetUpdateRect(m_CursorScreenPos);
-   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+
+   if(! m_CursorLine)
+      m_CursorLine = GetFirstLine();
+
+   AddCursorPosToUpdateRect();
+
    m_CursorLine->Insert(m_CursorPos.x, obj);
    m_CursorPos.x += obj->GetLength();
    m_CursorLine->Insert(m_CursorPos.x, obj);
    m_CursorPos.x += obj->GetLength();
+
+   m_CursorLine->RecalculatePositions(0, this);
+
    return true;
 }
 
    return true;
 }
 
+bool
+wxLayoutList::Insert(wxLayoutList *llist)
+{
+   wxASSERT(llist);
+   bool rc = TRUE;
+
+   for(wxLayoutLine *line = llist->GetFirstLine();
+       line;
+       line = line->GetNextLine()
+      )
+   {
+      for(wxLOiterator i = line->GetFirstObject();
+          i != NULLIT;
+          i++)
+         rc |= Insert(*i);
+      LineBreak();
+   }
+   return rc;
+}
+
 bool
 wxLayoutList::LineBreak(void)
 {
    wxASSERT(m_CursorLine);
    bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0);
 bool
 wxLayoutList::LineBreak(void)
 {
    wxASSERT(m_CursorLine);
    bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0);
-   SetUpdateRect(m_CursorScreenPos);
-   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+
+   AddCursorPosToUpdateRect();
+
+   wxPoint position(m_CursorLine->GetPosition());
+
+   wxCoord width = m_CursorLine->GetWidth(),
+           height = m_CursorLine->GetHeight();
+
    m_CursorLine = m_CursorLine->Break(m_CursorPos.x, this);
    if(setFirst) // we were at beginning of first line
       m_FirstLine = m_CursorLine->GetPreviousLine();
    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++;
+   if(m_CursorPos.x != 0)
+      m_CursorPos.y++;
    m_CursorPos.x = 0;
    m_CursorPos.x = 0;
+// doesn't help   m_CursorLine.MarkDirty();
+
+   wxLayoutLine *prev = m_CursorLine->GetPreviousLine();
+   wxCHECK_MSG(prev, false, "just broke the line, where is the previous one?");
+
+   height += prev->GetHeight();
+
+   SetUpdateRect(position);
+   SetUpdateRect(position.x + width + MSW_CORRECTION,
+                 position.y + height + MSW_CORRECTION);
+
    return true;
 }
 
    return true;
 }
 
@@ -1333,11 +1776,15 @@ wxLayoutList::WrapLine(CoordType column)
       //else:
       CoordType newpos = m_CursorPos.x - xpos - 1;
       m_CursorPos.x = xpos;
       //else:
       CoordType newpos = m_CursorPos.x - xpos - 1;
       m_CursorPos.x = xpos;
-      SetUpdateRect(m_CursorScreenPos);
-      SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+
+      AddCursorPosToUpdateRect();
+
       LineBreak();
       Delete(1); // delete the space
       m_CursorPos.x = newpos;
       LineBreak();
       Delete(1); // delete the space
       m_CursorPos.x = newpos;
+
+      m_CursorLine->RecalculatePositions(1, this);
+
       return true;
    }
 }
       return true;
    }
 }
@@ -1345,40 +1792,79 @@ wxLayoutList::WrapLine(CoordType column)
 bool
 wxLayoutList::Delete(CoordType npos)
 {
 bool
 wxLayoutList::Delete(CoordType npos)
 {
-   wxASSERT(m_CursorLine);
-   SetUpdateRect(m_CursorScreenPos);
-   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+   wxCHECK_MSG(m_CursorLine, false, "can't delete in non existing line");
+   wxASSERT_MSG(npos > 0, "nothing to delete?");
+
+   AddCursorPosToUpdateRect();
+
+   // were other lines appended to this one (this is important to know because
+   // this means that our width _increased_ as the result of deletion)
+   bool wasMerged = false;
+
+   // the size of the region to update
+   CoordType totalHeight = m_CursorLine->GetHeight(),
+             totalWidth = m_CursorLine->GetWidth();
+
    CoordType left;
    do
    {
       left = m_CursorLine->Delete(m_CursorPos.x, npos);
    CoordType left;
    do
    {
       left = m_CursorLine->Delete(m_CursorPos.x, npos);
-      if(left == 0)
-         return true;
-      // More to delete, continue on next line.
-      // First, check if line is empty:
-      if(m_CursorLine->GetLength() == 0)
-      {  // in this case, updating could probably be optimised
-#ifdef WXLO_DEBUG   
-         wxASSERT(DeleteLines(1) == 0);
+
+      if( left > 0 )
+      {
+         // More to delete, continue on next line.
+
+         // First, check if line is empty:
+         if(m_CursorLine->GetLength() == 0)
+         {
+            // in this case, updating could probably be optimised
+#ifdef WXLO_DEBUG
+            wxASSERT(DeleteLines(1) == 0);
 #else
 #else
-         DeleteLines(1);
+            DeleteLines(1);
 #endif
 #endif
-         
-         left--;
-      }
-      else 
-      {
-         // Need to join next line
-         if(! m_CursorLine->GetNextLine())
-            break; // cannot
+
+            left--;
+         }
          else
          {
          else
          {
-            m_CursorLine->MergeNextLine(this);
-            left--;
+            // Need to join next line
+            if(! m_CursorLine->GetNextLine())
+               break; // cannot
+            else
+            {
+               wasMerged = true;
+               wxLayoutLine *next = m_CursorLine->GetNextLine();
+               if ( next )
+               {
+                  totalHeight += next->GetHeight();
+                  totalWidth += next->GetWidth();
+
+                  m_CursorLine->MergeNextLine(this);
+                  left--;
+               }
+               else
+               {
+                  wxFAIL_MSG("can't delete all this");
+
+                  return false;
+               }
+            }
          }
       }
    }
          }
       }
    }
-   while(left);
+   while ( left> 0 );
+
+   // we need to update the whole tail of the line and the lines which
+   // disappeared
+   if ( wasMerged )
+   {
+      wxPoint position(m_CursorLine->GetPosition());
+      SetUpdateRect(position);
+      SetUpdateRect(position.x + totalWidth + MSW_CORRECTION,
+                    position.y + totalHeight + MSW_CORRECTION);
+   }
+
    return left == 0;
 }
 
    return left == 0;
 }
 
@@ -1387,14 +1873,16 @@ wxLayoutList::DeleteLines(int n)
 {
    wxASSERT(m_CursorLine);
    wxLayoutLine *line;
 {
    wxASSERT(m_CursorLine);
    wxLayoutLine *line;
-   SetUpdateRect(m_CursorScreenPos);
-   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+
+   AddCursorPosToUpdateRect();
+
    while(n > 0)
    {
       if(!m_CursorLine->GetNextLine())
       {  // we cannot delete this line, but we can clear it
          MoveCursorToBeginOfLine();
          DeleteToEndOfLine();
    while(n > 0)
    {
       if(!m_CursorLine->GetNextLine())
       {  // we cannot delete this line, but we can clear it
          MoveCursorToBeginOfLine();
          DeleteToEndOfLine();
+         m_CursorLine->RecalculatePositions(2, this);
          return n-1;
       }
       //else:
          return n-1;
       }
       //else:
@@ -1416,7 +1904,7 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
 
    // first, make sure everything is calculated - this might not be
    // needed, optimise it later
 
    // first, make sure everything is calculated - this might not be
    // needed, optimise it later
-   m_DefaultSetting->Layout(dc);
+   ApplyStyle(&m_DefaultSetting, dc);
    while(line)
    {
       line->RecalculatePosition(this); // so we don't need to do it all the time
    while(line)
    {
       line->RecalculatePosition(this); // so we don't need to do it all the time
@@ -1440,22 +1928,37 @@ wxLayoutList::GetCursorScreenPos(wxDC &dc)
    return m_CursorScreenPos;
 }
 
    return m_CursorScreenPos;
 }
 
+/*
+  Is called before each Draw(). Now, it will re-layout all lines which
+  have changed.
+*/
 void
 void
-wxLayoutList::Layout(wxDC &dc, CoordType bottom)
+wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll)
 {
 {
-   wxLayoutLine *line = m_FirstLine;
-
    // first, make sure everything is calculated - this might not be
    // needed, optimise it later
    // first, make sure everything is calculated - this might not be
    // needed, optimise it later
-   m_DefaultSetting->Layout(dc);
+   ApplyStyle(&m_DefaultSetting, dc);
+
+   // FIXME this is completely wrong - we should start by first *visible* line
+   //       (and stop on the last one) instead of looping over all lines!!
+   wxLayoutLine *line = m_FirstLine;
    while(line)
    {
    while(line)
    {
-      if(line == m_CursorLine)
-         line->Layout(dc, this, (wxPoint *)&m_CursorScreenPos, (wxPoint *)&m_CursorSize, m_CursorPos.x);
-      else
-         line->Layout(dc, this);
-      // little condition to speed up redrawing:
-      if(bottom != -1 && line->GetPosition().y > bottom) break;
+      if(forceAll || line->IsDirty())
+      {
+         line->GetStyleInfo() = m_CurrentSetting;
+         if(line == m_CursorLine)
+            line->Layout(dc, this, (wxPoint *)&m_CursorScreenPos,
+                         (wxPoint *)&m_CursorSize, m_CursorPos.x);
+         else
+            line->Layout(dc, this);
+
+         // little condition to speed up redrawing:
+         if(bottom != -1 && line->GetPosition().y > bottom)
+             break;
+      }
+
+      line->RecalculatePositions(1, this);
       line = line->GetNextLine();
    }
 
       line = line->GetNextLine();
    }
 
@@ -1466,8 +1969,7 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom)
                                     m_CursorLine->GetNextLine() == NULL &&
                                     m_CursorLine == m_FirstLine));
 #endif
                                     m_CursorLine->GetNextLine() == NULL &&
                                     m_CursorLine == m_FirstLine));
 #endif
-   SetUpdateRect(m_CursorScreenPos);
-   SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+   AddCursorPosToUpdateRect();
 }
 
 void
 }
 
 void
@@ -1478,24 +1980,23 @@ wxLayoutList::Draw(wxDC &dc,
 {
    wxLayoutLine *line = m_FirstLine;
 
 {
    wxLayoutLine *line = m_FirstLine;
 
-   Layout(dc, bottom);
-   m_DefaultSetting->Draw(dc, wxPoint(0,0), this);
-   wxBrush brush(m_ColourBG, wxSOLID);
+   Layout(dc);
+   ApplyStyle(&m_DefaultSetting, dc);
+   wxBrush brush(m_CurrentSetting.m_bg, wxSOLID);
    dc.SetBrush(brush);
    dc.SetBrush(brush);
-   
+   dc.SetBackgroundMode(wxTRANSPARENT);
+
    while(line)
    {
       // only draw if between top and bottom:
       if((top == -1 || line->GetPosition().y + line->GetHeight() >= top))
          line->Draw(dc, this, offset);
    while(line)
    {
       // only draw if between top and bottom:
       if((top == -1 || line->GetPosition().y + line->GetHeight() >= top))
          line->Draw(dc, this, offset);
+      else
+         line->Layout(dc, this);
       // little condition to speed up redrawing:
       if(bottom != -1 && line->GetPosition().y > bottom) break;
       line = line->GetNextLine();
    }
       // little condition to speed up redrawing:
       if(bottom != -1 && line->GetPosition().y > 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();
 
    WXLO_DEBUG(("Selection is %s : l%d,%ld/%ld,%ld",
    InvalidateUpdateRect();
 
    WXLO_DEBUG(("Selection is %s : l%d,%ld/%ld,%ld",
@@ -1512,15 +2013,23 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
    // First, find the right line:
    wxLayoutLine *line = m_FirstLine;
    wxPoint p;
    // First, find the right line:
    wxLayoutLine *line = m_FirstLine;
    wxPoint p;
-   
-   // we need to run a layout here to get font sizes right :-(
-   m_DefaultSetting->Layout(dc);
+
+   ApplyStyle(&m_DefaultSetting, dc);
    while(line)
    {
       p = line->GetPosition();
       if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
          break;
    while(line)
    {
       p = line->GetPosition();
       if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
          break;
+#if 0
+      // we need to run a layout here to get font sizes right :-(
+
+      // VZ: we can't call Layout() from here because it marks the line as
+      //     clean and it is not refreshed when it's called from wxLayoutList::
+      //     Layout() - if we really need to do this, we should introduce an
+      //     extra argument to Layout() to prevent the line from MarkClean()ing
+      //     itself here
       line->Layout(dc, this);
       line->Layout(dc, this);
+#endif
       line = line->GetNextLine();
    }
    if(line == NULL)
       line = line->GetNextLine();
    }
    if(line == NULL)
@@ -1534,7 +2043,7 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
                                            cursorPos ? & cursorPos->x : NULL ,
                                            found);
    return (i == NULLIT) ? NULL : *i;
                                            cursorPos ? & cursorPos->x : NULL ,
                                            found);
    return (i == NULLIT) ? NULL : *i;
-   
+
 }
 
 wxPoint
 }
 
 wxPoint
@@ -1547,7 +2056,7 @@ wxLayoutList::GetSize(void) const
       return wxPoint(0,0);
 
    wxPoint maxPoint(0,0);
       return wxPoint(0,0);
 
    wxPoint maxPoint(0,0);
-   
+
    // find last line:
    while(line)
    {
    // find last line:
    while(line)
    {
@@ -1561,13 +2070,12 @@ wxLayoutList::GetSize(void) const
    return maxPoint;
 }
 
    return maxPoint;
 }
 
+
 void
 wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
 {
 void
 wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
 {
-   wxPoint coords;
-   coords = m_CursorScreenPos;
-   coords.x += translate.x;
-   coords.y += translate.y;
+   wxPoint coords(m_CursorScreenPos);
+   coords += translate;
 
 #ifdef WXLAYOUT_DEBUG
    WXLO_DEBUG(("Drawing cursor (%ld,%ld) at %ld,%ld, size %ld,%ld, line: %ld, len %ld",
 
 #ifdef WXLAYOUT_DEBUG
    WXLO_DEBUG(("Drawing cursor (%ld,%ld) at %ld,%ld, size %ld,%ld, line: %ld, len %ld",
@@ -1576,8 +2084,13 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
                (long)m_CursorSize.x, (long)m_CursorSize.y,
                (long)m_CursorLine->GetLineNumber(),
                (long)m_CursorLine->GetLength()));
                (long)m_CursorSize.x, (long)m_CursorSize.y,
                (long)m_CursorLine->GetLineNumber(),
                (long)m_CursorLine->GetLength()));
+
+   wxLogStatus("Cursor is at (%d, %d)", m_CursorPos.x, m_CursorPos.y);
 #endif
 #endif
-   
+
+#ifdef WXLAYOUT_USE_CARET
+   m_caret->Move(coords);
+#else // !WXLAYOUT_USE_CARET
    dc.SetBrush(*wxBLACK_BRUSH);
    dc.SetLogicalFunction(wxXOR);
    dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
    dc.SetBrush(*wxBLACK_BRUSH);
    dc.SetLogicalFunction(wxXOR);
    dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
@@ -1597,6 +2110,7 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
    }
    dc.SetLogicalFunction(wxCOPY);
    //dc.SetBrush(wxNullBrush);
    }
    dc.SetLogicalFunction(wxCOPY);
    //dc.SetBrush(wxNullBrush);
+#endif // WXLAYOUT_USE_CARET/!WXLAYOUT_USE_CARET
 }
 
 void
 }
 
 void
@@ -1615,22 +2129,29 @@ wxLayoutList::SetUpdateRect(CoordType x, CoordType y)
 }
 
 void
 }
 
 void
-wxLayoutList::StartSelection(void)
+wxLayoutList::StartSelection(wxPoint cpos)
 {
 {
-   WXLO_DEBUG(("Starting selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y));
-   m_Selection.m_CursorA = m_CursorPos;
-   m_Selection.m_CursorB = m_CursorPos;
+   if(cpos.x == -1)
+      cpos = m_CursorPos;
+   WXLO_DEBUG(("Starting selection at %ld/%ld", cpos.x, cpos.y));
+   m_Selection.m_CursorA = cpos;
+   m_Selection.m_CursorB = cpos;
    m_Selection.m_selecting = true;
    m_Selection.m_valid = false;
 }
 
 void
    m_Selection.m_selecting = true;
    m_Selection.m_valid = false;
 }
 
 void
-wxLayoutList::ContinueSelection(void)
+wxLayoutList::ContinueSelection(wxPoint cpos)
 {
 {
+   if(cpos.x == -1)
+      cpos = m_CursorPos;
    wxASSERT(m_Selection.m_selecting == true);
    wxASSERT(m_Selection.m_valid == false);
    wxASSERT(m_Selection.m_selecting == true);
    wxASSERT(m_Selection.m_valid == false);
-   WXLO_DEBUG(("Continuing selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y));
-   m_Selection.m_CursorB = m_CursorPos;
+   WXLO_DEBUG(("Continuing selection at %ld/%ld", cpos.x, cpos.y));
+   if(m_Selection.m_CursorB <= cpos)
+      m_Selection.m_CursorB = cpos;
+   else
+      m_Selection.m_CursorA = cpos;
    // We always want m_CursorA <= m_CursorB!
    if(! (m_Selection.m_CursorA <= m_Selection.m_CursorB))
    {
    // We always want m_CursorA <= m_CursorB!
    if(! (m_Selection.m_CursorA <= m_Selection.m_CursorB))
    {
@@ -1641,10 +2162,12 @@ wxLayoutList::ContinueSelection(void)
 }
 
 void
 }
 
 void
-wxLayoutList::EndSelection(void)
+wxLayoutList::EndSelection(wxPoint cpos)
 {
 {
-   ContinueSelection();
-   WXLO_DEBUG(("Ending selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y));
+   if(cpos.x == -1)
+      cpos = m_CursorPos;
+   ContinueSelection(cpos);
+   WXLO_DEBUG(("Ending selection at %ld/%ld", cpos.x, cpos.y));
    m_Selection.m_selecting = false;
    m_Selection.m_valid = true;
 }
    m_Selection.m_selecting = false;
    m_Selection.m_valid = true;
 }
@@ -1706,14 +2229,70 @@ wxLayoutList::IsSelected(const wxLayoutLine *line, CoordType *from,
       return 0;
 }
 
       return 0;
 }
 
+void
+wxLayoutList::DeleteSelection(void)
+{
+   if(! m_Selection.m_valid)
+      return;
+
+   m_Selection.m_valid = false;
+
+   // Only delete part of the current line?
+   if(m_Selection.m_CursorA.y == m_Selection.m_CursorB.y)
+   {
+      MoveCursorTo(m_Selection.m_CursorA);
+      Delete(m_Selection.m_CursorB.x - m_Selection.m_CursorA.x);
+      return;
+   }
+
+
+   wxLayoutLine
+      * firstLine = NULL,
+      * lastLine = NULL;
+
+   for(firstLine = m_FirstLine;
+       firstLine && firstLine->GetLineNumber() < m_Selection.m_CursorA.y;
+       firstLine=firstLine->GetNextLine())
+      ;
+   if(!firstLine || firstLine->GetLineNumber() != m_Selection.m_CursorA.y)
+      return;
+
+
+   for(lastLine = m_FirstLine;
+       lastLine && lastLine->GetLineNumber() < m_Selection.m_CursorB.y;
+       lastLine=lastLine->GetNextLine())
+      ;
+   if(!lastLine || lastLine->GetLineNumber() != m_Selection.m_CursorB.y)
+      return;
+
+
+   // We now know that the two lines are different:
+
+   // First, delete what's left of this line:
+   MoveCursorTo(m_Selection.m_CursorA);
+   DeleteToEndOfLine();
+
+   wxLayoutLine *nextLine = firstLine->GetNextLine();
+   while(nextLine && nextLine != lastLine)
+      nextLine = nextLine->DeleteLine(false, this);
+
+   // Now nextLine = lastLine;
+   Delete(1); // This joins firstLine and nextLine
+   Delete(m_Selection.m_CursorB.x); // This deletes the first x
+   // positions
+
+   /// Recalculate:
+   firstLine->RecalculatePositions(1, this);
+}
 
 /// Starts highlighting the selection
 void
 wxLayoutList::StartHighlighting(wxDC &dc)
 {
 #if SHOW_SELECTIONS
 
 /// Starts highlighting the selection
 void
 wxLayoutList::StartHighlighting(wxDC &dc)
 {
 #if SHOW_SELECTIONS
-   dc.SetTextForeground(m_ColourBG);
-   dc.SetTextBackground(m_ColourFG);
+   dc.SetTextForeground(m_CurrentSetting.m_bg);
+   dc.SetTextBackground(m_CurrentSetting.m_fg);
+   dc.SetBackgroundMode(wxSOLID);
 #endif
 }
 
 #endif
 }
 
@@ -1722,8 +2301,9 @@ void
 wxLayoutList::EndHighlighting(wxDC &dc)
 {
 #if SHOW_SELECTIONS
 wxLayoutList::EndHighlighting(wxDC &dc)
 {
 #if SHOW_SELECTIONS
-   dc.SetTextForeground(m_ColourFG);
-   dc.SetTextBackground(m_ColourBG);
+   dc.SetTextForeground(m_CurrentSetting.m_fg);
+   dc.SetTextBackground(m_CurrentSetting.m_bg);
+   dc.SetBackgroundMode(wxTRANSPARENT);
 #endif
 }
 
 #endif
 }
 
@@ -1767,11 +2347,15 @@ wxLayoutList::Copy(const wxPoint &from,
    {
       // Extract objects from first line
       firstLine->Copy(llist, from.x);
    {
       // Extract objects from first line
       firstLine->Copy(llist, from.x);
+      llist->LineBreak();
       // Extract all lines between
       for(wxLayoutLine *line = firstLine->GetNextLine();
           line != lastLine;
           line = line->GetNextLine())
       // Extract all lines between
       for(wxLayoutLine *line = firstLine->GetNextLine();
           line != lastLine;
           line = line->GetNextLine())
+      {
          line->Copy(llist);
          line->Copy(llist);
+         llist->LineBreak();
+      }
       // Extract objects from last line
       lastLine->Copy(llist, 0, to.x);
    }
       // Extract objects from last line
       lastLine->Copy(llist, 0, to.x);
    }
@@ -1779,18 +2363,74 @@ wxLayoutList::Copy(const wxPoint &from,
 }
 
 wxLayoutList *
 }
 
 wxLayoutList *
-wxLayoutList::GetSelection(void)
+wxLayoutList::GetSelection(wxLayoutDataObject *wxlo, bool invalidate)
 {
    if(! m_Selection.m_valid)
 {
    if(! m_Selection.m_valid)
-      return NULL;
+   {
+      if(m_Selection.m_selecting)
+         EndSelection();
+      else
+         return NULL;
+   }
+
+   if(invalidate) m_Selection.m_valid = false;
+
+   wxLayoutList *llist = Copy( m_Selection.m_CursorA,
+                               m_Selection.m_CursorB );
+
+   if(llist && wxlo) // export as data object, too
+   {
+      wxString string;
+
+      wxLayoutExportObject *export;
+      wxLayoutExportStatus status(llist);
+      while((export = wxLayoutExport( &status, WXLO_EXPORT_AS_OBJECTS)) != NULL)
+      {
+         if(export->type == WXLO_EXPORT_EMPTYLINE)
+            ; //FIXME missing support for linebreaks in string format
+         else
+            export->content.object->Write(string);
+         delete export;
+      }
+
+      wxlo->SetData(string.c_str(), string.Length()+1);
+   }
+   return llist;
+}
+
 
 
-   return Copy( m_Selection.m_CursorA, m_Selection.m_CursorB );
+
+#define COPY_SI(what) if(si->what != -1) { m_CurrentSetting.what = si->what; fontChanged = TRUE; }
+
+void
+wxLayoutList::ApplyStyle(wxLayoutStyleInfo *si, wxDC &dc)
+{
+   bool fontChanged = FALSE;
+   COPY_SI(family);
+   COPY_SI(size);
+   COPY_SI(style);
+   COPY_SI(weight);
+   COPY_SI(underline);
+   if(fontChanged)
+      dc.SetFont( m_FontCache.GetFont(m_CurrentSetting) );
+
+   if(si->m_fg_valid)
+   {
+      m_CurrentSetting.m_fg = si->m_fg;
+      dc.SetTextForeground(m_CurrentSetting.m_fg);
+   }
+   if(si->m_bg_valid)
+   {
+      m_CurrentSetting.m_bg = si->m_bg;
+      dc.SetTextBackground(m_CurrentSetting.m_bg);
+   }
 }
 }
-   
+
+
 #ifdef WXLAYOUT_DEBUG
 
 void
 #ifdef WXLAYOUT_DEBUG
 
 void
-wxLayoutList::Debug(void) 
+wxLayoutList::Debug(void)
 {
    wxLayoutLine *line;
 
 {
    wxLayoutLine *line;
 
@@ -1804,7 +2444,7 @@ wxLayoutList::Debug(void)
 #endif
 
 
 #endif
 
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
    wxLayoutPrintout
 
 
    wxLayoutPrintout
 
@@ -1816,6 +2456,9 @@ wxLayoutPrintout::wxLayoutPrintout(wxLayoutList *llist,
 {
    m_llist = llist;
    m_title = title;
 {
    m_llist = llist;
    m_title = title;
+   // remove any highlighting which could interfere with printing:
+   m_llist->StartSelection();
+   m_llist->EndSelection();
 }
 
 wxLayoutPrintout::~wxLayoutPrintout()
 }
 
 wxLayoutPrintout::~wxLayoutPrintout()
@@ -1827,7 +2470,7 @@ wxLayoutPrintout::ScaleDC(wxDC *dc)
 {
    // The following bit is taken from the printing sample, let's see
    // whether it works for us.
 {
    // The following bit is taken from the printing sample, let's see
    // whether it works for us.
-   
+
    /* You might use THIS code to set the printer DC to ROUGHLY reflect
     * the screen text size. This page also draws lines of actual length 5cm
     * on the page.
    /* You might use THIS code to set the printer DC to ROUGHLY reflect
     * the screen text size. This page also draws lines of actual length 5cm
     * on the page.
@@ -1848,7 +2491,7 @@ wxLayoutPrintout::ScaleDC(wxDC *dc)
       ppiPrinterX = 72;
       ppiPrinterY = 72;
    }
       ppiPrinterX = 72;
       ppiPrinterY = 72;
    }
-  
+
   // This scales the DC so that the printout roughly represents the
   // the screen scaling. The text point size _should_ be the right size
   // but in fact is too small for some reason. This is a detail that will
   // This scales the DC so that the printout roughly represents the
   // the screen scaling. The text point size _should_ be the right size
   // but in fact is too small for some reason. This is a detail that will
@@ -1877,7 +2520,7 @@ bool wxLayoutPrintout::OnPrintPage(int page)
    wxDC *dc = GetDC();
 
    ScaleDC(dc);
    wxDC *dc = GetDC();
 
    ScaleDC(dc);
-   
+
    if (dc)
    {
       int top, bottom;
    if (dc)
    {
       int top, bottom;
@@ -1913,8 +2556,8 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom,
    // This is the length of the printable area.
    m_PrintoutHeight = m_PageHeight - (int) (m_PageHeight * 0.15);
    m_PrintoutHeight = (int)( m_PrintoutHeight / scale); // we want to use the real paper height
    // This is the length of the printable area.
    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 = 1 +
       (int)( m_llist->GetSize().y / (float)(m_PrintoutHeight));
 
    m_NumOfPages = 1 +
       (int)( m_llist->GetSize().y / (float)(m_PrintoutHeight));
 
@@ -1945,12 +2588,12 @@ wxLayoutPrintout::DrawHeader(wxDC &dc,
    const wxBrush& brush = dc.GetBrush();
    const wxPen&   pen = dc.GetPen();
    const wxFont&  font = dc.GetFont();
    const wxBrush& brush = dc.GetBrush();
    const wxPen&   pen = dc.GetPen();
    const wxFont&  font = dc.GetFont();
-   
+
    dc.SetBrush(*wxWHITE_BRUSH);
    dc.SetPen(wxPen(*wxBLACK,0,wxSOLID));
    dc.DrawRoundedRectangle(topleft.x,
                            topleft.y,bottomright.x-topleft.x,
    dc.SetBrush(*wxWHITE_BRUSH);
    dc.SetPen(wxPen(*wxBLACK,0,wxSOLID));
    dc.DrawRoundedRectangle(topleft.x,
                            topleft.y,bottomright.x-topleft.x,
-                           bottomright.y-topleft.y);  
+                           bottomright.y-topleft.y);
    dc.SetBrush(*wxBLACK_BRUSH);
    wxFont myfont = wxFont((WXLO_DEFAULTFONTSIZE*12)/10,
                           wxSWISS,wxNORMAL,wxBOLD,false,"Helvetica");
    dc.SetBrush(*wxBLACK_BRUSH);
    wxFont myfont = wxFont((WXLO_DEFAULTFONTSIZE*12)/10,
                           wxSWISS,wxNORMAL,wxBOLD,false,"Helvetica");
@@ -1973,3 +2616,18 @@ wxLayoutPrintout::DrawHeader(wxDC &dc,
 #endif
 
 
 #endif
 
 
+wxFont &
+wxFontCache::GetFont(int family, int size, int style, int weight,
+                     bool underline)
+{
+   for(wxFCEList::iterator i = m_FontList.begin();
+       i != m_FontList.end(); i++)
+      if( (**i).Matches(family, size, style, weight, underline) )
+         return (**i).GetFont();
+   // not found:
+   wxFontCacheEntry *fce = new wxFontCacheEntry(family, size, style,
+                                                weight, underline);
+   m_FontList.push_back(fce);
+   return fce->GetFont();
+}
+