rodecomp/Source/UI/Text/TextMarkup.cpp
ragnarok-clanker e844522fe1 Maintenance: [forced, user-approved] Remove fabricated UIListBoxContext and NavigationDestination (family B; follow-up to #10188). Ev
Batch #10189 by ragnarok-clanker: forced by an admin (15 lower score(s), 71 changed function(s)); checked with 118 compiled unit(s), including every includer of Source/UI/Buttons/UINaviLinkButton.h, Source/UI/Chat/UISubChatHisWnd.h, Source/UI/Dialogs/UIChooseWarpWnd.h, Source/UI/Dialogs/UIChooseWnd.h, Source/UI/Edit/UIEditCtrl.h, Source/UI/EntryQueue/UIEntryQueueWnd.h, Source/UI/Guild/UIAgitWnd.h, Source/UI/Guild/UIGuildWnd.h, Source/UI/Items/UIItemRepairWnd.h, Source/UI/Items/UIMakeTargetListWnd.h, Source/UI/Items/UIWeaponRefineWnd.h, Source/UI/Lists/UIChatHisBox.h, Source/UI/Lists/UIComboBox.h, Source/UI/Lists/UIComboBoxEx.h, Source/UI/Lists/UIListBox.h, Source/UI/Lists/UIListBoxEx.h, Source/UI/Lists/UIListBoxNavi.h, Source/UI/Lists/UIListBoxNaviSearch.h, Source/UI/Lists/UIMemberListBox.h, Source/UI/Lists/UIPackageBoxNameList.h, Source/UI/Lists/UIReplayListBox.h, Source/UI/Navigation/UINavigationV4Wnd.h, Source/UI/Text/TextMarkup.h, Source/UI/Text/UITextViewer.h, Source/UI/UIRoundBoxTooltipWnd.h, Source/UI/Window/UIChatRoomWnd.h, Source/UI/Window/UINavigationWnd.h, Source/UI/Window/UISecondCostumeWnd.h, Source/UI/Window/UISelectReplayDataWnd.h, Source/UI/Window/UIShowWarpWnd.h.
2026-11-02 20:18:32 +00:00

272 lines
6.7 KiB
C++

#include "UI/Text/ColoredText.h"
#include "UI/Text/TextMarkup.h"
#include <windows.h>
#include <utility>
namespace {
// INLINED
bool Hex(unsigned char value) {
return (value >= '0' && value <= '9') || (value >= 'a' && value <= 'f') || (value >= 'A' && value <= 'F');
}
// INLINED
}
// GLOBAL: gl_24593
static const std::string g_naviTagBegin = "<NAVI>";
// GLOBAL: gl_24594
static const std::string g_naviTagEnd = "</NAVI>";
// GLOBAL: gl_24595
static const std::string g_itemTagBegin = "<ITEM>";
// GLOBAL: gl_24596
static const std::string g_itemTagEnd = "</ITEM>";
// GLOBAL: gl_24599
static const std::string g_questTagBegin = "<QUEST>";
// GLOBAL: gl_24600
static const std::string g_questTagEnd = "</QUEST>";
// OFFSET: 0x00A7CA90
// FUNCTION: fn_16949
void ExtractNavigationTextLinks(std::string&& text, std::vector<TextLink>& links) {
ExtractTextLinks(std::move(text), g_naviTagBegin, g_naviTagEnd, links);
}
// GLOBAL: gl_24597
static const std::string g_tipBoxTagBegin = "<TIPBOX>";
// GLOBAL: gl_24598
static const std::string g_tipBoxTagEnd = "</TIPBOX>";
// OFFSET: 0x00A7D690
// FUNCTION: fn_16951
void ExtractTipBoxTextLinks(std::string&& text, std::vector<TextLink>& links) {
ExtractTextLinks(std::move(text), g_tipBoxTagBegin, g_tipBoxTagEnd, links);
}
// GLOBAL: gl_24591
static const std::string g_urlTagBegin = "<URL>";
// GLOBAL: gl_24592
static const std::string g_urlTagEnd = "</URL>";
// OFFSET: 0x00A7D6B0
// FUNCTION: fn_16952
void ExtractUrlTextLinks(std::string&& text, std::vector<TextLink>& links) {
ExtractTextLinks(std::move(text), g_urlTagBegin, g_urlTagEnd, links);
}
// OFFSET: 0x00A81A70
// FUNCTION: fn_16980
bool HasTextLinks(const std::string& text) {
return text.find("<URL>") != std::string::npos || text.find("<NAVI>") != std::string::npos || text.find("<INFO>") != std::string::npos ||
text.find("<ITEML>") != std::string::npos || text.find("<TIPBOX>") != std::string::npos || text.find("<QUEST>") != std::string::npos;
}
// OFFSET: 0x008791E0
// FUNCTION: fn_11214
std::string ExpandTextEscapes(std::string text) {
auto position = text.find("\\n");
while (position != std::string::npos) {
text.replace(position, 2, "\n");
position = text.find("\\n");
}
position = text.find("\\r");
while (position != std::string::npos) {
text.replace(position, 2, "\r");
position = text.find("\\r");
}
return text;
}
// OFFSET: 0x00A7EDC0
// FUNCTION: fn_16961
std::string RemoveTextColors(const char* text) {
const char* end = text + std::char_traits<char>::length(text);
const char* current = text;
std::string result;
while (current < end) {
const char* next = SegmentEnd(current, end);
result.append(current, next);
if (next >= end) {
break;
}
current = next + 7;
}
return result;
}
// OFFSET: 0x00A7F660
// FUNCTION: fn_16966
std::string DisplayTextTag(std::string text, const std::string& begin, const std::string& end) {
auto position = text.find(begin);
if (position == std::string::npos) {
return text;
}
std::string result;
do {
if (position > 0) {
result.append(text, 0, position);
}
const auto content = position + begin.size();
std::string tail = text.substr(content);
const auto close = tail.find(end);
if (close == std::string::npos) {
position = content;
} else {
result.append(tail, 0, close);
text = tail.substr(close + end.size());
position = text.find(begin);
}
} while (position != std::string::npos);
result += text;
return result;
}
// OFFSET: 0x00A7F510
// FUNCTION: fn_16963
std::string DisplayItemTextTag(const std::string& text) {
return DisplayTextTag(text, g_itemTagBegin, g_itemTagEnd);
}
// OFFSET: 0x00A7F580
// FUNCTION: fn_16964
std::string DisplayNavigationTextTag(const std::string& text) {
return DisplayTextTag(text, g_naviTagBegin, g_naviTagEnd);
}
// OFFSET: 0x00A7F5F0
// FUNCTION: fn_16965
std::string DisplayQuestTextTag(const std::string& text) {
return DisplayTextTag(text, g_questTagBegin, g_questTagEnd);
}
// OFFSET: 0x00A7FE50
// FUNCTION: fn_16967
std::string DisplayTipBoxTextTag(const std::string& text) {
return DisplayTextTag(text, g_tipBoxTagBegin, g_tipBoxTagEnd);
}
// OFFSET: 0x00A7FEC0
// FUNCTION: fn_16968
std::string DisplayUrlTextTag(const std::string& text) {
return DisplayTextTag(text, g_urlTagBegin, g_urlTagEnd);
}
// OFFSET: 0x00A7EF40
// FUNCTION: fn_16962
std::string RemoveTextLinkInfo(std::string text) {
auto position = text.find("<INFO>");
if (position == std::string::npos) {
return text;
}
std::string result;
do {
if (position > 0) {
result.append(text, 0, position);
}
const auto close = text.find("</INFO>");
if (close != std::string::npos) {
text = text.substr(close + 7);
position = text.find("<INFO>");
}
} while (position != std::string::npos);
result += text;
return result;
}
// OFFSET: 0x00A7CAB0
// FUNCTION: fn_16950
void ExtractTextLinks(std::string text, const std::string& begin, const std::string& end, std::vector<TextLink>& links) {
auto position = text.find(begin);
if (position == std::string::npos) {
return;
}
std::string prefix = RemoveTextLinkInfo(text.substr(0, position));
std::uint32_t offset = static_cast<std::uint32_t>(prefix.size());
do {
const auto content = position + begin.size();
std::string tail = text.substr(content);
const auto close = tail.find(end);
if (close == std::string::npos) {
position = content;
continue;
}
std::string display = tail.substr(0, close);
std::string metadata;
const auto info = display.find("<INFO>");
if (info != std::string::npos) {
display = tail.substr(0, info);
metadata = tail.substr(info + 6);
const auto infoEnd = metadata.find("</INFO>");
if (infoEnd != std::string::npos) {
metadata.resize(infoEnd);
}
}
TextLink link;
link.position = offset;
link.display = display;
link.metadata = metadata;
links.push_back(std::move(link));
offset += static_cast<std::uint32_t>(display.size());
text = tail.substr(close + end.size());
position = text.find(begin);
if (position != std::string::npos) {
prefix = RemoveTextLinkInfo(text.substr(0, position));
offset += static_cast<std::uint32_t>(prefix.size());
}
} while (position != std::string::npos);
}
// OFFSET: 0x00877650
// FUNCTION: fn_11210
void SplitTextLinkArguments(std::string text, std::vector<std::string>& arguments) {
if (text.empty()) {
return;
}
auto comma = text.find(',');
while (comma != std::string::npos) {
arguments.push_back(text.substr(0, comma));
text = text.substr(comma + 1);
comma = text.find(',');
}
arguments.push_back(text);
}