mirror of https://github.com/WerWolv/ImHex
Compare commits
34 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
77c1ee3e7a | |
|
|
4be2c33985 | |
|
|
3034d79373 | |
|
|
e7daa586ba | |
|
|
3f4bdfdf61 | |
|
|
ab5860dc9a | |
|
|
53b2347358 | |
|
|
a195179101 | |
|
|
fdccc55805 | |
|
|
55dce338b2 | |
|
|
03c217addb | |
|
|
a3a3f52b48 | |
|
|
477b284041 | |
|
|
b52495bc33 | |
|
|
46ed451712 | |
|
|
963afdce96 | |
|
|
3f18a9a536 | |
|
|
64b226e12d | |
|
|
b74dc3d8b9 | |
|
|
9668a885e8 | |
|
|
b7afbf4a74 | |
|
|
4784a82d51 | |
|
|
a1ff1af754 | |
|
|
5c6b20c0ec | |
|
|
79af360822 | |
|
|
fb23708220 | |
|
|
93f6ab25e6 | |
|
|
6faefed4f4 | |
|
|
6a159be861 | |
|
|
d7b43b54f9 | |
|
|
1a92425995 | |
|
|
347bdd9508 | |
|
|
b80e8b63c9 | |
|
|
621d529682 |
|
|
@ -28,7 +28,7 @@
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "lib/third_party/lunasvg"]
|
[submodule "lib/third_party/lunasvg"]
|
||||||
path = lib/third_party/lunasvg
|
path = lib/third_party/lunasvg
|
||||||
url = https://github.com/sammycage/lunasvg
|
url = https://github.com/WerWolv/lunasvg
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
|
|
||||||
[submodule "lib/external/libromfs"]
|
[submodule "lib/external/libromfs"]
|
||||||
|
|
|
||||||
|
|
@ -262,3 +262,10 @@ function js_resizeCanvas() {
|
||||||
canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
|
canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
|
||||||
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
|
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent some default browser shortcuts from preventing ImHex ones to work
|
||||||
|
document.addEventListener('keydown', e => {
|
||||||
|
if (e.ctrlKey) {
|
||||||
|
if (e.which == 83) e.preventDefault();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
@ -38,6 +38,7 @@ set(LIBIMHEX_SOURCES
|
||||||
source/helpers/debugging.cpp
|
source/helpers/debugging.cpp
|
||||||
source/helpers/default_paths.cpp
|
source/helpers/default_paths.cpp
|
||||||
source/helpers/imgui_hooks.cpp
|
source/helpers/imgui_hooks.cpp
|
||||||
|
source/helpers/semantic_version.cpp
|
||||||
|
|
||||||
source/test/tests.cpp
|
source/test/tests.cpp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@ namespace hex {
|
||||||
EVENT_DEF(EventOSThemeChanged);
|
EVENT_DEF(EventOSThemeChanged);
|
||||||
EVENT_DEF(EventDPIChanged, float, float);
|
EVENT_DEF(EventDPIChanged, float, float);
|
||||||
EVENT_DEF(EventWindowFocused, bool);
|
EVENT_DEF(EventWindowFocused, bool);
|
||||||
|
EVENT_DEF(EventImHexUpdated, SemanticVersion, SemanticVersion);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when the provider is created.
|
* @brief Called when the provider is created.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <hex.hpp>
|
#include <hex.hpp>
|
||||||
#include <hex/api/localization_manager.hpp>
|
#include <hex/api/localization_manager.hpp>
|
||||||
|
#include <hex/helpers/semantic_version.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
@ -618,7 +619,7 @@ namespace hex {
|
||||||
* @brief Gets the current ImHex version
|
* @brief Gets the current ImHex version
|
||||||
* @return ImHex version
|
* @return ImHex version
|
||||||
*/
|
*/
|
||||||
std::string getImHexVersion(bool withBuildType = true);
|
SemanticVersion getImHexVersion();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the current git commit hash
|
* @brief Gets the current git commit hash
|
||||||
|
|
@ -695,6 +696,13 @@ namespace hex {
|
||||||
*/
|
*/
|
||||||
void* getLibImHexModuleHandle();
|
void* getLibImHexModuleHandle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new migration routine that will be executed when upgrading from a lower version than specified in migrationVersion
|
||||||
|
* @param migrationVersion Upgrade point version
|
||||||
|
* @param function Function to run
|
||||||
|
*/
|
||||||
|
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -153,12 +153,7 @@ namespace hex {
|
||||||
constexpr static auto SUPER = Key(static_cast<Keys>(0x0800'0000));
|
constexpr static auto SUPER = Key(static_cast<Keys>(0x0800'0000));
|
||||||
constexpr static auto CurrentView = Key(static_cast<Keys>(0x1000'0000));
|
constexpr static auto CurrentView = Key(static_cast<Keys>(0x1000'0000));
|
||||||
constexpr static auto AllowWhileTyping = Key(static_cast<Keys>(0x2000'0000));
|
constexpr static auto AllowWhileTyping = Key(static_cast<Keys>(0x2000'0000));
|
||||||
|
constexpr static auto CTRLCMD = Key(static_cast<Keys>(0x4000'0000));
|
||||||
#if defined (OS_MACOS)
|
|
||||||
constexpr static auto CTRLCMD = SUPER;
|
|
||||||
#else
|
|
||||||
constexpr static auto CTRLCMD = CTRL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class Shortcut {
|
class Shortcut {
|
||||||
public:
|
public:
|
||||||
|
|
@ -255,6 +250,8 @@ namespace hex {
|
||||||
static void resumeShortcuts();
|
static void resumeShortcuts();
|
||||||
static void pauseShortcuts();
|
static void pauseShortcuts();
|
||||||
|
|
||||||
|
static void enableMacOSMode();
|
||||||
|
|
||||||
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
|
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
|
||||||
|
|
||||||
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
|
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <hex.hpp>
|
||||||
|
|
||||||
|
#include <compare>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace hex {
|
||||||
|
|
||||||
|
class SemanticVersion {
|
||||||
|
public:
|
||||||
|
SemanticVersion() = default;
|
||||||
|
SemanticVersion(std::string version);
|
||||||
|
SemanticVersion(std::string_view version);
|
||||||
|
SemanticVersion(const char *version);
|
||||||
|
|
||||||
|
std::strong_ordering operator<=>(const SemanticVersion &) const;
|
||||||
|
bool operator==(const SemanticVersion &other) const;
|
||||||
|
|
||||||
|
u32 major() const;
|
||||||
|
u32 minor() const;
|
||||||
|
u32 patch() const;
|
||||||
|
bool nightly() const;
|
||||||
|
const std::string& buildType() const;
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
std::string get(bool withBuildType = true) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> m_parts;
|
||||||
|
std::string m_buildType;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,10 @@
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#if defined(OS_WEB)
|
||||||
|
#include <emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
static AutoReset<std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>> s_achievements;
|
static AutoReset<std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>> s_achievements;
|
||||||
|
|
@ -215,7 +219,16 @@ namespace hex {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto json = nlohmann::json::parse(file.readString());
|
#if defined(OS_WEB)
|
||||||
|
auto data = (char *) MAIN_THREAD_EM_ASM_INT({
|
||||||
|
let data = localStorage.getItem("achievements");
|
||||||
|
return data ? stringToNewUTF8(data) : null;
|
||||||
|
});
|
||||||
|
#else
|
||||||
|
auto data = file.readString();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto json = nlohmann::json::parse(data);
|
||||||
|
|
||||||
for (const auto &[categoryName, achievements] : getAchievements()) {
|
for (const auto &[categoryName, achievements] : getAchievements()) {
|
||||||
for (const auto &[achievementName, achievement] : achievements) {
|
for (const auto &[achievementName, achievement] : achievements) {
|
||||||
|
|
@ -254,6 +267,12 @@ namespace hex {
|
||||||
if (json.empty())
|
if (json.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if defined(OS_WEB)
|
||||||
|
auto data = json.dump();
|
||||||
|
MAIN_THREAD_EM_ASM({
|
||||||
|
localStorage.setItem("achievements", UTF8ToString($0));
|
||||||
|
}, data.c_str());
|
||||||
|
#else
|
||||||
for (const auto &directory : paths::Config.write()) {
|
for (const auto &directory : paths::Config.write()) {
|
||||||
auto path = directory / AchievementsFile;
|
auto path = directory / AchievementsFile;
|
||||||
|
|
||||||
|
|
@ -264,6 +283,7 @@ namespace hex {
|
||||||
file.writeString(json.dump(4));
|
file.writeString(json.dump(4));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -630,7 +630,7 @@ namespace hex {
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.addDefine("__IMHEX__");
|
runtime.addDefine("__IMHEX__");
|
||||||
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion());
|
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
|
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
|
||||||
|
|
|
||||||
|
|
@ -645,6 +645,14 @@ namespace hex {
|
||||||
return hex::getContainingModule(reinterpret_cast<void*>(&getLibImHexModuleHandle));
|
return hex::getContainingModule(reinterpret_cast<void*>(&getLibImHexModuleHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function) {
|
||||||
|
EventImHexUpdated::subscribe([migrationVersion, function](const SemanticVersion &oldVersion, const SemanticVersion &newVersion) {
|
||||||
|
if (oldVersion < migrationVersion && newVersion >= migrationVersion) {
|
||||||
|
function();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::map<std::string, std::string>& getInitArguments() {
|
const std::map<std::string, std::string>& getInitArguments() {
|
||||||
return *impl::s_initArguments;
|
return *impl::s_initArguments;
|
||||||
|
|
@ -794,16 +802,11 @@ namespace hex {
|
||||||
return { { name, version } };
|
return { { name, version } };
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getImHexVersion(bool withBuildType) {
|
SemanticVersion getImHexVersion() {
|
||||||
#if defined IMHEX_VERSION
|
#if defined IMHEX_VERSION
|
||||||
if (withBuildType) {
|
return SemanticVersion(IMHEX_VERSION);
|
||||||
return IMHEX_VERSION;
|
|
||||||
} else {
|
|
||||||
auto version = std::string(IMHEX_VERSION);
|
|
||||||
return version.substr(0, version.find('-'));
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
return "Unknown";
|
return {};
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -837,7 +840,7 @@ namespace hex {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNightlyBuild() {
|
bool isNightlyBuild() {
|
||||||
return getImHexVersion(false).ends_with("WIP");
|
return getImHexVersion().nightly();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateImHex(UpdateType updateType) {
|
bool updateImHex(UpdateType updateType) {
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ namespace hex {
|
||||||
|
|
||||||
|
|
||||||
const auto requestedVersion = getCompatibleVersion();
|
const auto requestedVersion = getCompatibleVersion();
|
||||||
const auto imhexVersion = ImHexApi::System::getImHexVersion();
|
const auto imhexVersion = ImHexApi::System::getImHexVersion().get();
|
||||||
if (!imhexVersion.starts_with(requestedVersion)) {
|
if (!imhexVersion.starts_with(requestedVersion)) {
|
||||||
if (requestedVersion.empty()) {
|
if (requestedVersion.empty()) {
|
||||||
log::warn("Plugin '{}' did not specify a compatible version, assuming it is compatible with the current version of ImHex.", wolv::util::toUTF8String(m_path.filename()));
|
log::warn("Plugin '{}' did not specify a compatible version, assuming it is compatible with the current version of ImHex.", wolv::util::toUTF8String(m_path.filename()));
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ namespace hex {
|
||||||
AutoReset<std::map<Shortcut, ShortcutManager::ShortcutEntry>> s_globalShortcuts;
|
AutoReset<std::map<Shortcut, ShortcutManager::ShortcutEntry>> s_globalShortcuts;
|
||||||
std::atomic<bool> s_paused;
|
std::atomic<bool> s_paused;
|
||||||
std::optional<Shortcut> s_prevShortcut;
|
std::optional<Shortcut> s_prevShortcut;
|
||||||
|
bool s_macOSMode = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,22 +79,14 @@ namespace hex {
|
||||||
std::string Shortcut::toString() const {
|
std::string Shortcut::toString() const {
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
#if defined(OS_MACOS)
|
const auto CTRL_NAME = s_macOSMode ? "⌃" : "CTRL";
|
||||||
constexpr static auto CTRL_NAME = "⌃";
|
const auto ALT_NAME = s_macOSMode ? "⌥" : "ALT";
|
||||||
constexpr static auto ALT_NAME = "⌥";
|
const auto SHIFT_NAME = s_macOSMode ? "⇧" : "SHIFT";
|
||||||
constexpr static auto SHIFT_NAME = "⇧";
|
const auto SUPER_NAME = s_macOSMode ? "⌘" : "SUPER";
|
||||||
constexpr static auto SUPER_NAME = "⌘";
|
const auto Concatination = s_macOSMode ? " " : " + ";
|
||||||
constexpr static auto Concatination = " ";
|
|
||||||
#else
|
|
||||||
constexpr static auto CTRL_NAME = "CTRL";
|
|
||||||
constexpr static auto ALT_NAME = "ALT";
|
|
||||||
constexpr static auto SHIFT_NAME = "SHIFT";
|
|
||||||
constexpr static auto SUPER_NAME = "SUPER";
|
|
||||||
constexpr static auto Concatination = " + ";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto keys = m_keys;
|
auto keys = m_keys;
|
||||||
if (keys.erase(CTRL) > 0) {
|
if (keys.erase(CTRL) > 0 || (!s_macOSMode && keys.erase(CTRLCMD) > 0)) {
|
||||||
result += CTRL_NAME;
|
result += CTRL_NAME;
|
||||||
result += Concatination;
|
result += Concatination;
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +98,7 @@ namespace hex {
|
||||||
result += SHIFT_NAME;
|
result += SHIFT_NAME;
|
||||||
result += Concatination;
|
result += Concatination;
|
||||||
}
|
}
|
||||||
if (keys.erase(SUPER) > 0) {
|
if (keys.erase(SUPER) > 0 || (s_macOSMode && keys.erase(CTRLCMD) > 0)) {
|
||||||
result += SUPER_NAME;
|
result += SUPER_NAME;
|
||||||
result += Concatination;
|
result += Concatination;
|
||||||
}
|
}
|
||||||
|
|
@ -267,13 +260,13 @@ namespace hex {
|
||||||
Shortcut pressedShortcut;
|
Shortcut pressedShortcut;
|
||||||
|
|
||||||
if (ctrl)
|
if (ctrl)
|
||||||
pressedShortcut += CTRL;
|
pressedShortcut += s_macOSMode ? CTRL : CTRLCMD;
|
||||||
if (alt)
|
if (alt)
|
||||||
pressedShortcut += ALT;
|
pressedShortcut += ALT;
|
||||||
if (shift)
|
if (shift)
|
||||||
pressedShortcut += SHIFT;
|
pressedShortcut += SHIFT;
|
||||||
if (super)
|
if (super)
|
||||||
pressedShortcut += SUPER;
|
pressedShortcut += s_macOSMode ? CTRLCMD : SUPER;
|
||||||
if (focused)
|
if (focused)
|
||||||
pressedShortcut += CurrentView;
|
pressedShortcut += CurrentView;
|
||||||
if (ImGui::GetIO().WantTextInput)
|
if (ImGui::GetIO().WantTextInput)
|
||||||
|
|
@ -387,4 +380,9 @@ namespace hex {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShortcutManager::enableMacOSMode() {
|
||||||
|
s_macOSMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -33,6 +33,13 @@ namespace hex {
|
||||||
idStack.push_back(0);
|
idStack.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add(const char *string) {
|
||||||
|
const ImGuiID seed = idStack.back();
|
||||||
|
const ImGuiID id = ImHashStr(string, 0, seed);
|
||||||
|
|
||||||
|
idStack.push_back(id);
|
||||||
|
}
|
||||||
|
|
||||||
void add(const std::string &string) {
|
void add(const std::string &string) {
|
||||||
const ImGuiID seed = idStack.back();
|
const ImGuiID seed = idStack.back();
|
||||||
const ImGuiID id = ImHashStr(string.c_str(), string.length(), seed);
|
const ImGuiID id = ImHashStr(string.c_str(), string.length(), seed);
|
||||||
|
|
@ -87,6 +94,10 @@ namespace hex {
|
||||||
const auto element = hex::s_highlights->find(id);
|
const auto element = hex::s_highlights->find(id);
|
||||||
if (element != hex::s_highlights->end()) {
|
if (element != hex::s_highlights->end()) {
|
||||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||||
|
|
||||||
|
const auto window = ImGui::GetCurrentWindow();
|
||||||
|
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
|
||||||
|
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,13 @@ namespace hex::fs {
|
||||||
// Call callback that will write the file
|
// Call callback that will write the file
|
||||||
Module._fileBrowserCallback(stringToNewUTF8("/savedFiles/" + filename));
|
Module._fileBrowserCallback(stringToNewUTF8("/savedFiles/" + filename));
|
||||||
|
|
||||||
let data = FS.readFile("/savedFiles/" + filename);
|
let data;
|
||||||
|
try {
|
||||||
|
data = FS.readFile("/savedFiles/" + filename);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const reader = Object.assign(new FileReader(), {
|
const reader = Object.assign(new FileReader(), {
|
||||||
onload: () => {
|
onload: () => {
|
||||||
|
|
@ -191,6 +197,7 @@ namespace hex::fs {
|
||||||
else if (!validExtensions.empty())
|
else if (!validExtensions.empty())
|
||||||
path = "file." + validExtensions[0].spec;
|
path = "file." + validExtensions[0].spec;
|
||||||
|
|
||||||
|
std::fs::create_directory("/savedFiles");
|
||||||
callJs_saveFile(path.filename().string().c_str());
|
callJs_saveFile(path.filename().string().c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
#include <hex/helpers/fmt.hpp>
|
||||||
|
#include <hex/helpers/semantic_version.hpp>
|
||||||
|
#include <wolv/utils/string.hpp>
|
||||||
|
|
||||||
|
namespace hex {
|
||||||
|
|
||||||
|
SemanticVersion::SemanticVersion(const char *version) : SemanticVersion(std::string(version)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SemanticVersion::SemanticVersion(std::string_view version) : SemanticVersion(std::string(version.begin(), version.end())) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SemanticVersion::SemanticVersion(std::string version) {
|
||||||
|
if (version.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (version.starts_with("v"))
|
||||||
|
version = version.substr(1);
|
||||||
|
|
||||||
|
m_parts = wolv::util::splitString(version, ".");
|
||||||
|
|
||||||
|
if (m_parts.size() != 3 && m_parts.size() != 4) {
|
||||||
|
m_parts.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_parts.back().contains("-")) {
|
||||||
|
auto buildTypeParts = wolv::util::splitString(m_parts.back(), "-");
|
||||||
|
if (buildTypeParts.size() != 2) {
|
||||||
|
m_parts.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_parts.back() = buildTypeParts[0];
|
||||||
|
m_buildType = buildTypeParts[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SemanticVersion::major() const {
|
||||||
|
if (!isValid()) return 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return std::stoul(m_parts[0]);
|
||||||
|
} catch (...) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SemanticVersion::minor() const {
|
||||||
|
if (!isValid()) return 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return std::stoul(m_parts[1]);
|
||||||
|
} catch (...) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SemanticVersion::patch() const {
|
||||||
|
if (!isValid()) return 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return std::stoul(m_parts[2]);
|
||||||
|
} catch (...) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SemanticVersion::nightly() const {
|
||||||
|
if (!isValid()) return false;
|
||||||
|
|
||||||
|
return m_parts.size() == 4 && m_parts[3] == "WIP";
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& SemanticVersion::buildType() const {
|
||||||
|
return m_buildType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SemanticVersion::isValid() const {
|
||||||
|
return !m_parts.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SemanticVersion::operator==(const SemanticVersion& other) const {
|
||||||
|
return this->m_parts == other.m_parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::strong_ordering SemanticVersion::operator<=>(const SemanticVersion &other) const {
|
||||||
|
if (*this == other)
|
||||||
|
return std::strong_ordering::equivalent;
|
||||||
|
|
||||||
|
if (this->major() > other.major())
|
||||||
|
return std::strong_ordering::greater;
|
||||||
|
if (this->minor() > other.minor())
|
||||||
|
return std::strong_ordering::greater;
|
||||||
|
if (this->patch() > other.patch())
|
||||||
|
return std::strong_ordering::greater;
|
||||||
|
if (!this->nightly() && other.nightly())
|
||||||
|
return std::strong_ordering::greater;
|
||||||
|
|
||||||
|
return std::strong_ordering::less;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SemanticVersion::get(bool withBuildType) const {
|
||||||
|
if (!isValid()) return "";
|
||||||
|
|
||||||
|
auto result = wolv::util::combineStrings(m_parts, ".");
|
||||||
|
|
||||||
|
if (withBuildType && !m_buildType.empty())
|
||||||
|
result += hex::format("-{}", m_buildType);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0c9fce2ffefecfdce794e1859584e25877b7b592
|
Subproject commit 0e8aad961d66904cfda8d7cc894f6f6eee2d9f30
|
||||||
|
|
@ -307,6 +307,7 @@ public:
|
||||||
return text.empty() || text == "\n";
|
return text.empty() || text == "\n";
|
||||||
}
|
}
|
||||||
void SetTopLine();
|
void SetTopLine();
|
||||||
|
void SetScrollY();
|
||||||
void SetTextLines(const std::vector<std::string>& aLines);
|
void SetTextLines(const std::vector<std::string>& aLines);
|
||||||
std::vector<std::string> GetTextLines() const;
|
std::vector<std::string> GetTextLines() const;
|
||||||
|
|
||||||
|
|
@ -406,7 +407,7 @@ public:
|
||||||
void Cut();
|
void Cut();
|
||||||
void Paste();
|
void Paste();
|
||||||
void Delete();
|
void Delete();
|
||||||
int32_t GetPageSize() const;
|
float GetPageSize() const;
|
||||||
|
|
||||||
ImVec2 &GetCharAdvance() { return mCharAdvance; }
|
ImVec2 &GetCharAdvance() { return mCharAdvance; }
|
||||||
|
|
||||||
|
|
@ -600,8 +601,8 @@ private:
|
||||||
float mLineNumberFieldWidth = 0.0F;
|
float mLineNumberFieldWidth = 0.0F;
|
||||||
float mLongest = 0.0F;
|
float mLongest = 0.0F;
|
||||||
float mTextStart = 20.0F; // position (in pixels) where a code line starts relative to the left of the TextEditor.
|
float mTextStart = 20.0F; // position (in pixels) where a code line starts relative to the left of the TextEditor.
|
||||||
int mLeftMargin = 10;
|
float mLeftMargin = 10.0;
|
||||||
int mTopLine = 0;
|
float mTopLine = 0.0F;
|
||||||
bool mSetTopLine = false;
|
bool mSetTopLine = false;
|
||||||
bool mCursorPositionChanged = false;
|
bool mCursorPositionChanged = false;
|
||||||
bool mBreakPointsChanged = false;
|
bool mBreakPointsChanged = false;
|
||||||
|
|
@ -631,7 +632,9 @@ private:
|
||||||
float mSavedScrollY = 0;
|
float mSavedScrollY = 0;
|
||||||
float mShiftedScrollY = 0;
|
float mShiftedScrollY = 0;
|
||||||
float mScrollY = 0;
|
float mScrollY = 0;
|
||||||
int mNumberOfLinesDisplayed = 0;
|
float mScrollYIncrement = 0.0F;
|
||||||
|
bool mSetScrollY = false;
|
||||||
|
float mNumberOfLinesDisplayed = 0;
|
||||||
float mLastClick = -1.0F;
|
float mLastClick = -1.0F;
|
||||||
bool mShowCursor = true;
|
bool mShowCursor = true;
|
||||||
bool mShowLineNumbers = true;
|
bool mShowLineNumbers = true;
|
||||||
|
|
|
||||||
|
|
@ -311,6 +311,9 @@ TextEditor::Coordinates TextEditor::ScreenPosToCoordinates(const ImVec2 &aPositi
|
||||||
ImVec2 local(aPosition.x - origin.x, aPosition.y - origin.y);
|
ImVec2 local(aPosition.x - origin.x, aPosition.y - origin.y);
|
||||||
|
|
||||||
int lineNo = std::max(0, (int)floor(local.y / mCharAdvance.y));
|
int lineNo = std::max(0, (int)floor(local.y / mCharAdvance.y));
|
||||||
|
if (local.x < mCharAdvance.x)
|
||||||
|
return Coordinates(lineNo, 0);
|
||||||
|
local.x -= mCharAdvance.x;
|
||||||
|
|
||||||
int columnCoord = 0;
|
int columnCoord = 0;
|
||||||
|
|
||||||
|
|
@ -349,7 +352,7 @@ TextEditor::Coordinates TextEditor::ScreenPosToCoordinates(const ImVec2 &aPositi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SanitizeCoordinates(Coordinates(lineNo, columnCoord - (columnCoord != 0)));
|
return SanitizeCoordinates(Coordinates(lineNo, columnCoord));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditor::DeleteWordLeft() {
|
void TextEditor::DeleteWordLeft() {
|
||||||
|
|
@ -891,14 +894,16 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||||
ImVec2 cursorScreenPos = ImGui::GetCursorScreenPos();
|
ImVec2 cursorScreenPos = ImGui::GetCursorScreenPos();
|
||||||
ImVec2 position = lineNumbersStartPos;
|
ImVec2 position = lineNumbersStartPos;
|
||||||
auto scrollX = ImGui::GetScrollX();
|
auto scrollX = ImGui::GetScrollX();
|
||||||
|
if (mSetScrollY)
|
||||||
|
SetScrollY();
|
||||||
auto scrollY = ImGui::GetScrollY();
|
auto scrollY = ImGui::GetScrollY();
|
||||||
if (mSetTopLine)
|
if (mSetTopLine)
|
||||||
SetTopLine();
|
SetTopLine();
|
||||||
else
|
else
|
||||||
mTopLine = std::max<int>(0, std::floor((scrollY-mTopMargin) / mCharAdvance.y));
|
mTopLine = std::max<float>(0.0F, (scrollY-mTopMargin) / mCharAdvance.y);
|
||||||
auto lineNo = mTopLine;
|
auto lineNo = mTopLine;
|
||||||
int globalLineMax = mLines.size();
|
float globalLineMax = mLines.size();
|
||||||
auto lineMax = std::clamp(lineNo + mNumberOfLinesDisplayed, 0, globalLineMax - 1);
|
auto lineMax = std::clamp(lineNo + mNumberOfLinesDisplayed, 0.0F, globalLineMax-1.0F);
|
||||||
int totalDigitCount = std::floor(std::log10(globalLineMax)) + 1;
|
int totalDigitCount = std::floor(std::log10(globalLineMax)) + 1;
|
||||||
mLongest = GetLongestLineLength() * mCharAdvance.x;
|
mLongest = GetLongestLineLength() * mCharAdvance.x;
|
||||||
|
|
||||||
|
|
@ -906,7 +911,7 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||||
char buf[16];
|
char buf[16];
|
||||||
|
|
||||||
if (mShowLineNumbers)
|
if (mShowLineNumbers)
|
||||||
snprintf(buf, 16, " %d ", globalLineMax);
|
snprintf(buf, 16, " %d ", int(globalLineMax));
|
||||||
else
|
else
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
mTextStart = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf, nullptr, nullptr).x + mLeftMargin;
|
mTextStart = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf, nullptr, nullptr).x + mLeftMargin;
|
||||||
|
|
@ -915,7 +920,7 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||||
float spaceSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, " ", nullptr, nullptr).x;
|
float spaceSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, " ", nullptr, nullptr).x;
|
||||||
|
|
||||||
while (lineNo <= lineMax) {
|
while (lineNo <= lineMax) {
|
||||||
ImVec2 lineStartScreenPos = ImVec2(cursorScreenPos.x + mLeftMargin, cursorScreenPos.y + lineNo * mCharAdvance.y);
|
ImVec2 lineStartScreenPos = ImVec2(cursorScreenPos.x + mLeftMargin, mTopMargin + cursorScreenPos.y + std::floor(lineNo) * mCharAdvance.y);
|
||||||
ImVec2 textScreenPos = lineStartScreenPos;
|
ImVec2 textScreenPos = lineStartScreenPos;
|
||||||
|
|
||||||
auto &line = mLines[lineNo];
|
auto &line = mLines[lineNo];
|
||||||
|
|
@ -941,11 +946,8 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||||
ImVec2 vend(lineStartScreenPos.x + ssend, lineStartScreenPos.y + mCharAdvance.y);
|
ImVec2 vend(lineStartScreenPos.x + ssend, lineStartScreenPos.y + mCharAdvance.y);
|
||||||
drawList->AddRectFilled(vstart, vend, mPalette[(int)PaletteIndex::Selection]);
|
drawList->AddRectFilled(vstart, vend, mPalette[(int)PaletteIndex::Selection]);
|
||||||
}
|
}
|
||||||
float startPos = 0;
|
ImVec2 lineNoStartScreenPos = ImVec2(position.x, mTopMargin + cursorScreenPos.y + std::floor(lineNo) * mCharAdvance.y);
|
||||||
if (scrollY < mTopMargin)
|
auto start = ImVec2(lineNoStartScreenPos.x + mLineNumberFieldWidth, lineStartScreenPos.y);
|
||||||
startPos = mTopMargin - scrollY;
|
|
||||||
ImVec2 lineNoStartScreenPos = ImVec2(position.x, startPos + position.y + (lineNo - mTopLine) * mCharAdvance.y);
|
|
||||||
auto start = ImVec2(lineNoStartScreenPos.x + mLineNumberFieldWidth, lineNoStartScreenPos.y);
|
|
||||||
bool focused = ImGui::IsWindowFocused();
|
bool focused = ImGui::IsWindowFocused();
|
||||||
if (!mIgnoreImGuiChild)
|
if (!mIgnoreImGuiChild)
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
@ -960,14 +962,14 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||||
while (padding-- > 0) {
|
while (padding-- > 0) {
|
||||||
space += " ";
|
space += " ";
|
||||||
}
|
}
|
||||||
std::string lineNoStr = space + std::to_string(lineNo + 1);
|
std::string lineNoStr = space + std::to_string((int)(lineNo + 1));
|
||||||
TextUnformattedColoredAt(ImVec2(mLeftMargin + lineNoStartScreenPos.x, lineNoStartScreenPos.y), mPalette[(int) PaletteIndex::LineNumber], lineNoStr.c_str());
|
TextUnformattedColoredAt(ImVec2(mLeftMargin + lineNoStartScreenPos.x, lineStartScreenPos.y), mPalette[(int) PaletteIndex::LineNumber], lineNoStr.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw breakpoints
|
// Draw breakpoints
|
||||||
if (mBreakpoints.count(lineNo + 1) != 0) {
|
if (mBreakpoints.count(lineNo + 1) != 0) {
|
||||||
auto end = ImVec2(lineNoStartScreenPos.x + contentSize.x + mLineNumberFieldWidth, lineNoStartScreenPos.y + mCharAdvance.y);
|
auto end = ImVec2(lineNoStartScreenPos.x + contentSize.x + mLineNumberFieldWidth, lineStartScreenPos.y + mCharAdvance.y);
|
||||||
drawList->AddRectFilled(ImVec2(lineNumbersStartPos.x, lineNoStartScreenPos.y), end, mPalette[(int)PaletteIndex::Breakpoint]);
|
drawList->AddRectFilled(ImVec2(lineNumbersStartPos.x, lineStartScreenPos.y), end, mPalette[(int)PaletteIndex::Breakpoint]);
|
||||||
|
|
||||||
drawList->AddCircleFilled(start + ImVec2(0, mCharAdvance.y) / 2, mCharAdvance.y / 3, mPalette[(int)PaletteIndex::Breakpoint]);
|
drawList->AddCircleFilled(start + ImVec2(0, mCharAdvance.y) / 2, mCharAdvance.y / 3, mPalette[(int)PaletteIndex::Breakpoint]);
|
||||||
drawList->AddCircle(start + ImVec2(0, mCharAdvance.y) / 2, mCharAdvance.y / 3, mPalette[(int)PaletteIndex::Default]);
|
drawList->AddCircle(start + ImVec2(0, mCharAdvance.y) / 2, mCharAdvance.y / 3, mPalette[(int)PaletteIndex::Default]);
|
||||||
|
|
@ -977,9 +979,9 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||||
|
|
||||||
// Highlight the current line (where the cursor is)
|
// Highlight the current line (where the cursor is)
|
||||||
if (!HasSelection()) {
|
if (!HasSelection()) {
|
||||||
auto end = ImVec2(lineNoStartScreenPos.x + contentSize.x + mLineNumberFieldWidth, lineNoStartScreenPos.y + mCharAdvance.y);
|
auto end = ImVec2(lineNoStartScreenPos.x + contentSize.x + mLineNumberFieldWidth, lineStartScreenPos.y + mCharAdvance.y);
|
||||||
drawList->AddRectFilled(ImVec2(lineNumbersStartPos.x, lineNoStartScreenPos.y), end, mPalette[(int)(focused ? PaletteIndex::CurrentLineFill : PaletteIndex::CurrentLineFillInactive)]);
|
drawList->AddRectFilled(ImVec2(lineNumbersStartPos.x, lineStartScreenPos.y), end, mPalette[(int)(focused ? PaletteIndex::CurrentLineFill : PaletteIndex::CurrentLineFillInactive)]);
|
||||||
drawList->AddRect(ImVec2(lineNumbersStartPos.x, lineNoStartScreenPos.y), end, mPalette[(int)PaletteIndex::CurrentLineEdge], 1.0f);
|
drawList->AddRect(ImVec2(lineNumbersStartPos.x, lineStartScreenPos.y), end, mPalette[(int)PaletteIndex::CurrentLineEdge], 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mShowLineNumbers && !mIgnoreImGuiChild)
|
if (mShowLineNumbers && !mIgnoreImGuiChild)
|
||||||
|
|
@ -1152,7 +1154,7 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||||
mLineBuffer.clear();
|
mLineBuffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
++lineNo;
|
lineNo = std::floor(lineNo + 1.0F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!mIgnoreImGuiChild)
|
if (!mIgnoreImGuiChild)
|
||||||
|
|
@ -1167,9 +1169,9 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||||
ImGui::BeginChild(aTitle);
|
ImGui::BeginChild(aTitle);
|
||||||
|
|
||||||
if (mShowLineNumbers)
|
if (mShowLineNumbers)
|
||||||
ImGui::Dummy(ImVec2(mLongest, (globalLineMax - lineMax - 2) * mCharAdvance.y + ImGui::GetCurrentWindow()->InnerClipRect.GetHeight()));
|
ImGui::Dummy(ImVec2(mLongest, (globalLineMax - lineMax - 2.0F) * mCharAdvance.y + ImGui::GetCurrentWindow()->InnerClipRect.GetHeight()));
|
||||||
else
|
else
|
||||||
ImGui::Dummy(ImVec2(mLongest, (globalLineMax - 1 - lineMax + GetPageSize() - 1) * mCharAdvance.y));
|
ImGui::Dummy(ImVec2(mLongest, (globalLineMax - 1.0f - lineMax + GetPageSize() - 1.0f ) * mCharAdvance.y - 2 * ImGuiStyle().WindowPadding.y));
|
||||||
|
|
||||||
if (mScrollToCursor)
|
if (mScrollToCursor)
|
||||||
EnsureCursorVisible();
|
EnsureCursorVisible();
|
||||||
|
|
@ -1222,6 +1224,7 @@ void TextEditor::Render(const char *aTitle, const ImVec2 &aSize, bool aBorder) {
|
||||||
if (mShowLineNumbers ) {
|
if (mShowLineNumbers ) {
|
||||||
std::string lineNumber = " " + std::to_string(mLines.size()) + " ";
|
std::string lineNumber = " " + std::to_string(mLines.size()) + " ";
|
||||||
mLineNumberFieldWidth = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, lineNumber.c_str(), nullptr, nullptr).x + mLeftMargin;
|
mLineNumberFieldWidth = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, lineNumber.c_str(), nullptr, nullptr).x + mLeftMargin;
|
||||||
|
ImGui::SetNextWindowPos(position);
|
||||||
ImGui::SetCursorScreenPos(position);
|
ImGui::SetCursorScreenPos(position);
|
||||||
auto lineNoSize = ImVec2(mLineNumberFieldWidth, aSize.y);
|
auto lineNoSize = ImVec2(mLineNumberFieldWidth, aSize.y);
|
||||||
if (!mIgnoreImGuiChild) {
|
if (!mIgnoreImGuiChild) {
|
||||||
|
|
@ -1648,6 +1651,11 @@ void TextEditor::JumpToCoords(const Coordinates &aNewPos) {
|
||||||
void TextEditor::MoveUp(int aAmount, bool aSelect) {
|
void TextEditor::MoveUp(int aAmount, bool aSelect) {
|
||||||
ResetCursorBlinkTime();
|
ResetCursorBlinkTime();
|
||||||
auto oldPos = mState.mCursorPosition;
|
auto oldPos = mState.mCursorPosition;
|
||||||
|
if (aAmount < 0) {
|
||||||
|
mScrollYIncrement = -1.0;
|
||||||
|
SetScrollY();
|
||||||
|
return;
|
||||||
|
}
|
||||||
mState.mCursorPosition.mLine = std::max(0, mState.mCursorPosition.mLine - aAmount);
|
mState.mCursorPosition.mLine = std::max(0, mState.mCursorPosition.mLine - aAmount);
|
||||||
if (oldPos != mState.mCursorPosition) {
|
if (oldPos != mState.mCursorPosition) {
|
||||||
if (aSelect) {
|
if (aSelect) {
|
||||||
|
|
@ -1671,10 +1679,16 @@ void TextEditor::MoveDown(int aAmount, bool aSelect) {
|
||||||
IM_ASSERT(mState.mCursorPosition.mColumn >= 0);
|
IM_ASSERT(mState.mCursorPosition.mColumn >= 0);
|
||||||
ResetCursorBlinkTime();
|
ResetCursorBlinkTime();
|
||||||
auto oldPos = mState.mCursorPosition;
|
auto oldPos = mState.mCursorPosition;
|
||||||
|
if (aAmount < 0) {
|
||||||
|
mScrollYIncrement = 1.0;
|
||||||
|
SetScrollY();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mState.mCursorPosition.mLine = std::clamp(mState.mCursorPosition.mLine + aAmount, 0, (int)mLines.size() - 1);
|
mState.mCursorPosition.mLine = std::clamp(mState.mCursorPosition.mLine + aAmount, 0, (int)mLines.size() - 1);
|
||||||
if (oldPos.mLine == (mLines.size() - 1)) {
|
if (oldPos.mLine == (mLines.size() - 1)) {
|
||||||
mTopLine += aAmount;
|
mTopLine += aAmount;
|
||||||
mTopLine = std::clamp(mTopLine, 0, (int)mLines.size() - 1);
|
mTopLine = std::clamp(mTopLine, 0.0F, mLines.size() - 1.0F);
|
||||||
SetTopLine();
|
SetTopLine();
|
||||||
EnsureCursorVisible();
|
EnsureCursorVisible();
|
||||||
return;
|
return;
|
||||||
|
|
@ -3002,6 +3016,17 @@ float TextEditor::TextDistanceToLineStart(const Coordinates &aFrom) const {
|
||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextEditor::SetScrollY() {
|
||||||
|
if (!mWithinRender) {
|
||||||
|
mSetScrollY = true;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
mSetScrollY = false;
|
||||||
|
auto scrollY = ImGui::GetScrollY();
|
||||||
|
ImGui::SetScrollY(std::clamp(scrollY+mScrollYIncrement,0.0f,ImGui::GetScrollMaxY()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TextEditor::SetTopLine() {
|
void TextEditor::SetTopLine() {
|
||||||
if (!mWithinRender) {
|
if (!mWithinRender) {
|
||||||
mSetTopLine = true;
|
mSetTopLine = true;
|
||||||
|
|
@ -3065,9 +3090,9 @@ void TextEditor::EnsureCursorVisible() {
|
||||||
mOldTopMargin = mTopMargin;
|
mOldTopMargin = mTopMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextEditor::GetPageSize() const {
|
float TextEditor::GetPageSize() const {
|
||||||
auto height = ImGui::GetCurrentWindow()->InnerClipRect.GetHeight() - mTopMargin - ImGui::GetStyle().FramePadding.y;
|
auto height = ImGui::GetCurrentWindow()->InnerClipRect.GetHeight();
|
||||||
return (int)floor(height / mCharAdvance.y);
|
return height / mCharAdvance.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditor::ResetCursorBlinkTime() {
|
void TextEditor::ResetCursorBlinkTime() {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Platform: Clipboard support.
|
// [X] Platform: Clipboard support.
|
||||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
|
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
|
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
|
||||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||||
|
|
@ -28,15 +28,17 @@
|
||||||
struct GLFWwindow;
|
struct GLFWwindow;
|
||||||
struct GLFWmonitor;
|
struct GLFWmonitor;
|
||||||
|
|
||||||
|
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
|
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
|
||||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
|
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
|
||||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
|
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
|
||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
|
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
|
||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
|
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
|
||||||
|
|
||||||
// Emscripten related initialization phase methods
|
// Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL)
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector);
|
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector);
|
||||||
|
//static inline void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { ImGui_ImplGlfw_InstallEmscriptenCallbacks(nullptr, canvas_selector); } } // Renamed in 1.91.0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// GLFW callbacks install
|
// GLFW callbacks install
|
||||||
|
|
@ -59,4 +61,7 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key,
|
||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
|
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
|
||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
|
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
|
||||||
|
|
||||||
|
// GLFW helpers
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds);
|
||||||
|
|
||||||
#endif // #ifndef IMGUI_DISABLE
|
#endif // #ifndef IMGUI_DISABLE
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Platform: Clipboard support.
|
// [X] Platform: Clipboard support.
|
||||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
|
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
|
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
|
||||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||||
|
|
@ -21,9 +21,23 @@
|
||||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||||
// - Introduction, links and more at the top of imgui.cpp
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
|
// About Emscripten support:
|
||||||
|
// - Emscripten provides its own GLFW (3.2.1) implementation (syntax: "-sUSE_GLFW=3"), but Joystick is broken and several features are not supported (multiple windows, clipboard, timer, etc.)
|
||||||
|
// - A third-party Emscripten GLFW (3.4.0) implementation (syntax: "--use-port=contrib.glfw3") fixes the Joystick issue and implements all relevant features for the browser.
|
||||||
|
// See https://github.com/pongasoft/emscripten-glfw/blob/master/docs/Comparison.md for details.
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2024-11-05: [Docking] Added Linux workaround for spurious mouse up events emitted while dragging and creating new viewport. (#3158, #7733, #7922)
|
||||||
|
// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
|
||||||
|
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
|
||||||
|
// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn
|
||||||
|
// - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn
|
||||||
|
// 2024-07-31: Added ImGui_ImplGlfw_Sleep() helper function for usage by our examples app, since GLFW doesn't provide one.
|
||||||
|
// 2024-07-08: *BREAKING* Renamed ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback to ImGui_ImplGlfw_InstallEmscriptenCallbacks(), added GLFWWindow* parameter.
|
||||||
|
// 2024-07-08: Emscripten: Added support for GLFW3 contrib port (GLFW 3.4.0 features + bug fixes): to enable, replace -sUSE_GLFW=3 with --use-port=contrib.glfw3 (requires emscripten 3.1.59+) (https://github.com/pongasoft/emscripten-glfw)
|
||||||
|
// 2024-07-02: Emscripten: Added io.PlatformOpenInShellFn() handler for Emscripten versions.
|
||||||
// 2023-12-19: Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window.
|
// 2023-12-19: Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window.
|
||||||
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys.
|
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys.
|
||||||
// 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609)
|
// 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609)
|
||||||
|
|
@ -104,15 +118,25 @@
|
||||||
//#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
|
//#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
|
||||||
// #endif
|
// #endif
|
||||||
// IMHEX PATCH END
|
// IMHEX PATCH END
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h> // for usleep()
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
|
|
||||||
// IMHEX PATCH BEGIN
|
// IMHEX PATCH BEGIN
|
||||||
#include <emscripten_browser_clipboard.h>
|
#include <emscripten_browser_clipboard.h>
|
||||||
|
|
||||||
static std::string clipboardContent;
|
static std::string clipboardContent;
|
||||||
// IMHEX PATCH END
|
// IMHEX PATCH END
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3
|
||||||
|
#include <GLFW/emscripten_glfw3.h>
|
||||||
|
#else
|
||||||
|
#define EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We gather version tests as define in order to easily see which features are version-dependent.
|
// We gather version tests as define in order to easily see which features are version-dependent.
|
||||||
|
|
@ -159,12 +183,14 @@ struct ImGui_ImplGlfw_Data
|
||||||
double Time;
|
double Time;
|
||||||
GLFWwindow* MouseWindow;
|
GLFWwindow* MouseWindow;
|
||||||
GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
||||||
|
bool MouseIgnoreButtonUpWaitForFocusLoss;
|
||||||
|
bool MouseIgnoreButtonUp;
|
||||||
ImVec2 LastValidMousePos;
|
ImVec2 LastValidMousePos;
|
||||||
GLFWwindow* KeyOwnerWindows[GLFW_KEY_LAST];
|
GLFWwindow* KeyOwnerWindows[GLFW_KEY_LAST];
|
||||||
bool InstalledCallbacks;
|
bool InstalledCallbacks;
|
||||||
bool CallbacksChainForAllWindows;
|
bool CallbacksChainForAllWindows;
|
||||||
bool WantUpdateMonitors;
|
bool WantUpdateMonitors;
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
const char* CanvasSelector;
|
const char* CanvasSelector;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -198,8 +224,8 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
|
||||||
|
|
||||||
// Forward Declarations
|
// Forward Declarations
|
||||||
static void ImGui_ImplGlfw_UpdateMonitors();
|
static void ImGui_ImplGlfw_UpdateMonitors();
|
||||||
static void ImGui_ImplGlfw_InitPlatformInterface();
|
static void ImGui_ImplGlfw_InitMultiViewportSupport();
|
||||||
static void ImGui_ImplGlfw_ShutdownPlatformInterface();
|
static void ImGui_ImplGlfw_ShutdownMultiViewportSupport();
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
||||||
|
|
@ -224,9 +250,12 @@ static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
|
||||||
// IMHEX PATCH END
|
// IMHEX PATCH END
|
||||||
}
|
}
|
||||||
|
|
||||||
static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
|
// Not static to allow third-party code to use that if they want to (but undocumented)
|
||||||
|
ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode);
|
||||||
|
ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode)
|
||||||
{
|
{
|
||||||
switch (key)
|
IM_UNUSED(scancode);
|
||||||
|
switch (keycode)
|
||||||
{
|
{
|
||||||
case GLFW_KEY_TAB: return ImGuiKey_Tab;
|
case GLFW_KEY_TAB: return ImGuiKey_Tab;
|
||||||
case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow;
|
case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow;
|
||||||
|
|
@ -351,13 +380,18 @@ static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
|
||||||
|
|
||||||
// X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW
|
// X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW
|
||||||
// See https://github.com/ocornut/imgui/issues/6034 and https://github.com/glfw/glfw/issues/1630
|
// See https://github.com/ocornut/imgui/issues/6034 and https://github.com/glfw/glfw/issues/1630
|
||||||
static void ImGui_ImplGlfw_UpdateKeyModifiers(GLFWwindow* window)
|
static void ImGui_ImplGlfw_UpdateKeyModifiers(int mods)
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.AddKeyEvent(ImGuiMod_Ctrl, (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS));
|
|
||||||
io.AddKeyEvent(ImGuiMod_Shift, (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS));
|
// IMHEX PATCH BEGIN
|
||||||
io.AddKeyEvent(ImGuiMod_Alt, (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS));
|
// The original version of this caused the CTRL key to sometimes get stuck when pressing ALT GR, SHIFT and Enter
|
||||||
io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS));
|
// together in some ways
|
||||||
|
io.AddKeyEvent(ImGuiMod_Ctrl, (mods & GLFW_MOD_CONTROL) != 0);
|
||||||
|
io.AddKeyEvent(ImGuiMod_Shift, (mods & GLFW_MOD_SHIFT) != 0);
|
||||||
|
io.AddKeyEvent(ImGuiMod_Alt, (mods & GLFW_MOD_ALT) != 0);
|
||||||
|
io.AddKeyEvent(ImGuiMod_Super, (mods & GLFW_MOD_SUPER) != 0);
|
||||||
|
// IMHEX PATCH END
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ImGui_ImplGlfw_ShouldChainCallback(GLFWwindow* window)
|
static bool ImGui_ImplGlfw_ShouldChainCallback(GLFWwindow* window)
|
||||||
|
|
@ -372,7 +406,11 @@ void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int acti
|
||||||
if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
||||||
bd->PrevUserCallbackMousebutton(window, button, action, mods);
|
bd->PrevUserCallbackMousebutton(window, button, action, mods);
|
||||||
|
|
||||||
ImGui_ImplGlfw_UpdateKeyModifiers(window);
|
// Workaround for Linux: ignore mouse up events which are following an focus loss following a viewport creation
|
||||||
|
if (bd->MouseIgnoreButtonUp && action == GLFW_RELEASE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGui_ImplGlfw_UpdateKeyModifiers(mods);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
if (button >= 0 && button < ImGuiMouseButton_COUNT)
|
if (button >= 0 && button < ImGuiMouseButton_COUNT)
|
||||||
|
|
@ -385,7 +423,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
|
||||||
if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
||||||
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
|
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
// Ignore GLFW events: will be processed in ImGui_ImplEmscripten_WheelCallback().
|
// Ignore GLFW events: will be processed in ImGui_ImplEmscripten_WheelCallback().
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -394,9 +432,10 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
|
||||||
io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
|
io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: should this be baked into ImGui_ImplGlfw_KeyToImGuiKey()? then what about the values passed to io.SetKeyEventNativeData()?
|
||||||
static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
||||||
{
|
{
|
||||||
#if GLFW_HAS_GETKEYNAME && !defined(__EMSCRIPTEN__)
|
#if GLFW_HAS_GETKEYNAME && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3)
|
||||||
// GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult.
|
// GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult.
|
||||||
// (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently)
|
// (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently)
|
||||||
// See https://github.com/glfw/glfw/issues/1502 for details.
|
// See https://github.com/glfw/glfw/issues/1502 for details.
|
||||||
|
|
@ -407,7 +446,7 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
||||||
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);
|
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);
|
||||||
const char* key_name = glfwGetKeyName(key, scancode);
|
const char* key_name = glfwGetKeyName(key, scancode);
|
||||||
glfwSetErrorCallback(prev_error_callback);
|
glfwSetErrorCallback(prev_error_callback);
|
||||||
#if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908)
|
#if GLFW_HAS_GETERROR && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3) // Eat errors (see #5908)
|
||||||
(void)glfwGetError(nullptr);
|
(void)glfwGetError(nullptr);
|
||||||
#endif
|
#endif
|
||||||
if (key_name && key_name[0] != 0 && key_name[1] == 0)
|
if (key_name && key_name[0] != 0 && key_name[1] == 0)
|
||||||
|
|
@ -436,7 +475,7 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
|
||||||
if (action != GLFW_PRESS && action != GLFW_RELEASE)
|
if (action != GLFW_PRESS && action != GLFW_RELEASE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGui_ImplGlfw_UpdateKeyModifiers(window);
|
ImGui_ImplGlfw_UpdateKeyModifiers(mods);
|
||||||
|
|
||||||
if (keycode >= 0 && keycode < IM_ARRAYSIZE(bd->KeyOwnerWindows))
|
if (keycode >= 0 && keycode < IM_ARRAYSIZE(bd->KeyOwnerWindows))
|
||||||
bd->KeyOwnerWindows[keycode] = (action == GLFW_PRESS) ? window : nullptr;
|
bd->KeyOwnerWindows[keycode] = (action == GLFW_PRESS) ? window : nullptr;
|
||||||
|
|
@ -444,7 +483,7 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
|
||||||
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
|
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode);
|
ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode, scancode);
|
||||||
io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
|
io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
|
||||||
io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
|
io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
|
||||||
}
|
}
|
||||||
|
|
@ -455,6 +494,10 @@ void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
|
||||||
if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
||||||
bd->PrevUserCallbackWindowFocus(window, focused);
|
bd->PrevUserCallbackWindowFocus(window, focused);
|
||||||
|
|
||||||
|
// Workaround for Linux: when losing focus with MouseIgnoreButtonUpWaitForFocusLoss set, we will temporarily ignore subsequent Mouse Up events
|
||||||
|
bd->MouseIgnoreButtonUp = (bd->MouseIgnoreButtonUpWaitForFocusLoss && focused == 0);
|
||||||
|
bd->MouseIgnoreButtonUpWaitForFocusLoss = false;
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.AddFocusEvent(focused != 0);
|
io.AddFocusEvent(focused != 0);
|
||||||
}
|
}
|
||||||
|
|
@ -515,7 +558,7 @@ void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
|
||||||
bd->WantUpdateMonitors = true;
|
bd->WantUpdateMonitors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*)
|
static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*)
|
||||||
{
|
{
|
||||||
// Mimic Emscripten_HandleWheel() in SDL.
|
// Mimic Emscripten_HandleWheel() in SDL.
|
||||||
|
|
@ -600,6 +643,7 @@ EM_JS(void, ImGui_ImplGlfw_EmscriptenOpenURL, (const char* url), { url = url ? U
|
||||||
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
|
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||||
//printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED);
|
//printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED);
|
||||||
|
|
||||||
|
|
@ -665,14 +709,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||||
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
|
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
|
||||||
if (install_callbacks)
|
if (install_callbacks)
|
||||||
ImGui_ImplGlfw_InstallCallbacks(window);
|
ImGui_ImplGlfw_InstallCallbacks(window);
|
||||||
// Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
|
|
||||||
// We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
|
|
||||||
// FIXME: May break chaining in case user registered their own Emscripten callback?
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, ImGui_ImplEmscripten_WheelCallback);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Update monitors the first time (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784)
|
// Update monitor a first time during init
|
||||||
|
// (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784)
|
||||||
ImGui_ImplGlfw_UpdateMonitors();
|
ImGui_ImplGlfw_UpdateMonitors();
|
||||||
glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
|
glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
|
||||||
|
|
||||||
|
|
@ -689,8 +728,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||||
#else
|
#else
|
||||||
IM_UNUSED(main_viewport);
|
IM_UNUSED(main_viewport);
|
||||||
#endif
|
#endif
|
||||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
ImGui_ImplGlfw_InitMultiViewportSupport();
|
||||||
ImGui_ImplGlfw_InitPlatformInterface();
|
|
||||||
|
|
||||||
// Windows: register a WndProc hook so we can intercept some messages.
|
// Windows: register a WndProc hook so we can intercept some messages.
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
@ -699,6 +737,23 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||||
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
|
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Emscripten: the same application can run on various platforms, so we detect the Apple platform at runtime
|
||||||
|
// to override io.ConfigMacOSXBehaviors from its default (which is always false in Emscripten).
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 34020240817
|
||||||
|
if (emscripten::glfw3::IsRuntimePlatformApple())
|
||||||
|
{
|
||||||
|
ImGui::GetIO().ConfigMacOSXBehaviors = true;
|
||||||
|
|
||||||
|
// Due to how the browser (poorly) handles the Meta Key, this line essentially disables repeats when used.
|
||||||
|
// This means that Meta + V only registers a single key-press, even if the keys are held.
|
||||||
|
// This is a compromise for dealing with this issue in ImGui since ImGui implements key repeat itself.
|
||||||
|
// See https://github.com/pongasoft/emscripten-glfw/blob/v3.4.0.20240817/docs/Usage.md#the-problem-of-the-super-key
|
||||||
|
emscripten::glfw3::SetSuperPlusKeyTimeouts(10, 10);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
bd->ClientApi = client_api;
|
bd->ClientApi = client_api;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -724,12 +779,13 @@ void ImGui_ImplGlfw_Shutdown()
|
||||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
ImGui_ImplGlfw_ShutdownPlatformInterface();
|
ImGui_ImplGlfw_ShutdownMultiViewportSupport();
|
||||||
|
|
||||||
if (bd->InstalledCallbacks)
|
if (bd->InstalledCallbacks)
|
||||||
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
|
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr);
|
if (bd->CanvasSelector)
|
||||||
|
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||||
|
|
@ -761,14 +817,14 @@ static void ImGui_ImplGlfw_UpdateMouseData()
|
||||||
ImGuiViewport* viewport = platform_io.Viewports[n];
|
ImGuiViewport* viewport = platform_io.Viewports[n];
|
||||||
GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle;
|
GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle;
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
const bool is_window_focused = true;
|
const bool is_window_focused = true;
|
||||||
#else
|
#else
|
||||||
const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0;
|
const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0;
|
||||||
#endif
|
#endif
|
||||||
if (is_window_focused)
|
if (is_window_focused)
|
||||||
{
|
{
|
||||||
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
|
||||||
// When multi-viewports are enabled, all Dear ImGui positions are same as OS positions.
|
// When multi-viewports are enabled, all Dear ImGui positions are same as OS positions.
|
||||||
if (io.WantSetMousePos)
|
if (io.WantSetMousePos)
|
||||||
glfwSetCursorPos(window, (double)(mouse_pos_prev.x - viewport->Pos.x), (double)(mouse_pos_prev.y - viewport->Pos.y));
|
glfwSetCursorPos(window, (double)(mouse_pos_prev.x - viewport->Pos.x), (double)(mouse_pos_prev.y - viewport->Pos.y));
|
||||||
|
|
@ -840,7 +896,6 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
|
||||||
{
|
{
|
||||||
// Show OS mouse cursor
|
// Show OS mouse cursor
|
||||||
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
||||||
|
|
||||||
// IMHEX PATCH BEGIN
|
// IMHEX PATCH BEGIN
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||||
|
|
@ -861,7 +916,7 @@ static void ImGui_ImplGlfw_UpdateGamepads()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||||
#if GLFW_HAS_GAMEPAD_API && !defined(__EMSCRIPTEN__)
|
#if GLFW_HAS_GAMEPAD_API && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3)
|
||||||
GLFWgamepadstate gamepad;
|
GLFWgamepadstate gamepad;
|
||||||
if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad))
|
if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad))
|
||||||
return;
|
return;
|
||||||
|
|
@ -940,13 +995,9 @@ static void ImGui_ImplGlfw_UpdateMonitors()
|
||||||
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
|
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
|
||||||
float x_scale, y_scale;
|
float x_scale, y_scale;
|
||||||
glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);
|
glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);
|
||||||
|
if (x_scale == 0.0f)
|
||||||
|
continue; // Some accessibility applications are declaring virtual monitors with a DPI of 0, see #7902.
|
||||||
monitor.DpiScale = x_scale;
|
monitor.DpiScale = x_scale;
|
||||||
|
|
||||||
// IMHEX PATCH BEGIN
|
|
||||||
// REASON: Prevent occasional crash when a monitor connection status is changed
|
|
||||||
if (x_scale > 0)
|
|
||||||
monitor.DpiScale = x_scale;
|
|
||||||
// IMHEX PATCH END
|
|
||||||
#endif
|
#endif
|
||||||
monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes"
|
monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes"
|
||||||
platform_io.Monitors.push_back(monitor);
|
platform_io.Monitors.push_back(monitor);
|
||||||
|
|
@ -978,6 +1029,7 @@ void ImGui_ImplGlfw_NewFrame()
|
||||||
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
|
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
|
||||||
bd->Time = current_time;
|
bd->Time = current_time;
|
||||||
|
|
||||||
|
bd->MouseIgnoreButtonUp = false;
|
||||||
ImGui_ImplGlfw_UpdateMouseData();
|
ImGui_ImplGlfw_UpdateMouseData();
|
||||||
ImGui_ImplGlfw_UpdateMouseCursor();
|
ImGui_ImplGlfw_UpdateMouseCursor();
|
||||||
|
|
||||||
|
|
@ -985,7 +1037,17 @@ void ImGui_ImplGlfw_NewFrame()
|
||||||
ImGui_ImplGlfw_UpdateGamepads();
|
ImGui_ImplGlfw_UpdateGamepads();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
// GLFW doesn't provide a portable sleep function
|
||||||
|
void ImGui_ImplGlfw_Sleep(int milliseconds)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
::Sleep(milliseconds);
|
||||||
|
#else
|
||||||
|
usleep(milliseconds * 1000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data)
|
static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
|
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
|
||||||
|
|
@ -1006,7 +1068,7 @@ static EM_BOOL ImGui_ImplEmscripten_FullscreenChangeCallback(int event_type, con
|
||||||
|
|
||||||
// 'canvas_selector' is a CSS selector. The event listener is applied to the first element that matches the query.
|
// 'canvas_selector' is a CSS selector. The event listener is applied to the first element that matches the query.
|
||||||
// STRING MUST PERSIST FOR THE APPLICATION DURATION. PLEASE USE A STRING LITERAL OR ENSURE POINTER WILL STAY VALID.
|
// STRING MUST PERSIST FOR THE APPLICATION DURATION. PLEASE USE A STRING LITERAL OR ENSURE POINTER WILL STAY VALID.
|
||||||
void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector)
|
void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow*, const char* canvas_selector)
|
||||||
{
|
{
|
||||||
IM_ASSERT(canvas_selector != nullptr);
|
IM_ASSERT(canvas_selector != nullptr);
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||||
|
|
@ -1018,8 +1080,24 @@ void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_sel
|
||||||
|
|
||||||
// Change the size of the GLFW window according to the size of the canvas
|
// Change the size of the GLFW window according to the size of the canvas
|
||||||
ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd);
|
ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd);
|
||||||
|
|
||||||
|
// Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
|
||||||
|
// We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
|
||||||
|
// FIXME: May break chaining in case user registered their own Emscripten callback?
|
||||||
|
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, ImGui_ImplEmscripten_WheelCallback);
|
||||||
}
|
}
|
||||||
#endif
|
#elif defined(EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3)
|
||||||
|
// When using --use-port=contrib.glfw3 for the GLFW implementation, you can override the behavior of this call
|
||||||
|
// by invoking emscripten_glfw_make_canvas_resizable afterward.
|
||||||
|
// See https://github.com/pongasoft/emscripten-glfw/blob/master/docs/Usage.md#how-to-make-the-canvas-resizable-by-the-user for an explanation
|
||||||
|
void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector)
|
||||||
|
{
|
||||||
|
GLFWwindow* w = (GLFWwindow*)(EM_ASM_INT({ return Module.glfwGetWindow(UTF8ToString($0)); }, canvas_selector));
|
||||||
|
IM_ASSERT(window == w); // Sanity check
|
||||||
|
IM_UNUSED(w);
|
||||||
|
emscripten_glfw_make_canvas_resizable(window, "window", nullptr);
|
||||||
|
}
|
||||||
|
#endif // #ifdef EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -1091,6 +1169,11 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
|
||||||
ImGui_ImplGlfw_ViewportData* vd = IM_NEW(ImGui_ImplGlfw_ViewportData)();
|
ImGui_ImplGlfw_ViewportData* vd = IM_NEW(ImGui_ImplGlfw_ViewportData)();
|
||||||
viewport->PlatformUserData = vd;
|
viewport->PlatformUserData = vd;
|
||||||
|
|
||||||
|
// Workaround for Linux: ignore mouse up events corresponding to losing focus of the previously focused window (#7733, #3158, #7922)
|
||||||
|
#ifdef __linux__
|
||||||
|
bd->MouseIgnoreButtonUpWaitForFocusLoss = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
// GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of GLFW_FOCUSED
|
// GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of GLFW_FOCUSED
|
||||||
// With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
|
// With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
|
||||||
glfwWindowHint(GLFW_VISIBLE, false);
|
glfwWindowHint(GLFW_VISIBLE, false);
|
||||||
|
|
@ -1152,6 +1235,7 @@ static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)
|
||||||
if (bd->KeyOwnerWindows[i] == vd->Window)
|
if (bd->KeyOwnerWindows[i] == vd->Window)
|
||||||
ImGui_ImplGlfw_KeyCallback(vd->Window, i, 0, GLFW_RELEASE, 0); // Later params are only used for main viewport, on which this function is never called.
|
ImGui_ImplGlfw_KeyCallback(vd->Window, i, 0, GLFW_RELEASE, 0); // Later params are only used for main viewport, on which this function is never called.
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwDestroyWindow(vd->Window);
|
glfwDestroyWindow(vd->Window);
|
||||||
}
|
}
|
||||||
vd->Window = nullptr;
|
vd->Window = nullptr;
|
||||||
|
|
@ -1324,7 +1408,7 @@ static int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst
|
||||||
}
|
}
|
||||||
#endif // GLFW_HAS_VULKAN
|
#endif // GLFW_HAS_VULKAN
|
||||||
|
|
||||||
static void ImGui_ImplGlfw_InitPlatformInterface()
|
static void ImGui_ImplGlfw_InitMultiViewportSupport()
|
||||||
{
|
{
|
||||||
// Register platform interface (will be coupled with a renderer interface)
|
// Register platform interface (will be coupled with a renderer interface)
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||||
|
|
@ -1359,7 +1443,7 @@ static void ImGui_ImplGlfw_InitPlatformInterface()
|
||||||
main_viewport->PlatformHandle = (void*)bd->Window;
|
main_viewport->PlatformHandle = (void*)bd->Window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGui_ImplGlfw_ShutdownPlatformInterface()
|
static void ImGui_ImplGlfw_ShutdownMultiViewportSupport()
|
||||||
{
|
{
|
||||||
ImGui::DestroyPlatformWindows();
|
ImGui::DestroyPlatformWindows();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15592,7 +15592,7 @@ void ImGui::SetCurrentViewport(ImGuiWindow* current_window, ImGuiViewportP* view
|
||||||
return;
|
return;
|
||||||
g.CurrentDpiScale = viewport ? viewport->DpiScale : 1.0f;
|
g.CurrentDpiScale = viewport ? viewport->DpiScale : 1.0f;
|
||||||
g.CurrentViewport = viewport;
|
g.CurrentViewport = viewport;
|
||||||
IM_ASSERT(g.CurrentDpiScale > 0.0f && g.CurrentDpiScale < 99.0f); // Typical correct values would be between 1.0f and 4.0f
|
//IM_ASSERT(g.CurrentDpiScale > 0.0f && g.CurrentDpiScale < 99.0f); // Typical correct values would be between 1.0f and 4.0f
|
||||||
//IMGUI_DEBUG_LOG_VIEWPORT("[viewport] SetCurrentViewport changed '%s' 0x%08X\n", current_window ? current_window->Name : NULL, viewport ? viewport->ID : 0);
|
//IMGUI_DEBUG_LOG_VIEWPORT("[viewport] SetCurrentViewport changed '%s' 0x%08X\n", current_window ? current_window->Name : NULL, viewport ? viewport->ID : 0);
|
||||||
|
|
||||||
// Notify platform layer of viewport changes
|
// Notify platform layer of viewport changes
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#define LLVM_DEMANGLE_DEMANGLE_H
|
#define LLVM_DEMANGLE_DEMANGLE_H
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
|
@ -32,7 +33,7 @@ enum : int {
|
||||||
/// Returns a non-NULL pointer to a NUL-terminated C style string
|
/// Returns a non-NULL pointer to a NUL-terminated C style string
|
||||||
/// that should be explicitly freed, if successful. Otherwise, may return
|
/// that should be explicitly freed, if successful. Otherwise, may return
|
||||||
/// nullptr if mangled_name is not a valid mangling or is nullptr.
|
/// nullptr if mangled_name is not a valid mangling or is nullptr.
|
||||||
char *itaniumDemangle(std::string_view mangled_name);
|
char *itaniumDemangle(std::string_view mangled_name, bool ParseParams = true);
|
||||||
|
|
||||||
enum MSDemangleFlags {
|
enum MSDemangleFlags {
|
||||||
MSDF_None = 0,
|
MSDF_None = 0,
|
||||||
|
|
@ -54,6 +55,9 @@ enum MSDemangleFlags {
|
||||||
char *microsoftDemangle(std::string_view mangled_name, size_t *n_read,
|
char *microsoftDemangle(std::string_view mangled_name, size_t *n_read,
|
||||||
int *status, MSDemangleFlags Flags = MSDF_None);
|
int *status, MSDemangleFlags Flags = MSDF_None);
|
||||||
|
|
||||||
|
std::optional<size_t>
|
||||||
|
getArm64ECInsertionPointInMangledName(std::string_view MangledName);
|
||||||
|
|
||||||
// Demangles a Rust v0 mangled symbol.
|
// Demangles a Rust v0 mangled symbol.
|
||||||
char *rustDemangle(std::string_view MangledName);
|
char *rustDemangle(std::string_view MangledName);
|
||||||
|
|
||||||
|
|
@ -67,7 +71,9 @@ char *dlangDemangle(std::string_view MangledName);
|
||||||
/// demangling occurred.
|
/// demangling occurred.
|
||||||
std::string demangle(std::string_view MangledName);
|
std::string demangle(std::string_view MangledName);
|
||||||
|
|
||||||
bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result);
|
bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result,
|
||||||
|
bool CanHaveLeadingDot = true,
|
||||||
|
bool ParseParams = true);
|
||||||
|
|
||||||
/// "Partial" demangler. This supports demangling a string into an AST
|
/// "Partial" demangler. This supports demangling a string into an AST
|
||||||
/// (typically an intermediate stage in itaniumDemangle) and querying certain
|
/// (typically an intermediate stage in itaniumDemangle) and querying certain
|
||||||
|
|
@ -102,7 +108,7 @@ struct ItaniumPartialDemangler {
|
||||||
char *getFunctionParameters(char *Buf, size_t *N) const;
|
char *getFunctionParameters(char *Buf, size_t *N) const;
|
||||||
char *getFunctionReturnType(char *Buf, size_t *N) const;
|
char *getFunctionReturnType(char *Buf, size_t *N) const;
|
||||||
|
|
||||||
/// If this function has any any cv or reference qualifiers. These imply that
|
/// If this function has any cv or reference qualifiers. These imply that
|
||||||
/// the function is a non-static member function.
|
/// the function is a non-static member function.
|
||||||
bool hasFunctionQualifiers() const;
|
bool hasFunctionQualifiers() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,11 @@
|
||||||
#define DEMANGLE_FALLTHROUGH
|
#define DEMANGLE_FALLTHROUGH
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEMANGLE_ASSERT
|
||||||
|
#include <cassert>
|
||||||
|
#define DEMANGLE_ASSERT(__expr, __msg) assert((__expr) && (__msg))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DEMANGLE_NAMESPACE_BEGIN namespace llvm { namespace itanium_demangle {
|
#define DEMANGLE_NAMESPACE_BEGIN namespace llvm { namespace itanium_demangle {
|
||||||
#define DEMANGLE_NAMESPACE_END } }
|
#define DEMANGLE_NAMESPACE_END } }
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -19,6 +19,7 @@ NODE(QualType)
|
||||||
NODE(ConversionOperatorType)
|
NODE(ConversionOperatorType)
|
||||||
NODE(PostfixQualifiedType)
|
NODE(PostfixQualifiedType)
|
||||||
NODE(ElaboratedTypeSpefType)
|
NODE(ElaboratedTypeSpefType)
|
||||||
|
NODE(TransformedType)
|
||||||
NODE(NameType)
|
NODE(NameType)
|
||||||
NODE(AbiTagAttr)
|
NODE(AbiTagAttr)
|
||||||
NODE(EnableIfAttr)
|
NODE(EnableIfAttr)
|
||||||
|
|
@ -36,6 +37,7 @@ NODE(SpecialName)
|
||||||
NODE(CtorVtableSpecialName)
|
NODE(CtorVtableSpecialName)
|
||||||
NODE(QualifiedName)
|
NODE(QualifiedName)
|
||||||
NODE(NestedName)
|
NODE(NestedName)
|
||||||
|
NODE(MemberLikeFriendName)
|
||||||
NODE(LocalName)
|
NODE(LocalName)
|
||||||
NODE(ModuleName)
|
NODE(ModuleName)
|
||||||
NODE(ModuleEntity)
|
NODE(ModuleEntity)
|
||||||
|
|
@ -44,7 +46,9 @@ NODE(PixelVectorType)
|
||||||
NODE(BinaryFPType)
|
NODE(BinaryFPType)
|
||||||
NODE(BitIntType)
|
NODE(BitIntType)
|
||||||
NODE(SyntheticTemplateParamName)
|
NODE(SyntheticTemplateParamName)
|
||||||
|
NODE(TemplateParamQualifiedArg)
|
||||||
NODE(TypeTemplateParamDecl)
|
NODE(TypeTemplateParamDecl)
|
||||||
|
NODE(ConstrainedTypeTemplateParamDecl)
|
||||||
NODE(NonTypeTemplateParamDecl)
|
NODE(NonTypeTemplateParamDecl)
|
||||||
NODE(TemplateTemplateParamDecl)
|
NODE(TemplateTemplateParamDecl)
|
||||||
NODE(TemplateParamPackDecl)
|
NODE(TemplateParamPackDecl)
|
||||||
|
|
@ -91,5 +95,10 @@ NODE(DoubleLiteral)
|
||||||
NODE(LongDoubleLiteral)
|
NODE(LongDoubleLiteral)
|
||||||
NODE(BracedExpr)
|
NODE(BracedExpr)
|
||||||
NODE(BracedRangeExpr)
|
NODE(BracedRangeExpr)
|
||||||
|
NODE(RequiresExpr)
|
||||||
|
NODE(ExprRequirement)
|
||||||
|
NODE(TypeRequirement)
|
||||||
|
NODE(NestedRequirement)
|
||||||
|
NODE(ExplicitObjectParameter)
|
||||||
|
|
||||||
#undef NODE
|
#undef NODE
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
|
#ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
|
||||||
#define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
|
#define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
|
||||||
|
|
||||||
|
#include "llvm/Demangle/Demangle.h"
|
||||||
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
|
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
@ -54,6 +55,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete the copy constructor and the copy assignment operator.
|
||||||
|
ArenaAllocator(const ArenaAllocator &) = delete;
|
||||||
|
ArenaAllocator &operator=(const ArenaAllocator &) = delete;
|
||||||
|
|
||||||
char *allocUnalignedBuffer(size_t Size) {
|
char *allocUnalignedBuffer(size_t Size) {
|
||||||
assert(Head && Head->Buf);
|
assert(Head && Head->Buf);
|
||||||
|
|
||||||
|
|
@ -137,6 +142,9 @@ enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder };
|
||||||
// It has a set of functions to parse mangled symbols into Type instances.
|
// It has a set of functions to parse mangled symbols into Type instances.
|
||||||
// It also has a set of functions to convert Type instances to strings.
|
// It also has a set of functions to convert Type instances to strings.
|
||||||
class Demangler {
|
class Demangler {
|
||||||
|
friend std::optional<size_t>
|
||||||
|
llvm::getArm64ECInsertionPointInMangledName(std::string_view MangledName);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Demangler() = default;
|
Demangler() = default;
|
||||||
virtual ~Demangler() = default;
|
virtual ~Demangler() = default;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ differences, we want to keep the "core" generic demangling library
|
||||||
identical between both copies to simplify development and testing.
|
identical between both copies to simplify development and testing.
|
||||||
|
|
||||||
If you're working on the generic library, then do the work first in
|
If you're working on the generic library, then do the work first in
|
||||||
libcxxabi, then run the cp-to-llvm.sh script in src/demangle. This
|
libcxxabi, then run libcxxabi/src/demangle/cp-to-llvm.sh. This
|
||||||
script takes as an optional argument the path to llvm, and copies the
|
script takes as an optional argument the path to llvm, and copies the
|
||||||
changes you made to libcxxabi over. Note that this script just
|
changes you made to libcxxabi over. Note that this script just
|
||||||
blindly overwrites all changes to the generic library in llvm, so be
|
blindly overwrites all changes to the generic library in llvm, so be
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,9 @@
|
||||||
#include "DemangleConfig.h"
|
#include "DemangleConfig.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <exception>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
|
@ -49,7 +47,7 @@ class OutputBuffer {
|
||||||
BufferCapacity = Need;
|
BufferCapacity = Need;
|
||||||
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
|
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
|
||||||
if (Buffer == nullptr)
|
if (Buffer == nullptr)
|
||||||
std::terminate();
|
std::abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,7 +158,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(size_t Pos, const char *S, size_t N) {
|
void insert(size_t Pos, const char *S, size_t N) {
|
||||||
assert(Pos <= CurrentPosition);
|
DEMANGLE_ASSERT(Pos <= CurrentPosition, "");
|
||||||
if (N == 0)
|
if (N == 0)
|
||||||
return;
|
return;
|
||||||
grow(N);
|
grow(N);
|
||||||
|
|
@ -173,7 +171,7 @@ public:
|
||||||
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
|
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
|
||||||
|
|
||||||
char back() const {
|
char back() const {
|
||||||
assert(CurrentPosition);
|
DEMANGLE_ASSERT(CurrentPosition, "");
|
||||||
return Buffer[CurrentPosition - 1];
|
return Buffer[CurrentPosition - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ std::string llvm::demangle(std::string_view MangledName) {
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
if (starts_with(MangledName, '_') &&
|
if (starts_with(MangledName, '_') &&
|
||||||
nonMicrosoftDemangle(MangledName.substr(1), Result))
|
nonMicrosoftDemangle(MangledName.substr(1), Result,
|
||||||
|
/*CanHaveLeadingDot=*/false))
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
if (char *Demangled = microsoftDemangle(MangledName, nullptr, nullptr)) {
|
if (char *Demangled = microsoftDemangle(MangledName, nullptr, nullptr)) {
|
||||||
|
|
@ -46,10 +47,18 @@ static bool isRustEncoding(std::string_view S) { return starts_with(S, "_R"); }
|
||||||
static bool isDLangEncoding(std::string_view S) { return starts_with(S, "_D"); }
|
static bool isDLangEncoding(std::string_view S) { return starts_with(S, "_D"); }
|
||||||
|
|
||||||
bool llvm::nonMicrosoftDemangle(std::string_view MangledName,
|
bool llvm::nonMicrosoftDemangle(std::string_view MangledName,
|
||||||
std::string &Result) {
|
std::string &Result, bool CanHaveLeadingDot,
|
||||||
|
bool ParseParams) {
|
||||||
char *Demangled = nullptr;
|
char *Demangled = nullptr;
|
||||||
|
|
||||||
|
// Do not consider the dot prefix as part of the demangled symbol name.
|
||||||
|
if (CanHaveLeadingDot && MangledName.size() > 0 && MangledName[0] == '.') {
|
||||||
|
MangledName.remove_prefix(1);
|
||||||
|
Result = ".";
|
||||||
|
}
|
||||||
|
|
||||||
if (isItaniumEncoding(MangledName))
|
if (isItaniumEncoding(MangledName))
|
||||||
Demangled = itaniumDemangle(MangledName);
|
Demangled = itaniumDemangle(MangledName, ParseParams);
|
||||||
else if (isRustEncoding(MangledName))
|
else if (isRustEncoding(MangledName))
|
||||||
Demangled = rustDemangle(MangledName);
|
Demangled = rustDemangle(MangledName);
|
||||||
else if (isDLangEncoding(MangledName))
|
else if (isDLangEncoding(MangledName))
|
||||||
|
|
@ -58,7 +67,7 @@ bool llvm::nonMicrosoftDemangle(std::string_view MangledName,
|
||||||
if (!Demangled)
|
if (!Demangled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result = Demangled;
|
Result += Demangled;
|
||||||
std::free(Demangled);
|
std::free(Demangled);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -366,13 +366,13 @@ public:
|
||||||
|
|
||||||
using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
|
using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
|
||||||
|
|
||||||
char *llvm::itaniumDemangle(std::string_view MangledName) {
|
char *llvm::itaniumDemangle(std::string_view MangledName, bool ParseParams) {
|
||||||
if (MangledName.empty())
|
if (MangledName.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Demangler Parser(MangledName.data(),
|
Demangler Parser(MangledName.data(),
|
||||||
MangledName.data() + MangledName.length());
|
MangledName.data() + MangledName.length());
|
||||||
Node *AST = Parser.parse();
|
Node *AST = Parser.parse(ParseParams);
|
||||||
if (!AST)
|
if (!AST)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
|
|
@ -53,6 +54,18 @@ static bool consumeFront(std::string_view &S, std::string_view C) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool consumeFront(std::string_view &S, std::string_view PrefixA,
|
||||||
|
std::string_view PrefixB, bool A) {
|
||||||
|
const std::string_view &Prefix = A ? PrefixA : PrefixB;
|
||||||
|
return consumeFront(S, Prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool startsWith(std::string_view S, std::string_view PrefixA,
|
||||||
|
std::string_view PrefixB, bool A) {
|
||||||
|
const std::string_view &Prefix = A ? PrefixA : PrefixB;
|
||||||
|
return llvm::itanium_demangle::starts_with(S, Prefix);
|
||||||
|
}
|
||||||
|
|
||||||
static bool isMemberPointer(std::string_view MangledName, bool &Error) {
|
static bool isMemberPointer(std::string_view MangledName, bool &Error) {
|
||||||
Error = false;
|
Error = false;
|
||||||
const char F = MangledName.front();
|
const char F = MangledName.front();
|
||||||
|
|
@ -2256,6 +2269,18 @@ Demangler::demangleTemplateParameterList(std::string_view &MangledName) {
|
||||||
|
|
||||||
NodeList &TP = **Current;
|
NodeList &TP = **Current;
|
||||||
|
|
||||||
|
// <auto-nttp> ::= $ M <type> <nttp>
|
||||||
|
const bool IsAutoNTTP = consumeFront(MangledName, "$M");
|
||||||
|
if (IsAutoNTTP) {
|
||||||
|
// The deduced type of the auto NTTP parameter isn't printed so
|
||||||
|
// we want to ignore the AST created from demangling the type.
|
||||||
|
//
|
||||||
|
// TODO: Avoid the extra allocations to the bump allocator in this case.
|
||||||
|
(void)demangleType(MangledName, QualifierMangleMode::Drop);
|
||||||
|
if (Error)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
TemplateParameterReferenceNode *TPRN = nullptr;
|
TemplateParameterReferenceNode *TPRN = nullptr;
|
||||||
if (consumeFront(MangledName, "$$Y")) {
|
if (consumeFront(MangledName, "$$Y")) {
|
||||||
// Template alias
|
// Template alias
|
||||||
|
|
@ -2266,15 +2291,17 @@ Demangler::demangleTemplateParameterList(std::string_view &MangledName) {
|
||||||
} else if (consumeFront(MangledName, "$$C")) {
|
} else if (consumeFront(MangledName, "$$C")) {
|
||||||
// Type has qualifiers.
|
// Type has qualifiers.
|
||||||
TP.N = demangleType(MangledName, QualifierMangleMode::Mangle);
|
TP.N = demangleType(MangledName, QualifierMangleMode::Mangle);
|
||||||
} else if (llvm::itanium_demangle::starts_with(MangledName, "$1") ||
|
} else if (startsWith(MangledName, "$1", "1", !IsAutoNTTP) ||
|
||||||
llvm::itanium_demangle::starts_with(MangledName, "$H") ||
|
startsWith(MangledName, "$H", "H", !IsAutoNTTP) ||
|
||||||
llvm::itanium_demangle::starts_with(MangledName, "$I") ||
|
startsWith(MangledName, "$I", "I", !IsAutoNTTP) ||
|
||||||
llvm::itanium_demangle::starts_with(MangledName, "$J")) {
|
startsWith(MangledName, "$J", "J", !IsAutoNTTP)) {
|
||||||
// Pointer to member
|
// Pointer to member
|
||||||
TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
|
TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
|
||||||
TPRN->IsMemberPointer = true;
|
TPRN->IsMemberPointer = true;
|
||||||
|
|
||||||
MangledName.remove_prefix(1);
|
if (!IsAutoNTTP)
|
||||||
|
MangledName.remove_prefix(1); // Remove leading '$'
|
||||||
|
|
||||||
// 1 - single inheritance <name>
|
// 1 - single inheritance <name>
|
||||||
// H - multiple inheritance <name> <number>
|
// H - multiple inheritance <name> <number>
|
||||||
// I - virtual inheritance <name> <number> <number>
|
// I - virtual inheritance <name> <number> <number>
|
||||||
|
|
@ -2317,12 +2344,13 @@ Demangler::demangleTemplateParameterList(std::string_view &MangledName) {
|
||||||
TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
|
TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
|
||||||
TPRN->Symbol = parse(MangledName);
|
TPRN->Symbol = parse(MangledName);
|
||||||
TPRN->Affinity = PointerAffinity::Reference;
|
TPRN->Affinity = PointerAffinity::Reference;
|
||||||
} else if (llvm::itanium_demangle::starts_with(MangledName, "$F") ||
|
} else if (startsWith(MangledName, "$F", "F", !IsAutoNTTP) ||
|
||||||
llvm::itanium_demangle::starts_with(MangledName, "$G")) {
|
startsWith(MangledName, "$G", "G", !IsAutoNTTP)) {
|
||||||
TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
|
TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
|
||||||
|
|
||||||
// Data member pointer.
|
// Data member pointer.
|
||||||
MangledName.remove_prefix(1);
|
if (!IsAutoNTTP)
|
||||||
|
MangledName.remove_prefix(1); // Remove leading '$'
|
||||||
char InheritanceSpecifier = MangledName.front();
|
char InheritanceSpecifier = MangledName.front();
|
||||||
MangledName.remove_prefix(1);
|
MangledName.remove_prefix(1);
|
||||||
|
|
||||||
|
|
@ -2342,7 +2370,7 @@ Demangler::demangleTemplateParameterList(std::string_view &MangledName) {
|
||||||
}
|
}
|
||||||
TPRN->IsMemberPointer = true;
|
TPRN->IsMemberPointer = true;
|
||||||
|
|
||||||
} else if (consumeFront(MangledName, "$0")) {
|
} else if (consumeFront(MangledName, "$0", "0", !IsAutoNTTP)) {
|
||||||
// Integral non-type template parameter
|
// Integral non-type template parameter
|
||||||
bool IsNegative = false;
|
bool IsNegative = false;
|
||||||
uint64_t Value = 0;
|
uint64_t Value = 0;
|
||||||
|
|
@ -2397,6 +2425,24 @@ void Demangler::dumpBackReferences() {
|
||||||
std::printf("\n");
|
std::printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<size_t>
|
||||||
|
llvm::getArm64ECInsertionPointInMangledName(std::string_view MangledName) {
|
||||||
|
std::string_view ProcessedName{MangledName};
|
||||||
|
|
||||||
|
// We only support this for MSVC-style C++ symbols.
|
||||||
|
if (!consumeFront(ProcessedName, '?'))
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
// The insertion point is just after the name of the symbol, so parse that to
|
||||||
|
// remove it from the processed name.
|
||||||
|
Demangler D;
|
||||||
|
D.demangleFullyQualifiedSymbolName(ProcessedName);
|
||||||
|
if (D.Error)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
return MangledName.length() - ProcessedName.length();
|
||||||
|
}
|
||||||
|
|
||||||
char *llvm::microsoftDemangle(std::string_view MangledName, size_t *NMangled,
|
char *llvm::microsoftDemangle(std::string_view MangledName, size_t *NMangled,
|
||||||
int *Status, MSDemangleFlags Flags) {
|
int *Status, MSDemangleFlags Flags) {
|
||||||
Demangler D;
|
Demangler D;
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 23578c7461634623a5de903370310b3af5140536
|
Subproject commit 14df4816411ee9e391df0cfe5a62f67afe9687d9
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -331,9 +331,9 @@ namespace hex::init {
|
||||||
// Draw version information
|
// Draw version information
|
||||||
// In debug builds, also display the current commit hash and branch
|
// In debug builds, also display the current commit hash and branch
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
const static auto VersionInfo = hex::format("{0} : {1}@{2}", ImHexApi::System::getImHexVersion(), ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash());
|
const static auto VersionInfo = hex::format("{0} : {1}@{2}", ImHexApi::System::getImHexVersion().get(), ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash());
|
||||||
#else
|
#else
|
||||||
const static auto VersionInfo = hex::format("{0}", ImHexApi::System::getImHexVersion());
|
const static auto VersionInfo = hex::format("{0}", ImHexApi::System::getImHexVersion().get());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
drawList->AddText(ImVec2((this->m_splashBackgroundTexture.getSize().x - ImGui::CalcTextSize(VersionInfo.c_str()).x) / 2, 105), ImColor(0xFF, 0xFF, 0xFF, 0xFF), VersionInfo.c_str());
|
drawList->AddText(ImVec2((this->m_splashBackgroundTexture.getSize().x - ImGui::CalcTextSize(VersionInfo.c_str()).x) / 2, 105), ImColor(0xFF, 0xFF, 0xFF, 0xFF), VersionInfo.c_str());
|
||||||
|
|
@ -497,7 +497,7 @@ namespace hex::init {
|
||||||
ImGui_ImplOpenGL3_Init("#version 150");
|
ImGui_ImplOpenGL3_Init("#version 150");
|
||||||
#elif defined(OS_WEB)
|
#elif defined(OS_WEB)
|
||||||
ImGui_ImplOpenGL3_Init();
|
ImGui_ImplOpenGL3_Init();
|
||||||
ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas");
|
ImGui_ImplGlfw_InstallEmscriptenCallbacks(m_window, "#canvas");
|
||||||
#else
|
#else
|
||||||
ImGui_ImplOpenGL3_Init("#version 130");
|
ImGui_ImplOpenGL3_Init("#version 130");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log some system information to aid debugging when users share their logs
|
// Log some system information to aid debugging when users share their logs
|
||||||
log::info("Welcome to ImHex {}!", ImHexApi::System::getImHexVersion());
|
log::info("Welcome to ImHex {}!", ImHexApi::System::getImHexVersion().get());
|
||||||
log::info("Compiled using commit {}@{}", ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash());
|
log::info("Compiled using commit {}@{}", ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash());
|
||||||
log::info("Running on {} {} ({})", ImHexApi::System::getOSName(), ImHexApi::System::getOSVersion(), ImHexApi::System::getArchitecture());
|
log::info("Running on {} {} ({})", ImHexApi::System::getOSName(), ImHexApi::System::getOSVersion(), ImHexApi::System::getArchitecture());
|
||||||
#if defined(OS_LINUX)
|
#if defined(OS_LINUX)
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@ EM_JS(void, resizeCanvas, (), {
|
||||||
js_resizeCanvas();
|
js_resizeCanvas();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
EM_JS(bool, isMacOS, (), {
|
||||||
|
return navigator.userAgent.indexOf('Mac OS X') != -1
|
||||||
|
});
|
||||||
|
|
||||||
EM_JS(void, fixCanvasInPlace, (), {
|
EM_JS(void, fixCanvasInPlace, (), {
|
||||||
document.getElementById('canvas').classList.add('canvas-fixed');
|
document.getElementById('canvas').classList.add('canvas-fixed');
|
||||||
});
|
});
|
||||||
|
|
@ -126,6 +130,9 @@ namespace hex {
|
||||||
|
|
||||||
if (themeFollowSystem)
|
if (themeFollowSystem)
|
||||||
EventOSThemeChanged::post();
|
EventOSThemeChanged::post();
|
||||||
|
|
||||||
|
if (isMacOS())
|
||||||
|
ShortcutManager::enableMacOSMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::beginNativeWindowFrame() {
|
void Window::beginNativeWindowFrame() {
|
||||||
|
|
|
||||||
|
|
@ -256,10 +256,17 @@ namespace hex {
|
||||||
RegionTop * (cursor.y < (window.top + border.y)) |
|
RegionTop * (cursor.y < (window.top + border.y)) |
|
||||||
RegionBottom * (cursor.y >= (window.bottom - border.y));
|
RegionBottom * (cursor.y >= (window.bottom - border.y));
|
||||||
|
|
||||||
if (result != 0 && (ImGui::IsAnyItemHovered() || ImGui::IsPopupOpen(nullptr, ImGuiPopupFlags_AnyPopupId))) {
|
if (result != 0 && (ImGui::IsAnyItemHovered())) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::IsPopupOpen(nullptr, ImGuiPopupFlags_AnyPopupId)) {
|
||||||
|
if (result == RegionClient)
|
||||||
|
return HTCLIENT;
|
||||||
|
else
|
||||||
|
return HTCAPTION;
|
||||||
|
}
|
||||||
|
|
||||||
std::string_view hoveredWindowName = GImGui->HoveredWindow == nullptr ? "" : GImGui->HoveredWindow->Name;
|
std::string_view hoveredWindowName = GImGui->HoveredWindow == nullptr ? "" : GImGui->HoveredWindow->Name;
|
||||||
|
|
||||||
if (!ImHexApi::System::impl::isWindowResizable()) {
|
if (!ImHexApi::System::impl::isWindowResizable()) {
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,10 @@ namespace hex {
|
||||||
EventImHexStartupFinished::post();
|
EventImHexStartupFinished::post();
|
||||||
|
|
||||||
TutorialManager::init();
|
TutorialManager::init();
|
||||||
|
|
||||||
|
#if defined(OS_MACOS)
|
||||||
|
ShortcutManager::enableMacOSMode();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window() {
|
Window::~Window() {
|
||||||
|
|
@ -525,17 +529,18 @@ namespace hex {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string localizedName = name.get();
|
||||||
if (currPopup->isModal())
|
if (currPopup->isModal())
|
||||||
createPopup(ImGui::BeginPopupModal(name, closeButton, flags));
|
createPopup(ImGui::BeginPopupModal(localizedName.c_str(), closeButton, flags));
|
||||||
else
|
else
|
||||||
createPopup(ImGui::BeginPopup(name, flags));
|
createPopup(ImGui::BeginPopup(localizedName.c_str(), flags));
|
||||||
|
|
||||||
if (!ImGui::IsPopupOpen(name) && displayFrameCount < 5) {
|
if (!ImGui::IsPopupOpen(localizedName.c_str()) && displayFrameCount < 5) {
|
||||||
ImGui::OpenPopup(name);
|
ImGui::OpenPopup(localizedName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currPopup->shouldClose() || !open) {
|
if (currPopup->shouldClose() || !open) {
|
||||||
log::debug("Closing popup '{}'", name);
|
log::debug("Closing popup '{}'", localizedName);
|
||||||
positionSet = sizeSet = false;
|
positionSet = sizeSet = false;
|
||||||
|
|
||||||
currPopup = nullptr;
|
currPopup = nullptr;
|
||||||
|
|
@ -881,13 +886,12 @@ namespace hex {
|
||||||
EventWindowFocused::post(focused == GLFW_TRUE);
|
EventWindowFocused::post(focused == GLFW_TRUE);
|
||||||
});
|
});
|
||||||
|
|
||||||
#if !defined(OS_WEB)
|
|
||||||
// Register key press callback
|
// Register key press callback
|
||||||
glfwSetInputMode(m_window, GLFW_LOCK_KEY_MODS, GLFW_TRUE);
|
glfwSetInputMode(m_window, GLFW_LOCK_KEY_MODS, GLFW_TRUE);
|
||||||
glfwSetKeyCallback(m_window, [](GLFWwindow *window, int key, int scanCode, int action, int mods) {
|
glfwSetKeyCallback(m_window, [](GLFWwindow *window, int key, int scanCode, int action, int mods) {
|
||||||
std::ignore = mods;
|
std::ignore = mods;
|
||||||
|
|
||||||
|
#if !defined(OS_WEB)
|
||||||
// Handle A-Z keys using their ASCII value instead of the keycode
|
// Handle A-Z keys using their ASCII value instead of the keycode
|
||||||
if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) {
|
if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) {
|
||||||
std::string_view name = glfwGetKeyName(key, scanCode);
|
std::string_view name = glfwGetKeyName(key, scanCode);
|
||||||
|
|
@ -902,6 +906,10 @@ namespace hex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
std::ignore = scanCode;
|
||||||
|
// Emscripten doesn't support glfwGetKeyName. Just pass the value through.
|
||||||
|
#endif
|
||||||
|
|
||||||
if (key == GLFW_KEY_UNKNOWN) return;
|
if (key == GLFW_KEY_UNKNOWN) return;
|
||||||
|
|
||||||
|
|
@ -930,7 +938,6 @@ namespace hex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#endif
|
|
||||||
|
|
||||||
// Register window close callback
|
// Register window close callback
|
||||||
glfwSetWindowCloseCallback(m_window, [](GLFWwindow *window) {
|
glfwSetWindowCloseCallback(m_window, [](GLFWwindow *window) {
|
||||||
|
|
@ -1035,7 +1042,7 @@ namespace hex {
|
||||||
ImGui_ImplOpenGL3_Init("#version 150");
|
ImGui_ImplOpenGL3_Init("#version 150");
|
||||||
#elif defined(OS_WEB)
|
#elif defined(OS_WEB)
|
||||||
ImGui_ImplOpenGL3_Init();
|
ImGui_ImplOpenGL3_Init();
|
||||||
ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas");
|
ImGui_ImplGlfw_InstallEmscriptenCallbacks(m_window, "#canvas");
|
||||||
#else
|
#else
|
||||||
ImGui_ImplOpenGL3_Init("#version 130");
|
ImGui_ImplOpenGL3_Init("#version 130");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
[[nodiscard]] u64 getActualSize() const override { return 0x00; }
|
[[nodiscard]] u64 getActualSize() const override { return 0x00; }
|
||||||
|
|
||||||
[[nodiscard]] std::string getName() const override { return "None"; }
|
[[nodiscard]] std::string getName() const override { return "ImHex"; }
|
||||||
[[nodiscard]] std::vector<Description> getDataDescription() const override { return { }; }
|
[[nodiscard]] std::vector<Description> getDataDescription() const override { return { }; }
|
||||||
|
|
||||||
void loadSettings(const nlohmann::json &settings) override { std::ignore = settings; }
|
void loadSettings(const nlohmann::json &settings) override { std::ignore = settings; }
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
bool download(const paths::impl::DefaultPath *pathType, const std::string &fileName, const std::string &url);
|
bool download(const paths::impl::DefaultPath *pathType, const std::string &fileName, const std::string &url);
|
||||||
bool remove(const paths::impl::DefaultPath *pathType, const std::string &fileName);
|
bool remove(const paths::impl::DefaultPath *pathType, const std::string &fileName);
|
||||||
|
void updateAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HttpRequest m_httpRequest = HttpRequest("GET", "");
|
HttpRequest m_httpRequest = HttpRequest("GET", "");
|
||||||
|
|
|
||||||
|
|
@ -1014,6 +1014,8 @@
|
||||||
"hex.builtin.view.pattern_editor.shortcut.move_word_right": "Move Cursor One Word to the Right",
|
"hex.builtin.view.pattern_editor.shortcut.move_word_right": "Move Cursor One Word to the Right",
|
||||||
"hex.builtin.view.pattern_editor.shortcut.move_up": "Move Cursor One Line Up",
|
"hex.builtin.view.pattern_editor.shortcut.move_up": "Move Cursor One Line Up",
|
||||||
"hex.builtin.view.pattern_editor.shortcut.move_down": "Move Cursor One Line Down",
|
"hex.builtin.view.pattern_editor.shortcut.move_down": "Move Cursor One Line Down",
|
||||||
|
"hex.builtin.view.pattern_editor.shortcut.move_pixel_up": "Move Cursor One Pixel Up",
|
||||||
|
"hex.builtin.view.pattern_editor.shortcut.move_pixel_down": "Move Cursor One Pixel Down",
|
||||||
"hex.builtin.view.pattern_editor.shortcut.move_page_up": "Move Cursor One Page Up",
|
"hex.builtin.view.pattern_editor.shortcut.move_page_up": "Move Cursor One Page Up",
|
||||||
"hex.builtin.view.pattern_editor.shortcut.move_page_down": "Move Cursor One Page Down",
|
"hex.builtin.view.pattern_editor.shortcut.move_page_down": "Move Cursor One Page Down",
|
||||||
"hex.builtin.view.pattern_editor.shortcut.move_home": "Move Cursor to the Start of the Line",
|
"hex.builtin.view.pattern_editor.shortcut.move_home": "Move Cursor to the Start of the Line",
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace hex::plugin::builtin {
|
||||||
std::ignore = args;
|
std::ignore = args;
|
||||||
|
|
||||||
hex::log::print(std::string(romfs::get("logo.ans").string()),
|
hex::log::print(std::string(romfs::get("logo.ans").string()),
|
||||||
ImHexApi::System::getImHexVersion(),
|
ImHexApi::System::getImHexVersion().get(),
|
||||||
ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash(),
|
ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash(),
|
||||||
__DATE__, __TIME__,
|
__DATE__, __TIME__,
|
||||||
ImHexApi::System::isPortableVersion() ? "Portable" : "Installed");
|
ImHexApi::System::isPortableVersion() ? "Portable" : "Installed");
|
||||||
|
|
@ -142,10 +142,10 @@ namespace hex::plugin::builtin {
|
||||||
hex::log::println("Loaded plugins:");
|
hex::log::println("Loaded plugins:");
|
||||||
|
|
||||||
for (const auto &plugin : PluginManager::getPlugins()) {
|
for (const auto &plugin : PluginManager::getPlugins()) {
|
||||||
|
if (plugin.isLibraryPlugin()) continue;
|
||||||
|
|
||||||
hex::log::print("- \033[1m{}\033[0m", plugin.getPluginName());
|
hex::log::print("- \033[1m{}\033[0m", plugin.getPluginName());
|
||||||
|
|
||||||
hex::log::println(" by {}", plugin.getPluginAuthor());
|
hex::log::println(" by {}", plugin.getPluginAuthor());
|
||||||
|
|
||||||
hex::log::println(" \033[2;3m{}\033[0m", plugin.getPluginDescription());
|
hex::log::println(" \033[2;3m{}\033[0m", plugin.getPluginDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace hex::plugin::builtin {
|
||||||
nlohmann::json result;
|
nlohmann::json result;
|
||||||
|
|
||||||
result["build"] = {
|
result["build"] = {
|
||||||
{ "version", ImHexApi::System::getImHexVersion() },
|
{ "version", ImHexApi::System::getImHexVersion().get() },
|
||||||
{ "commit", ImHexApi::System::getCommitHash(true) },
|
{ "commit", ImHexApi::System::getCommitHash(true) },
|
||||||
{ "branch", ImHexApi::System::getCommitBranch() }
|
{ "branch", ImHexApi::System::getCommitBranch() }
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -226,11 +226,15 @@ namespace hex::plugin::builtin {
|
||||||
});
|
});
|
||||||
|
|
||||||
EventWindowInitialized::subscribe([] {
|
EventWindowInitialized::subscribe([] {
|
||||||
if (ContentRegistry::Settings::read<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", "") == "") {
|
const auto currVersion = ImHexApi::System::getImHexVersion();
|
||||||
|
const auto prevLaunchVersion = ContentRegistry::Settings::read<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", "");
|
||||||
|
if (prevLaunchVersion == "") {
|
||||||
EventFirstLaunch::post();
|
EventFirstLaunch::post();
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentRegistry::Settings::write<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", ImHexApi::System::getImHexVersion());
|
EventImHexUpdated::post(SemanticVersion(prevLaunchVersion), currVersion);
|
||||||
|
|
||||||
|
ContentRegistry::Settings::write<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", currVersion.get(false));
|
||||||
});
|
});
|
||||||
|
|
||||||
EventWindowDeinitializing::subscribe([](GLFWwindow *window) {
|
EventWindowDeinitializing::subscribe([](GLFWwindow *window) {
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,7 @@ namespace hex::plugin::builtin {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Convert the current version string to a format that can be compared to the latest release
|
// Convert the current version string to a format that can be compared to the latest release
|
||||||
auto versionString = ImHexApi::System::getImHexVersion();
|
auto currVersion = "v" + ImHexApi::System::getImHexVersion().get(false);
|
||||||
size_t versionLength = std::min(versionString.find_first_of('-'), versionString.length());
|
|
||||||
auto currVersion = "v" + versionString.substr(0, versionLength);
|
|
||||||
|
|
||||||
// Get the latest release version string
|
// Get the latest release version string
|
||||||
auto latestVersion = releases["tag_name"].get<std::string_view>();
|
auto latestVersion = releases["tag_name"].get<std::string_view>();
|
||||||
|
|
@ -59,7 +57,7 @@ namespace hex::plugin::builtin {
|
||||||
ContentRegistry::Settings::write<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", uuid);
|
ContentRegistry::Settings::write<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskManager::createBackgroundTask("hex.builtin.task.sending_statistics"_lang, [uuid, versionString](auto&) {
|
TaskManager::createBackgroundTask("hex.builtin.task.sending_statistics"_lang, [uuid](auto&) {
|
||||||
// To avoid potentially flooding our database with lots of dead users
|
// To avoid potentially flooding our database with lots of dead users
|
||||||
// from people just visiting the website, don't send telemetry data from
|
// from people just visiting the website, don't send telemetry data from
|
||||||
// the web version
|
// the web version
|
||||||
|
|
@ -71,7 +69,7 @@ namespace hex::plugin::builtin {
|
||||||
nlohmann::json telemetry = {
|
nlohmann::json telemetry = {
|
||||||
{ "uuid", uuid },
|
{ "uuid", uuid },
|
||||||
{ "format_version", "1" },
|
{ "format_version", "1" },
|
||||||
{ "imhex_version", versionString },
|
{ "imhex_version", ImHexApi::System::getImHexVersion().get(false) },
|
||||||
{ "imhex_commit", fmt::format("{}@{}", ImHexApi::System::getCommitHash(true), ImHexApi::System::getCommitBranch()) },
|
{ "imhex_commit", fmt::format("{}@{}", ImHexApi::System::getCommitHash(true), ImHexApi::System::getCommitBranch()) },
|
||||||
{ "install_type", ImHexApi::System::isPortableVersion() ? "Portable" : "Installed" },
|
{ "install_type", ImHexApi::System::isPortableVersion() ? "Portable" : "Installed" },
|
||||||
{ "os", ImHexApi::System::getOSName() },
|
{ "os", ImHexApi::System::getOSName() },
|
||||||
|
|
|
||||||
|
|
@ -298,7 +298,7 @@ namespace hex::plugin::builtin {
|
||||||
ImGui::TextUnformatted("hex.builtin.oobe.server_contact.data_collected.version"_lang);
|
ImGui::TextUnformatted("hex.builtin.oobe.server_contact.data_collected.version"_lang);
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGuiExt::TextFormattedWrapped("{}\n{}@{}\n{}",
|
ImGuiExt::TextFormattedWrapped("{}\n{}@{}\n{}",
|
||||||
ImHexApi::System::getImHexVersion(),
|
ImHexApi::System::getImHexVersion().get(),
|
||||||
ImHexApi::System::getCommitHash(true),
|
ImHexApi::System::getCommitHash(true),
|
||||||
ImHexApi::System::getCommitBranch(),
|
ImHexApi::System::getCommitBranch(),
|
||||||
ImHexApi::System::isPortableVersion() ? "Portable" : "Installed"
|
ImHexApi::System::isPortableVersion() ? "Portable" : "Installed"
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ namespace hex::plugin::builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto metadataContent = hex::format("{}\n{}", MetadataHeaderMagic, ImHexApi::System::getImHexVersion());
|
const auto metadataContent = hex::format("{}\n{}", MetadataHeaderMagic, ImHexApi::System::getImHexVersion().get(false));
|
||||||
tar.writeString(MetadataPath, metadataContent);
|
tar.writeString(MetadataPath, metadataContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -285,9 +285,7 @@ namespace hex::plugin::builtin {
|
||||||
|
|
||||||
ImGui::BeginDisabled(m_drawShortcut.matches(m_defaultShortcut));
|
ImGui::BeginDisabled(m_drawShortcut.matches(m_defaultShortcut));
|
||||||
if (ImGuiExt::IconButton(ICON_VS_X, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
if (ImGuiExt::IconButton(ICON_VS_X, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||||
m_hasDuplicate = !ShortcutManager::updateShortcut(m_shortcut, m_defaultShortcut, m_view);
|
this->reset();
|
||||||
|
|
||||||
m_drawShortcut = m_defaultShortcut;
|
|
||||||
if (!m_hasDuplicate) {
|
if (!m_hasDuplicate) {
|
||||||
m_shortcut = m_defaultShortcut;
|
m_shortcut = m_defaultShortcut;
|
||||||
settingChanged = true;
|
settingChanged = true;
|
||||||
|
|
@ -356,6 +354,12 @@ namespace hex::plugin::builtin {
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
m_hasDuplicate = !ShortcutManager::updateShortcut(m_shortcut, m_defaultShortcut, m_view);
|
||||||
|
|
||||||
|
m_drawShortcut = m_defaultShortcut;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool detectShortcut() {
|
bool detectShortcut() {
|
||||||
if (const auto &shortcut = ShortcutManager::getPreviousShortcut(); shortcut.has_value()) {
|
if (const auto &shortcut = ShortcutManager::getPreviousShortcut(); shortcut.has_value()) {
|
||||||
|
|
@ -971,6 +975,21 @@ namespace hex::plugin::builtin {
|
||||||
ContentRegistry::Settings::add<ToolbarIconsWidget>("hex.builtin.setting.toolbar", "", "hex.builtin.setting.toolbar.icons");
|
ContentRegistry::Settings::add<ToolbarIconsWidget>("hex.builtin.setting.toolbar", "", "hex.builtin.setting.toolbar.icons");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImHexApi::System::addMigrationRoutine("v1.36.1", [] {
|
||||||
|
log::warn("Resetting shortcut key settings for them to work with this version of ImHex");
|
||||||
|
|
||||||
|
for (const auto &category : ContentRegistry::Settings::impl::getSettings()) {
|
||||||
|
for (const auto &subcategory : category.subCategories) {
|
||||||
|
for (const auto &entry : subcategory.entries) {
|
||||||
|
if (auto keybindingWidget = dynamic_cast<KeybindingWidget*>(entry.widget.get())) {
|
||||||
|
keybindingWidget->reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentRegistry::Settings::impl::store();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loadLayoutSettings() {
|
static void loadLayoutSettings() {
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ namespace hex::plugin::builtin {
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
{
|
{
|
||||||
// Draw basic information about ImHex and its version
|
// Draw basic information about ImHex and its version
|
||||||
ImGuiExt::TextFormatted("ImHex Hex Editor v{} by WerWolv", ImHexApi::System::getImHexVersion());
|
ImGuiExt::TextFormatted("ImHex Hex Editor v{} by WerWolv", ImHexApi::System::getImHexVersion().get());
|
||||||
ImGui::Indent(25_scaled);
|
ImGui::Indent(25_scaled);
|
||||||
ImGuiExt::TextFormatted("Powered by Dear ImGui v{}", ImGui::GetVersion());
|
ImGuiExt::TextFormatted("Powered by Dear ImGui v{}", ImGui::GetVersion());
|
||||||
ImGui::Unindent(25_scaled);
|
ImGui::Unindent(25_scaled);
|
||||||
|
|
@ -582,9 +582,9 @@ namespace hex::plugin::builtin {
|
||||||
static ReleaseNotes notes;
|
static ReleaseNotes notes;
|
||||||
|
|
||||||
// Set up the request to get the release notes the first time the page is opened
|
// Set up the request to get the release notes the first time the page is opened
|
||||||
const static auto ImHexVersionString = ImHexApi::System::getImHexVersion(false);
|
const static auto ImHexVersion = ImHexApi::System::getImHexVersion();
|
||||||
AT_FIRST_TIME {
|
AT_FIRST_TIME {
|
||||||
static HttpRequest request("GET", GitHubApiURL + std::string("/releases/") + (ImHexVersionString.ends_with(".WIP") ? "latest" : ( "tags/v" + ImHexVersionString)));
|
static HttpRequest request("GET", GitHubApiURL + std::string("/releases/") + (ImHexVersion.nightly() ? "latest" : ( "tags/v" + ImHexVersion.get(false))));
|
||||||
|
|
||||||
m_releaseNoteRequest = request.execute();
|
m_releaseNoteRequest = request.execute();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,14 @@ namespace hex::plugin::builtin {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load settings
|
// Load settings
|
||||||
m_showPopup = ContentRegistry::Settings::read<bool>("hex.builtin.setting.interface", "hex.builtin.setting.interface.achievement_popup", true);
|
{
|
||||||
|
bool defaultValue = true;
|
||||||
|
#if defined(OS_WEB)
|
||||||
|
defaultValue = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_showPopup = ContentRegistry::Settings::read<bool>("hex.builtin.setting.interface", "hex.builtin.setting.interface.achievement_popup", defaultValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewAchievements::~ViewAchievements() {
|
ViewAchievements::~ViewAchievements() {
|
||||||
|
|
|
||||||
|
|
@ -496,8 +496,10 @@ namespace hex::plugin::builtin {
|
||||||
editor.SetShowWhitespaces(false);
|
editor.SetShowWhitespaces(false);
|
||||||
|
|
||||||
if (!locked || (locked && !comment.empty())) {
|
if (!locked || (locked && !comment.empty())) {
|
||||||
ImGuiExt::Header("hex.builtin.view.bookmarks.header.comment"_lang);
|
if (ImGuiExt::BeginSubWindow("hex.builtin.view.bookmarks.header.comment"_lang)) {
|
||||||
editor.Render("##comment", ImVec2(ImGui::GetContentRegionAvail().x, 150_scaled), true);
|
editor.Render("##comment", ImVec2(ImGui::GetContentRegionAvail().x, 150_scaled), false);
|
||||||
|
}
|
||||||
|
ImGuiExt::EndSubWindow();
|
||||||
|
|
||||||
if (editor.IsTextChanged())
|
if (editor.IsTextChanged())
|
||||||
comment = editor.GetText();
|
comment = editor.GetText();
|
||||||
|
|
|
||||||
|
|
@ -2513,6 +2513,11 @@ namespace hex::plugin::builtin {
|
||||||
editor->MoveUp(1, false);
|
editor->MoveUp(1, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ShortcutManager::addShortcut(this, ALT + Keys::Up + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_pixel_up", [this] {
|
||||||
|
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
|
||||||
|
editor->MoveUp(-1, false);
|
||||||
|
});
|
||||||
|
|
||||||
ShortcutManager::addShortcut(this, Keys::PageUp + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_page_up", [this] {
|
ShortcutManager::addShortcut(this, Keys::PageUp + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_page_up", [this] {
|
||||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
|
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
|
||||||
editor->MoveUp(editor->GetPageSize()-4, false);
|
editor->MoveUp(editor->GetPageSize()-4, false);
|
||||||
|
|
@ -2523,6 +2528,11 @@ namespace hex::plugin::builtin {
|
||||||
editor->MoveDown(1, false);
|
editor->MoveDown(1, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ShortcutManager::addShortcut(this, ALT+ Keys::Down + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_pixel_down", [this] {
|
||||||
|
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
|
||||||
|
editor->MoveDown(-1, false);
|
||||||
|
});
|
||||||
|
|
||||||
ShortcutManager::addShortcut(this, Keys::PageDown + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_page_down", [this] {
|
ShortcutManager::addShortcut(this, Keys::PageDown + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_page_down", [this] {
|
||||||
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
|
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
|
||||||
editor->MoveDown(editor->GetPageSize()-4, false);
|
editor->MoveDown(editor->GetPageSize()-4, false);
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,16 @@ namespace hex::plugin::builtin {
|
||||||
ThemeManager::addTheme(themeFile.readString());
|
ThemeManager::addTheme(themeFile.readString());
|
||||||
});
|
});
|
||||||
addCategory("hex.builtin.view.store.tab.yara", "yara", &paths::Yara);
|
addCategory("hex.builtin.view.store.tab.yara", "yara", &paths::Yara);
|
||||||
|
|
||||||
|
TaskManager::doLater([this] {
|
||||||
|
// Force update all installed items after an update so that there's no old and incompatible versions around anymore
|
||||||
|
{
|
||||||
|
const auto prevUpdateVersion = ContentRegistry::Settings::read<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", "");
|
||||||
|
if (SemanticVersion(prevUpdateVersion) != ImHexApi::System::getImHexVersion()) {
|
||||||
|
updateAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -197,28 +207,7 @@ namespace hex::plugin::builtin {
|
||||||
ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - 25_scaled);
|
ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - 25_scaled);
|
||||||
ImGui::BeginDisabled(m_updateAllTask.isRunning() || m_updateCount == 0);
|
ImGui::BeginDisabled(m_updateAllTask.isRunning() || m_updateCount == 0);
|
||||||
if (ImGuiExt::IconButton(ICON_VS_CLOUD_DOWNLOAD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
if (ImGuiExt::IconButton(ICON_VS_CLOUD_DOWNLOAD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||||
m_updateAllTask = TaskManager::createTask("hex.builtin.task.updating_store"_lang, m_updateCount, [this](auto &task) {
|
this->updateAll();
|
||||||
for (auto &category : m_categories) {
|
|
||||||
for (auto &entry : category.entries) {
|
|
||||||
if (entry.hasUpdate) {
|
|
||||||
entry.downloading = this->download(category.path, entry.fileName, entry.link);
|
|
||||||
if (!m_download.valid())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
m_download.wait();
|
|
||||||
|
|
||||||
while (m_download.valid() && m_download.wait_for(100ms) != std::future_status::ready) {
|
|
||||||
task.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
entry.hasUpdate = false;
|
|
||||||
entry.downloading = false;
|
|
||||||
|
|
||||||
task.increment();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
ImGuiExt::InfoTooltip(hex::format("hex.builtin.view.store.update_count"_lang, m_updateCount.load()).c_str());
|
ImGuiExt::InfoTooltip(hex::format("hex.builtin.view.store.update_count"_lang, m_updateCount.load()).c_str());
|
||||||
|
|
||||||
|
|
@ -346,6 +335,36 @@ namespace hex::plugin::builtin {
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewStore::updateAll() {
|
||||||
|
m_updateAllTask = TaskManager::createTask("hex.builtin.task.updating_store"_lang, m_updateCount, [this](auto &task) {
|
||||||
|
for (auto &category : m_categories) {
|
||||||
|
for (auto &entry : category.entries) {
|
||||||
|
if (entry.hasUpdate) {
|
||||||
|
entry.downloading = this->download(category.path, entry.fileName, entry.link);
|
||||||
|
if (!m_download.valid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_download.wait();
|
||||||
|
|
||||||
|
while (m_download.valid() && m_download.wait_for(100ms) != std::future_status::ready) {
|
||||||
|
task.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.hasUpdate = false;
|
||||||
|
entry.downloading = false;
|
||||||
|
|
||||||
|
task.increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskManager::doLater([] {
|
||||||
|
ContentRegistry::Settings::write<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", ImHexApi::System::getImHexVersion().get(false));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ViewStore::addCategory(const UnlocalizedString &unlocalizedName, const std::string &requestName, const paths::impl::DefaultPath *path, std::function<void()> downloadCallback) {
|
void ViewStore::addCategory(const UnlocalizedString &unlocalizedName, const std::string &requestName, const paths::impl::DefaultPath *path, std::function<void()> downloadCallback) {
|
||||||
m_categories.push_back({ unlocalizedName, requestName, path, { }, std::move(downloadCallback) });
|
m_categories.push_back({ unlocalizedName, requestName, path, { }, std::move(downloadCallback) });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ IMHEX_PLUGIN_SUBCOMMANDS() {
|
||||||
{ "pl", "", "Interact with the pattern language", hex::plugin::builtin::handlePatternLanguageCommand },
|
{ "pl", "", "Interact with the pattern language", hex::plugin::builtin::handlePatternLanguageCommand },
|
||||||
{ "hexdump", "", "Generate a hex dump of the provided file", hex::plugin::builtin::handleHexdumpCommand },
|
{ "hexdump", "", "Generate a hex dump of the provided file", hex::plugin::builtin::handleHexdumpCommand },
|
||||||
{ "demangle", "", "Demangle a mangled symbol", hex::plugin::builtin::handleDemangleCommand },
|
{ "demangle", "", "Demangle a mangled symbol", hex::plugin::builtin::handleDemangleCommand },
|
||||||
{ "reset-settings", "", "Demangle a mangled symbol", hex::plugin::builtin::handleSettingsResetCommand },
|
{ "reset-settings", "", "Resets all settings back to default", hex::plugin::builtin::handleSettingsResetCommand },
|
||||||
};
|
};
|
||||||
|
|
||||||
IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") {
|
IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") {
|
||||||
|
|
|
||||||
|
|
@ -104,21 +104,23 @@ namespace hex::plugin::disasm {
|
||||||
std::vector<u8> data(std::min<u64>(32, evaluator->getSectionSize(sectionId) - address));
|
std::vector<u8> data(std::min<u64>(32, evaluator->getSectionSize(sectionId) - address));
|
||||||
evaluator->readData(address, data.data(), data.size(), sectionId);
|
evaluator->readData(address, data.data(), data.size(), sectionId);
|
||||||
|
|
||||||
cs_insn instruction;
|
auto *instruction = cs_malloc(capstone);
|
||||||
|
ON_SCOPE_EXIT { cs_free(instruction, 1); };
|
||||||
|
|
||||||
const u8 *code = data.data();
|
const u8 *code = data.data();
|
||||||
size_t dataSize = data.size();
|
size_t dataSize = data.size();
|
||||||
if (!cs_disasm_iter(capstone, &code, &dataSize, &instructionLoadAddress, &instruction)) {
|
if (!cs_disasm_iter(capstone, &code, &dataSize, &instructionLoadAddress, instruction)) {
|
||||||
err::E0012.throwError("Failed to disassemble instruction");
|
err::E0012.throwError("Failed to disassemble instruction");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = std::make_unique<PatternInstruction>(evaluator, address, instruction.size, 0);
|
auto result = std::make_unique<PatternInstruction>(evaluator, address, instruction->size, 0);
|
||||||
|
|
||||||
std::string instructionString;
|
std::string instructionString;
|
||||||
if (instruction.mnemonic[0] != '\x00')
|
if (instruction->mnemonic[0] != '\x00')
|
||||||
instructionString += instruction.mnemonic;
|
instructionString += instruction->mnemonic;
|
||||||
if (instruction.op_str[0] != '\x00') {
|
if (instruction->op_str[0] != '\x00') {
|
||||||
instructionString += ' ';
|
instructionString += ' ';
|
||||||
instructionString += instruction.op_str;
|
instructionString += instruction->op_str;
|
||||||
}
|
}
|
||||||
result->setInstructionString(instructionString);
|
result->setInstructionString(instructionString);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,14 @@ namespace hex::plugin::disasm {
|
||||||
|
|
||||||
m_disassemblerTask = TaskManager::createTask("hex.disassembler.view.disassembler.disassembling"_lang, m_regionToDisassemble.getSize(), [this](auto &task) {
|
m_disassemblerTask = TaskManager::createTask("hex.disassembler.view.disassembler.disassembling"_lang, m_regionToDisassemble.getSize(), [this](auto &task) {
|
||||||
csh capstoneHandle;
|
csh capstoneHandle;
|
||||||
cs_insn instruction;
|
|
||||||
|
|
||||||
cs_mode mode = m_mode;
|
cs_mode mode = m_mode;
|
||||||
|
|
||||||
// Create a capstone disassembler instance
|
// Create a capstone disassembler instance
|
||||||
if (cs_open(Disassembler::toCapstoneArchitecture(m_architecture), mode, &capstoneHandle) == CS_ERR_OK) {
|
if (cs_open(Disassembler::toCapstoneArchitecture(m_architecture), mode, &capstoneHandle) == CS_ERR_OK) {
|
||||||
|
auto *instruction = cs_malloc(capstoneHandle);
|
||||||
|
ON_SCOPE_EXIT { cs_free(instruction, 1); };
|
||||||
|
|
||||||
|
|
||||||
// Tell capstone to skip data bytes
|
// Tell capstone to skip data bytes
|
||||||
cs_option(capstoneHandle, CS_OPT_SKIPDATA, CS_OPT_ON);
|
cs_option(capstoneHandle, CS_OPT_SKIPDATA, CS_OPT_ON);
|
||||||
|
|
@ -75,24 +77,24 @@ namespace hex::plugin::disasm {
|
||||||
|
|
||||||
// Ask capstone to disassemble the data
|
// Ask capstone to disassemble the data
|
||||||
const u8 *code = buffer.data();
|
const u8 *code = buffer.data();
|
||||||
while (cs_disasm_iter(capstoneHandle, &code, &bufferSize, &instructionLoadAddress, &instruction)) {
|
while (cs_disasm_iter(capstoneHandle, &code, &bufferSize, &instructionLoadAddress, instruction)) {
|
||||||
task.update(instructionDataAddress);
|
task.update(instructionDataAddress);
|
||||||
|
|
||||||
// Convert the capstone instructions to our disassembly format
|
// Convert the capstone instructions to our disassembly format
|
||||||
Disassembly disassembly = { };
|
Disassembly disassembly = { };
|
||||||
disassembly.address = instruction.address;
|
disassembly.address = instruction->address;
|
||||||
disassembly.offset = instructionDataAddress - m_imageBaseAddress;
|
disassembly.offset = instructionDataAddress - m_imageBaseAddress;
|
||||||
disassembly.size = instruction.size;
|
disassembly.size = instruction->size;
|
||||||
disassembly.mnemonic = instruction.mnemonic;
|
disassembly.mnemonic = instruction->mnemonic;
|
||||||
disassembly.operators = instruction.op_str;
|
disassembly.operators = instruction->op_str;
|
||||||
|
|
||||||
for (u16 j = 0; j < instruction.size; j++)
|
for (u16 j = 0; j < instruction->size; j++)
|
||||||
disassembly.bytes += hex::format("{0:02X} ", instruction.bytes[j]);
|
disassembly.bytes += hex::format("{0:02X} ", instruction->bytes[j]);
|
||||||
disassembly.bytes.pop_back();
|
disassembly.bytes.pop_back();
|
||||||
|
|
||||||
m_disassembly.push_back(disassembly);
|
m_disassembly.push_back(disassembly);
|
||||||
|
|
||||||
instructionDataAddress += instruction.size;
|
instructionDataAddress += instruction->size;
|
||||||
hadError = false;
|
hadError = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,7 @@ namespace hex::plugin::hashes {
|
||||||
ImGui::OpenPopup("##CreateHash");
|
ImGui::OpenPopup("##CreateHash");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::SetNextWindowSize(scaled({ 400, 0 }), ImGuiCond_Always);
|
||||||
if (ImGui::BeginPopup("##CreateHash")) {
|
if (ImGui::BeginPopup("##CreateHash")) {
|
||||||
ImGuiExt::InputTextIcon("hex.hashes.view.hashes.hash_name"_lang, ICON_VS_SYMBOL_KEY, m_newHashName);
|
ImGuiExt::InputTextIcon("hex.hashes.view.hashes.hash_name"_lang, ICON_VS_SYMBOL_KEY, m_newHashName);
|
||||||
|
|
||||||
|
|
@ -175,7 +176,7 @@ namespace hex::plugin::hashes {
|
||||||
if (m_newHashName.empty() && m_selectedHash != nullptr)
|
if (m_newHashName.empty() && m_selectedHash != nullptr)
|
||||||
m_newHashName = hex::format("{} {}", Lang(m_selectedHash->getUnlocalizedName()), static_cast<const char *>("hex.hashes.view.hashes.hash"_lang));
|
m_newHashName = hex::format("{} {}", Lang(m_selectedHash->getUnlocalizedName()), static_cast<const char *>("hex.hashes.view.hashes.hash"_lang));
|
||||||
|
|
||||||
if (ImGuiExt::BeginSubWindow("hex.ui.common.settings"_lang, nullptr, scaled({ 400, 200 }))) {
|
if (ImGuiExt::BeginSubWindow("hex.ui.common.settings"_lang, nullptr, scaled({ 0, 250 }))) {
|
||||||
if (m_selectedHash != nullptr) {
|
if (m_selectedHash != nullptr) {
|
||||||
auto startPos = ImGui::GetCursorPosY();
|
auto startPos = ImGui::GetCursorPosY();
|
||||||
m_selectedHash->draw();
|
m_selectedHash->draw();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue