From 79a4f8e9458ddf52843d87f339db5b0d67a1e8e4 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Sun, 1 Nov 2026 13:54:19 +0000 Subject: [PATCH] Decompile fn_13888 (UITagListBox::sub_9BB8E0) Batch #9454 by secret: 0 byte-identical, 1 confirmed by peer review. - fn_13888 UITagListBox::sub_9BB8E0: logic confirmed by peer review Peer-reviewed-by: ragnarok-clanker, meitogi, sherollyner Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/UI/Lists/UITagListBox.cpp | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/Source/UI/Lists/UITagListBox.cpp b/Source/UI/Lists/UITagListBox.cpp index 7a10d7c8..1079e39b 100644 --- a/Source/UI/Lists/UITagListBox.cpp +++ b/Source/UI/Lists/UITagListBox.cpp @@ -1,5 +1,6 @@ #include "UI/Lists/UITagListBox.h" +#include "Client/Input/InputCharset.h" #include "Contents/Items/ItemDescription.h" #include "Contents/Items/ItemInfo.h" #include "Contents/NavigationManager.h" @@ -600,7 +601,63 @@ std::string UITagListBox::sub_9B8AA0(std::string text, std::vector& return result; } +namespace { +// INLINED +int WrappedLineLength(const char* text, int length, int width) { + if (text == nullptr) { + return -1; + } + + using NextCharacter = const char*(__thiscall*)(InputCharset*, const char*, int); + const char* end = text + length; + const char* current = text; + const char* limit = text + width; + while (current < limit && current < end) { + if (*current == '\n') { + return static_cast(current - text) + 1; + } + + if (IsHexColorToken(current, end)) { + current += 7; + limit += 7; + } else if (IsPipeColorToken(current)) { + current += 3; + limit += 3; + } else { + current = (*reinterpret_cast(g_serverLanguage))[5](g_serverLanguage, current, static_cast(limit - current)); + } + } + + return static_cast(current - text); +} +} + // OFFSET: 0x009BB8E0 +// FUNCTION: fn_13888 +void UITagListBox::sub_9BB8E0(std::string text, std::vector& tags, int width) { + const int firstLine = static_cast(this->lines.size()); + const char* buffer = text.c_str(); + std::size_t position = 0; + while (position < text.size()) { + const char* start = buffer + position; + int next = WrappedLineLength(start, static_cast(text.size() - position), width) + static_cast(position); + for (std::size_t index = 0; index < tags.size(); ++index) { + if (next > tags[index].unknown_0008 && next < tags[index].unknown_000C) { + next = tags[index].unknown_0008; + break; + } + } + + const std::string line(start, buffer + next); + this->AddLine(line.c_str()); + position = next; + } + + for (std::vector::iterator tag = tags.begin(); tag != tags.end(); ++tag) { + this->AddTagButton(*tag, static_cast(this->lines.size()) - firstLine); + } + this->SendMsg(nullptr, 7, 0, 0, 0, 0); +} // OFFSET: 0x009B7A20 // FUNCTION: fn_13870