X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5912d19ef7db2e64e3b4e130cbaf872a30173d1a..b2b4f8c0ca2884f99a923d30b4b37b12c76e936b:/src/richtext/richtextbuffer.cpp diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index 1242224d0a..dc91157cc3 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -46,6 +46,8 @@ WX_DEFINE_LIST(wxRichTextLineList) // Switch off if the platform doesn't like it for some reason #define wxRICHTEXT_USE_OPTIMIZED_DRAWING 1 +const wxChar wxRichTextLineBreakChar = (wxChar) 29; + /*! * wxRichTextObject * This is the base for drawable objects. @@ -1567,7 +1569,7 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const { wxRichTextParagraphStyleDefinition* def = GetStyleSheet()->FindParagraphStyle(wholeStyle.GetParagraphStyleName()); if (def) - wxRichTextApplyStyle(wholeStyle, def->GetStyle()); + wxRichTextApplyStyle(wholeStyle, def->GetStyleMergedWithBase(GetStyleSheet())); } // Limit the attributes to be set to the content to only character attributes. @@ -1578,7 +1580,7 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const { wxRichTextCharacterStyleDefinition* def = GetStyleSheet()->FindCharacterStyle(characterAttributes.GetCharacterStyleName()); if (def) - wxRichTextApplyStyle(characterAttributes, def->GetStyle()); + wxRichTextApplyStyle(characterAttributes, def->GetStyleMergedWithBase(GetStyleSheet())); } // If we are associated with a control, make undoable; otherwise, apply immediately @@ -1836,9 +1838,9 @@ bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttrEx& currentStyle, cons { if (style.HasFont()) { - if (style.HasSize() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_SIZE)) + if (style.HasFontSize() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_SIZE)) { - if (currentStyle.GetFont().Ok() && currentStyle.HasSize()) + if (currentStyle.GetFont().Ok() && currentStyle.HasFontSize()) { if (currentStyle.GetFont().GetPointSize() != style.GetFont().GetPointSize()) { @@ -1859,9 +1861,9 @@ bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttrEx& currentStyle, cons } } - if (style.HasItalic() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_ITALIC)) + if (style.HasFontItalic() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_ITALIC)) { - if (currentStyle.GetFont().Ok() && currentStyle.HasItalic()) + if (currentStyle.GetFont().Ok() && currentStyle.HasFontItalic()) { if (currentStyle.GetFont().GetStyle() != style.GetFont().GetStyle()) { @@ -1881,9 +1883,9 @@ bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttrEx& currentStyle, cons } } - if (style.HasWeight() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_WEIGHT)) + if (style.HasFontWeight() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_WEIGHT)) { - if (currentStyle.GetFont().Ok() && currentStyle.HasWeight()) + if (currentStyle.GetFont().Ok() && currentStyle.HasFontWeight()) { if (currentStyle.GetFont().GetWeight() != style.GetFont().GetWeight()) { @@ -1903,9 +1905,9 @@ bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttrEx& currentStyle, cons } } - if (style.HasFaceName() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_FACE)) + if (style.HasFontFaceName() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_FACE)) { - if (currentStyle.GetFont().Ok() && currentStyle.HasFaceName()) + if (currentStyle.GetFont().Ok() && currentStyle.HasFontFaceName()) { wxString faceName1(currentStyle.GetFont().GetFaceName()); wxString faceName2(style.GetFont().GetFaceName()); @@ -1928,9 +1930,9 @@ bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttrEx& currentStyle, cons } } - if (style.HasUnderlined() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_UNDERLINE)) + if (style.HasFontUnderlined() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_UNDERLINE)) { - if (currentStyle.GetFont().Ok() && currentStyle.HasUnderlined()) + if (currentStyle.GetFont().Ok() && currentStyle.HasFontUnderlined()) { if (currentStyle.GetFont().GetUnderlined() != style.GetFont().GetUnderlined()) { @@ -2510,13 +2512,13 @@ bool wxRichTextParagraphLayoutBox::ApplyStyleSheet(wxRichTextStyleSheet* styleSh wxRichTextListStyleDefinition* listDef = styleSheet->FindListStyle(para->GetAttributes().GetListStyleName()); if (paraDef && !listDef) { - para->GetAttributes() = paraDef->GetStyle(); + para->GetAttributes() = paraDef->GetStyleMergedWithBase(styleSheet); foundCount ++; } else if (listDef && !paraDef) { // Set overall style defined for the list style definition - para->GetAttributes() = listDef->GetStyle(); + para->GetAttributes() = listDef->GetStyleMergedWithBase(styleSheet); // Apply the style for this level wxRichTextApplyStyle(para->GetAttributes(), * listDef->GetLevelAttributes(listDef->FindLevelForIndent(currentIndent))); @@ -2525,7 +2527,7 @@ bool wxRichTextParagraphLayoutBox::ApplyStyleSheet(wxRichTextStyleSheet* styleSh else if (listDef && paraDef) { // Combines overall list style, style for level, and paragraph style - para->GetAttributes() = listDef->CombineWithParagraphStyle(currentIndent, paraDef->GetStyle()); + para->GetAttributes() = listDef->CombineWithParagraphStyle(currentIndent, paraDef->GetStyleMergedWithBase(styleSheet)); foundCount ++; } } @@ -2536,7 +2538,7 @@ bool wxRichTextParagraphLayoutBox::ApplyStyleSheet(wxRichTextStyleSheet* styleSh wxRichTextListStyleDefinition* listDef = styleSheet->FindListStyle(para->GetAttributes().GetListStyleName()); // Overall list definition style - para->GetAttributes() = listDef->GetStyle(); + para->GetAttributes() = listDef->GetStyleMergedWithBase(styleSheet); // Style for this level wxRichTextApplyStyle(para->GetAttributes(), * listDef->GetLevelAttributes(listDef->FindLevelForIndent(currentIndent))); @@ -2548,7 +2550,7 @@ bool wxRichTextParagraphLayoutBox::ApplyStyleSheet(wxRichTextStyleSheet* styleSh wxRichTextParagraphStyleDefinition* def = styleSheet->FindParagraphStyle(para->GetAttributes().GetParagraphStyleName()); if (def) { - para->GetAttributes() = def->GetStyle(); + para->GetAttributes() = def->GetStyleMergedWithBase(styleSheet); foundCount ++; } } @@ -2562,6 +2564,8 @@ bool wxRichTextParagraphLayoutBox::ApplyStyleSheet(wxRichTextStyleSheet* styleSh /// Set list style bool wxRichTextParagraphLayoutBox::SetListStyle(const wxRichTextRange& range, wxRichTextListStyleDefinition* def, int flags, int startFrom, int specifiedLevel) { + wxRichTextStyleSheet* styleSheet = GetStyleSheet(); + bool withUndo = ((flags & wxRICHTEXT_SETSTYLE_WITH_UNDO) != 0); // bool applyMinimal = ((flags & wxRICHTEXT_SETSTYLE_OPTIMIZE) != 0); bool specifyLevel = ((flags & wxRICHTEXT_SETSTYLE_SPECIFY_LEVEL) != 0); @@ -2629,7 +2633,7 @@ bool wxRichTextParagraphLayoutBox::SetListStyle(const wxRichTextRange& range, wx // Renumbering will need to be done when we promote/demote a paragraph. // Apply the overall list style, and item style for this level - wxTextAttrEx listStyle(def->GetCombinedStyleForLevel(thisLevel)); + wxTextAttrEx listStyle(def->GetCombinedStyleForLevel(thisLevel, styleSheet)); wxRichTextApplyStyle(newPara->GetAttributes(), listStyle); // Now we need to do numbering @@ -2652,13 +2656,12 @@ bool wxRichTextParagraphLayoutBox::SetListStyle(const wxRichTextRange& range, wx // Eliminate the main list-related attributes newPara->GetAttributes().SetFlags(newPara->GetAttributes().GetFlags() & ~wxTEXT_ATTR_LEFT_INDENT & ~wxTEXT_ATTR_BULLET_STYLE & ~wxTEXT_ATTR_BULLET_NUMBER & ~wxTEXT_ATTR_BULLET_TEXT & wxTEXT_ATTR_LIST_STYLE_NAME); - wxRichTextStyleSheet* styleSheet = GetStyleSheet(); if (styleSheet && !newPara->GetAttributes().GetParagraphStyleName().IsEmpty()) { wxRichTextParagraphStyleDefinition* def = styleSheet->FindParagraphStyle(newPara->GetAttributes().GetParagraphStyleName()); if (def) { - newPara->GetAttributes() = def->GetStyle(); + newPara->GetAttributes() = def->GetStyleMergedWithBase(styleSheet); } } } @@ -2702,6 +2705,8 @@ bool wxRichTextParagraphLayoutBox::NumberList(const wxRichTextRange& range, wxRi bool wxRichTextParagraphLayoutBox::DoNumberList(const wxRichTextRange& range, const wxRichTextRange& promotionRange, int promoteBy, wxRichTextListStyleDefinition* def, int flags, int startFrom, int specifiedLevel) { + wxRichTextStyleSheet* styleSheet = GetStyleSheet(); + bool withUndo = ((flags & wxRICHTEXT_SETSTYLE_WITH_UNDO) != 0); // bool applyMinimal = ((flags & wxRICHTEXT_SETSTYLE_OPTIMIZE) != 0); #ifdef __WXDEBUG__ @@ -2779,10 +2784,8 @@ bool wxRichTextParagraphLayoutBox::DoNumberList(const wxRichTextRange& range, co wxRichTextListStyleDefinition* defToUse = def; if (!defToUse) { - wxRichTextStyleSheet* sheet = GetStyleSheet(); - - if (sheet && !newPara->GetAttributes().GetListStyleName().IsEmpty()) - defToUse = sheet->FindListStyle(newPara->GetAttributes().GetListStyleName()); + if (styleSheet && !newPara->GetAttributes().GetListStyleName().IsEmpty()) + defToUse = styleSheet->FindListStyle(newPara->GetAttributes().GetListStyleName()); } if (defToUse) @@ -2805,7 +2808,7 @@ bool wxRichTextParagraphLayoutBox::DoNumberList(const wxRichTextRange& range, co } // Apply the overall list style, and item style for this level - wxTextAttrEx listStyle(defToUse->GetCombinedStyleForLevel(thisLevel)); + wxTextAttrEx listStyle(defToUse->GetCombinedStyleForLevel(thisLevel, styleSheet)); wxRichTextApplyStyle(newPara->GetAttributes(), listStyle); // OK, we've (re)applied the style, now let's get the numbering right. @@ -2921,10 +2924,10 @@ bool wxRichTextParagraphLayoutBox::FindNextParagraphNumber(wxRichTextParagraph* if (!previousParagraph->GetAttributes().HasFlag(wxTEXT_ATTR_BULLET_STYLE) || previousParagraph->GetAttributes().GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_NONE) return false; - wxRichTextStyleSheet* sheet = GetStyleSheet(); - if (sheet && !previousParagraph->GetAttributes().GetListStyleName().IsEmpty()) + wxRichTextStyleSheet* styleSheet = GetStyleSheet(); + if (styleSheet && !previousParagraph->GetAttributes().GetListStyleName().IsEmpty()) { - wxRichTextListStyleDefinition* def = sheet->FindListStyle(previousParagraph->GetAttributes().GetListStyleName()); + wxRichTextListStyleDefinition* def = styleSheet->FindListStyle(previousParagraph->GetAttributes().GetListStyleName()); if (def) { // int thisIndent = previousParagraph->GetAttributes().GetLeftIndent(); @@ -3014,6 +3017,16 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR wxTextAttrEx bulletAttr(GetCombinedAttributes()); + // Combine with the font of the first piece of content, if one is specified + if (GetChildren().GetCount() > 0) + { + wxRichTextObject* firstObj = (wxRichTextObject*) GetChildren().GetFirst()->GetData(); + if (firstObj->GetAttributes().HasFont()) + { + wxRichTextApplyStyle(bulletAttr, firstObj->GetAttributes()); + } + } + // Get line height from first line, if any wxRichTextLine* line = m_cachedLines.GetFirst() ? (wxRichTextLine* ) m_cachedLines.GetFirst()->GetData() : (wxRichTextLine*) NULL; @@ -3183,6 +3196,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) // can't tell the position until the size is determined. So possibly introduce // another layout phase. + // TODO: can't this be called only once per child? child->Layout(dc, rect, style); // Available width depends on whether we're on the first or subsequent lines @@ -3193,18 +3207,32 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) // We may only be looking at part of a child, if we searched back for wrapping // and found a suitable point some way into the child. So get the size for the fragment // if necessary. + + long nextBreakPos = GetFirstLineBreakPosition(lastEndPos+1); + long lastPosToUse = child->GetRange().GetEnd(); + bool lineBreakInThisObject = (nextBreakPos > -1 && nextBreakPos <= child->GetRange().GetEnd()); + + if (lineBreakInThisObject) + lastPosToUse = nextBreakPos; wxSize childSize; int childDescent = 0; - if (lastEndPos == child->GetRange().GetStart() - 1) + + if ((nextBreakPos == -1) && (lastEndPos == child->GetRange().GetStart() - 1)) // i.e. we want to get the whole thing { childSize = child->GetCachedSize(); childDescent = child->GetDescent(); } else - GetRangeSize(wxRichTextRange(lastEndPos+1, child->GetRange().GetEnd()), childSize, childDescent, dc, wxRICHTEXT_UNFORMATTED,rect.GetPosition()); + GetRangeSize(wxRichTextRange(lastEndPos+1, lastPosToUse), childSize, childDescent, dc, wxRICHTEXT_UNFORMATTED, rect.GetPosition()); - if (childSize.x + currentWidth > availableSpaceForText) + // Cases: + // 1) There was a line break BEFORE the natural break + // 2) There was a line break AFTER the natural break + // 3) The child still fits (carry on) + + if ((lineBreakInThisObject && (childSize.x + currentWidth <= availableSpaceForText)) || + (childSize.x + currentWidth > availableSpaceForText)) { long wrapPosition = 0; @@ -3874,11 +3902,19 @@ bool wxRichTextParagraph::FindWrapPosition(const wxRichTextRange& range, wxDC& d wxString plainText; if (GetContiguousPlainText(plainText, wxRichTextRange(range.GetStart(), breakPosition), false)) { - int spacePos = plainText.Find(wxT(' '), true); - if (spacePos != wxNOT_FOUND) + int newLinePos = plainText.Find(wxRichTextLineBreakChar); + if (newLinePos != wxNOT_FOUND) + { + breakPosition = wxMax(0, range.GetStart() + newLinePos); + } + else { - int positionsFromEndOfString = plainText.length() - spacePos - 1; - breakPosition = breakPosition - positionsFromEndOfString; + int spacePos = plainText.Find(wxT(' '), true); + if (spacePos != wxNOT_FOUND) + { + int positionsFromEndOfString = plainText.length() - spacePos - 1; + breakPosition = breakPosition - positionsFromEndOfString; + } } } @@ -4036,6 +4072,27 @@ void wxRichTextParagraph::ClearDefaultTabs() sm_defaultTabs.Clear(); } +/// Get the first position from pos that has a line break character. +long wxRichTextParagraph::GetFirstLineBreakPosition(long pos) +{ + wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst(); + while (node) + { + wxRichTextObject* obj = node->GetData(); + if (pos >= obj->GetRange().GetStart() && pos <= obj->GetRange().GetEnd()) + { + wxRichTextPlainText* textObj = wxDynamicCast(obj, wxRichTextPlainText); + if (textObj) + { + long breakPos = textObj->GetFirstLineBreakPosition(pos); + if (breakPos > -1) + return breakPos; + } + } + node = node->GetNext(); + } + return -1; +} /*! * wxRichTextLine @@ -4107,8 +4164,13 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR int offset = GetRange().GetStart(); + // Replace line break characters with spaces + wxString str = m_text; + wxString toRemove = wxRichTextLineBreakChar; + str.Replace(toRemove, wxT(" ")); + long len = range.GetLength(); - wxString stringChunk = m_text.Mid(range.GetStart() - offset, (size_t) len); + wxString stringChunk = str.Mid(range.GetStart() - offset, (size_t) len); if (textAttr.HasTextEffects() && (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_CAPITALS)) stringChunk.MakeUpper(); @@ -4149,7 +4211,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR int fragmentLen = s1 - r1 + 1; if (fragmentLen < 0) wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen); - wxString stringFragment = m_text.Mid(r1 - offset, fragmentLen); + wxString stringFragment = str.Mid(r1 - offset, fragmentLen); DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false); @@ -4157,8 +4219,8 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR if (stringChunk.Find(wxT("\t")) == wxNOT_FOUND) { // Compensate for kerning difference - wxString stringFragment2(m_text.Mid(r1 - offset, fragmentLen+1)); - wxString stringFragment3(m_text.Mid(r1 - offset + fragmentLen, 1)); + wxString stringFragment2(str.Mid(r1 - offset, fragmentLen+1)); + wxString stringFragment3(str.Mid(r1 - offset + fragmentLen, 1)); wxCoord w1, h1, w2, h2, w3, h3; dc.GetTextExtent(stringFragment, & w1, & h1); @@ -4180,7 +4242,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR int fragmentLen = s2 - s1 + 1; if (fragmentLen < 0) wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen); - wxString stringFragment = m_text.Mid(s1 - offset, fragmentLen); + wxString stringFragment = str.Mid(s1 - offset, fragmentLen); DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, true); @@ -4188,8 +4250,8 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR if (stringChunk.Find(wxT("\t")) == wxNOT_FOUND) { // Compensate for kerning difference - wxString stringFragment2(m_text.Mid(s1 - offset, fragmentLen+1)); - wxString stringFragment3(m_text.Mid(s1 - offset + fragmentLen, 1)); + wxString stringFragment2(str.Mid(s1 - offset, fragmentLen+1)); + wxString stringFragment3(str.Mid(s1 - offset + fragmentLen, 1)); wxCoord w1, h1, w2, h2, w3, h3; dc.GetTextExtent(stringFragment, & w1, & h1); @@ -4211,7 +4273,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR int fragmentLen = r2 - s2 + 1; if (fragmentLen < 0) wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen); - wxString stringFragment = m_text.Mid(s2 - offset, fragmentLen); + wxString stringFragment = str.Mid(s2 - offset, fragmentLen); DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false); } @@ -4337,6 +4399,9 @@ bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), int WXU if (textAttr.HasTextEffects() && (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_CAPITALS)) str.MakeUpper(); + wxString toReplace = wxRichTextLineBreakChar; + str.Replace(toReplace, wxT(" ")); + wxCoord w, h; dc.GetTextExtent(str, & w, & h, & m_descent); m_size = wxSize(w, dc.GetCharHeight()); @@ -4373,7 +4438,12 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz int startPos = range.GetStart() - GetRange().GetStart(); long len = range.GetLength(); - wxString stringChunk = m_text.Mid(startPos, (size_t) len); + + wxString str(m_text); + wxString toReplace = wxRichTextLineBreakChar; + str.Replace(toReplace, wxT(" ")); + + wxString stringChunk = str.Mid(startPos, (size_t) len); if (textAttr.HasTextEffects() && (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_CAPITALS)) stringChunk.MakeUpper(); @@ -4432,7 +4502,8 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz /// the first part in 'this'. wxRichTextObject* wxRichTextPlainText::DoSplit(long pos) { - int index = pos - GetRange().GetStart(); + long index = pos - GetRange().GetStart(); + if (index < 0 || index >= (int) m_text.length()) return NULL; @@ -4446,7 +4517,7 @@ wxRichTextObject* wxRichTextPlainText::DoSplit(long pos) newObject->SetRange(wxRichTextRange(pos, GetRange().GetEnd())); GetRange().SetEnd(pos-1); - + return newObject; } @@ -4520,6 +4591,23 @@ void wxRichTextPlainText::Dump(wxTextOutputStream& stream) stream << m_text << wxT("\n"); } +/// Get the first position from pos that has a line break character. +long wxRichTextPlainText::GetFirstLineBreakPosition(long pos) +{ + int i; + int len = m_text.length(); + int startPos = pos - m_range.GetStart(); + for (i = startPos; i < len; i++) + { + wxChar ch = m_text[i]; + if (ch == wxRichTextLineBreakChar) + { + return i + m_range.GetStart(); + } + } + return -1; +} + /*! * wxRichTextBuffer * This is a kind of box, used to represent the whole buffer @@ -4652,7 +4740,8 @@ bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRich wxTextAttrEx paraAttr; if (flags & wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE) { - paraAttr = GetStyleForNewParagraph(pos); + // Get appropriate paragraph style + paraAttr = GetStyleForNewParagraph(pos, false, false); if (!paraAttr.IsDefault()) p = & paraAttr; } @@ -4667,6 +4756,8 @@ bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRich length --; action->GetNewParagraphs().SetPartialParagraph(true); } + else if (text.length() > 0 && text.Last() == wxT('\n')) + length --; action->SetPosition(pos); @@ -4687,7 +4778,7 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int wxTextAttrEx paraAttr; if (flags & wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE) { - paraAttr = GetStyleForNewParagraph(pos); + paraAttr = GetStyleForNewParagraph(pos, false, true /* look for next paragraph style */); if (!paraAttr.IsDefault()) p = & paraAttr; } @@ -4751,7 +4842,7 @@ bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& /// Get the style that is appropriate for a new paragraph at this position. /// If the previous paragraph has a paragraph style name, look up the next-paragraph /// style. -wxRichTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPosition) const +wxRichTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPosition, bool lookUpNewParaStyle) const { wxRichTextParagraph* para = GetParagraphAtPosition(pos, caretPosition); if (para) @@ -4760,7 +4851,7 @@ wxRichTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPos bool foundAttributes = false; // Look for a matching paragraph style - if (!para->GetAttributes().GetParagraphStyleName().IsEmpty() && GetStyleSheet()) + if (lookUpNewParaStyle && !para->GetAttributes().GetParagraphStyleName().IsEmpty() && GetStyleSheet()) { wxRichTextParagraphStyleDefinition* paraDef = GetStyleSheet()->FindParagraphStyle(para->GetAttributes().GetParagraphStyleName()); if (paraDef) @@ -4771,7 +4862,7 @@ wxRichTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPos if (nextParaDef) { foundAttributes = true; - attr = nextParaDef->GetStyle(); + attr = nextParaDef->GetStyleMergedWithBase(GetStyleSheet()); } } @@ -4779,7 +4870,7 @@ wxRichTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPos if (!foundAttributes) { foundAttributes = true; - attr = paraDef->GetStyle(); + attr = paraDef->GetStyleMergedWithBase(GetStyleSheet()); } } } @@ -4810,11 +4901,11 @@ wxRichTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPos } /// Submit command to delete this range -bool wxRichTextBuffer::DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long WXUNUSED(newCaretPositon), wxRichTextCtrl* ctrl) +bool wxRichTextBuffer::DeleteRangeWithUndo(const wxRichTextRange& range, wxRichTextCtrl* ctrl) { wxRichTextAction* action = new wxRichTextAction(NULL, _("Delete"), wxRICHTEXT_DELETE, this, ctrl); - action->SetPosition(initialCaretPosition); + action->SetPosition(ctrl->GetCaretPosition()); // Set the range to delete action->SetRange(range); @@ -5137,7 +5228,7 @@ bool wxRichTextBuffer::BeginCharacterStyle(const wxString& characterStyle) wxRichTextCharacterStyleDefinition* def = GetStyleSheet()->FindCharacterStyle(characterStyle); if (def) { - wxTextAttrEx attr = def->GetStyle(); + wxTextAttrEx attr = def->GetStyleMergedWithBase(GetStyleSheet()); return BeginStyle(attr); } } @@ -5152,7 +5243,7 @@ bool wxRichTextBuffer::BeginParagraphStyle(const wxString& paragraphStyle) wxRichTextParagraphStyleDefinition* def = GetStyleSheet()->FindParagraphStyle(paragraphStyle); if (def) { - wxTextAttrEx attr = def->GetStyle(); + wxTextAttrEx attr = def->GetStyleMergedWithBase(GetStyleSheet()); return BeginStyle(attr); } } @@ -5187,7 +5278,7 @@ bool wxRichTextBuffer::BeginURL(const wxString& url, const wxString& characterSt wxRichTextCharacterStyleDefinition* def = GetStyleSheet()->FindCharacterStyle(characterStyle); if (def) { - attr = def->GetStyle(); + attr = def->GetStyleMergedWithBase(GetStyleSheet()); } } attr.SetURL(url); @@ -5960,6 +6051,13 @@ bool wxRichTextAction::Do() // Don't take into account the last newline if (m_newParagraphs.GetPartialParagraph()) newCaretPosition --; + else + if (m_newParagraphs.GetChildren().GetCount() > 1) + { + wxRichTextObject* p = (wxRichTextObject*) m_newParagraphs.GetChildren().GetLast()->GetData(); + if (p->GetRange().GetLength() == 1) + newCaretPosition --; + } newCaretPosition = wxMin(newCaretPosition, (m_buffer->GetRange().GetEnd()-1)); @@ -6771,9 +6869,7 @@ bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxTextAttrEx& style) bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxRichTextAttr& style, wxRichTextAttr* compareWith) { - wxTextAttrEx attr(destStyle); - wxRichTextApplyStyle(attr, style, compareWith); - destStyle = attr; + destStyle = destStyle.Combine(style, compareWith); return true; } @@ -6792,7 +6888,7 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style, if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE) { - if (compareWith && compareWith->HasFaceName() && compareWith->GetFontFaceName() == style.GetFontFaceName()) + if (compareWith && compareWith->HasFontFaceName() && compareWith->GetFontFaceName() == style.GetFontFaceName()) { // The same as currently displayed, so don't set } @@ -6805,7 +6901,7 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style, if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE) { - if (compareWith && compareWith->HasSize() && compareWith->GetFontSize() == style.GetFontSize()) + if (compareWith && compareWith->HasFontSize() && compareWith->GetFontSize() == style.GetFontSize()) { // The same as currently displayed, so don't set } @@ -6818,7 +6914,7 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style, if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC) { - if (compareWith && compareWith->HasItalic() && compareWith->GetFontStyle() == style.GetFontStyle()) + if (compareWith && compareWith->HasFontItalic() && compareWith->GetFontStyle() == style.GetFontStyle()) { // The same as currently displayed, so don't set } @@ -6831,7 +6927,7 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style, if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT) { - if (compareWith && compareWith->HasWeight() && compareWith->GetFontWeight() == style.GetFontWeight()) + if (compareWith && compareWith->HasFontWeight() && compareWith->GetFontWeight() == style.GetFontWeight()) { // The same as currently displayed, so don't set } @@ -6844,7 +6940,7 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style, if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE) { - if (compareWith && compareWith->HasUnderlined() && compareWith->GetFontUnderlined() == style.GetFontUnderlined()) + if (compareWith && compareWith->HasFontUnderlined() && compareWith->GetFontUnderlined() == style.GetFontUnderlined()) { // The same as currently displayed, so don't set } @@ -7334,116 +7430,184 @@ bool wxRichTextAttr::GetFontAttributes(const wxFont& font) return true; } -wxRichTextAttr wxRichTextAttr::Combine(const wxRichTextAttr& attr, - const wxRichTextAttr& attrDef, - const wxTextCtrlBase *text) +wxRichTextAttr wxRichTextAttr::Combine(const wxRichTextAttr& style, const wxRichTextAttr* compareWith) const { - wxColour colFg = attr.GetTextColour(); - if ( !colFg.Ok() ) - { - colFg = attrDef.GetTextColour(); + wxRichTextAttr destStyle = (*this); + destStyle.Apply(style, compareWith); + + return destStyle; +} - if ( text && !colFg.Ok() ) - colFg = text->GetForegroundColour(); +bool wxRichTextAttr::Apply(const wxRichTextAttr& style, const wxRichTextAttr* compareWith) +{ + wxRichTextAttr& destStyle = (*this); + + if (style.HasFontWeight()) + { + if (!(compareWith && compareWith->HasFontWeight() && compareWith->GetFontWeight() == style.GetFontWeight())) + destStyle.SetFontWeight(style.GetFontWeight()); } - wxColour colBg = attr.GetBackgroundColour(); - if ( !colBg.Ok() ) + if (style.HasFontSize()) { - colBg = attrDef.GetBackgroundColour(); - - if ( text && !colBg.Ok() ) - colBg = text->GetBackgroundColour(); + if (!(compareWith && compareWith->HasFontSize() && compareWith->GetFontSize() == style.GetFontSize())) + destStyle.SetFontSize(style.GetFontSize()); } - wxRichTextAttr newAttr(colFg, colBg); + if (style.HasFontItalic()) + { + if (!(compareWith && compareWith->HasFontItalic() && compareWith->GetFontStyle() == style.GetFontStyle())) + destStyle.SetFontStyle(style.GetFontStyle()); + } - if (attr.HasWeight()) - newAttr.SetFontWeight(attr.GetFontWeight()); + if (style.HasFontUnderlined()) + { + if (!(compareWith && compareWith->HasFontUnderlined() && compareWith->GetFontUnderlined() == style.GetFontUnderlined())) + destStyle.SetFontUnderlined(style.GetFontUnderlined()); + } - if (attr.HasSize()) - newAttr.SetFontSize(attr.GetFontSize()); + if (style.HasFontFaceName()) + { + if (!(compareWith && compareWith->HasFontFaceName() && compareWith->GetFontFaceName() == style.GetFontFaceName())) + destStyle.SetFontFaceName(style.GetFontFaceName()); + } - if (attr.HasItalic()) - newAttr.SetFontStyle(attr.GetFontStyle()); + if (style.GetTextColour().Ok() && style.HasTextColour()) + { + if (!(compareWith && compareWith->HasTextColour() && compareWith->GetTextColour() == style.GetTextColour())) + destStyle.SetTextColour(style.GetTextColour()); + } - if (attr.HasUnderlined()) - newAttr.SetFontUnderlined(attr.GetFontUnderlined()); + if (style.GetBackgroundColour().Ok() && style.HasBackgroundColour()) + { + if (!(compareWith && compareWith->HasBackgroundColour() && compareWith->GetBackgroundColour() == style.GetBackgroundColour())) + destStyle.SetBackgroundColour(style.GetBackgroundColour()); + } - if (attr.HasFaceName()) - newAttr.SetFontFaceName(attr.GetFontFaceName()); + if (style.HasAlignment()) + { + if (!(compareWith && compareWith->HasAlignment() && compareWith->GetAlignment() == style.GetAlignment())) + destStyle.SetAlignment(style.GetAlignment()); + } - if (attr.HasAlignment()) - newAttr.SetAlignment(attr.GetAlignment()); - else if (attrDef.HasAlignment()) - newAttr.SetAlignment(attrDef.GetAlignment()); + if (style.HasTabs()) + { + if (!(compareWith && compareWith->HasTabs() && wxRichTextTabsEq(compareWith->GetTabs(), style.GetTabs()))) + destStyle.SetTabs(style.GetTabs()); + } - if (attr.HasTabs()) - newAttr.SetTabs(attr.GetTabs()); - else if (attrDef.HasTabs()) - newAttr.SetTabs(attrDef.GetTabs()); + if (style.HasLeftIndent()) + { + if (!(compareWith && compareWith->HasLeftIndent() && compareWith->GetLeftIndent() == style.GetLeftIndent() + && compareWith->GetLeftSubIndent() == style.GetLeftSubIndent())) + destStyle.SetLeftIndent(style.GetLeftIndent(), style.GetLeftSubIndent()); + } - if (attr.HasLeftIndent()) - newAttr.SetLeftIndent(attr.GetLeftIndent(), attr.GetLeftSubIndent()); - else if (attrDef.HasLeftIndent()) - newAttr.SetLeftIndent(attrDef.GetLeftIndent(), attr.GetLeftSubIndent()); + if (style.HasRightIndent()) + { + if (!(compareWith && compareWith->HasRightIndent() && compareWith->GetRightIndent() == style.GetRightIndent())) + destStyle.SetRightIndent(style.GetRightIndent()); + } - if (attr.HasRightIndent()) - newAttr.SetRightIndent(attr.GetRightIndent()); - else if (attrDef.HasRightIndent()) - newAttr.SetRightIndent(attrDef.GetRightIndent()); + if (style.HasParagraphSpacingAfter()) + { + if (!(compareWith && compareWith->HasParagraphSpacingAfter() && compareWith->GetParagraphSpacingAfter() == style.GetParagraphSpacingAfter())) + destStyle.SetParagraphSpacingAfter(style.GetParagraphSpacingAfter()); + } - // NEW ATTRIBUTES + if (style.HasParagraphSpacingBefore()) + { + if (!(compareWith && compareWith->HasParagraphSpacingBefore() && compareWith->GetParagraphSpacingBefore() == style.GetParagraphSpacingBefore())) + destStyle.SetParagraphSpacingBefore(style.GetParagraphSpacingBefore()); + } - if (attr.HasParagraphSpacingAfter()) - newAttr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter()); + if (style.HasLineSpacing()) + { + if (!(compareWith && compareWith->HasLineSpacing() && compareWith->GetLineSpacing() == style.GetLineSpacing())) + destStyle.SetLineSpacing(style.GetLineSpacing()); + } - if (attr.HasParagraphSpacingBefore()) - newAttr.SetParagraphSpacingBefore(attr.GetParagraphSpacingBefore()); + if (style.HasCharacterStyleName()) + { + if (!(compareWith && compareWith->HasCharacterStyleName() && compareWith->GetCharacterStyleName() == style.GetCharacterStyleName())) + destStyle.SetCharacterStyleName(style.GetCharacterStyleName()); + } - if (attr.HasLineSpacing()) - newAttr.SetLineSpacing(attr.GetLineSpacing()); + if (style.HasParagraphStyleName()) + { + if (!(compareWith && compareWith->HasParagraphStyleName() && compareWith->GetParagraphStyleName() == style.GetParagraphStyleName())) + destStyle.SetParagraphStyleName(style.GetParagraphStyleName()); + } - if (attr.HasCharacterStyleName()) - newAttr.SetCharacterStyleName(attr.GetCharacterStyleName()); + if (style.HasListStyleName()) + { + if (!(compareWith && compareWith->HasListStyleName() && compareWith->GetListStyleName() == style.GetListStyleName())) + destStyle.SetListStyleName(style.GetListStyleName()); + } - if (attr.HasParagraphStyleName()) - newAttr.SetParagraphStyleName(attr.GetParagraphStyleName()); + if (style.HasBulletStyle()) + { + if (!(compareWith && compareWith->HasBulletStyle() && compareWith->GetBulletStyle() == style.GetBulletStyle())) + destStyle.SetBulletStyle(style.GetBulletStyle()); + } - if (attr.HasListStyleName()) - newAttr.SetListStyleName(attr.GetListStyleName()); + if (style.HasBulletText()) + { + if (!(compareWith && compareWith->HasBulletText() && compareWith->GetBulletText() == style.GetBulletText())) + { + destStyle.SetBulletText(style.GetBulletText()); + destStyle.SetBulletFont(style.GetBulletFont()); + } + } - if (attr.HasBulletStyle()) - newAttr.SetBulletStyle(attr.GetBulletStyle()); + if (style.HasBulletNumber()) + { + if (!(compareWith && compareWith->HasBulletNumber() && compareWith->GetBulletNumber() == style.GetBulletNumber())) + destStyle.SetBulletNumber(style.GetBulletNumber()); + } - if (attr.HasBulletNumber()) - newAttr.SetBulletNumber(attr.GetBulletNumber()); + if (style.HasBulletName()) + { + if (!(compareWith && compareWith->HasBulletName() && compareWith->GetBulletName() == style.GetBulletName())) + destStyle.SetBulletName(style.GetBulletName()); + } - if (attr.HasBulletName()) - newAttr.SetBulletName(attr.GetBulletName()); + if (style.HasURL()) + { + if (!(compareWith && compareWith->HasURL() && compareWith->GetURL() == style.GetURL())) + destStyle.SetURL(style.GetURL()); + } - if (attr.HasBulletText()) + if (style.HasPageBreak()) { - newAttr.SetBulletText(attr.GetBulletText()); - newAttr.SetBulletFont(attr.GetBulletFont()); + if (!(compareWith && compareWith->HasPageBreak())) + destStyle.SetPageBreak(); } - if (attr.HasURL()) - newAttr.SetURL(attr.GetURL()); + if (style.HasTextEffects()) + { + if (!(compareWith && compareWith->HasTextEffects() && compareWith->GetTextEffects() == style.GetTextEffects())) + { + int destBits = destStyle.GetTextEffects(); + int destFlags = destStyle.GetTextEffectFlags(); - if (attr.HasPageBreak()) - newAttr.SetPageBreak(); + int srcBits = style.GetTextEffects(); + int srcFlags = style.GetTextEffectFlags(); + + wxRichTextCombineBitlists(destBits, srcBits, destFlags, srcFlags); + + destStyle.SetTextEffects(destBits); + destStyle.SetTextEffectFlags(destFlags); + } + } - if (attr.HasTextEffects()) + if (style.HasOutlineLevel()) { - newAttr.SetTextEffects(attr.GetTextEffects()); - newAttr.SetTextEffectFlags(attr.GetTextEffectFlags()); + if (!(compareWith && compareWith->HasOutlineLevel() && compareWith->GetOutlineLevel() == style.GetOutlineLevel())) + destStyle.SetOutlineLevel(style.GetOutlineLevel()); } - if (attr.HasOutlineLevel()) - newAttr.SetOutlineLevel(attr.GetOutlineLevel()); - - return newAttr; + return true; } /*! @@ -7566,27 +7730,27 @@ wxTextAttrEx wxTextAttrEx::CombineEx(const wxTextAttrEx& attr, // Otherwise, if there are font attributes in attr, apply them if (attr.GetFlags() & wxTEXT_ATTR_FONT) { - if (attr.HasSize()) + if (attr.HasFontSize()) { flags |= wxTEXT_ATTR_FONT_SIZE; font.SetPointSize(attr.GetFont().GetPointSize()); } - if (attr.HasItalic()) + if (attr.HasFontItalic()) { flags |= wxTEXT_ATTR_FONT_ITALIC;; font.SetStyle(attr.GetFont().GetStyle()); } - if (attr.HasWeight()) + if (attr.HasFontWeight()) { flags |= wxTEXT_ATTR_FONT_WEIGHT; font.SetWeight(attr.GetFont().GetWeight()); } - if (attr.HasFaceName()) + if (attr.HasFontFaceName()) { flags |= wxTEXT_ATTR_FONT_FACE; font.SetFaceName(attr.GetFont().GetFaceName()); } - if (attr.HasUnderlined()) + if (attr.HasFontUnderlined()) { flags |= wxTEXT_ATTR_FONT_UNDERLINE; font.SetUnderlined(attr.GetFont().GetUnderlined()); @@ -7775,6 +7939,10 @@ bool wxRichTextPlainTextHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputSt return false; wxString text = buffer->GetText(); + + wxString newLine = wxRichTextLineBreakChar; + text.Replace(newLine, wxT("\n")); + wxCharBuffer buf = text.ToAscii(); stream.Write((const char*) buf, text.length());