X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/336d8ae9a3feae7b2c3ecd8f64fe0e16984edfe7..346d8899f312739ffe0cca64bb0538ecdb34dcdf:/src/richtext/richtextbuffer.cpp diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index 6388b00489..4b78f06808 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -906,7 +906,7 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraph(const wxString& text, // Don't use the base style, just the default style, and the base style will // be combined at display time. // Divide into paragraph and character styles. - + wxTextAttrEx defaultCharStyle; wxTextAttrEx defaultParaStyle; @@ -930,7 +930,7 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text // Don't use the base style, just the default style, and the base style will // be combined at display time. // Divide into paragraph and character styles. - + wxTextAttrEx defaultCharStyle; wxTextAttrEx defaultParaStyle; wxRichTextSplitParaCharStyles(GetDefaultStyle(), defaultParaStyle, defaultCharStyle); @@ -993,7 +993,7 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddImage(const wxImage& image, wxT // Don't use the base style, just the default style, and the base style will // be combined at display time. // Divide into paragraph and character styles. - + wxTextAttrEx defaultCharStyle; wxTextAttrEx defaultParaStyle; wxRichTextSplitParaCharStyles(GetDefaultStyle(), defaultParaStyle, defaultCharStyle); @@ -1561,11 +1561,12 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const bool parasOnly = ((flags & wxRICHTEXT_SETSTYLE_PARAGRAPHS_ONLY) != 0); bool charactersOnly = ((flags & wxRICHTEXT_SETSTYLE_CHARACTERS_ONLY) != 0); bool resetExistingStyle = ((flags & wxRICHTEXT_SETSTYLE_RESET) != 0); + bool removeStyle = ((flags & wxRICHTEXT_SETSTYLE_REMOVE) != 0); // Apply paragraph style first, if any wxRichTextAttr wholeStyle(style); - if (wholeStyle.HasParagraphStyleName() && GetStyleSheet()) + if (!removeStyle && wholeStyle.HasParagraphStyleName() && GetStyleSheet()) { wxRichTextParagraphStyleDefinition* def = GetStyleSheet()->FindParagraphStyle(wholeStyle.GetParagraphStyleName()); if (def) @@ -1576,7 +1577,7 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const wxRichTextAttr characterAttributes(wholeStyle); characterAttributes.SetFlags(characterAttributes.GetFlags() & (wxTEXT_ATTR_CHARACTER)); - if (characterAttributes.HasCharacterStyleName() && GetStyleSheet()) + if (!removeStyle && characterAttributes.HasCharacterStyleName() && GetStyleSheet()) { wxRichTextCharacterStyleDefinition* def = GetStyleSheet()->FindCharacterStyle(characterAttributes.GetCharacterStyleName()); if (def) @@ -1630,7 +1631,12 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const // to be included in the paragraph style if ((paragraphStyle || parasOnly) && !charactersOnly) { - if (resetExistingStyle) + if (removeStyle) + { + // Removes the given style from the paragraph + wxRichTextRemoveStyle(newPara->GetAttributes(), style); + } + else if (resetExistingStyle) newPara->GetAttributes() = wholeStyle; else { @@ -1705,7 +1711,12 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const { wxRichTextObject* child = node2->GetData(); - if (resetExistingStyle) + if (removeStyle) + { + // Removes the given style from the paragraph + wxRichTextRemoveStyle(child->GetAttributes(), style); + } + else if (resetExistingStyle) child->GetAttributes() = characterAttributes; else { @@ -2221,7 +2232,7 @@ bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttrEx& currentStyle, cons { // We need to find the bits in the new style that are different: // just look at those bits that are specified by the new style. - + int currentRelevantTextEffects = currentStyle.GetTextEffects() & style.GetTextEffectFlags(); int newRelevantTextEffects = style.GetTextEffects() & style.GetTextEffectFlags(); @@ -2229,7 +2240,7 @@ bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttrEx& currentStyle, cons { // Find the text effects that were different, using XOR int differentEffects = currentRelevantTextEffects ^ newRelevantTextEffects; - + // Clash of style - mark as such multipleTextEffectAttributes |= differentEffects; currentStyle.SetTextEffectFlags(currentStyle.GetTextEffectFlags() & ~differentEffects); @@ -2271,7 +2282,7 @@ bool wxRichTextParagraphLayoutBox::GetStyleForRange(const wxRichTextRange& range // The attributes that aren't valid because of multiple styles within the range long multipleStyleAttributes = 0; int multipleTextEffectAttributes = 0; - + wxRichTextObjectList::compatibility_iterator node = GetChildren().GetFirst(); while (node) { @@ -2433,7 +2444,7 @@ void wxRichTextParagraphLayoutBox::Reset() Clear(); AddParagraph(wxEmptyString); - + Invalidate(wxRICHTEXT_ALL); } @@ -2565,7 +2576,7 @@ bool wxRichTextParagraphLayoutBox::ApplyStyleSheet(wxRichTextStyleSheet* styleSh 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); @@ -2923,7 +2934,7 @@ bool wxRichTextParagraphLayoutBox::FindNextParagraphNumber(wxRichTextParagraph* { if (!previousParagraph->GetAttributes().HasFlag(wxTEXT_ATTR_BULLET_STYLE) || previousParagraph->GetAttributes().GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_NONE) return false; - + wxRichTextStyleSheet* styleSheet = GetStyleSheet(); if (styleSheet && !previousParagraph->GetAttributes().GetListStyleName().IsEmpty()) { @@ -2932,7 +2943,7 @@ bool wxRichTextParagraphLayoutBox::FindNextParagraphNumber(wxRichTextParagraph* { // int thisIndent = previousParagraph->GetAttributes().GetLeftIndent(); // int thisLevel = def->FindLevelForIndent(thisIndent); - + bool isOutline = (previousParagraph->GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_OUTLINE) != 0; attr.SetFlags(previousParagraph->GetAttributes().GetFlags() & (wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_TEXT|wxTEXT_ATTR_BULLET_NAME)); @@ -2940,10 +2951,10 @@ bool wxRichTextParagraphLayoutBox::FindNextParagraphNumber(wxRichTextParagraph* attr.SetBulletName(previousParagraph->GetAttributes().GetBulletName()); attr.SetBulletStyle(previousParagraph->GetAttributes().GetBulletStyle()); attr.SetListStyleName(previousParagraph->GetAttributes().GetListStyleName()); - + int nextNumber = previousParagraph->GetAttributes().GetBulletNumber() + 1; attr.SetBulletNumber(nextNumber); - + if (isOutline) { wxString text = previousParagraph->GetAttributes().GetBulletText(); @@ -2962,7 +2973,7 @@ bool wxRichTextParagraphLayoutBox::FindNextParagraphNumber(wxRichTextParagraph* attr.SetBulletText(text); } } - + return true; } else @@ -3017,6 +3028,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; @@ -3049,15 +3070,15 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR if (wxRichTextBuffer::GetRenderer()) wxRichTextBuffer::GetRenderer()->DrawBitmapBullet(this, dc, bulletAttr, bulletRect); } - else if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_STANDARD) - { + else if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_STANDARD) + { if (wxRichTextBuffer::GetRenderer()) wxRichTextBuffer::GetRenderer()->DrawStandardBullet(this, dc, bulletAttr, bulletRect); } else { wxString bulletText = GetBulletText(); - + if (!bulletText.empty() && wxRichTextBuffer::GetRenderer()) wxRichTextBuffer::GetRenderer()->DrawTextBullet(this, dc, bulletAttr, bulletRect, bulletText); } @@ -3084,7 +3105,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR while (node2) { wxRichTextObject* child = node2->GetData(); - + if (!child->GetRange().IsOutside(lineRange) && !lineRange.IsOutside(range)) { // Draw this part of the line at the correct position @@ -3197,17 +3218,17 @@ 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 ((nextBreakPos == -1) && (lastEndPos == child->GetRange().GetStart() - 1)) // i.e. we want to get the whole thing { childSize = child->GetCachedSize(); @@ -3479,7 +3500,7 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz rangeToUse.LimitTo(child->GetRange()); int childDescent = 0; - if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, position)) + if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, wxPoint(position.x + sz.x, position.y))) { sz.y = wxMax(sz.y, childSize.y); sz.x += childSize.x; @@ -3524,7 +3545,7 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz wxSize childSize; int childDescent = 0; - if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, position)) + if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, wxPoint(position.x + sz.x, position.y))) { lineSize.y = wxMax(lineSize.y, childSize.y); lineSize.x += childSize.x; @@ -3658,12 +3679,12 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition if (pt.x < linePos.x) { textPosition = lineRange.GetStart(); - return wxRICHTEXT_HITTEST_BEFORE; + return wxRICHTEXT_HITTEST_BEFORE|wxRICHTEXT_HITTEST_OUTSIDE; } else if (pt.x >= (linePos.x + lineSize.x)) { textPosition = lineRange.GetEnd(); - return wxRICHTEXT_HITTEST_AFTER; + return wxRICHTEXT_HITTEST_AFTER|wxRICHTEXT_HITTEST_OUTSIDE; } else { @@ -3900,9 +3921,11 @@ bool wxRichTextParagraph::FindWrapPosition(const wxRichTextRange& range, wxDC& d else { int spacePos = plainText.Find(wxT(' '), true); - if (spacePos != wxNOT_FOUND) + int tabPos = plainText.Find(wxT('\t'), true); + int pos = wxMax(spacePos, tabPos); + if (pos != wxNOT_FOUND) { - int positionsFromEndOfString = plainText.length() - spacePos - 1; + int positionsFromEndOfString = plainText.length() - pos - 1; breakPosition = breakPosition - positionsFromEndOfString; } } @@ -3950,7 +3973,7 @@ wxString wxRichTextParagraph::GetBulletText() { text = GetAttributes().GetBulletText(); } - + if (GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_OUTLINE) { // The outline style relies on the text being computed statically, @@ -4144,6 +4167,9 @@ wxRichTextPlainText::wxRichTextPlainText(const wxString& text, wxRichTextObject* #define USE_KERNING_FIX 1 +// If insufficient tabs are defined, this is the tab width used +#define WIDTH_FOR_DEFAULT_TABS 50 + /// Draw the item bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int WXUNUSED(style)) { @@ -4158,7 +4184,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR wxString str = m_text; wxString toRemove = wxRichTextLineBreakChar; str.Replace(toRemove, wxT(" ")); - + long len = range.GetLength(); wxString stringChunk = str.Mid(range.GetStart() - offset, (size_t) len); if (textAttr.HasTextEffects() && (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_CAPITALS)) @@ -4310,7 +4336,14 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, c else { dc.SetTextForeground(attr.GetTextColour()); - dc.SetBackgroundMode(wxTRANSPARENT); + + if (attr.HasFlag(wxTEXT_ATTR_BACKGROUND_COLOUR) && attr.GetBackgroundColour().IsOk()) + { + dc.SetBackgroundMode(wxSOLID); + dc.SetTextBackground(attr.GetBackgroundColour()); + } + else + dc.SetBackgroundMode(wxTRANSPARENT); } while (hasTabs) @@ -4325,8 +4358,18 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, c for (int i = 0; i < tabCount && not_found; ++i) { nextTabPos = tabArray.Item(i); - if (nextTabPos > tabPos) + + // Find the next tab position. + // Even if we're at the end of the tab array, we must still draw the chunk. + + if (nextTabPos > tabPos || (i == (tabCount - 1))) { + if (nextTabPos <= tabPos) + { + int defaultTabWidth = ConvertTenthsMMToPixels(dc, WIDTH_FOR_DEFAULT_TABS); + nextTabPos = tabPos + defaultTabWidth; + } + not_found = false; if (selected) { @@ -4377,24 +4420,7 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, c /// Lay the item out bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), int WXUNUSED(style)) { - wxRichTextParagraph* para = wxDynamicCast(GetParent(), wxRichTextParagraph); - wxASSERT (para != NULL); - - wxTextAttrEx textAttr(para ? para->GetCombinedAttributes(GetAttributes()) : GetAttributes()); - - if (textAttr.GetFont().Ok()) - dc.SetFont(textAttr.GetFont()); - - wxString str = m_text; - 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()); + GetRangeSize(GetRange(), m_size, m_descent, dc, 0, wxPoint(0, 0)); return true; } @@ -4428,7 +4454,7 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz int startPos = range.GetStart() - GetRange().GetStart(); long len = range.GetLength(); - + wxString str(m_text); wxString toReplace = wxRichTextLineBreakChar; str.Replace(toReplace, wxT(" ")); @@ -4469,12 +4495,23 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz dc.GetTextExtent(stringFragment, & w, & h); width += w; int absoluteWidth = width + position.x; + bool notFound = true; for (int i = 0; i < tabCount && notFound; ++i) { nextTabPos = tabArray.Item(i); - if (nextTabPos > absoluteWidth) + + // Find the next tab position. + // Even if we're at the end of the tab array, we must still process the chunk. + + if (nextTabPos > absoluteWidth || (i == (tabCount - 1))) { + if (nextTabPos <= absoluteWidth) + { + int defaultTabWidth = ((wxRichTextPlainText*) this)->ConvertTenthsMMToPixels(dc, WIDTH_FOR_DEFAULT_TABS); + nextTabPos = absoluteWidth + defaultTabWidth; + } + notFound = false; width = nextTabPos - position.x; } @@ -4493,7 +4530,7 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz wxRichTextObject* wxRichTextPlainText::DoSplit(long pos) { long index = pos - GetRange().GetStart(); - + if (index < 0 || index >= (int) m_text.length()) return NULL; @@ -4507,7 +4544,7 @@ wxRichTextObject* wxRichTextPlainText::DoSplit(long pos) newObject->SetRange(wxRichTextRange(pos, GetRange().GetEnd())); GetRange().SetEnd(pos-1); - + return newObject; } @@ -4636,7 +4673,7 @@ wxRichTextBuffer::~wxRichTextBuffer() void wxRichTextBuffer::ResetAndClearCommands() { Reset(); - + GetCommandProcessor()->ClearCommands(); Modify(false); @@ -4730,7 +4767,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; } @@ -4745,6 +4783,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); @@ -4765,7 +4805,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; } @@ -4829,16 +4869,16 @@ 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) { wxRichTextAttr attr; 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) @@ -4852,7 +4892,7 @@ wxRichTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPos attr = nextParaDef->GetStyleMergedWithBase(GetStyleSheet()); } } - + // If we didn't find the 'next style', use this style instead. if (!foundAttributes) { @@ -4872,7 +4912,7 @@ wxRichTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPos (~ wxTEXT_ATTR_BACKGROUND_COLOUR) ); attr.SetFlags(flags); } - + // Now see if we need to number the paragraph. if (attr.HasBulletStyle()) { @@ -5637,7 +5677,7 @@ bool wxRichTextBuffer::RemoveEventHandler(wxEvtHandler* handler, bool deleteHand m_eventHandlers.Erase(node); if (deleteHandler) delete handler; - + return true; } else @@ -5672,17 +5712,17 @@ bool wxRichTextBuffer::SendEvent(wxEvent& event, bool sendToAll) bool wxRichTextBuffer::SetStyleSheetAndNotify(wxRichTextStyleSheet* sheet) { wxRichTextStyleSheet* oldSheet = GetStyleSheet(); - + wxWindowID id = wxID_ANY; if (GetRichTextCtrl()) id = GetRichTextCtrl()->GetId(); - + wxRichTextEvent event(wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING, id); event.SetEventObject(GetRichTextCtrl()); event.SetOldStyleSheet(oldSheet); event.SetNewStyleSheet(sheet); event.Allow(); - + if (SendEvent(event) && !event.IsAllowed()) { if (sheet != oldSheet) @@ -5733,26 +5773,26 @@ bool wxRichTextStdRenderer::DrawStandardBullet(wxRichTextParagraph* paragraph, w dc.SetFont(font); int charHeight = dc.GetCharHeight(); - + int bulletWidth = (int) (((float) charHeight) * wxRichTextBuffer::GetBulletProportion()); int bulletHeight = bulletWidth; int x = rect.x; - + // Calculate the top position of the character (as opposed to the whole line height) int y = rect.y + (rect.height - charHeight); - + // Calculate where the bullet should be positioned y = y + (charHeight+1)/2 - (bulletHeight+1)/2; - + // The margin between a bullet and text. int margin = paragraph->ConvertTenthsMMToPixels(dc, wxRichTextBuffer::GetBulletRightMargin()); - + if (bulletAttr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT) x = rect.x + rect.width - bulletWidth - margin; else if (bulletAttr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE) x = x + (rect.width)/2 - bulletWidth/2; - + if (bulletAttr.GetBulletName() == wxT("standard/square")) { dc.DrawRectangle(x, y, bulletWidth, bulletHeight); @@ -5764,7 +5804,7 @@ bool wxRichTextStdRenderer::DrawStandardBullet(wxRichTextParagraph* paragraph, w pts[1].x = x + bulletWidth/2; pts[1].y = y; pts[2].x = x + bulletWidth; pts[2].y = y + bulletHeight/2; pts[3].x = x + bulletWidth/2; pts[3].y = y + bulletHeight; - + dc.DrawPolygon(4, pts); } else if (bulletAttr.GetBulletName() == wxT("standard/triangle")) @@ -5773,14 +5813,14 @@ bool wxRichTextStdRenderer::DrawStandardBullet(wxRichTextParagraph* paragraph, w pts[0].x = x; pts[0].y = y; pts[1].x = x + bulletWidth; pts[1].y = y + bulletHeight/2; pts[2].x = x; pts[2].y = y + bulletHeight; - + dc.DrawPolygon(3, pts); } else // "standard/circle", and catch-all { dc.DrawEllipse(x, y, bulletWidth, bulletHeight); - } - + } + return true; } @@ -5814,18 +5854,18 @@ bool wxRichTextStdRenderer::DrawTextBullet(wxRichTextParagraph* paragraph, wxDC& int x = rect.x; // Calculate the top position of the character (as opposed to the whole line height) - int y = rect.y + (rect.height - charHeight); + int y = rect.y + (rect.height - charHeight); // The margin between a bullet and text. int margin = paragraph->ConvertTenthsMMToPixels(dc, wxRichTextBuffer::GetBulletRightMargin()); - + if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT) x = (rect.x + rect.width) - tw - margin; else if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE) x = x + (rect.width)/2 - tw/2; dc.DrawText(text, x, y); - + return true; } else @@ -5992,7 +6032,7 @@ bool wxRichTextAction::Do() wxSize clientSize = m_ctrl->GetClientSize(); wxPoint firstVisiblePt = m_ctrl->GetFirstVisiblePoint(); int lastY = firstVisiblePt.y + clientSize.y; - + wxRichTextParagraph* para = m_buffer->GetParagraphAtPosition(GetPosition()); wxRichTextObjectList::compatibility_iterator node = m_buffer->GetChildren().Find(para); while (node) @@ -6004,14 +6044,14 @@ bool wxRichTextAction::Do() wxRichTextLine* line = node2->GetData(); wxPoint pt = line->GetAbsolutePosition(); wxRichTextRange range = line->GetAbsoluteRange(); - + if (pt.y > lastY) { node2 = wxRichTextLineList::compatibility_iterator(); node = wxRichTextObjectList::compatibility_iterator(); } else if (range.GetStart() > GetPosition() && pt.y >= firstVisiblePt.y) - { + { optimizationLineCharPositions.Add(range.GetStart()); optimizationLineYPositions.Add(pt.y); } @@ -6019,11 +6059,11 @@ bool wxRichTextAction::Do() if (node2) node2 = node2->GetNext(); } - + if (node) node = node->GetNext(); } - } + } #endif m_buffer->InsertFragment(GetPosition(), m_newParagraphs); @@ -6038,21 +6078,28 @@ 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)); + newCaretPosition = wxMin(newCaretPosition, (m_buffer->GetRange().GetEnd()-1)); if (optimizationLineCharPositions.GetCount() > 0) UpdateAppearance(newCaretPosition, true /* send update event */, & optimizationLineCharPositions, & optimizationLineYPositions); else UpdateAppearance(newCaretPosition, true /* send update event */); - + wxRichTextEvent cmdEvent( wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED, m_ctrl ? m_ctrl->GetId() : -1); cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer); cmdEvent.SetRange(GetRange()); cmdEvent.SetPosition(GetRange().GetStart()); - + m_buffer->SendEvent(cmdEvent); break; @@ -6071,7 +6118,7 @@ bool wxRichTextAction::Do() cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer); cmdEvent.SetRange(GetRange()); cmdEvent.SetPosition(GetRange().GetStart()); - + m_buffer->SendEvent(cmdEvent); break; @@ -6089,7 +6136,7 @@ bool wxRichTextAction::Do() cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer); cmdEvent.SetRange(GetRange()); cmdEvent.SetPosition(GetRange().GetStart()); - + m_buffer->SendEvent(cmdEvent); break; @@ -6114,7 +6161,7 @@ bool wxRichTextAction::Undo() m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart())); long newCaretPosition = GetPosition() - 1; - + UpdateAppearance(newCaretPosition, true /* send update event */); wxRichTextEvent cmdEvent( @@ -6123,7 +6170,7 @@ bool wxRichTextAction::Undo() cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer); cmdEvent.SetRange(GetRange()); cmdEvent.SetPosition(GetRange().GetStart()); - + m_buffer->SendEvent(cmdEvent); break; @@ -6142,7 +6189,7 @@ bool wxRichTextAction::Undo() cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer); cmdEvent.SetRange(GetRange()); cmdEvent.SetPosition(GetRange().GetStart()); - + m_buffer->SendEvent(cmdEvent); break; @@ -6160,7 +6207,7 @@ bool wxRichTextAction::Undo() cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer); cmdEvent.SetRange(GetRange()); cmdEvent.SetPosition(GetRange().GetStart()); - + m_buffer->SendEvent(cmdEvent); break; @@ -6182,30 +6229,30 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent { m_ctrl->LayoutContent(); m_ctrl->PositionCaret(); - + #if wxRICHTEXT_USE_OPTIMIZED_DRAWING // Find refresh rectangle if we are in a position to optimise refresh if (m_cmdId == wxRICHTEXT_INSERT && optimizationLineCharPositions && optimizationLineCharPositions->GetCount() > 0) { size_t i; - + wxSize clientSize = m_ctrl->GetClientSize(); wxPoint firstVisiblePt = m_ctrl->GetFirstVisiblePoint(); - + // Start/end positions int firstY = 0; int lastY = firstVisiblePt.y + clientSize.y; - + bool foundStart = false; bool foundEnd = false; - + // position offset - how many characters were inserted int positionOffset = GetRange().GetLength(); // find the first line which is being drawn at the same position as it was // before. Since we're talking about a simple insertion, we can assume // that the rest of the window does not need to be redrawn. - + wxRichTextParagraph* para = m_buffer->GetParagraphAtPosition(GetPosition()); wxRichTextObjectList::compatibility_iterator node = m_buffer->GetChildren().Find(para); while (node) @@ -6217,10 +6264,10 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent wxRichTextLine* line = node2->GetData(); wxPoint pt = line->GetAbsolutePosition(); wxRichTextRange range = line->GetAbsoluteRange(); - + // we want to find the first line that is in the same position // as before. This will mean we're at the end of the changed text. - + if (pt.y > lastY) // going past the end of the window, no more info { node2 = wxRichTextLineList::compatibility_iterator(); @@ -6234,7 +6281,7 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent foundStart = true; } - // search for this line being at the same position as before + // search for this line being at the same position as before for (i = 0; i < optimizationLineCharPositions->GetCount(); i++) { if (((*optimizationLineCharPositions)[i] + positionOffset == range.GetStart()) && @@ -6248,18 +6295,18 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent node = wxRichTextObjectList::compatibility_iterator(); break; - } + } } } if (node2) node2 = node2->GetNext(); } - + if (node) node = node->GetNext(); } - + if (!foundStart) firstY = firstVisiblePt.y; if (!foundEnd) @@ -6267,12 +6314,12 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent wxRect rect(firstVisiblePt.x, firstY, firstVisiblePt.x + clientSize.x, lastY - firstY); m_ctrl->RefreshRect(rect); - + // TODO: we need to make sure that lines are only drawn if in the update region. The rect // passed to Draw is currently used in different ways (to pass the position the content should // be drawn at as well as the relevant region). } - else + else #endif m_ctrl->Refresh(false); @@ -6826,9 +6873,9 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxTextAttrEx& style) int srcBits = style.GetTextEffects(); int srcFlags = style.GetTextEffectFlags(); - + wxRichTextCombineBitlists(destBits, srcBits, destFlags, srcFlags); - + destStyle.SetTextEffects(destBits); destStyle.SetTextEffectFlags(destFlags); } @@ -7062,9 +7109,9 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style, int srcBits = style.GetTextEffects(); int srcFlags = style.GetTextEffectFlags(); - + wxRichTextCombineBitlists(destBits, srcBits, destFlags, srcFlags); - + destStyle.SetTextEffects(destBits); destStyle.SetTextEffectFlags(destFlags); } @@ -7079,23 +7126,34 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style, return true; } +// Remove attributes +bool wxRichTextRemoveStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style) +{ + int flags = style.GetFlags(); + int destFlags = destStyle.GetFlags(); + + destStyle.SetFlags(destFlags & ~flags); + + return true; +} + /// Combine two bitlists, specifying the bits of interest with separate flags. bool wxRichTextCombineBitlists(int& valueA, int valueB, int& flagsA, int flagsB) { // We want to apply B's bits to A, taking into account each's flags which indicate which bits // are to be taken into account. A zero in B's bits should reset that bit in A but only if B's flags // indicate it. - + // First, reset the 0 bits from B. We make a mask so we're only dealing with B's zero // bits at this point, ignoring any 1 bits in B or 0 bits in B that are not relevant. int valueA2 = ~(~valueB & flagsB) & valueA; - + // Now combine the 1 bits. int valueA3 = (valueB & flagsB) | valueA2; - + valueA = valueA3; flagsA = (flagsA | flagsB); - + return true; } @@ -7117,7 +7175,7 @@ bool wxRichTextSplitParaCharStyles(const wxTextAttrEx& style, wxTextAttrEx& parS wxRichTextApplyStyle(charStyle, defaultCharStyle1); wxRichTextApplyStyle(parStyle, defaultParaStyle1); - + return true; } @@ -7273,7 +7331,7 @@ void wxRichTextAttr::Copy(const wxRichTextAttr& attr) // operators void wxRichTextAttr::operator= (const wxRichTextAttr& attr) -{ +{ Copy(attr); } @@ -7381,7 +7439,7 @@ bool wxRichTextAttr::operator== (const wxRichTextAttr& attr) const GetFontWeight() == attr.GetFontWeight() && GetFontUnderlined() == attr.GetFontUnderlined() && GetFontFaceName() == attr.GetFontFaceName() && - + GetURL() == attr.GetURL(); } @@ -7414,14 +7472,14 @@ wxRichTextAttr wxRichTextAttr::Combine(const wxRichTextAttr& style, const wxRich { wxRichTextAttr destStyle = (*this); destStyle.Apply(style, compareWith); - + return destStyle; } bool wxRichTextAttr::Apply(const wxRichTextAttr& style, const wxRichTextAttr* compareWith) { wxRichTextAttr& destStyle = (*this); - + if (style.HasFontWeight()) { if (!(compareWith && compareWith->HasFontWeight() && compareWith->GetFontWeight() == style.GetFontWeight())) @@ -7573,9 +7631,9 @@ bool wxRichTextAttr::Apply(const wxRichTextAttr& style, const wxRichTextAttr* co int srcBits = style.GetTextEffects(); int srcFlags = style.GetTextEffectFlags(); - + wxRichTextCombineBitlists(destBits, srcBits, destFlags, srcFlags); - + destStyle.SetTextEffects(destBits); destStyle.SetTextEffectFlags(destFlags); } @@ -7922,7 +7980,7 @@ bool wxRichTextPlainTextHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputSt wxString newLine = wxRichTextLineBreakChar; text.Replace(newLine, wxT("\n")); - + wxCharBuffer buf = text.ToAscii(); stream.Write((const char*) buf, text.length()); @@ -8143,8 +8201,8 @@ bool wxRichTextImageBlock::ReadHex(wxInputStream& stream, int length, int imageT int i; for (i = 0; i < dataSize; i ++) { - str[0] = stream.GetC(); - str[1] = stream.GetC(); + str[0] = (char)stream.GetC(); + str[1] = (char)stream.GetC(); m_data[i] = (unsigned char)wxHexToDec(str); }