1
0
Fork 0

Compare commits

...

8 Commits

Author SHA1 Message Date
SamuXarick d33ef37852
Merge 3d8dad2cc6 into 1d38cbafcb 2025-07-13 23:10:26 +00:00
Peter Nelson 1d38cbafcb Codechange: Use unique_ptr for ScriptInfo instances.
Replaces raw pointers, slightly.
2025-07-14 00:10:14 +01:00
Peter Nelson 992d58d799 Codechange: Pass ScriptInfo by reference to IsSameScript. 2025-07-14 00:10:14 +01:00
Peter Nelson 8f34b7a821 Codechange: Keep Squirrel engine in unique_ptr. 2025-07-14 00:10:14 +01:00
Peter Nelson bf6d0c4934
Codechange: Don't pre-fill font metrics when loading fonts. (#14436)
Each font cache implementation sets its own metrics based on the loaded font, so there is no need to pre-fill with (unscaled, invalid) default metrics.
2025-07-13 23:38:31 +01:00
Michael Lutz 3c4fb21a5e
Fix: [Win32] Link failure with newer Windows SDK version due to WinRT changes. (#14432) 2025-07-13 22:34:32 +01:00
SamuXarick 3d8dad2cc6 Codechange: Optimize FlowRiver
Make all height_tile int to allow comparison between heights generated from TileHeight and heights generated from IsTileFlat.
Make the first check IsWaterTile as that is the first thing that should be checked for FlowRiver recursive calls. Swaps position with height_begin.
Change FlatSet to std::unordered_set which is faster at the contains function.
Change std::list to std::vector to be a queue, but do not pop items from it when advancing the queue. The tiles in it are ordered by insertion which is what's needed for the n-th tile to make lake_centre.
count is not required. It can be extracted from either the unordered set or the vector.
Swap the order of checks for determining the validity of lake_centre tile, making IsTileFlat and DistanceManhattan the last ones to check as I believe are the most computational.
2025-05-08 12:26:39 +01:00
SamuXarick 7ddbd1643e Codechange: Implementation of std::hash for StrongType::Typedef 2025-05-08 10:15:21 +01:00
11 changed files with 129 additions and 77 deletions

View File

@ -90,7 +90,7 @@ template <> SQInteger PushClassName<AIInfo, ScriptType::AI>(HSQUIRRELVM vm) { sq
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */ /* Remove the link to the real instance, else it might get deleted by RegisterAI() */
sq_setinstanceup(vm, 2, nullptr); sq_setinstanceup(vm, 2, nullptr);
/* Register the AI to the base system */ /* Register the AI to the base system */
info->GetScanner()->RegisterScript(info); info->GetScanner()->RegisterScript(std::unique_ptr<AIInfo>{info});
return 0; return 0;
} }
@ -136,22 +136,21 @@ bool AIInfo::CanLoadFromVersion(int version) const
/* static */ SQInteger AILibrary::Constructor(HSQUIRRELVM vm) /* static */ SQInteger AILibrary::Constructor(HSQUIRRELVM vm)
{ {
/* Create a new library */ /* Create a new library */
AILibrary *library = new AILibrary(); auto library = std::make_unique<AILibrary>();
SQInteger res = ScriptInfo::Constructor(vm, *library); SQInteger res = ScriptInfo::Constructor(vm, *library);
if (res != 0) { if (res != 0) {
delete library;
return res; return res;
} }
/* Cache the category */ /* Cache the category */
if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) { if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) {
delete library;
return SQ_ERROR; return SQ_ERROR;
} }
/* Register the Library to the base system */ /* Register the Library to the base system */
library->GetScanner()->RegisterScript(library); ScriptScanner *scanner = library->GetScanner();
scanner->RegisterScript(std::move(library));
return 0; return 0;
} }

View File

@ -29,7 +29,7 @@ void AIScannerInfo::Initialize()
{ {
ScriptScanner::Initialize("AIScanner"); ScriptScanner::Initialize("AIScanner");
ScriptAllocatorScope alloc_scope(this->engine); ScriptAllocatorScope alloc_scope(this->engine.get());
/* Create the dummy AI */ /* Create the dummy AI */
this->main_script = "%_dummy"; this->main_script = "%_dummy";

View File

@ -158,4 +158,31 @@ namespace StrongType {
}; };
} }
/**
* Implementation of std::hash for StrongType::Typedef.
*
* This specialization of std::hash allows hashing of StrongType::Typedef instances
* by leveraging the hash of the base type.
*
* Example Usage:
* using MyType = StrongType::Typedef<int, struct MyTypeTag>;
* std::unordered_map<MyType, std::string> my_map;
*
* @tparam TBaseType The underlying type of the StrongType::Typedef.
* @tparam TProperties Additional properties for the StrongType::Typedef.
*/
template <typename TBaseType, typename... TProperties>
struct std::hash<StrongType::Typedef<TBaseType, TProperties...>> {
/**
* Computes the hash value for a StrongType::Typedef instance.
*
* @param t The StrongType::Typedef instance to hash.
* @return The hash value of the base type of t.
*/
std::size_t operator()(const StrongType::Typedef<TBaseType, TProperties...> &t) const noexcept
{
return std::hash<TBaseType>()(t.base());
}
};
#endif /* STRONG_TYPEDEF_TYPE_HPP */ #endif /* STRONG_TYPEDEF_TYPE_HPP */

View File

@ -22,9 +22,10 @@
#include "safeguards.h" #include "safeguards.h"
/** Default heights for the different sizes of fonts. */ /** Default unscaled heights for the different sizes of fonts. */
static const int _default_font_height[FS_END] = {10, 6, 18, 10}; /* static */ const int FontCache::DEFAULT_FONT_HEIGHT[FS_END] = {10, 6, 18, 10};
static const int _default_font_ascender[FS_END] = { 8, 5, 15, 8}; /** Default unscaled ascenders for the different sizes of fonts. */
/* static */ const int FontCache::DEFAULT_FONT_ASCENDER[FS_END] = {8, 5, 15, 8};
FontCacheSettings _fcsettings; FontCacheSettings _fcsettings;
@ -32,8 +33,7 @@ FontCacheSettings _fcsettings;
* Create a new font cache. * Create a new font cache.
* @param fs The size of the font. * @param fs The size of the font.
*/ */
FontCache::FontCache(FontSize fs) : parent(FontCache::Get(fs)), fs(fs), height(_default_font_height[fs]), FontCache::FontCache(FontSize fs) : parent(FontCache::Get(fs)), fs(fs)
ascender(_default_font_ascender[fs]), descender(_default_font_ascender[fs] - _default_font_height[fs])
{ {
assert(this->parent == nullptr || this->fs == this->parent->fs); assert(this->parent == nullptr || this->fs == this->parent->fs);
FontCache::caches[this->fs] = this; FontCache::caches[this->fs] = this;
@ -50,7 +50,7 @@ FontCache::~FontCache()
int FontCache::GetDefaultFontHeight(FontSize fs) int FontCache::GetDefaultFontHeight(FontSize fs)
{ {
return _default_font_height[fs]; return FontCache::DEFAULT_FONT_HEIGHT[fs];
} }
/** /**

View File

@ -23,9 +23,9 @@ protected:
static FontCache *caches[FS_END]; ///< All the font caches. static FontCache *caches[FS_END]; ///< All the font caches.
FontCache *parent; ///< The parent of this font cache. FontCache *parent; ///< The parent of this font cache.
const FontSize fs; ///< The size of the font. const FontSize fs; ///< The size of the font.
int height; ///< The height of the font. int height = 0; ///< The height of the font.
int ascender; ///< The ascender value of the font. int ascender = 0; ///< The ascender value of the font.
int descender; ///< The descender value of the font. int descender = 0; ///< The descender value of the font.
public: public:
FontCache(FontSize fs); FontCache(FontSize fs);
@ -33,6 +33,11 @@ public:
static void InitializeFontCaches(); static void InitializeFontCaches();
/** Default unscaled font heights. */
static const int DEFAULT_FONT_HEIGHT[FS_END];
/** Default unscaled font ascenders. */
static const int DEFAULT_FONT_ASCENDER[FS_END];
static int GetDefaultFontHeight(FontSize fs); static int GetDefaultFontHeight(FontSize fs);
/** /**

View File

@ -78,7 +78,7 @@ template <> SQInteger PushClassName<GameInfo, ScriptType::GS>(HSQUIRRELVM vm) {
/* Remove the link to the real instance, else it might get deleted by RegisterGame() */ /* Remove the link to the real instance, else it might get deleted by RegisterGame() */
sq_setinstanceup(vm, 2, nullptr); sq_setinstanceup(vm, 2, nullptr);
/* Register the Game to the base system */ /* Register the Game to the base system */
info->GetScanner()->RegisterScript(info); info->GetScanner()->RegisterScript(std::unique_ptr<GameInfo>{info});
return 0; return 0;
} }
@ -106,22 +106,21 @@ bool GameInfo::CanLoadFromVersion(int version) const
/* static */ SQInteger GameLibrary::Constructor(HSQUIRRELVM vm) /* static */ SQInteger GameLibrary::Constructor(HSQUIRRELVM vm)
{ {
/* Create a new library */ /* Create a new library */
GameLibrary *library = new GameLibrary(); auto library = std::make_unique<GameLibrary>();
SQInteger res = ScriptInfo::Constructor(vm, *library); SQInteger res = ScriptInfo::Constructor(vm, *library);
if (res != 0) { if (res != 0) {
delete library;
return res; return res;
} }
/* Cache the category */ /* Cache the category */
if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) { if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) {
delete library;
return SQ_ERROR; return SQ_ERROR;
} }
/* Register the Library to the base system */ /* Register the Library to the base system */
library->GetScanner()->RegisterScript(library); ScriptScanner *scanner = library->GetScanner();
scanner->RegisterScript(std::move(library));
return 0; return 0;
} }

View File

@ -92,8 +92,8 @@ GameLibrary *GameScannerLibrary::FindLibrary(const std::string &library, int ver
std::string library_name = fmt::format("{}.{}", library, version); std::string library_name = fmt::format("{}.{}", library, version);
/* Check if the library + version exists */ /* Check if the library + version exists */
ScriptInfoList::iterator it = this->info_list.find(library_name); auto it = this->info_list.find(library_name);
if (it == this->info_list.end()) return nullptr; if (it == this->info_list.end()) return nullptr;
return static_cast<GameLibrary *>((*it).second); return static_cast<GameLibrary *>(it->second);
} }

View File

@ -27,7 +27,6 @@
#include "effectvehicle_func.h" #include "effectvehicle_func.h"
#include "landscape_type.h" #include "landscape_type.h"
#include "animated_tile_func.h" #include "animated_tile_func.h"
#include "core/flatset_type.hpp"
#include "core/random_func.hpp" #include "core/random_func.hpp"
#include "object_base.h" #include "object_base.h"
#include "company_func.h" #include "company_func.h"
@ -43,6 +42,8 @@
#include "table/strings.h" #include "table/strings.h"
#include "table/sprites.h" #include "table/sprites.h"
#include <unordered_set>
#include "safeguards.h" #include "safeguards.h"
extern const TileTypeProcs extern const TileTypeProcs
@ -1298,28 +1299,26 @@ public:
*/ */
static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length) static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length)
{ {
uint height_begin = TileHeight(begin);
if (IsWaterTile(begin)) { if (IsWaterTile(begin)) {
return { DistanceManhattan(spring, begin) > min_river_length, GetTileZ(begin) == 0 }; return { DistanceManhattan(spring, begin) > min_river_length, GetTileZ(begin) == 0 };
} }
FlatSet<TileIndex> marks; int height_begin = TileHeight(begin);
std::unordered_set<TileIndex> marks;
marks.insert(begin); marks.insert(begin);
/* Breadth first search for the closest tile we can flow down to. */ std::vector<TileIndex> queue;
std::list<TileIndex> queue;
queue.push_back(begin); queue.push_back(begin);
/* Breadth first search for the closest tile we can flow down to. */
bool found = false; bool found = false;
uint count = 0; // Number of tiles considered; to be used for lake location guessing.
TileIndex end; TileIndex end;
do { for (size_t i = 0; i != queue.size(); i++) {
end = queue.front(); end = queue[i];
queue.pop_front();
uint height_end = TileHeight(end); int height_end;
if (IsTileFlat(end) && (height_end < height_begin || (height_end == height_begin && IsWaterTile(end)))) { if (IsTileFlat(end, &height_end) && (height_end < height_begin || (height_end == height_begin && IsWaterTile(end)))) {
found = true; found = true;
break; break;
} }
@ -1328,31 +1327,29 @@ static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint
TileIndex t = end + TileOffsByDiagDir(d); TileIndex t = end + TileOffsByDiagDir(d);
if (IsValidTile(t) && !marks.contains(t) && FlowsDown(end, t)) { if (IsValidTile(t) && !marks.contains(t) && FlowsDown(end, t)) {
marks.insert(t); marks.insert(t);
count++;
queue.push_back(t); queue.push_back(t);
} }
} }
} while (!queue.empty()); }
bool main_river = false; bool main_river = false;
if (found) { if (found) {
/* Flow further down hill. */ /* Flow further down hill. */
std::tie(found, main_river) = FlowRiver(spring, end, min_river_length); std::tie(found, main_river) = FlowRiver(spring, end, min_river_length);
} else if (count > 32) { } else if (queue.size() > 32) {
/* Maybe we can make a lake. Find the Nth of the considered tiles. */ /* Maybe we can make a lake. Find the Nth of the considered tiles. */
auto cit = marks.cbegin(); TileIndex lake_centre = queue[RandomRange(static_cast<uint32_t>(queue.size()))];
std::advance(cit, RandomRange(count - 1)); int height_lake;
TileIndex lake_centre = *cit;
if (IsValidTile(lake_centre) && if (IsValidTile(lake_centre) &&
/* A river, or lake, can only be built on flat slopes. */
IsTileFlat(lake_centre) &&
/* We want the lake to be built at the height of the river. */
TileHeight(begin) == TileHeight(lake_centre) &&
/* We don't want the lake at the entry of the valley. */ /* We don't want the lake at the entry of the valley. */
lake_centre != begin && lake_centre != begin &&
/* We don't want lakes in the desert. */ /* We don't want lakes in the desert. */
(_settings_game.game_creation.landscape != LandscapeType::Tropic || GetTropicZone(lake_centre) != TROPICZONE_DESERT) && (_settings_game.game_creation.landscape != LandscapeType::Tropic || GetTropicZone(lake_centre) != TROPICZONE_DESERT) &&
/* A river, or lake, can only be built on flat slopes. */
IsTileFlat(lake_centre, &height_lake) &&
/* We want the lake to be built at the height of the river. */
height_lake == height_begin &&
/* We only want a lake if the river is long enough. */ /* We only want a lake if the river is long enough. */
DistanceManhattan(spring, lake_centre) > min_river_length) { DistanceManhattan(spring, lake_centre) > min_river_length) {
end = lake_centre; end = lake_centre;
@ -1362,7 +1359,7 @@ static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint
/* Run the loop twice, so artefacts from going circular in one direction get (mostly) hidden. */ /* Run the loop twice, so artefacts from going circular in one direction get (mostly) hidden. */
for (uint loops = 0; loops < 2; ++loops) { for (uint loops = 0; loops < 2; ++loops) {
for (auto tile : SpiralTileSequence(lake_centre, diameter)) { for (auto tile : SpiralTileSequence(lake_centre, diameter)) {
MakeLake(tile, height_begin); MakeLake(tile, height_lake);
} }
} }
@ -1370,7 +1367,6 @@ static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint
} }
} }
marks.clear();
if (found) RiverBuilder::Exec(begin, end, spring, main_river); if (found) RiverBuilder::Exec(begin, end, spring, main_river);
return { found, main_river }; return { found, main_river };
} }

View File

@ -44,10 +44,7 @@ bool ScriptScanner::AddFile(const std::string &filename, size_t, const std::stri
return true; return true;
} }
ScriptScanner::ScriptScanner() : ScriptScanner::ScriptScanner() = default;
engine(nullptr)
{
}
void ScriptScanner::ResetEngine() void ScriptScanner::ResetEngine()
{ {
@ -58,7 +55,7 @@ void ScriptScanner::ResetEngine()
void ScriptScanner::Initialize(std::string_view name) void ScriptScanner::Initialize(std::string_view name)
{ {
this->engine = new Squirrel(name); this->engine = std::make_unique<Squirrel>(name);
this->RescanDir(); this->RescanDir();
@ -68,8 +65,6 @@ void ScriptScanner::Initialize(std::string_view name)
ScriptScanner::~ScriptScanner() ScriptScanner::~ScriptScanner()
{ {
this->Reset(); this->Reset();
delete this->engine;
} }
void ScriptScanner::RescanDir() void ScriptScanner::RescanDir()
@ -83,15 +78,12 @@ void ScriptScanner::RescanDir()
void ScriptScanner::Reset() void ScriptScanner::Reset()
{ {
for (const auto &item : this->info_list) {
delete item.second;
}
this->info_list.clear(); this->info_list.clear();
this->info_single_list.clear(); this->info_single_list.clear();
this->info_vector.clear();
} }
void ScriptScanner::RegisterScript(ScriptInfo *info) void ScriptScanner::RegisterScript(std::unique_ptr<ScriptInfo> &&info)
{ {
std::string script_original_name = this->GetScriptName(*info); std::string script_original_name = this->GetScriptName(*info);
std::string script_name = fmt::format("{}.{}", script_original_name, info->GetVersion()); std::string script_name = fmt::format("{}.{}", script_original_name, info->GetVersion());
@ -99,7 +91,6 @@ void ScriptScanner::RegisterScript(ScriptInfo *info)
/* Check if GetShortName follows the rules */ /* Check if GetShortName follows the rules */
if (info->GetShortName().size() != 4) { if (info->GetShortName().size() != 4) {
Debug(script, 0, "The script '{}' returned a string from GetShortName() which is not four characters. Unable to load the script.", info->GetName()); Debug(script, 0, "The script '{}' returned a string from GetShortName() which is not four characters. Unable to load the script.", info->GetName());
delete info;
return; return;
} }
@ -111,7 +102,6 @@ void ScriptScanner::RegisterScript(ScriptInfo *info)
#else #else
if (it->second->GetMainScript() == info->GetMainScript()) { if (it->second->GetMainScript() == info->GetMainScript()) {
#endif #endif
delete info;
return; return;
} }
@ -120,20 +110,20 @@ void ScriptScanner::RegisterScript(ScriptInfo *info)
Debug(script, 1, " 2: {}", info->GetMainScript()); Debug(script, 1, " 2: {}", info->GetMainScript());
Debug(script, 1, "The first is taking precedence."); Debug(script, 1, "The first is taking precedence.");
delete info;
return; return;
} }
this->info_list[script_name] = info; ScriptInfo *script_info = this->info_vector.emplace_back(std::move(info)).get();
this->info_list[script_name] = script_info;
if (!info->IsDeveloperOnly() || _settings_client.gui.ai_developer_tools) { if (!script_info->IsDeveloperOnly() || _settings_client.gui.ai_developer_tools) {
/* Add the script to the 'unique' script list, where only the highest version /* Add the script to the 'unique' script list, where only the highest version
* of the script is registered. */ * of the script is registered. */
auto it = this->info_single_list.find(script_original_name); auto it = this->info_single_list.find(script_original_name);
if (it == this->info_single_list.end()) { if (it == this->info_single_list.end()) {
this->info_single_list[script_original_name] = info; this->info_single_list[script_original_name] = script_info;
} else if (it->second->GetVersion() < info->GetVersion()) { } else if (it->second->GetVersion() < script_info->GetVersion()) {
it->second = info; it->second = script_info;
} }
} }
} }
@ -195,17 +185,17 @@ struct ScriptFileChecksumCreator : FileScanner {
* @param info The script to get the shortname and md5 sum from. * @param info The script to get the shortname and md5 sum from.
* @return True iff they're the same. * @return True iff they're the same.
*/ */
static bool IsSameScript(const ContentInfo &ci, bool md5sum, ScriptInfo *info, Subdirectory dir) static bool IsSameScript(const ContentInfo &ci, bool md5sum, const ScriptInfo &info, Subdirectory dir)
{ {
uint32_t id = 0; uint32_t id = 0;
auto str = std::string_view{info->GetShortName()}.substr(0, 4); auto str = std::string_view{info.GetShortName()}.substr(0, 4);
for (size_t j = 0; j < str.size(); j++) id |= static_cast<uint8_t>(str[j]) << (8 * j); for (size_t j = 0; j < str.size(); j++) id |= static_cast<uint8_t>(str[j]) << (8 * j);
if (id != ci.unique_id) return false; if (id != ci.unique_id) return false;
if (!md5sum) return true; if (!md5sum) return true;
ScriptFileChecksumCreator checksum(dir); ScriptFileChecksumCreator checksum(dir);
const auto &tar_filename = info->GetTarFile(); const auto &tar_filename = info.GetTarFile();
TarList::iterator iter; TarList::iterator iter;
if (!tar_filename.empty() && (iter = _tar_list[dir].find(tar_filename)) != _tar_list[dir].end()) { if (!tar_filename.empty() && (iter = _tar_list[dir].find(tar_filename)) != _tar_list[dir].end()) {
/* The main script is in a tar file, so find all files that /* The main script is in a tar file, so find all files that
@ -224,7 +214,7 @@ static bool IsSameScript(const ContentInfo &ci, bool md5sum, ScriptInfo *info, S
/* There'll always be at least 1 path separator character in a script /* There'll always be at least 1 path separator character in a script
* main script name as the search algorithm requires the main script to * main script name as the search algorithm requires the main script to
* be in a subdirectory of the script directory; so <dir>/<path>/main.nut. */ * be in a subdirectory of the script directory; so <dir>/<path>/main.nut. */
const std::string &main_script = info->GetMainScript(); const std::string &main_script = info.GetMainScript();
std::string path = main_script.substr(0, main_script.find_last_of(PATHSEPCHAR)); std::string path = main_script.substr(0, main_script.find_last_of(PATHSEPCHAR));
checksum.Scan(".nut", path); checksum.Scan(".nut", path);
} }
@ -235,7 +225,7 @@ static bool IsSameScript(const ContentInfo &ci, bool md5sum, ScriptInfo *info, S
bool ScriptScanner::HasScript(const ContentInfo &ci, bool md5sum) bool ScriptScanner::HasScript(const ContentInfo &ci, bool md5sum)
{ {
for (const auto &item : this->info_list) { for (const auto &item : this->info_list) {
if (IsSameScript(ci, md5sum, item.second, this->GetDirectory())) return true; if (IsSameScript(ci, md5sum, *item.second, this->GetDirectory())) return true;
} }
return false; return false;
} }
@ -243,7 +233,7 @@ bool ScriptScanner::HasScript(const ContentInfo &ci, bool md5sum)
std::optional<std::string_view> ScriptScanner::FindMainScript(const ContentInfo &ci, bool md5sum) std::optional<std::string_view> ScriptScanner::FindMainScript(const ContentInfo &ci, bool md5sum)
{ {
for (const auto &item : this->info_list) { for (const auto &item : this->info_list) {
if (IsSameScript(ci, md5sum, item.second, this->GetDirectory())) return item.second->GetMainScript(); if (IsSameScript(ci, md5sum, *item.second, this->GetDirectory())) return item.second->GetMainScript();
} }
return std::nullopt; return std::nullopt;
} }

View File

@ -13,7 +13,7 @@
#include "../fileio_func.h" #include "../fileio_func.h"
#include "../string_func.h" #include "../string_func.h"
typedef std::map<std::string, class ScriptInfo *, CaseInsensitiveComparator> ScriptInfoList; ///< Type for the list of scripts. using ScriptInfoList = std::map<std::string, class ScriptInfo *, CaseInsensitiveComparator>; ///< Type for the list of scripts.
/** Scanner to help finding scripts. */ /** Scanner to help finding scripts. */
class ScriptScanner : public FileScanner { class ScriptScanner : public FileScanner {
@ -26,7 +26,7 @@ public:
/** /**
* Get the engine of the main squirrel handler (it indexes all available scripts). * Get the engine of the main squirrel handler (it indexes all available scripts).
*/ */
class Squirrel *GetEngine() { return this->engine; } class Squirrel *GetEngine() { return this->engine.get(); }
/** /**
* Get the current main script the ScanDir is currently tracking. * Get the current main script the ScanDir is currently tracking.
@ -51,7 +51,7 @@ public:
/** /**
* Register a ScriptInfo to the scanner. * Register a ScriptInfo to the scanner.
*/ */
void RegisterScript(class ScriptInfo *info); void RegisterScript(std::unique_ptr<class ScriptInfo> &&info);
/** /**
* Get the list of registered scripts to print on the console. * Get the list of registered scripts to print on the console.
@ -84,11 +84,13 @@ public:
void RescanDir(); void RescanDir();
protected: protected:
class Squirrel *engine; ///< The engine we're scanning with. std::unique_ptr<class Squirrel> engine; ///< The engine we're scanning with.
std::string main_script; ///< The full path of the script. std::string main_script; ///< The full path of the script.
std::string tar_file; ///< If, which tar file the script was in. std::string tar_file; ///< If, which tar file the script was in.
ScriptInfoList info_list; ///< The list of all script. std::vector<std::unique_ptr<ScriptInfo>> info_vector;
ScriptInfoList info_list; ///< The list of all script.
ScriptInfoList info_single_list; ///< The list of all unique script. The best script (highest version) is shown. ScriptInfoList info_single_list; ///< The list of all unique script. The best script (highest version) is shown.
/** /**

View File

@ -401,6 +401,40 @@ static void CancelIMEComposition(HWND hwnd)
HandleTextInput({}, true); HandleTextInput({}, true);
} }
#if defined(_MSC_VER) && defined(NTDDI_WIN10_RS4)
/* We only use WinRT functions on Windows 10 or later. Unfortunately, newer Windows SDKs are now
* linking the two functions below directly instead of using dynamic linking as previously.
* To avoid any runtime linking errors on Windows 7 or older, we stub in our own dynamic
* linking trampoline. */
static LibraryLoader _combase("combase.dll");
extern "C" int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(int32_t error, void *message, void *languageException) noexcept
{
typedef BOOL(WINAPI *PFNRoOriginateLanguageException)(int32_t, void *, void *);
static PFNRoOriginateLanguageException RoOriginateLanguageException = _combase.GetFunction("RoOriginateLanguageException");
if (RoOriginateLanguageException != nullptr) {
return RoOriginateLanguageException(error, message, languageException);
} else {
return TRUE;
}
}
extern "C" int32_t __stdcall WINRT_IMPL_RoGetActivationFactory(void *classId, winrt::guid const &iid, void **factory) noexcept
{
typedef BOOL(WINAPI *PFNRoGetActivationFactory)(void *, winrt::guid const &, void **);
static PFNRoGetActivationFactory RoGetActivationFactory = _combase.GetFunction("RoGetActivationFactory");
if (RoGetActivationFactory != nullptr) {
return RoGetActivationFactory(classId, iid, factory);
} else {
*factory = nullptr;
return winrt::impl::error_class_not_available;
}
}
#endif
static bool IsDarkModeEnabled() static bool IsDarkModeEnabled()
{ {
/* Only build if SDK is Windows 10 1803 or later. */ /* Only build if SDK is Windows 10 1803 or later. */