]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/richedit/wxllist.cpp
Ifdef'd out sample code for wxStaticBitmap. It's not working under
[wxWidgets.git] / samples / richedit / wxllist.cpp
index 6fc798d84ae55317f72192868cf905dee7f52e5c..e4ca6a41979a983496d640adc4fc8090a7124d8d 100644 (file)
@@ -463,23 +463,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;
@@ -629,25 +622,35 @@ wxLayoutObjectCmd::Layout(wxDC &dc, class wxLayoutList * llist)
 
 wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
 {
-   m_LineNumber = 0;
    m_Width = m_Height = 0;
    m_Length = 0;
+
+   m_updateLeft = -1;
    MarkDirty(0);
+
    m_Previous = prev;
    m_Next = NULL;
+
+   m_LineNumber = 0;
    RecalculatePosition(llist);
+
    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_StyleInfo = llist->GetDefaultStyleInfo();
+
+   llist->IncNumLines();
 }
 
 wxLayoutLine::~wxLayoutLine()
@@ -738,30 +741,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();
 }
 
@@ -1008,12 +1026,24 @@ wxLayoutLine::DeleteWord(CoordType xpos)
 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;
+   // maintain linked list integrity
+   if(m_Next)
+       m_Next->m_Previous = m_Previous;
+   if(m_Previous)
+       m_Previous->m_Next = m_Next;
+
+   wxLayoutLine *next = m_Next;
+   if ( next )
+   {
+      // get the line numbers right again
+      next->MoveLines(-1);
+   }
+
    if(update)
    {
-      m_Next->MoveLines(-1);
-      m_Next->RecalculatePositions(1, llist);
+      if ( next )
+         next->RecalculatePositions(1, llist);
+
       /* We assume that if we have more than one object in the list,
          this means that we have a command object, so we need to
          update the following lines. */
@@ -1023,8 +1053,11 @@ wxLayoutLine::DeleteLine(bool update, wxLayoutList *llist)
          )
          MarkNextDirty(-1);
    }
-   wxLayoutLine *next = m_Next;
+
    delete this;
+
+   llist->DecNumLines();
+
    return next;
 }
 
@@ -1075,6 +1108,7 @@ wxLayoutLine::Layout(wxDC &dc,
                      wxLayoutList *llist,
                      wxPoint *cursorPos,
                      wxPoint *cursorSize,
+                     wxLayoutStyleInfo *cursorStyle,
                      int cx,
                      bool suppressSIupdate)
 {
@@ -1137,19 +1171,28 @@ wxLayoutLine::Layout(wxDC &dc,
                else
                   str = 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
             }
@@ -1212,7 +1255,7 @@ wxLayoutLine::Layout(wxDC &dc,
    }
 
    // 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:
@@ -1352,6 +1395,8 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
 #endif // 0
    }
 
+   llist->DecNumLines();
+
    delete oldnext;
 }
 
@@ -1507,6 +1552,7 @@ wxLayoutList::wxLayoutList()
    m_caret = NULL;
 #endif // WXLAYOUT_USE_CARET
 
+   m_numLines = 0;
    m_FirstLine = NULL;
    InvalidateUpdateRect();
    Clear();
@@ -1515,7 +1561,10 @@ wxLayoutList::wxLayoutList()
 wxLayoutList::~wxLayoutList()
 {
    InternalClear();
+   Empty();
    m_FirstLine->DeleteLine(false, this);
+
+   wxASSERT_MSG( m_numLines == 0, "line count calculation broken" );
 }
 
 void
@@ -1537,7 +1586,6 @@ wxLayoutList::Empty(void)
 void
 wxLayoutList::InternalClear(void)
 {
-   Empty();
    m_Selection.m_selecting = false;
    m_Selection.m_valid = false;
 
@@ -1552,6 +1600,7 @@ wxLayoutList::InternalClear(void)
    m_DefaultStyleInfo.m_bg = *wxWHITE;
 
    m_CurrentStyleInfo = m_DefaultStyleInfo;
+   m_CursorStyleInfo = m_DefaultStyleInfo;
 }
 
 void
@@ -1601,6 +1650,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
@@ -1761,70 +1815,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" );
 
    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 wxString& text = tobj->GetText();
+            const char *start = text.c_str();
+            const char *end = start + text.length();
             const char *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);
@@ -1898,7 +2040,6 @@ bool
 wxLayoutList::LineBreak(void)
 {
    wxASSERT(m_CursorLine);
-   bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0);
 
    AddCursorPosToUpdateRect();
 
@@ -1909,16 +2050,20 @@ 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)
+   if(m_CursorLine->GetPreviousLine() == NULL)
+      m_FirstLine = m_CursorLine;
+   if(m_CursorPos.x > 0)
       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;
 
@@ -2084,49 +2229,9 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
    }
 }
 
-void
-wxLayoutList::UpdateCursorScreenPos(wxDC &dc,
-                                    bool resetCursorMovedFlag,
-                                    const wxPoint& translate)
-{
-   wxCHECK_RET( m_CursorLine, "no cursor line" );
-
-   if ( m_movedCursor )
-   {
-      // 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,
-                           /* suppress update */ true);
-      ApplyStyle(SiBackup, dc); // restore it
-
-      if ( resetCursorMovedFlag )
-      {
-#ifdef WXLAYOUT_USE_CARET
-            // adjust the caret position
-            wxPoint coords(m_CursorScreenPos);
-            coords += translate;
-
-            // and set it
-            m_caret->Move(coords);
-#endif // WXLAYOUT_USE_CARET
-
-         m_movedCursor = false;
-      }
-   }
-}
-
 wxPoint
 wxLayoutList::GetCursorScreenPos(wxDC &dc)
 {
-   // this function is called with wxMemoryDC argument from ScrollToCursor(),
-   // for example, so it shouldn't clear "cursor moved" flag - or else the
-   // cursor won't be moved when UpdateCursorScreenPos() is called with the
-   // "real" (i.e. the one used for drawing) wxDC.
-   UpdateCursorScreenPos(dc, false /* don't reset the flag */);
-
    return m_CursorScreenPos;
 }
 
@@ -2136,8 +2241,7 @@ wxLayoutList::GetCursorScreenPos(wxDC &dc)
 */
 void
 wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
-                     wxPoint *cpos = NULL,
-                     wxPoint *csize = NULL)
+                     wxPoint *cpos, wxPoint *csize)
 {
    // first, make sure everything is calculated - this might not be
    // needed, optimise it later
@@ -2158,13 +2262,25 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
          // 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);
+                         (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;
+            }
+         }
+         else
+            if(cpos && line->GetLineNumber() == cpos->y)
+               line->Layout(dc, this,
+                            cpos,
+                            csize, NULL, cpos->x);
          else
             line->Layout(dc, this);
          // little condition to speed up redrawing:
@@ -2184,7 +2300,7 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll,
 }
 
 wxPoint
-wxLayoutList::GetScreenPos(wxDC &dc, const wxPoint &cpos, wxPoint *csize = NULL)
+wxLayoutList::GetScreenPos(wxDC &dc, const wxPoint &cpos, wxPoint *csize)
 {
    wxPoint pos = cpos;
    Layout(dc, -1, false, &pos, csize);
@@ -2199,6 +2315,23 @@ wxLayoutList::Draw(wxDC &dc,
 {
    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;
+   }
+
    /* 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
@@ -2212,21 +2345,19 @@ wxLayoutList::Draw(wxDC &dc,
    {
       // only draw if between top and bottom:
       if((top == -1 ||
-          line->GetPosition().y + line->GetHeight() >= top))
+          line->GetPosition().y + line->GetHeight() > top))
       {
 //         if(! style_set)
          {
             ApplyStyle(line->GetStyleInfo(), dc);
             style_set = true;
          }
+         // little condition to speed up redrawing:
+         if(bottom != -1
+            && line->GetPosition().y+line->GetHeight() >= bottom)
+            break;
          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();
@@ -2243,7 +2374,9 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
                                bool *found)
 {
    // First, find the right line:
-   wxLayoutLine *line = m_FirstLine;
+   wxLayoutLine
+      *line = m_FirstLine,
+      *lastline = m_FirstLine;
    wxPoint p;
 
    ApplyStyle(m_DefaultStyleInfo, dc);
@@ -2252,28 +2385,30 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
       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
+      lastline = line;
       line = line->GetNextLine();
    }
-   if(line == NULL)
+
+   bool didFind = line != NULL;
+
+   if ( !line )
    {
-      if(found) *found = false;
-      return NULL; // not found
+      // use the last line:
+      line = lastline;
    }
-   if(cursorPos) cursorPos->y = line->GetLineNumber();
+
+   if ( cursorPos )
+       cursorPos->y = line->GetLineNumber();
+
+   bool foundinline = true;
    // Now, find the object in the line:
-   wxLOiterator i = line->FindObjectScreen(dc, pos.x,
-                                           cursorPos ? & cursorPos->x : NULL ,
-                                           found);
+   wxLOiterator i = line->FindObjectScreen(dc, this,
+                                           pos.x,
+                                           cursorPos ? &cursorPos->x : NULL,
+                                           &foundinline);
+   if ( found )
+      *found = didFind && foundinline;
+
    return (i == NULLIT) ? NULL : *i;
 
 }
@@ -2320,6 +2455,9 @@ wxLayoutList::GetSize(void) const
 void
 wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
 {
+   if ( m_movedCursor )
+      m_movedCursor = false;
+
    wxPoint coords(m_CursorScreenPos);
    coords += translate;
 
@@ -2334,12 +2472,15 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
    wxLogStatus("Cursor is at (%d, %d)", m_CursorPos.x, m_CursorPos.y);
 #endif
 
-#ifndef WXLAYOUT_USE_CARET
-   dc.SetBrush(*wxBLACK_BRUSH);
-   dc.SetLogicalFunction(wxXOR);
+#ifdef WXLAYOUT_USE_CARET
+   m_caret->Move(coords);
+#else // !WXLAYOUT_USE_CARET
+   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);
@@ -2347,6 +2488,7 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
    }
    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);
@@ -2443,28 +2585,17 @@ wxLayoutList::DiscardSelection()
 
    m_Selection.m_valid =
    m_Selection.m_selecting = false;
-
-   // 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_discarded = true;
 }
 
 bool
-wxLayoutList::IsSelecting(void)
+wxLayoutList::IsSelecting(void) const
 {
    return m_Selection.m_selecting;
 }
 
 bool
-wxLayoutList::IsSelected(const wxPoint &cursor)
+wxLayoutList::IsSelected(const wxPoint &cursor) const
 {
    if ( !HasSelection() )
       return false;
@@ -2529,44 +2660,29 @@ wxLayoutList::DeleteSelection(void)
       return;
    }
 
+   // We now know that the two lines are different:
 
    wxLayoutLine
-      * firstLine = NULL,
-      * lastLine = NULL;
-
-   for(firstLine = m_FirstLine;
-       firstLine && firstLine->GetLineNumber() < m_Selection.m_CursorA.y;
-       firstLine=firstLine->GetNextLine())
-      ;
-   if(!firstLine || firstLine->GetLineNumber() != m_Selection.m_CursorA.y)
-      return;
-
-
-   for(lastLine = m_FirstLine;
-       lastLine && lastLine->GetLineNumber() < m_Selection.m_CursorB.y;
-       lastLine=lastLine->GetNextLine())
-      ;
-   if(!lastLine || lastLine->GetLineNumber() != m_Selection.m_CursorB.y)
-      return;
-
-
-   // We now know that the two lines are different:
+      * firstLine = GetLine(m_Selection.m_CursorA.y),
+      * lastLine = GetLine(m_Selection.m_CursorB.y);
 
    // First, delete what's left of this line:
    MoveCursorTo(m_Selection.m_CursorA);
    DeleteToEndOfLine();
 
-   wxLayoutLine *nextLine = firstLine->GetNextLine();
+   wxLayoutLine *prevLine = firstLine->GetPreviousLine(),
+                *nextLine = firstLine->GetNextLine();
    while(nextLine && nextLine != lastLine)
       nextLine = nextLine->DeleteLine(false, this);
 
    // Now nextLine = lastLine;
    Delete(1); // This joins firstLine and nextLine
-   Delete(m_Selection.m_CursorB.x); // This deletes the first x
-   // positions
+   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->RecalculatePositions(1, this);
 }
 
 /// Starts highlighting the selection
@@ -2812,6 +2928,9 @@ bool wxLayoutPrintout::OnPrintPage(int page)
       int top, bottom;
       top = (page - 1)*m_PrintoutHeight;
       bottom = top + m_PrintoutHeight;
+
+      WXLO_DEBUG(("OnPrintPage(%d) printing from %d to %d", page, top, 
+                  bottom));
       // SetDeviceOrigin() doesn't work here, so we need to manually
       // translate all coordinates.
       wxPoint translate(m_Offset.x,m_Offset.y-top);
@@ -2836,13 +2955,21 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom,
    float scale = ScaleDC(&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);
+
+   // 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
-
+#if 0
+   // We should really use the margin settings of wxWindows somehow.
+   m_Offset = wxPoint(0,0);
+   // This is the length of the printable area.
+   m_PrintoutHeight = m_PageHeight;
+   m_PrintoutHeight = (int)( m_PrintoutHeight / scale); // we want to use the real paper height
+#endif
+   
 
    m_NumOfPages = 1 +
       (int)( m_llist->GetSize().y / (float)(m_PrintoutHeight));