+ }
+ wxASSERT(0); // we should never arrive here
+}
+
+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);
+ }
+ wxLayoutLine *next = m_Next;
+ delete this;
+ return next;
+}
+
+void
+wxLayoutLine::Draw(wxDC &dc,
+ wxLayoutList *llist,
+ const wxPoint & offset) const
+{
+ wxLayoutObjectList::iterator i;
+ wxPoint pos = offset;
+ pos = pos + GetPosition();
+
+ pos.y += m_BaseLine;
+
+ 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!
+ llist->StartHighlighting(dc);
+ else
+ llist->EndHighlighting(dc);
+
+ for(i = m_ObjectList.begin(); i != NULLIT; i++)
+ {
+ if(highlight == -1) // partially highlight line
+ {
+ // parts of the line need highlighting
+ tempto = xpos+(**i).GetLength();
+ (**i).Draw(dc, pos, llist, from-xpos, to-xpos);
+ }
+ else
+ (**i).Draw(dc, pos, llist);
+ pos.x += (**i).GetWidth();
+ xpos += (**i).GetLength();
+ }
+}
+
+void
+wxLayoutLine::Layout(wxDC &dc,
+ wxLayoutList *llist,
+ wxPoint *cursorPos,
+ wxPoint *cursorSize,
+ int cx)
+{
+ wxLayoutObjectList::iterator i;
+
+ CoordType
+ oldWidth = m_Width,
+ oldHeight = m_Height;
+ CoordType
+ topHeight, bottomHeight; // above and below baseline
+ CoordType
+ objHeight = 0,
+ objTopHeight, objBottomHeight;
+ CoordType
+ len, count = 0;
+ m_Height = 0; m_BaseLine = 0;
+ m_Width = 0;
+ topHeight = 0; bottomHeight = 0;
+ 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);
+ size = (**i).GetSize(&objTopHeight, &objBottomHeight);
+
+ if(cursorPos && ! cursorFound)
+ { // we need to check whether the text cursor is here
+ len = (**i).GetLength();
+ if(count <= cx && count+len > cx)
+ {
+ if((**i).GetType() == WXLO_TYPE_TEXT)
+ {
+ len = cx - count; // pos in object
+ CoordType width, height, descent;
+ dc.GetTextExtent((*(wxLayoutObjectText*)*i).GetText().substr(0,len),
+ &width, &height, &descent);
+ cursorPos->x += width;
+ cursorPos->y = m_Position.y;
+ wxString str;
+ if(len < (**i).GetLength())
+ str = (*(wxLayoutObjectText*)*i).GetText().substr(len,1);
+ 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 = objHeight;
+ cursorSize->x = width;
+ cursorSize->y = height;
+ cursorFound = true; // no more checks
+ }
+ else
+ { // on some other object
+ CoordType top, bottom; // unused
+ *cursorSize = (**i).GetSize(&top,&bottom);
+ cursorPos->y = m_Position.y;
+ cursorFound = true; // no more checks
+ }
+ }
+ else
+ {
+ count += len;
+ cursorPos->x += (**i).GetWidth();
+ }
+ } // cursor finding
+ objHeight = size.y;
+ m_Width += size.x;
+ if(objHeight > m_Height) m_Height = objHeight;
+ if(objTopHeight > topHeight) topHeight = objTopHeight;
+ if(objBottomHeight > bottomHeight) bottomHeight = objBottomHeight;
+ }
+
+ // special case of a line which becomes empty (after deletion, for example):
+ // we should invalidate the screen space it occupied (usually this happens
+ // from wxLayoutObject::Layout called in the loop above)
+ if ( m_ObjectList.empty() )
+ {
+ wxPoint position(GetPosition());
+ llist->SetUpdateRect(position.x + oldWidth + MSW_CORRECTION,
+ position.y + oldHeight + MSW_CORRECTION);
+ }
+
+ if(topHeight + bottomHeight > m_Height)
+ m_Height = topHeight+bottomHeight;
+ m_BaseLine = topHeight;
+
+ if(m_Height == 0)
+ {
+ CoordType width, height, descent;
+ dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
+ m_Height = height;
+ m_BaseLine = m_Height - descent;
+ }
+
+
+ // tell next line about coordinate change
+ if(m_Next && objHeight != oldHeight)
+ m_Next->RecalculatePositions(0, llist);
+
+ // We need to check whether we found a valid cursor size:
+ if(cursorPos)
+ {
+ // 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)
+ {
+ CoordType width, height, descent;
+ dc.GetTextExtent(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);
+}
+
+
+wxLayoutLine *
+wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
+{
+ wxASSERT(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)
+ { // 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)
+ // must be at the end of the line then
+ return new wxLayoutLine(this, llist);
+ // split this line:
+
+ wxLayoutLine *newLine = new wxLayoutLine(this, llist);
+ // split object at i:
+ if((**i).GetType() == WXLO_TYPE_TEXT && offset != 0)
+ {
+ wxString left, right;
+ wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
+ left = tobj->GetText().substr(0,offset);
+ right = tobj->GetText().substr(offset,tobj->GetLength()-offset);
+ // current text object gets set to left half
+ tobj->GetText() = left; // set new text
+ newLine->Append(new wxLayoutObjectText(right));
+ m_Length -= right.Length();
+ i++; // don't move this object to the new list
+ }
+ else
+ if(offset > 0)
+ i++; // move objects from here to new list
+
+ while(i != m_ObjectList.end())
+ {
+ newLine->Append(*i);
+ m_Length -= (**i).GetLength();
+ m_ObjectList.remove(i); // remove without deleting it
+ }
+ if(m_Next)
+ m_Next->RecalculatePositions(2, llist);
+ return newLine;
+}
+
+
+void
+wxLayoutLine::MergeNextLine(wxLayoutList *llist)
+{
+ 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;
+
+ wxLayoutObject *last = NULL;
+ for(i = list.begin(); i != list.end();)
+ {
+ wxLayoutObject *current = *i;
+
+ // merge text objects together for efficiency
+ if ( last && last->GetType() == WXLO_TYPE_TEXT &&
+ current->GetType() == WXLO_TYPE_TEXT )
+ {
+ wxLayoutObjectText *textObj = (wxLayoutObjectText *)last;
+ wxString text(textObj->GetText());
+ text += ((wxLayoutObjectText *)current)->GetText();
+ textObj->SetText(text);
+
+ list.erase(i); // remove and delete it
+ }
+ else
+ {
+ // just append the object "as was"
+ current->UnattachFromLine();
+ Append(current);
+
+ list.remove(i); // remove without deleting it
+ }
+ }
+ wxASSERT(list.empty());
+
+ wxLayoutLine *oldnext = GetNextLine();
+ wxLayoutLine *nextLine = oldnext->GetNextLine();
+ SetNext(nextLine);
+ delete oldnext;
+ if ( nextLine )
+ {
+ nextLine->MoveLines(-1);
+ }
+
+ // no RecalculatePositions needed - called from Delete() anyhow
+}
+
+CoordType
+wxLayoutLine::GetWrapPosition(CoordType column)
+{
+ CoordType offset;
+ wxLOiterator i = FindObject(column, &offset);
+ if(i == NULLIT) return -1; // cannot wrap
+
+ // go backwards through the list and look for space in text objects
+ do
+ {
+ if((**i).GetType() == WXLO_TYPE_TEXT)
+ {
+ do
+ {
+ if( isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
+ return column;
+ else
+ {
+ offset--;
+ column--;
+ }
+ }while(offset != -1);
+ i--; // move on to previous object
+ }
+ else
+ {
+ column -= (**i).GetLength();
+ i--;
+ }
+ if( i != NULLIT)
+ offset = (**i).GetLength();
+ }while(i != NULLIT);
+ /* If we reached the begin of the list and have more than one
+ object, that one is longer than the margin, so break behind
+ it. */
+ CoordType pos = 0;
+ i = m_ObjectList.begin();
+ while(i != NULLIT && (**i).GetType() != WXLO_TYPE_TEXT)
+ {
+ pos += (**i).GetLength();
+ i++;
+ }
+ if(i == NULLIT) return -1; //why should this happen?
+ 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
+}
+
+
+#ifdef WXLAYOUT_DEBUG
+void
+wxLayoutLine::Debug(void)
+{
+ wxString tmp;
+ wxPoint pos = GetPosition();
+ WXLO_DEBUG(("Line %ld, Pos (%ld,%ld), Height %ld",
+ (long int) GetLineNumber(),
+ (long int) pos.x, (long int) pos.y,
+ (long int) GetHeight()));
+ if(m_ObjectList.begin() != NULLIT)
+ (**m_ObjectList.begin()).Debug();
+
+}
+#endif
+
+void
+wxLayoutLine::Copy(wxLayoutList *llist,
+ CoordType from,
+ CoordType to)
+{
+ 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 != NULLIT && last != NULLIT && *first == *last )
+ {
+ if( (**first).GetType() == WXLO_TYPE_TEXT )
+ {
+ llist->Insert(new wxLayoutObjectText(
+ ((wxLayoutObjectText
+ *)*first)->GetText().substr(firstOffset,
+ lastOffset-firstOffset))
+ );
+ return;
+ }
+ else // what can we do?
+ {
+ if(lastOffset > firstOffset) // i.e. +1 :-)
+ llist->Insert( (**first).Copy() );
+ return;
+ }
+ }
+
+ // If we reach here, we can safely copy the whole first object from
+ // the firstOffset position on:
+ if((**first).GetType() == WXLO_TYPE_TEXT && firstOffset != 0)
+ {
+ llist->Insert(new wxLayoutObjectText(
+ ((wxLayoutObjectText *)*first)->GetText().substr(firstOffset))
+ );
+ }
+ else if(firstOffset == 0)
+ llist->Insert( (**first).Copy() );
+ // else nothing to copy :-(
+
+ // Now we copy all objects before the last one:
+ wxLOiterator i = first; i++;
+ for( ; i != last; i++)
+ llist->Insert( (**i).Copy() );
+
+ // And now the last object:
+ if(lastOffset != 0)
+ {
+ if( (**last).GetType() == WXLO_TYPE_TEXT )
+ {
+ llist->Insert(new wxLayoutObjectText(
+ ((wxLayoutObjectText *)*last)->GetText().substr(0,lastOffset))
+ );
+ }
+ else
+ llist->Insert( (**last).Copy() );
+ }
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+ The wxLayoutList object
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+wxLayoutList::wxLayoutList()
+{
+#ifdef WXLAYOUT_USE_CARET
+ m_caret = NULL;
+#endif // WXLAYOUT_USE_CARET
+
+ m_FirstLine = NULL;
+ InvalidateUpdateRect();
+ Clear();
+}
+
+wxLayoutList::~wxLayoutList()
+{
+ InternalClear();
+ m_FirstLine->DeleteLine(false, this);
+}
+
+void
+wxLayoutList::Empty(void)
+{
+ while(m_FirstLine)
+ m_FirstLine = m_FirstLine->DeleteLine(false, this);
+
+ m_CursorPos = wxPoint(0,0);
+ m_CursorScreenPos = wxPoint(0,0);
+ m_CursorSize = wxPoint(0,0);
+ m_FirstLine = new wxLayoutLine(NULL, this); // empty first line
+ m_CursorLine = m_FirstLine;
+ InvalidateUpdateRect();
+}
+
+
+void
+wxLayoutList::InternalClear(void)
+{
+ Empty();
+ m_Selection.m_selecting = false;
+ m_Selection.m_valid = false;
+
+ 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
+wxLayoutList::SetFont(int family, int size, int style, int weight,
+ int underline, wxColour *fg,
+ wxColour *bg)
+{
+ if(family != -1) m_CurrentSetting.family = family;
+ if(size != -1) m_CurrentSetting.size = size;
+ 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.m_fg = *fg;
+ if(bg) m_CurrentSetting.m_bg = *bg;
+ Insert(
+ new wxLayoutObjectCmd(
+ m_CurrentSetting.family,
+ m_CurrentSetting.size,
+ m_CurrentSetting.style,
+ m_CurrentSetting.weight,
+ m_CurrentSetting.underline,
+ fg, bg));
+}
+
+void
+wxLayoutList::SetFont(int family, int size, int style, int weight,
+ int underline, char const *fg, char const *bg)
+
+{
+ wxColour
+ *cfg = NULL,
+ *cbg = NULL;
+
+ if( fg )
+ cfg = wxTheColourDatabase->FindColour(fg);
+ if( bg )
+ cbg = wxTheColourDatabase->FindColour(bg);
+
+ SetFont(family,size,style,weight,underline,cfg,cbg);
+}
+
+void
+wxLayoutList::Clear(int family, int size, int style, int weight,
+ int underline, wxColour *fg, wxColour *bg)
+{
+ InternalClear();
+ m_DefaultSetting = wxLayoutStyleInfo(family, size, style, weight,
+ underline, fg, bg);
+ m_CurrentSetting = m_DefaultSetting;
+}
+
+wxPoint
+wxLayoutList::FindText(const wxString &needle, const wxPoint &cpos) const
+{
+ int xpos;
+
+ wxLayoutLine *line;
+ for(line = m_FirstLine;
+ line;
+ line = line->GetNextLine())
+ {
+ if(line->GetLineNumber() >= cpos.y)
+ {
+ xpos = line->FindText(needle,
+ (line->GetLineNumber() == cpos.y) ?
+ cpos.x : 0);
+ if(xpos != -1)
+ return wxPoint(xpos, line->GetLineNumber());
+ }
+ }
+ return wxPoint(-1,-1);
+}
+
+
+bool
+wxLayoutList::MoveCursorTo(wxPoint const &p)
+{
+ AddCursorPosToUpdateRect();
+
+ wxLayoutLine *line = m_FirstLine;
+ while(line && line->GetLineNumber() != p.y)
+ line = line->GetNextLine();
+ if(line && line->GetLineNumber() == p.y) // found it
+ {
+ m_CursorPos.y = p.y;
+ m_CursorLine = line;
+ CoordType len = line->GetLength();
+ if(len >= p.x)
+ {
+ m_CursorPos.x = p.x;
+ return true;
+ }
+ else
+ {
+ m_CursorPos.x = len;
+ return false;
+ }
+ }
+ return false;
+}
+
+bool
+wxLayoutList::MoveCursorVertically(int n)
+{
+ AddCursorPosToUpdateRect();
+
+ bool rc;
+ if(n < 0) // move up
+ {
+ if(m_CursorLine == m_FirstLine) return false;
+ while(n < 0 && m_CursorLine)
+ {
+ m_CursorLine = m_CursorLine->GetPreviousLine();
+ m_CursorPos.y--;
+ n++;
+ }
+ if(! m_CursorLine)
+ {
+ m_CursorLine = m_FirstLine;
+ m_CursorPos.y = 0;
+ rc = false;
+ }
+ else
+ {
+ if(m_CursorPos.x > m_CursorLine->GetLength())
+ m_CursorPos.x = m_CursorLine->GetLength();
+ rc = true;
+ }
+ }
+ else // move down
+ {
+ wxLayoutLine *last = m_CursorLine;
+ if(! m_CursorLine->GetNextLine()) return false;
+ while(n > 0 && m_CursorLine)
+ {
+ n--;
+ m_CursorPos.y ++;
+ m_CursorLine = m_CursorLine->GetNextLine();
+ }
+ if(! m_CursorLine)
+ {
+ m_CursorLine = last;
+ m_CursorPos.y ++;
+ rc = false;
+ }
+ else
+ {
+ if(m_CursorPos.x > m_CursorLine->GetLength())
+ m_CursorPos.x = m_CursorLine->GetLength();
+ rc = true;
+ }
+ }
+ return rc;
+}
+
+bool
+wxLayoutList::MoveCursorHorizontally(int n)
+{
+ AddCursorPosToUpdateRect();
+
+ int move;
+ while(n < 0)
+ {
+ if(m_CursorPos.x == 0) // at begin of line
+ {
+ if(! MoveCursorVertically(-1))
+ break;
+ MoveCursorToEndOfLine();
+ n++;
+ continue;
+ }
+ move = -n;
+ if(move > m_CursorPos.x) move = m_CursorPos.x;
+ m_CursorPos.x -= move; n += move;
+ }
+
+ while(n > 0)
+ {
+ int len = m_CursorLine->GetLength();
+ if(m_CursorPos.x == len) // at end of line
+ {
+ if(! MoveCursorVertically(1))
+ break;
+ MoveCursorToBeginOfLine();
+ n--;
+ continue;
+ }
+ move = n;
+ if( move >= len-m_CursorPos.x) move = len-m_CursorPos.x;
+ m_CursorPos.x += move;
+ n -= move;
+ }
+ return n == 0;
+}
+
+bool
+wxLayoutList::Insert(wxString const &text)
+{
+ wxASSERT(m_CursorLine);
+
+ AddCursorPosToUpdateRect();
+
+ m_CursorLine->Insert(m_CursorPos.x, text);
+ m_CursorPos.x += text.Length();
+ m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
+ return true;
+}
+
+bool
+wxLayoutList::Insert(wxLayoutObject *obj)
+{
+ wxASSERT(m_CursorLine);
+
+ if(! m_CursorLine)
+ m_CursorLine = GetFirstLine();
+
+ AddCursorPosToUpdateRect();
+
+ m_CursorLine->Insert(m_CursorPos.x, obj);
+ m_CursorPos.x += obj->GetLength();
+ m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
+ 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)
+{
+ wxASSERT(m_CursorLine);
+ bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0);
+
+ AddCursorPosToUpdateRect();
+
+ wxPoint position(m_CursorLine->GetPosition());
+
+ wxCoord width = m_CursorLine->GetWidth(),
+ 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++;
+ m_CursorPos.x = 0;
+// doesn't help m_CursorLine.MarkDirty();
+
+ wxLayoutLine *prev = m_CursorLine->GetPreviousLine();
+ wxCHECK_MSG(prev, false, "just broke the line, where is the previous one?");
+
+ height += prev->GetHeight();
+
+ SetUpdateRect(position);
+ SetUpdateRect(position.x + width + MSW_CORRECTION,
+ position.y + height + MSW_CORRECTION);
+
+ return true;
+}
+
+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(true, this); //FIXME needed?
+ return true;
+ }
+}
+
+bool
+wxLayoutList::Delete(CoordType npos)
+{
+ wxCHECK_MSG(m_CursorLine, false, "can't delete in non existing line");
+ wxASSERT_MSG(npos > 0, "nothing to delete?");
+
+ AddCursorPosToUpdateRect();
+
+ // were other lines appended to this one (this is important to know because
+ // this means that our width _increased_ as the result of deletion)
+ bool wasMerged = false;
+
+ // the size of the region to update
+ CoordType totalHeight = m_CursorLine->GetHeight(),
+ totalWidth = m_CursorLine->GetWidth();
+
+ CoordType left;
+ do
+ {
+ left = m_CursorLine->Delete(m_CursorPos.x, npos);
+
+ if( left > 0 )
+ {
+ // More to delete, continue on next line.
+
+ // First, check if line is empty:
+ if(m_CursorLine->GetLength() == 0)
+ {
+ // in this case, updating could probably be optimised
+#ifdef WXLO_DEBUG
+ wxASSERT(DeleteLines(1) == 0);
+#else
+ DeleteLines(1);
+#endif
+
+ left--;
+ }
+ else
+ {
+ // Need to join next line
+ if(! m_CursorLine->GetNextLine())
+ break; // cannot
+ else
+ {
+ wasMerged = true;
+ wxLayoutLine *next = m_CursorLine->GetNextLine();
+ if ( next )
+ totalHeight += next->GetHeight();
+ m_CursorLine->MergeNextLine(this);
+ left--;
+ }
+ }
+ }
+ }
+ while ( left> 0 );
+
+ // we need to update the whole tail of the line and the lines which
+ // disappeared
+ if ( wasMerged )
+ {
+ wxPoint position(m_CursorLine->GetPosition());
+ SetUpdateRect(position.x + totalWidth + MSW_CORRECTION,
+ position.y + totalHeight + MSW_CORRECTION);
+ }
+
+ return left == 0;
+}
+
+int
+wxLayoutList::DeleteLines(int n)
+{
+ wxASSERT(m_CursorLine);
+ wxLayoutLine *line;
+
+ AddCursorPosToUpdateRect();
+
+ while(n > 0)
+ {
+ if(!m_CursorLine->GetNextLine())
+ { // we cannot delete this line, but we can clear it
+ MoveCursorToBeginOfLine();
+ DeleteToEndOfLine();
+ m_CursorLine->RecalculatePositions(2, this);
+ return n-1;
+ }
+ //else:
+ line = m_CursorLine;
+ m_CursorLine = m_CursorLine->DeleteLine(true, this);
+ n--;
+ if(line == m_FirstLine) m_FirstLine = m_CursorLine;
+ wxASSERT(m_FirstLine);
+ wxASSERT(m_CursorLine);
+ }
+ m_CursorLine->RecalculatePositions(2, this);
+ return n;
+}
+
+void
+wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
+{
+ wxLayoutLine *line = m_FirstLine;
+
+ // first, make sure everything is calculated - this might not be
+ // needed, optimise it later
+ ApplyStyle(&m_DefaultSetting, dc);
+ while(line)
+ {
+ line->RecalculatePosition(this); // so we don't need to do it all the time
+ // little condition to speed up redrawing:
+ if(bottom != -1 && line->GetPosition().y > bottom) break;
+ line = line->GetNextLine();
+ }
+}
+
+void
+wxLayoutList::UpdateCursorScreenPos(wxDC &dc)
+{
+ wxASSERT(m_CursorLine);
+ m_CursorLine->Layout(dc, this, (wxPoint *)&m_CursorScreenPos, (wxPoint *)&m_CursorSize, m_CursorPos.x);
+}
+
+wxPoint
+wxLayoutList::GetCursorScreenPos(wxDC &dc)
+{
+ UpdateCursorScreenPos(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, bool forceAll)
+{
+ wxLayoutLine *line = m_FirstLine;
+
+ // first, make sure everything is calculated - this might not be
+ // needed, optimise it later
+ ApplyStyle(&m_DefaultSetting, dc);
+ while(line)
+ {
+ if(forceAll || line->IsDirty())