From 2f72e3aada0795dd9bc431801277bb6b82e2e7b2 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Fri, 30 Oct 2026 13:23:42 +0000 Subject: [PATCH] Decompile 2 functions in Source/UI/Window/UIWindow.cpp, Source/UI/Window/UIWindow.h, ... Batch #5472 by Yommy: 0 byte-identical, 2 confirmed by peer review. - fn_16977 UIWindow::FitDisplayText: logic confirmed by peer review - fn_16978 UIWindow::FitVerticalDisplayText: logic confirmed by peer review Peer-reviewed-by: ragnarok-clanker, willerthal Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/UI/Text/UITextViewer.h | 2 + Source/UI/Window/UIWindow.cpp | 117 ++++++++++++++++++++++++++++++++++ Source/UI/Window/UIWindow.h | 6 ++ 3 files changed, 125 insertions(+) diff --git a/Source/UI/Text/UITextViewer.h b/Source/UI/Text/UITextViewer.h index 7514ccd9..5e0e12e4 100644 --- a/Source/UI/Text/UITextViewer.h +++ b/Source/UI/Text/UITextViewer.h @@ -34,6 +34,8 @@ struct UITextViewerContext { }; class UITextViewer : public UIListBox { + friend class UIWindow; + public: UITextViewer(UIWindowContext& windows, UITextViewerContext& text); ~UITextViewer() override; diff --git a/Source/UI/Window/UIWindow.cpp b/Source/UI/Window/UIWindow.cpp index f26e42bf..2877fbc9 100644 --- a/Source/UI/Window/UIWindow.cpp +++ b/Source/UI/Window/UIWindow.cpp @@ -26,6 +26,9 @@ #include "UI/Lists/UIScrollBar.h" #include "UI/Lists/UIScrollBarNavi.h" #include "UI/Text/ColoredText.h" +#include "UI/Text/NavigationLink.h" +#include "UI/Text/TextMarkup.h" +#include "UI/Text/UITextViewer.h" #include "UI/UIStaticBitmap.h" #include "UI/Navigation/UINavigationV4Wnd.h" #include "UI/Navigation/UIPrivateAirplaneWnd.h" @@ -35,8 +38,10 @@ #include "UI/Window/WindowManagerWindows.h" #include "UI/Window/WindowPolicy.h" #include "UI/Window/WindowRegistration.h" +#include "Utility/Text/StringUtil.h" #include +#include #include #include #include @@ -1340,6 +1345,118 @@ int UIWindow::FormattedTextWidth(std::string text, int family, int height, unsig return total; } +// OFFSET: 0x00A80880 +// FUNCTION: fn_16977 +std::string UIWindow::FitDisplayText(int width, const char* text, int family, int height, unsigned char bold) { + std::string display = DisplayTextTag(std::string(text), "", ""); + display = DisplayTextTag(std::move(display), "", ""); + display = DisplayTextTag(std::move(display), "", ""); + display = DisplayTextTag(std::move(display), "", ""); + display = RemoveTextLinkInfo(std::move(display)); + + if (this->m_context->chatConverter) { + display = this->m_context->chatConverter->ConvertChat(std::move(display)); + } + + std::string navigation; + DisplayNavigationLink(navigation, display); + display = std::move(navigation); + display = DisplayTextTag(std::move(display), "", ""); + + const auto textWidth = [this, family, height, bold](const char* value) { + if (!value) { + return 0; + } + + const unsigned bytes = static_cast(std::strlen(value)); + if (!bytes) { + return 0; + } + + TextContext context(*this->geometry.surface); + context.SetFont(family, height, bold, 0); + return static_cast(context.Measure(value, bytes).cx); + }; + + const int extent = textWidth(display.c_str()); + { + TextContext context(*this->geometry.surface); + context.SetFont(family, height, bold, 0); + context.Measure("...", 3); + } + + if (extent <= width) { + return display; + } + + std::string fitted(display); + ATL::CA2WEX<128> wide(display.c_str(), CP_THREAD_ACP); + std::wstring remaining(wide); + + while (remaining.size() > 1) { + std::size_t length = remaining.size() - 1; + + if ((remaining[remaining.size() - 2] & 0x80) != 0 && (remaining[remaining.size() - 1] & 0x80) != 0) { + --length; + } + + remaining.resize(length); + + ATL::CW2AEX<128> converted(remaining.c_str(), CP_THREAD_ACP); + fitted = std::string(converted) + "..."; + + if (textWidth(fitted.c_str()) <= width) { + return fitted; + } + } + + ATL::CW2AEX<128> converted(remaining.c_str(), CP_THREAD_ACP); + fitted = std::string(converted) + "..."; + return fitted; +} + +// OFFSET: 0x00A81400 +// FUNCTION: fn_16978 +std::string UIWindow::FitVerticalDisplayText(int height, const char* text, int family, int fontHeight, unsigned char bold) { + std::string display = DisplayTextTag(std::string(text), "", ""); + display = DisplayTextTag(std::move(display), "", ""); + display = DisplayTextTag(std::move(display), "", ""); + display = DisplayTextTag(std::move(display), "", ""); + display = RemoveTextLinkInfo(std::move(display)); + + if (this->m_context->chatConverter) { + display = this->m_context->chatConverter->ConvertChat(std::move(display)); + } + + std::string navigation; + DisplayNavigationLink(navigation, display); + display = std::move(navigation); + display = DisplayTextTag(std::move(display), "", ""); + + if (this->VerticalTextHeight(this->m_context->fonts, this->m_context->locale, display.c_str(), display.size(), family, fontHeight, bold) <= height) { + return display; + } + + const char* begin = display.c_str(); + std::size_t length = display.size(); + std::string fitted(display); + int extent; + + do { + fitted.resize(length); + fitted += "."; + + if (CountCharacters(static_cast(g_textCodePage), begin, begin + length) <= 1) { + break; + } + + extent = this->VerticalTextHeight(this->m_context->fonts, this->m_context->locale, fitted.c_str(), fitted.size(), family, fontHeight, bold); + length = CharPrevExA(static_cast(g_textCodePage), begin, begin + length, 0) - begin; + } while (height < extent); + + return fitted; +} + // OFFSET: 0x00A7E120 // FUNCTION: fn_16959 std::list UIWindow::WrapFormattedText(std::string text, std::list* lines, int maxWidth, int family, int height, unsigned char bold) { diff --git a/Source/UI/Window/UIWindow.h b/Source/UI/Window/UIWindow.h index 3dc43491..6eafd3c0 100644 --- a/Source/UI/Window/UIWindow.h +++ b/Source/UI/Window/UIWindow.h @@ -31,6 +31,7 @@ struct SpriteFrameCell; class CBitmapRes; class CActRes; class TextureCache; +class UITextViewer; struct WindowReplayRecorder; struct UIWindowContext { @@ -43,6 +44,9 @@ struct UIWindowContext { WindowRegistration& registration; UIWindowMgr& windowMgr; std::unordered_set& deferredDeletion; + UITextViewer* const& chatConverter; + FontCache& fonts; + const TextLocale& locale; void DestroyDeferredChildren(); }; @@ -175,6 +179,8 @@ public: FontCache& fonts, const TextLocale& locale, const char* text, unsigned bytes, int family, int height, unsigned char bold, unsigned char italic ); int FormattedTextWidth(std::string text, int family, int height, unsigned char bold); + std::string FitDisplayText(int width, const char* text, int family, int height, unsigned char bold); + std::string FitVerticalDisplayText(int height, const char* text, int family, int fontHeight, unsigned char bold); std::list WrapFormattedText(std::string text, std::list* lines, int maxWidth, int family, int height, unsigned char bold); int RecordEditTexts(WindowReplayRecorder& recorder); int RestoreEditTexts(const unsigned char* data);