Merge branch 'master' into jgrpp

# Conflicts:
#	src/company_gui.cpp
#	src/group_gui.cpp
#	src/newgrf.cpp
#	src/newgrf_debug_gui.cpp
#	src/saveload/saveload.cpp
pull/590/head
Jonathan G Rennison 9 months ago
commit 5a28405ced

@ -204,6 +204,7 @@ add_files(
group_cmd.cpp group_cmd.cpp
group_gui.cpp group_gui.cpp
group_gui.h group_gui.h
group_gui_list.h
group_type.h group_type.h
gui.h gui.h
guitimer_func.h guitimer_func.h

@ -275,19 +275,18 @@ static EngineID _last_engine[2] = { INVALID_ENGINE, INVALID_ENGINE };
*/ */
static bool EngineNameSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) static bool EngineNameSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
{ {
static char last_name[2][64] = { "", "" }; static std::string last_name[2] = { {}, {} };
if (a.engine_id != _last_engine[0]) { if (a.engine_id != _last_engine[0]) {
_last_engine[0] = a.engine_id; _last_engine[0] = a.engine_id;
SetDParam(0, PackEngineNameDParam(a.engine_id, EngineNameContext::PurchaseList)); SetDParam(0, PackEngineNameDParam(a.engine_id, EngineNameContext::PurchaseList));
last_name[0] = GetString(STR_ENGINE_NAME);
GetString(last_name[0], STR_ENGINE_NAME, lastof(last_name[0]));
} }
if (b.engine_id != _last_engine[1]) { if (b.engine_id != _last_engine[1]) {
_last_engine[1] = b.engine_id; _last_engine[1] = b.engine_id;
SetDParam(0, PackEngineNameDParam(b.engine_id, EngineNameContext::PurchaseList)); SetDParam(0, PackEngineNameDParam(b.engine_id, EngineNameContext::PurchaseList));
GetString(last_name[1], STR_ENGINE_NAME, lastof(last_name[1])); last_name[1] = GetString(STR_ENGINE_NAME);
} }
int r = StrNaturalCompare(last_name[0], last_name[1]); // Sort by name (natural sorting). int r = StrNaturalCompare(last_name[0], last_name[1]); // Sort by name (natural sorting).

@ -37,6 +37,7 @@
#include "station_func.h" #include "station_func.h"
#include "zoom_func.h" #include "zoom_func.h"
#include "sortlist_type.h" #include "sortlist_type.h"
#include "group_gui_list.h"
#include "core/backup_type.hpp" #include "core/backup_type.hpp"
#include "widgets/company_widget.h" #include "widgets/company_widget.h"
@ -671,11 +672,6 @@ public:
} }
}; };
typedef GUIList<const Group*> GUIGroupList;
/* cached values for GroupNameSorter to spare many GetString() calls */
static const Group *_last_group[2] = { nullptr, nullptr };
/** Company livery colour scheme window. */ /** Company livery colour scheme window. */
struct SelectCompanyLiveryWindow : public Window { struct SelectCompanyLiveryWindow : public Window {
private: private:
@ -738,27 +734,6 @@ private:
ShowDropDownList(this, std::move(list), sel, widget); ShowDropDownList(this, std::move(list), sel, widget);
} }
static bool GroupNameSorter(const Group * const &a, const Group * const &b)
{
static char last_name[2][64] = { "", "" };
if (a != _last_group[0]) {
_last_group[0] = a;
SetDParam(0, a->index);
GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0]));
}
if (b != _last_group[1]) {
_last_group[1] = b;
SetDParam(0, b->index);
GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1]));
}
int r = StrNaturalCompare(last_name[0], last_name[1]); // Sort by name (natural sorting).
if (r == 0) return a->index < b->index;
return r < 0;
}
void AddChildren(GUIGroupList &source, GroupID parent, int indent) void AddChildren(GUIGroupList &source, GroupID parent, int indent)
{ {
for (const Group *g : source) { for (const Group *g : source) {
@ -787,11 +762,7 @@ private:
} }
list.ForceResort(); list.ForceResort();
SortGUIGroupList(list);
/* invalidate cached values for name sorter - group names could change */
_last_group[0] = _last_group[1] = nullptr;
list.Sort(&GroupNameSorter);
AddChildren(list, INVALID_GROUP, 0); AddChildren(list, INVALID_GROUP, 0);
} }

@ -598,8 +598,6 @@ DEF_CONSOLE_CMD(ConChangeDirectory)
DEF_CONSOLE_CMD(ConPrintWorkingDirectory) DEF_CONSOLE_CMD(ConPrintWorkingDirectory)
{ {
const char *path;
if (argc == 0) { if (argc == 0) {
IConsoleHelp("Print out the current working directory. Usage: 'pwd'"); IConsoleHelp("Print out the current working directory. Usage: 'pwd'");
return true; return true;
@ -609,8 +607,7 @@ DEF_CONSOLE_CMD(ConPrintWorkingDirectory)
_console_file_list.ValidateFileList(true); _console_file_list.ValidateFileList(true);
_console_file_list.InvalidateFileList(); _console_file_list.InvalidateFileList();
FiosGetDescText(&path, nullptr); IConsolePrint(CC_DEFAULT, FiosGetCurrentPath().c_str());
IConsolePrint(CC_DEFAULT, path);
return true; return true;
} }

@ -42,7 +42,6 @@ extern bool FiosIsRoot(const char *path);
extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb); extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
extern bool FiosIsHiddenFile(const struct dirent *ent); extern bool FiosIsHiddenFile(const struct dirent *ent);
extern void FiosGetDrives(FileList &file_list); extern void FiosGetDrives(FileList &file_list);
extern bool FiosGetDiskFreeSpace(const char *path, uint64 *tot);
/* get the name of an oldstyle savegame */ /* get the name of an oldstyle savegame */
extern void GetOldSaveGameName(const std::string &file, char *title, const char *last); extern void GetOldSaveGameName(const std::string &file, char *title, const char *last);
@ -131,16 +130,11 @@ const FiosItem *FileList::FindItem(const std::string_view file)
} }
/** /**
* Get descriptive texts. Returns the path and free space * Get the current path/working directory.
* left on the device
* @param path string describing the path
* @param total_free total free space in megabytes, optional (can be nullptr)
* @return StringID describing the path (free space or failure)
*/ */
StringID FiosGetDescText(const char **path, uint64 *total_free) std::string FiosGetCurrentPath()
{ {
*path = _fios_path->c_str(); return *_fios_path;
return FiosGetDiskFreeSpace(*path, total_free) ? STR_SAVELOAD_BYTES_FREE : STR_ERROR_UNABLE_TO_READ_DRIVE;
} }
/** /**

@ -59,7 +59,8 @@ void FiosGetHeightmapList(SaveLoadOperation fop, FileList &file_list);
bool FiosBrowseTo(const FiosItem *item); bool FiosBrowseTo(const FiosItem *item);
StringID FiosGetDescText(const char **path, uint64 *total_free); std::string FiosGetCurrentPath();
std::optional<uint64_t> FiosGetDiskFreeSpace(const std::string &path);
bool FiosDelete(const char *name); bool FiosDelete(const char *name);
std::string FiosMakeHeightmapName(const char *name); std::string FiosMakeHeightmapName(const char *name);
std::string FiosMakeSavegameName(const char *name); std::string FiosMakeSavegameName(const char *name);

@ -427,19 +427,19 @@ public:
break; break;
case WID_SL_BACKGROUND: { case WID_SL_BACKGROUND: {
static const char *path = nullptr; static std::string path;
static StringID str = STR_ERROR_UNABLE_TO_READ_DRIVE; static std::optional<uint64_t> free_space = std::nullopt;
static uint64 tot = 0;
if (_fios_path_changed) { if (_fios_path_changed) {
str = FiosGetDescText(&path, &tot); path = FiosGetCurrentPath();
free_space = FiosGetDiskFreeSpace(path);
_fios_path_changed = false; _fios_path_changed = false;
} }
Rect ir = r.Shrink(WidgetDimensions::scaled.framerect); Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
if (str != STR_ERROR_UNABLE_TO_READ_DRIVE) SetDParam(0, tot); if (free_space.has_value()) SetDParam(0, free_space.value());
DrawString(ir.left, ir.right, ir.top + FONT_HEIGHT_NORMAL, str); DrawString(ir.left, ir.right, ir.top + FONT_HEIGHT_NORMAL, free_space.has_value() ? STR_SAVELOAD_BYTES_FREE : STR_ERROR_UNABLE_TO_READ_DRIVE);
DrawString(ir.left, ir.right, ir.top, path, TC_BLACK); DrawString(ir.left, ir.right, ir.top, path, TC_BLACK);
break; break;
} }

@ -29,6 +29,7 @@
#include "gfx_func.h" #include "gfx_func.h"
#include "tbtr_template_gui_main.h" #include "tbtr_template_gui_main.h"
#include "newgrf_debug.h" #include "newgrf_debug.h"
#include "group_gui_list.h"
#include "widgets/group_widget.h" #include "widgets/group_widget.h"
@ -36,8 +37,6 @@
#include "safeguards.h" #include "safeguards.h"
typedef GUIList<const Group*> GUIGroupList;
static const NWidgetPart _nested_group_widgets[] = { static const NWidgetPart _nested_group_widgets[] = {
NWidget(NWID_HORIZONTAL), // Window header NWidget(NWID_HORIZONTAL), // Window header
NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CLOSEBOX, COLOUR_GREY),
@ -117,29 +116,28 @@ static const NWidgetPart _nested_group_widgets[] = {
EndContainer(), EndContainer(),
}; };
/* cached values for GroupNameSorter to spare many GetString() calls */ void SortGUIGroupList(GUIGroupList &list)
static const Group *_last_group[2] = { nullptr, nullptr };
/** Sort the groups by their name */
bool GroupNameSorter(const Group * const &a, const Group * const &b)
{ {
static char last_name[2][64] = { "", "" }; /* Sort the groups by their name */
const Group *last_group[2] = { nullptr, nullptr };
if (a != _last_group[0]) { std::string last_name[2] = { {}, {} };
_last_group[0] = a; list.Sort([&](const Group * const &a, const Group * const &b) {
SetDParam(0, a->index); if (a != last_group[0]) {
GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0])); last_group[0] = a;
} SetDParam(0, a->index);
last_name[0] = GetString(STR_GROUP_NAME);
}
if (b != _last_group[1]) { if (b != last_group[1]) {
_last_group[1] = b; last_group[1] = b;
SetDParam(0, b->index); SetDParam(0, b->index);
GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1])); last_name[1] = GetString(STR_GROUP_NAME);
} }
int r = StrNaturalCompare(last_name[0], last_name[1]); // Sort by name (natural sorting). int r = StrNaturalCompare(last_name[0], last_name[1]); // Sort by name (natural sorting).
if (r == 0) return a->index < b->index; if (r == 0) return a->index < b->index;
return r < 0; return r < 0;
});
} }
class VehicleGroupWindow : public BaseVehicleListWindow { class VehicleGroupWindow : public BaseVehicleListWindow {
@ -222,11 +220,7 @@ private:
this->SetWidgetDisabledState(WID_GL_COLLAPSE_ALL_GROUPS, !enable_collapse_all); this->SetWidgetDisabledState(WID_GL_COLLAPSE_ALL_GROUPS, !enable_collapse_all);
list.ForceResort(); list.ForceResort();
SortGUIGroupList(list);
/* invalidate cached values for name sorter - group names could change */
_last_group[0] = _last_group[1] = nullptr;
list.Sort(&GroupNameSorter);
AddChildren(list, INVALID_GROUP, 0); AddChildren(list, INVALID_GROUP, 0);

@ -0,0 +1,19 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file group_gui_list.h Group GUI lists. */
#ifndef GROUP_GUI_LIST_H
#define GROUP_GUI_LIST_H
#include "group.h"
#include "sortlist_type.h"
typedef GUIList<const Group*> GUIGroupList;
void SortGUIGroupList(GUIGroupList &list);
#endif /* GROUP_GUI_LIST_H */

@ -344,7 +344,7 @@ class NetworkContentListWindow : public Window, ContentCallback {
uint filesize_sum; ///< The sum of all selected file sizes uint filesize_sum; ///< The sum of all selected file sizes
Scrollbar *vscroll; ///< Cache of the vertical scrollbar Scrollbar *vscroll; ///< Cache of the vertical scrollbar
static char content_type_strs[CONTENT_TYPE_END][64]; ///< Cached strings for all content types. static std::string content_type_strs[CONTENT_TYPE_END]; ///< Cached strings for all content types.
/** Search external websites for content */ /** Search external websites for content */
void OpenExternalSearch() void OpenExternalSearch()
@ -1021,7 +1021,7 @@ NetworkContentListWindow::GUIContentList::FilterFunction * const NetworkContentL
&TypeOrSelectedFilter, &TypeOrSelectedFilter,
}; };
char NetworkContentListWindow::content_type_strs[CONTENT_TYPE_END][64]; std::string NetworkContentListWindow::content_type_strs[CONTENT_TYPE_END];
/** /**
* Build array of all strings corresponding to the content types. * Build array of all strings corresponding to the content types.
@ -1029,7 +1029,7 @@ char NetworkContentListWindow::content_type_strs[CONTENT_TYPE_END][64];
void BuildContentTypeStringList() void BuildContentTypeStringList()
{ {
for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) { for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
GetString(NetworkContentListWindow::content_type_strs[i], STR_CONTENT_TYPE_BASE_GRAPHICS + i - CONTENT_TYPE_BASE_GRAPHICS, lastof(NetworkContentListWindow::content_type_strs[i])); NetworkContentListWindow::content_type_strs[i] = GetString(STR_CONTENT_TYPE_BASE_GRAPHICS + i - CONTENT_TYPE_BASE_GRAPHICS);
} }
} }

@ -6306,15 +6306,6 @@ static void NewSpriteGroup(ByteReader *buf)
static CargoID TranslateCargo(uint8 feature, uint8 ctype) static CargoID TranslateCargo(uint8 feature, uint8 ctype)
{ {
if (feature == GSF_OBJECTS) {
switch (ctype) {
case 0: return 0;
case 0xFF: return CT_PURCHASE_OBJECT;
default:
grfmsg(1, "TranslateCargo: Invalid cargo bitnum %d for objects, skipping.", ctype);
return CT_INVALID;
}
}
/* Special cargo types for purchase list and stations */ /* Special cargo types for purchase list and stations */
if ((feature == GSF_STATIONS || feature == GSF_ROADSTOPS) && ctype == 0xFE) return CT_DEFAULT_NA; if ((feature == GSF_STATIONS || feature == GSF_ROADSTOPS) && ctype == 0xFE) return CT_DEFAULT_NA;
if (ctype == 0xFF) return CT_PURCHASE; if (ctype == 0xFF) return CT_PURCHASE;
@ -6710,8 +6701,11 @@ static void ObjectMapSpriteGroup(ByteReader *buf, uint8 idcount)
uint16 groupid = buf->ReadWord(); uint16 groupid = buf->ReadWord();
if (!IsValidGroupID(groupid, "ObjectMapSpriteGroup")) continue; if (!IsValidGroupID(groupid, "ObjectMapSpriteGroup")) continue;
ctype = TranslateCargo(GSF_OBJECTS, ctype); /* The only valid option here is purchase list sprite groups. */
if (ctype == CT_INVALID) continue; if (ctype != 0xFF) {
grfmsg(1, "ObjectMapSpriteGroup: Invalid cargo bitnum %d for objects, skipping.", ctype);
continue;
}
for (uint i = 0; i < idcount; i++) { for (uint i = 0; i < idcount; i++) {
ObjectSpec *spec = (objects[i] >= _cur.grffile->objectspec.size()) ? nullptr : _cur.grffile->objectspec[objects[i]].get(); ObjectSpec *spec = (objects[i] >= _cur.grffile->objectspec.size()) ? nullptr : _cur.grffile->objectspec[objects[i]].get();
@ -6721,7 +6715,7 @@ static void ObjectMapSpriteGroup(ByteReader *buf, uint8 idcount)
continue; continue;
} }
spec->grf_prop.spritegroup[ctype] = GetGroupByID(groupid); spec->grf_prop.spritegroup[OBJECT_SPRITE_GROUP_PURCHASE] = GetGroupByID(groupid);
} }
} }
@ -6741,9 +6735,9 @@ static void ObjectMapSpriteGroup(ByteReader *buf, uint8 idcount)
continue; continue;
} }
spec->grf_prop.spritegroup[0] = GetGroupByID(groupid); spec->grf_prop.spritegroup[OBJECT_SPRITE_GROUP_DEFAULT] = GetGroupByID(groupid);
spec->grf_prop.grffile = _cur.grffile; spec->grf_prop.grffile = _cur.grffile;
spec->grf_prop.local_id = objects[i]; spec->grf_prop.local_id = objects[i];
} }
} }

@ -72,14 +72,13 @@ static void ShowNewGRFInfo(const GRFConfig *c, const Rect &r, bool show_params)
{ {
Rect tr = r.Shrink(WidgetDimensions::scaled.frametext); Rect tr = r.Shrink(WidgetDimensions::scaled.frametext);
if (c->error != nullptr) { if (c->error != nullptr) {
char message[512];
SetDParamStr(0, c->error->custom_message); // is skipped by built-in messages SetDParamStr(0, c->error->custom_message); // is skipped by built-in messages
SetDParamStr(1, c->filename); SetDParamStr(1, c->filename);
SetDParamStr(2, c->error->data); SetDParamStr(2, c->error->data);
for (uint i = 0; i < c->error->param_value.size(); i++) { for (uint i = 0; i < c->error->param_value.size(); i++) {
SetDParam(3 + i, c->error->param_value[i]); SetDParam(3 + i, c->error->param_value[i]);
} }
GetString(message, c->error->message != STR_NULL ? c->error->message : STR_JUST_RAW_STRING, lastof(message)); std::string message = GetString(c->error->message != STR_NULL ? c->error->message : STR_JUST_RAW_STRING);
SetDParamStr(0, message); SetDParamStr(0, message);
tr.top = DrawStringMultiLine(tr, c->error->severity); tr.top = DrawStringMultiLine(tr, c->error->severity);

@ -403,8 +403,8 @@ ObjectResolverObject::ObjectResolverObject(const ObjectSpec *spec, Object *obj,
: ResolverObject(spec->grf_prop.grffile, callback, param1, param2), object_scope(*this, obj, spec, tile, view) : ResolverObject(spec->grf_prop.grffile, callback, param1, param2), object_scope(*this, obj, spec, tile, view)
{ {
this->town_scope = nullptr; this->town_scope = nullptr;
this->root_spritegroup = (obj == nullptr && spec->grf_prop.spritegroup[CT_PURCHASE_OBJECT] != nullptr) ? this->root_spritegroup = (obj == nullptr && spec->grf_prop.spritegroup[OBJECT_SPRITE_GROUP_PURCHASE] != nullptr) ?
spec->grf_prop.spritegroup[CT_PURCHASE_OBJECT] : spec->grf_prop.spritegroup[0]; spec->grf_prop.spritegroup[OBJECT_SPRITE_GROUP_PURCHASE] : spec->grf_prop.spritegroup[OBJECT_SPRITE_GROUP_DEFAULT];
} }
ObjectResolverObject::~ObjectResolverObject() ObjectResolverObject::~ObjectResolverObject()

@ -202,8 +202,8 @@ private:
/** Struct containing information relating to object classes. */ /** Struct containing information relating to object classes. */
typedef NewGRFClass<ObjectSpec, ObjectClassID, OBJECT_CLASS_MAX> ObjectClass; typedef NewGRFClass<ObjectSpec, ObjectClassID, OBJECT_CLASS_MAX> ObjectClass;
/** Mapping of purchase for objects. */ static const size_t OBJECT_SPRITE_GROUP_DEFAULT = 0;
static const CargoID CT_PURCHASE_OBJECT = 1; static const size_t OBJECT_SPRITE_GROUP_PURCHASE = 1;
uint16 GetObjectCallback(CallbackID callback, uint32 param1, uint32 param2, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view = 0); uint16 GetObjectCallback(CallbackID callback, uint32 param1, uint32 param2, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view = 0);

@ -95,32 +95,21 @@ void FiosGetDrives(FileList &file_list)
#endif #endif
} }
bool FiosGetDiskFreeSpace(const char *path, uint64 *tot) std::optional<uint64_t> FiosGetDiskFreeSpace(const std::string &path)
{ {
#ifndef __INNOTEK_LIBC__ #ifndef __INNOTEK_LIBC__
struct diskfree_t free; struct diskfree_t free;
char drive = path[0] - 'A' + 1; char drive = path[0] - 'A' + 1;
if (tot != nullptr && _getdiskfree(drive, &free) == 0) { if (_getdiskfree(drive, &free) == 0) {
*tot = free.avail_clusters * free.sectors_per_cluster * free.bytes_per_sector; return free.avail_clusters * free.sectors_per_cluster * free.bytes_per_sector;
return true;
} }
#elif defined(HAS_STATVFS)
struct statvfs s;
return false; if (statvfs(path.c_str(), &s) == 0) return static_cast<uint64_t>(s.f_frsize) * s.f_bavail;
#else
uint64 free = 0;
#ifdef HAS_STATVFS
{
struct statvfs s;
if (statvfs(path, &s) != 0) return false;
free = (uint64)s.f_frsize * s.f_bavail;
}
#endif
if (tot != nullptr) *tot = free;
return true;
#endif #endif
return std::nullopt;
} }
bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)

@ -75,23 +75,18 @@ void FiosGetDrives(FileList &file_list)
return; return;
} }
bool FiosGetDiskFreeSpace(const char *path, uint64 *tot) std::optional<uint64_t> FiosGetDiskFreeSpace(const std::string &path)
{ {
uint64 free = 0;
#ifdef __APPLE__ #ifdef __APPLE__
struct statfs s; struct statfs s;
if (statfs(path, &s) != 0) return false; if (statfs(path.c_str(), &s) == 0) return static_cast<uint64_t>(s.f_bsize) * s.f_bavail;
free = (uint64)s.f_bsize * s.f_bavail;
#elif defined(HAS_STATVFS) #elif defined(HAS_STATVFS)
struct statvfs s; struct statvfs s;
if (statvfs(path, &s) != 0) return false; if (statvfs(path.c_str(), &s) == 0) return static_cast<uint64_t>(s.f_frsize) * s.f_bavail;
free = (uint64)s.f_frsize * s.f_bavail;
#endif #endif
if (tot != nullptr) *tot = free; return std::nullopt;
return true;
} }
bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)

@ -256,16 +256,17 @@ bool FiosIsHiddenFile(const struct dirent *ent)
return (ent->dir->fd.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0; return (ent->dir->fd.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0;
} }
bool FiosGetDiskFreeSpace(const char *path, uint64 *tot) std::optional<uint64_t> FiosGetDiskFreeSpace(const std::string &path)
{ {
UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box
ULARGE_INTEGER bytes_free; ULARGE_INTEGER bytes_free;
bool retval = GetDiskFreeSpaceEx(OTTD2FS(path).c_str(), &bytes_free, nullptr, nullptr); bool retval = GetDiskFreeSpaceEx(OTTD2FS(path).c_str(), &bytes_free, nullptr, nullptr);
if (retval && tot != nullptr) *tot = bytes_free.QuadPart;
SetErrorMode(sem); // reset previous setting SetErrorMode(sem); // reset previous setting
return retval;
if (retval) return bytes_free.QuadPart;
return std::nullopt;
} }
static int ParseCommandLine(char *line, char **argv, int max_argc) static int ParseCommandLine(char *line, char **argv, int max_argc)

@ -347,27 +347,18 @@ static WindowDesc _osk_desc(
*/ */
void GetKeyboardLayout() void GetKeyboardLayout()
{ {
char keyboard[2][OSK_KEYBOARD_ENTRIES * 4 + 1]; std::string keyboard[2];
char errormark[2][OSK_KEYBOARD_ENTRIES + 1]; // used for marking invalid chars std::string errormark[2]; // used for marking invalid chars
bool has_error = false; // true when an invalid char is detected bool has_error = false; // true when an invalid char is detected
if (_keyboard_opt[0].empty()) { keyboard[0] = _keyboard_opt[0].empty() ? GetString(STR_OSK_KEYBOARD_LAYOUT) : _keyboard_opt[0];
GetString(keyboard[0], STR_OSK_KEYBOARD_LAYOUT, lastof(keyboard[0])); keyboard[1] = _keyboard_opt[1].empty() ? GetString(STR_OSK_KEYBOARD_LAYOUT_CAPS) : _keyboard_opt[1];
} else {
strecpy(keyboard[0], _keyboard_opt[0].c_str(), lastof(keyboard[0]));
}
if (_keyboard_opt[1].empty()) {
GetString(keyboard[1], STR_OSK_KEYBOARD_LAYOUT_CAPS, lastof(keyboard[1]));
} else {
strecpy(keyboard[1], _keyboard_opt[1].c_str(), lastof(keyboard[1]));
}
for (uint j = 0; j < 2; j++) { for (uint j = 0; j < 2; j++) {
const char *kbd = keyboard[j]; auto kbd = keyboard[j].begin();
bool ended = false; bool ended = false;
for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) { for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
_keyboard[j][i] = Utf8Consume(&kbd); _keyboard[j][i] = Utf8Consume(kbd);
/* Be lenient when the last characters are missing (is quite normal) */ /* Be lenient when the last characters are missing (is quite normal) */
if (_keyboard[j][i] == '\0' || ended) { if (_keyboard[j][i] == '\0' || ended) {
@ -377,10 +368,10 @@ void GetKeyboardLayout()
} }
if (IsPrintable(_keyboard[j][i])) { if (IsPrintable(_keyboard[j][i])) {
errormark[j][i] = ' '; errormark[j] += ' ';
} else { } else {
has_error = true; has_error = true;
errormark[j][i] = '^'; errormark[j] += '^';
_keyboard[j][i] = ' '; _keyboard[j][i] = ' ';
} }
} }
@ -388,10 +379,10 @@ void GetKeyboardLayout()
if (has_error) { if (has_error) {
ShowInfoF("The keyboard layout you selected contains invalid chars. Please check those chars marked with ^."); ShowInfoF("The keyboard layout you selected contains invalid chars. Please check those chars marked with ^.");
ShowInfoF("Normal keyboard: %s", keyboard[0]); ShowInfoF("Normal keyboard: %s", keyboard[0].c_str());
ShowInfoF(" %s", errormark[0]); ShowInfoF(" %s", errormark[0].c_str());
ShowInfoF("Caps Lock: %s", keyboard[1]); ShowInfoF("Caps Lock: %s", keyboard[1].c_str());
ShowInfoF(" %s", errormark[1]); ShowInfoF(" %s", errormark[1].c_str());
} }
} }

@ -39,6 +39,7 @@
#include "window_func.h" #include "window_func.h"
#include "window_gui.h" #include "window_gui.h"
#include "zoom_func.h" #include "zoom_func.h"
#include "group_gui_list.h"
#include "tbtr_template_gui_main.h" #include "tbtr_template_gui_main.h"
#include "tbtr_template_gui_create.h" #include "tbtr_template_gui_create.h"
@ -49,9 +50,6 @@
#include "safeguards.h" #include "safeguards.h"
typedef GUIList<const Group*> GUIGroupList;
enum TemplateReplaceWindowWidgets { enum TemplateReplaceWindowWidgets {
TRW_CAPTION, TRW_CAPTION,
@ -582,8 +580,7 @@ public:
} }
list.ForceResort(); list.ForceResort();
extern bool GroupNameSorter(const Group * const &a, const Group * const &b); SortGUIGroupList(list);
list.Sort(&GroupNameSorter);
AddParents(&list, INVALID_GROUP, 0); AddParents(&list, INVALID_GROUP, 0);

@ -19,8 +19,6 @@
#include "tbtr_template_vehicle.h" #include "tbtr_template_vehicle.h"
#include "tbtr_template_vehicle_func.h" #include "tbtr_template_vehicle_func.h"
typedef GUIList<const Group*> GUIGroupList;
void ShowTemplateReplaceWindow(); void ShowTemplateReplaceWindow();
bool TemplateVehicleClicked(const TemplateVehicle *v); bool TemplateVehicleClicked(const TemplateVehicle *v);

@ -46,6 +46,7 @@
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
#include "infrastructure_func.h" #include "infrastructure_func.h"
#include "zoom_func.h" #include "zoom_func.h"
#include "group_gui_list.h"
#include "core/span_type.hpp" #include "core/span_type.hpp"
#include "3rdparty/cpp-btree/btree_map.h" #include "3rdparty/cpp-btree/btree_map.h"
@ -641,9 +642,6 @@ static const TraceRestrictDropDownListSet *GetSortedCargoTypeDropDownListSet()
*/ */
static DropDownList GetGroupDropDownList(Owner owner, GroupID group_id, int &selected) static DropDownList GetGroupDropDownList(Owner owner, GroupID group_id, int &selected)
{ {
typedef GUIList<const Group*> GUIGroupList;
extern bool GroupNameSorter(const Group * const &a, const Group * const &b);
GUIGroupList list; GUIGroupList list;
for (const Group *g : Group::Iterate()) { for (const Group *g : Group::Iterate()) {
@ -653,7 +651,7 @@ static DropDownList GetGroupDropDownList(Owner owner, GroupID group_id, int &sel
} }
list.ForceResort(); list.ForceResort();
list.Sort(&GroupNameSorter); SortGUIGroupList(list);
DropDownList dlist; DropDownList dlist;
selected = -1; selected = -1;

@ -1546,18 +1546,18 @@ static bool VehicleNumberSorter(const Vehicle * const &a, const Vehicle * const
/** Sort vehicles by their name */ /** Sort vehicles by their name */
static bool VehicleNameSorter(const Vehicle * const &a, const Vehicle * const &b) static bool VehicleNameSorter(const Vehicle * const &a, const Vehicle * const &b)
{ {
static char last_name[2][64]; static std::string last_name[2] = { {}, {} };
if (a != _last_vehicle[0]) { if (a != _last_vehicle[0]) {
_last_vehicle[0] = a; _last_vehicle[0] = a;
SetDParam(0, a->index); SetDParam(0, a->index);
GetString(last_name[0], STR_VEHICLE_NAME, lastof(last_name[0])); last_name[0] = GetString(STR_VEHICLE_NAME);
} }
if (b != _last_vehicle[1]) { if (b != _last_vehicle[1]) {
_last_vehicle[1] = b; _last_vehicle[1] = b;
SetDParam(0, b->index); SetDParam(0, b->index);
GetString(last_name[1], STR_VEHICLE_NAME, lastof(last_name[1])); last_name[1] = GetString(STR_VEHICLE_NAME);
} }
int r = StrNaturalCompare(last_name[0], last_name[1]); // Sort by name (natural sorting). int r = StrNaturalCompare(last_name[0], last_name[1]); // Sort by name (natural sorting).

Loading…
Cancel
Save