Fix nested markup conversion to NSAttributedString
Unix builds / Ubuntu 18.04 wxGTK 3 compatible 3.0 (push) Has been cancelled
Unix builds / Ubuntu 24.04 wxGTK ASAN not compatible (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxGTK UTF-8 (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxQt (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxX11 (push) Has been cancelled
Unix builds / Ubuntu 20.04 wxGTK 3 with clang (push) Has been cancelled
Unix builds / Ubuntu 22.04 wxGTK with wx containers (push) Has been cancelled
Unix builds / Ubuntu 24.04 wxGTK UBSAN (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxDFB (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxGTK 3 static with gcc 4.8 (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxGTK 2 (push) Has been cancelled
CMake builds / Ubuntu 22.04 wxGTK 3 (push) Has been cancelled
CMake builds / MSW/MSVC wxMSW (push) Has been cancelled
CMake builds / MSW/Clang wxMSW (push) Has been cancelled
CMake builds / macOS latest wxOSX Ninja (push) Has been cancelled
CMake builds / macOS 14 wxOSX Xcode (push) Has been cancelled
CMake builds / macOS 14 wxIOS (push) Has been cancelled
CMake builds / MSW/MSVC wxQt 5.15 (push) Has been cancelled
CMake builds / MSW/MSVC wxQt 6.8 (push) Has been cancelled
Mac builds / wxMac ARM ASAN not compatible (push) Has been cancelled
Mac builds / wxMac Universal C++14 (push) Has been cancelled
Mac builds / wxiOS Simulator on Silicon Mac (push) Has been cancelled
Mac builds / wxiOS (push) Has been cancelled
Mac builds / wxMac Intel C++17 (push) Has been cancelled
Mac Xcode builds / iOS Simulator static (push) Has been cancelled
Mac Xcode builds / macOS dynamic Release (push) Has been cancelled
Mac Xcode builds / iOS static Debug (push) Has been cancelled
MSW builds / wxMSW vs2022 DLL Debug x64 (push) Has been cancelled
MSW builds / wxMSW vs2022 DLL Release x64 (push) Has been cancelled
MSW builds / wxMSW vs2022 Debug Win32 (push) Has been cancelled
MSW builds / wxMSW vs2022 Release arm64 (push) Has been cancelled
MSW cross-builds / wxMSW 64 bits not compatible (push) Has been cancelled
MSW cross-builds / wxMSW/Univ (push) Has been cancelled
MSW cross-builds / wxMSW 32 bits (push) Has been cancelled
Code Checks / Check Spelling (push) Has been cancelled
Code Checks / Check Whitespace (push) Has been cancelled
Code Checks / Check Mixed EOL (push) Has been cancelled
Code Checks / Check C++ Style (push) Has been cancelled
Code Checks / Check All Headers In allheaders.h (push) Has been cancelled
Update Documentation / Update Online Documentation (push) Has been cancelled

wxMarkupToAttrStringBase implementation of markup parsing failed to
correctly apply nested attributes: in e.g. <i><b>foo</b></i>, only the
outer attribute was in effect.

This was due to applying - and overwriting - attributes to a span in
OnAttrEnd(), which is called first for the inner span, and then for the
outer one, overwriting all inner changes.

Instead, apply the currently effective attributes to text in OnText(),
similarly to how wxMarkupParserRenderOutput does it. As a side effect,
this also eliminates the need to apply default font to the entire range
first.

Closes #25864.
This commit is contained in:
Václav Slavík
2025-10-06 22:41:56 +02:00
committed by Vadim Zeitlin
parent e068efbc14
commit ca05aee2f8
+23 -61
View File
@@ -37,12 +37,6 @@ protected:
[m_attrString beginEditing];
// First thing we do is change the default string font: as mentioned in
// Apple documentation, attributed strings use "Helvetica 12" font by
// default which is different from the system "Lucida Grande" font. So
// we need to explicitly change the font for the entire string.
ApplyFont(font, NSMakeRange(0, [m_attrString length]));
// Now translate the markup tags to corresponding attributes.
wxMarkupParser parser(*this);
parser.Parse(markup);
@@ -56,27 +50,6 @@ protected:
[m_attrString release];
}
void ApplyFont(const wxFont& font, const NSRange& range)
{
[m_attrString addAttribute:NSFontAttributeName
value:font.OSXGetNSFont()
range:range];
if ( font.GetStrikethrough() )
{
[m_attrString addAttribute:NSStrikethroughStyleAttributeName
value:@(NSUnderlineStyleSingle)
range:range];
}
if ( font.GetUnderlined() )
{
[m_attrString addAttribute:NSUnderlineStyleAttributeName
value:@(NSUnderlineStyleSingle)
range:range];
}
}
// prepare text chunk for display, e.g. strip mnemonics from it
virtual wxString PrepareText(const wxString& text) = 0;
@@ -89,43 +62,35 @@ public:
return m_attrString;
}
// Implement base class pure virtual methods to process markup tags.
virtual void OnText(const wxString& text) override
{
m_pos += PrepareText(text).length();
const Attr& attr = GetAttr();
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSFontAttributeName] = attr.effectiveFont.OSXGetNSFont();
if ( attr.effectiveFont.GetStrikethrough() )
dict[NSStrikethroughStyleAttributeName] = @(NSUnderlineStyleSingle);
if ( attr.effectiveFont.GetUnderlined() )
dict[NSUnderlineStyleAttributeName] = @(NSUnderlineStyleSingle);
if ( attr.effectiveForeground.IsOk() )
dict[NSForegroundColorAttributeName] = attr.effectiveForeground.OSXGetWXColor();
if ( attr.effectiveBackground.IsOk() )
dict[NSBackgroundColorAttributeName] = attr.effectiveBackground.OSXGetWXColor();
const unsigned len = PrepareText(text).length();
[m_attrString addAttributes:dict range:NSMakeRange(m_pos, len)];
m_pos += len;
}
virtual void OnAttrStart(const Attr& WXUNUSED(attr)) override
{
// Just remember the starting position of the range, we can't really
// set the attribute until we find the end of it.
m_rangeStarts.push(m_pos);
}
virtual void OnAttrStart(const Attr& WXUNUSED(attr)) override {}
virtual void OnAttrEnd(const Attr& attr) override
{
unsigned start = m_rangeStarts.top();
m_rangeStarts.pop();
const NSRange range = NSMakeRange(start, m_pos - start);
ApplyFont(attr.font, range);
if ( attr.foreground.IsOk() )
{
[m_attrString addAttribute:NSForegroundColorAttributeName
value:attr.foreground.OSXGetWXColor()
range:range];
}
if ( attr.background.IsOk() )
{
[m_attrString addAttribute:NSBackgroundColorAttributeName
value:attr.background.OSXGetWXColor()
range:range];
}
}
virtual void OnAttrEnd(const Attr& WXUNUSED(attr)) override {}
private:
// The attributed string we're building.
@@ -133,9 +98,6 @@ private:
// The current position in the output string.
unsigned m_pos;
// The positions of starting ranges.
wxStack<unsigned> m_rangeStarts;
};