]> git.saurik.com Git - wxWidgets.git/blobdiff - user/wxLayout/wxllist.cpp
new location for setup.h.in file
[wxWidgets.git] / user / wxLayout / wxllist.cpp
index d0a3bc05a5aa59d8550c24e03c2a2393d82b3719..caf366bcb2ef3ec43be2005a3477ebfbcce76a65 100644 (file)
@@ -24,6 +24,7 @@
 
 #ifdef M_BASEDIR
 #   include "gui/wxllist.h"
+#   include "gui/wxlparser.h"
 #   define  SHOW_SELECTIONS 1
 #else
 #   include "wxllist.h"
@@ -37,6 +38,7 @@
 #   include   <wx/dcps.h>
 #   include   <wx/print.h>
 #   include   <wx/log.h>
+#   include   <wx/filefn.h>
 #endif
 
 #include <ctype.h>
@@ -118,6 +120,45 @@ bool Contains(const wxRect &r, const wxPoint &p)
 
 //@}
 
+
+void ReadString(wxString &to, wxString &from)
+{
+   to = "";
+   const char *cptr = from.c_str();
+   while(*cptr && *cptr != '\n')
+      to += *cptr++;
+   if(*cptr) cptr++;
+   from = cptr;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+
+   wxLayoutObject
+
+   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* static */
+wxLayoutObject *
+wxLayoutObject::Read(wxString &istr)
+{
+   wxString tmp;
+   ReadString(tmp, istr);
+   int type = -1;
+   sscanf(tmp.c_str(),"%d", &type);
+   
+   switch(type)
+   {
+   case WXLO_TYPE_TEXT:
+      return wxLayoutObjectText::Read(istr);
+   case WXLO_TYPE_CMD:
+      return wxLayoutObjectCmd::Read(istr);
+   case WXLO_TYPE_ICON:
+      return wxLayoutObjectIcon::Read(istr);
+   default:
+      return NULL;
+   }
+}
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 
    wxLayoutObjectText
@@ -145,6 +186,23 @@ wxLayoutObjectText::Copy(void)
    return obj;
 }
 
+
+void
+wxLayoutObjectText::Write(wxString &ostr)
+{
+   ostr << (int) WXLO_TYPE_TEXT << '\n' 
+        << m_Text << '\n';
+}
+/* static */
+wxLayoutObjectText *
+wxLayoutObjectText::Read(wxString &istr)
+{
+   wxString text;
+   ReadString(text, istr);
+   
+   return new wxLayoutObjectText(text);
+}
+
 wxPoint
 wxLayoutObjectText::GetSize(CoordType *top, CoordType *bottom) const
 {
@@ -158,7 +216,7 @@ wxLayoutObjectText::Draw(wxDC &dc, wxPoint const &coords,
                          wxLayoutList *wxllist,
                          CoordType begin, CoordType end)
 {
-   if(begin == -1)
+   if( end <= 0)
       dc.DrawText(m_Text, coords.x, coords.y-m_Top);
    else
    {
@@ -168,6 +226,10 @@ wxLayoutObjectText::Draw(wxDC &dc, wxPoint const &coords,
          xpos = coords.x,
          ypos = coords.y-m_Top;
       long width, height, descent;
+
+      if(begin < 0) begin = 0;
+      if( end > (signed)m_Text.Length() )
+         end = m_Text.Length();
       
       str = m_Text.Mid(0, begin);
       dc.DrawText(str, xpos, ypos);
@@ -219,6 +281,7 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList * )
    m_Top = m_Height - m_Bottom;
 }
 
+
 #ifdef WXLAYOUT_DEBUG
 void
 wxLayoutObjectText::Debug(void)
@@ -239,6 +302,38 @@ wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap const &icon)
    m_Icon = new wxBitmap(icon);
 }
 
+
+void
+wxLayoutObjectIcon::Write(wxString &ostr)
+{
+   /* Exports icon through a temporary file. */
+
+   wxString file = wxGetTempFileName("wxloexport");
+
+   ostr << WXLO_TYPE_ICON << '\n'
+        << file << '\n';
+   m_Icon->SaveFile(file, WXLO_BITMAP_FORMAT);
+}
+/* static */
+wxLayoutObjectIcon *
+wxLayoutObjectIcon::Read(wxString &istr)
+{
+   wxString file;
+   ReadString(file, istr);
+   
+   if(! wxFileExists(file))
+      return NULL;
+   wxLayoutObjectIcon *obj = new wxLayoutObjectIcon;
+   
+   if(!obj->m_Icon->LoadFile(file, WXLO_BITMAP_FORMAT))
+   {
+      delete obj;
+      return NULL;
+   }
+   else
+      return obj;
+}
+
 wxLayoutObject *
 wxLayoutObjectIcon::Copy(void)
 {
@@ -297,76 +392,127 @@ wxLayoutStyleInfo::wxLayoutStyleInfo(int ifamily,
    underline = iul;
    if(fg)
    {
-      fg_valid = true;
-      fg_red = fg->Red();
-      fg_blue = fg->Blue();
-      fg_green = fg->Green();
+      m_fg = *fg;
+      m_fg_valid = TRUE;
    }
    else
-      fg_valid = false;
+      m_fg = *wxBLACK;
    if(bg)
    {
-      bg_valid = true;
-      bg_red = bg->Red();
-      bg_blue = bg->Blue();
-      bg_green = bg->Green();
+      m_bg = *bg;
+      m_bg_valid = TRUE;
    }
    else
-      bg_valid = false;
+      m_bg = *wxWHITE;
 }
 
-#define SET_SI(what) tmp.what = (what != -1) ? what : ( si ? si->what : wxNORMAL);
-
+#define COPY_SI_(what) if(right.what != -1) what = right.what;
 
-wxFont *
-wxLayoutStyleInfo::GetFont(wxLayoutStyleInfo *si)
+wxLayoutStyleInfo &
+wxLayoutStyleInfo::operator=(const wxLayoutStyleInfo &right)
 {
-   wxLayoutStyleInfo tmp;
-   
-   SET_SI(family);
-   SET_SI(size);
-   SET_SI(style);
-   SET_SI(weight);
-   SET_SI(underline);
-
-   return new wxFont(tmp.size,tmp.family,tmp.style,tmp.weight,tmp.underline);
-
+   COPY_SI_(family);
+   COPY_SI_(style);
+   COPY_SI_(size);
+   COPY_SI_(weight);
+   COPY_SI_(underline);
+   if(right.m_fg_valid) m_fg = right.m_fg;
+   if(right.m_bg_valid) m_bg = right.m_bg;
+   return *this;
 }
 
-wxLayoutObjectCmd::wxLayoutObjectCmd(int size, int family, int style, int
+wxLayoutObjectCmd::wxLayoutObjectCmd(int family, int size, int style, int
                                      weight, int underline,
                                      wxColour *fg, wxColour *bg)
    
 {
-   m_StyleInfo = new
-      wxLayoutStyleInfo(size,family,style,weight,underline,fg,bg);
-   m_font = NULL;
+   m_StyleInfo = new wxLayoutStyleInfo(family, size,style,weight,underline,fg,bg);
 }
 
 wxLayoutObject *
 wxLayoutObjectCmd::Copy(void)
 {
-   wxColour
-      * fg = NULL,
-      * bg = NULL;
-   if(m_StyleInfo->fg_valid)
-      fg = new
-         wxColour(m_StyleInfo->fg_red,m_StyleInfo->fg_green,m_StyleInfo->fg_blue);
-   if(m_StyleInfo->bg_valid)
-      bg = new
-         wxColour(m_StyleInfo->bg_red,m_StyleInfo->bg_green,m_StyleInfo->bg_blue);
-   
    wxLayoutObjectCmd *obj = new wxLayoutObjectCmd(
       m_StyleInfo->size,
       m_StyleInfo->family,
       m_StyleInfo->style,
       m_StyleInfo->weight,
       m_StyleInfo->underline,
-      fg, bg);
+      m_StyleInfo->m_fg_valid ?
+      &m_StyleInfo->m_fg : NULL,
+      m_StyleInfo->m_bg_valid ?
+      &m_StyleInfo->m_bg : NULL);
    obj->SetUserData(m_UserData);
+   return obj;
+}
+
+void
+wxLayoutObjectCmd::Write(wxString &ostr)
+{
+   ostr << WXLO_TYPE_CMD << '\n'
+        << m_StyleInfo->size << '\n'
+        << m_StyleInfo->family << '\n'
+        << m_StyleInfo->style << '\n'
+        << m_StyleInfo->weight << '\n'
+        << m_StyleInfo->underline << '\n'
+        << m_StyleInfo->m_fg_valid << '\n'
+        << m_StyleInfo->m_bg_valid << '\n';
+   if(m_StyleInfo->m_fg_valid)
+   {
+      ostr << m_StyleInfo->m_fg.Red() << '\n'
+           << m_StyleInfo->m_fg.Green() << '\n'
+           << m_StyleInfo->m_fg.Blue() << '\n';
+   }
+   if(m_StyleInfo->m_bg_valid)
+   {
+      ostr << m_StyleInfo->m_bg.Red() << '\n'
+           << m_StyleInfo->m_bg.Green() << '\n'
+           << m_StyleInfo->m_bg.Blue() << '\n';
+   }
+}
+/* static */
+wxLayoutObjectCmd *
+wxLayoutObjectCmd::Read(wxString &istr)
+{
+   wxLayoutObjectCmd *obj = new wxLayoutObjectCmd;
 
-   if(fg) delete fg;
-   if(bg) delete bg;
+   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;
 }
 
@@ -374,7 +520,6 @@ wxLayoutObjectCmd::Copy(void)
 wxLayoutObjectCmd::~wxLayoutObjectCmd()
 {
    delete m_StyleInfo;
-   if(m_font) delete m_font;
 }
 
 wxLayoutStyleInfo *
@@ -389,17 +534,12 @@ wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint const & /* coords */,
                         CoordType begin, CoordType /* len */)
 {
    wxASSERT(m_StyleInfo);
-   dc.SetFont(*m_font);
    wxllist->ApplyStyle(m_StyleInfo, dc);
 }
 
 void
 wxLayoutObjectCmd::Layout(wxDC &dc, class wxLayoutList * llist)
 {
-   if(m_font) delete m_font;
-   m_font = m_StyleInfo->GetFont(llist->GetStyleInfo());
-
-
    // this get called, so that recalculation uses right font sizes
    Draw(dc, wxPoint(0,0), llist);
 }
@@ -425,7 +565,6 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
       m_LineNumber = m_Previous->GetLineNumber()+1;
       m_Next = m_Previous->GetNextLine();
       m_Previous->m_Next = this;
-      m_Height = m_Previous->GetHeight();
    }
    if(m_Next)
    {
@@ -459,6 +598,11 @@ wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
 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;
@@ -516,12 +660,10 @@ wxLayoutLine::FindObjectScreen(wxDC &dc,
    
    for(i = m_ObjectList.begin(); i != NULLIT; i++)
    {
-//FIXME!      (**i).Layout(dc, NULL);
       width = (**i).GetWidth();
       if( x <= xpos && xpos <= x + width )
       {
          *cxpos = cx + (**i).GetOffsetScreen(dc, xpos-x);
-//         WXLO_DEBUG(("wxLayoutLine::FindObjectScreen: cursor xpos = %ld", *cxpos));
          if(found) *found = true;
          return i;
       }
@@ -540,7 +682,7 @@ wxLayoutLine::FindObjectScreen(wxDC &dc,
     @return the cursoor coord where it was found or -1
 */
 CoordType
-wxLayoutLine::FindText(const wxString &needle, CoordType xpos = 0) const
+wxLayoutLine::FindText(const wxString &needle, CoordType xpos) const
 {
    int
       cpos = 0,
@@ -571,6 +713,8 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
 {
    wxASSERT(xpos >= 0);
    wxASSERT(obj != NULL);
+   //FIXME: this could be optimised, for now be prudent:
+   m_Dirty = true;
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i == NULLIT)
@@ -625,6 +769,8 @@ bool
 wxLayoutLine::Insert(CoordType xpos, wxString text)
 {
    wxASSERT(xpos >= 0);
+   //FIXME: this could be optimised, for now be prudent:
+   m_Dirty = true;
    CoordType offset;
    wxLOiterator i = FindObject(xpos, &offset);
    if(i != NULLIT && (**i).GetType() == WXLO_TYPE_TEXT)
@@ -646,6 +792,8 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
 
    wxASSERT(xpos >= 0);
    wxASSERT(npos >= 0);
+   //FIXME: this could be optimised, for now be prudent:
+   m_Dirty = true;
    wxLOiterator i = FindObject(xpos, &offset);
    while(npos > 0)
    {
@@ -699,6 +847,8 @@ wxLayoutLine::DeleteWord(CoordType xpos)
 {
    wxASSERT(xpos >= 0);
    CoordType offset;
+   //FIXME: this could be optimised, for now be prudent:
+   m_Dirty = true;
 
    wxLOiterator i = FindObject(xpos, &offset);
 
@@ -769,6 +919,9 @@ wxLayoutLine::Draw(wxDC &dc,
    CoordType xpos = 0; // cursorpos, lenght of line
 
    CoordType from, to, tempto;
+   //FIXME This doesn't work yet, needs updating afterr default
+   //settings for list or a wxLayoutObjectCmd have changed:
+   //llist->ApplyStyle(&((wxLayoutLine *)this)->m_StyleInfo, dc);
    int highlight = llist->IsSelected(this, &from, &to);
 //   WXLO_DEBUG(("highlight=%d",  highlight ));
    if(highlight == 1) // we need to draw the whole line inverted!
@@ -782,20 +935,7 @@ wxLayoutLine::Draw(wxDC &dc,
       {
          // parts of the line need highlighting
          tempto = xpos+(**i).GetLength();
-         if(tempto >= from && xpos <= to)
-         {
-            tempto = to-xpos;
-            if(tempto > (**i).GetLength())
-               tempto = (**i).GetLength();
-            CoordType tmp = from-xpos;
-            if(tmp < 0) tmp = 0;
-            (**i).Draw(dc, pos, llist, from-xpos, tempto);
-         }
-         else
-         {
-            llist->EndHighlighting(dc); // FIXME! inefficient
-            (**i).Draw(dc, pos, llist);
-         }
+         (**i).Draw(dc, pos, llist, from-xpos, to-xpos);
       }
       else
          (**i).Draw(dc, pos, llist);
@@ -828,12 +968,17 @@ wxLayoutLine::Layout(wxDC &dc,
    wxPoint size;
    bool cursorFound = false;
 
+   m_Dirty = false;
+   
    if(cursorPos)
    {
       *cursorPos = m_Position;
       if(cursorSize) *cursorSize = wxPoint(0,0);
    }
-   
+
+   //FIXME This doesn't work yet, needs updating afterr default
+   //settings for list or a wxLayoutObjectCmd have changed:
+   //llist->ApplyStyle(&m_StyleInfo, dc);
    for(i = m_ObjectList.begin(); i != NULLIT; i++)
    {
       (**i).Layout(dc, llist);
@@ -892,18 +1037,10 @@ wxLayoutLine::Layout(wxDC &dc,
 
    if(m_Height == 0)
    {
-      if(GetPreviousLine()) // empty line
-      {
-         m_Height = GetPreviousLine()->GetHeight();
-         m_BaseLine = GetPreviousLine()->m_BaseLine;
-      }
-      else
-      {
-            CoordType width, height, descent;
-            dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
-            m_Height = height;
-            m_BaseLine = m_Height - descent;
-      }
+      CoordType width, height, descent;
+      dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
+      m_Height = height;
+      m_BaseLine = m_Height - descent;
    }
 
    
@@ -926,6 +1063,7 @@ wxLayoutLine::Layout(wxDC &dc,
       if(m_BaseLine >= cursorSize->y) // the normal case anyway
          cursorPos->y += m_BaseLine-cursorSize->y;
    }
+   RecalculatePositions(1, llist);
 }
 
 
@@ -933,8 +1071,13 @@ wxLayoutLine *
 wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
 {
    wxASSERT(xpos >= 0);
-   
-   if(xpos == 0)
+   //FIXME: this could be optimised, for now be prudent:
+   m_Dirty = true;
+
+   /* 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)
@@ -942,12 +1085,11 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
          // before this.
          prev->m_Next = this;
          m_Previous = prev;
-         m_Previous->m_Height = GetHeight(); // this is a wild guess
+         m_Previous->m_Height = 0; // this is a wild guess
       }
-      MoveLines(+1);
       if(m_Next)
          m_Next->RecalculatePositions(1, llist);
-      return this;
+      return m_Previous;
    }
    
    CoordType offset;
@@ -990,9 +1132,11 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
 void
 wxLayoutLine::MergeNextLine(wxLayoutList *llist)
 {
-   wxASSERT(GetNextLine());
+   wxCHECK_RET(GetNextLine(),"wxLayout internal error: no next line to merge");
    wxLayoutObjectList &list = GetNextLine()->m_ObjectList;
    wxLOiterator i;
+   //FIXME: this could be optimised, for now be prudent:
+   m_Dirty = true;
    
    for(i = list.begin(); i != list.end();)
    {
@@ -1003,6 +1147,7 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
    wxLayoutLine *oldnext = GetNextLine();
    SetNext(GetNextLine()->GetNextLine());
    delete oldnext;
+   GetNextLine()->MoveLines(-1);
    RecalculatePositions(1, llist);
 }
 
@@ -1087,12 +1232,13 @@ wxLayoutLine::Copy(wxLayoutList *llist,
    CoordType firstOffset, lastOffset;
 
    if(to == -1) to = GetLength();
-   
+   if(from == to) return;
+      
    wxLOiterator first = FindObject(from, &firstOffset);
    wxLOiterator last  = FindObject(to, &lastOffset);
 
    // Common special case: only one object
-   if( *first == *last )
+   if( first != NULLIT && last != NULLIT && *first == *last )
    {
       if( (**first).GetType() == WXLO_TYPE_TEXT )
       {
@@ -1142,6 +1288,7 @@ wxLayoutLine::Copy(wxLayoutList *llist,
    }
 }
 
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    
    The wxLayoutList object
@@ -1150,10 +1297,7 @@ wxLayoutLine::Copy(wxLayoutList *llist,
 
 wxLayoutList::wxLayoutList()
 {
-   m_DefaultSetting = NULL;
    m_FirstLine = NULL;
-   m_ColourFG = *wxBLACK;
-   m_ColourBG = *wxWHITE;
    InvalidateUpdateRect();
    Clear();
 }
@@ -1183,19 +1327,20 @@ void
 wxLayoutList::InternalClear(void)
 {
    Empty();
-   if(m_DefaultSetting)
-   {
-      delete m_DefaultSetting;
-      m_DefaultSetting = NULL;
-   }
    m_Selection.m_selecting = false;
    m_Selection.m_valid = false;
 
-   m_CurrentSetting.family = wxSWISS;
-   m_CurrentSetting.size = WXLO_DEFAULTFONTSIZE;
-   m_CurrentSetting.style = wxNORMAL;
-   m_CurrentSetting.weight = wxNORMAL;
-   m_CurrentSetting.underline = 0;
+   m_DefaultSetting.family = wxSWISS;
+   m_DefaultSetting.size = WXLO_DEFAULTFONTSIZE;
+   m_DefaultSetting.style = wxNORMAL;
+   m_DefaultSetting.weight = wxNORMAL;
+   m_DefaultSetting.underline = 0;
+   m_DefaultSetting.m_fg_valid = TRUE;
+   m_DefaultSetting.m_fg = *wxBLACK;
+   m_DefaultSetting.m_bg_valid = TRUE;
+   m_DefaultSetting.m_bg = *wxWHITE;
+   
+   m_CurrentSetting = m_DefaultSetting;
 }
 
 void
@@ -1208,27 +1353,16 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
    if(style != -1)     m_CurrentSetting.style = style;
    if(weight != -1)    m_CurrentSetting.weight = weight;
    if(underline != -1) m_CurrentSetting.underline = underline != 0;
-   if(fg)
-   {
-      m_CurrentSetting.fg_valid = true;
-      m_CurrentSetting.fg_red = fg->Red();
-      m_CurrentSetting.fg_blue = fg->Blue();
-      m_CurrentSetting.fg_green = fg->Green();
-   }
-   if(bg)
-   {
-      m_CurrentSetting.bg_valid = true;
-      m_CurrentSetting.bg_red = bg->Red();
-      m_CurrentSetting.bg_blue = bg->Blue();
-      m_CurrentSetting.bg_green = bg->Green();
-   }
+   if(fg) m_CurrentSetting.m_fg = *fg;
+   if(bg) m_CurrentSetting.m_bg = *bg;
    Insert(
       new wxLayoutObjectCmd(
-         m_CurrentSetting.size,
          m_CurrentSetting.family,
+         m_CurrentSetting.size,
          m_CurrentSetting.style,
          m_CurrentSetting.weight,
-         m_CurrentSetting.underline, fg, bg));
+         m_CurrentSetting.underline,
+         fg, bg));
 }
 
 void
@@ -1245,7 +1379,7 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
    if( bg )
       cbg = wxTheColourDatabase->FindColour(bg);
    
-   SetFont(size,family,style,weight,underline,cfg,cbg);
+   SetFont(family,size,style,weight,underline,cfg,cbg);
 }
 
 void
@@ -1253,12 +1387,9 @@ wxLayoutList::Clear(int family, int size, int style, int weight,
                     int underline, wxColour *fg, wxColour *bg)
 {
    InternalClear();
-   
-   if(m_DefaultSetting)
-      delete m_DefaultSetting;
-
-   m_DefaultSetting = new 
-      wxLayoutStyleInfo(family,size,style,weight,underline,fg,bg);
+   m_DefaultSetting = wxLayoutStyleInfo(family, size, style, weight,
+                                        underline, fg, bg);
+   m_CurrentSetting = m_DefaultSetting;
 }
 
 wxPoint
@@ -1421,6 +1552,7 @@ bool
 wxLayoutList::Insert(wxLayoutObject *obj)
 {
    wxASSERT(m_CursorLine);
+   if(! m_CursorLine) m_CursorLine = GetFirstLine();
    SetUpdateRect(m_CursorScreenPos);
    SetUpdateRect(m_CursorScreenPos+m_CursorSize);
    m_CursorLine->Insert(m_CursorPos.x, obj);
@@ -1429,6 +1561,29 @@ wxLayoutList::Insert(wxLayoutObject *obj)
    return true;
 }
 
+bool
+wxLayoutList::Insert(wxLayoutList *llist)
+{
+   wxASSERT(llist);
+   bool rc = TRUE;
+   
+   for(wxLayoutLine *line = llist->GetFirstLine();
+       line;
+       line = line->GetNextLine()
+      )
+   {
+      for(wxLOiterator i = line->GetFirstObject();
+          i != NULLIT;
+          i++)
+         rc |= Insert(*i);
+      LineBreak();
+   }
+   return rc;
+}
+
+
+
+
 bool
 wxLayoutList::LineBreak(void)
 {
@@ -1439,8 +1594,10 @@ wxLayoutList::LineBreak(void)
    m_CursorLine = m_CursorLine->Break(m_CursorPos.x, this);
    if(setFirst) // we were at beginning of first line
       m_FirstLine = m_CursorLine->GetPreviousLine();
-   m_CursorPos.y++;
+   if(m_CursorPos.x != 0)
+      m_CursorPos.y++;
    m_CursorPos.x = 0;
+// doesn't help   m_CursorLine.MarkDirty();
    m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
    return true;
 }
@@ -1544,7 +1701,7 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
 
    // first, make sure everything is calculated - this might not be
    // needed, optimise it later
-   ApplyStyle(m_DefaultSetting, dc);
+   ApplyStyle(&m_DefaultSetting, dc);
    while(line)
    {
       line->RecalculatePosition(this); // so we don't need to do it all the time
@@ -1568,22 +1725,32 @@ wxLayoutList::GetCursorScreenPos(wxDC &dc)
    return m_CursorScreenPos;
 }
 
+/*
+  Is called before each Draw(). Now, it will re-layout all lines which 
+  have changed.
+*/
 void
-wxLayoutList::Layout(wxDC &dc, CoordType bottom)
+wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll)
 {
    wxLayoutLine *line = m_FirstLine;
-
+   
    // first, make sure everything is calculated - this might not be
    // needed, optimise it later
-   ApplyStyle(m_DefaultSetting, dc);
+   ApplyStyle(&m_DefaultSetting, dc);
    while(line)
    {
-      if(line == m_CursorLine)
-         line->Layout(dc, this, (wxPoint *)&m_CursorScreenPos, (wxPoint *)&m_CursorSize, m_CursorPos.x);
-      else
-         line->Layout(dc, this);
-      // little condition to speed up redrawing:
-      if(bottom != -1 && line->GetPosition().y > bottom) break;
+      if(forceAll || line->IsDirty())
+      {
+         line->GetStyleInfo() = m_CurrentSetting;
+         if(line == m_CursorLine)
+            line->Layout(dc, this, (wxPoint *)&m_CursorScreenPos,
+                         (wxPoint *)&m_CursorSize, m_CursorPos.x);
+         else
+            line->Layout(dc, this);
+         // little    condition to speed up redrawing:
+         if(bottom != -1 && line->GetPosition().y > bottom) break;
+      }
+      line->RecalculatePositions(1,this);
       line = line->GetNextLine();
    }
 
@@ -1606,16 +1773,19 @@ wxLayoutList::Draw(wxDC &dc,
 {
    wxLayoutLine *line = m_FirstLine;
 
-   Layout(dc, bottom);
-   ApplyStyle(m_DefaultSetting, dc);
-   wxBrush brush(m_ColourBG, wxSOLID);
+   Layout(dc); 
+   ApplyStyle(&m_DefaultSetting, dc);
+   wxBrush brush(m_CurrentSetting.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))
          line->Draw(dc, this, offset);
+      else
+         line->Layout(dc, this);
       // little condition to speed up redrawing:
       if(bottom != -1 && line->GetPosition().y > bottom) break;
       line = line->GetNextLine();
@@ -1638,7 +1808,7 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
    wxPoint p;
    
    // we need to run a layout here to get font sizes right :-(
-   ApplyStyle(m_DefaultSetting, dc);
+   ApplyStyle(&m_DefaultSetting, dc);
    while(line)
    {
       p = line->GetPosition();
@@ -1740,22 +1910,29 @@ wxLayoutList::SetUpdateRect(CoordType x, CoordType y)
 }
 
 void
-wxLayoutList::StartSelection(void)
+wxLayoutList::StartSelection(wxPoint cpos)
 {
-   WXLO_DEBUG(("Starting selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y));
-   m_Selection.m_CursorA = m_CursorPos;
-   m_Selection.m_CursorB = m_CursorPos;
+   if(cpos.x == -1)
+      cpos = m_CursorPos;
+   WXLO_DEBUG(("Starting selection at %ld/%ld", cpos.x, cpos.y));
+   m_Selection.m_CursorA = cpos;
+   m_Selection.m_CursorB = cpos;
    m_Selection.m_selecting = true;
    m_Selection.m_valid = false;
 }
 
 void
-wxLayoutList::ContinueSelection(void)
+wxLayoutList::ContinueSelection(wxPoint cpos)
 {
+   if(cpos.x == -1)
+      cpos = m_CursorPos;
    wxASSERT(m_Selection.m_selecting == true);
    wxASSERT(m_Selection.m_valid == false);
-   WXLO_DEBUG(("Continuing selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y));
-   m_Selection.m_CursorB = m_CursorPos;
+   WXLO_DEBUG(("Continuing selection at %ld/%ld", cpos.x, cpos.y));
+   if(m_Selection.m_CursorB <= cpos)
+      m_Selection.m_CursorB = cpos;
+   else
+      m_Selection.m_CursorA = cpos;
    // We always want m_CursorA <= m_CursorB!
    if(! (m_Selection.m_CursorA <= m_Selection.m_CursorB))
    {
@@ -1766,10 +1943,12 @@ wxLayoutList::ContinueSelection(void)
 }
 
 void
-wxLayoutList::EndSelection(void)
+wxLayoutList::EndSelection(wxPoint cpos)
 {
-   ContinueSelection();
-   WXLO_DEBUG(("Ending selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y));
+   if(cpos.x == -1)
+      cpos = m_CursorPos;
+   ContinueSelection(cpos);
+   WXLO_DEBUG(("Ending selection at %ld/%ld", cpos.x, cpos.y));
    m_Selection.m_selecting = false;
    m_Selection.m_valid = true;
 }
@@ -1892,8 +2071,9 @@ void
 wxLayoutList::StartHighlighting(wxDC &dc)
 {
 #if SHOW_SELECTIONS
-   dc.SetTextForeground(m_ColourBG);
-   dc.SetTextBackground(m_ColourFG);
+   dc.SetTextForeground(m_CurrentSetting.m_bg);
+   dc.SetTextBackground(m_CurrentSetting.m_fg);
+   dc.SetBackgroundMode(wxSOLID);
 #endif
 }
 
@@ -1902,8 +2082,9 @@ void
 wxLayoutList::EndHighlighting(wxDC &dc)
 {
 #if SHOW_SELECTIONS
-   dc.SetTextForeground(m_ColourFG);
-   dc.SetTextBackground(m_ColourBG);
+   dc.SetTextForeground(m_CurrentSetting.m_fg);
+   dc.SetTextBackground(m_CurrentSetting.m_bg);
+   dc.SetBackgroundMode(wxTRANSPARENT);
 #endif
 }
 
@@ -1963,7 +2144,7 @@ wxLayoutList::Copy(const wxPoint &from,
 }
 
 wxLayoutList *
-wxLayoutList::GetSelection(void)
+wxLayoutList::GetSelection(wxLayoutDataObject *wxlo, bool invalidate)
 {
    if(! m_Selection.m_valid)
    {
@@ -1973,47 +2154,56 @@ wxLayoutList::GetSelection(void)
          return NULL;
    }
    
-   m_Selection.m_valid = false;
-   return Copy( m_Selection.m_CursorA, m_Selection.m_CursorB );
+   if(invalidate) m_Selection.m_valid = false;
+
+   wxLayoutList *llist = Copy( m_Selection.m_CursorA,
+                               m_Selection.m_CursorB );
+   
+   if(llist && wxlo) // export as data object, too
+   {
+      wxString string;
+
+      wxLayoutExportObject *export;
+      wxLayoutExportStatus status(llist);
+      while((export = wxLayoutExport( &status, WXLO_EXPORT_AS_OBJECTS)) != NULL)
+      {
+         if(export->type == WXLO_EXPORT_EMPTYLINE)
+            ; //FIXME missing support for linebreaks in string format
+         else
+            export->content.object->Write(string);
+         delete export;
+      }
+      wxlo->SetData(string.c_str(), string.Length()+1);
+   }
+   return llist;
 }
 
 
 
-#define COPY_SI(what) if(si->what != -1) m_CurrentSetting.what = si->what;
+#define COPY_SI(what) if(si->what != -1) { m_CurrentSetting.what = si->what; fontChanged = TRUE; }
 
 void
 wxLayoutList::ApplyStyle(wxLayoutStyleInfo *si, wxDC &dc)
 {
+   bool fontChanged = FALSE;
    COPY_SI(family);
    COPY_SI(size);
    COPY_SI(style);
    COPY_SI(weight);
    COPY_SI(underline);
+   if(fontChanged)
+      dc.SetFont( m_FontCache.GetFont(m_CurrentSetting) );
 
-   
-   if(si->fg_valid)
+   if(si->m_fg_valid)
    {
-      m_CurrentSetting.fg_valid = true;
-      m_CurrentSetting.fg_red = si->fg_red;
-      m_CurrentSetting.fg_green = si->fg_green;
-      m_CurrentSetting.fg_blue = si->fg_blue;
+      m_CurrentSetting.m_fg = si->m_fg;
+      dc.SetTextForeground(m_CurrentSetting.m_fg);
    }
-   if(si->bg_valid)
+   if(si->m_bg_valid)
    {
-      m_CurrentSetting.bg_valid = true;
-      m_CurrentSetting.bg_red = si->bg_red;
-      m_CurrentSetting.bg_green = si->bg_green;
-      m_CurrentSetting.bg_blue = si->bg_blue;
+      m_CurrentSetting.m_bg = si->m_bg;
+      dc.SetTextBackground(m_CurrentSetting.m_bg);
    }
-
-   m_ColourFG = wxColour(m_CurrentSetting.fg_red,
-                         m_CurrentSetting.fg_green,
-                         m_CurrentSetting.fg_blue);
-   m_ColourBG = wxColour(m_CurrentSetting.bg_red,
-                         m_CurrentSetting.bg_green,
-                         m_CurrentSetting.bg_blue);
-   dc.SetTextForeground(m_ColourFG);
-   dc.SetTextBackground(m_ColourBG);
 }
 
 
@@ -2046,6 +2236,9 @@ wxLayoutPrintout::wxLayoutPrintout(wxLayoutList *llist,
 {
    m_llist = llist;
    m_title = title;
+   // remove any highlighting which could interfere with printing:
+   m_llist->StartSelection();
+   m_llist->EndSelection(); 
 }
 
 wxLayoutPrintout::~wxLayoutPrintout()
@@ -2203,3 +2396,18 @@ wxLayoutPrintout::DrawHeader(wxDC &dc,
 #endif
 
 
+wxFont &
+wxFontCache::GetFont(int family, int size, int style, int weight, 
+                     bool underline)
+{
+   for(wxFCEList::iterator i = m_FontList.begin();
+       i != m_FontList.end(); i++)
+      if( (**i).Matches(family, size, style, weight, underline) )
+         return (**i).GetFont();
+   // not found:
+   wxFontCacheEntry *fce = new wxFontCacheEntry(family, size, style,
+                                                weight, underline);
+   m_FontList.push_back(fce);
+   return fce->GetFont();
+}