1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-19 12:39:11 +00:00

Compare commits

..

2 Commits

Author SHA1 Message Date
57186d4650 Fix: Editbox behaved improperly with RTL languages. (#12746)
Text in the editbox was always left-aligned and did not scroll with the caret position.
2024-06-04 23:05:51 +01:00
579ce8eae0 Codefix: Find GRF override entries properly. (#12743)
My naive code from 16 years ago tested for GRF overrides in a way that will create empty 0 entries for each source GRF tested.
2024-06-04 18:06:19 +01:00
2 changed files with 55 additions and 28 deletions

View File

@@ -780,6 +780,25 @@ static int GetCaretWidth()
return GetCharacterWidth(FS_NORMAL, '_');
}
/**
* Reposition edit text box rect based on textbuf length can caret position.
* @param r Initial rect of edit text box.
* @param tb The Textbuf being processed.
* @return Updated rect.
*/
static Rect ScrollEditBoxTextRect(Rect r, const Textbuf &tb)
{
const int linewidth = tb.pixels + GetCaretWidth();
const int boxwidth = r.Width();
if (linewidth <= boxwidth) return r;
/* Extend to cover whole string. This is left-aligned, adjusted by caret position. */
r = r.WithWidth(linewidth, false);
/* Slide so that the caret is at the centre unless limited by bounds of the line, i.e. near either end. */
return r.Translate(-std::clamp(tb.caretxoffs - (boxwidth / 2), 0, linewidth - boxwidth), 0);
}
void QueryString::DrawEditBox(const Window *w, WidgetID wid) const
{
const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
@@ -805,24 +824,29 @@ void QueryString::DrawEditBox(const Window *w, WidgetID wid) const
/* Limit the drawing of the string inside the widget boundaries */
DrawPixelInfo dpi;
if (!FillDrawPixelInfo(&dpi, fr)) return;
/* Keep coordinates relative to the window. */
dpi.left += fr.left;
dpi.top += fr.top;
AutoRestoreBackup dpi_backup(_cur_dpi, &dpi);
/* We will take the current widget length as maximum width, with a small
* space reserved at the end for the caret to show */
const Textbuf *tb = &this->text;
int delta = std::min(0, (fr.right - fr.left) - tb->pixels - GetCaretWidth());
if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs;
fr = ScrollEditBoxTextRect(fr, *tb);
/* If we have a marked area, draw a background highlight. */
if (tb->marklength != 0) GfxFillRect(delta + tb->markxoffs, 0, delta + tb->markxoffs + tb->marklength - 1, fr.bottom - fr.top, PC_GREY);
if (tb->marklength != 0) GfxFillRect(fr.left + tb->markxoffs, fr.top, fr.left + tb->markxoffs + tb->marklength - 1, fr.bottom, PC_GREY);
DrawString(delta, tb->pixels, 0, tb->buf, TC_YELLOW);
DrawString(fr.left, fr.right, CenterBounds(fr.top, fr.bottom, GetCharacterHeight(FS_NORMAL)), tb->buf, TC_YELLOW);
bool focussed = w->IsWidgetGloballyFocused(wid) || IsOSKOpenedFor(w, wid);
if (focussed && tb->caret) {
int caret_width = GetStringBoundingBox("_").width;
DrawString(tb->caretxoffs + delta, tb->caretxoffs + delta + caret_width, 0, "_", TC_WHITE);
int caret_width = GetCaretWidth();
if (rtl) {
DrawString(fr.right - tb->pixels + tb->caretxoffs - caret_width, fr.right - tb->pixels + tb->caretxoffs, CenterBounds(fr.top, fr.bottom, GetCharacterHeight(FS_NORMAL)), "_", TC_WHITE);
} else {
DrawString(fr.left + tb->caretxoffs, fr.left + tb->caretxoffs + caret_width, CenterBounds(fr.top, fr.bottom, GetCharacterHeight(FS_NORMAL)), "_", TC_WHITE);
}
}
}
@@ -846,10 +870,9 @@ Point QueryString::GetCaretPosition(const Window *w, WidgetID wid) const
/* Clamp caret position to be inside out current width. */
const Textbuf *tb = &this->text;
int delta = std::min(0, (r.right - r.left) - tb->pixels - GetCaretWidth());
if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs;
r = ScrollEditBoxTextRect(r, *tb);
Point pt = {r.left + tb->caretxoffs + delta, r.top};
Point pt = {r.left + tb->caretxoffs, r.top};
return pt;
}
@@ -875,14 +898,13 @@ Rect QueryString::GetBoundingRect(const Window *w, WidgetID wid, const char *fro
/* Clamp caret position to be inside our current width. */
const Textbuf *tb = &this->text;
int delta = std::min(0, r.Width() - tb->pixels - GetCaretWidth());
if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs;
r = ScrollEditBoxTextRect(r, *tb);
/* Get location of first and last character. */
Point p1 = GetCharPosInString(tb->buf, from, FS_NORMAL);
Point p2 = from != to ? GetCharPosInString(tb->buf, to, FS_NORMAL) : p1;
return { Clamp(r.left + p1.x + delta, r.left, r.right), r.top, Clamp(r.left + p2.x + delta, r.left, r.right), r.bottom };
return { Clamp(r.left + p1.x, r.left, r.right), r.top, Clamp(r.left + p2.x, r.left, r.right), r.bottom };
}
/**
@@ -908,10 +930,9 @@ ptrdiff_t QueryString::GetCharAtPosition(const Window *w, WidgetID wid, const Po
/* Clamp caret position to be inside our current width. */
const Textbuf *tb = &this->text;
int delta = std::min(0, r.Width() - tb->pixels - GetCaretWidth());
if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs;
r = ScrollEditBoxTextRect(r, *tb);
return ::GetCharAtPosition(tb->buf, pt.x - delta - r.left);
return ::GetCharAtPosition(tb->buf, pt.x - r.left);
}
void QueryString::ClickEditBox(Window *w, Point pt, WidgetID wid, int click_count, bool focus_changed)

View File

@@ -590,8 +590,13 @@ static std::map<uint32_t, uint32_t> _grf_id_overrides;
*/
static void SetNewGRFOverride(uint32_t source_grfid, uint32_t target_grfid)
{
_grf_id_overrides[source_grfid] = target_grfid;
GrfMsg(5, "SetNewGRFOverride: Added override of 0x{:X} to 0x{:X}", BSWAP32(source_grfid), BSWAP32(target_grfid));
if (target_grfid == 0) {
_grf_id_overrides.erase(source_grfid);
GrfMsg(5, "SetNewGRFOverride: Removed override of 0x{:X}", BSWAP32(source_grfid));
} else {
_grf_id_overrides[source_grfid] = target_grfid;
GrfMsg(5, "SetNewGRFOverride: Added override of 0x{:X} to 0x{:X}", BSWAP32(source_grfid), BSWAP32(target_grfid));
}
}
/**
@@ -610,14 +615,13 @@ static Engine *GetNewEngine(const GRFFile *file, VehicleType type, uint16_t inte
if (_settings_game.vehicle.dynamic_engines) {
/* If dynamic_engies is enabled, there can be multiple independent ID ranges. */
scope_grfid = file->grfid;
uint32_t override = _grf_id_overrides[file->grfid];
if (override != 0) {
scope_grfid = override;
const GRFFile *grf_match = GetFileByGRFID(override);
if (auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
scope_grfid = it->second;
const GRFFile *grf_match = GetFileByGRFID(scope_grfid);
if (grf_match == nullptr) {
GrfMsg(5, "Tried mapping from GRFID {:x} to {:x} but target is not loaded", BSWAP32(file->grfid), BSWAP32(override));
GrfMsg(5, "Tried mapping from GRFID {:x} to {:x} but target is not loaded", BSWAP32(file->grfid), BSWAP32(scope_grfid));
} else {
GrfMsg(5, "Mapping from GRFID {:x} to {:x}", BSWAP32(file->grfid), BSWAP32(override));
GrfMsg(5, "Mapping from GRFID {:x} to {:x}", BSWAP32(file->grfid), BSWAP32(scope_grfid));
}
}
@@ -699,8 +703,9 @@ EngineID GetNewEngineID(const GRFFile *file, VehicleType type, uint16_t internal
uint32_t scope_grfid = INVALID_GRFID; // If not using dynamic_engines, all newgrfs share their ID range
if (_settings_game.vehicle.dynamic_engines) {
scope_grfid = file->grfid;
uint32_t override = _grf_id_overrides[file->grfid];
if (override != 0) scope_grfid = override;
if (auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
scope_grfid = it->second;
}
}
return _engine_mngr.GetID(type, internal_id, scope_grfid);
@@ -9790,8 +9795,9 @@ static void FinalisePriceBaseMultipliers()
std::vector<int> grf_overrides(num_grfs, -1);
for (int i = 0; i < num_grfs; i++) {
GRFFile *source = _grf_files[i];
uint32_t override = _grf_id_overrides[source->grfid];
if (override == 0) continue;
auto it = _grf_id_overrides.find(source->grfid);
if (it == std::end(_grf_id_overrides)) continue;
uint32_t override = it->second;
GRFFile *dest = GetFileByGRFID(override);
if (dest == nullptr) continue;