]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/richedit/wxllist.cpp
pragma interface/implementation should not be used for __APPLE__
[wxWidgets.git] / samples / richedit / wxllist.cpp
index 9ea3e73f2b1d9b5e90558b368e5d3c0a099086b4..3a2ff3a6045cc13356d7c5c2b1554bbebde94c74 100644 (file)
@@ -1,7 +1,7 @@
 /*-*- 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$
  *******************************************************************/
@@ -25,7 +25,7 @@
 #   pragma implementation "wxllist.h"
 #endif
 
-#include <wx/wxprec.h>
+#include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 #  pragma hdrstop
 #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>
@@ -60,6 +64,7 @@
 
 #include <ctype.h>
 
+
 /// This should never really get created
 #define   WXLLIST_TEMPFILE   "__wxllist.tmp"
 
    {
       "invalid", "text", "cmd", "icon"
    };
-   void
-   wxLayoutObject::Debug(void)
+   wxString
+   wxLayoutObject::DebugDump(void) const
    {
-      WXLO_DEBUG(("%s",g_aTypeStrings[GetType()]));
+      wxString str;
+      str.Printf(wxT("%s"), g_aTypeStrings[GetType()]);
+      return str;
    }
 #else
-#  define   TypeString(t)        ""
-#  define   WXLO_DEBUG(x)
+#   define   TypeString(t)        ""
+#   define   WXLO_DEBUG(x)
 #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
@@ -165,14 +173,20 @@ bool Contains(const wxRect &r, const wxPoint &p)
 //@}
 
 
+static
 void ReadString(wxString &to, wxString &from)
 {
-   to = "";
-   const char *cptr = from.c_str();
-   while(*cptr && *cptr != '\n')
-      to += *cptr++;
-   if(*cptr) cptr++;
-   from = cptr;
+    to = wxT("");
+    const wxChar *cptr = from.c_str();
+    while(*cptr && *cptr != wxT('\n'))
+    {
+        to += cptr;
+        cptr++;
+    }
+
+    if(*cptr) cptr++;
+
+    from = cptr;
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -185,22 +199,23 @@ void ReadString(wxString &to, wxString &from)
 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;
-   }
+    wxString tmp;
+    ReadString(tmp, istr);
+    long l = WXLO_TYPE_INVALID;
+    tmp.ToLong(&l);
+    int type = (int) l;
+
+    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;
+    }
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -370,11 +385,14 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
 
 
 #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(wxT(" `%s`"), m_Text.c_str());
+   return str+str2;
 }
 #endif
 
@@ -388,7 +406,7 @@ wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap const &icon)
 {
    if ( !icon.Ok() )
    {
-      wxFAIL_MSG("invalid icon");
+      wxFAIL_MSG(wxT("invalid icon"));
 
       m_Icon = NULL;
 
@@ -412,7 +430,7 @@ wxLayoutObjectIcon::Write(wxString &ostr)
 
    wxString file = wxGetTempFileName("wxloexport");
 
-   ostr << WXLO_TYPE_ICON << '\n'
+   ostr << (int) WXLO_TYPE_ICON << '\n'
         << file << '\n';
    m_Icon->SaveFile(file, WXLO_BITMAP_FORMAT);
 }
@@ -448,6 +466,8 @@ wxLayoutObjectIcon::Copy(void)
 wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap *icon)
 {
    m_Icon = icon;
+   if(! m_Icon)
+      m_Icon = new wxBitmap;
 }
 
 void
@@ -524,12 +544,19 @@ wxLayoutObjectCmd::wxLayoutObjectCmd(int family, int size, int style, int
    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(
-      m_StyleInfo->size,
       m_StyleInfo->family,
+      m_StyleInfo->size,
       m_StyleInfo->style,
       m_StyleInfo->weight,
       m_StyleInfo->underline,
@@ -544,71 +571,101 @@ wxLayoutObjectCmd::Copy(void)
 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)
    {
-      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)
    {
-      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 */
 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 *obj = new wxLayoutObjectCmd;
+
+    long l = 0;
+    wxString tmp;
+    ReadString(tmp, istr);
+    tmp.ToLong(&l);
+    obj->m_StyleInfo->family = (int) l;
+
+
+    ReadString(tmp, istr);
+    tmp.ToLong(&l);
+    obj->m_StyleInfo->size = (int) l;
+
+    ReadString(tmp, istr);
+    tmp.ToLong(&l);
+    obj->m_StyleInfo->style = (int) l;
+
+    ReadString(tmp, istr);
+    tmp.ToLong(&l);
+    obj->m_StyleInfo->weight = (int) l;
+
+    ReadString(tmp, istr);
+    tmp.ToLong(&l);
+    obj->m_StyleInfo->underline = (int) l;
+
+    ReadString(tmp, istr);
+    tmp.ToLong(&l);
+    obj->m_StyleInfo->m_fg_valid = (int) l;
+
+    ReadString(tmp, istr);
+    tmp.ToLong(&l);
+    obj->m_StyleInfo->m_bg_valid = (int) l;
+
+    if(obj->m_StyleInfo->m_fg_valid)
+    {
+        int red, green, blue;
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        red = (int) l;
+
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        green = (int) l;
+
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        blue = (int) l;
+
+        obj->m_StyleInfo->m_fg = wxColour(red, green, blue);
+    }
+
+    if(obj->m_StyleInfo->m_bg_valid)
+    {
+        int red, green, blue;
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        red = (int) l;
+
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        green = (int) l;
+
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        blue = (int) l;
+
+        obj->m_StyleInfo->m_bg = wxColour(red, green, blue);
+    }
+
+    return obj;
 }
 
 
@@ -652,10 +709,9 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
    m_Length = 0;
 
    m_updateLeft = -1;
-   MarkDirty(0);
-
    m_Previous = prev;
    m_Next = NULL;
+   MarkDirty(0);
 
    m_LineNumber = 0;
    RecalculatePosition(llist);
@@ -961,49 +1017,51 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
 bool
 wxLayoutLine::DeleteWord(CoordType xpos)
 {
-   wxASSERT(xpos >= 0);
-   CoordType offset;
-   MarkDirty(xpos);
+    wxASSERT(xpos >= 0);
+    CoordType offset;
+    MarkDirty(xpos);
+
+    wxLOiterator i = FindObject(xpos, &offset);
+
+    for(;;)
+    {
+        if(i == NULLIT) return false;
+        if((**i).GetType() != WXLO_TYPE_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
+            m_ObjectList.erase(i);
+            return true; // we are done
+        }
+        else
+        {  // text object:
+            if(offset == (**i).GetLength()) // at end of object
+            {
+                i++; offset = 0;
+                continue;
+            }
 
-   wxLOiterator i = FindObject(xpos, &offset);
+            wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i;
+            size_t count = 0;
+            wxString str = tobj->GetText();
+            str = str.substr(offset,str.Length()-offset);
+            // Find out how many positions we need to delete:
+            // 1. eat leading space
+            while(isspace(str.c_str()[count])) count++;
+            // 2. eat the word itself:
+            while(isalnum(str.c_str()[count])) count++;
+            // now delete it:
+            wxASSERT(count+offset <= (size_t) (**i).GetLength());
+            ((wxLayoutObjectText *)*i)->GetText().erase(offset,count);
+            m_Length -= count;
 
-   for(;;)
-   {
-      if(i == NULLIT) return false;
-      if((**i).GetType() != WXLO_TYPE_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
-         m_ObjectList.erase(i);
-         return true; // we are done
-      }
-      else
-      {  // text object:
-         if(offset == (**i).GetLength()) // at end of object
-         {
-            i++; offset = 0;
-            continue;
-         }
-         wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i;
-         size_t count = 0;
-         wxString str = tobj->GetText();
-         str = str.substr(offset,str.Length()-offset);
-         // Find out how many positions we need to delete:
-         // 1. eat leading space
-         while(isspace(str.c_str()[count])) count++;
-         // 2. eat the word itself:
-         while(isalnum(str.c_str()[count])) count++;
-         // now delete it:
-         wxASSERT(count+offset <= (size_t) (**i).GetLength());
-         ((wxLayoutObjectText *)*i)->GetText().erase(offset,count);
-         m_Length -= count;
-         return true;
-      }
-   }
+            return true;
+        }
+    }
 
-   wxFAIL_MSG("unreachable");
+    wxFAIL_MSG(wxT("unreachable"));
 }
 
 wxLayoutLine *
@@ -1260,7 +1318,9 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
 
    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;
@@ -1291,6 +1351,131 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
    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,
+                wxT("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)
 {
@@ -1305,7 +1490,8 @@ wxLayoutLine::ReNumber(void)
 void
 wxLayoutLine::MergeNextLine(wxLayoutList *llist)
 {
-   wxCHECK_RET(GetNextLine(),"wxLayout internal error: no next line to merge");
+   wxCHECK_RET( GetNextLine(),
+                wxT("wxLayout internal error: no next line to merge"));
    wxLayoutObjectList &list = GetNextLine()->m_ObjectList;
    wxLOiterator i;
 
@@ -1376,7 +1562,7 @@ wxLayoutLine::GetWrapPosition(CoordType column)
       {
          do
          {
-            if( isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
+            if(isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
                return column;
             else
             {
@@ -1405,34 +1591,34 @@ wxLayoutLine::GetWrapPosition(CoordType column)
       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();
-   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
-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",
+   WXLO_DEBUG((wxT("Line %ld, Pos (%ld,%ld), Height %ld, BL %ld, Font: %d"),
                (long int) GetLineNumber(),
                (long int) pos.x, (long int) pos.y,
                (long int) GetHeight(),
                (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
@@ -1529,7 +1715,7 @@ wxLayoutList::~wxLayoutList()
    Empty();
    m_FirstLine->DeleteLine(false, this);
 
-   wxASSERT_MSG( m_numLines == 0, "line count calculation broken" );
+   wxASSERT_MSG( m_numLines == 0, wxT("line count calculation broken"));
 }
 
 void
@@ -1568,6 +1754,41 @@ wxLayoutList::InternalClear(void)
    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');
+      long l = WXLO_TYPE_INVALID;
+      tmp.ToLong(&l);
+      int type = (int) l;
+
+      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,
@@ -1713,6 +1934,7 @@ wxLayoutList::MoveCursorVertically(int n)
       {
          n--;
          m_CursorPos.y ++;
+         last = m_CursorLine;
          m_CursorLine = m_CursorLine->GetNextLine();
       }
       if(! m_CursorLine)
@@ -1782,8 +2004,8 @@ wxLayoutList::MoveCursorHorizontally(int n)
 bool
 wxLayoutList::MoveCursorWord(int n, bool untilNext)
 {
-   wxCHECK_MSG( m_CursorLine, false, "no current line" );
-   wxCHECK_MSG( n == -1 || n == +1, false, "not implemented yet" );
+   wxCHECK_MSG( m_CursorLine, false, wxT("no current line") );
+   wxCHECK_MSG( n == -1 || n == +1, false, wxT("not implemented yet") );
 
    CoordType moveDistance = 0;
    CoordType offset;
@@ -1872,9 +2094,9 @@ wxLayoutList::MoveCursorWord(int n, bool untilNext)
          if ( canAdvance )
          {
             const wxString& text = tobj->GetText();
-            const char *start = text.c_str();
-            const char *end = start + text.length();
-            const char *p = start + offset;
+            const wxChar *start = text.c_str();
+            const wxChar *end = start + text.length();
+            const wxChar *p = start + offset;
 
             if ( n < 0 )
             {
@@ -1943,16 +2165,18 @@ bool
 wxLayoutList::Insert(wxString const &text)
 {
    wxASSERT(m_CursorLine);
-   wxASSERT_MSG( text.Find('\n') == wxNOT_FOUND, "use wxLayoutImportText!" );
+   wxASSERT_MSG( text.Find(wxT('\n')) == wxNOT_FOUND,
+                 wxT("use wxLayoutImportText!") );
 
    if ( !text )
        return true;
 
    AddCursorPosToUpdateRect();
 
+   wxASSERT(m_CursorLine->GetLength() >= m_CursorPos.x);
+
    if ( !m_CursorLine->Insert(m_CursorPos.x, text) )
       return false;
-
    m_CursorPos.x += text.Length();
 
    m_movedCursor = true;
@@ -2043,35 +2267,28 @@ wxLayoutList::LineBreak(void)
 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->MarkDirty();
-
-      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
 wxLayoutList::Delete(CoordType npos)
 {
-   wxCHECK_MSG(m_CursorLine, false, "can't delete in non existing line");
+   wxCHECK_MSG(m_CursorLine, false, wxT("can't delete in non existing line"));
 
    if ( npos == 0 )
        return true;
@@ -2126,7 +2343,7 @@ wxLayoutList::Delete(CoordType npos)
                }
                else
                {
-                  wxFAIL_MSG("can't delete all this");
+                  wxFAIL_MSG(wxT("can't delete all this"));
 
                   return false;
                }
@@ -2229,6 +2446,9 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
    // 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)
    {
@@ -2238,6 +2458,8 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
          // 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
@@ -2245,6 +2467,9 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
          || 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())
@@ -2266,17 +2491,20 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
                if ( csize )
                   *csize = m_CursorSize;
             }
+            cursorReached = TRUE;
          } 
          else
+         {
             if(cpos && line->GetLineNumber() == cpos->y)
+            {
                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;
+               cursorReached = TRUE;
+            }
+            else
+               line->Layout(dc, this);
+         }
       }
       line = line->GetNextLine();
    }
@@ -2352,8 +2580,8 @@ wxLayoutList::Draw(wxDC &dc,
    }
    InvalidateUpdateRect();
 
-   WXLO_DEBUG(("Selection is %s : l%d,%ld/%ld,%ld",
-               m_Selection.m_valid ? "valid" : "invalid",
+   WXLO_DEBUG((wxT("Selection is %s : %ld,%ld/%ld,%ld"),
+               m_Selection.m_valid ? wxT("valid") : wxT("invalid"),
                m_Selection.m_CursorA.x, m_Selection.m_CursorA.y,
                m_Selection.m_CursorB.x, m_Selection.m_CursorB.y));
 }
@@ -2465,14 +2693,14 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
    coords += translate;
 
 #ifdef WXLAYOUT_DEBUG
-   WXLO_DEBUG(("Drawing cursor (%ld,%ld) at %ld,%ld, size %ld,%ld, line: %ld, len %ld",
+   WXLO_DEBUG((wxT("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()));
 
-   wxLogStatus("Cursor is at (%d, %d)", m_CursorPos.x, m_CursorPos.y);
+   wxLogStatus(wxT("Cursor is at (%d, %d)"), m_CursorPos.x, m_CursorPos.y);
 #endif
 
 #ifdef WXLAYOUT_USE_CARET
@@ -2489,7 +2717,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);
-      SetUpdateRect(coords.x+m_CursorSize.x, coords.y+m_CursorSize.y);
+      SetUpdateRect(coords.x+m_CursorSize.x,
+                    coords.y+m_CursorSize.y);
    }
    else
    {
@@ -2525,7 +2754,7 @@ wxLayoutList::StartSelection(const wxPoint& cposOrig, const wxPoint& spos)
    wxPoint cpos(cposOrig);
    if ( cpos.x == -1 )
       cpos = m_CursorPos;
-   WXLO_DEBUG(("Starting selection at %ld/%ld", cpos.x, cpos.y));
+   WXLO_DEBUG((wxT("Starting selection at %ld/%ld"), cpos.x, cpos.y));
    m_Selection.m_CursorA = cpos;
    m_Selection.m_CursorB = cpos;
    m_Selection.m_ScreenA = spos;
@@ -2543,7 +2772,7 @@ wxLayoutList::ContinueSelection(const wxPoint& cposOrig, const wxPoint& spos)
 
    wxASSERT(m_Selection.m_selecting == true);
    wxASSERT(m_Selection.m_valid == false);
-   WXLO_DEBUG(("Continuing selection at %ld/%ld", cpos.x, cpos.y));
+   WXLO_DEBUG((wxT("Continuing selection at %ld/%ld"), cpos.x, cpos.y));
 
    m_Selection.m_ScreenB = spos;
    m_Selection.m_CursorB = cpos;
@@ -2555,7 +2784,7 @@ 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));
+   WXLO_DEBUG((wxT("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 )
    {
@@ -2744,7 +2973,7 @@ wxLayoutLine *
 wxLayoutList::GetLine(CoordType index) const
 {
    wxASSERT_MSG( (0 <= index) && (index < (CoordType)m_numLines),
-                 "invalid index" );
+                 wxT("invalid index") );
 
    wxLayoutLine *line;
    CoordType n = index;
@@ -2850,12 +3079,11 @@ wxLayoutList::GetSelection(wxLayoutDataObject *wxlo, bool invalidate)
       while((exp = wxLayoutExport( &status, WXLO_EXPORT_AS_OBJECTS)) != NULL)
       {
          if(exp->type == WXLO_EXPORT_EMPTYLINE)
-            ; //FIXME missing support for linebreaks in string format
+            string << (int) WXLO_TYPE_LINEBREAK << '\n';
          else
             exp->content.object->Write(string);
          delete exp;
       }
-
       wxlo->SetLayoutData(string);
    }
    return llist;
@@ -2880,11 +3108,13 @@ wxLayoutList::ApplyStyle(wxLayoutStyleInfo const &si, wxDC &dc)
    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;
+      m_CurrentStyleInfo.m_bg_valid = true;
       dc.SetTextBackground(m_CurrentStyleInfo.m_bg);
    }
 }
@@ -2895,7 +3125,7 @@ wxLayoutList::ApplyStyle(wxLayoutStyleInfo const &si, wxDC &dc)
 void
 wxLayoutList::Debug(void)
 {
-   WXLO_DEBUG(("Cursor is in line %d, screen pos = (%d, %d)",
+   WXLO_DEBUG((wxT("Cursor is in line %d, screen pos = (%d, %d)"),
                m_CursorLine->GetLineNumber(),
                m_CursorScreenPos.x, m_CursorScreenPos.y));
 
@@ -2995,7 +3225,7 @@ bool wxLayoutPrintout::OnPrintPage(int page)
       top = (page - 1)*m_PrintoutHeight;
       bottom = top + m_PrintoutHeight; 
 
-      WXLO_DEBUG(("OnPrintPage(%d) printing from %d to %d", page, top, 
+      WXLO_DEBUG((wxT("OnPrintPage(%d) printing from %d to %d"), page, top, 
                   bottom));
       // SetDeviceOrigin() doesn't work here, so we need to manually
       // translate all coordinates.
@@ -3013,7 +3243,7 @@ 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. */
-#ifdef __WXMSW__
+#if defined(__WXMSW__)
    wxPrinterDC *psdc = new wxPrinterDC("","",WXLLIST_TEMPFILE,false);
 #else
    wxPostScriptDC *psdc = new wxPostScriptDC(WXLLIST_TEMPFILE,false);