[Git][wxwidgets/wxwidgets][master] 8 commits: CMake: Fix warning about backslashes in macro

2 views
Skip to first unread message

Vadim Zeitlin (@_VZ_)

unread,
Aug 17, 2026, 3:18:23 PM (11 days ago) Aug 17
to wx-commi...@googlegroups.com


Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets


Commits:
02405c4a by Maarten Bent at 2026-08-17T19:18:11+02:00
CMake: Fix warning about backslashes in macro

CMake 4.4 added a new policy CMP0219 to preserve backslashes in macros.
Ideally we want to use the new policy, but older CMake version will
still use the old one. Change the macro to a function so we don't have
to deal with handling old and new policies.

Closes #26852.

- - - - -
269024aa by Richard at 2026-08-17T19:36:58+02:00
Use image-relative coordinates for HTML image maps

Convert container and idle mouse positions to the target cell coordinate
space before querying links, so wxHTML image map hit testing receives
image-relative positions.

Add a wxHtmlWindow regression test covering a shifted image map.

Fixes #3163.

Closes #26859.

- - - - -
255d7ef0 by Richard at 2026-08-17T19:40:50+02:00
Avoid modal HTML help after missing topic

Only make wxHtmlHelpController window modal after a display operation
succeeds, so a failed topic lookup can fall through to a fallback topic
without showing a modal help frame.

Add a regression test covering a modal help dialog display request for a
missing topic.

Fixes #3219.

Closes #26860.

- - - - -
54bab87a by Richard at 2026-08-17T19:46:02+02:00
Preserve leading wxHTML BR elements

Keep an initial BR element as a real blank line even when the current
container only has formatting cells.

Add a wxHtmlWindow regression test covering text preceded by an initial
BR element.

Fixes #3345.

Closes #26861.

- - - - -
ef6c63a4 by Richard at 2026-08-17T20:08:43+02:00
Add missing Dstrok HTML entity

Recognize the uppercase and lowercase stroked-D named entities in the
HTML entity parser and cover them with a focused parser test.

Fixes #3996.

Closes #26864.

- - - - -
281a4b26 by Richard at 2026-08-17T20:17:28+02:00
Handle wxRichTextCtrl clipboard transfer failures

Fall back to lower-priority clipboard formats if advertised rich text
data can't actually be read, and only report paste success after data
has been retrieved.

Also avoid deleting the selection from wxRichTextCtrl::Cut() unless it
was successfully copied to the clipboard, and make the CutCopyPaste
test verify clipboard contents before relying on them.

See #18738 and #24120 possibly related to this.

Closes #26865.

- - - - -
4958d2db by Richard at 2026-08-17T20:43:44+02:00
Fix XRC unknown-control size hints after attach

Refresh the containing top-level window's sizer hints after an unknown
control is reparented into its placeholder. This lets wxPanel-derived
controls with their own size hints expand the dialog instead of staying
clipped at the placeholder's original size.

Add a regression test covering a panel attached to an unknown XRC
placeholder.

Fixes #2726.

Closes #26725.

- - - - -
0dc27e6a by Vadim Zeitlin at 2026-08-17T20:52:46+02:00
Add HtmlWindowTestCase::DisplayMissingHelpTopic() code

This was somehow lost when applying 255d7ef061 (Avoid modal HTML help
after missing topic, 2026-07-09).

See #26860.

- - - - -


15 changed files:

- build/cmake/functions.cmake
- build/cmake/install.cmake
- build/cmake/utils/CMakeLists.txt
- src/html/helpctrl.cpp
- src/html/htmlcell.cpp
- src/html/htmlpars.cpp
- src/html/htmlwin.cpp
- src/html/m_layout.cpp
- src/richtext/richtextbuffer.cpp
- src/richtext/richtextctrl.cpp
- src/xrc/xmlres.cpp
- tests/controls/richtextctrltest.cpp
- tests/html/htmlparser.cpp
- tests/html/htmlwindow.cpp
- tests/xml/xrctest.cpp


Changes:

=====================================
build/cmake/functions.cmake
=====================================
@@ -98,7 +98,7 @@ endmacro()
# wx_install_symlink(...)
# Create symlink dst pointing to src
# try different symlink and copy methods until one succeeds
-macro(wx_install_symlink src dst)
+function(wx_install_symlink src dst)
if(wxBUILD_INSTALL)
install(CODE "
set(SYMLINK_SRC \"${src}\")
@@ -129,7 +129,7 @@ macro(wx_install_symlink src dst)
endif()
")
endif()
-endmacro()
+endfunction()

# Get a valid flavour name with optional prefix
macro(wx_get_flavour flavour prefix)


=====================================
build/cmake/install.cmake
=====================================
@@ -67,7 +67,7 @@ else()

wx_get_install_platform_dir(runtime)
install(DIRECTORY DESTINATION "${runtime_dir}")
- set(CONFIG_DIR "\\\$ENV{DESTDIR}\\\${CMAKE_INSTALL_PREFIX}")
+ set(CONFIG_DIR "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}")
set(CONFIG_SRC "${CONFIG_DIR}/${library_dir}/wx/config/${wxBUILD_FILE_ID}")
set(CONFIG_DST "${CONFIG_DIR}/${runtime_dir}/wx-config")
wx_install_symlink(${CONFIG_SRC} ${CONFIG_DST})


=====================================
build/cmake/utils/CMakeLists.txt
=====================================
@@ -38,7 +38,7 @@ if(wxUSE_XRC)
set(EXE_SUFFIX ${CMAKE_EXECUTABLE_SUFFIX})
endif()

- set(WXRC_DIR "\\\$ENV{DESTDIR}\\\${CMAKE_INSTALL_PREFIX}")
+ set(WXRC_DIR "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}")
set(WXRC_SRC "${WXRC_DIR}/${runtime_dir}/${wxrc_output_name}${EXE_SUFFIX}")
set(WXRC_DST "${WXRC_DIR}/${runtime_dir}/wxrc${EXE_SUFFIX}")
wx_install_symlink(${WXRC_SRC} ${WXRC_DST})


=====================================
src/html/helpctrl.cpp
=====================================
@@ -405,7 +405,8 @@ bool wxHtmlHelpController::Display(const wxString& x)
{
CreateHelpWindow();
bool success = m_helpWindow->Display(x);
- MakeModalIfNeeded();
+ if ( success )
+ MakeModalIfNeeded();
return success;
}

@@ -413,7 +414,8 @@ bool wxHtmlHelpController::Display(int id)
{
CreateHelpWindow();
bool success = m_helpWindow->Display(id);
- MakeModalIfNeeded();
+ if ( success )
+ MakeModalIfNeeded();
return success;
}

@@ -421,7 +423,8 @@ bool wxHtmlHelpController::DisplayContents()
{
CreateHelpWindow();
bool success = m_helpWindow->DisplayContents();
- MakeModalIfNeeded();
+ if ( success )
+ MakeModalIfNeeded();
return success;
}

@@ -429,7 +432,8 @@ bool wxHtmlHelpController::DisplayIndex()
{
CreateHelpWindow();
bool success = m_helpWindow->DisplayIndex();
- MakeModalIfNeeded();
+ if ( success )
+ MakeModalIfNeeded();
return success;
}

@@ -438,7 +442,8 @@ bool wxHtmlHelpController::KeywordSearch(const wxString& keyword,
{
CreateHelpWindow();
bool success = m_helpWindow->KeywordSearch(keyword, mode);
- MakeModalIfNeeded();
+ if ( success )
+ MakeModalIfNeeded();
return success;
}



=====================================
src/html/htmlcell.cpp
=====================================
@@ -1187,10 +1187,13 @@ wxHtmlLinkInfo *wxHtmlContainerCell::GetLink(int x, int y) const
{
wxHtmlCell *cell = FindCellByPos(x, y);

- // VZ: I don't know if we should pass absolute or relative coords to
- // wxHtmlCell::GetLink()? As the base class version just ignores them
- // anyhow, it hardly matters right now but should still be clarified
- return cell ? cell->GetLink(x, y) : nullptr;
+ if ( !cell )
+ return nullptr;
+
+ wxPoint relpos(x, y);
+ relpos -= cell->GetAbsPos(this);
+
+ return cell->GetLink(relpos.x, relpos.y);
}


@@ -1366,7 +1369,11 @@ bool wxHtmlContainerCell::ProcessMouseClick(wxHtmlWindowInterface *window,
bool retval = false;
wxHtmlCell *cell = FindCellByPos(pos.x, pos.y);
if ( cell )
- retval = cell->ProcessMouseClick(window, pos, event);
+ {
+ wxPoint relpos(pos);
+ relpos -= cell->GetAbsPos(this);
+ retval = cell->ProcessMouseClick(window, relpos, event);
+ }

return retval;
}


=====================================
src/html/htmlpars.cpp
=====================================
@@ -555,6 +555,7 @@ wxChar wxHtmlEntitiesParser::GetEntityChar(const wxString& entity) const
ENTITY("Chi", 935),
ENTITY("Dagger", 8225),
ENTITY("Delta", 916),
+ ENTITY("Dstrok", 272),
ENTITY("ETH", 208),
ENTITY("Eacute", 201),
ENTITY("Ecirc", 202),
@@ -639,6 +640,7 @@ wxChar wxHtmlEntitiesParser::GetEntityChar(const wxString& entity) const
ENTITY("delta", 948),
ENTITY("diams", 9830),
ENTITY("divide", 247),
+ ENTITY("dstrok", 273),
ENTITY("eacute", 233),
ENTITY("ecirc", 234),
ENTITY("egrave", 232),


=====================================
src/html/htmlwin.cpp
=====================================
@@ -195,49 +195,46 @@ void wxHtmlWindowMouseHelper::HandleIdle(wxHtmlCell *rootCell,
const wxPoint& pos)
{
wxHtmlCell *cell = rootCell ? rootCell->FindCellByPos(pos.x, pos.y) : nullptr;
+ wxHtmlLinkInfo *lnk = nullptr;
+ wxPoint relpos;

- if (cell != m_tmpLastCell)
+ if ( cell )
{
- wxHtmlLinkInfo *lnk = nullptr;
- if (cell)
- {
- // adjust the coordinates to be relative to this cell:
- wxPoint relpos = pos - cell->GetAbsPos(rootCell);
- lnk = cell->GetLink(relpos.x, relpos.y);
- }
-
- wxCursor cur;
- if (cell)
- cur = cell->GetMouseCursorAt(m_interface, pos);
- else
- cur = m_interface->GetHTMLCursor(
- wxHtmlWindowInterface::HTMLCursor_Default);
+ relpos = pos - cell->GetAbsPos(rootCell);
+ lnk = cell->GetLink(relpos.x, relpos.y);
+ }

- m_interface->GetHTMLWindow()->SetCursor(cur);
+ wxCursor cur;
+ if ( cell )
+ {
+ cur = cell->GetMouseCursorAt(m_interface, relpos);
+ }
+ else
+ {
+ cur = m_interface->GetHTMLCursor(
+ wxHtmlWindowInterface::HTMLCursor_Default);
+ }

- if (lnk != m_tmpLastLink)
- {
- if (lnk)
- m_interface->SetHTMLStatusText(lnk->GetHref());
- else
- m_interface->SetHTMLStatusText(wxEmptyString);
+ m_interface->GetHTMLWindow()->SetCursor(cur);

- m_tmpLastLink = lnk;
- }
+ if ( lnk != m_tmpLastLink )
+ {
+ if ( lnk )
+ m_interface->SetHTMLStatusText(lnk->GetHref());
+ else
+ m_interface->SetHTMLStatusText(wxEmptyString);

- m_tmpLastCell = cell;
+ m_tmpLastLink = lnk;
}
- else // mouse moved but stayed in the same cell
+
+ if ( cell == m_tmpLastCell )
{
if ( cell )
- {
- // A single cell can have different cursors for different positions,
- // so update cursor for this case as well.
- wxCursor cur = cell->GetMouseCursorAt(m_interface, pos);
- m_interface->GetHTMLWindow()->SetCursor(cur);
-
- OnCellMouseHover(cell, pos.x, pos.y);
- }
+ OnCellMouseHover(cell, relpos.x, relpos.y);
+ }
+ else
+ {
+ m_tmpLastCell = cell;
}

m_tmpMouseMoved = false;
@@ -1568,13 +1565,7 @@ void wxHtmlWindow::OnInternalIdle()

// handle cursor and status bar text changes:

- // NB: because we're passing in 'cell' and not 'm_Cell' (so that the
- // leaf cell lookup isn't done twice), we need to adjust the
- // position for the new root:
- wxPoint posInCell(x, y);
- if (cell)
- posInCell -= cell->GetAbsPos();
- wxHtmlWindowMouseHelper::HandleIdle(cell, posInCell);
+ wxHtmlWindowMouseHelper::HandleIdle(m_Cell, wxPoint(x, y));
}
}



=====================================
src/html/m_layout.cpp
=====================================
@@ -90,7 +90,31 @@ wxHtmlPageBreakCell::AdjustPagebreak(int* pagebreak, int pageHeight) const
return false;
}

+class wxHtmlLineBreakCell : public wxHtmlCell
+{
+public:
+ wxHtmlLineBreakCell(const wxHtmlTag& tag, int height) : wxHtmlCell(tag)
+ { m_Height = height; }
+
+ void Draw(wxDC& WXUNUSED(dc),
+ int WXUNUSED(x), int WXUNUSED(y),
+ int WXUNUSED(view_y1), int WXUNUSED(view_y2),
+ wxHtmlRenderingInfo& WXUNUSED(info)) override {}

+private:
+ wxDECLARE_NO_COPY_CLASS(wxHtmlLineBreakCell);
+};
+
+static bool HasLayoutContent(wxHtmlContainerCell *c)
+{
+ for ( wxHtmlCell *cell = c->GetFirstChild(); cell; cell = cell->GetNext() )
+ {
+ if ( !cell->IsTerminalCell() || !cell->IsFormattingCell() )
+ return true;
+ }
+
+ return false;
+}

TAG_HANDLER_BEGIN(P, "P")
TAG_HANDLER_CONSTR(P) { }
@@ -119,14 +143,29 @@ TAG_HANDLER_BEGIN(BR, "BR")
TAG_HANDLER_PROC(tag)
{
int al = m_WParser->GetContainer()->GetAlignHor();
- wxHtmlContainerCell *c;
+ wxHtmlContainerCell *c = m_WParser->GetContainer();
+
+ if ( !HasLayoutContent(c) && !c->HasId() )
+ {
+ c->CopyId(tag);
+ c->SetAlignHor(al);
+ c->SetAlign(tag);
+ c->InsertCell(
+ new wxHtmlLineBreakCell(tag, m_WParser->GetCharHeight()));
+
+ m_WParser->CloseContainer();
+ c = m_WParser->OpenContainer();
+ }
+ else
+ {
+ m_WParser->CloseContainer();
+ c = m_WParser->OpenContainer();
+ c->CopyId(tag);
+ c->SetMinHeight(m_WParser->GetCharHeight());
+ }

- m_WParser->CloseContainer();
- c = m_WParser->OpenContainer();
- c->CopyId(tag);
c->SetAlignHor(al);
c->SetAlign(tag);
- c->SetMinHeight(m_WParser->GetCharHeight());
return false;
}



=====================================
src/richtext/richtextbuffer.cpp
=====================================
@@ -8950,68 +8950,80 @@ bool wxRichTextBuffer::PasteFromClipboard(long position)
if (wxTheClipboard->IsSupported(wxDataFormat(wxRichTextBufferDataObject::GetRichTextBufferFormatId())))
{
wxRichTextBufferDataObject data;
- wxTheClipboard->GetData(data);
- wxRichTextBuffer* richTextBuffer = data.GetRichTextBuffer();
- if (richTextBuffer)
+ if (wxTheClipboard->GetData(data))
{
- container->InsertParagraphsWithUndo(this, position+1, *richTextBuffer, GetRichTextCtrl(), 0);
- if (GetRichTextCtrl())
- GetRichTextCtrl()->ShowPosition(position + richTextBuffer->GetOwnRange().GetEnd());
- if (richTextBuffer->GetStyleSheet())
+ wxRichTextBuffer* richTextBuffer = data.GetRichTextBuffer();
+ if (richTextBuffer)
{
- delete richTextBuffer->GetStyleSheet();
- richTextBuffer->SetStyleSheet(nullptr);
+ container->InsertParagraphsWithUndo(this, position+1, *richTextBuffer, GetRichTextCtrl(), 0);
+ if (GetRichTextCtrl())
+ GetRichTextCtrl()->ShowPosition(position + richTextBuffer->GetOwnRange().GetEnd());
+ if (richTextBuffer->GetStyleSheet())
+ {
+ delete richTextBuffer->GetStyleSheet();
+ richTextBuffer->SetStyleSheet(nullptr);
+ }
+ delete richTextBuffer;
+
+ success = true;
}
- delete richTextBuffer;
}
}
- else if (wxTheClipboard->IsSupported(wxDF_TEXT)
+
+ // Fall back if advertised rich text couldn't be read.
+ if (!success && (wxTheClipboard->IsSupported(wxDF_TEXT)
|| wxTheClipboard->IsSupported(wxDF_UNICODETEXT)
)
+ )
{
wxTextDataObject data;
- wxTheClipboard->GetData(data);
- wxString text(data.GetText());
-#ifdef __WXMSW__
- wxString text2;
- text2.Alloc(text.length()+1);
- for ( wxUniChar ch : text )
+ if (wxTheClipboard->GetData(data))
{
- if (ch != wxT('\r'))
- text2 += ch;
- }
+ wxString text(data.GetText());
+#ifdef __WXMSW__
+ wxString text2;
+ text2.Alloc(text.length()+1);
+ for ( wxUniChar ch : text )
+ {
+ if (ch != wxT('\r'))
+ text2 += ch;
+ }
#else
- wxString text2 = text;
+ wxString text2 = text;
#endif
- container->InsertTextWithUndo(this, position+1, text2, GetRichTextCtrl(), wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE);
+ container->InsertTextWithUndo(this, position+1, text2, GetRichTextCtrl(), wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE);

- if (GetRichTextCtrl())
- GetRichTextCtrl()->ShowPosition(position + text2.length());
+ if (GetRichTextCtrl())
+ GetRichTextCtrl()->ShowPosition(position + text2.length());

- success = true;
+ success = true;
+ }
}
- else if (wxTheClipboard->IsSupported(wxDF_BITMAP))
+
+ if (!success && wxTheClipboard->IsSupported(wxDF_BITMAP))
{
wxBitmapDataObject data;
- wxTheClipboard->GetData(data);
- wxBitmap bitmap(data.GetBitmap());
- wxImage image(bitmap.ConvertToImage());
+ if (wxTheClipboard->GetData(data))
+ {
+ wxBitmap bitmap(data.GetBitmap());
+ wxImage image(bitmap.ConvertToImage());

- wxRichTextAction* action = new wxRichTextAction(nullptr, _("Insert Image"), wxRICHTEXT_INSERT, this, container, GetRichTextCtrl(), false);
+ wxRichTextAction* action = new wxRichTextAction(nullptr, _("Insert Image"), wxRICHTEXT_INSERT, this, container, GetRichTextCtrl(), false);

- action->GetNewParagraphs().AddImage(image);
+ action->GetNewParagraphs().AddImage(image);

- if (action->GetNewParagraphs().GetChildCount() == 1)
- action->GetNewParagraphs().SetPartialParagraph(true);
+ if (action->GetNewParagraphs().GetChildCount() == 1)
+ action->GetNewParagraphs().SetPartialParagraph(true);

- action->SetPosition(position+1);
+ action->SetPosition(position+1);

- // Set the range we'll need to delete in Undo
- action->SetRange(wxRichTextRange(position+1, position+1));
+ // Set the range we'll need to delete in Undo
+ action->SetRange(wxRichTextRange(position+1, position+1));

- SubmitAction(action);
+ SubmitAction(action);

- success = true;
+ success = true;
+ }
}
wxTheClipboard->Close();
}


=====================================
src/richtext/richtextctrl.cpp
=====================================
@@ -3489,11 +3489,13 @@ void wxRichTextCtrl::Cut()
if (CanCut())
{
wxRichTextRange range = GetInternalSelectionRange();
- GetBuffer().CopyToClipboard(range);
-
- DeleteSelectedContent();
- LayoutContent();
- Refresh(false);
+ // Keep the selection if it couldn't be put on the clipboard.
+ if ( GetBuffer().CopyToClipboard(range) )
+ {
+ DeleteSelectedContent();
+ LayoutContent();
+ Refresh(false);
+ }
}
}



=====================================
src/xrc/xmlres.cpp
=====================================
@@ -21,6 +21,7 @@
#include "wx/panel.h"
#include "wx/frame.h"
#include "wx/dialog.h"
+ #include "wx/sizer.h"
#include "wx/settings.h"
#include "wx/bitmap.h"
#include "wx/image.h"
@@ -616,6 +617,29 @@ wxXmlResource::DoLoadObject(wxObject *instance,
}


+namespace
+{
+
+void UpdateSizeHintsForAttachedUnknownControl(wxWindow *container,
+ wxWindow *control)
+{
+ if ( auto* const window = wxGetTopLevelParent(container) )
+ {
+ wxSizer * const sizer = window->GetSizer();
+ if ( sizer )
+ {
+ sizer->SetSizeHints(window);
+ // SetSizeHints() can resize the TLW without immediately laying out
+ // its children, as happens in wxQt, so force the attached control
+ // to take the expanded placeholder size now.
+ window->Layout();
+ control->SetSize(wxRect(container->GetClientSize()));
+ }
+ }
+}
+
+} // anonymous namespace
+
bool wxXmlResource::AttachUnknownControl(const wxString& name,
wxWindow *control, wxWindow *parent)
{
@@ -627,7 +651,12 @@ bool wxXmlResource::AttachUnknownControl(const wxString& name,
wxLogError("Cannot find container for unknown control '%s'.", name);
return false;
}
- return control->Reparent(container);
+
+ const bool attached = control->Reparent(container);
+ if ( attached )
+ UpdateSizeHintsForAttachedUnknownControl(container, control);
+
+ return attached;
}

// Small helper returning true if any of the tokens in the given string


=====================================
tests/controls/richtextctrltest.cpp
=====================================
@@ -17,9 +17,16 @@

#include "wx/richtext/richtextctrl.h"
#include "wx/richtext/richtextstyles.h"
+#include "wx/uiaction.h"
+
+#if wxUSE_CLIPBOARD && wxUSE_DATAOBJ && !defined(__WXOSX__)
+ #include "wx/clipbrd.h"
+ #include "wx/dataobj.h"
+#endif // wxUSE_CLIPBOARD && wxUSE_DATAOBJ && !defined(__WXOSX__)
+
#include "testableframe.h"
#include "asserthelper.h"
-#include "wx/uiaction.h"
+#include "waitfor.h"

class RichTextCtrlTestCase : public CppUnit::TestCase
{
@@ -103,6 +110,37 @@ CPPUNIT_TEST_SUITE_REGISTRATION( RichTextCtrlTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( RichTextCtrlTestCase, "RichTextCtrlTestCase" );

+#if wxUSE_CLIPBOARD && wxUSE_DATAOBJ && !defined(__WXOSX__)
+
+namespace
+{
+
+bool SetClipboardText(const wxString &text)
+{
+ wxClipboardLocker lock;
+
+ if ( !lock )
+ return false;
+
+ wxTheClipboard->Clear();
+ return wxTheClipboard->SetData(new wxTextDataObject(text));
+}
+
+bool ClipboardContainsText(const wxString &text)
+{
+ wxClipboardLocker lock;
+
+ if ( !lock )
+ return false;
+
+ wxTextDataObject data;
+ return wxTheClipboard->GetData(data) && data.GetText() == text;
+}
+
+} // anonymous namespace
+
+#endif // wxUSE_CLIPBOARD && wxUSE_DATAOBJ && !defined(__WXOSX__)
+
void RichTextCtrlTestCase::setUp()
{
m_rich = new wxRichTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
@@ -258,33 +296,62 @@ void RichTextCtrlTestCase::TextEvent()

void RichTextCtrlTestCase::CutCopyPaste()
{
-#ifndef __WXOSX__
- m_rich->AppendText("sometext");
+#if wxUSE_CLIPBOARD && wxUSE_DATAOBJ && !defined(__WXOSX__)
+ const wxString text("sometext");
+ const wxString sentinel("not sometext");
+
+ auto waitForPaste = [&]()
+ {
+ return WaitFor("wxRichTextCtrl paste clipboard update",
+ [&]()
+ {
+ if ( m_rich->GetValue() == text )
+ return true;
+
+ m_rich->Paste();
+ return m_rich->GetValue() == text;
+ });
+ };
+
+ m_rich->AppendText(text);
m_rich->SelectAll();

- if(m_rich->CanCut() && m_rich->CanPaste())
+ REQUIRE(WaitFor("wxRichTextCtrl clipboard setup",
+ [&]() { return SetClipboardText(sentinel); }));
+
+ if ( m_rich->CanCut() )
{
- m_rich->Cut();
+ REQUIRE(WaitFor("wxRichTextCtrl cut clipboard update",
+ [&]()
+ {
+ m_rich->Cut();
+ return m_rich->IsEmpty() &&
+ ClipboardContainsText(text);
+ }));
CPPUNIT_ASSERT(m_rich->IsEmpty());

- wxYield();
-
- m_rich->Paste();
- CPPUNIT_ASSERT_EQUAL("sometext", m_rich->GetValue());
+ REQUIRE(waitForPaste());
+ CPPUNIT_ASSERT_EQUAL(text, m_rich->GetValue());
}

m_rich->SelectAll();

- if(m_rich->CanCopy() && m_rich->CanPaste())
+ REQUIRE(WaitFor("wxRichTextCtrl clipboard setup",
+ [&]() { return SetClipboardText(sentinel); }));
+
+ if ( m_rich->CanCopy() )
{
- m_rich->Copy();
+ REQUIRE(WaitFor("wxRichTextCtrl copy clipboard update",
+ [&]()
+ {
+ m_rich->Copy();
+ return ClipboardContainsText(text);
+ }));
m_rich->Clear();
CPPUNIT_ASSERT(m_rich->IsEmpty());

- wxYield();
-
- m_rich->Paste();
- CPPUNIT_ASSERT_EQUAL("sometext", m_rich->GetValue());
+ REQUIRE(waitForPaste());
+ CPPUNIT_ASSERT_EQUAL(text, m_rich->GetValue());
}
#endif
}


=====================================
tests/html/htmlparser.cpp
=====================================
@@ -190,6 +190,15 @@ TEST_CASE("wxHtmlParser::NBSPLineBreak", "[html][parser]")
CHECK(cells[1]->GetAbsPos().y == cells[2]->GetAbsPos().y);
}

+TEST_CASE("wxHtmlEntitiesParser::StrokedD", "[html][parser][entity]")
+{
+ wxHtmlEntitiesParser p;
+ wxString expected;
+ expected << wxUniChar(0x0110) << wxUniChar(0x0111);
+
+ CHECK( p.Parse("&Dstrok;&dstrok;") == expected );
+}
+
TEST_CASE("wxHtmlCell::Detach", "[html][cell]")
{
wxMemoryDC dc;


=====================================
tests/html/htmlwindow.cpp
=====================================
@@ -17,8 +17,11 @@

#ifndef WX_PRECOMP
#include "wx/app.h"
+ #include "wx/timer.h"
#endif // WX_PRECOMP

+#include "wx/html/helpctrl.h"
+#include "wx/html/helpdlg.h"
#include "wx/html/htmlwin.h"
#include "wx/uiaction.h"
#include "testableframe.h"
@@ -39,17 +42,27 @@ private:
CPPUNIT_TEST_SUITE( HtmlWindowTestCase );
CPPUNIT_TEST( SelectionToText );
CPPUNIT_TEST( Title );
+ CPPUNIT_TEST( InitialLineBreak );
#if wxUSE_UIACTIONSIMULATOR
WXUISIM_TEST( CellClick );
WXUISIM_TEST( LinkClick );
#endif // wxUSE_UIACTIONSIMULATOR
+#if wxUSE_WXHTML_HELP
+ CPPUNIT_TEST( DisplayMissingHelpTopic );
+#endif // wxUSE_WXHTML_HELP
+ CPPUNIT_TEST( ImageMapCoordinates );
CPPUNIT_TEST( AppendToPage );
CPPUNIT_TEST_SUITE_END();

void SelectionToText();
void Title();
+ void InitialLineBreak();
void CellClick();
void LinkClick();
+#if wxUSE_WXHTML_HELP
+ void DisplayMissingHelpTopic();
+#endif // wxUSE_WXHTML_HELP
+ void ImageMapCoordinates();
void AppendToPage();

wxHtmlWindow *m_win;
@@ -99,6 +112,74 @@ static const char *TEST_MARKUP_LINK =
static const char *TEST_PLAIN_TEXT =
"Title\nA longer line\nand the last line.";

+static const char *TEST_MARKUP_IMAGEMAP =
+ "<html><body>"
+ "Text<br>"
+ "<img src=\"missing.png\" width=\"100\" height=\"100\" usemap=\"#map\">"
+ "<map name=\"map\">"
+ "<area shape=\"rect\" coords=\"10,10,20,20\" href=\"hit\">"
+ "</map>"
+ "</body></html>";
+
+#if wxUSE_WXHTML_HELP
+
+class CloseModalHelpDialogTimer : public wxTimer
+{
+public:
+ CloseModalHelpDialogTimer(wxHtmlHelpController& controller)
+ : m_controller(controller),
+ m_modalShown(false)
+ {
+ }
+
+ bool WasModalShown() const { return m_modalShown; }
+
+private:
+ virtual void Notify() override
+ {
+ wxHtmlHelpDialog *dialog = m_controller.GetDialog();
+ if ( dialog && dialog->IsModal() )
+ {
+ m_modalShown = true;
+ dialog->EndModal(wxID_CANCEL);
+ }
+ }
+
+ wxHtmlHelpController& m_controller;
+ bool m_modalShown;
+};
+
+#endif // wxUSE_WXHTML_HELP
+
+static wxHtmlCell *FindCellWithLink(wxHtmlCell *cell, wxPoint *pos)
+{
+ if ( !cell->GetFirstChild() )
+ {
+ for ( int y = 0; y < cell->GetHeight(); y++ )
+ {
+ for ( int x = 0; x < cell->GetWidth(); x++ )
+ {
+ if ( cell->GetLink(x, y) )
+ {
+ *pos = wxPoint(x, y);
+ return cell;
+ }
+ }
+ }
+ }
+
+ for ( wxHtmlCell *child = cell->GetFirstChild();
+ child;
+ child = child->GetNext() )
+ {
+ wxHtmlCell *found = FindCellWithLink(child, pos);
+ if ( found )
+ return found;
+ }
+
+ return nullptr;
+}
+
void HtmlWindowTestCase::SelectionToText()
{
#if wxUSE_CLIPBOARD
@@ -116,6 +197,25 @@ void HtmlWindowTestCase::Title()
CPPUNIT_ASSERT_EQUAL("Page", m_win->GetOpenedPageTitle());
}

+void HtmlWindowTestCase::InitialLineBreak()
+{
+ m_win->SetBorders(0);
+ m_win->SetPage("<html><body>TEXT</body></html>");
+
+ wxHtmlContainerCell *plainTextRoot = m_win->GetInternalRepresentation();
+
+ CPPUNIT_ASSERT(plainTextRoot);
+
+ int plainTextHeight = plainTextRoot->GetHeight();
+
+ m_win->SetPage("<html><body><br>TEXT</body></html>");
+
+ wxHtmlContainerCell *rootWithBreak = m_win->GetInternalRepresentation();
+
+ CPPUNIT_ASSERT(rootWithBreak);
+ CPPUNIT_ASSERT(rootWithBreak->GetHeight() > plainTextHeight);
+}
+
#if wxUSE_UIACTIONSIMULATOR
void HtmlWindowTestCase::CellClick()
{
@@ -156,6 +256,45 @@ void HtmlWindowTestCase::LinkClick()
}
#endif // wxUSE_UIACTIONSIMULATOR

+#if wxUSE_WXHTML_HELP
+void HtmlWindowTestCase::DisplayMissingHelpTopic()
+{
+ wxHtmlHelpController controller(
+ wxHF_DEFAULT_STYLE | wxHF_DIALOG | wxHF_MODAL,
+ wxTheApp->GetTopWindow());
+ CloseModalHelpDialogTimer timer(controller);
+
+ timer.StartOnce(50);
+
+ CPPUNIT_ASSERT(!controller.Display("missing topic"));
+
+ timer.Stop();
+
+ CPPUNIT_ASSERT(!timer.WasModalShown());
+ controller.Quit();
+}
+#endif // wxUSE_WXHTML_HELP
+
+void HtmlWindowTestCase::ImageMapCoordinates()
+{
+ m_win->SetBorders(0);
+ m_win->SetPage(TEST_MARKUP_IMAGEMAP);
+
+ wxHtmlContainerCell *root = m_win->GetInternalRepresentation();
+ wxPoint hitpos;
+ wxHtmlCell *image = FindCellWithLink(root, &hitpos);
+
+ CPPUNIT_ASSERT(image);
+
+ const wxPoint imgpos = image->GetAbsPos(root);
+ wxHtmlLinkInfo *link = root->GetLink(imgpos.x + hitpos.x,
+ imgpos.y + hitpos.y);
+
+ CPPUNIT_ASSERT(link);
+ CPPUNIT_ASSERT_EQUAL("hit", link->GetHref());
+ CPPUNIT_ASSERT(!root->GetLink(imgpos.x, imgpos.y));
+}
+
void HtmlWindowTestCase::AppendToPage()
{
#if wxUSE_CLIPBOARD


=====================================
tests/xml/xrctest.cpp
=====================================
@@ -135,6 +135,19 @@ void LoadTestXrc()
LoadXrcFrom(wxString::FromAscii(xrcText));
}

+class XrcSizeHintPanel : public wxPanel
+{
+public:
+ explicit XrcSizeHintPanel(wxWindow *parent)
+ : wxPanel(parent, wxID_ANY)
+ {
+ wxBoxSizer * const sizer = new wxBoxSizer(wxVERTICAL);
+ sizer->Add(220, 120);
+ SetSizer(sizer);
+ sizer->SetSizeHints(this);
+ }
+};
+
} // anon namespace


@@ -212,6 +225,42 @@ TEST_CASE_METHOD(XrcTestCase, "XRC::IDRanges", "[xrc]")
}
}

+TEST_CASE("XRC::UnknownControlSizeHints", "[xrc]")
+{
+ wxXmlResource::Get()->InitAllHandlers();
+
+ LoadXrcFrom(R"(<?xml version="1.0" ?>
+<resource>
+ <object class="wxDialog" name="unknown_dialog">
+ <title>unknown</title>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="unknown" name="unknown_panel">
+ <size>100,100</size>
+ </object>
+ </object>
+ </object>
+ </object>
+</resource>
+ )");
+
+ wxDialog dlg;
+ REQUIRE( wxXmlResource::Get()->LoadDialog(&dlg, nullptr, "unknown_dialog") );
+
+ const wxSize sizeBefore = dlg.GetClientSize();
+ XrcSizeHintPanel * const panel = new XrcSizeHintPanel(&dlg);
+ const wxSize panelMin = panel->GetMinSize();
+
+ REQUIRE( panelMin.x > sizeBefore.x );
+ REQUIRE( wxXmlResource::Get()->AttachUnknownControl("unknown_panel",
+ panel,
+ &dlg) );
+
+ CHECK( dlg.GetClientSize().x >= panelMin.x );
+ CHECK( panel->GetSize().x >= panelMin.x );
+}
+
TEST_CASE("XRC::PathWithFragment", "[xrc][uri]")
{
wxXmlResource::Get()->AddHandler(new wxBitmapXmlHandler);



View it on GitLab: https://gitlab.com/wxwidgets/wxwidgets/-/compare/443c024e07aca3c2ff8ffc8a9e72f52c9b7421f8...0dc27e6a3f979d6848305e1d6bb4f06673304835

--
View it on GitLab: https://gitlab.com/wxwidgets/wxwidgets/-/compare/443c024e07aca3c2ff8ffc8a9e72f52c9b7421f8...0dc27e6a3f979d6848305e1d6bb4f06673304835
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help


Reply all
Reply to author
Forward
0 new messages