+ llist->Insert(new wxLayoutObjectText(
+ ((wxLayoutObjectText *)*last)->GetText().substr(0,lastOffset))
+ );
+ }
+ else
+ llist->Insert( (**last).Copy() );
+ }
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+ The wxLayoutList object
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+wxLayoutList::wxLayoutList()
+{
+ 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)
+{
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+ 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)
+{
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+ 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)
+{
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+ 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);
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+ 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();
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+ 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);
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+ 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();
+ m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
+ 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;
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+ LineBreak();
+ Delete(1); // delete the space
+ m_CursorPos.x = newpos;
+ m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
+ return true;
+ }
+}
+
+bool
+wxLayoutList::Delete(CoordType npos)
+{
+ wxASSERT(m_CursorLine);
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+ CoordType left;
+ do
+ {
+ left = m_CursorLine->Delete(m_CursorPos.x, npos);
+ if(left == 0)
+ return true;
+ // 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--;