]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/richedit/wxllist.cpp
Committing in .
[wxWidgets.git] / samples / richedit / wxllist.cpp
index 37880ef13fa50ded40a4fcfd82d238359d135c5e..3e696cde7ec8f3e41a68c1ee15709223c60ac56e 100644 (file)
@@ -1,7 +1,7 @@
 /*-*- c++ -*-********************************************************
  * wxllist: wxLayoutList, a layout engine for text and graphics     *
  *                                                                  *
 /*-*- c++ -*-********************************************************
  * wxllist: wxLayoutList, a layout engine for text and graphics     *
  *                                                                  *
- * (C) 1998-1999 by Karsten Ballüder (Ballueder@usa.net)            *
+ * (C) 1998-2000 by Karsten Ballüder (Ballueder@gmx.net)            *
  *                                                                  *
  * $Id$
  *******************************************************************/
  *                                                                  *
  * $Id$
  *******************************************************************/
@@ -25,7 +25,7 @@
 #   pragma implementation "wxllist.h"
 #endif
 
 #   pragma implementation "wxllist.h"
 #endif
 
-#include <wx/wxprec.h>
+#include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 #  pragma hdrstop
 
 #ifdef __BORLANDC__
 #  pragma hdrstop
@@ -34,6 +34,7 @@
 #include "Mpch.h"
 
 #ifdef M_BASEDIR
 #include "Mpch.h"
 
 #ifdef M_BASEDIR
+#   include "Mcommon.h"
 #   include "gui/wxllist.h"
 #   include "gui/wxlparser.h"
 #   define  SHOW_SELECTIONS 1
 #   include "gui/wxllist.h"
 #   include "gui/wxlparser.h"
 #   define  SHOW_SELECTIONS 1
 #endif
 
 #ifndef USE_PCH
 #endif
 
 #ifndef USE_PCH
-#   include <iostream.h>
+#if wxUSE_IOSTREAMH
+    #include <iostream.h>
+#else
+    #include <iostream>
+#endif
 
 #   include <wx/dc.h>
 #   include <wx/dcps.h>
 
 #   include <wx/dc.h>
 #   include <wx/dcps.h>
@@ -59,6 +64,7 @@
 
 #include <ctype.h>
 
 
 #include <ctype.h>
 
+
 /// This should never really get created
 #define   WXLLIST_TEMPFILE   "__wxllist.tmp"
 
 /// This should never really get created
 #define   WXLLIST_TEMPFILE   "__wxllist.tmp"
 
    {
       "invalid", "text", "cmd", "icon"
    };
    {
       "invalid", "text", "cmd", "icon"
    };
-   void
-   wxLayoutObject::Debug(void)
+   wxString
+   wxLayoutObject::DebugDump(void) const
    {
    {
-      WXLO_DEBUG(("%s",g_aTypeStrings[GetType()]));
+      wxString str;
+      str.Printf("%s",g_aTypeStrings[GetType()]);
+      return str;
    }
 #else
    }
 #else
-#  define   TypeString(t)        ""
-#  define   WXLO_DEBUG(x)
+#   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
 // 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
@@ -164,6 +173,7 @@ bool Contains(const wxRect &r, const wxPoint &p)
 //@}
 
 
 //@}
 
 
+static
 void ReadString(wxString &to, wxString &from)
 {
    to = "";
 void ReadString(wxString &to, wxString &from)
 {
    to = "";
@@ -186,7 +196,7 @@ wxLayoutObject::Read(wxString &istr)
 {
    wxString tmp;
    ReadString(tmp, istr);
 {
    wxString tmp;
    ReadString(tmp, istr);
-   int type = -1;
+   int type = WXLO_TYPE_INVALID;
    sscanf(tmp.c_str(),"%d", &type);
 
    switch(type)
    sscanf(tmp.c_str(),"%d", &type);
 
    switch(type)
@@ -328,6 +338,16 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
              heightOld = m_Height;
 #endif // 0
 
              heightOld = m_Height;
 #endif // 0
 
+#ifdef __WXDEBUG__
+   CoordType a,b,c,d,e,f;
+   dc.GetTextExtent("test ", &a, &b, &c);
+   dc.GetTextExtent("test", &d, &e, &f);
+   wxASSERT(a != d);
+   wxASSERT(b == e);
+   wxASSERT(c == f);
+   dc.GetTextExtent(" ", &d, &e, &f);
+   wxASSERT(a > 0);
+#endif
    dc.GetTextExtent(m_Text, &m_Width, &m_Height, &descent);
 
 #if 0
    dc.GetTextExtent(m_Text, &m_Width, &m_Height, &descent);
 
 #if 0
@@ -359,11 +379,14 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
 
 
 #ifdef WXLAYOUT_DEBUG
 
 
 #ifdef WXLAYOUT_DEBUG
-void
-wxLayoutObjectText::Debug(void)
+wxString
+wxLayoutObjectText::DebugDump(void) const
 {
 {
-   wxLayoutObject::Debug();
-   WXLO_DEBUG((" `%s`", m_Text.c_str()));
+   wxString str;
+   str = wxLayoutObject::DebugDump();
+   wxString str2;
+   str2.Printf(" `%s`", m_Text.c_str());
+   return str+str2;
 }
 #endif
 
 }
 #endif
 
@@ -375,7 +398,22 @@ wxLayoutObjectText::Debug(void)
 
 wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap const &icon)
 {
 
 wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap const &icon)
 {
+   if ( !icon.Ok() )
+   {
+      wxFAIL_MSG("invalid icon");
+
+      m_Icon = NULL;
+
+      return;
+   }
+
+#ifdef __WXMSW__
+   // FIXME ugly, ugly, ugly - but the only way to avoid slicing
+   m_Icon = icon.GetHBITMAP() ? new wxBitmap(icon)
+                              : new wxBitmap(wxBitmap((const wxBitmap &)icon));
+#else // !MSW
    m_Icon = new wxBitmap(icon);
    m_Icon = new wxBitmap(icon);
+#endif // MSW/!MSW
 }
 
 
 }
 
 
@@ -386,7 +424,7 @@ wxLayoutObjectIcon::Write(wxString &ostr)
 
    wxString file = wxGetTempFileName("wxloexport");
 
 
    wxString file = wxGetTempFileName("wxloexport");
 
-   ostr << WXLO_TYPE_ICON << '\n'
+   ostr << (int) WXLO_TYPE_ICON << '\n'
         << file << '\n';
    m_Icon->SaveFile(file, WXLO_BITMAP_FORMAT);
 }
         << file << '\n';
    m_Icon->SaveFile(file, WXLO_BITMAP_FORMAT);
 }
@@ -422,6 +460,8 @@ wxLayoutObjectIcon::Copy(void)
 wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap *icon)
 {
    m_Icon = icon;
 wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap *icon)
 {
    m_Icon = icon;
+   if(! m_Icon)
+      m_Icon = new wxBitmap;
 }
 
 void
 }
 
 void
@@ -498,12 +538,19 @@ wxLayoutObjectCmd::wxLayoutObjectCmd(int family, int size, int style, int
    m_StyleInfo = new wxLayoutStyleInfo(family, size,style,weight,underline,fg,bg);
 }
 
    m_StyleInfo = new wxLayoutStyleInfo(family, size,style,weight,underline,fg,bg);
 }
 
+wxLayoutObjectCmd::wxLayoutObjectCmd(const wxLayoutStyleInfo &si)
+
+{
+   m_StyleInfo = new wxLayoutStyleInfo;
+   *m_StyleInfo = si;
+}
+
 wxLayoutObject *
 wxLayoutObjectCmd::Copy(void)
 {
    wxLayoutObjectCmd *obj = new wxLayoutObjectCmd(
 wxLayoutObject *
 wxLayoutObjectCmd::Copy(void)
 {
    wxLayoutObjectCmd *obj = new wxLayoutObjectCmd(
-      m_StyleInfo->size,
       m_StyleInfo->family,
       m_StyleInfo->family,
+      m_StyleInfo->size,
       m_StyleInfo->style,
       m_StyleInfo->weight,
       m_StyleInfo->underline,
       m_StyleInfo->style,
       m_StyleInfo->weight,
       m_StyleInfo->underline,
@@ -518,25 +565,25 @@ wxLayoutObjectCmd::Copy(void)
 void
 wxLayoutObjectCmd::Write(wxString &ostr)
 {
 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';
+   ostr << (int) WXLO_TYPE_CMD << '\n'
+        << (int) m_StyleInfo->family << '\n'
+        << (int) m_StyleInfo->size << '\n'
+        << (int) m_StyleInfo->style << '\n'
+        << (int) m_StyleInfo->weight << '\n'
+        << (int) m_StyleInfo->underline << '\n'
+        << (int) m_StyleInfo->m_fg_valid << '\n'
+        << (int) m_StyleInfo->m_bg_valid << '\n';
    if(m_StyleInfo->m_fg_valid)
    {
    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';
+      ostr << (int) m_StyleInfo->m_fg.Red() << '\n'
+           << (int) m_StyleInfo->m_fg.Green() << '\n'
+           << (int) m_StyleInfo->m_fg.Blue() << '\n';
    }
    if(m_StyleInfo->m_bg_valid)
    {
    }
    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';
+      ostr << (int) m_StyleInfo->m_bg.Red() << '\n'
+           << (int) m_StyleInfo->m_bg.Green() << '\n'
+           << (int) m_StyleInfo->m_bg.Blue() << '\n';
    }
 }
 /* static */
    }
 }
 /* static */
@@ -547,10 +594,10 @@ wxLayoutObjectCmd::Read(wxString &istr)
 
    wxString tmp;
    ReadString(tmp, istr);
 
    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->family);
    ReadString(tmp, istr);
+   sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->size);
+   ReadString(tmp, istr);
    sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->style);
    ReadString(tmp, istr);
    sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->weight);
    sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->style);
    ReadString(tmp, istr);
    sscanf(tmp.c_str(),"%d", &obj->m_StyleInfo->weight);
@@ -626,14 +673,14 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
    m_Length = 0;
 
    m_updateLeft = -1;
    m_Length = 0;
 
    m_updateLeft = -1;
-   MarkDirty(0);
-
    m_Previous = prev;
    m_Next = NULL;
    m_Previous = prev;
    m_Next = NULL;
+   MarkDirty(0);
 
    m_LineNumber = 0;
    RecalculatePosition(llist);
 
 
    m_LineNumber = 0;
    RecalculatePosition(llist);
 
+   MarkDirty();
    if(m_Previous)
    {
       m_LineNumber = m_Previous->GetLineNumber() + 1;
    if(m_Previous)
    {
       m_LineNumber = m_Previous->GetLineNumber() + 1;
@@ -644,8 +691,7 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
    if(m_Next)
    {
       m_Next->m_Previous = this;
    if(m_Next)
    {
       m_Next->m_Previous = this;
-      m_Next->MoveLines(+1);
-      m_Next->RecalculatePositions(1,llist);
+      m_Next->ReNumber();
    }
 
    m_StyleInfo = llist->GetDefaultStyleInfo();
    }
 
    m_StyleInfo = llist->GetDefaultStyleInfo();
@@ -687,28 +733,6 @@ wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
    return m_Position;
 }
 
    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;
-
-//   WXLO_TRACE("RecalculatePositions()");
-   RecalculatePosition(llist);
-   if(m_Next)
-   {
-      if(recurse > 0)
-         m_Next->RecalculatePositions(--recurse, llist);
-      else if(pos != m_Position || m_Height != height)
-         m_Next->RecalculatePositions(0, llist);
-   }
-}
 
 wxLayoutObjectList::iterator
 wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const
 
 wxLayoutObjectList::iterator
 wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const
@@ -823,11 +847,6 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
 
    MarkDirty(xpos);
 
 
    MarkDirty(xpos);
 
-   // If we insert a command object, we need to recalculate all lines
-   // to update their styleinfo structure.
-   if(obj->GetType() == WXLO_TYPE_CMD)
-      MarkNextDirty(-1);
-
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i == NULLIT)
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i == NULLIT)
@@ -923,10 +942,6 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
          len = (**i).GetLength();
          m_Length -= len;
          npos -= len;
          len = (**i).GetLength();
          m_Length -= len;
          npos -= len;
-         // If we delete a command object, we need to recalculate all lines
-         // to update their styleinfo structure.
-         if((**i).GetType() == WXLO_TYPE_CMD)
-            MarkNextDirty(-1);
          m_ObjectList.erase(i);
       }
       else
          m_ObjectList.erase(i);
       }
       else
@@ -963,18 +978,6 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
    return npos;
 }
 
    return npos;
 }
 
-void
-wxLayoutLine::MarkNextDirty(int recurse)
-{
-   wxLayoutLine *line = GetNextLine();
-   while(line && (recurse == -1 || recurse >= 0))
-   {
-      line->MarkDirty();
-      line = line->GetNextLine();
-      if(recurse > 0) recurse --;
-   }
-}
-
 bool
 wxLayoutLine::DeleteWord(CoordType xpos)
 {
 bool
 wxLayoutLine::DeleteWord(CoordType xpos)
 {
@@ -1032,28 +1035,15 @@ wxLayoutLine::DeleteLine(bool update, wxLayoutList *llist)
    if(m_Previous)
        m_Previous->m_Next = m_Next;
 
    if(m_Previous)
        m_Previous->m_Next = m_Next;
 
-   wxLayoutLine *next = m_Next;
-   if ( next )
-   {
-      // get the line numbers right again
-      next->MoveLines(-1);
-   }
+   // get the line numbers right again
+   if ( update && m_Next)
+      m_Next->ReNumber();
 
 
-   if(update)
-   {
-      if ( next )
-         next->RecalculatePositions(1, llist);
-
-      /* We assume that if we have more than one object in the list,
-         this means that we have a command object, so we need to
-         update the following lines. */
-      if(m_ObjectList.size() > 1 ||
-         ( m_ObjectList.begin() != NULLIT &&
-           (**m_ObjectList.begin()).GetType() == WXLO_TYPE_CMD)
-         )
-         MarkNextDirty(-1);
-   }
+   MarkDirty();
 
 
+   // we can't use m_Next after "delete this", so we must save this pointer
+   // first
+   wxLayoutLine *next = m_Next;
    delete this;
 
    llist->DecNumLines();
    delete this;
 
    llist->DecNumLines();
@@ -1138,6 +1128,8 @@ wxLayoutLine::Layout(wxDC &dc,
 
    bool cursorFound = false;
 
 
    bool cursorFound = false;
 
+   RecalculatePosition(llist);
+   
    if(cursorPos)
    {
       *cursorPos = m_Position;
    if(cursorPos)
    {
       *cursorPos = m_Position;
@@ -1250,16 +1242,15 @@ wxLayoutLine::Layout(wxDC &dc,
    // tell next line about coordinate change
    if(m_Next && m_Height != heightOld)
    {
    // tell next line about coordinate change
    if(m_Next && m_Height != heightOld)
    {
-      // FIXME isn't this done in RecalculatePositions() below anyhow?
-      m_Next->RecalculatePositions(0, llist);
+      m_Next->MarkDirty();
    }
    }
-
+   
    // We need to check whether we found a valid cursor size:
    if(cursorPos && cursorSize)
    {
       // this might be the case if the cursor is at the end of the
       // line or on a command object:
    // We need to check whether we found a valid cursor size:
    if(cursorPos && cursorSize)
    {
       // 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(cursorSize->x < WXLO_MINIMUM_CURSOR_WIDTH)
       {
          CoordType width, height, descent;
          dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
       {
          CoordType width, height, descent;
          dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
@@ -1269,7 +1260,6 @@ 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();
 }
 
    MarkClean();
 }
 
@@ -1281,24 +1271,6 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
 
    MarkDirty(xpos);
 
 
    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)
-      {  // We were in first line, need to link in new empty line
-         // before this.
-         prev->m_Next = this;
-         m_Previous = prev;
-         m_Previous->m_Height = 0; // this is a wild guess
-      }
-      if(m_Next)
-         m_Next->RecalculatePositions(1, llist);
-      return m_Previous;
-   }
-
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i == NULLIT)
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i == NULLIT)
@@ -1308,7 +1280,9 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
 
    wxLayoutLine *newLine = new wxLayoutLine(this, llist);
    // split object at i:
 
    wxLayoutLine *newLine = new wxLayoutLine(this, llist);
    // split object at i:
-   if((**i).GetType() == WXLO_TYPE_TEXT && offset != 0)
+   if((**i).GetType() == WXLO_TYPE_TEXT
+      && offset != 0
+      && offset != (**i).GetLength() )
    {
       wxString left, right;
       wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
    {
       wxString left, right;
       wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
@@ -1335,10 +1309,144 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
       m_ObjectList.remove(i); // remove without deleting it
    }
    if(m_Next)
       m_ObjectList.remove(i); // remove without deleting it
    }
    if(m_Next)
-      m_Next->RecalculatePositions(2, llist);
+      m_Next->MarkDirty();
    return newLine;
 }
 
    return newLine;
 }
 
+bool
+wxLayoutLine::Wrap(CoordType wrapmargin, wxLayoutList *llist)
+{
+   if(GetLength() < wrapmargin)
+      return FALSE; // nothing to do
+   
+   // find the object which covers the wrapmargin:
+   CoordType offset;
+   wxLOiterator i = FindObject(wrapmargin, &offset);
+   wxCHECK_MSG( i != NULLIT, FALSE, "Cannot find object covering wrapmargin.");
+   
+   // from this object on, the rest of the line must be copied to the
+   // next one:
+   wxLOiterator copyObject = NULLIT;
+   // if we split a text-object, we must pre-pend some text to the
+   // next line later on, remember it here:
+   wxString prependText = "";
+   // we might need to adjust the cursor position later, so remember it
+   size_t xpos = llist->GetCursorPos().x;
+   // by how much did we shorten the current line:
+   size_t shorter = 0;
+   // remember cursor location of object
+   size_t objectCursorPos = 0;
+   
+   size_t breakpos = offset;
+
+   if( (**i).GetType() != WXLO_TYPE_TEXT )
+   {
+      // break before a non-text object
+      copyObject = i;
+   }
+   else
+   {
+      bool foundSpace = FALSE;
+      do
+      {
+//         while(i != NULLIT && (**i).GetType() != WXLO_TYPE_TEXT)
+//            i--;
+         // try to find a suitable place to split the object:
+         wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i;
+         if((**i).GetType() == WXLO_TYPE_TEXT
+            && tobj->GetText().Length() >= breakpos)
+         {
+            do
+            {
+               foundSpace = isspace(tobj->GetText()[breakpos]) != 0;
+               if ( foundSpace )
+                  break;
+            }
+            while ( breakpos-- > 0 );
+         }
+         else
+         {
+            breakpos = 0;
+         }
+
+         if(! foundSpace) // breakpos == 0!
+         {
+            if(i == m_ObjectList.begin())
+               return FALSE; // could not break line
+            else
+            {
+               i--;
+               while(i != m_ObjectList.begin()
+                     && (**i).GetType() != WXLO_TYPE_TEXT )
+               {
+                  i--;
+               }
+               breakpos = (**i).GetLength();
+            }
+         }
+      }while(! foundSpace);
+      // before we actually break the object, we need to know at which
+      // cursorposition it starts, so we can restore the cursor if needed:
+      if( this == llist->GetCursorLine() && xpos >= breakpos )
+      {
+         for(wxLOiterator j = m_ObjectList.begin();
+             j != NULLIT && j != i; j++)
+            objectCursorPos += (**j).GetLength();
+      }
+      // now we know where to break it:
+      wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i;
+      shorter = tobj->GetLength() - breakpos;
+      // remember text to copy from this object
+      prependText = tobj->GetText().Mid(breakpos+1);
+      tobj->SetText(tobj->GetText().Left(breakpos));
+      // copy every following object:
+      copyObject = i; copyObject ++;
+   }
+
+   // make sure there is an empty m_Next line:
+   (void) new wxLayoutLine(this, llist);
+   wxASSERT(m_Next);
+   // We need to move this and all following objects to the next
+   // line. Starting from the end of line, to keep the order right. 
+   if(copyObject != NULLIT)
+   {
+      wxLOiterator j;
+      for(j = m_ObjectList.tail(); j != copyObject; j--)
+         m_Next->Prepend(*j);
+      m_Next->Prepend(*copyObject);
+      // and now remove them from this list:
+      while( copyObject != m_ObjectList.end() )
+      {
+         shorter += (**copyObject).GetLength();
+         m_ObjectList.remove(copyObject); // remove without deleting it
+      }
+   }
+   m_Length -= shorter;
+   
+   if(prependText.Length() > 0)
+      m_Next->Insert(0, prependText);
+
+   // do we need to adjust the cursor position?
+   if( this == llist->GetCursorLine() && xpos >= breakpos)
+   {
+      xpos = objectCursorPos + (xpos - objectCursorPos - breakpos -
+                                ((xpos > breakpos) ? 1 : 0 ));
+      wxASSERT(xpos >= 0);
+      llist->MoveCursorTo( wxPoint( xpos, m_Next->GetLineNumber()) );
+   }
+   return TRUE; // we wrapped the line
+}
+
+void
+wxLayoutLine::ReNumber(void)
+{
+   CoordType lineNo = m_Previous ? m_Previous->m_LineNumber+1 : 0;
+   m_LineNumber = lineNo++;
+   
+   for(wxLayoutLine *next = GetNextLine();
+       next; next = next->GetNextLine())
+      next->m_LineNumber = lineNo++;
+}
 
 void
 wxLayoutLine::MergeNextLine(wxLayoutList *llist)
 
 void
 wxLayoutLine::MergeNextLine(wxLayoutList *llist)
@@ -1380,7 +1488,7 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
    SetNext(nextLine);
    if ( nextLine )
    {
    SetNext(nextLine);
    if ( nextLine )
    {
-      nextLine->MoveLines(-1);
+      nextLine->ReNumber();
    }
    else
    {
    }
    else
    {
@@ -1414,7 +1522,7 @@ wxLayoutLine::GetWrapPosition(CoordType column)
       {
          do
          {
       {
          do
          {
-            if( isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
+            if(isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
                return column;
             else
             {
                return column;
             else
             {
@@ -1443,25 +1551,23 @@ wxLayoutLine::GetWrapPosition(CoordType column)
       i++;
    }
    if(i == NULLIT) return -1;  //why should this happen?
       i++;
    }
    if(i == NULLIT) return -1;  //why should this happen?
+
+   // now we are behind the one long text object and need to find the
+   // first space in it
+   for(offset = 0; offset < (**i).GetLength(); offset++)
+      if( isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
+      {
+         return pos+offset;
+      }
    pos += (**i).GetLength();
    pos += (**i).GetLength();
-   i++;
-   while(i != NULLIT && (**i).GetType() != WXLO_TYPE_TEXT)
-   {
-            pos += (**i).GetLength();
-            i++;
-   }
-   if(i == NULLIT) return -1;  //this is possible, if there is only one text object
-   // now we are at the second text object:
-   pos -= (**i).GetLength();
-   return pos; // in front of it
+   return pos;
 }
 
 
 #ifdef WXLAYOUT_DEBUG
 void
 }
 
 
 #ifdef WXLAYOUT_DEBUG
 void
-wxLayoutLine::Debug(void)
+wxLayoutLine::Debug(void) const
 {
 {
-   wxString tmp;
    wxPoint pos = GetPosition();
    WXLO_DEBUG(("Line %ld, Pos (%ld,%ld), Height %ld, BL %ld, Font: %d",
                (long int) GetLineNumber(),
    wxPoint pos = GetPosition();
    WXLO_DEBUG(("Line %ld, Pos (%ld,%ld), Height %ld, BL %ld, Font: %d",
                (long int) GetLineNumber(),
@@ -1470,7 +1576,9 @@ wxLayoutLine::Debug(void)
                (long int) m_BaseLine,
                (int) m_StyleInfo.family));
    if(m_ObjectList.begin() != NULLIT)
                (long int) m_BaseLine,
                (int) m_StyleInfo.family));
    if(m_ObjectList.begin() != NULLIT)
-      (**m_ObjectList.begin()).Debug();
+   {
+      WXLO_DEBUG(((**m_ObjectList.begin()).DebugDump().c_str()));
+   }
 
 }
 #endif
 
 }
 #endif
@@ -1554,12 +1662,15 @@ wxLayoutList::wxLayoutList()
 
    m_numLines = 0;
    m_FirstLine = NULL;
 
    m_numLines = 0;
    m_FirstLine = NULL;
+   SetAutoFormatting(TRUE);
+   ForceTotalLayout(TRUE);  // for the first time, do all
    InvalidateUpdateRect();
    Clear();
 }
 
 wxLayoutList::~wxLayoutList()
 {
    InvalidateUpdateRect();
    Clear();
 }
 
 wxLayoutList::~wxLayoutList()
 {
+   SetAutoFormatting(FALSE);
    InternalClear();
    Empty();
    m_FirstLine->DeleteLine(false, this);
    InternalClear();
    Empty();
    m_FirstLine->DeleteLine(false, this);
@@ -1603,6 +1714,39 @@ wxLayoutList::InternalClear(void)
    m_CursorStyleInfo = m_DefaultStyleInfo;
 }
 
    m_CursorStyleInfo = m_DefaultStyleInfo;
 }
 
+void
+wxLayoutList::Read(wxString &istr)
+{
+   /* In order to handle input of formatted string "nicely", we need
+      to restore our current font settings after the string. So first
+      of all, we create a StyleInfo structure with our current
+      settings. */
+   wxLayoutStyleInfo current_si = GetStyleInfo();
+
+   while(istr.Length())
+   {
+      // check for a linebreak:
+      wxString tmp;
+      tmp = istr.BeforeFirst('\n');
+      int type = WXLO_TYPE_INVALID;
+      sscanf(tmp.c_str(),"%d", &type);
+      if(type == WXLO_TYPE_LINEBREAK)
+      {
+         LineBreak();
+         istr = istr.AfterFirst('\n');
+      }
+      else
+      {
+         wxLayoutObject *obj = wxLayoutObject::Read(istr);
+         if(obj)
+            Insert(obj);
+      }
+   }
+   /* Now we use the current_si to restore our last font settings: */
+   Insert(new wxLayoutObjectCmd(current_si));
+}
+
+
 void
 wxLayoutList::SetFont(int family, int size, int style, int weight,
                       int underline, wxColour *fg,
 void
 wxLayoutList::SetFont(int family, int size, int style, int weight,
                       int underline, wxColour *fg,
@@ -1748,12 +1892,13 @@ wxLayoutList::MoveCursorVertically(int n)
       {
          n--;
          m_CursorPos.y ++;
       {
          n--;
          m_CursorPos.y ++;
+         last = m_CursorLine;
          m_CursorLine = m_CursorLine->GetNextLine();
       }
       if(! m_CursorLine)
       {
          m_CursorLine = last;
          m_CursorLine = m_CursorLine->GetNextLine();
       }
       if(! m_CursorLine)
       {
          m_CursorLine = last;
-         m_CursorPos.y ++;
+         m_CursorPos.y --;
          rc = false;
       }
       else
          rc = false;
       }
       else
@@ -1985,14 +2130,16 @@ wxLayoutList::Insert(wxString const &text)
 
    AddCursorPosToUpdateRect();
 
 
    AddCursorPosToUpdateRect();
 
+   wxASSERT(m_CursorLine->GetLength() >= m_CursorPos.x);
+
    if ( !m_CursorLine->Insert(m_CursorPos.x, text) )
       return false;
    if ( !m_CursorLine->Insert(m_CursorPos.x, text) )
       return false;
-
    m_CursorPos.x += text.Length();
 
    m_movedCursor = true;
 
    m_CursorPos.x += text.Length();
 
    m_movedCursor = true;
 
-   m_CursorLine->RecalculatePositions(0, this);
+   if(m_AutoFormat)
+      m_CursorLine->MarkDirty();
 
    return true;
 }
 
    return true;
 }
@@ -2011,7 +2158,8 @@ wxLayoutList::Insert(wxLayoutObject *obj)
    m_CursorPos.x += obj->GetLength();
    m_movedCursor = true;
 
    m_CursorPos.x += obj->GetLength();
    m_movedCursor = true;
 
-   m_CursorLine->RecalculatePositions(0, this);
+   if(m_AutoFormat)
+      m_CursorLine->MarkDirty();
 
    return true;
 }
 
    return true;
 }
@@ -2052,8 +2200,7 @@ wxLayoutList::LineBreak(void)
    m_CursorLine = m_CursorLine->Break(m_CursorPos.x, this);
    if(m_CursorLine->GetPreviousLine() == NULL)
       m_FirstLine = m_CursorLine;
    m_CursorLine = m_CursorLine->Break(m_CursorPos.x, this);
    if(m_CursorLine->GetPreviousLine() == NULL)
       m_FirstLine = m_CursorLine;
-   if(m_CursorPos.x > 0)
-      m_CursorPos.y++;
+   m_CursorPos.y++;
    m_CursorPos.x = 0;
 
    // The following code will produce a height which is guaranteed to
    m_CursorPos.x = 0;
 
    // The following code will produce a height which is guaranteed to
@@ -2077,29 +2224,22 @@ wxLayoutList::LineBreak(void)
 bool
 wxLayoutList::WrapLine(CoordType column)
 {
 bool
 wxLayoutList::WrapLine(CoordType column)
 {
-   if(m_CursorPos.x <= column || column < 1)
-      return false; // do nothing yet
-   else
-   {
-      CoordType xpos = m_CursorLine->GetWrapPosition(column);
-      if(xpos == -1)
-         return false; // cannot break line
-      //else:
-      CoordType newpos = m_CursorPos.x - xpos - 1;
-      m_CursorPos.x = xpos;
-
-      AddCursorPosToUpdateRect();
-
-      LineBreak();
-      Delete(1); // delete the space
-      m_CursorPos.x = newpos;
-
-      m_CursorLine->RecalculatePositions(1, this);
-
-      m_movedCursor = true;
+   return m_CursorLine->Wrap(column, this);
+}
 
 
-      return true;
+bool
+wxLayoutList::WrapAll(CoordType column)
+{
+   wxLayoutLine *line = m_FirstLine;
+   if(! line)
+      return FALSE;
+   bool rc = TRUE;
+   while(line && rc)
+   {
+      rc &= line->Wrap(column, this);
+      line = line->GetNextLine();
    }
    }
+   return rc;
 }
 
 bool
 }
 
 bool
@@ -2197,7 +2337,8 @@ wxLayoutList::DeleteLines(int n)
       {  // we cannot delete this line, but we can clear it
          MoveCursorToBeginOfLine();
          DeleteToEndOfLine();
       {  // we cannot delete this line, but we can clear it
          MoveCursorToBeginOfLine();
          DeleteToEndOfLine();
-         m_CursorLine->RecalculatePositions(2, this);
+         if(m_AutoFormat)
+            m_CursorLine->MarkDirty();
          return n-1;
       }
       //else:
          return n-1;
       }
       //else:
@@ -2208,13 +2349,16 @@ wxLayoutList::DeleteLines(int n)
       wxASSERT(m_FirstLine);
       wxASSERT(m_CursorLine);
    }
       wxASSERT(m_FirstLine);
       wxASSERT(m_CursorLine);
    }
-   m_CursorLine->RecalculatePositions(2, this);
+   if(m_AutoFormat)
+      m_CursorLine->MarkDirty();
    return n;
 }
 
 void
 wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
 {
    return n;
 }
 
 void
 wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
 {
+   if(! m_AutoFormat)
+      return;
    wxLayoutLine *line = m_FirstLine;
 
    // first, make sure everything is calculated - this might not be
    wxLayoutLine *line = m_FirstLine;
 
    // first, make sure everything is calculated - this might not be
@@ -2230,7 +2374,7 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
 }
 
 wxPoint
 }
 
 wxPoint
-wxLayoutList::GetCursorScreenPos(wxDC &dc)
+wxLayoutList::GetCursorScreenPos(void) const
 {
    return m_CursorScreenPos;
 }
 {
    return m_CursorScreenPos;
 }
@@ -2247,18 +2391,47 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
    // needed, optimise it later
    ApplyStyle(m_DefaultStyleInfo, dc);
 
    // needed, optimise it later
    ApplyStyle(m_DefaultStyleInfo, dc);
 
-   // This one we always Layout() to get the current cursor
-   // coordinates on the screen:
-   m_CursorLine->MarkDirty();
-   bool wasDirty = false;
+   
+   if(m_ReLayoutAll)
+   {
+      forceAll = TRUE;
+      bottom = -1;
+   }
+   ForceTotalLayout(FALSE);
+   
+
+   // If one line was dirty, we need to re-calculate all
+   // following lines, too.
+   bool wasDirty = forceAll;
+   // we need to layout until we reach at least the cursor line,
+   // otherwise we won't be able to scroll to it
+   bool cursorReached = false;
    wxLayoutLine *line = m_FirstLine;
    while(line)
    {
       if(! wasDirty)
          ApplyStyle(line->GetStyleInfo(), dc);
    wxLayoutLine *line = m_FirstLine;
    while(line)
    {
       if(! wasDirty)
          ApplyStyle(line->GetStyleInfo(), dc);
-      if(forceAll || line->IsDirty()
-         || (cpos && line->GetLineNumber() == cpos->y))
+      if(
+         // if any previous line was dirty, we need to layout all
+         // following lines:   
+         wasDirty
+         // go on until we find the cursorline
+         || ! cursorReached
+         // layout dirty lines:
+         || line->IsDirty()
+         // always layout the cursor line toupdate the cursor
+         // position and size:
+         || line == m_CursorLine
+         // or if it's the line we are asked to look for:
+         || (cpos && line->GetLineNumber() == cpos->y) 
+         // layout at least the desired region:
+         || (bottom == -1 )
+         || (line->GetPosition().y <= bottom)
+         )
       {
       {
+         if(line->IsDirty())
+            wasDirty = true;
+         
          // The following Layout() calls will update our
          // m_CurrentStyleInfo if needed.
          if(line == m_CursorLine)
          // The following Layout() calls will update our
          // m_CurrentStyleInfo if needed.
          if(line == m_CursorLine)
@@ -2275,27 +2448,30 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
                if ( csize )
                   *csize = m_CursorSize;
             }
                if ( csize )
                   *csize = m_CursorSize;
             }
-         }
+            cursorReached = TRUE;
+         } 
          else
          else
+         {
             if(cpos && line->GetLineNumber() == cpos->y)
             if(cpos && line->GetLineNumber() == cpos->y)
+            {
                line->Layout(dc, this,
                             cpos,
                             csize, NULL, cpos->x);
                line->Layout(dc, this,
                             cpos,
                             csize, NULL, cpos->x);
-         else
-            line->Layout(dc, this);
-         // little condition to speed up redrawing:
-         if(bottom != -1 && line->GetPosition().y > bottom)
-            break;
-         wasDirty = true;
+               cursorReached = TRUE;
+            }
+            else
+               line->Layout(dc, this);
+         }
       }
       }
-      line->RecalculatePositions(1, this);
       line = line->GetNextLine();
    }
    
       line = line->GetNextLine();
    }
    
+#ifndef WXLAYOUT_USE_CARET
    // 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));
    // 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 // WXLAYOUT_USE_CARET
    AddCursorPosToUpdateRect();
 }
 
    AddCursorPosToUpdateRect();
 }
 
@@ -2311,7 +2487,8 @@ void
 wxLayoutList::Draw(wxDC &dc,
                    wxPoint const &offset,
                    CoordType top,
 wxLayoutList::Draw(wxDC &dc,
                    wxPoint const &offset,
                    CoordType top,
-                   CoordType bottom)
+                   CoordType bottom,
+                   bool clipStrictly)
 {
    wxLayoutLine *line = m_FirstLine;
 
 {
    wxLayoutLine *line = m_FirstLine;
 
@@ -2332,29 +2509,27 @@ wxLayoutList::Draw(wxDC &dc,
       m_Selection.m_discarded = false;
    }
 
       m_Selection.m_discarded = false;
    }
 
-   /* We need to re-layout all dirty lines to update styleinfos
-      etc. However, somehow we don't find all dirty lines... */
-   Layout(dc); //,-1,true); //FIXME
+   /* This call to Layout() will re-calculate and update all lines
+      marked as dirty.
+   */
+   Layout(dc, bottom);
+   
    ApplyStyle(m_DefaultStyleInfo, dc);
    wxBrush brush(m_CurrentStyleInfo.m_bg, wxSOLID);
    dc.SetBrush(brush);
    dc.SetBackgroundMode(wxTRANSPARENT);
 
    ApplyStyle(m_DefaultStyleInfo, dc);
    wxBrush brush(m_CurrentStyleInfo.m_bg, wxSOLID);
    dc.SetBrush(brush);
    dc.SetBackgroundMode(wxTRANSPARENT);
 
-   bool style_set = false;
    while(line)
    {
       // only draw if between top and bottom:
       if((top == -1 ||
           line->GetPosition().y + line->GetHeight() > top))
       {
    while(line)
    {
       // only draw if between top and bottom:
       if((top == -1 ||
           line->GetPosition().y + line->GetHeight() > top))
       {
-//         if(! style_set)
-         {
-            ApplyStyle(line->GetStyleInfo(), dc);
-            style_set = true;
-         }
+         ApplyStyle(line->GetStyleInfo(), dc);
          // little condition to speed up redrawing:
          // little condition to speed up redrawing:
-         if(bottom != -1
-            && line->GetPosition().y+line->GetHeight() >= bottom)
+         if( bottom != -1
+             && line->GetPosition().y
+                +(clipStrictly ? line->GetHeight() : 0) >= bottom)
             break;
          line->Draw(dc, this, offset);
       }
             break;
          line->Draw(dc, this, offset);
       }
@@ -2362,7 +2537,7 @@ wxLayoutList::Draw(wxDC &dc,
    }
    InvalidateUpdateRect();
 
    }
    InvalidateUpdateRect();
 
-   WXLO_DEBUG(("Selection is %s : l%d,%ld/%ld,%ld",
+   WXLO_DEBUG(("Selection is %s : %ld,%ld/%ld,%ld",
                m_Selection.m_valid ? "valid" : "invalid",
                m_Selection.m_CursorA.x, m_Selection.m_CursorA.y,
                m_Selection.m_CursorB.x, m_Selection.m_CursorB.y));
                m_Selection.m_valid ? "valid" : "invalid",
                m_Selection.m_CursorA.x, m_Selection.m_CursorA.y,
                m_Selection.m_CursorB.x, m_Selection.m_CursorB.y));
@@ -2389,10 +2564,10 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
       line = line->GetNextLine();
    }
 
       line = line->GetNextLine();
    }
 
+   bool didFind = line != NULL;
+
    if ( !line )
    {
    if ( !line )
    {
-      if ( found )
-          *found = false;
       // use the last line:
       line = lastline;
    }
       // use the last line:
       line = lastline;
    }
@@ -2401,13 +2576,27 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
        cursorPos->y = line->GetLineNumber();
 
    bool foundinline = true;
        cursorPos->y = line->GetLineNumber();
 
    bool foundinline = true;
+   long cx = 0;
+
    // Now, find the object in the line:
    // Now, find the object in the line:
-   wxLOiterator i = line->FindObjectScreen(dc, this,
+   wxLOiterator i;
+
+   if (cursorPos)
+   {
+     i = line->FindObjectScreen(dc, this,
                                            pos.x,
                                            pos.x,
-                                           cursorPos ? &cursorPos->x : NULL,
+                                           &cx,
                                            &foundinline);
                                            &foundinline);
-   if(found)
-      *found = *found && foundinline;
+     cursorPos->x = cx;
+   }
+   else
+     i = line->FindObjectScreen(dc, this,
+                                           pos.x,
+                                           NULL,
+                                           &foundinline);
+   if ( found )
+      *found = didFind && foundinline;
+
    return (i == NULLIT) ? NULL : *i;
 
 }
    return (i == NULLIT) ? NULL : *i;
 
 }
@@ -2463,7 +2652,7 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
 #ifdef WXLAYOUT_DEBUG
    WXLO_DEBUG(("Drawing cursor (%ld,%ld) at %ld,%ld, size %ld,%ld, line: %ld, len %ld",
                (long)m_CursorPos.x, (long)m_CursorPos.y,
 #ifdef WXLAYOUT_DEBUG
    WXLO_DEBUG(("Drawing cursor (%ld,%ld) at %ld,%ld, size %ld,%ld, line: %ld, len %ld",
                (long)m_CursorPos.x, (long)m_CursorPos.y,
-               (long)coords.x, (long)coords.y,
+               (long)coords.x, (long)coords.y, 
                (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()));
@@ -2474,6 +2663,8 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
 #ifdef WXLAYOUT_USE_CARET
    m_caret->Move(coords);
 #else // !WXLAYOUT_USE_CARET
 #ifdef WXLAYOUT_USE_CARET
    m_caret->Move(coords);
 #else // !WXLAYOUT_USE_CARET
+
+   wxASSERT(m_CursorSize.x >= WXLO_MINIMUM_CURSOR_WIDTH);
    dc.SetBrush(*wxWHITE_BRUSH);
    //FIXME: wxGTK XOR is borken at the moment!!!dc.SetLogicalFunction(wxXOR);
    dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
    dc.SetBrush(*wxWHITE_BRUSH);
    //FIXME: wxGTK XOR is borken at the moment!!!dc.SetLogicalFunction(wxXOR);
    dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
@@ -2483,7 +2674,8 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
       dc.DrawRectangle(coords.x, coords.y,
                        m_CursorSize.x, m_CursorSize.y);
       SetUpdateRect(coords.x, coords.y);
       dc.DrawRectangle(coords.x, coords.y,
                        m_CursorSize.x, m_CursorSize.y);
       SetUpdateRect(coords.x, coords.y);
-      SetUpdateRect(coords.x+m_CursorSize.x, coords.y+m_CursorSize.y);
+      SetUpdateRect(coords.x+m_CursorSize.x,
+                    coords.y+m_CursorSize.y);
    }
    else
    {
    }
    else
    {
@@ -2539,17 +2731,17 @@ wxLayoutList::ContinueSelection(const wxPoint& cposOrig, const wxPoint& spos)
    wxASSERT(m_Selection.m_valid == false);
    WXLO_DEBUG(("Continuing selection at %ld/%ld", cpos.x, cpos.y));
 
    wxASSERT(m_Selection.m_valid == false);
    WXLO_DEBUG(("Continuing selection at %ld/%ld", cpos.x, cpos.y));
 
-   if ( m_Selection.m_CursorB <= cpos )
-   {
-      m_Selection.m_ScreenB = spos;
-      m_Selection.m_CursorB = cpos;
-   }
-   else
-   {
-      m_Selection.m_ScreenA = spos;
-      m_Selection.m_CursorA = cpos;
-   }
+   m_Selection.m_ScreenB = spos;
+   m_Selection.m_CursorB = cpos;
+}
 
 
+void
+wxLayoutList::EndSelection(const wxPoint& cposOrig, const wxPoint& spos)
+{
+   wxPoint cpos(cposOrig);
+   if(cpos.x == -1) cpos = m_CursorPos;
+   ContinueSelection(cpos, spos);
+   WXLO_DEBUG(("Ending selection at %ld/%ld", cpos.x, cpos.y));
    // 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 )
    {
@@ -2562,18 +2754,12 @@ wxLayoutList::ContinueSelection(const wxPoint& cposOrig, const wxPoint& spos)
       m_Selection.m_ScreenB = m_Selection.m_ScreenA;
       m_Selection.m_ScreenA = help;
    }
       m_Selection.m_ScreenB = m_Selection.m_ScreenA;
       m_Selection.m_ScreenA = help;
    }
-}
-
-void
-wxLayoutList::EndSelection(const wxPoint& cposOrig, const wxPoint& spos)
-{
-   wxPoint cpos(cposOrig);
-   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;
+   /// In case we just clicked somewhere, the selection will have zero 
+   /// size, so we discard it immediately.
+   if(m_Selection.m_CursorA == m_Selection.m_CursorB)
+      DiscardSelection();
 }
 
 void
 }
 
 void
@@ -2599,7 +2785,12 @@ wxLayoutList::IsSelected(const wxPoint &cursor) const
    if ( !HasSelection() )
       return false;
 
    if ( !HasSelection() )
       return false;
 
-   return m_Selection.m_CursorA <= cursor && cursor <= m_Selection.m_CursorB;
+   return (
+      (m_Selection.m_CursorA <= cursor
+       && cursor <= m_Selection.m_CursorB) 
+      || (m_Selection.m_CursorB <= cursor
+          && cursor <= m_Selection.m_CursorA)
+      );
 }
 
 
 }
 
 
@@ -2619,7 +2810,10 @@ wxLayoutList::IsSelected(const wxLayoutLine *line, CoordType *from,
       return 0;
 
    CoordType y = line->GetLineNumber();
       return 0;
 
    CoordType y = line->GetLineNumber();
-   if(m_Selection.m_CursorA.y < y && m_Selection.m_CursorB.y > y)
+   if(
+      (m_Selection.m_CursorA.y < y && m_Selection.m_CursorB.y > y)
+      || (m_Selection.m_CursorB.y < y && m_Selection.m_CursorA.y > y)
+      )
       return 1;
    else if(m_Selection.m_CursorA.y == y)
    {
       return 1;
    else if(m_Selection.m_CursorA.y == y)
    {
@@ -2627,7 +2821,18 @@ wxLayoutList::IsSelected(const wxLayoutLine *line, CoordType *from,
       if(m_Selection.m_CursorB.y == y)
          *to = m_Selection.m_CursorB.x;
       else
       if(m_Selection.m_CursorB.y == y)
          *to = m_Selection.m_CursorB.x;
       else
-         *to = line->GetLength();
+      {
+         if(m_Selection.m_CursorB > m_Selection.m_CursorA)
+            *to = line->GetLength();
+         else
+            *to = 0;
+      }
+      if(*to < *from)
+      {
+         CoordType help = *to;
+         *to = *from;
+         *from = help;
+      }
       return -1;
    }
    else if(m_Selection.m_CursorB.y == y)
       return -1;
    }
    else if(m_Selection.m_CursorB.y == y)
@@ -2636,7 +2841,18 @@ wxLayoutList::IsSelected(const wxLayoutLine *line, CoordType *from,
       if(m_Selection.m_CursorA.y == y)
          *from = m_Selection.m_CursorA.x;
       else
       if(m_Selection.m_CursorA.y == y)
          *from = m_Selection.m_CursorA.x;
       else
-         *from = 0;
+      {
+         if(m_Selection.m_CursorB > m_Selection.m_CursorA)
+            *from = 0;
+         else
+            *from = line->GetLength();
+      }
+      if(*to < *from)
+      {
+         CoordType help = *to;
+         *to = *from;
+         *from = help;
+      }
       return -1;
    }
    else
       return -1;
    }
    else
@@ -2664,7 +2880,10 @@ wxLayoutList::DeleteSelection(void)
    wxLayoutLine
       * firstLine = GetLine(m_Selection.m_CursorA.y),
       * lastLine = GetLine(m_Selection.m_CursorB.y);
    wxLayoutLine
       * firstLine = GetLine(m_Selection.m_CursorA.y),
       * lastLine = GetLine(m_Selection.m_CursorB.y);
-
+   // be a bit paranoid:
+   if(! firstLine || ! lastLine)
+      return;
+   
    // First, delete what's left of this line:
    MoveCursorTo(m_Selection.m_CursorA);
    DeleteToEndOfLine();
    // First, delete what's left of this line:
    MoveCursorTo(m_Selection.m_CursorA);
    DeleteToEndOfLine();
@@ -2681,7 +2900,7 @@ wxLayoutList::DeleteSelection(void)
    // Recalculate the line positions and numbers but notice that firstLine
    // might not exist any more - it could be deleted by Delete(1) above
    wxLayoutLine *firstLine2 = prevLine ? prevLine->GetNextLine() : m_FirstLine;
    // Recalculate the line positions and numbers but notice that firstLine
    // might not exist any more - it could be deleted by Delete(1) above
    wxLayoutLine *firstLine2 = prevLine ? prevLine->GetNextLine() : m_FirstLine;
-   firstLine2->RecalculatePositions(1, this);
+   firstLine2->MarkDirty();
 }
 
 /// Starts highlighting the selection
 }
 
 /// Starts highlighting the selection
@@ -2707,6 +2926,37 @@ wxLayoutList::EndHighlighting(wxDC &dc)
 }
 
 
 }
 
 
+wxLayoutLine *
+wxLayoutList::GetLine(CoordType index) const
+{
+   wxASSERT_MSG( (0 <= index) && (index < (CoordType)m_numLines),
+                 "invalid index" );
+
+   wxLayoutLine *line;
+   CoordType n = index;
+#ifdef DEBUG
+   CoordType lineNo = 0;
+#endif
+       
+   for ( line = m_FirstLine; line && n-- > 0; line =
+            line->GetNextLine() )
+   {
+#ifdef DEBUG
+wxASSERT(line->GetLineNumber() == lineNo );
+      lineNo++;
+#endif
+}
+
+   if ( line )
+   {
+      // should be the right one
+      wxASSERT( line->GetLineNumber() == index );
+   }
+
+   return line;
+}
+
+
 wxLayoutList *
 wxLayoutList::Copy(const wxPoint &from,
                    const wxPoint &to)
 wxLayoutList *
 wxLayoutList::Copy(const wxPoint &from,
                    const wxPoint &to)
@@ -2781,18 +3031,17 @@ wxLayoutList::GetSelection(wxLayoutDataObject *wxlo, bool invalidate)
    {
       wxString string;
 
    {
       wxString string;
 
-      wxLayoutExportObject *export;
+      wxLayoutExportObject *exp;
       wxLayoutExportStatus status(llist);
       wxLayoutExportStatus status(llist);
-      while((export = wxLayoutExport( &status, WXLO_EXPORT_AS_OBJECTS)) != NULL)
+      while((exp = wxLayoutExport( &status, WXLO_EXPORT_AS_OBJECTS)) != NULL)
       {
       {
-         if(export->type == WXLO_EXPORT_EMPTYLINE)
-            ; //FIXME missing support for linebreaks in string format
+         if(exp->type == WXLO_EXPORT_EMPTYLINE)
+            string << (int) WXLO_TYPE_LINEBREAK << '\n';
          else
          else
-            export->content.object->Write(string);
-         delete export;
+            exp->content.object->Write(string);
+         delete exp;
       }
       }
-
-      wxlo->SetData(string.c_str(), string.Length()+1);
+      wxlo->SetLayoutData(string);
    }
    return llist;
 }
    }
    return llist;
 }
@@ -2816,11 +3065,13 @@ wxLayoutList::ApplyStyle(wxLayoutStyleInfo const &si, wxDC &dc)
    if(si.m_fg_valid)
    {
       m_CurrentStyleInfo.m_fg = si.m_fg;
    if(si.m_fg_valid)
    {
       m_CurrentStyleInfo.m_fg = si.m_fg;
+      m_CurrentStyleInfo.m_fg_valid = true;
       dc.SetTextForeground(m_CurrentStyleInfo.m_fg);
    }
    if(si.m_bg_valid)
    {
       m_CurrentStyleInfo.m_bg = si.m_bg;
       dc.SetTextForeground(m_CurrentStyleInfo.m_fg);
    }
    if(si.m_bg_valid)
    {
       m_CurrentStyleInfo.m_bg = si.m_bg;
+      m_CurrentStyleInfo.m_bg_valid = true;
       dc.SetTextBackground(m_CurrentStyleInfo.m_bg);
    }
 }
       dc.SetTextBackground(m_CurrentStyleInfo.m_bg);
    }
 }
@@ -2860,6 +3111,9 @@ wxLayoutPrintout::wxLayoutPrintout(wxLayoutList *llist,
    // remove any highlighting which could interfere with printing:
    m_llist->StartSelection();
    m_llist->EndSelection();
    // remove any highlighting which could interfere with printing:
    m_llist->StartSelection();
    m_llist->EndSelection();
+   // force a full layout of the list:
+   m_llist->ForceTotalLayout();
+   // layout  is called in ScaleDC() when we have a DC
 }
 
 wxLayoutPrintout::~wxLayoutPrintout()
 }
 
 wxLayoutPrintout::~wxLayoutPrintout()
@@ -2926,14 +3180,15 @@ bool wxLayoutPrintout::OnPrintPage(int page)
    {
       int top, bottom;
       top = (page - 1)*m_PrintoutHeight;
    {
       int top, bottom;
       top = (page - 1)*m_PrintoutHeight;
-      bottom = top + m_PrintoutHeight;
+      bottom = top + m_PrintoutHeight; 
 
       WXLO_DEBUG(("OnPrintPage(%d) printing from %d to %d", page, top, 
                   bottom));
       // SetDeviceOrigin() doesn't work here, so we need to manually
       // translate all coordinates.
       wxPoint translate(m_Offset.x,m_Offset.y-top);
 
       WXLO_DEBUG(("OnPrintPage(%d) printing from %d to %d", page, top, 
                   bottom));
       // SetDeviceOrigin() doesn't work here, so we need to manually
       // translate all coordinates.
       wxPoint translate(m_Offset.x,m_Offset.y-top);
-      m_llist->Draw(*dc, translate, top, bottom);
+      m_llist->Draw(*dc, translate, top, bottom, TRUE /* clip strictly 
+                                                       */);
       return true;
    }
    else
       return true;
    }
    else
@@ -2945,30 +3200,27 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom,
    /* We allocate a temporary wxDC for printing, so that we can
       determine the correct paper size and scaling. We don't actually
       print anything on it. */
    /* We allocate a temporary wxDC for printing, so that we can
       determine the correct paper size and scaling. We don't actually
       print anything on it. */
-#ifdef __WXMSW__
-   wxPrinterDC psdc("","",WXLLIST_TEMPFILE,false);
+#if defined(__WXMSW__)
+   wxPrinterDC *psdc = new wxPrinterDC("","",WXLLIST_TEMPFILE,false);
 #else
 #else
-   wxPostScriptDC psdc(WXLLIST_TEMPFILE,false);
+   wxPostScriptDC *psdc = new wxPostScriptDC(WXLLIST_TEMPFILE,false);
 #endif
 
 #endif
 
-   float scale = ScaleDC(&psdc);
+   psdc->StartDoc(m_title);
+   // before we draw anything, me must make sure the list is properly
+   // laid out
+   m_llist->Layout(*psdc);
+
+   float scale = ScaleDC(psdc);
 
 
-   psdc.GetSize(&m_PageWidth, &m_PageHeight);
+   psdc->GetSize(&m_PageWidth, &m_PageHeight);
 
 
-   // This sets a left/top origin of 10% and 7%:
-   m_Offset = wxPoint((10*m_PageWidth)/100, (7*m_PageHeight)/100);
+   // This sets a left/top origin of 15% and 5%:
+   m_Offset = wxPoint((15*m_PageWidth)/100, (5*m_PageHeight)/100);
 
    // This is the length of the printable area.
    m_PrintoutHeight = m_PageHeight - 2*m_Offset.y;
    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 - 2*m_Offset.y;
    m_PrintoutHeight = (int)( m_PrintoutHeight / scale); // we want to use the real paper height
-#if 0
-   // We should really use the margin settings of wxWindows somehow.
-   m_Offset = wxPoint(0,0);
-   // This is the length of the printable area.
-   m_PrintoutHeight = m_PageHeight;
-   m_PrintoutHeight = (int)( m_PrintoutHeight / scale); // we want to use the real paper height
-#endif
-   
 
    m_NumOfPages = 1 +
       (int)( m_llist->GetSize().y / (float)(m_PrintoutHeight));
 
    m_NumOfPages = 1 +
       (int)( m_llist->GetSize().y / (float)(m_PrintoutHeight));
@@ -2978,6 +3230,8 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom,
 
    *selPageFrom = 1;
    *selPageTo = m_NumOfPages;
 
    *selPageFrom = 1;
    *selPageTo = m_NumOfPages;
+   psdc->EndDoc();
+   delete psdc;
    wxRemoveFile(WXLLIST_TEMPFILE);
 }
 
    wxRemoveFile(WXLLIST_TEMPFILE);
 }