2021-08-29 14:18:45 +02:00
|
|
|
|
#include <hex/api/content_registry.hpp>
|
2021-09-21 02:29:54 +02:00
|
|
|
|
#include <hex/api/imhex_api.hpp>
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2021-08-28 00:45:59 +02:00
|
|
|
|
#include <hex/helpers/net.hpp>
|
2021-08-29 14:18:45 +02:00
|
|
|
|
#include <hex/helpers/shared_data.hpp>
|
2021-08-29 22:15:18 +02:00
|
|
|
|
#include <hex/helpers/utils.hpp>
|
|
|
|
|
#include <hex/helpers/fmt.hpp>
|
2021-09-22 17:56:06 +02:00
|
|
|
|
#include <hex/helpers/file.hpp>
|
|
|
|
|
#include <hex/helpers/literals.hpp>
|
2022-01-13 14:33:30 +01:00
|
|
|
|
#include <hex/helpers/paths.hpp>
|
2021-08-28 00:45:59 +02:00
|
|
|
|
|
2021-09-22 17:56:06 +02:00
|
|
|
|
#include <algorithm>
|
2021-08-28 00:45:59 +02:00
|
|
|
|
#include <chrono>
|
2021-09-22 17:56:06 +02:00
|
|
|
|
#include <random>
|
|
|
|
|
#include <regex>
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
|
|
|
|
#include <llvm/Demangle/Demangle.h>
|
|
|
|
|
#include "math_evaluator.hpp"
|
|
|
|
|
|
2021-08-29 14:18:45 +02:00
|
|
|
|
#include <imgui.h>
|
|
|
|
|
#define IMGUI_DEFINE_MATH_OPERATORS
|
|
|
|
|
#include <imgui_internal.h>
|
|
|
|
|
|
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
|
|
2021-01-22 18:01:39 +01:00
|
|
|
|
namespace hex::plugin::builtin {
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
2021-08-28 16:02:53 +02:00
|
|
|
|
using namespace std::literals::string_literals;
|
2021-08-28 00:45:59 +02:00
|
|
|
|
using namespace std::literals::chrono_literals;
|
2021-09-22 17:56:06 +02:00
|
|
|
|
using namespace hex::literals;
|
2021-08-28 00:45:59 +02:00
|
|
|
|
|
2021-01-22 18:01:39 +01:00
|
|
|
|
void drawDemangler() {
|
|
|
|
|
static std::vector<char> mangledBuffer(0xF'FFFF, 0x00);
|
|
|
|
|
static std::string demangledName;
|
|
|
|
|
|
2021-02-11 23:09:45 +01:00
|
|
|
|
if (ImGui::InputText("hex.builtin.tools.demangler.mangled"_lang, mangledBuffer.data(), 0xF'FFFF)) {
|
2021-01-22 18:01:39 +01:00
|
|
|
|
demangledName = llvm::demangle(mangledBuffer.data());
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-11 23:09:45 +01:00
|
|
|
|
ImGui::InputText("hex.builtin.tools.demangler.demangled"_lang, demangledName.data(), demangledName.size(), ImGuiInputTextFlags_ReadOnly);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void drawASCIITable() {
|
|
|
|
|
static bool asciiTableShowOctal = false;
|
|
|
|
|
|
|
|
|
|
ImGui::BeginTable("##asciitable", 4);
|
|
|
|
|
ImGui::TableSetupColumn("");
|
|
|
|
|
ImGui::TableSetupColumn("");
|
|
|
|
|
ImGui::TableSetupColumn("");
|
|
|
|
|
ImGui::TableSetupColumn("");
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
|
|
for (u8 tablePart = 0; tablePart < 4; tablePart++) {
|
|
|
|
|
ImGui::BeginTable("##asciitablepart", asciiTableShowOctal ? 4 : 3, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg);
|
|
|
|
|
ImGui::TableSetupColumn("dec");
|
|
|
|
|
if (asciiTableShowOctal)
|
|
|
|
|
ImGui::TableSetupColumn("oct");
|
|
|
|
|
ImGui::TableSetupColumn("hex");
|
|
|
|
|
ImGui::TableSetupColumn("char");
|
|
|
|
|
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
|
|
|
|
|
u32 rowCount = 0;
|
|
|
|
|
for (u8 i = 0; i < 0x80 / 4; i++) {
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
2021-12-31 01:10:06 +01:00
|
|
|
|
ImGui::TextFormatted("{0:03d}", i + 32 * tablePart);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
|
|
|
|
if (asciiTableShowOctal) {
|
|
|
|
|
ImGui::TableNextColumn();
|
2021-12-31 01:10:06 +01:00
|
|
|
|
ImGui::TextFormatted("0o{0:03o}", i + 32 * tablePart);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
2021-12-31 01:10:06 +01:00
|
|
|
|
ImGui::TextFormatted("0x{0:02X}", i + 32 * tablePart);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
2021-12-31 01:10:06 +01:00
|
|
|
|
ImGui::TextFormatted("{0}", hex::makePrintable(i + 32 * tablePart));
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
|
|
|
|
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ((rowCount % 2) == 0) ? 0xFF101010 : 0xFF303030);
|
|
|
|
|
|
|
|
|
|
rowCount++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
|
2021-02-11 23:09:45 +01:00
|
|
|
|
ImGui::Checkbox("hex.builtin.tools.ascii_table.octal"_lang, &asciiTableShowOctal);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void drawRegexReplacer() {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
static auto regexInput = [] { std::string s; s.reserve(0xFFF); return s; }();
|
|
|
|
|
static auto regexPattern = [] { std::string s; s.reserve(0xFFF); return s; }();
|
|
|
|
|
static auto replacePattern = [] { std::string s; s.reserve(0xFFF); return s; }();
|
|
|
|
|
static auto regexOutput = [] { std::string s; s.reserve(0xFFF); return s; }();
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
|
bool changed1 = ImGui::InputText("hex.builtin.tools.regex_replacer.pattern"_lang, regexPattern.data(), regexPattern.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, ®exPattern);
|
|
|
|
|
bool changed2 = ImGui::InputText("hex.builtin.tools.regex_replacer.replace"_lang, replacePattern.data(), replacePattern.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &replacePattern);
|
|
|
|
|
bool changed3 = ImGui::InputTextMultiline("hex.builtin.tools.regex_replacer.input"_lang, regexInput.data(), regexInput.capacity(), ImVec2(0, 0), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, ®exInput);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2021-09-20 23:50:37 +02:00
|
|
|
|
if (changed1 || changed2 || changed3) {
|
2021-01-22 18:01:39 +01:00
|
|
|
|
try {
|
|
|
|
|
regexOutput = std::regex_replace(regexInput.data(), std::regex(regexPattern.data()), replacePattern.data());
|
2022-01-24 20:53:17 +01:00
|
|
|
|
} catch (std::regex_error &) { }
|
2021-01-22 18:01:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-20 23:50:37 +02:00
|
|
|
|
ImGui::InputTextMultiline("hex.builtin.tools.regex_replacer.output"_lang, regexOutput.data(), regexOutput.size(), ImVec2(0, 0), ImGuiInputTextFlags_ReadOnly);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void drawColorPicker() {
|
|
|
|
|
static std::array<float, 4> pickedColor = { 0 };
|
|
|
|
|
|
|
|
|
|
ImGui::SetNextItemWidth(300.0F);
|
2022-01-24 20:53:17 +01:00
|
|
|
|
ImGui::ColorPicker4("hex.builtin.tools.color"_lang, pickedColor.data(), ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void drawMathEvaluator() {
|
|
|
|
|
static std::vector<long double> mathHistory;
|
|
|
|
|
static std::string lastMathError;
|
2022-01-24 20:53:17 +01:00
|
|
|
|
static auto mathInput = [] {
|
2021-08-28 18:15:20 +02:00
|
|
|
|
std::string s;
|
|
|
|
|
s.reserve(0xFFFF);
|
|
|
|
|
std::memset(s.data(), 0x00, s.capacity());
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}();
|
|
|
|
|
bool evaluate = false;
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
static MathEvaluator mathEvaluator = [&] {
|
2021-01-22 18:01:39 +01:00
|
|
|
|
MathEvaluator evaluator;
|
|
|
|
|
|
|
|
|
|
evaluator.registerStandardVariables();
|
|
|
|
|
evaluator.registerStandardFunctions();
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
evaluator.setFunction(
|
|
|
|
|
"clear", [&](auto args) -> std::optional<long double> {
|
|
|
|
|
mathHistory.clear();
|
|
|
|
|
lastMathError.clear();
|
|
|
|
|
mathEvaluator.getVariables().clear();
|
|
|
|
|
mathEvaluator.registerStandardVariables();
|
|
|
|
|
mathInput.clear();
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
return {};
|
|
|
|
|
},
|
|
|
|
|
0,
|
|
|
|
|
0);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
evaluator.setFunction(
|
|
|
|
|
"read", [](auto args) -> std::optional<long double> {
|
|
|
|
|
u8 value = 0;
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
auto provider = ImHexApi::Provider::get();
|
|
|
|
|
if (!ImHexApi::Provider::isValid() || !provider->isReadable() || args[0] >= provider->getActualSize())
|
|
|
|
|
return {};
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
provider->read(args[0], &value, sizeof(u8));
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
return value;
|
|
|
|
|
},
|
|
|
|
|
1,
|
|
|
|
|
1);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
evaluator.setFunction(
|
|
|
|
|
"write", [](auto args) -> std::optional<long double> {
|
|
|
|
|
auto provider = ImHexApi::Provider::get();
|
|
|
|
|
if (!ImHexApi::Provider::isValid() || !provider->isWritable() || args[0] >= provider->getActualSize())
|
|
|
|
|
return {};
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
if (args[1] > 0xFF)
|
|
|
|
|
return {};
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
u8 value = args[1];
|
|
|
|
|
provider->write(args[0], &value, sizeof(u8));
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
return {};
|
|
|
|
|
},
|
|
|
|
|
2,
|
|
|
|
|
2);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
|
|
|
|
return std::move(evaluator);
|
|
|
|
|
}();
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
enum class MathDisplayType {
|
|
|
|
|
Standard,
|
|
|
|
|
Scientific,
|
|
|
|
|
Engineering,
|
|
|
|
|
Programmer
|
|
|
|
|
} mathDisplayType;
|
2021-01-22 18:01:39 +01:00
|
|
|
|
if (ImGui::BeginTabBar("##mathFormatTabBar")) {
|
2021-02-11 23:09:45 +01:00
|
|
|
|
if (ImGui::BeginTabItem("hex.builtin.tools.format.standard"_lang)) {
|
2021-01-22 18:01:39 +01:00
|
|
|
|
mathDisplayType = MathDisplayType::Standard;
|
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
|
}
|
2021-02-11 23:09:45 +01:00
|
|
|
|
if (ImGui::BeginTabItem("hex.builtin.tools.format.scientific"_lang)) {
|
2021-01-22 18:01:39 +01:00
|
|
|
|
mathDisplayType = MathDisplayType::Scientific;
|
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
|
}
|
2021-02-11 23:09:45 +01:00
|
|
|
|
if (ImGui::BeginTabItem("hex.builtin.tools.format.engineering"_lang)) {
|
2021-01-22 18:01:39 +01:00
|
|
|
|
mathDisplayType = MathDisplayType::Engineering;
|
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
|
}
|
2021-02-11 23:09:45 +01:00
|
|
|
|
if (ImGui::BeginTabItem("hex.builtin.tools.format.programmer"_lang)) {
|
2021-01-22 18:01:39 +01:00
|
|
|
|
mathDisplayType = MathDisplayType::Programmer;
|
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::EndTabBar();
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-28 18:15:20 +02:00
|
|
|
|
if (ImGui::BeginTable("##mathWrapper", 3)) {
|
|
|
|
|
ImGui::TableSetupColumn("##keypad", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize);
|
|
|
|
|
ImGui::TableSetupColumn("##results", ImGuiTableColumnFlags_WidthStretch, 0.666);
|
|
|
|
|
ImGui::TableSetupColumn("##variables", ImGuiTableColumnFlags_WidthStretch, 0.666);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
ImGui::TableNextColumn();
|
2021-08-28 18:15:20 +02:00
|
|
|
|
|
|
|
|
|
auto buttonSize = ImVec2(3, 2) * ImGui::GetTextLineHeightWithSpacing();
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
if (ImGui::Button("Ans", buttonSize)) mathInput += "ans";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Pi", buttonSize)) mathInput += "pi";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("e", buttonSize)) mathInput += "e";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("CE", buttonSize)) mathInput.clear();
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button(ICON_FA_BACKSPACE, buttonSize)) mathInput.clear();
|
|
|
|
|
ImGui::SameLine();
|
2021-08-28 18:15:20 +02:00
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
switch (mathDisplayType) {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
case MathDisplayType::Standard:
|
|
|
|
|
case MathDisplayType::Scientific:
|
|
|
|
|
case MathDisplayType::Engineering:
|
|
|
|
|
if (ImGui::Button("x²", buttonSize)) mathInput += "** 2";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("1/x", buttonSize)) mathInput += "1/";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("|x|", buttonSize)) mathInput += "abs";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("exp", buttonSize)) mathInput += "e ** ";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("%", buttonSize)) mathInput += "%";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
break;
|
|
|
|
|
case MathDisplayType::Programmer:
|
|
|
|
|
if (ImGui::Button("<<", buttonSize)) mathInput += "<<";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button(">>", buttonSize)) mathInput += ">>";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("&", buttonSize)) mathInput += "&";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("|", buttonSize)) mathInput += "|";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("^", buttonSize)) mathInput += "^";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
break;
|
2021-08-28 18:15:20 +02:00
|
|
|
|
}
|
|
|
|
|
ImGui::NewLine();
|
2022-01-24 20:53:17 +01:00
|
|
|
|
if (ImGui::Button("sqrt", buttonSize)) mathInput += "sqrt";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("(", buttonSize)) mathInput += "(";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button(")", buttonSize)) mathInput += ")";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("sign", buttonSize)) mathInput += "sign";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("÷", buttonSize)) mathInput += "/";
|
|
|
|
|
ImGui::SameLine();
|
2021-08-28 18:15:20 +02:00
|
|
|
|
ImGui::NewLine();
|
2022-01-24 20:53:17 +01:00
|
|
|
|
if (ImGui::Button("xª", buttonSize)) mathInput += "**";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("7", buttonSize)) mathInput += "7";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("8", buttonSize)) mathInput += "8";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("9", buttonSize)) mathInput += "9";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("×", buttonSize)) mathInput += "*";
|
|
|
|
|
ImGui::SameLine();
|
2021-08-28 18:15:20 +02:00
|
|
|
|
ImGui::NewLine();
|
2022-01-24 20:53:17 +01:00
|
|
|
|
if (ImGui::Button("log", buttonSize)) mathInput += "log";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("4", buttonSize)) mathInput += "4";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("5", buttonSize)) mathInput += "5";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("6", buttonSize)) mathInput += "6";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("-", buttonSize)) mathInput += "-";
|
|
|
|
|
ImGui::SameLine();
|
2021-08-28 18:15:20 +02:00
|
|
|
|
ImGui::NewLine();
|
2022-01-24 20:53:17 +01:00
|
|
|
|
if (ImGui::Button("ln", buttonSize)) mathInput += "ln";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("1", buttonSize)) mathInput += "1";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("2", buttonSize)) mathInput += "2";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("3", buttonSize)) mathInput += "3";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("+", buttonSize)) mathInput += "+";
|
|
|
|
|
ImGui::SameLine();
|
2021-08-28 18:15:20 +02:00
|
|
|
|
ImGui::NewLine();
|
2022-01-24 20:53:17 +01:00
|
|
|
|
if (ImGui::Button("lb", buttonSize)) mathInput += "lb";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("x=", buttonSize)) mathInput += "=";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("0", buttonSize)) mathInput += "0";
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button(".", buttonSize)) mathInput += ".";
|
|
|
|
|
ImGui::SameLine();
|
2021-08-28 18:15:20 +02:00
|
|
|
|
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetCustomColorVec4(ImGuiCustomCol_DescButtonHovered));
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetCustomColorVec4(ImGuiCustomCol_DescButton));
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetCustomColorVec4(ImGuiCustomCol_DescButtonActive));
|
2022-01-24 20:53:17 +01:00
|
|
|
|
if (ImGui::Button("=", buttonSize)) evaluate = true;
|
|
|
|
|
ImGui::SameLine();
|
2021-08-28 18:15:20 +02:00
|
|
|
|
ImGui::PopStyleColor(3);
|
|
|
|
|
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
|
|
if (ImGui::BeginTable("##mathHistory", 1, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(0, 300))) {
|
2021-01-22 18:01:39 +01:00
|
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
2021-02-11 23:09:45 +01:00
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.tools.history"_lang);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
|
|
|
|
ImGuiListClipper clipper;
|
|
|
|
|
clipper.Begin(mathHistory.size());
|
|
|
|
|
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
while (clipper.Step()) {
|
|
|
|
|
for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
|
|
|
|
if (i == 0)
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, ImU32(ImColor(0xA5, 0x45, 0x45)));
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
|
|
switch (mathDisplayType) {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
case MathDisplayType::Standard:
|
|
|
|
|
ImGui::TextFormatted("{0:.3Lf}", mathHistory[(mathHistory.size() - 1) - i]);
|
|
|
|
|
break;
|
|
|
|
|
case MathDisplayType::Scientific:
|
|
|
|
|
ImGui::TextFormatted("{0:.6Le}", mathHistory[(mathHistory.size() - 1) - i]);
|
|
|
|
|
break;
|
|
|
|
|
case MathDisplayType::Engineering:
|
|
|
|
|
ImGui::TextFormatted("{0}", hex::toEngineeringString(mathHistory[(mathHistory.size() - 1) - i]).c_str());
|
|
|
|
|
break;
|
|
|
|
|
case MathDisplayType::Programmer:
|
|
|
|
|
ImGui::TextFormatted("0x{0:X} ({1})",
|
|
|
|
|
u64(mathHistory[(mathHistory.size() - 1) - i]),
|
|
|
|
|
u64(mathHistory[(mathHistory.size() - 1) - i]));
|
|
|
|
|
break;
|
2021-01-22 18:01:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clipper.End();
|
|
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
2021-08-28 18:15:20 +02:00
|
|
|
|
if (ImGui::BeginTable("##mathVariables", 2, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(0, 300))) {
|
2021-01-22 18:01:39 +01:00
|
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
2021-02-11 23:09:45 +01:00
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.tools.name"_lang);
|
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.tools.value"_lang);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
for (const auto &[name, value] : mathEvaluator.getVariables()) {
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
ImGui::TextUnformatted(name.c_str());
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
switch (mathDisplayType) {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
case MathDisplayType::Standard:
|
|
|
|
|
ImGui::TextFormatted("{0:.3Lf}", value);
|
|
|
|
|
break;
|
|
|
|
|
case MathDisplayType::Scientific:
|
|
|
|
|
ImGui::TextFormatted("{0:.6Le}", value);
|
|
|
|
|
break;
|
|
|
|
|
case MathDisplayType::Engineering:
|
|
|
|
|
ImGui::TextFormatted("{}", hex::toEngineeringString(value));
|
|
|
|
|
break;
|
|
|
|
|
case MathDisplayType::Programmer:
|
|
|
|
|
ImGui::TextFormatted("0x{0:X} ({1})", u64(value), u64(value));
|
|
|
|
|
break;
|
2021-01-22 18:01:39 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
}
|
2021-08-28 18:15:20 +02:00
|
|
|
|
|
|
|
|
|
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth());
|
2021-12-07 22:47:41 +01:00
|
|
|
|
if (ImGui::InputText("##input", mathInput.data(), mathInput.capacity(), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &mathInput)) {
|
2021-08-28 18:15:20 +02:00
|
|
|
|
ImGui::SetKeyboardFocusHere();
|
|
|
|
|
evaluate = true;
|
|
|
|
|
}
|
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
|
|
|
|
|
|
if (!lastMathError.empty())
|
2022-01-15 14:14:53 +01:00
|
|
|
|
ImGui::TextFormattedColored(ImColor(0xA00040FF), "hex.builtin.tools.error"_lang, lastMathError);
|
2021-08-28 18:15:20 +02:00
|
|
|
|
else
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
|
|
|
|
|
if (evaluate) {
|
|
|
|
|
std::optional<long double> result;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
result = mathEvaluator.evaluate(mathInput);
|
|
|
|
|
} catch (std::invalid_argument &e) {
|
|
|
|
|
lastMathError = e.what();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result.has_value()) {
|
|
|
|
|
mathHistory.push_back(result.value());
|
|
|
|
|
mathInput.clear();
|
|
|
|
|
lastMathError.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-22 18:01:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-05 00:17:56 +01:00
|
|
|
|
void drawBaseConverter() {
|
|
|
|
|
static char buffer[4][0xFFF] = { { '0' }, { '0' }, { '0' }, { '0' } };
|
|
|
|
|
|
|
|
|
|
static auto CharFilter = [](ImGuiInputTextCallbackData *data) -> int {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
switch (*static_cast<u32 *>(data->UserData)) {
|
|
|
|
|
case 16:
|
|
|
|
|
return std::isxdigit(data->EventChar);
|
|
|
|
|
case 10:
|
|
|
|
|
return std::isdigit(data->EventChar);
|
|
|
|
|
case 8:
|
|
|
|
|
return std::isdigit(data->EventChar) && data->EventChar < '8';
|
|
|
|
|
case 2:
|
|
|
|
|
return data->EventChar == '0' || data->EventChar == '1';
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
2021-02-05 00:17:56 +01:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static auto ConvertBases = [](u8 base) {
|
|
|
|
|
u64 number;
|
|
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
switch (base) {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
case 16:
|
|
|
|
|
number = std::strtoull(buffer[1], nullptr, base);
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
number = std::strtoull(buffer[0], nullptr, base);
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
number = std::strtoull(buffer[2], nullptr, base);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
number = std::strtoull(buffer[3], nullptr, base);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return;
|
2021-02-05 00:17:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
auto base10String = std::to_string(number);
|
|
|
|
|
auto base16String = hex::format("0x{0:X}", number);
|
|
|
|
|
auto base8String = hex::format("{0:#o}", number);
|
|
|
|
|
auto base2String = hex::toBinaryString(number);
|
2021-02-05 00:17:56 +01:00
|
|
|
|
|
|
|
|
|
std::strncpy(buffer[0], base10String.c_str(), sizeof(buffer[0]));
|
|
|
|
|
std::strncpy(buffer[1], base16String.c_str(), sizeof(buffer[1]));
|
2022-01-24 20:53:17 +01:00
|
|
|
|
std::strncpy(buffer[2], base8String.c_str(), sizeof(buffer[2]));
|
|
|
|
|
std::strncpy(buffer[3], base2String.c_str(), sizeof(buffer[3]));
|
2021-02-05 00:17:56 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
u8 base = 10;
|
2021-02-11 23:09:45 +01:00
|
|
|
|
if (ImGui::InputText("hex.builtin.tools.base_converter.dec"_lang, buffer[0], 20 + 1, ImGuiInputTextFlags_CallbackCharFilter, CharFilter, &base))
|
2021-02-05 00:17:56 +01:00
|
|
|
|
ConvertBases(base);
|
|
|
|
|
|
|
|
|
|
base = 16;
|
2021-02-11 23:09:45 +01:00
|
|
|
|
if (ImGui::InputText("hex.builtin.tools.base_converter.hex"_lang, buffer[1], 16 + 1, ImGuiInputTextFlags_CallbackCharFilter, CharFilter, &base))
|
2021-02-05 00:17:56 +01:00
|
|
|
|
ConvertBases(base);
|
|
|
|
|
|
|
|
|
|
base = 8;
|
2021-02-11 23:09:45 +01:00
|
|
|
|
if (ImGui::InputText("hex.builtin.tools.base_converter.oct"_lang, buffer[2], 22 + 1, ImGuiInputTextFlags_CallbackCharFilter, CharFilter, &base))
|
2021-02-05 00:17:56 +01:00
|
|
|
|
ConvertBases(base);
|
|
|
|
|
|
|
|
|
|
base = 2;
|
2021-02-11 23:09:45 +01:00
|
|
|
|
if (ImGui::InputText("hex.builtin.tools.base_converter.bin"_lang, buffer[3], 64 + 1, ImGuiInputTextFlags_CallbackCharFilter, CharFilter, &base))
|
2021-02-05 00:17:56 +01:00
|
|
|
|
ConvertBases(base);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-22 18:01:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-27 22:46:37 +02:00
|
|
|
|
void drawPermissionsCalculator() {
|
|
|
|
|
static bool setuid, setgid, sticky;
|
|
|
|
|
static bool r[3], w[3], x[3];
|
|
|
|
|
|
|
|
|
|
ImGui::TextUnformatted("hex.builtin.tools.permissions.perm_bits"_lang);
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
if (ImGui::BeginTable("Permissions", 4, ImGuiTableFlags_Borders)) {
|
|
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
|
|
|
|
ImGui::TableSetupColumn("Special", ImGuiTableColumnFlags_NoSort);
|
|
|
|
|
ImGui::TableSetupColumn("User", ImGuiTableColumnFlags_NoSort);
|
|
|
|
|
ImGui::TableSetupColumn("Group", ImGuiTableColumnFlags_NoSort);
|
|
|
|
|
ImGui::TableSetupColumn("Other", ImGuiTableColumnFlags_NoSort);
|
|
|
|
|
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
|
|
ImGui::Checkbox("setuid", &setuid);
|
|
|
|
|
ImGui::Checkbox("setgid", &setgid);
|
|
|
|
|
ImGui::Checkbox("Sticky bit", &sticky);
|
|
|
|
|
|
|
|
|
|
for (u8 i = 0; i < 3; i++) {
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
|
|
ImGui::PushID(i);
|
|
|
|
|
ImGui::Checkbox("Read", &r[i]);
|
|
|
|
|
ImGui::Checkbox("Write", &w[i]);
|
|
|
|
|
ImGui::Checkbox("Execute", &x[i]);
|
|
|
|
|
ImGui::PopID();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
ImGui::TextUnformatted("hex.builtin.tools.permissions.absolute"_lang);
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
auto result = hex::format("{}{}{}{}",
|
|
|
|
|
(setuid << 2) | (setgid << 1) | (sticky << 0),
|
|
|
|
|
(r[0] << 2) | (w[0] << 1) | (x[0] << 0),
|
|
|
|
|
(r[1] << 2) | (w[1] << 1) | (x[1] << 0),
|
|
|
|
|
(r[2] << 2) | (w[2] << 1) | (x[2] << 0));
|
|
|
|
|
ImGui::InputText("##permissions_absolute", result.data(), result.size(), ImGuiInputTextFlags_ReadOnly);
|
|
|
|
|
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
|
|
|
|
|
static const auto WarningColor = ImColor(0.92F, 0.25F, 0.2F, 1.0F);
|
|
|
|
|
if (setuid && !x[0])
|
2022-01-15 14:14:53 +01:00
|
|
|
|
ImGui::TextFormattedColored(WarningColor, "{}", "hex.builtin.tools.permissions.setuid_error"_lang);
|
2021-07-27 22:46:37 +02:00
|
|
|
|
if (setgid && !x[1])
|
2022-01-15 14:14:53 +01:00
|
|
|
|
ImGui::TextFormattedColored(WarningColor, "{}", "hex.builtin.tools.permissions.setgid_error"_lang);
|
2021-07-27 22:46:37 +02:00
|
|
|
|
if (sticky && !x[2])
|
2022-01-15 14:14:53 +01:00
|
|
|
|
ImGui::TextFormattedColored(WarningColor, "{}", "hex.builtin.tools.permissions.sticky_error"_lang);
|
2021-07-27 22:46:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-28 00:45:59 +02:00
|
|
|
|
void drawFileUploader() {
|
|
|
|
|
struct UploadedFile {
|
|
|
|
|
std::string fileName, link, size;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static hex::Net net;
|
|
|
|
|
static std::future<Response<std::string>> uploadProcess;
|
2022-01-13 14:33:30 +01:00
|
|
|
|
static fs::path currFile;
|
2021-08-28 00:45:59 +02:00
|
|
|
|
static std::vector<UploadedFile> links;
|
|
|
|
|
|
|
|
|
|
bool uploading = uploadProcess.valid() && uploadProcess.wait_for(0s) != std::future_status::ready;
|
|
|
|
|
|
|
|
|
|
ImGui::Header("hex.builtin.tools.file_uploader.control"_lang, true);
|
|
|
|
|
if (!uploading) {
|
|
|
|
|
if (ImGui::Button("hex.builtin.tools.file_uploader.upload"_lang)) {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
hex::openFileBrowser("hex.builtin.tools.file_uploader.done"_lang, DialogMode::Open, {}, [&](auto path) {
|
2021-08-28 00:45:59 +02:00
|
|
|
|
uploadProcess = net.uploadFile("https://api.anonfiles.com/upload", path);
|
|
|
|
|
currFile = path;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (ImGui::Button("hex.common.cancel"_lang)) {
|
|
|
|
|
net.cancel();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
|
|
ImGui::ProgressBar(net.getProgress(), ImVec2(0, 0), uploading ? nullptr : "Done!");
|
|
|
|
|
|
|
|
|
|
ImGui::Header("hex.builtin.tools.file_uploader.recent"_lang);
|
|
|
|
|
|
2021-08-28 18:15:47 +02:00
|
|
|
|
if (ImGui::BeginTable("##links", 3, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg, ImVec2(0, 200))) {
|
2021-08-28 00:45:59 +02:00
|
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
|
|
|
|
ImGui::TableSetupColumn("hex.common.file"_lang);
|
|
|
|
|
ImGui::TableSetupColumn("hex.common.link"_lang);
|
|
|
|
|
ImGui::TableSetupColumn("hex.common.size"_lang);
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
|
|
|
|
|
ImGuiListClipper clipper;
|
|
|
|
|
clipper.Begin(links.size());
|
|
|
|
|
|
|
|
|
|
while (clipper.Step()) {
|
2022-01-22 22:37:52 +01:00
|
|
|
|
for (i32 i = clipper.DisplayEnd - 1; i >= clipper.DisplayStart; i--) {
|
2021-08-28 00:45:59 +02:00
|
|
|
|
auto &[fileName, link, size] = links[i];
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
ImGui::TextUnformatted(fileName.c_str());
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
if (ImGui::Hyperlink(link.c_str())) {
|
|
|
|
|
if (ImGui::GetMergedKeyModFlags() == ImGuiKeyModFlags_Ctrl)
|
|
|
|
|
hex::openWebpage(link);
|
|
|
|
|
else
|
|
|
|
|
ImGui::SetClipboardText(link.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::InfoTooltip("hex.builtin.tools.file_uploader.tooltip"_lang);
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
ImGui::TextUnformatted(size.c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clipper.End();
|
|
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (uploadProcess.valid() && uploadProcess.wait_for(0s) == std::future_status::ready) {
|
|
|
|
|
auto response = uploadProcess.get();
|
|
|
|
|
if (response.code == 200) {
|
|
|
|
|
try {
|
|
|
|
|
auto json = nlohmann::json::parse(response.body);
|
2022-01-24 20:53:17 +01:00
|
|
|
|
links.push_back({ currFile.filename().string(),
|
|
|
|
|
json["data"]["file"]["url"]["short"],
|
|
|
|
|
json["data"]["file"]["metadata"]["size"]["readable"] });
|
2021-08-28 00:45:59 +02:00
|
|
|
|
} catch (...) {
|
|
|
|
|
View::showErrorPopup("hex.builtin.tools.file_uploader.invalid_response"_lang);
|
|
|
|
|
}
|
|
|
|
|
} else if (response.code == 0) {
|
|
|
|
|
// Canceled by user, no action needed
|
|
|
|
|
} else View::showErrorPopup(hex::format("hex.builtin.tools.file_uploader.error"_lang, response.code));
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
uploadProcess = {};
|
2021-08-28 00:45:59 +02:00
|
|
|
|
currFile.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-28 16:02:53 +02:00
|
|
|
|
void drawWikiExplainer() {
|
|
|
|
|
static hex::Net net;
|
2021-08-28 18:15:47 +02:00
|
|
|
|
|
2021-08-28 16:02:53 +02:00
|
|
|
|
static std::string resultTitle, resultExtract;
|
|
|
|
|
static std::future<Response<std::string>> searchProcess;
|
|
|
|
|
static bool extendedSearch = false;
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
static auto searchString = [] {
|
2021-08-28 18:15:47 +02:00
|
|
|
|
std::string s;
|
|
|
|
|
s.reserve(0xFFFF);
|
|
|
|
|
std::memset(s.data(), 0x00, s.capacity());
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}();
|
|
|
|
|
|
2021-08-28 16:02:53 +02:00
|
|
|
|
constexpr static auto WikipediaApiUrl = "https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&explaintext&redirects=10&formatversion=2";
|
|
|
|
|
|
2021-08-28 18:15:47 +02:00
|
|
|
|
ImGui::Header("hex.builtin.tools.wiki_explain.control"_lang, true);
|
2021-08-28 16:02:53 +02:00
|
|
|
|
|
2021-08-28 18:15:47 +02:00
|
|
|
|
bool startSearch;
|
2021-08-28 16:02:53 +02:00
|
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
|
startSearch = ImGui::InputText("##search", searchString.data(), searchString.capacity(), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &searchString);
|
2021-08-28 16:02:53 +02:00
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
2021-08-28 18:15:47 +02:00
|
|
|
|
ImGui::BeginDisabled(searchProcess.valid() && searchProcess.wait_for(0s) != std::future_status::ready || searchString.empty());
|
2022-01-24 20:53:17 +01:00
|
|
|
|
startSearch = ImGui::Button("hex.builtin.tools.wiki_explain.search"_lang) || startSearch;
|
2021-08-28 16:02:53 +02:00
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
|
2021-08-28 18:15:47 +02:00
|
|
|
|
if (startSearch && !searchString.empty()) {
|
2021-08-28 16:02:53 +02:00
|
|
|
|
searchProcess = net.getString(WikipediaApiUrl + "&exintro"s + "&titles="s + net.encode(searchString));
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-28 18:15:47 +02:00
|
|
|
|
ImGui::Header("hex.builtin.tools.wiki_explain.results"_lang);
|
2021-08-28 16:02:53 +02:00
|
|
|
|
|
|
|
|
|
if (ImGui::BeginChild("##summary", ImVec2(0, 300), true)) {
|
|
|
|
|
if (!resultTitle.empty() && !resultExtract.empty()) {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
ImGui::HeaderColored(resultTitle.c_str(), ImGui::GetCustomColorVec4(ImGuiCustomCol_Highlight), true);
|
2022-01-15 14:14:53 +01:00
|
|
|
|
ImGui::TextFormattedWrapped("{}", resultExtract.c_str());
|
2021-08-28 16:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
|
|
|
|
|
|
if (searchProcess.valid() && searchProcess.wait_for(0s) == std::future_status::ready) {
|
|
|
|
|
try {
|
|
|
|
|
auto response = searchProcess.get();
|
|
|
|
|
if (response.code != 200) throw std::runtime_error("Invalid response");
|
|
|
|
|
|
|
|
|
|
auto json = nlohmann::json::parse(response.body);
|
|
|
|
|
|
|
|
|
|
resultTitle = json["query"]["pages"][0]["title"];
|
|
|
|
|
resultExtract = json["query"]["pages"][0]["extract"];
|
|
|
|
|
|
|
|
|
|
if (!extendedSearch && resultExtract.ends_with(':')) {
|
|
|
|
|
extendedSearch = true;
|
|
|
|
|
searchProcess = net.getString(WikipediaApiUrl + "&titles="s + net.encode(searchString));
|
|
|
|
|
resultTitle.clear();
|
|
|
|
|
resultExtract.clear();
|
|
|
|
|
} else {
|
|
|
|
|
extendedSearch = false;
|
|
|
|
|
searchString.clear();
|
|
|
|
|
}
|
|
|
|
|
} catch (...) {
|
|
|
|
|
resultTitle.clear();
|
|
|
|
|
resultExtract.clear();
|
|
|
|
|
extendedSearch = false;
|
2022-01-24 20:53:17 +01:00
|
|
|
|
searchProcess = {};
|
2021-08-28 16:02:53 +02:00
|
|
|
|
|
|
|
|
|
resultTitle = "???";
|
2021-08-28 18:15:47 +02:00
|
|
|
|
resultExtract = "hex.builtin.tools.wiki_explain.invalid_response"_lang.get();
|
2021-08-28 16:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-22 17:56:06 +02:00
|
|
|
|
|
|
|
|
|
void drawFileToolShredder() {
|
|
|
|
|
static bool shredding = false;
|
2022-01-24 20:53:17 +01:00
|
|
|
|
static auto selectedFile = [] { std::string s; s.reserve(0x1000); return s; }();
|
2021-09-22 17:56:06 +02:00
|
|
|
|
static bool fastMode = false;
|
|
|
|
|
|
|
|
|
|
ImGui::TextUnformatted("hex.builtin.tools.file_tools.shredder.warning"_lang);
|
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
|
|
|
|
|
if (ImGui::BeginChild("settings", { 0, ImGui::GetTextLineHeightWithSpacing() * 4 }, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
|
|
|
|
ImGui::BeginDisabled(shredding);
|
|
|
|
|
{
|
|
|
|
|
ImGui::TextUnformatted("hex.builtin.tools.file_tools.shredder.input"_lang);
|
|
|
|
|
ImGui::SameLine();
|
2021-12-07 22:47:41 +01:00
|
|
|
|
ImGui::InputText("##path", selectedFile.data(), selectedFile.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &selectedFile);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("...")) {
|
2022-01-16 01:51:31 +01:00
|
|
|
|
hex::openFileBrowser("hex.builtin.tools.file_tools.shredder.picker"_lang, DialogMode::Open, {}, [](const auto &path) {
|
|
|
|
|
selectedFile = path.string();
|
2021-09-22 17:56:06 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::Checkbox("hex.builtin.tools.file_tools.shredder.fast"_lang, &fastMode);
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
|
|
|
|
|
|
if (shredding)
|
|
|
|
|
ImGui::TextSpinner("hex.builtin.tools.file_tools.shredder.shredding"_lang);
|
|
|
|
|
else {
|
|
|
|
|
ImGui::BeginDisabled(selectedFile.empty());
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::Button("hex.builtin.tools.file_tools.shredder.shred"_lang)) {
|
|
|
|
|
shredding = true;
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
std::thread([] {
|
|
|
|
|
ON_SCOPE_EXIT {
|
|
|
|
|
shredding = false;
|
|
|
|
|
selectedFile.clear();
|
|
|
|
|
};
|
2021-09-22 17:56:06 +02:00
|
|
|
|
File file(selectedFile, File::Mode::Write);
|
|
|
|
|
|
|
|
|
|
if (!file.isValid()) {
|
|
|
|
|
View::showErrorPopup("hex.builtin.tools.file_tools.shredder.error.open"_lang);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::array<u8, 3>> overwritePattern;
|
|
|
|
|
if (fastMode) {
|
|
|
|
|
/* Should be sufficient for modern disks */
|
|
|
|
|
overwritePattern.push_back({ 0x00, 0x00, 0x00 });
|
|
|
|
|
overwritePattern.push_back({ 0xFF, 0xFF, 0xFF });
|
2022-01-24 20:53:17 +01:00
|
|
|
|
} else {
|
2021-09-22 17:56:06 +02:00
|
|
|
|
/* Gutmann's method. Secure for magnetic storage */
|
|
|
|
|
std::random_device rd;
|
|
|
|
|
std::uniform_int_distribution<u8> dist(0x00, 0xFF);
|
|
|
|
|
|
|
|
|
|
/* Fill fixed patterns */
|
|
|
|
|
overwritePattern = {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
{ },
|
|
|
|
|
{ },
|
|
|
|
|
{},
|
|
|
|
|
{},
|
|
|
|
|
{ 0x55, 0x55, 0x55 },
|
|
|
|
|
{ 0xAA, 0xAA, 0xAA },
|
|
|
|
|
{ 0x92, 0x49, 0x24 },
|
|
|
|
|
{ 0x49, 0x24, 0x92 },
|
|
|
|
|
{ 0x24, 0x92, 0x49 },
|
|
|
|
|
{ 0x00, 0x00, 0x00 },
|
|
|
|
|
{ 0x11, 0x11, 0x11 },
|
|
|
|
|
{ 0x22, 0x22, 0x22 },
|
|
|
|
|
{ 0x33, 0x33, 0x44 },
|
|
|
|
|
{ 0x55, 0x55, 0x55 },
|
|
|
|
|
{ 0x66, 0x66, 0x66 },
|
|
|
|
|
{ 0x77, 0x77, 0x77 },
|
|
|
|
|
{ 0x88, 0x88, 0x88 },
|
|
|
|
|
{ 0x99, 0x99, 0x99 },
|
|
|
|
|
{ 0xAA, 0xAA, 0xAA },
|
|
|
|
|
{ 0xBB, 0xBB, 0xBB },
|
|
|
|
|
{ 0xCC, 0xCC, 0xCC },
|
|
|
|
|
{ 0xDD, 0xDD, 0xDD },
|
|
|
|
|
{ 0xEE, 0xEE, 0xEE },
|
|
|
|
|
{ 0xFF, 0xFF, 0xFF },
|
|
|
|
|
{ 0x92, 0x49, 0x24 },
|
|
|
|
|
{ 0x49, 0x24, 0x92 },
|
|
|
|
|
{ 0x24, 0x92, 0x49 },
|
|
|
|
|
{ 0x6D, 0xB6, 0xDB },
|
|
|
|
|
{ 0xB6, 0xDB, 0x6D },
|
|
|
|
|
{ 0xBD, 0x6D, 0xB6 },
|
|
|
|
|
{},
|
|
|
|
|
{},
|
|
|
|
|
{},
|
|
|
|
|
{}
|
2021-09-22 17:56:06 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Fill random patterns */
|
|
|
|
|
for (u8 i = 0; i < 4; i++)
|
|
|
|
|
overwritePattern[i] = { dist(rd), dist(rd), dist(rd) };
|
|
|
|
|
for (u8 i = 0; i < 4; i++)
|
|
|
|
|
overwritePattern[overwritePattern.size() - 1 - i] = { dist(rd), dist(rd), dist(rd) };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t fileSize = file.getSize();
|
2021-12-16 23:48:52 +01:00
|
|
|
|
|
|
|
|
|
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.shredder.shredding", fileSize);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
for (const auto &pattern : overwritePattern) {
|
|
|
|
|
for (u64 offset = 0; offset < fileSize; offset += 3) {
|
2021-10-09 23:07:58 +02:00
|
|
|
|
file.write(pattern.data(), std::min<u64>(pattern.size(), fileSize - offset));
|
2021-12-16 23:48:52 +01:00
|
|
|
|
task.update(offset);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
}
|
2021-10-09 23:07:58 +02:00
|
|
|
|
|
2021-09-22 17:56:06 +02:00
|
|
|
|
file.flush();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file.remove();
|
|
|
|
|
|
|
|
|
|
View::showMessagePopup("hex.builtin.tools.file_tools.shredder.success"_lang);
|
|
|
|
|
}).detach();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void drawFileToolSplitter() {
|
|
|
|
|
std::array sizeText = {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
(const char *)"hex.builtin.tools.file_tools.splitter.sizes.5_75_floppy"_lang,
|
|
|
|
|
(const char *)"hex.builtin.tools.file_tools.splitter.sizes.3_5_floppy"_lang,
|
|
|
|
|
(const char *)"hex.builtin.tools.file_tools.splitter.sizes.zip100"_lang,
|
|
|
|
|
(const char *)"hex.builtin.tools.file_tools.splitter.sizes.zip200"_lang,
|
|
|
|
|
(const char *)"hex.builtin.tools.file_tools.splitter.sizes.cdrom650"_lang,
|
|
|
|
|
(const char *)"hex.builtin.tools.file_tools.splitter.sizes.cdrom700"_lang,
|
|
|
|
|
(const char *)"hex.builtin.tools.file_tools.splitter.sizes.fat32"_lang,
|
|
|
|
|
(const char *)"hex.builtin.tools.file_tools.splitter.sizes.custom"_lang
|
2021-09-22 17:56:06 +02:00
|
|
|
|
};
|
|
|
|
|
std::array<u64, sizeText.size()> sizes = {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
1200_KiB,
|
|
|
|
|
1400_KiB,
|
|
|
|
|
100_MiB,
|
|
|
|
|
200_MiB,
|
|
|
|
|
650_MiB,
|
|
|
|
|
700_MiB,
|
|
|
|
|
4_GiB,
|
|
|
|
|
1
|
2021-09-22 17:56:06 +02:00
|
|
|
|
};
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
static bool splitting = false;
|
|
|
|
|
static auto selectedFile = [] { std::string s; s.reserve(0x1000); return s; }();
|
|
|
|
|
static auto baseOutputPath = [] { std::string s; s.reserve(0x1000); return s; }();
|
2021-09-22 17:56:06 +02:00
|
|
|
|
static u64 splitSize = sizes[0];
|
|
|
|
|
static int selectedItem = 0;
|
|
|
|
|
|
|
|
|
|
if (ImGui::BeginChild("split_settings", { 0, ImGui::GetTextLineHeightWithSpacing() * 7 }, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
|
|
|
|
ImGui::BeginDisabled(splitting);
|
|
|
|
|
{
|
2021-12-07 22:47:41 +01:00
|
|
|
|
ImGui::InputText("##path", selectedFile.data(), selectedFile.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &selectedFile);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("...##input")) {
|
2022-01-16 01:51:31 +01:00
|
|
|
|
hex::openFileBrowser("hex.builtin.tools.file_tools.splitter.picker.input"_lang, DialogMode::Open, {}, [](const auto &path) {
|
|
|
|
|
selectedFile = path.string();
|
2021-09-22 17:56:06 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
2021-12-20 22:04:10 +01:00
|
|
|
|
ImGui::TextUnformatted("hex.builtin.tools.file_tools.splitter.input"_lang);
|
|
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
|
ImGui::InputText("##base_path", baseOutputPath.data(), baseOutputPath.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &baseOutputPath);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("...##output")) {
|
2022-01-16 01:51:31 +01:00
|
|
|
|
hex::openFileBrowser("hex.builtin.tools.file_tools.splitter.picker.output"_lang, DialogMode::Save, {}, [](const auto &path) {
|
|
|
|
|
baseOutputPath = path.string();
|
2021-09-22 17:56:06 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
2021-12-20 22:04:10 +01:00
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::TextUnformatted("hex.builtin.tools.file_tools.splitter.output"_lang);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
|
|
if (ImGui::Combo("###part_size", &selectedItem, sizeText.data(), sizeText.size())) {
|
|
|
|
|
splitSize = sizes[selectedItem];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
ImGui::BeginDisabled(splitting || selectedItem != sizes.size() - 1);
|
|
|
|
|
{
|
|
|
|
|
ImGui::InputScalar("###custom_size", ImGuiDataType_U64, &splitSize);
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::TextUnformatted("Bytes");
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
|
|
|
|
|
|
ImGui::BeginDisabled(selectedFile.empty() || baseOutputPath.empty() || splitSize == 0);
|
|
|
|
|
{
|
|
|
|
|
if (splitting)
|
|
|
|
|
ImGui::TextSpinner("hex.builtin.tools.file_tools.splitter.splitting"_lang);
|
|
|
|
|
else {
|
|
|
|
|
if (ImGui::Button("hex.builtin.tools.file_tools.splitter.split"_lang)) {
|
|
|
|
|
splitting = true;
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
std::thread([] {
|
|
|
|
|
ON_SCOPE_EXIT {
|
|
|
|
|
splitting = false;
|
|
|
|
|
selectedFile.clear();
|
|
|
|
|
baseOutputPath.clear();
|
|
|
|
|
};
|
2021-09-22 17:56:06 +02:00
|
|
|
|
File file(selectedFile, File::Mode::Read);
|
|
|
|
|
|
|
|
|
|
if (!file.isValid()) {
|
|
|
|
|
View::showErrorPopup("hex.builtin.tools.file_tools.splitter.error.open"_lang);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (file.getSize() < splitSize) {
|
|
|
|
|
View::showErrorPopup("hex.builtin.tools.file_tools.splitter.error.size"_lang);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-16 23:48:52 +01:00
|
|
|
|
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.splitter.splitting", file.getSize());
|
2021-09-22 17:56:06 +02:00
|
|
|
|
u32 index = 1;
|
|
|
|
|
for (u64 offset = 0; offset < file.getSize(); offset += splitSize) {
|
2021-12-16 23:48:52 +01:00
|
|
|
|
task.update(offset);
|
|
|
|
|
|
2021-09-22 17:56:06 +02:00
|
|
|
|
File partFile(baseOutputPath + hex::format(".{:05}", index), File::Mode::Create);
|
|
|
|
|
|
|
|
|
|
if (!partFile.isValid()) {
|
|
|
|
|
View::showErrorPopup(hex::format("hex.builtin.tools.file_tools.splitter.error.create"_lang, index));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constexpr auto BufferSize = 0xFF'FFFF;
|
|
|
|
|
for (u64 partOffset = 0; partOffset < splitSize; partOffset += BufferSize) {
|
|
|
|
|
partFile.write(file.readBytes(std::min<u64>(BufferSize, splitSize - partOffset)));
|
|
|
|
|
partFile.flush();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
View::showMessagePopup("hex.builtin.tools.file_tools.splitter.success"_lang);
|
|
|
|
|
}).detach();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void drawFileToolCombiner() {
|
|
|
|
|
static bool combining = false;
|
|
|
|
|
static std::vector<std::string> files;
|
2022-01-24 20:53:17 +01:00
|
|
|
|
static auto outputPath = [] { std::string s; s.reserve(0x1000); return s; }();
|
2022-01-22 22:37:52 +01:00
|
|
|
|
static i32 selectedIndex;
|
2021-09-22 17:56:06 +02:00
|
|
|
|
|
|
|
|
|
if (ImGui::BeginTable("files_table", 2, ImGuiTableFlags_SizingStretchProp)) {
|
|
|
|
|
ImGui::TableSetupColumn("file list", ImGuiTableColumnFlags_NoHeaderLabel, 10);
|
|
|
|
|
ImGui::TableSetupColumn("buttons", ImGuiTableColumnFlags_NoHeaderLabel, 1);
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
|
|
if (ImGui::BeginListBox("##files", { -FLT_MIN, 10 * ImGui::GetTextLineHeightWithSpacing() })) {
|
|
|
|
|
|
2022-01-22 22:37:52 +01:00
|
|
|
|
i32 index = 0;
|
2021-09-22 17:56:06 +02:00
|
|
|
|
for (auto &file : files) {
|
2022-01-13 14:33:30 +01:00
|
|
|
|
if (ImGui::Selectable(fs::path(file).filename().string().c_str(), index == selectedIndex))
|
2021-09-22 17:56:06 +02:00
|
|
|
|
selectedIndex = index;
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::EndListBox();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
ImGui::BeginDisabled(selectedIndex <= 0);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
{
|
|
|
|
|
if (ImGui::ArrowButton("move_up", ImGuiDir_Up)) {
|
|
|
|
|
std::iter_swap(files.begin() + selectedIndex, files.begin() + selectedIndex - 1);
|
|
|
|
|
selectedIndex--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
ImGui::BeginDisabled(files.empty() || selectedIndex >= files.size() - 1);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
{
|
|
|
|
|
if (ImGui::ArrowButton("move_down", ImGuiDir_Down)) {
|
|
|
|
|
std::iter_swap(files.begin() + selectedIndex, files.begin() + selectedIndex + 1);
|
|
|
|
|
selectedIndex++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
|
|
ImGui::BeginDisabled(combining);
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.add"_lang)) {
|
2022-01-16 01:51:31 +01:00
|
|
|
|
hex::openFileBrowser("hex.builtin.tools.file_tools.combiner.add.picker"_lang, DialogMode::Open, {}, [](const auto &path) {
|
|
|
|
|
files.push_back(path.string());
|
2021-09-22 17:56:06 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.delete"_lang)) {
|
|
|
|
|
files.erase(files.begin() + selectedIndex);
|
|
|
|
|
selectedIndex--;
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.clear"_lang)) {
|
|
|
|
|
files.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::BeginDisabled(combining);
|
|
|
|
|
{
|
2021-12-07 22:47:41 +01:00
|
|
|
|
ImGui::InputText("##output_path", outputPath.data(), outputPath.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &outputPath);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("...")) {
|
2022-01-16 01:51:31 +01:00
|
|
|
|
hex::openFileBrowser("hex.builtin.tools.file_tools.combiner.output.picker"_lang, DialogMode::Save, {}, [](const auto &path) {
|
|
|
|
|
outputPath = path.string();
|
2021-09-22 17:56:06 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
2021-12-20 22:04:10 +01:00
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::TextUnformatted("hex.builtin.tools.file_tools.combiner.output"_lang);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
}
|
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
|
|
|
|
|
ImGui::BeginDisabled(files.empty() || outputPath.empty());
|
|
|
|
|
{
|
|
|
|
|
if (combining)
|
|
|
|
|
ImGui::TextSpinner("hex.builtin.tools.file_tools.combiner.combining"_lang);
|
|
|
|
|
else {
|
|
|
|
|
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.combine"_lang)) {
|
|
|
|
|
combining = true;
|
|
|
|
|
|
2022-01-24 20:53:17 +01:00
|
|
|
|
std::thread([] {
|
2021-09-22 17:56:06 +02:00
|
|
|
|
ON_SCOPE_EXIT { combining = false; };
|
|
|
|
|
|
|
|
|
|
File output(outputPath, File::Mode::Create);
|
|
|
|
|
|
|
|
|
|
if (!output.isValid()) {
|
|
|
|
|
View::showErrorPopup("hex.builtin.tools.file_tools.combiner.error.open_output"_lang);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-16 23:48:52 +01:00
|
|
|
|
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.combiner.combining", files.size());
|
|
|
|
|
|
|
|
|
|
u64 fileIndex = 0;
|
2021-09-22 17:56:06 +02:00
|
|
|
|
for (const auto &file : files) {
|
2021-12-16 23:48:52 +01:00
|
|
|
|
task.update(fileIndex);
|
|
|
|
|
fileIndex++;
|
2021-09-22 17:56:06 +02:00
|
|
|
|
|
2021-12-16 23:48:52 +01:00
|
|
|
|
File input(file, File::Mode::Read);
|
2021-09-22 17:56:06 +02:00
|
|
|
|
if (!input.isValid()) {
|
2022-01-13 14:33:30 +01:00
|
|
|
|
View::showErrorPopup(hex::format("hex.builtin.tools.file_tools.combiner.open_input"_lang, fs::path(file).filename().string()));
|
2021-09-22 17:56:06 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constexpr auto BufferSize = 0xFF'FFFF;
|
|
|
|
|
auto inputSize = input.getSize();
|
|
|
|
|
for (u64 inputOffset = 0; inputOffset < inputSize; inputOffset += BufferSize) {
|
|
|
|
|
output.write(input.readBytes(std::min<u64>(BufferSize, inputSize - inputOffset)));
|
|
|
|
|
output.flush();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
files.clear();
|
|
|
|
|
selectedIndex = 0;
|
|
|
|
|
outputPath.clear();
|
|
|
|
|
|
|
|
|
|
View::showMessagePopup("hex.builtin.tools.file_tools.combiner.success"_lang);
|
|
|
|
|
}).detach();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void drawFileTools() {
|
|
|
|
|
|
|
|
|
|
if (ImGui::BeginTabBar("file_tools_tabs")) {
|
|
|
|
|
|
|
|
|
|
if (ImGui::BeginTabItem("hex.builtin.tools.file_tools.shredder"_lang)) {
|
|
|
|
|
drawFileToolShredder();
|
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ImGui::BeginTabItem("hex.builtin.tools.file_tools.splitter"_lang)) {
|
|
|
|
|
drawFileToolSplitter();
|
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ImGui::BeginTabItem("hex.builtin.tools.file_tools.combiner"_lang)) {
|
|
|
|
|
drawFileToolCombiner();
|
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::EndTabBar();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-22 18:01:39 +01:00
|
|
|
|
void registerToolEntries() {
|
2022-01-24 20:53:17 +01:00
|
|
|
|
ContentRegistry::Tools::add("hex.builtin.tools.demangler", drawDemangler);
|
|
|
|
|
ContentRegistry::Tools::add("hex.builtin.tools.ascii_table", drawASCIITable);
|
|
|
|
|
ContentRegistry::Tools::add("hex.builtin.tools.regex_replacer", drawRegexReplacer);
|
|
|
|
|
ContentRegistry::Tools::add("hex.builtin.tools.color", drawColorPicker);
|
|
|
|
|
ContentRegistry::Tools::add("hex.builtin.tools.calc", drawMathEvaluator);
|
|
|
|
|
ContentRegistry::Tools::add("hex.builtin.tools.base_converter", drawBaseConverter);
|
|
|
|
|
ContentRegistry::Tools::add("hex.builtin.tools.permissions", drawPermissionsCalculator);
|
|
|
|
|
ContentRegistry::Tools::add("hex.builtin.tools.file_uploader", drawFileUploader);
|
|
|
|
|
ContentRegistry::Tools::add("hex.builtin.tools.wiki_explain", drawWikiExplainer);
|
|
|
|
|
ContentRegistry::Tools::add("hex.builtin.tools.file_tools", drawFileTools);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|