+ SetSelection(range.GetStart(), range.GetEnd());
+}
+
+/// Set list style
+bool wxRichTextCtrl::SetListStyle(const wxRichTextRange& range, wxRichTextListStyleDefinition* def, int flags, int startFrom, int specifiedLevel)
+{
+ return GetFocusObject()->SetListStyle(range.ToInternal(), def, flags, startFrom, specifiedLevel);
+}
+
+bool wxRichTextCtrl::SetListStyle(const wxRichTextRange& range, const wxString& defName, int flags, int startFrom, int specifiedLevel)
+{
+ return GetFocusObject()->SetListStyle(range.ToInternal(), defName, flags, startFrom, specifiedLevel);
+}
+
+/// Clear list for given range
+bool wxRichTextCtrl::ClearListStyle(const wxRichTextRange& range, int flags)
+{
+ return GetFocusObject()->ClearListStyle(range.ToInternal(), flags);
+}
+
+/// Number/renumber any list elements in the given range
+bool wxRichTextCtrl::NumberList(const wxRichTextRange& range, wxRichTextListStyleDefinition* def, int flags, int startFrom, int specifiedLevel)
+{
+ return GetFocusObject()->NumberList(range.ToInternal(), def, flags, startFrom, specifiedLevel);
+}
+
+bool wxRichTextCtrl::NumberList(const wxRichTextRange& range, const wxString& defName, int flags, int startFrom, int specifiedLevel)
+{
+ return GetFocusObject()->NumberList(range.ToInternal(), defName, flags, startFrom, specifiedLevel);
+}
+
+/// Promote the list items within the given range. promoteBy can be a positive or negative number, e.g. 1 or -1
+bool wxRichTextCtrl::PromoteList(int promoteBy, const wxRichTextRange& range, wxRichTextListStyleDefinition* def, int flags, int specifiedLevel)
+{
+ return GetFocusObject()->PromoteList(promoteBy, range.ToInternal(), def, flags, specifiedLevel);
+}
+
+bool wxRichTextCtrl::PromoteList(int promoteBy, const wxRichTextRange& range, const wxString& defName, int flags, int specifiedLevel)
+{
+ return GetFocusObject()->PromoteList(promoteBy, range.ToInternal(), defName, flags, specifiedLevel);
+}
+
+// Given a character position at which there is a list style, find the range
+// encompassing the same list style by looking backwards and forwards.
+wxRichTextRange wxRichTextCtrl::FindRangeForList(long pos, bool& isNumberedList)
+{
+ wxRichTextParagraphLayoutBox* focusObject = GetFocusObject();
+ wxRichTextRange range = wxRichTextRange(-1, -1);
+ wxRichTextParagraph* para = focusObject->GetParagraphAtPosition(pos);
+ if (!para || !para->GetAttributes().HasListStyleName())
+ return range;
+ else
+ {
+ wxString listStyle = para->GetAttributes().GetListStyleName();
+ range = para->GetRange();
+
+ isNumberedList = para->GetAttributes().HasBulletNumber();
+
+ // Search back
+ wxRichTextObjectList::compatibility_iterator initialNode = focusObject->GetChildren().Find(para);
+ if (initialNode)
+ {
+ wxRichTextObjectList::compatibility_iterator startNode = initialNode->GetPrevious();
+ while (startNode)
+ {
+ wxRichTextParagraph* p = wxDynamicCast(startNode->GetData(), wxRichTextParagraph);
+ if (p)
+ {
+ if (!p->GetAttributes().HasListStyleName() || p->GetAttributes().GetListStyleName() != listStyle)
+ break;
+ else
+ range.SetStart(p->GetRange().GetStart());
+ }
+
+ startNode = startNode->GetPrevious();
+ }
+
+ // Search forward
+ wxRichTextObjectList::compatibility_iterator endNode = initialNode->GetNext();
+ while (endNode)
+ {
+ wxRichTextParagraph* p = wxDynamicCast(endNode->GetData(), wxRichTextParagraph);
+ if (p)
+ {
+ if (!p->GetAttributes().HasListStyleName() || p->GetAttributes().GetListStyleName() != listStyle)
+ break;
+ else
+ range.SetEnd(p->GetRange().GetEnd());
+ }
+
+ endNode = endNode->GetNext();
+ }
+ }
+ }
+ return range;
+}
+
+/// Deletes the content in the given range
+bool wxRichTextCtrl::Delete(const wxRichTextRange& range)
+{
+ return GetFocusObject()->DeleteRangeWithUndo(range.ToInternal(), this, & GetBuffer());
+}
+
+const wxArrayString& wxRichTextCtrl::GetAvailableFontNames()
+{
+ if (sm_availableFontNames.GetCount() == 0)
+ {
+ sm_availableFontNames = wxFontEnumerator::GetFacenames();
+ sm_availableFontNames.Sort();
+ }
+ return sm_availableFontNames;
+}
+
+void wxRichTextCtrl::ClearAvailableFontNames()
+{
+ sm_availableFontNames.Clear();
+}
+
+void wxRichTextCtrl::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
+{
+ //wxLogDebug(wxT("wxRichTextCtrl::OnSysColourChanged"));
+
+ wxTextAttrEx basicStyle = GetBasicStyle();
+ basicStyle.SetTextColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
+ SetBasicStyle(basicStyle);
+ SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+
+ Refresh();
+}
+
+// Refresh the area affected by a selection change
+bool wxRichTextCtrl::RefreshForSelectionChange(const wxRichTextSelection& oldSelection, const wxRichTextSelection& newSelection)
+{
+ // If the selection is not part of the focus object, or we have multiple ranges, then the chances are that
+ // the selection contains whole containers rather than just text, so refresh everything
+ // for now as it would be hard to compute the rectangle bounding all selections.
+ // TODO: improve on this.
+ if ((oldSelection.IsValid() && (oldSelection.GetContainer() != GetFocusObject() || oldSelection.GetCount() > 1)) ||
+ (newSelection.IsValid() && (newSelection.GetContainer() != GetFocusObject() || newSelection.GetCount() > 1)))
+ {
+ Refresh(false);
+ return true;
+ }
+
+ wxRichTextRange oldRange, newRange;
+ if (oldSelection.IsValid())
+ oldRange = oldSelection.GetRange();
+ else
+ oldRange = wxRICHTEXT_NO_SELECTION;
+ if (newSelection.IsValid())
+ newRange = newSelection.GetRange();
+ else
+ newRange = wxRICHTEXT_NO_SELECTION;
+
+ // Calculate the refresh rectangle - just the affected lines
+ long firstPos, lastPos;
+ if (oldRange.GetStart() == -2 && newRange.GetStart() != -2)
+ {
+ firstPos = newRange.GetStart();
+ lastPos = newRange.GetEnd();
+ }
+ else if (oldRange.GetStart() != -2 && newRange.GetStart() == -2)
+ {
+ firstPos = oldRange.GetStart();
+ lastPos = oldRange.GetEnd();
+ }
+ else if (oldRange.GetStart() == -2 && newRange.GetStart() == -2)
+ {
+ return false;
+ }
+ else
+ {
+ firstPos = wxMin(oldRange.GetStart(), newRange.GetStart());
+ lastPos = wxMax(oldRange.GetEnd(), newRange.GetEnd());
+ }
+
+ wxRichTextLine* firstLine = GetFocusObject()->GetLineAtPosition(firstPos);
+ wxRichTextLine* lastLine = GetFocusObject()->GetLineAtPosition(lastPos);
+
+ if (firstLine && lastLine)
+ {
+ wxSize clientSize = GetClientSize();
+ wxPoint pt1 = GetPhysicalPoint(GetScaledPoint(firstLine->GetAbsolutePosition()));
+ wxPoint pt2 = GetPhysicalPoint(GetScaledPoint(lastLine->GetAbsolutePosition())) + wxPoint(0, (int) (0.5 + lastLine->GetSize().y * GetScale()));
+
+ pt1.x = 0;
+ pt1.y = wxMax(0, pt1.y);
+ pt2.x = 0;
+ pt2.y = wxMin(clientSize.y, pt2.y);
+
+ wxRect rect(pt1, wxSize(clientSize.x, pt2.y - pt1.y));
+ RefreshRect(rect, false);
+ }
+ else
+ Refresh(false);
+
+ return true;
+}
+
+// margins functions
+bool wxRichTextCtrl::DoSetMargins(const wxPoint& pt)
+{
+ GetBuffer().GetAttributes().GetTextBoxAttr().GetMargins().GetLeft().SetValue(pt.x, wxTEXT_ATTR_UNITS_PIXELS);
+ GetBuffer().GetAttributes().GetTextBoxAttr().GetMargins().GetRight().SetValue(pt.x, wxTEXT_ATTR_UNITS_PIXELS);
+ GetBuffer().GetAttributes().GetTextBoxAttr().GetMargins().GetTop().SetValue(pt.y, wxTEXT_ATTR_UNITS_PIXELS);
+ GetBuffer().GetAttributes().GetTextBoxAttr().GetMargins().GetBottom().SetValue(pt.y, wxTEXT_ATTR_UNITS_PIXELS);
+
+ return true;
+}
+
+wxPoint wxRichTextCtrl::DoGetMargins() const
+{
+ return wxPoint(GetBuffer().GetAttributes().GetTextBoxAttr().GetMargins().GetLeft().GetValue(),
+ GetBuffer().GetAttributes().GetTextBoxAttr().GetMargins().GetTop().GetValue());
+}
+
+bool wxRichTextCtrl::SetFocusObject(wxRichTextParagraphLayoutBox* obj, bool setCaretPosition)
+{
+ if (obj && !obj->AcceptsFocus())
+ return false;
+
+ wxRichTextParagraphLayoutBox* oldContainer = GetFocusObject();
+ bool changingContainer = (m_focusObject != obj);
+
+ if (changingContainer && HasSelection())
+ SelectNone();
+
+ m_focusObject = obj;
+
+ if (!obj)
+ m_focusObject = & m_buffer;
+
+ if (setCaretPosition && changingContainer)
+ {
+ m_selection.Reset();
+ m_selectionAnchor = -2;
+ m_selectionAnchorObject = NULL;
+ m_selectionState = wxRichTextCtrlSelectionState_Normal;
+
+ long pos = -1;
+
+ m_caretAtLineStart = false;
+ MoveCaret(pos, m_caretAtLineStart);
+ SetDefaultStyleToCursorStyle();
+
+ wxRichTextEvent cmdEvent(
+ wxEVT_RICHTEXT_FOCUS_OBJECT_CHANGED,
+ GetId());
+ cmdEvent.SetEventObject(this);
+ cmdEvent.SetPosition(m_caretPosition+1);
+ cmdEvent.SetOldContainer(oldContainer);
+ cmdEvent.SetContainer(m_focusObject);
+
+ GetEventHandler()->ProcessEvent(cmdEvent);
+ }
+ return true;
+}
+
+#if wxUSE_DRAG_AND_DROP
+void wxRichTextCtrl::OnDrop(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxDragResult def, wxDataObject* DataObj)
+{
+ m_preDrag = false;
+
+ if ((def != wxDragCopy) && (def != wxDragMove))
+ {
+ return;
+ }
+
+ if (!GetSelection().IsValid())
+ {
+ return;
+ }
+
+ wxRichTextParagraphLayoutBox* originContainer = GetSelection().GetContainer();
+ wxRichTextParagraphLayoutBox* destContainer = GetFocusObject(); // This will be the drop container, not necessarily the same as the origin one
+
+ wxRichTextBuffer* richTextBuffer = ((wxRichTextBufferDataObject*)DataObj)->GetRichTextBuffer();
+ if (richTextBuffer)
+ {
+ long position = GetCaretPosition();
+ wxRichTextRange selectionrange = GetInternalSelectionRange();
+ if (selectionrange.Contains(position) && (def == wxDragMove))
+ {
+ // It doesn't make sense to move onto itself
+ return;
+ }
+
+ // If we're moving, and the data is being moved forward, we need to drop first, then delete the selection
+ // If moving backwards, we need to delete then drop. If we're copying (or doing nothing) we don't delete anyway
+ bool DeleteAfter = (def == wxDragMove) && (position > selectionrange.GetEnd());
+ if ((def == wxDragMove) && !DeleteAfter)
+ {
+ // We can't use e.g. DeleteSelectedContent() as it uses the focus container
+ originContainer->DeleteRangeWithUndo(selectionrange, this, &GetBuffer());
+ }
+
+ destContainer->InsertParagraphsWithUndo(&GetBuffer(), position+1, *richTextBuffer, this, 0);
+ ShowPosition(position + richTextBuffer->GetOwnRange().GetEnd());
+
+ delete richTextBuffer;
+
+ if (DeleteAfter)
+ {
+ // We can't use e.g. DeleteSelectedContent() as it uses the focus container
+ originContainer->DeleteRangeWithUndo(selectionrange, this, &GetBuffer());
+ }
+
+ SelectNone();
+ Refresh();
+ }
+}
+#endif // wxUSE_DRAG_AND_DROP
+
+
+#if wxUSE_DRAG_AND_DROP
+bool wxRichTextDropSource::GiveFeedback(wxDragResult WXUNUSED(effect))
+{
+ wxCHECK_MSG(m_rtc, false, wxT("NULL m_rtc"));
+
+ long position = 0;
+ int hit = 0;
+ wxRichTextObject* hitObj = NULL;
+ wxRichTextParagraphLayoutBox* container = m_rtc->FindContainerAtPoint(m_rtc->GetUnscaledPoint(m_rtc->ScreenToClient(wxGetMousePosition())), position, hit, hitObj);
+
+ if (!(hit & wxRICHTEXT_HITTEST_NONE) && container && container->AcceptsFocus())
+ {
+ m_rtc->StoreFocusObject(container);
+ m_rtc->SetCaretPositionAfterClick(container, position, hit);
+ }
+
+ return false; // so that the base-class sets a cursor
+}
+#endif // wxUSE_DRAG_AND_DROP
+
+bool wxRichTextCtrl::CanDeleteRange(wxRichTextParagraphLayoutBox& WXUNUSED(container), const wxRichTextRange& WXUNUSED(range)) const
+{
+ return true;
+}
+
+bool wxRichTextCtrl::CanInsertContent(wxRichTextParagraphLayoutBox& WXUNUSED(container), long WXUNUSED(pos)) const
+{
+ return true;
+}
+
+void wxRichTextCtrl::EnableVerticalScrollbar(bool enable)
+{
+ m_verticalScrollbarEnabled = enable;
+ SetupScrollbars();
+}