rodecomp/Source/UI/Edit/UIEditCtrl.cpp
ragnarok-clanker a47d20f8be Reconstruct readable C++ and organize cohesive source subsystems
Administrative source import: native x86 compilation passed for 423 authored units. Source placement and submission states are migrated separately; this commit does not imply peer acceptance.

Previous head: 35d2a8cb36
Payload SHA256: 592f016d2730c5593bb653aa054c1e5f76a6df72c8f5a09e66f74876e2e33dee
2026-10-25 07:42:41 +00:00

328 lines
8.8 KiB
C++

#include "Client/Input/TextInputBuffer.h"
#include "Network/TextEncoding.h"
#include "Render/DeviceContext/DeviceContext.h"
#include "UI/Edit/EditPainting.h"
#include "UI/Edit/EditTextState.h"
#include "UI/Edit/EditViewport.h"
#include "UI/Window/InputFocus.h"
#include "UI/Buttons/UIButton.h"
#include "UI/Edit/UIEditCtrl.h"
#include "UI/Window/WindowManagerWindows.h"
#include <algorithm>
#include <cstring>
#include <windows.h>
#include <timeapi.h>
namespace {
class LinkLayout : public EditLinkLayout {
public:
explicit LinkLayout(UIEditCtrl& control) : m_control(control) {
}
void Update() override {
this->m_control.UpdateLinks();
}
private:
UIEditCtrl& m_control;
};
}
// OFFSET: 0x0084FAE0
// FUNCTION: fn_10663
UIEditCtrl::UIEditCtrl(UIWindowContext& windows, UIEditContext& edit)
: UIWindow(windows, 0), anchor(0), cursor(0), mask(0), maximum(255), flat(1), red(255), green(255), blue(255), borderRed(0), borderGreen(0), borderBlue(0),
textColor(0), secondColor(0xFFFFFFFF), firstVisible(0), textY(0), invalidatesParent(0), disabled(0), unknown_00F0(0), topPadding(0), preserveInput(0),
m_edit(&edit) {
this->text.reserve(255);
}
// OFFSET: 0x008517E0
// OFFSET: 0x00852980
// FUNCTION: fn_10718
UIEditCtrl::~UIEditCtrl() = default;
// OFFSET: 0x005C3210
// FUNCTION: fn_03552
bool UIEditCtrl::Slot05() {
return this->disabled == 0;
}
// OFFSET: 0x0085CCA0
// FUNCTION: fn_10807
void UIEditCtrl::Paint() {
const auto component = [&](int value) { return static_cast<unsigned char>(this->disabled != 0 && value > 30 ? value - 30 : value); };
const unsigned color = component(this->red) | (component(this->green) << 8) | (component(this->blue) << 16);
this->textY = 0;
if (this->geometry.surface) {
if (this->flat == 0) {
RECT rectangle{0, 0, this->geometry.width, this->geometry.height};
const unsigned border = static_cast<unsigned char>(this->borderRed) | (static_cast<unsigned char>(this->borderGreen) << 8) |
(static_cast<unsigned char>(this->borderBlue) << 16);
this->geometry.surface->Fill(&rectangle, border);
rectangle = {1, 1, this->geometry.width - 1, this->geometry.height - 1};
this->geometry.surface->Fill(&rectangle, color);
} else {
this->geometry.surface->Fill(nullptr, color);
}
}
this->textY = this->topPadding + 2;
this->PaintText();
}
// OFFSET: 0x0085AAB0
// FUNCTION: fn_10783
void UIEditCtrl::Slot23() {
this->m_edit->input.CancelComposition();
this->m_edit->input.CancelComposition();
this->m_edit->input.Insert(this->text.c_str());
this->m_edit->password = this->mask != 0;
this->SelectAll();
}
// OFFSET: 0x0085E3B0
// FUNCTION: fn_10826
void UIEditCtrl::Slot24(int) {
this->Synchronize();
this->Invalidate();
}
// OFFSET: 0x0085EC20
// FUNCTION: fn_10842
void UIEditCtrl::Slot25(int, int) {
if (this->disabled == 0) {
this->m_edit->focus.Set(this);
}
}
// OFFSET: 0x0085F390
// FUNCTION: fn_10860
void UIEditCtrl::Slot28(int x, int y) {
if (this->disabled != 0) {
return;
}
this->Slot27(x, y);
if (!this->tooltip.empty()) {
int left = 10, top = -20;
for (const UIWindow* window = this; window; window = static_cast<const UIWindow*>(window->parent)) {
left += window->geometry.x;
top += window->geometry.y;
}
this->m_edit->buttons.services.Tooltip(this->tooltip.c_str(), left, top, -1, false, true);
}
}
// OFFSET: 0x008641C0
// FUNCTION: fn_10914
int UIEditCtrl::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) {
if (message == 153) {
this->InsertLink(reinterpret_cast<const char*>(a));
} else if (message == 98 && c > 0) {
UIWindow* window = this->m_edit->windows.EnsureWindow(12);
if (window) {
window->SendMsg(nullptr, 24, c, 0, 0, 0);
}
}
UIWindow::SendMsg(sender, message, a, b, c, d);
if (message == 0 && this->preserveInput == 0) {
this->m_edit->input.CancelComposition();
}
return 0;
}
// OFFSET: 0x005C44E0
int UIEditCtrl::Slot46() {
return 2;
}
// OFFSET: 0x008680D0
// FUNCTION: fn_10952
void UIEditCtrl::SetText(const char* value) {
this->text.assign(value, std::strlen(value));
this->Trim();
if (this->m_edit->focus.window == this) {
this->m_edit->input.CancelComposition();
this->m_edit->input.CancelComposition();
this->m_edit->input.Insert(this->text.c_str());
}
this->SelectAll();
if (this->parent) {
static_cast<UIWindow*>(this->parent)->Invalidate();
}
}
// OFFSET: 0x0085A590
// FUNCTION: fn_10778
void UIEditCtrl::SelectAll() {
const bool focused = this->m_edit->focus.window == this;
EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage};
state.SelectAll();
}
// OFFSET: 0x00856980
// FUNCTION: fn_10755
void UIEditCtrl::PaintText() {
this->PaintTextWithPolicy(false, nullptr, 0, false);
}
void UIEditCtrl::PaintTextWithPolicy(bool alternate, const std::string* placeholder, std::uint32_t placeholderColor, bool placeholderEnabled) {
const bool focused = this->m_edit->focus.window == this;
EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage};
EditViewport viewport{
this->text,
this->anchor,
this->cursor,
this->firstVisible,
this->geometry.width,
g_textCodePage,
this->m_edit->input,
state,
*this->geometry.surface,
this->m_edit->buttons.fonts,
this->m_edit->buttons.locale
};
UIWindow* parent = static_cast<UIWindow*>(this->parent);
int left = 0, top = 0;
for (const UIWindow* window = this; window; window = static_cast<const UIWindow*>(window->parent)) {
left += window->geometry.x;
top += window->geometry.y;
}
const bool chat = this->m_edit->input.chatInput == this || this->m_edit->otherChatInput == this;
const DWORD tick = timeGetTime();
LinkLayout layout(*this);
EditPainting painting{
this->text,
this->anchor,
this->cursor,
this->mask,
this->firstVisible,
this->textY,
this->invalidatesParent,
this->textColor,
this->secondColor,
focused,
chat,
this->m_edit->input.suggestionsEnabled,
tick,
this->m_edit->candidateCursor,
this->geometry.width,
this->geometry.height,
this->m_edit->screenWidth,
this->m_edit->screenHeight,
this->m_edit->input,
this->m_edit->charset,
viewport,
*this->geometry.surface,
this->m_edit->buttons.fonts,
this->m_edit->buttons.locale,
this->m_edit->colorChip,
parent,
this->m_edit->candidateWindow,
this->m_edit->readingWindow,
left,
top,
this->links,
layout
};
painting.alternate = alternate;
painting.placeholder = placeholder;
painting.placeholderColor = placeholderColor;
painting.placeholderEnabled = placeholderEnabled;
painting.Draw();
}
// OFFSET: 0x00862FB0
// FUNCTION: fn_10905
void UIEditCtrl::Synchronize() {
const bool focused = this->m_edit->focus.window == this;
EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage};
EditViewport viewport{
this->text,
this->anchor,
this->cursor,
this->firstVisible,
this->geometry.width,
g_textCodePage,
this->m_edit->input,
state,
*this->geometry.surface,
this->m_edit->buttons.fonts,
this->m_edit->buttons.locale
};
viewport.Synchronize();
}
// OFFSET: 0x00868450
// FUNCTION: fn_10959
void UIEditCtrl::Trim() {
const bool focused = this->m_edit->focus.window == this;
EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage};
state.Trim();
}
// OFFSET: 0x00858D50
// FUNCTION: fn_10768
int UIEditCtrl::Length() const {
return static_cast<int>(this->m_edit->focus.window == this ? this->m_edit->input.text.size() : this->text.size());
}
// OFFSET: 0x00858D20
// FUNCTION: fn_10767
const char* UIEditCtrl::Text() {
if (this->m_edit->focus.window == this) {
this->Synchronize();
}
return this->text.c_str();
}
// OFFSET: 0x00865DD0
// FUNCTION: fn_10937
void UIEditCtrl::Background(int red, int green, int blue) {
this->red = red;
this->green = green;
this->blue = blue;
this->Invalidate();
}
// OFFSET: 0x00868570
// FUNCTION: fn_10960
void UIEditCtrl::TextColor(std::uint32_t primary, std::uint32_t secondary) {
this->secondColor = secondary;
this->textColor = primary;
this->Invalidate();
}
// OFFSET: 0x0097C230
// FUNCTION: fn_13324
UIEditCtrlWheel::UIEditCtrlWheel(UIWindowContext& windows, UIEditContext& edit) : UIEditCtrl(windows, edit) {
}
// OFFSET: 0x009701B0
// FUNCTION: fn_13241
UIEditCtrlWheel::~UIEditCtrlWheel() = default;
// OFFSET: 0x0098A240
// FUNCTION: fn_13408
void UIEditCtrlWheel::Slot35(int value) {
if (this->parent) {
static_cast<UIWindow*>(this->parent)->Slot35(value);
}
}