From 3eee14711140c3e71ac2e8c8de63bf81fcdae470 Mon Sep 17 00:00:00 2001 From: Richard Date: Thu, 9 Jul 2026 20:45:39 -0600 Subject: [PATCH] Increment numbered bullet continuation in wxRichTextCtrl Let the control continue numbered bullet styles that are not backed by a named list style when creating the next paragraph. Preserve named list style validation and keep explicit bullet numbers unchanged. Fixes #10074. Closes #27030. --- src/richtext/richtextbuffer.cpp | 96 ++++++++++++++++------------- tests/controls/richtextctrltest.cpp | 10 +++ 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index a96d6a1f61..8c847f8be9 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -4717,53 +4717,65 @@ bool wxRichTextParagraphLayoutBox::FindNextParagraphNumber(wxRichTextParagraph* if (!previousParagraph || !previousParagraph->GetAttributes().HasFlag(wxTEXT_ATTR_BULLET_STYLE) || previousParagraph->GetAttributes().GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_NONE) return false; + const wxRichTextAttr& previousAttr = previousParagraph->GetAttributes(); + const int numberedStyles = + wxTEXT_ATTR_BULLET_STYLE_ARABIC | + wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER | + wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER | + wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER | + wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER | + wxTEXT_ATTR_BULLET_STYLE_OUTLINE; + wxRichTextBuffer* buffer = GetBuffer(); wxRichTextStyleSheet* styleSheet = buffer->GetStyleSheet(); - if (styleSheet && !previousParagraph->GetAttributes().GetListStyleName().IsEmpty()) + bool hasListStyle = !previousAttr.GetListStyleName().IsEmpty(); + + if ( !(previousAttr.GetBulletStyle() & numberedStyles) || + (!hasListStyle && !previousAttr.HasBulletNumber()) ) + return false; + + if ( hasListStyle ) { - wxRichTextListStyleDefinition* def = styleSheet->FindListStyle(previousParagraph->GetAttributes().GetListStyleName()); - if (def) - { - // 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)); - if (previousParagraph->GetAttributes().HasBulletName()) - 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(); - if (!text.IsEmpty()) - { - int pos = text.Find(wxT('.'), true); - if (pos != wxNOT_FOUND) - { - text = text.Mid(0, text.length() - pos - 1); - } - else - text.clear(); - if (!text.IsEmpty()) - text += wxT("."); - text += wxString::Format(wxT("%d"), nextNumber); - attr.SetBulletText(text); - } - } - - return true; - } - else + if ( !styleSheet || + !styleSheet->FindListStyle(previousAttr.GetListStyleName()) ) return false; } - else - return false; + + bool isOutline = + (previousAttr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_OUTLINE) != 0; + + attr.SetFlags(previousAttr.GetFlags() & (wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_TEXT|wxTEXT_ATTR_BULLET_NAME)); + if ( previousAttr.HasBulletName() ) + attr.SetBulletName(previousAttr.GetBulletName()); + attr.SetBulletStyle(previousAttr.GetBulletStyle()); + if ( previousAttr.HasListStyleName() ) + attr.SetListStyleName(previousAttr.GetListStyleName()); + + int nextNumber = previousAttr.HasBulletNumber() + ? previousAttr.GetBulletNumber() + 1 + : 1; + attr.SetBulletNumber(nextNumber); + + if ( isOutline ) + { + wxString text = previousAttr.GetBulletText(); + if ( !text.IsEmpty() ) + { + int pos = text.Find(wxT('.'), true); + if ( pos != wxNOT_FOUND ) + { + text = text.Mid(0, text.length() - pos - 1); + } + else + text.clear(); + if ( !text.IsEmpty() ) + text += wxT("."); + text += wxString::Format(wxT("%d"), nextNumber); + attr.SetBulletText(text); + } + } + + return true; } /*! diff --git a/tests/controls/richtextctrltest.cpp b/tests/controls/richtextctrltest.cpp index c264b52869..ee06845577 100644 --- a/tests/controls/richtextctrltest.cpp +++ b/tests/controls/richtextctrltest.cpp @@ -678,6 +678,16 @@ TEST_CASE_METHOD(RichTextCtrlTestCase, "RichTextCtrl::NumberedBullet", CHECK(bullet.GetLeftIndent() == 15); CHECK(bullet.GetLeftSubIndent() == 20); + wxRichTextParagraph *firstPara = + m_rich->GetFocusObject()->GetParagraphAtPosition(5); + wxRichTextAttr nextBullet; + + REQUIRE(m_rich->GetFocusObject()->FindNextParagraphNumber(firstPara, + nextBullet)); + CHECK(nextBullet.HasBulletStyle()); + CHECK(nextBullet.HasBulletNumber()); + CHECK(nextBullet.GetBulletNumber() == 2); + m_rich->GetStyle(15, bullet); CHECK(bullet.HasBulletStyle());