Decompile fn_16992 (UIWindow::WrapTextWithBreaks)

Batch #9633 by ragnarok-clanker: 0 byte-identical, 1 confirmed by peer review.

- fn_16992 UIWindow::WrapTextWithBreaks: logic confirmed by peer review

Peer-reviewed-by: alisonrag, Romain, dori
Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes).
This commit is contained in:
ragnarok-clanker 2026-11-01 17:17:22 +00:00
commit 3246e9793d

View file

@ -1682,8 +1682,13 @@ const char* UIWindow::TruncateText(const char* text, int maxBytes) {
}
// OFFSET: 0x00A81FD0
// FUNCTION: fn_16992
void UIWindow::WrapTextWithBreaks(const char* text, std::vector<std::string>* lines, std::vector<bool>* breaks, int width) {
using NextCharacter = const char* (__thiscall*)(InputCharset*, const char*, int);
if (!text) {
return;
}
const int totalWidth = this->TextWidth(this->m_context->fonts, this->m_context->locale, text, 0, 0, 12, 0, 0);
const int length = static_cast<int>(std::strlen(text));
if (totalWidth <= 0) {
@ -2487,295 +2492,6 @@ void UINavigationroadiconWnd::Paint() {
}
// OFFSET: 0x005C7CC0
int UINavigationV4Wnd::SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) {
switch (message) {
case 0:
if (sender == this->unknown_00E0 && static_cast<UIEditCtrl*>(this->unknown_00E0)->Length() > 0) {
this->SendMsg(this->unknown_00E0, 6, 0x141, 0, 0, 0);
}
break;
case 6:
if (argument1 != 0x150 && argument1 != 0x1B9) {
reinterpret_cast<WindowResponseRecorder*>(this)->Record(this->geometry.id, static_cast<int>(argument1), argument2, argument3, argument4);
if (argument1 > 499) {
break;
}
if (argument1 == 499) {
if (!g_windowMgr.LookupWindow(6)) {
UIPrivateAirplaneWnd* window = new UIPrivateAirplaneWnd();
window->SetSize(0xD0, 0x6E);
window->Move(static_cast<int>((g_renderer->viewport.width - 0xD0) * 0.5), static_cast<int>((g_renderer->viewport.height - 0x6E) * 0.5));
g_windowMgr.AddRendered(window);
if (g_navigationManager.GetCurrentTargetType() == 2) {
window->SendMsg(nullptr, 0x9A, reinterpret_cast<std::intptr_t>(LookupMessage(0xD3B)), 0, 0, 0);
}
std::string mapName = static_cast<CGameMode*>(g_modeMgr.GetGameMode())->MapName();
mapName = mapName.substr(0, mapName.find(".rsw")) + ".gat";
if (!g_privateAirplaneItems->IsStartableMap(mapName)) {
window->SendMsg(nullptr, 0x9A, reinterpret_cast<std::intptr_t>(LookupMessage(0xD03)), 0, 0, 0);
window->SendMsg(nullptr, 0x23, 0, 0, 0, 0);
}
std::string targetName = g_navigationManager.GetCurrentTargetName() + ".gat";
if (!g_privateAirplaneItems->IsEndableMap(targetName)) {
window->SendMsg(nullptr, 0x9A, reinterpret_cast<std::intptr_t>(LookupMessage(0xD04)), 0, 0, 0);
window->SendMsg(nullptr, 0x23, 0, 0, 0, 0);
}
if (mapName.compare(targetName) == 0) {
window->SendMsg(nullptr, 0x9A, reinterpret_cast<std::intptr_t>(LookupMessage(0xD19)), 0, 0, 0);
window->SendMsg(nullptr, 0x23, 0, 0, 0, 0);
}
CGameMode* mode = static_cast<CGameMode*>(g_modeMgr.GetGameMode());
if (mode->scene && static_cast<CGameMode*>(g_modeMgr.GetGameMode())->scene->player &&
static_cast<CGameMode*>(g_modeMgr.GetGameMode())->scene->player->render.unknown_0070 == 3) {
window->SendMsg(nullptr, 0x9A, reinterpret_cast<std::intptr_t>(LookupMessage(0xD1A)), 0, 0, 0);
window->SendMsg(nullptr, 0x23, 0, 0, 0, 0);
}
g_windowMgr.window_4F258 = window;
if (reinterpret_cast<WindowDialogs*>(&g_windowMgr)->RunModal(window) == 0xBC) {
g_windowMgr.window_4F258 = nullptr;
}
}
break;
}
}
switch (argument1) {
case 0xBD:
if (!g_windowMgr.CloseWindow(0x132)) {
g_windowMgr.EnsureWindow(0x132);
}
break;
case 0xBF: {
if (g_closeChatAfterGroups != 0) {
g_windowMgr.CloseWindow(0x1A);
}
for (std::string& text : this->unknown_0104) {
text.clear();
}
this->unknown_0104.erase(this->unknown_0104.begin(), this->unknown_0104.end());
const std::string directory = FormatOwnedString("%s\\Navigationdata\\", g_applicationDirectory);
EnumerateFileNames(this->unknown_0104, directory.c_str(), "*.txt");
const int count = static_cast<int>(this->unknown_0104.size());
if (count != 0) {
UIWindow* history = g_windowMgr.EnsureWindow(0x1A);
for (const std::string& name : this->unknown_0104) {
history->SendMsg(nullptr, 0x1F, reinterpret_cast<std::intptr_t>(name.c_str()), 0, 0, 0);
}
const int height = (std::min)(count * 0x10, 0xA0);
history->SendMsg(nullptr, 0x28, 0, 0, 0, 0);
history->Resize(0xA0, height);
history->SendMsg(nullptr, 0x53, 0xCB, 0, 0, 0);
int x = this->geometry.width - 0xA5;
int y = 0x24;
this->ToScreen(x, y);
history->Move(x, y);
}
break;
}
case 0xC8:
g_navigationMinimized = false;
this->geometry.targetAlpha = 0xFF;
this->geometry.alphaStart = timeGetTime();
g_navigationHidden = false;
this->RefreshLayout();
break;
case 0xC9:
if (g_navigationMode == 2) {
if (reinterpret_cast<WindowDialogs*>(&g_windowMgr)->Confirm(LookupMessage(0x8BF), 2, true, false, 0, "Message", 0x118, 0x78, 0) == 0xBB) {
g_navigationManager.SetViewMode(1);
g_navigationTab = 0;
g_navigationManager.ClearSavedTarget();
g_windowMgr.CloseWindow(0x13A);
this->RefreshLayout();
g_worldViewMgr.ClearMarks();
}
} else {
if (g_windowMgr.window_0428) {
this->SendMsg(nullptr, 6, 0xCA, 0, 0, 0);
}
g_navigationTab = 0;
g_navigationMinimized = false;
g_navigationManager.Reset(true);
g_worldViewMgr.ClearMarks();
g_worldViewMgr.ClearLevels();
g_worldViewMgr.ResetSelection();
g_windowMgr.CloseWindow(0x13A);
g_windowMgr.CloseWindow(0xCB);
}
break;
case 0xCA:
g_navigationMinimized = true;
this->geometry.targetAlpha = 0xAA;
this->geometry.alphaStart = timeGetTime();
if (g_windowMgr.window_0428) {
static_cast<UIRoMapWnd*>(g_windowMgr.window_0428)->UpdateNavigationButtons();
}
this->RefreshLayout();
break;
case 0xD5:
g_unknown16FC585 = false;
g_navigationFilter = argument2 != 0;
g_unknown16FC586 = g_navigationFilter;
break;
case 0x11C:
if (!g_navigationManager.GetSavedTarget().object) {
if (g_navigationTab == 2) {
if (g_navigationMode == 2) {
this->LayoutWithoutDetails();
g_navigationTab = 1;
g_navigationManager.SelectTarget(g_navigationManager.GetSelectedNode());
} else {
this->LayoutWithDetails();
g_navigationTab = 0;
g_navigationManager.SelectNodeState();
}
}
break;
}
if (g_navigationTab == 1 || (g_navigationTab == 2 && g_navigationMode != 2)) {
g_navigationTab = 0;
g_navigationManager.SelectNodeState();
this->RefreshLayout();
break;
}
g_navigationTab = 1;
g_navigationManager.SelectTarget(g_navigationManager.GetSelectedNode());
this->RefreshLayout();
break;
case 0x141:
if (static_cast<UIEditCtrl*>(this->unknown_00E0)->Length() != 0 && !g_navigationMinimized) {
g_navigationSearchText = static_cast<UIEditCtrl*>(this->unknown_00E0)->Text();
g_navigationManager.UpdateSearchResults();
this->unknown_00F0->Clear();
this->unknown_00F0->Invalidate();
g_navigationManager.ClearData();
g_navigationManager.LoadTargetPreview();
this->FillRouteGroups();
g_navigationTab = 0;
if (g_windowMgr.window_0428) {
static_cast<UINavigationWnd*>(g_windowMgr.window_0428)->RefreshWorldMapLevels();
}
this->LayoutWithDetails();
reinterpret_cast<CLanguage*>(g_serverLanguage)->ResetInput();
}
break;
case 0x150:
if (g_replayAnimationScaling == 0) {
argument2 = this->unknown_00EC->selected;
}
this->SelectRoute(static_cast<int>(argument2));
if (argument2 != -1) {
g_navigationSelectedNode = 0;
if (!g_navigationManager.SelectNodeState()) {
g_navigationSelectedNode = 0;
g_navigationManager.SelectNodeState();
}
this->unknown_00F0->selected = g_navigationSelectedNode;
this->unknown_00F0->Invalidate();
if (g_windowMgr.window_0428) {
static_cast<UINavigationWnd*>(g_windowMgr.window_0428)->RefreshWorldMapSelection();
}
this->Invalidate();
reinterpret_cast<WindowResponseRecorder*>(this)->Record(this->geometry.id, static_cast<int>(argument1), argument2, argument3, argument4);
}
this->Invalidate();
break;
case 0x157:
if (!g_windowMgr.CloseWindow(0xE5)) {
g_windowMgr.EnsureWindow(0xE5);
}
break;
case 0x162:
if (g_navigationManager.GetCurrentTargetName().size() != 0) {
const int type = g_navigationManager.GetCurrentTarget().type;
if (type < 2) {
this->LayoutWithoutDetails();
g_navigationTab = 2;
this->unknown_0118 = timeGetTime() + 5000;
} else {
const NavigationTarget target = g_navigationManager.GetCurrentTarget();
CNavi_Object* object = static_cast<CNavi_Object*>(target.object);
int x = 1000;
int y = 1000;
if (type == 2) {
NaviCell cell;
x = object->GetCell(&cell)->x;
NaviCell other;
y = object->GetCell(&other)->y;
}
this->InsertNavigationLink(object->GetInfo()->GetName(), x, y);
}
}
break;
case 0x1AE:
this->Invalidate();
if (g_navigationManager.SaveCurrentTarget() == 0) {
const NavigationTarget target = g_navigationManager.GetSavedTarget();
const int result = g_navigationManager.Navigate(target.x, target.y);
if (result >= 0) {
g_navigationTab = 1;
g_navigationManager.SelectTarget(g_navigationManager.GetSelectedNode());
if (g_windowMgr.window_0428) {
static_cast<UINavigationWnd*>(g_windowMgr.window_0428)->RefreshWorldMapMarks();
}
}
g_navigationManager.ShowRouteResult(result, 1, *reinterpret_cast<WindowDialogs*>(&g_windowMgr));
} else {
g_navigationManager.ShowRouteResult(0, 1, *reinterpret_cast<WindowDialogs*>(&g_windowMgr));
}
this->RefreshLayout();
if (UIWindow* window = g_windowMgr.LookupWindow(0x13A)) {
window->SendMsg(nullptr, 0x3C, 0, 0, 0, 0);
}
break;
case 0x1B9:
if (g_replayAnimationScaling == 0) {
argument2 = this->unknown_00F0->selected;
}
if (argument2 != -1) {
this->SelectRouteNode(static_cast<int>(argument2));
reinterpret_cast<WindowResponseRecorder*>(this)->Record(this->geometry.id, static_cast<int>(argument1), argument2, argument3, argument4);
}
this->Invalidate();
break;
case 0x1BA:
if (!g_windowMgr.CloseWindow(0x13A) && g_navigationManager.NodeCount() != 0) {
g_windowMgr.EnsureWindow(0x13A);
}
break;
}
break;
case 0x22:
this->info = reinterpret_cast<NavigationWindowInfo*>(argument1);
this->info->Clamp();
this->Move(this->info->x, this->info->y);
this->Invalidate();
break;
case 0x27:
if (sender == this->unknown_00DC) {
g_navigationSearchType = static_cast<int>(argument1);
g_navigationManager.BuildNodePaths();
this->FillRouteGroups();
this->Invalidate();
if (g_replayAnimationScaling != 0) {
this->unknown_00DC->SendMsg(nullptr, 0x39, argument1, 0, 0, 0);
}
} else if (g_replayAnimationScaling == 0) {
this->LoadRoute(static_cast<int>(argument1));
}
break;
case 0x28:
this->SetRoadIcon(static_cast<int>(argument1));
break;
}
return 0;
}
// OFFSET: 0x005C8D70
// FUNCTION: fn_03627