]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/richedit/wxllist.cpp
fixes for Metrowerks command line compiler (avoid redefining stuff already defined...
[wxWidgets.git] / samples / richedit / wxllist.cpp
index 83ff44ef42007bddb38cd267427dfea75506cf7a..51ba0553e8e0b23d75c754b60d2e4f52e3552e95 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
@@ -34,6 +34,7 @@
 #include "Mpch.h"
 
 #ifdef M_BASEDIR
+#   include "Mcommon.h"
 #   include "gui/wxllist.h"
 #   include "gui/wxlparser.h"
 #   define  SHOW_SELECTIONS 1
 #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/print.h>
-#   include <wx/log.h>
-#   include <wx/filefn.h>
+#   include "wx/dc.h"
+#   include "wx/dcps.h"
+#   include "wx/print.h"
+#   include "wx/log.h"
+#   include "wx/filefn.h"
 #endif
 
 #ifdef WXLAYOUT_USE_CARET
-#   include <wx/caret.h>
+#   include "wx/caret.h"
 #endif // WXLAYOUT_USE_CARET
 
 #include <ctype.h>
 
+
 /// This should never really get created
 #define   WXLLIST_TEMPFILE   "__wxllist.tmp"
 
 #  define   TypeString(t)      g_aTypeStrings[t]
 #  define   WXLO_DEBUG(x)      wxLogDebug x
 
-   static const char *g_aTypeStrings[] =
+   static const wxChar *g_aTypeStrings[] =
    {
-      "invalid", "text", "cmd", "icon"
+      _T("invalid"), _T("text"), _T("cmd"), _T("icon")
    };
-   void
-   wxLayoutObject::Debug(void)
+   wxString
+   wxLayoutObject::DebugDump() 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
@@ -164,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;
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -184,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);
+    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;
-   }
+    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);
+    }
+
+    return NULL;
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -218,7 +234,7 @@ wxLayoutObjectText::wxLayoutObjectText(const wxString &txt)
 }
 
 wxLayoutObject *
-wxLayoutObjectText::Copy(void)
+wxLayoutObjectText::Copy()
 {
    wxLayoutObjectText *obj = new wxLayoutObjectText(m_Text);
    obj->m_Width = m_Width;
@@ -317,7 +333,7 @@ wxLayoutObjectText::GetOffsetScreen(wxDC &dc, CoordType xpos) const
 }
 
 void
-wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
+wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *WXUNUSED(llist))
 {
    long descent = 0l;
 
@@ -328,6 +344,16 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
              heightOld = m_Height;
 #endif // 0
 
+#ifdef __WXDEBUG__
+   CoordType a,b,c,d,e,f;
+   dc.GetTextExtent(_T("test "), &a, &b, &c);
+   dc.GetTextExtent(_T("test"), &d, &e, &f);
+   wxASSERT(a != d);
+   wxASSERT(b == e);
+   wxASSERT(c == f);
+   dc.GetTextExtent(_T(" "), &d, &e, &f);
+   wxASSERT(a > 0);
+#endif
    dc.GetTextExtent(m_Text, &m_Width, &m_Height, &descent);
 
 #if 0
@@ -359,11 +385,14 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
 
 
 #ifdef WXLAYOUT_DEBUG
-void
-wxLayoutObjectText::Debug(void)
+wxString
+wxLayoutObjectText::DebugDump() 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
 
@@ -375,7 +404,22 @@ wxLayoutObjectText::Debug(void)
 
 wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap const &icon)
 {
+   if ( !icon.Ok() )
+   {
+      wxFAIL_MSG(wxT("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);
+#endif // MSW/!MSW
 }
 
 
@@ -384,9 +428,9 @@ wxLayoutObjectIcon::Write(wxString &ostr)
 {
    /* Exports icon through a temporary file. */
 
-   wxString file = wxGetTempFileName("wxloexport");
+   wxString file = wxGetTempFileName(_T("wxloexport"));
 
-   ostr << WXLO_TYPE_ICON << '\n'
+   ostr << (int) WXLO_TYPE_ICON << '\n'
         << file << '\n';
    m_Icon->SaveFile(file, WXLO_BITMAP_FORMAT);
 }
@@ -406,12 +450,12 @@ wxLayoutObjectIcon::Read(wxString &istr)
       delete obj;
       return NULL;
    }
-   else
-      return obj;
+
+   return obj;
 }
 
 wxLayoutObject *
-wxLayoutObjectIcon::Copy(void)
+wxLayoutObjectIcon::Copy()
 {
    wxLayoutObjectIcon *obj = new wxLayoutObjectIcon(new
                                                     wxBitmap(*m_Icon));
@@ -422,15 +466,17 @@ wxLayoutObjectIcon::Copy(void)
 wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap *icon)
 {
    m_Icon = icon;
+   if(! m_Icon)
+      m_Icon = new wxBitmap;
 }
 
 void
 wxLayoutObjectIcon::Draw(wxDC &dc, wxPoint const &coords,
-                         wxLayoutList *wxllist,
-                         CoordType begin, CoordType /* len */)
+                         wxLayoutList *WXUNUSED(wxllist),
+                         CoordType WXUNUSED(begin), CoordType WXUNUSED(len) )
 {
    dc.DrawBitmap(*m_Icon, coords.x, coords.y-m_Icon->GetHeight(),
-                 (m_Icon->GetMask() == NULL) ? FALSE : TRUE);
+                 (m_Icon->GetMask() == NULL) ? false : true);
 }
 
 void
@@ -463,23 +509,16 @@ wxLayoutStyleInfo::wxLayoutStyleInfo(int ifamily,
                                      wxColour *fg,
                                      wxColour *bg)
 {
-   family = ifamily; size = isize;
-   style = istyle; weight = iweight;
+   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;
+
+   m_fg_valid = fg != 0;
+   m_bg_valid = bg != 0;
+   m_fg = m_fg_valid ? *fg : *wxBLACK;
+   m_bg = m_bg_valid ? *bg : *wxWHITE;
 }
 
 #define COPY_SI_(what) if(right.what != -1) what = right.what;
@@ -505,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::Copy()
 {
    wxLayoutObjectCmd *obj = new wxLayoutObjectCmd(
-      m_StyleInfo->size,
       m_StyleInfo->family,
+      m_StyleInfo->size,
       m_StyleInfo->style,
       m_StyleInfo->weight,
       m_StyleInfo->underline,
@@ -525,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)
+    {
+        unsigned char red, green, blue;
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        red = (unsigned char) l;
+
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        green = (unsigned char) l;
+
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        blue = (unsigned char) l;
+
+        obj->m_StyleInfo->m_fg = wxColour(red, green, blue);
+    }
+
+    if(obj->m_StyleInfo->m_bg_valid)
+    {
+        unsigned char red, green, blue;
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        red = (unsigned char) l;
+
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        green = (unsigned char) l;
+
+        ReadString(tmp, istr);
+        tmp.ToLong(&l);
+        blue = (unsigned char) l;
+
+        obj->m_StyleInfo->m_bg = wxColour(red, green, blue);
+    }
+
+    return obj;
 }
 
 
@@ -599,15 +675,15 @@ wxLayoutObjectCmd::~wxLayoutObjectCmd()
 }
 
 wxLayoutStyleInfo *
-wxLayoutObjectCmd::GetStyle(void) const
+wxLayoutObjectCmd::GetStyle() const
 {
    return m_StyleInfo;
 }
 
 void
-wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint const & /* coords */,
+wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint const & WXUNUSED(coords),
                         wxLayoutList *wxllist,
-                        CoordType begin, CoordType /* len */)
+                        CoordType WXUNUSED(begin), CoordType WXUNUSED(len))
 {
    wxASSERT(m_StyleInfo);
    wxllist->ApplyStyle(*m_StyleInfo, dc);
@@ -629,25 +705,34 @@ wxLayoutObjectCmd::Layout(wxDC &dc, class wxLayoutList * llist)
 
 wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
 {
-   m_LineNumber = 0;
    m_Width = m_Height = 0;
    m_Length = 0;
-   MarkDirty(0);
+
+   m_updateLeft = -1;
    m_Previous = prev;
    m_Next = NULL;
+   MarkDirty(0);
+
+   m_LineNumber = 0;
    RecalculatePosition(llist);
+
+   MarkDirty();
    if(m_Previous)
    {
-      m_LineNumber = m_Previous->GetLineNumber()+1;
+      m_LineNumber = m_Previous->GetLineNumber() + 1;
       m_Next = m_Previous->GetNextLine();
       m_Previous->m_Next = 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();
+
+   llist->IncNumLines();
 }
 
 wxLayoutLine::~wxLayoutLine()
@@ -684,28 +769,6 @@ wxLayoutLine::RecalculatePosition(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;
-
-//   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
@@ -738,30 +801,45 @@ wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const
 }
 
 wxLayoutObjectList::iterator
-wxLayoutLine::FindObjectScreen(wxDC &dc,
+wxLayoutLine::FindObjectScreen(wxDC &dc, wxLayoutList *llist,
                                CoordType xpos, CoordType *cxpos,
                                bool *found) const
 {
    wxASSERT(cxpos);
-   wxASSERT(cxpos);
+
+   llist->ApplyStyle(GetStyleInfo(), dc);
+
    wxLayoutObjectList::iterator i;
    CoordType x = 0, cx = 0, width;
 
    for(i = m_ObjectList.begin(); i != NULLIT; i++)
    {
-      width = (**i).GetWidth();
+      wxLayoutObject *obj = *i;
+      if ( obj->GetType() == WXLO_TYPE_CMD )
+      {
+         // this will set the correct font for the objects which follow
+         obj->Layout(dc, llist);
+      }
+
+      width = obj->GetWidth();
       if( x <= xpos && xpos <= x + width )
       {
-         *cxpos = cx + (**i).GetOffsetScreen(dc, xpos-x);
-         if(found) *found = true;
+         *cxpos = cx + obj->GetOffsetScreen(dc, xpos-x);
+
+         if ( found )
+             *found = true;
          return i;
       }
-      x += (**i).GetWidth();
-      cx += (**i).GetLength();
+
+      x += obj->GetWidth();
+      cx += obj->GetLength();
    }
+
    // behind last object:
    *cxpos = cx;
-   if(found) *found = false;
+
+   if (found)
+       *found = false;
    return m_ObjectList.tail();
 }
 
@@ -773,9 +851,7 @@ wxLayoutLine::FindObjectScreen(wxDC &dc,
 CoordType
 wxLayoutLine::FindText(const wxString &needle, CoordType xpos) const
 {
-   int
-      cpos = 0,
-      relpos = -1;
+   int cpos = 0;
    wxString const *text;
 
    for(wxLOiterator i = m_ObjectList.begin(); i != m_ObjectList.end(); i++)
@@ -785,7 +861,7 @@ wxLayoutLine::FindText(const wxString &needle, CoordType xpos) const
          if((**i).GetType() == WXLO_TYPE_TEXT)
          {
             text = & ((wxLayoutObjectText*)(*i))->GetText();
-            relpos = text->Find(needle);
+            int relpos = text->Find(needle);
             if(relpos >= cpos-xpos) // -1 if not found
             {
                return cpos+relpos;
@@ -805,11 +881,6 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
 
    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)
@@ -905,10 +976,6 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
          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
@@ -945,86 +1012,80 @@ wxLayoutLine::Delete(CoordType xpos, CoordType 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)
 {
-   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;
-         }
-         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;
-      }
-   }
+    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;
+            }
 
-   wxFAIL_MSG("unreachable");
+            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;
+        }
+    }
+
+    #if 0
+    wxFAIL_MSG(wxT("unreachable"));
+    #endif
 }
 
 wxLayoutLine *
 wxLayoutLine::DeleteLine(bool update, wxLayoutList *llist)
 {
-   if(m_Next) m_Next->m_Previous = m_Previous;
-   if(m_Previous) m_Previous->m_Next = m_Next;
-   if(update)
-   {
-      m_Next->MoveLines(-1);
-      m_Next->RecalculatePositions(1, 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);
-   }
+   // maintain linked list integrity
+   if(m_Next)
+       m_Next->m_Previous = m_Previous;
+   if(m_Previous)
+       m_Previous->m_Next = m_Next;
+
+   // get the line numbers right again
+   if ( update && m_Next)
+      m_Next->ReNumber();
+
+   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();
+
    return next;
 }
 
@@ -1039,9 +1100,9 @@ wxLayoutLine::Draw(wxDC &dc,
 
    pos.y += m_BaseLine;
 
-   CoordType xpos = 0; // cursorpos, lenght of line
+   CoordType xpos = 0; // cursorpos, length of line
 
-   CoordType from, to, tempto;
+   CoordType from, to;
 
    int highlight = llist->IsSelected(this, &from, &to);
 //   WXLO_DEBUG(("highlight=%d",  highlight ));
@@ -1055,7 +1116,9 @@ wxLayoutLine::Draw(wxDC &dc,
       if(highlight == -1) // partially highlight line
       {
          // parts of the line need highlighting
-         tempto = xpos+(**i).GetLength();
+
+          // Next line commented, code has no effect
+         // xpos+(**i).GetLength();
          (**i).Draw(dc, pos, llist, from-xpos, to-xpos);
       }
       else
@@ -1075,8 +1138,9 @@ wxLayoutLine::Layout(wxDC &dc,
                      wxLayoutList *llist,
                      wxPoint *cursorPos,
                      wxPoint *cursorSize,
+                     wxLayoutStyleInfo *cursorStyle,
                      int cx,
-                     bool suppressSIupdate)
+                     bool WXUNUSED(suppressSIupdate))
 {
    wxLayoutObjectList::iterator i;
 
@@ -1104,6 +1168,8 @@ wxLayoutLine::Layout(wxDC &dc,
 
    bool cursorFound = false;
 
+   RecalculatePosition(llist);
+
    if(cursorPos)
    {
       *cursorPos = m_Position;
@@ -1135,21 +1201,30 @@ wxLayoutLine::Layout(wxDC &dc,
                if(len < obj->GetLength())
                   str = (*(wxLayoutObjectText*)*i).GetText().substr(len,1);
                else
-                  str = WXLO_CURSORCHAR;
+                  str = _T(WXLO_CURSORCHAR);
                dc.GetTextExtent(str, &width, &height, &descent);
-               wxASSERT(cursorSize);
-               // Just in case some joker inserted an empty string object:
-               if(width == 0) width = WXLO_MINIMUM_CURSOR_WIDTH;
-               if(height == 0) height = sizeObj.y;
-               cursorSize->x = width;
-               cursorSize->y = height;
+
+               if(cursorStyle) // set style info
+                  *cursorStyle = llist->GetStyleInfo();
+               if ( cursorSize )
+               {
+                  // Just in case some joker inserted an empty string object:
+                  if(width == 0)
+                     width = WXLO_MINIMUM_CURSOR_WIDTH;
+                  if(height == 0)
+                     height = sizeObj.y;
+                  cursorSize->x = width;
+                  cursorSize->y = height;
+               }
+
                cursorFound = true; // no more checks
             }
             else
             {
                // on some other object
                CoordType top, bottom; // unused
-               *cursorSize = obj->GetSize(&top,&bottom);
+               if(cursorSize)
+                  *cursorSize = obj->GetSize(&top,&bottom);
                cursorPos->y = m_Position.y;
                cursorFound = true; // no more checks
             }
@@ -1199,7 +1274,7 @@ wxLayoutLine::Layout(wxDC &dc,
    if(m_Height == 0)
    {
       CoordType width, height, descent;
-      dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
+      dc.GetTextExtent(_T(WXLO_CURSORCHAR), &width, &height, &descent);
       m_Height = height;
       m_BaseLine = m_Height - descent;
    }
@@ -1207,26 +1282,24 @@ wxLayoutLine::Layout(wxDC &dc,
    // 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)
+   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);
+         dc.GetTextExtent(_T(WXLO_CURSORCHAR), &width, &height, &descent);
          cursorSize->x = width;
          cursorSize->y = height;
       }
       if(m_BaseLine >= cursorSize->y) // the normal case anyway
          cursorPos->y += m_BaseLine-cursorSize->y;
    }
-   RecalculatePositions(1, llist);
    MarkClean();
 }
 
@@ -1238,24 +1311,6 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
 
    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)
@@ -1265,7 +1320,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;
@@ -1292,15 +1349,154 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
       m_ObjectList.remove(i); // remove without deleting it
    }
    if(m_Next)
-      m_Next->RecalculatePositions(2, llist);
+      m_Next->MarkDirty();
    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 = _T("");
+   // 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 ));
+      #if 0
+      // this assert is useless when xpos has unsigned type
+      wxASSERT(xpos >= 0);
+      #endif
+      llist->MoveCursorTo( wxPoint( xpos, m_Next->GetLineNumber()) );
+   }
+   return true; // we wrapped the line
+}
+
+void
+wxLayoutLine::ReNumber()
+{
+   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)
 {
-   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;
 
@@ -1337,7 +1533,7 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
    SetNext(nextLine);
    if ( nextLine )
    {
-      nextLine->MoveLines(-1);
+      nextLine->ReNumber();
    }
    else
    {
@@ -1352,6 +1548,8 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
 #endif // 0
    }
 
+   llist->DecNumLines();
+
    delete oldnext;
 }
 
@@ -1369,7 +1567,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
             {
@@ -1398,34 +1596,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() 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
@@ -1507,19 +1705,26 @@ wxLayoutList::wxLayoutList()
    m_caret = NULL;
 #endif // WXLAYOUT_USE_CARET
 
+   m_numLines = 0;
    m_FirstLine = NULL;
+   SetAutoFormatting(true);
+   ForceTotalLayout(true);  // for the first time, do all
    InvalidateUpdateRect();
    Clear();
 }
 
 wxLayoutList::~wxLayoutList()
 {
+   SetAutoFormatting(false);
    InternalClear();
+   Empty();
    m_FirstLine->DeleteLine(false, this);
+
+   wxASSERT_MSG( m_numLines == 0, wxT("line count calculation broken"));
 }
 
 void
-wxLayoutList::Empty(void)
+wxLayoutList::Empty()
 {
    while(m_FirstLine)
       m_FirstLine = m_FirstLine->DeleteLine(false, this);
@@ -1535,9 +1740,8 @@ wxLayoutList::Empty(void)
 
 
 void
-wxLayoutList::InternalClear(void)
+wxLayoutList::InternalClear()
 {
-   Empty();
    m_Selection.m_selecting = false;
    m_Selection.m_valid = false;
 
@@ -1546,14 +1750,50 @@ wxLayoutList::InternalClear(void)
    m_DefaultStyleInfo.style = wxNORMAL;
    m_DefaultStyleInfo.weight = wxNORMAL;
    m_DefaultStyleInfo.underline = 0;
-   m_DefaultStyleInfo.m_fg_valid = TRUE;
+   m_DefaultStyleInfo.m_fg_valid = true;
    m_DefaultStyleInfo.m_fg = *wxBLACK;
-   m_DefaultStyleInfo.m_bg_valid = TRUE;
+   m_DefaultStyleInfo.m_bg_valid = true;
    m_DefaultStyleInfo.m_bg = *wxWHITE;
 
    m_CurrentStyleInfo = 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');
+      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,
@@ -1578,19 +1818,13 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
 
 void
 wxLayoutList::SetFont(int family, int size, int style, int weight,
-                      int underline, char const *fg, char const *bg)
+                      int underline, wxChar const *fg, wxChar const *bg)
 
 {
-   wxColour
-      *cfg = NULL,
-      *cbg = NULL;
-
-   if( fg )
-      cfg = wxTheColourDatabase->FindColour(fg);
-   if( bg )
-      cbg = wxTheColourDatabase->FindColour(bg);
+   wxColour cfg = wxTheColourDatabase->Find((fg)?fg:wxT("BLACK"));
+   wxColour cbg = wxTheColourDatabase->Find((bg)?bg:wxT("WHITE"));
 
-   SetFont(family,size,style,weight,underline,cfg,cbg);
+   SetFont(family,size,style,weight,underline,&cfg,&cbg);
 }
 
 void
@@ -1601,6 +1835,11 @@ wxLayoutList::Clear(int family, int size, int style, int weight,
    m_DefaultStyleInfo = wxLayoutStyleInfo(family, size, style, weight,
                                         underline, fg, bg);
    m_CurrentStyleInfo = m_DefaultStyleInfo;
+
+   // Empty() should be called after we set m_DefaultStyleInfo because
+   // otherwise the style info for the first line (created in Empty()) would be
+   // incorrect
+   Empty();
 }
 
 wxPoint
@@ -1694,12 +1933,13 @@ wxLayoutList::MoveCursorVertically(int n)
       {
          n--;
          m_CursorPos.y ++;
+         last = m_CursorLine;
          m_CursorLine = m_CursorLine->GetNextLine();
       }
       if(! m_CursorLine)
       {
          m_CursorLine = last;
-         m_CursorPos.y ++;
+         m_CursorPos.y --;
          rc = false;
       }
       else
@@ -1761,70 +2001,158 @@ wxLayoutList::MoveCursorHorizontally(int n)
 }
 
 bool
-wxLayoutList::MoveCursorWord(int n)
+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;
-   for ( wxLOiterator i = m_CursorLine->FindObject(m_CursorPos.x, &offset);
+   wxLayoutLine *lineCur = m_CursorLine;
+   for ( wxLOiterator i = lineCur->FindObject(m_CursorPos.x, &offset);
          n != 0;
          n > 0 ? i++ : i-- )
    {
       if ( i == NULLIT )
-         return false;
+      {
+         if ( n > 0 )
+         {
+            // moving forward, pass to the first object of the next line
+            moveDistance++;
+            lineCur = lineCur->GetNextLine();
+            if ( lineCur )
+               i = lineCur->GetFirstObject();
+         }
+         else
+         {
+            // moving backwards, pass to the last object of the prev line
+            moveDistance--;
+            lineCur = lineCur->GetPreviousLine();
+            if ( lineCur )
+               i = lineCur->GetLastObject();
+         }
+
+         if ( i == NULLIT )
+         {
+            // moved to the end/beginning of text
+            return false;
+         }
+
+         offset = -1;
+      }
 
       wxLayoutObject *obj = *i;
+
+      if ( offset == -1 )
+      {
+         // calculate offset: we are either at the very beginning or the very
+         // end of the object, so it isn't very difficult (the only time when
+         // offset is != -1 is for the very first iteration when its value is
+         // returned by FindObject)
+         if ( n > 0 )
+            offset = 0;
+         else
+            offset = obj->GetLength();
+      }
+
       if( obj->GetType() != WXLO_TYPE_TEXT )
       {
-         // any non text objects count as one word
-         n > 0 ? n-- : n++;
+         // any visible non text objects count as one word
+         if ( obj->IsVisibleObject() )
+         {
+            n > 0 ? n-- : n++;
 
-         moveDistance += obj->GetLength();
+            moveDistance += obj->GetLength();
+         }
       }
-      else
+      else // text object
       {
-         // text object
          wxLayoutObjectText *tobj = (wxLayoutObjectText *)obj;
 
+         bool canAdvance = true;
+
          if ( offset == tobj->GetLength() )
          {
             // at end of object
-            n > 0 ? n-- : n++;
+            if ( n > 0 )
+            {
+               // can't move further in this text object
+               canAdvance = false;
+
+               // still should move over the object border
+               moveDistance++;
+               n--;
+            }
+            else if ( offset > 0 )
+            {
+               // offset is off by 1, make it a valid index
+               offset--;
+            }
          }
-         else
+
+         if ( canAdvance )
          {
-            const char *start = tobj->GetText().c_str();
-            const char *p = start + offset;
+            const wxString& text = tobj->GetText();
+            const wxChar *start = text.c_str();
+            const wxChar *end = start + text.length();
+            const wxChar *p = start + offset;
+
+            if ( n < 0 )
+            {
+               if ( offset > 0 )
+                  p--;
+            }
 
             // to the beginning/end of the next/prev word
-            while ( isspace(*p) )
+            while ( p >= start && p < end && isspace(*p) )
             {
                n > 0 ? p++ : p--;
             }
 
             // go to the end/beginning of the word (in a broad sense...)
-            while ( p >= start && !isspace(*p) )
+            while ( p >= start && p < end && !isspace(*p) )
             {
                n > 0 ? p++ : p--;
             }
 
             if ( n > 0 )
             {
-               // now advance to the beginning of the next word
-               while ( isspace(*p) )
+               if ( untilNext )
+               {
+                  // now advance to the beginning of the next word
+                  while ( isspace(*p) && p < end )
+                     p++;
+               }
+            }
+            else // backwards
+            {
+               // in these 2 cases we took 1 char too much
+               if ( (p < start) || isspace(*p) )
+               {
                   p++;
+               }
             }
 
-            n > 0 ? n-- : n++;
+            CoordType moveDelta = p - start - offset;
+            if ( (n < 0) && (offset == tobj->GetLength() - 1) )
+            {
+               // because we substracted 1 from offset in this case above, now
+               // compensate for it
+               moveDelta--;
+            }
+
+            if ( moveDelta != 0 )
+            {
+               moveDistance += moveDelta;
 
-            moveDistance = p - start - offset;
+               n > 0 ? n-- : n++;
+            }
          }
       }
 
-      // except for the first iteration, offset is 0
-      offset = 0;
+      // except for the first iteration, offset is calculated in the beginning
+      // of the loop
+      offset = -1;
    }
 
    MoveCursorHorizontally(moveDistance);
@@ -1836,21 +2164,24 @@ 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;
 
-   m_CursorLine->RecalculatePositions(0, this);
+   if(m_AutoFormat)
+      m_CursorLine->MarkDirty();
 
    return true;
 }
@@ -1869,7 +2200,8 @@ wxLayoutList::Insert(wxLayoutObject *obj)
    m_CursorPos.x += obj->GetLength();
    m_movedCursor = true;
 
-   m_CursorLine->RecalculatePositions(0, this);
+   if(m_AutoFormat)
+      m_CursorLine->MarkDirty();
 
    return true;
 }
@@ -1878,7 +2210,7 @@ bool
 wxLayoutList::Insert(wxLayoutList *llist)
 {
    wxASSERT(llist);
-   bool rc = TRUE;
+   bool rc = true;
 
    for(wxLayoutLine *line = llist->GetFirstLine();
        line;
@@ -1895,10 +2227,9 @@ wxLayoutList::Insert(wxLayoutList *llist)
 }
 
 bool
-wxLayoutList::LineBreak(void)
+wxLayoutList::LineBreak()
 {
    wxASSERT(m_CursorLine);
-   bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0);
 
    AddCursorPosToUpdateRect();
 
@@ -1909,16 +2240,19 @@ wxLayoutList::LineBreak(void)
       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();
-   if(m_CursorPos.x != 0)
-      m_CursorPos.y++;
+   if(m_CursorLine->GetPreviousLine() == NULL)
+      m_FirstLine = m_CursorLine;
+   m_CursorPos.y++;
    m_CursorPos.x = 0;
 
+   // The following code will produce a height which is guaranteed to
+   // be too high: old lineheight + the height of both new lines.
+   // We can probably drop the old line height and start with height =
+   // 0. FIXME
    wxLayoutLine *prev = m_CursorLine->GetPreviousLine();
-   wxCHECK_MSG(prev, false, "just broke the line, where is the previous one?");
-
-   height += prev->GetHeight();
+   if(prev)
+      height += prev->GetHeight();
+   height += m_CursorLine->GetHeight();
 
    m_movedCursor = true;
 
@@ -1932,35 +2266,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->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
 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;
@@ -2015,7 +2342,7 @@ wxLayoutList::Delete(CoordType npos)
                }
                else
                {
-                  wxFAIL_MSG("can't delete all this");
+                  wxFAIL_MSG(wxT("can't delete all this"));
 
                   return false;
                }
@@ -2052,7 +2379,8 @@ wxLayoutList::DeleteLines(int n)
       {  // 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:
@@ -2063,13 +2391,16 @@ wxLayoutList::DeleteLines(int n)
       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)
 {
+   if(! m_AutoFormat)
+      return;
    wxLayoutLine *line = m_FirstLine;
 
    // first, make sure everything is calculated - this might not be
@@ -2084,26 +2415,9 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
    }
 }
 
-void
-wxLayoutList::UpdateCursorScreenPos(wxDC &dc)
-{
-   wxCHECK_RET( m_CursorLine, "no cursor line" );
-
-   // we need to save the current style, in case the layout() of the line
-   // changes it
-   wxLayoutStyleInfo SiBackup = m_CurrentStyleInfo;
-   m_CursorLine->Layout(dc, this,
-                        &m_CursorScreenPos, &m_CursorSize,
-                        m_CursorPos.x,
-                        true /* suppress update */);
-   ApplyStyle(SiBackup, dc); // restore it
-}
-
 wxPoint
-wxLayoutList::GetCursorScreenPos(wxDC &dc)
+wxLayoutList::GetCursorScreenPos() const
 {
-   UpdateCursorScreenPos(dc);
-
    return m_CursorScreenPos;
 }
 
@@ -2113,149 +2427,231 @@ wxLayoutList::GetCursorScreenPos(wxDC &dc)
 */
 void
 wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
-                     wxPoint *cpos, wxPoint *csize)
+    wxPoint *cpos, wxPoint *csize)
 {
-   // first, make sure everything is calculated - this might not be
-   // needed, optimise it later
-   ApplyStyle(m_DefaultStyleInfo, dc);
+    // first, make sure everything is calculated - this might not be
+    // 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;
-   wxLayoutLine *line = m_FirstLine;
-   while(line)
-   {
-      if(! wasDirty)
-         ApplyStyle(line->GetStyleInfo(), dc);
-      if(forceAll || line->IsDirty()
-         || (cpos && line->GetLineNumber() == cpos->y))
-      {
-         // The following Layout() calls will update our
-         // m_CurrentStyleInfo if needed.
-         if(line == m_CursorLine)
-            line->Layout(dc, this,
-                         (wxPoint *)&m_CursorScreenPos,
-                         (wxPoint *)&m_CursorSize, m_CursorPos.x);
-         if(cpos && line->GetLineNumber() == cpos->y)
-            line->Layout(dc, this,
-                         cpos,
-                         csize, cpos->x);
+
+    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);
+        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)
+            {
+                line->Layout(dc, this,
+                    (wxPoint *)&m_CursorScreenPos,
+                    (wxPoint *)&m_CursorSize,
+                    &m_CursorStyleInfo,
+                    m_CursorPos.x);
+            // we cannot layout the line twice, so copy the coords:
+            if(cpos && line ->GetLineNumber() == cpos->y)
+            {
+                *cpos = m_CursorScreenPos;
+                if ( csize )
+                    *csize = m_CursorSize;
+            }
+
+            cursorReached = true;
+         }
          else
-            line->Layout(dc, this);
-         // little condition to speed up redrawing:
-         if(bottom != -1 && line->GetPosition().y > bottom)
-            break;
-         wasDirty = true;
-      }
-      line->RecalculatePositions(1, this);
-      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));
-   AddCursorPosToUpdateRect();
+         {
+            if(cpos && line->GetLineNumber() == cpos->y)
+            {
+                line->Layout(dc, this,
+                    cpos,
+                    csize, NULL, cpos->x);
+                cursorReached = true;
+            }
+            else
+                line->Layout(dc, this);
+            }
+        }
+
+        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));
+#endif // WXLAYOUT_USE_CARET
+
+    AddCursorPosToUpdateRect();
 }
 
 wxPoint
 wxLayoutList::GetScreenPos(wxDC &dc, const wxPoint &cpos, wxPoint *csize)
 {
-   wxPoint pos = cpos;
-   Layout(dc, -1, false, &pos, csize);
-   return pos;
+    wxPoint pos = cpos;
+    Layout(dc, -1, false, &pos, csize);
+    return pos;
 }
 
 void
 wxLayoutList::Draw(wxDC &dc,
                    wxPoint const &offset,
                    CoordType top,
-                   CoordType bottom)
-{
-   wxLayoutLine *line = m_FirstLine;
+                   CoordType bottom,
+                   bool clipStrictly)
+{
+    wxLayoutLine *line = m_FirstLine;
+
+    if ( m_Selection.m_discarded )
+    {
+        // calculate them if we don't have them already
+        if ( !m_Selection.HasValidScreenCoords() )
+        {
+            m_Selection.m_ScreenA = GetScreenPos(dc, m_Selection.m_CursorA);
+            m_Selection.m_ScreenB = GetScreenPos(dc, m_Selection.m_CursorB);
+        }
+
+        // invalidate the area which was previousle selected - and which is not
+        // selected any more
+        SetUpdateRect(m_Selection.m_ScreenA);
+        SetUpdateRect(m_Selection.m_ScreenB);
+
+        m_Selection.m_discarded = false;
+    }
+
+    /* 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);
+
+    while(line)
+    {
+        // only draw if between top and bottom:
+        if((top == -1 ||
+            line->GetPosition().y + line->GetHeight() > top))
+        {
+            ApplyStyle(line->GetStyleInfo(), dc);
+            // little condition to speed up redrawing:
+            if( bottom != -1
+                && line->GetPosition().y
+                +(clipStrictly ? line->GetHeight() : 0) >= bottom)
+                break;
 
-   /* 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
-   ApplyStyle(m_DefaultStyleInfo, dc);
-   wxBrush brush(m_CurrentStyleInfo.m_bg, wxSOLID);
-   dc.SetBrush(brush);
-   dc.SetBackgroundMode(wxTRANSPARENT);
+            line->Draw(dc, this, offset);
+        }
 
-   bool style_set = false;
-   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;
-         }
-         line->Draw(dc, this, offset);
-      }
-#if 0
-         else
-         line->Layout(dc, this);
-#endif
-         // little condition to speed up redrawing:
-      if(bottom != -1 && line->GetPosition().y > bottom) break;
-      line = line->GetNextLine();
-   }
-   InvalidateUpdateRect();
+        line = line->GetNextLine();
+    }
+
+    InvalidateUpdateRect();
 
-   WXLO_DEBUG(("Selection is %s : l%d,%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));
+    WXLO_DEBUG((wxT("Selection is %s : %d,%d/%d,%d"),
+        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));
 }
 
 wxLayoutObject *
 wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
-                               wxPoint *cursorPos,
-                               bool *found)
-{
-   // First, find the right line:
-   wxLayoutLine *line = m_FirstLine;
-   wxPoint p;
+    wxPoint *cursorPos, bool *found)
+{
+    // First, find the right line:
+    wxLayoutLine
+        *line = m_FirstLine,
+        *lastline = m_FirstLine;
+    wxPoint p;
+
+    ApplyStyle(m_DefaultStyleInfo, dc);
+    while(line)
+    {
+        p = line->GetPosition();
+        if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
+            break;
+        lastline = line;
+        line = line->GetNextLine();
+    }
 
-   ApplyStyle(m_DefaultStyleInfo, dc);
-   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);
-#endif
-      line = line->GetNextLine();
-   }
-   if(line == NULL)
-   {
-      if(found) *found = false;
-      return NULL; // not found
-   }
-   if(cursorPos) cursorPos->y = line->GetLineNumber();
-   // Now, find the object in the line:
-   wxLOiterator i = line->FindObjectScreen(dc, pos.x,
-                                           cursorPos ? & cursorPos->x : NULL ,
-                                           found);
-   return (i == NULLIT) ? NULL : *i;
+    bool didFind = line != NULL;
+
+    if ( !line )
+    {
+        // use the last line:
+        line = lastline;
+    }
+
+    if ( cursorPos )
+        cursorPos->y = line->GetLineNumber();
+
+    bool foundinline = true;
+    long cx = 0;
+
+    // Now, find the object in the line:
+    wxLOiterator i;
+
+    if (cursorPos)
+    {
+        i = line->FindObjectScreen(dc, this,
+            pos.x,
+            &cx,
+            &foundinline);
+        cursorPos->x = cx;
+    }
+    else
+        i = line->FindObjectScreen(dc, this,
+            pos.x,
+            NULL,
+            &foundinline);
+
+    if ( found )
+        *found = didFind && foundinline;
+
+    return (i == NULLIT) ? NULL : *i;
 
 }
 
 wxPoint
-wxLayoutList::GetSize(void) const
+wxLayoutList::GetSize() const
 {
    wxLayoutLine
       *line = m_FirstLine,
@@ -2294,82 +2690,100 @@ wxLayoutList::GetSize(void) const
 
 
 void
-wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
+wxLayoutList::DrawCursor(wxDC &
+#ifdef WXLAYOUT_USE_CARET
+    WXUNUSED(dc)
+#else
+    dc
+#endif
+    , bool
+#ifdef WXLAYOUT_USE_CARET
+    WXUNUSED(active)
+#else
+    active
+#endif
+    , wxPoint const &translate)
 {
-   if ( m_movedCursor )
-   {
-      UpdateCursorScreenPos(dc);
+    if ( m_movedCursor )
+        m_movedCursor = false;
 
-      m_movedCursor = false;
-   }
-
-   wxPoint coords(m_CursorScreenPos);
-   coords += translate;
+    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",
-               (long)m_CursorPos.x, (long)m_CursorPos.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);
+    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)m_CursorSize.x, (long)m_CursorSize.y,
+        (long)m_CursorLine->GetLineNumber(),
+        (long)m_CursorLine->GetLength()));
+
+    wxLogStatus(wxT("Cursor is at (%d, %d)"), m_CursorPos.x, m_CursorPos.y);
 #endif
 
 #ifdef WXLAYOUT_USE_CARET
-   m_caret->Move(coords);
+    m_caret->Move(coords);
 #else // !WXLAYOUT_USE_CARET
-   dc.SetBrush(*wxBLACK_BRUSH);
-   dc.SetLogicalFunction(wxXOR);
-   dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
-   if(active)
-   {
-      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);
-   }
-   else
-   {
-      dc.DrawLine(coords.x, coords.y+m_CursorSize.y-1,
-                  coords.x, coords.y);
-      SetUpdateRect(coords.x, coords.y+m_CursorSize.y-1);
-      SetUpdateRect(coords.x, coords.y);
-   }
-   dc.SetLogicalFunction(wxCOPY);
-   //dc.SetBrush(wxNullBrush);
+
+    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));
+    if(active)
+    {
+        dc.SetLogicalFunction(wxXOR);
+        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);
+    }
+    else
+    {
+        dc.SetLogicalFunction(wxCOPY);
+        dc.DrawLine(coords.x, coords.y+m_CursorSize.y-1,
+            coords.x, coords.y);
+        SetUpdateRect(coords.x, coords.y+m_CursorSize.y-1);
+        SetUpdateRect(coords.x, coords.y);
+    }
+
+    dc.SetLogicalFunction(wxCOPY);
+    //dc.SetBrush(wxNullBrush);
 #endif // WXLAYOUT_USE_CARET/!WXLAYOUT_USE_CARET
 }
 
 void
 wxLayoutList::SetUpdateRect(CoordType x, CoordType y)
 {
-   if(m_UpdateRectValid)
-      GrowRect(m_UpdateRect, x, y);
-   else
-   {
-      m_UpdateRect.x = x;
-      m_UpdateRect.y = y;
-      m_UpdateRect.width = 4; // large enough to avoid surprises from
-      m_UpdateRect.height = 4;// wxGTK :-)
-      m_UpdateRectValid = true;
-   }
+    if(m_UpdateRectValid)
+    {
+        GrowRect(m_UpdateRect, x, y);
+    }
+    else
+    {
+        m_UpdateRect.x = x;
+        m_UpdateRect.y = y;
+        m_UpdateRect.width = 4; // large enough to avoid surprises from
+        m_UpdateRect.height = 4;// wxGTK :-)
+        m_UpdateRectValid = true;
+    }
 }
 
 void
 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));
-   m_Selection.m_CursorA = cpos;
-   m_Selection.m_CursorB = cpos;
-   m_Selection.m_ScreenA = spos;
-   m_Selection.m_ScreenB = spos;
-   m_Selection.m_selecting = true;
-   m_Selection.m_valid = false;
+    wxPoint cpos(cposOrig);
+    if ( cpos.x == -1 )
+        cpos = m_CursorPos;
+
+    WXLO_DEBUG((wxT("Starting selection at %d/%d"), cpos.x, cpos.y));
+
+    m_Selection.m_CursorA = cpos;
+    m_Selection.m_CursorB = cpos;
+    m_Selection.m_ScreenA = spos;
+    m_Selection.m_ScreenB = spos;
+    m_Selection.m_selecting = true;
+    m_Selection.m_valid = false;
 }
 
 void
@@ -2381,80 +2795,75 @@ 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 %d/%d"), 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;
-   }
-
-   // we always want m_CursorA <= m_CursorB!
-   if( m_Selection.m_CursorA > m_Selection.m_CursorB )
-   {
-      // exchange the start/end points
-      wxPoint help = m_Selection.m_CursorB;
-      m_Selection.m_CursorB = m_Selection.m_CursorA;
-      m_Selection.m_CursorA = help;
-
-      help = m_Selection.m_ScreenB;
-      m_Selection.m_ScreenB = m_Selection.m_ScreenA;
-      m_Selection.m_ScreenA = help;
-   }
+   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);
-   WXLO_DEBUG(("Ending selection at %ld/%ld", cpos.x, cpos.y));
-   m_Selection.m_selecting = false;
-   m_Selection.m_valid = true;
+    wxPoint cpos(cposOrig);
+
+    if(cpos.x == -1) cpos = m_CursorPos;
+
+    ContinueSelection(cpos, spos);
+
+    WXLO_DEBUG((wxT("Ending selection at %d/%d"), cpos.x, cpos.y));
+
+    // we always want m_CursorA <= m_CursorB!
+    if( m_Selection.m_CursorA > m_Selection.m_CursorB )
+    {
+        // exchange the start/end points
+        wxPoint help = m_Selection.m_CursorB;
+        m_Selection.m_CursorB = m_Selection.m_CursorA;
+        m_Selection.m_CursorA = help;
+
+        help = m_Selection.m_ScreenB;
+        m_Selection.m_ScreenB = m_Selection.m_ScreenA;
+        m_Selection.m_ScreenA = help;
+    }
+
+    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
 wxLayoutList::DiscardSelection()
 {
-   if ( !HasSelection() )
-      return;
-
-   m_Selection.m_valid =
-   m_Selection.m_selecting = false;
+    if ( !HasSelection() )
+        return;
 
-   // invalidate the area which was previousle selected - and which is not
-   // selected any more
-   if ( m_Selection.HasValidScreenCoords() )
-   {
-      SetUpdateRect(m_Selection.m_ScreenA);
-      SetUpdateRect(m_Selection.m_ScreenB);
-   }
-   else
-   {
-       // TODO
-   }
+    m_Selection.m_valid =
+    m_Selection.m_selecting = false;
+    m_Selection.m_discarded = true;
 }
 
 bool
-wxLayoutList::IsSelecting(void)
+wxLayoutList::IsSelecting() const
 {
-   return m_Selection.m_selecting;
+    return m_Selection.m_selecting;
 }
 
 bool
-wxLayoutList::IsSelected(const wxPoint &cursor)
+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)
+    );
 }
 
 
@@ -2466,92 +2875,118 @@ wxLayoutList::IsSelected(const wxPoint &cursor)
     */
 int
 wxLayoutList::IsSelected(const wxLayoutLine *line, CoordType *from,
-                         CoordType *to)
-{
-   wxASSERT(line); wxASSERT(to); wxASSERT(from);
-
-   if(! m_Selection.m_valid && ! m_Selection.m_selecting)
-      return 0;
-
-   CoordType y = line->GetLineNumber();
-   if(m_Selection.m_CursorA.y < y && m_Selection.m_CursorB.y > y)
-      return 1;
-   else if(m_Selection.m_CursorA.y == y)
-   {
-      *from = m_Selection.m_CursorA.x;
-      if(m_Selection.m_CursorB.y == y)
-         *to = m_Selection.m_CursorB.x;
-      else
-         *to = line->GetLength();
-      return -1;
-   }
-   else if(m_Selection.m_CursorB.y == y)
-   {
-      *to = m_Selection.m_CursorB.x;
-      if(m_Selection.m_CursorA.y == y)
-         *from = m_Selection.m_CursorA.x;
-      else
-         *from = 0;
-      return -1;
-   }
-   else
-      return 0;
+    CoordType *to)
+{
+    wxASSERT(line); wxASSERT(to); wxASSERT(from);
+
+    if(! m_Selection.m_valid && ! m_Selection.m_selecting)
+        return 0;
+
+    CoordType y = line->GetLineNumber();
+    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)
+    {
+        *from = m_Selection.m_CursorA.x;
+        if(m_Selection.m_CursorB.y == y)
+        {
+            *to = m_Selection.m_CursorB.x;
+        }
+        else
+        {
+            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)
+    {
+        *to = m_Selection.m_CursorB.x;
+        if (m_Selection.m_CursorA.y == y)
+        {
+            *from = m_Selection.m_CursorA.x;
+        }
+        else
+        {
+            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 0;
+    }
 }
 
 void
-wxLayoutList::DeleteSelection(void)
+wxLayoutList::DeleteSelection()
 {
-   if(! m_Selection.m_valid)
-      return;
+    if (! m_Selection.m_valid)
+        return;
 
-   m_Selection.m_valid = false;
+    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;
+    // 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;
+    }
 
+   // We now know that the two lines are different:
 
-   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;
+    wxLayoutLine
+        * firstLine = GetLine(m_Selection.m_CursorA.y),
+        * lastLine = GetLine(m_Selection.m_CursorB.y);
 
+    // be a bit paranoid:
+    if(! firstLine || ! lastLine)
+        return;
 
-   // We now know that the two lines are different:
+    // 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();
+    wxLayoutLine *prevLine = firstLine->GetPreviousLine(),
+        *nextLine = firstLine->GetNextLine();
 
-   wxLayoutLine *nextLine = firstLine->GetNextLine();
-   while(nextLine && nextLine != lastLine)
-      nextLine = nextLine->DeleteLine(false, this);
+    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
+    // 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);
+    // 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->MarkDirty();
 }
 
 /// Starts highlighting the selection
@@ -2577,139 +3012,177 @@ wxLayoutList::EndHighlighting(wxDC &dc)
 }
 
 
-wxLayoutList *
-wxLayoutList::Copy(const wxPoint &from,
-                   const wxPoint &to)
+wxLayoutLine *
+wxLayoutList::GetLine(CoordType index) const
 {
-   wxLayoutLine
-      * firstLine = NULL,
-      * lastLine = NULL;
-
-   for(firstLine = m_FirstLine;
-       firstLine && firstLine->GetLineNumber() < from.y;
-       firstLine=firstLine->GetNextLine())
-      ;
-   if(!firstLine || firstLine->GetLineNumber() != from.y)
-      return NULL;
+    wxASSERT_MSG( (0 <= index) && (index < (CoordType)m_numLines),
+        wxT("invalid index") );
 
-   for(lastLine = m_FirstLine;
-       lastLine && lastLine->GetLineNumber() < to.y;
-       lastLine=lastLine->GetNextLine())
-      ;
-   if(!lastLine || lastLine->GetLineNumber() != to.y)
-      return NULL;
+    wxLayoutLine *line;
+    CoordType n = index;
+#ifdef DEBUG
+    CoordType lineNo = 0;
+#endif
 
-   if(to <= from)
-   {
-      wxLayoutLine *tmp = firstLine;
-      firstLine = lastLine;
-      lastLine = tmp;
-   }
+    for ( line = m_FirstLine; line && n-- > 0; line = line->GetNextLine() )
+    {
+#ifdef DEBUG
+    wxASSERT(line->GetLineNumber() == lineNo );
+    lineNo++;
+#endif
+    }
 
-   wxLayoutList *llist = new wxLayoutList();
+    if ( line )
+    {
+        // should be the right one
+        wxASSERT( line->GetLineNumber() == index );
+    }
 
-   if(firstLine == lastLine)
-   {
-      firstLine->Copy(llist, from.x, to.x);
-   }
-   else
-   {
-      // 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())
-      {
-         line->Copy(llist);
-         llist->LineBreak();
-      }
-      // Extract objects from last line
-      lastLine->Copy(llist, 0, to.x);
-   }
-   return llist;
+    return line;
+}
+
+
+wxLayoutList *
+wxLayoutList::Copy(const wxPoint &from,
+    const wxPoint &to)
+{
+    wxLayoutLine
+        * firstLine,
+        * lastLine;
+
+    for(firstLine = m_FirstLine;
+        firstLine && firstLine->GetLineNumber() < from.y;
+        firstLine=firstLine->GetNextLine())
+        ;
+
+    if(!firstLine || firstLine->GetLineNumber() != from.y)
+        return NULL;
+
+    for(lastLine = m_FirstLine;
+        lastLine && lastLine->GetLineNumber() < to.y;
+        lastLine=lastLine->GetNextLine())
+        ;
+
+    if(!lastLine || lastLine->GetLineNumber() != to.y)
+        return NULL;
+
+    if(to <= from)
+    {
+        wxLayoutLine *tmp = firstLine;
+        firstLine = lastLine;
+        lastLine = tmp;
+    }
+
+    wxLayoutList *llist = new wxLayoutList();
+
+    if(firstLine == lastLine)
+    {
+        firstLine->Copy(llist, from.x, to.x);
+    }
+    else
+    {
+        // 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() )
+        {
+            line->Copy(llist);
+            llist->LineBreak();
+        }
+
+        // Extract objects from last line
+        lastLine->Copy(llist, 0, to.x);
+    }
+
+    return llist;
 }
 
 wxLayoutList *
 wxLayoutList::GetSelection(wxLayoutDataObject *wxlo, bool invalidate)
 {
-   if(! m_Selection.m_valid)
-   {
-      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;
+    if(! m_Selection.m_valid)
+    {
+        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 *exp;
+        wxLayoutExportStatus status(llist);
+        while((exp = wxLayoutExport( &status, WXLO_EXPORT_AS_OBJECTS)) != NULL)
+        {
+            if(exp->type == WXLO_EXPORT_EMPTYLINE)
+                string << (int) WXLO_TYPE_LINEBREAK << '\n';
+            else
+                exp->content.object->Write(string);
+            delete exp;
+        }
 
-      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->SetLayoutData(string);
+    }
 
-      wxlo->SetData(string.c_str(), string.Length()+1);
-   }
-   return llist;
+    return llist;
 }
 
 
 
-#define COPY_SI(what) if(si.what != -1) { m_CurrentStyleInfo.what = si.what; fontChanged = TRUE; }
+#define COPY_SI(what) if(si.what != -1) { m_CurrentStyleInfo.what = si.what; fontChanged = true; }
 
 void
 wxLayoutList::ApplyStyle(wxLayoutStyleInfo const &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_CurrentStyleInfo) );
+    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_CurrentStyleInfo) );
 
-   if(si.m_fg_valid)
-   {
-      m_CurrentStyleInfo.m_fg = si.m_fg;
-      dc.SetTextForeground(m_CurrentStyleInfo.m_fg);
-   }
-   if(si.m_bg_valid)
-   {
-      m_CurrentStyleInfo.m_bg = si.m_bg;
-      dc.SetTextBackground(m_CurrentStyleInfo.m_bg);
-   }
+    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);
+    }
 }
 
 
 #ifdef WXLAYOUT_DEBUG
 
 void
-wxLayoutList::Debug(void)
+wxLayoutList::Debug()
 {
-   WXLO_DEBUG(("Cursor is in line %d, screen pos = (%d, %d)",
-               m_CursorLine->GetLineNumber(),
-               m_CursorScreenPos.x, m_CursorScreenPos.y));
+    WXLO_DEBUG((wxT("Cursor is in line %d, screen pos = (%d, %d)"),
+        (int)m_CursorLine->GetLineNumber(),
+        m_CursorScreenPos.x, m_CursorScreenPos.y));
 
-   wxLayoutLine *line;
-   for(line = m_FirstLine; line; line = line->GetNextLine())
-   {
-      line->Debug();
-   }
+    wxLayoutLine *line;
+    for(line = m_FirstLine; line; line = line->GetNextLine())
+    {
+        line->Debug();
+    }
 }
 
 #endif
@@ -2722,14 +3195,17 @@ wxLayoutList::Debug(void)
    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 wxLayoutPrintout::wxLayoutPrintout(wxLayoutList *llist,
-                                   wxString const & title)
-:wxPrintout(title)
+    wxString const & title)
+    :wxPrintout(title)
 {
-   m_llist = llist;
-   m_title = title;
-   // remove any highlighting which could interfere with printing:
-   m_llist->StartSelection();
-   m_llist->EndSelection();
+    m_llist = llist;
+    m_title = title;
+    // 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()
@@ -2739,72 +3215,84 @@ wxLayoutPrintout::~wxLayoutPrintout()
 float
 wxLayoutPrintout::ScaleDC(wxDC *dc)
 {
-   // 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.
-    */
-  // Get the logical pixels per inch of screen and printer
-   int ppiScreenX, ppiScreenY;
-   GetPPIScreen(&ppiScreenX, &ppiScreenY);
-   int ppiPrinterX, ppiPrinterY;
-   GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
-
-   if(ppiScreenX == 0) // not yet set, need to guess
-   {
-      ppiScreenX = 100;
-      ppiScreenY = 100;
-   }
-   if(ppiPrinterX == 0) // not yet set, need to guess
-   {
-      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
-  // need to be addressed at some point but can be fudged for the
-  // moment.
-  float scale = (float)((float)ppiPrinterX/(float)ppiScreenX);
-
-  // Now we have to check in case our real page size is reduced
-  // (e.g. because we're drawing to a print preview memory DC)
-  int pageWidth, pageHeight;
-  int w, h;
-  dc->GetSize(&w, &h);
-  GetPageSizePixels(&pageWidth, &pageHeight);
-  if(pageWidth != 0) // doesn't work always
-  {
-     // If printer pageWidth == current DC width, then this doesn't
-     // change. But w might be the preview bitmap width, so scale down.
-     scale = scale * (float)(w/(float)pageWidth);
-  }
-  dc->SetUserScale(scale, scale);
-  return scale;
+    // 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.
+     */
+
+    // Get the logical pixels per inch of screen and printer
+    int ppiScreenX, ppiScreenY;
+    GetPPIScreen(&ppiScreenX, &ppiScreenY);
+    int ppiPrinterX, ppiPrinterY;
+    GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
+
+    if(ppiScreenX == 0) // not yet set, need to guess
+    {
+        ppiScreenX = 100;
+        ppiScreenY = 100;
+    }
+    wxUnusedVar(ppiScreenY);
+
+    if(ppiPrinterX == 0) // not yet set, need to guess
+    {
+        ppiPrinterX = 72;
+        ppiPrinterY = 72;
+    }
+    wxUnusedVar(ppiPrinterY);
+
+    // 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
+    // need to be addressed at some point but can be fudged for the
+    // moment.
+    float scale = (float)((float)ppiPrinterX/(float)ppiScreenX);
+
+    // Now we have to check in case our real page size is reduced
+    // (e.g. because we're drawing to a print preview memory DC)
+    int pageWidth, pageHeight;
+    int w, h;
+    dc->GetSize(&w, &h);
+    GetPageSizePixels(&pageWidth, &pageHeight);
+    wxUnusedVar(pageHeight);
+    if(pageWidth != 0) // doesn't work always
+    {
+        // If printer pageWidth == current DC width, then this doesn't
+        // change. But w might be the preview bitmap width, so scale down.
+        scale = scale * (float)(w/(float)pageWidth);
+    }
+
+    dc->SetUserScale(scale, scale);
+    return scale;
 }
 
 bool wxLayoutPrintout::OnPrintPage(int page)
 {
-   wxDC *dc = GetDC();
+    wxDC *dc = GetDC();
 
-   ScaleDC(dc);
+    ScaleDC(dc);
 
-   if (dc)
-   {
-      int top, bottom;
-      top = (page - 1)*m_PrintoutHeight;
-      bottom = top + m_PrintoutHeight;
-      // 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);
-      return true;
+    if (dc)
+    {
+        int top, bottom;
+        top = (page - 1)*m_PrintoutHeight;
+        bottom = top + m_PrintoutHeight;
+
+        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.
+        wxPoint translate(m_Offset.x,m_Offset.y-top);
+        m_llist->Draw(*dc, translate, top, bottom, true /* clip strictly */);
+        return true;
    }
    else
+   {
       return false;
+   }
 }
 
 void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
@@ -2812,23 +3300,28 @@ 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__
-   wxPrinterDC psdc("","",WXLLIST_TEMPFILE,false);
+#if defined(__WXMSW__)
+   wxPrinterDC *psdc = new wxPrinterDC(wxEmptyString,wxEmptyString,_T(WXLLIST_TEMPFILE),false);
 #else
-   wxPostScriptDC psdc(WXLLIST_TEMPFILE,false);
+   wxPostScriptDC *psdc = new wxPostScriptDC(WXLLIST_TEMPFILE,false);
 #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);
 
-   psdc.GetSize(&m_PageWidth, &m_PageHeight);
-   // This sets a left/top origin of 15% and 20%:
-   m_Offset = wxPoint((15*m_PageWidth)/100, m_PageHeight/20);
+   float scale = ScaleDC(psdc);
+
+   psdc->GetSize(&m_PageWidth, &m_PageHeight);
+
+   // 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 - (int) (m_PageHeight * 0.15);
+   m_PrintoutHeight = m_PageHeight - 2*m_Offset.y;
    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));
 
@@ -2837,7 +3330,9 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom,
 
    *selPageFrom = 1;
    *selPageTo = m_NumOfPages;
-   wxRemoveFile(WXLLIST_TEMPFILE);
+   psdc->EndDoc();
+   delete psdc;
+   wxRemoveFile(_T(WXLLIST_TEMPFILE));
 }
 
 bool wxLayoutPrintout::HasPage(int pageNum)
@@ -2846,7 +3341,7 @@ bool wxLayoutPrintout::HasPage(int pageNum)
 }
 
 /*
-  Stupid wxWindows doesn't draw proper ellipses, so we comment this
+  Stupid wxWidgets doesn't draw proper ellipses, so we comment this
   out. It's a waste of paper anyway.
 */
 #if 0