refactor and perf improvements

This commit is contained in:
Akash Mozumdar 2019-06-21 01:29:48 -04:00
parent 6bac544c89
commit f1d46e9f73
9 changed files with 254 additions and 298 deletions

View File

@ -70,6 +70,14 @@ bool DispatchSentenceToExtensions(std::wstring& sentence, const InfoForExtension
return !sentence.empty(); return !sentence.empty();
} }
void CleanupExtensions()
{
std::scoped_lock writeLock(extenMutex);
for (auto extension : extensions)
FreeLibrary(GetModuleHandleW(extension.name.c_str()));
extensions.clear();
}
ExtenWindow::ExtenWindow(QWidget* parent) : ExtenWindow::ExtenWindow(QWidget* parent) :
QMainWindow(parent, Qt::WindowCloseButtonHint), QMainWindow(parent, Qt::WindowCloseButtonHint),
ui(new Ui::ExtenWindow) ui(new Ui::ExtenWindow)

View File

@ -14,6 +14,7 @@ struct InfoForExtension
}; };
bool DispatchSentenceToExtensions(std::wstring& sentence, const InfoForExtension* miscInfo); bool DispatchSentenceToExtensions(std::wstring& sentence, const InfoForExtension* miscInfo);
void CleanupExtensions(); // must call this before exiting the program, only way to uphold guarantee that DllMain and OnNewSentence won't be called concurrently
class ExtenWindow : public QMainWindow class ExtenWindow : public QMainWindow
{ {

View File

@ -134,6 +134,7 @@ MainWindow::MainWindow(QWidget *parent) :
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
QSettings(CONFIG_FILE, QSettings::IniFormat).setValue(WINDOW, geometry()); QSettings(CONFIG_FILE, QSettings::IniFormat).setValue(WINDOW, geometry());
CleanupExtensions();
SetErrorMode(SEM_NOGPFAULTERRORBOX); SetErrorMode(SEM_NOGPFAULTERRORBOX);
ExitProcess(0); ExitProcess(0);
} }
@ -177,7 +178,7 @@ void MainWindow::ThreadAdded(TextThread& thread)
{ {
std::wstring threadCode = Util::GenerateCode(thread.hp, thread.tp.processId); std::wstring threadCode = Util::GenerateCode(thread.hp, thread.tp.processId);
QString ttString = TextThreadString(thread) + S(thread.name) + " (" + S(threadCode) + ")"; QString ttString = TextThreadString(thread) + S(thread.name) + " (" + S(threadCode) + ")";
bool savedMatch = savedThreadCtx.first == thread.tp.ctx && savedThreadCtx.second == thread.tp.ctx2 && savedThreadCode == threadCode; bool savedMatch = savedThreadCtx == std::pair(thread.tp.ctx, thread.tp.ctx2) && savedThreadCode == threadCode;
if (savedMatch) savedThreadCtx.first = savedThreadCtx.second = savedThreadCode[0] = 0; if (savedMatch) savedThreadCtx.first = savedThreadCtx.second = savedThreadCode[0] = 0;
QMetaObject::invokeMethod(this, [this, ttString, savedMatch] QMetaObject::invokeMethod(this, [this, ttString, savedMatch]
{ {
@ -236,9 +237,9 @@ std::array<InfoForExtension, 10> MainWindow::GetMiscInfo(TextThread& thread)
{ {
void(*AddSentence)(MainWindow*, int64_t, const wchar_t*) = [](MainWindow* This, int64_t number, const wchar_t* sentence) void(*AddSentence)(MainWindow*, int64_t, const wchar_t*) = [](MainWindow* This, int64_t number, const wchar_t* sentence)
{ {
std::wstring sentenceStr = sentence; std::wstring copy = sentence;
// pointer from Host::GetThread may not stay valid unless on main thread // pointer from Host::GetThread may not stay valid unless on main thread
QMetaObject::invokeMethod(This, [=]() mutable { if (TextThread* thread = Host::GetThread(number)) thread->AddSentence(std::move(sentenceStr)); }); QMetaObject::invokeMethod(This, [=]() mutable { if (TextThread* thread = Host::GetThread(number)) thread->AddSentence(std::move(copy)); });
}; };
return return
@ -394,7 +395,7 @@ void MainWindow::FindHooks()
connect(&confirm, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); connect(&confirm, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
connect(&confirm, &QDialogButtonBox::helpRequested, &dialog, &QDialog::accept); connect(&confirm, &QDialogButtonBox::helpRequested, &dialog, &QDialog::accept);
dialog.setWindowTitle(SEARCH_FOR_HOOKS); dialog.setWindowTitle(SEARCH_FOR_HOOKS);
if (dialog.exec() == QDialog::Rejected) return; if (!dialog.exec()) return;
if (customSettings) if (customSettings)
{ {
@ -432,7 +433,7 @@ void MainWindow::FindHooks()
QPushButton startButton(START_HOOK_SEARCH, &dialog); QPushButton startButton(START_HOOK_SEARCH, &dialog);
layout.addWidget(&startButton); layout.addWidget(&startButton);
connect(&startButton, &QPushButton::clicked, &dialog, &QDialog::accept); connect(&startButton, &QPushButton::clicked, &dialog, &QDialog::accept);
if (dialog.exec() == QDialog::Rejected) return; if (!dialog.exec()) return;
QByteArray pattern = QByteArray::fromHex(patternInput.text().replace("??", QString::number(XX, 16)).toUtf8()); QByteArray pattern = QByteArray::fromHex(patternInput.text().replace("??", QString::number(XX, 16)).toUtf8());
memcpy(sp.pattern, pattern.data(), sp.length = min(pattern.size(), 25)); memcpy(sp.pattern, pattern.data(), sp.length = min(pattern.size(), 25));
try { filter = std::wregex(S(filterInput.text())); } catch (std::regex_error) {}; try { filter = std::wregex(S(filterInput.text())); } catch (std::regex_error) {};

View File

@ -1,12 +1,10 @@
#include "extension.h" #include "extension.h"
#include "ui_extrawindow.h"
#include "defs.h" #include "defs.h"
#include <QDialog>
#include <QInputDialog> #include <QInputDialog>
#include <QColorDialog> #include <QColorDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QMenu> #include <QMenu>
#include <QLayout>
#include <QLabel>
#include <QFormLayout> #include <QFormLayout>
#include <QLineEdit> #include <QLineEdit>
#include <QSpinBox> #include <QSpinBox>
@ -14,7 +12,6 @@
#include <QPainter> #include <QPainter>
#include <QMouseEvent> #include <QMouseEvent>
#include <QSettings> #include <QSettings>
#include <QTimer>
extern const char* EXTRA_WINDOW_INFO; extern const char* EXTRA_WINDOW_INFO;
extern const char* TOPMOST; extern const char* TOPMOST;
@ -29,117 +26,117 @@ extern const char* FONT_FAMILY;
extern const char* FONT_WEIGHT; extern const char* FONT_WEIGHT;
extern const char* SAVE_SETTINGS; extern const char* SAVE_SETTINGS;
std::mutex m; struct Window : QDialog
struct : QDialog
{ {
public: public:
void launch() Window()
{ {
settings->beginGroup("Extra Window"); ui.setupUi(this);
(new QHBoxLayout(this))->addWidget(display = new QLabel(EXTRA_WINDOW_INFO, this));
display->setTextFormat(Qt::PlainText); settings.beginGroup("Extra Window");
display->setTextInteractionFlags(Qt::TextSelectableByMouse);
display->setAlignment(Qt::AlignTop);
display->setWordWrap(true);
display->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
setWindowFlags(Qt::FramelessWindowHint); setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_TranslucentBackground);
setSizeGripEnabled(true); QMetaObject::invokeMethod(this, [this]
resize(400, 300); {
show(); show();
auto setBackgroundColor = [=](QColor color) QFont font = ui.display->font();
{ if (font.fromString(settings.value(FONT, font.toString()).toString())) ui.display->setFont(font);
if (!color.isValid()) return; setBackgroundColor(settings.value(BG_COLOR, palette().window().color()).value<QColor>());
if (color.alpha() == 0) color.setAlpha(1); setTextColor(settings.value(TEXT_COLOR, ui.display->palette().windowText().color()).value<QColor>());
bgColor = color; setLock(settings.value(SIZE_LOCK, false).toBool());
repaint(); setTopmost(settings.value(TOPMOST, false).toBool());
settings->setValue(BG_COLOR, color); setGeometry(settings.value(WINDOW, geometry()).toRect());
};
auto setTextColor = [=](QColor color) menu.addAction(FONT, this, &Window::RequestFont);
{ menu.addAction(BG_COLOR, [this] { setBackgroundColor(QColorDialog::getColor(bgColor, this, BG_COLOR, QColorDialog::ShowAlphaChannel)); });
if (!color.isValid()) return; menu.addAction(TEXT_COLOR, [this] { setTextColor(QColorDialog::getColor(ui.display->palette().windowText().color(), this, TEXT_COLOR, QColorDialog::ShowAlphaChannel)); });
auto newPalette = display->palette(); for (auto [name, default, slot] : Array<std::tuple<const char*, bool, void(Window::*)(bool)>>{
newPalette.setColor(QPalette::WindowText, color); { TOPMOST, false, &Window::setTopmost },
display->setPalette(newPalette); { SIZE_LOCK, false, &Window::setLock },
settings->setValue(TEXT_COLOR, color); { SHOW_ORIGINAL, true, &Window::setShowOriginal }
}; })
auto requestFont = [=]
{
QFont font = display->font();
auto fontDialog = new QDialog(this, Qt::WindowCloseButtonHint);
fontDialog->setAttribute(Qt::WA_DeleteOnClose);
fontDialog->setWindowTitle(FONT);
auto layout = new QFormLayout(fontDialog);
fontDialog->setLayout(layout);
auto fontFamily = new QLineEdit(font.family(), fontDialog);
layout->addRow(FONT_FAMILY, fontFamily);
auto fontSize = new QSpinBox(fontDialog);
fontSize->setValue(font.pointSize());
layout->addRow(FONT_SIZE, fontSize);
auto fontWeight = new QSpinBox(fontDialog);
fontWeight->setValue(font.weight());
layout->addRow(FONT_WEIGHT, fontWeight);
auto save = new QPushButton(SAVE_SETTINGS, fontDialog);
layout->addWidget(save);
connect(save, &QPushButton::clicked, fontDialog, &QDialog::accept);
fontDialog->open();
connect(fontDialog, &QDialog::accepted, [=]
{ {
QFont font(fontFamily->text(), fontSize->value(), fontWeight->value()); auto action = menu.addAction(name, this, slot);
settings->setValue(FONT, font.toString()); action->setCheckable(true);
display->setFont(font); action->setChecked(settings.value(name, default).toBool());
}); }
}; connect(ui.display, &QLabel::customContextMenuRequested, [this](QPoint point) { menu.exec(mapToGlobal(point)); });
auto setTopmost = [=](bool topmost)
{
SetWindowPos((HWND)winId(), topmost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
settings->setValue(TOPMOST, topmost);
};
auto setLock = [=](bool lock)
{
locked = lock;
setSizeGripEnabled(!lock);
settings->setValue(SIZE_LOCK, lock);
};
auto setShowOriginal = [=](bool showOriginal)
{
if (!showOriginal) QMessageBox::information(this, SHOW_ORIGINAL, SHOW_ORIGINAL_INFO);
settings->setValue(SHOW_ORIGINAL, showOriginal);
};
setGeometry(settings->value(WINDOW, geometry()).toRect());
setLock(settings->value(SIZE_LOCK, false).toBool());
setTopmost(settings->value(TOPMOST, false).toBool());
QFont font = display->font();
font.setPointSize(16);
font.fromString(settings->value(FONT, font.toString()).toString());
display->setFont(font);
setBackgroundColor(settings->value(BG_COLOR, palette().window().color()).value<QColor>());
setTextColor(settings->value(TEXT_COLOR, display->palette().windowText().color()).value<QColor>());
auto menu = new QMenu(display); QMetaObject::invokeMethod(this, [this] { ui.display->setText(EXTRA_WINDOW_INFO); }, Qt::QueuedConnection);
auto topmost = menu->addAction(TOPMOST, setTopmost); }, Qt::QueuedConnection);
topmost->setCheckable(true);
topmost->setChecked(settings->value(TOPMOST, false).toBool());
auto lock = menu->addAction(SIZE_LOCK, setLock);
lock->setCheckable(true);
lock->setChecked(settings->value(SIZE_LOCK, false).toBool());
auto showOriginal = menu->addAction(SHOW_ORIGINAL, setShowOriginal);
showOriginal->setCheckable(true);
showOriginal->setChecked(settings->value(SHOW_ORIGINAL, true).toBool());
menu->addAction(BG_COLOR, [=] { setBackgroundColor(QColorDialog::getColor(bgColor, this, BG_COLOR, QColorDialog::ShowAlphaChannel)); });
menu->addAction(TEXT_COLOR, [=] { setTextColor(QColorDialog::getColor(display->palette().windowText().color(), this, TEXT_COLOR, QColorDialog::ShowAlphaChannel)); });
menu->addAction(FONT, requestFont);
display->setContextMenuPolicy(Qt::CustomContextMenu);
connect(display, &QLabel::customContextMenuRequested, [=](QPoint point) { menu->exec(mapToGlobal(point)); });
connect(this, &QDialog::destroyed, [=] { settings->setValue(WINDOW, geometry()); });
} }
QSettings* settings = new QSettings(CONFIG_FILE, QSettings::IniFormat, this); ~Window()
QLabel* display; {
settings.setValue(WINDOW, geometry());
settings.sync();
}
Ui::ExtraWindow ui;
QSettings settings{ CONFIG_FILE, QSettings::IniFormat, this };
private: private:
void RequestFont()
{
QFont font = ui.display->font();
QDialog fontDialog(this, Qt::WindowCloseButtonHint);
fontDialog.setWindowTitle(FONT);
QFormLayout layout(&fontDialog);
QLineEdit fontFamily(font.family(), &fontDialog);
layout.addRow(FONT_FAMILY, &fontFamily);
QSpinBox fontSize(&fontDialog);
fontSize.setValue(font.pointSize());
layout.addRow(FONT_SIZE, &fontSize);
QSpinBox fontWeight(&fontDialog);
fontWeight.setValue(font.weight());
layout.addRow(FONT_WEIGHT, &fontWeight);
QPushButton save(SAVE_SETTINGS, &fontDialog);
layout.addWidget(&save);
connect(&save, &QPushButton::clicked, &fontDialog, &QDialog::accept);
if (!fontDialog.exec()) return;
font = QFont(fontFamily.text(), fontSize.value(), fontWeight.value());
settings.setValue(FONT, font.toString());
ui.display->setFont(font);
};
void setBackgroundColor(QColor color)
{
if (!color.isValid()) return;
if (color.alpha() == 0) color.setAlpha(1);
bgColor = color;
repaint();
settings.setValue(BG_COLOR, color);
};
void setTextColor(QColor color)
{
if (!color.isValid()) return;
auto newPalette = ui.display->palette();
newPalette.setColor(QPalette::WindowText, color);
ui.display->setPalette(newPalette);
settings.setValue(TEXT_COLOR, color);
};
void setTopmost(bool topmost)
{
SetWindowPos((HWND)winId(), topmost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
settings.setValue(TOPMOST, topmost);
};
void setLock(bool lock)
{
locked = lock;
setSizeGripEnabled(!lock);
settings.setValue(SIZE_LOCK, lock);
};
void setShowOriginal(bool showOriginal)
{
if (!showOriginal) QMessageBox::information(this, SHOW_ORIGINAL, SHOW_ORIGINAL_INFO);
settings.setValue(SHOW_ORIGINAL, showOriginal);
};
void paintEvent(QPaintEvent*) override void paintEvent(QPaintEvent*) override
{ {
QPainter(this).fillRect(rect(), bgColor); QPainter(this).fillRect(rect(), bgColor);
@ -157,51 +154,19 @@ private:
oldPos = event->globalPos(); oldPos = event->globalPos();
} }
bool locked; QMenu menu{ ui.display };
bool locked = true;
QColor bgColor; QColor bgColor;
QPoint oldPos; QPoint oldPos;
}*window = nullptr; } window;
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
QTimer::singleShot(0, []
{
std::lock_guard l(m);
(window = new std::remove_pointer_t<decltype(window)>)->launch();
});
}
break;
case DLL_PROCESS_DETACH:
{
std::lock_guard l(m);
if (window)
{
window->settings->setValue(WINDOW, window->geometry());
window->settings->sync();
}
if (lpReserved == NULL) // https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683
{
delete window;
window = nullptr;
}
}
break;
}
return TRUE;
}
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo) bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
{ {
std::lock_guard l(m); if (!sentenceInfo["current select"]) return false;
if (window == nullptr || !sentenceInfo["current select"]) return false;
QString qSentence = QString::fromStdWString(sentence); QString qSentence = QString::fromStdWString(sentence);
if (!window->settings->value(SHOW_ORIGINAL).toBool()) qSentence = qSentence.section('\n', qSentence.count('\n') / 2 + 1); if (!window.settings.value(SHOW_ORIGINAL).toBool()) qSentence = qSentence.section('\n', qSentence.count('\n') / 2 + 1);
QMetaObject::invokeMethod(window, [=] { window->display->setText(qSentence); }); QMetaObject::invokeMethod(&window, [=] { window.ui.display->setText(qSentence); });
return false; return false;
} }

48
extensions/extrawindow.ui Normal file
View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExtraWindow</class>
<widget class="QDialog" name="ExtraWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="display">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="alignment">
<set>Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -5,7 +5,6 @@
#include <QLayout> #include <QLayout>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QPushButton> #include <QPushButton>
#include <QTimer>
extern const char* LUA_INTRO; extern const char* LUA_INTRO;
extern const char* LOAD_LUA_SCRIPT; extern const char* LOAD_LUA_SCRIPT;
@ -45,61 +44,47 @@ bool logErrors = true;
Synchronized<std::string> script; Synchronized<std::string> script;
std::atomic<int> revCount = 0; std::atomic<int> revCount = 0;
struct : QMainWindow class Window : public QMainWindow
{ {
void launch() public:
Window()
{ {
auto centralWidget = new QWidget(this); connect(&loadButton, &QPushButton::clicked, this, &Window::LoadScript);
auto layout = new QHBoxLayout(centralWidget);
auto scriptEditor = new QPlainTextEdit(std::string(std::istreambuf_iterator<char>(std::ifstream(LUA_SAVE_FILE, std::ios::in)), {}).c_str(), centralWidget); if (scriptEditor.toPlainText().isEmpty()) scriptEditor.setPlainText(LUA_INTRO);
auto loadButton = new QPushButton(LOAD_LUA_SCRIPT, centralWidget); layout.addWidget(&scriptEditor);
if (scriptEditor->toPlainText().isEmpty()) scriptEditor->setPlainText(LUA_INTRO); layout.addWidget(&loadButton);
layout->addWidget(scriptEditor);
layout->addWidget(loadButton);
save = [=]
{
auto script = scriptEditor->toPlainText().toUtf8();
std::ofstream(LUA_SAVE_FILE, std::ios::out | std::ios::trunc).write(script, strlen(script));
};
connect(loadButton, &QPushButton::clicked, [=](bool)
{
revCount += 1;
script->assign(scriptEditor->toPlainText().toUtf8());
save();
});
resize(800, 600); resize(800, 600);
setCentralWidget(centralWidget); setCentralWidget(&centralWidget);
setWindowTitle("Lua"); setWindowTitle("Lua");
show(); QMetaObject::invokeMethod(this, &QWidget::show, Qt::QueuedConnection);
} }
std::function<void()> save; ~Window()
}*window = nullptr; {
Save();
}
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) private:
{ void LoadScript()
switch (ul_reason_for_call)
{ {
case DLL_PROCESS_ATTACH: revCount += 1;
script->assign(scriptEditor.toPlainText().toUtf8());
Save();
}
void Save()
{ {
QTimer::singleShot(0, [] auto script = scriptEditor.toPlainText().toUtf8();
{ std::ofstream(LUA_SAVE_FILE, std::ios::out | std::ios::trunc).write(script, script.size());
(window = new std::remove_pointer_t<decltype(window)>)->launch();
});
} }
break;
case DLL_PROCESS_DETACH: QWidget centralWidget{ this };
{ QHBoxLayout layout{ &centralWidget };
if (window) window->save(); QPlainTextEdit scriptEditor{ std::string(std::istreambuf_iterator<char>(std::ifstream(LUA_SAVE_FILE, std::ios::in)), {}).c_str(), &centralWidget };
if (lpReserved == NULL) // https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683 QPushButton loadButton{ LOAD_LUA_SCRIPT, &centralWidget };
{ } window;
delete window;
}
}
break;
}
return TRUE;
}
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo) bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
{ {

View File

@ -1,6 +1,5 @@
#include "extension.h" #include "extension.h"
#include "ui_regexfilter.h" #include "ui_regexfilter.h"
#include <QTimer>
extern const char* REGEX_FILTER; extern const char* REGEX_FILTER;
extern const char* INVALID_REGEX; extern const char* INVALID_REGEX;
@ -9,56 +8,35 @@ extern const char* CURRENT_FILTER;
std::wregex regex; std::wregex regex;
std::shared_mutex m; std::shared_mutex m;
struct : QMainWindow class Window : public QMainWindow
{ {
void launch() public:
Window()
{ {
ui.setupUi(this); ui.setupUi(this);
connect(ui.input, &QLineEdit::textEdited, [=](QString newRegex)
{ connect(ui.input, &QLineEdit::textEdited, this, &Window::setRegex);
std::lock_guard l(m);
try { regex = newRegex.toStdWString(); }
catch (std::regex_error) { return ui.output->setText(INVALID_REGEX); }
ui.output->setText(QString(CURRENT_FILTER).arg(newRegex));
});
setWindowTitle(REGEX_FILTER); setWindowTitle(REGEX_FILTER);
show(); QMetaObject::invokeMethod(this, &QWidget::show, Qt::QueuedConnection);
}
private:
void setRegex(QString newRegex)
{
std::lock_guard l(m);
try { regex = newRegex.toStdWString(); }
catch (std::regex_error) { return ui.output->setText(INVALID_REGEX); }
ui.output->setText(QString(CURRENT_FILTER).arg(newRegex));
} }
Ui::FilterWindow ui; Ui::FilterWindow ui;
}*window = nullptr; } window;
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
QTimer::singleShot(0, []
{
std::lock_guard l(m);
(window = new std::remove_pointer_t<decltype(window)>)->launch();
});
}
break;
case DLL_PROCESS_DETACH:
{
if (lpReserved == NULL) // https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683
{
std::lock_guard l(m);
delete window;
window = nullptr;
}
}
break;
}
return TRUE;
}
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo) bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
{ {
std::shared_lock l(m);
if (sentenceInfo["text number"] == 0) return false; if (sentenceInfo["text number"] == 0) return false;
std::shared_lock l(m);
sentence = std::regex_replace(sentence, regex, L""); sentence = std::regex_replace(sentence, regex, L"");
return true; return true;
} }

View File

@ -93,12 +93,12 @@ bool Replace(std::wstring& sentence)
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{ {
static HANDLE replacementFile; // not actually used to read/write, just to ensure it exists // not actually used to read/write, just to ensure it exists
static AutoHandle<> replacementFile = CreateFileA(REPLACE_SAVE_FILE, FILE_GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
switch (ul_reason_for_call) switch (ul_reason_for_call)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
{ {
replacementFile = CreateFileA(REPLACE_SAVE_FILE, FILE_GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
std::vector<BYTE> file(std::istreambuf_iterator<char>(std::ifstream(REPLACE_SAVE_FILE, std::ios::in | std::ios::binary)), {}); std::vector<BYTE> file(std::istreambuf_iterator<char>(std::ifstream(REPLACE_SAVE_FILE, std::ios::in | std::ios::binary)), {});
if (Parse(std::wstring((wchar_t*)file.data(), file.size() / sizeof(wchar_t))) == 0) if (Parse(std::wstring((wchar_t*)file.data(), file.size() / sizeof(wchar_t))) == 0)
{ {
@ -110,7 +110,6 @@ BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
{ {
CloseHandle(replacementFile);
} }
break; break;
} }

View File

@ -5,7 +5,6 @@
#include <QListWidget> #include <QListWidget>
#include <QInputDialog> #include <QInputDialog>
#include <QKeyEvent> #include <QKeyEvent>
#include <QTimer>
extern const char* THREAD_LINKER; extern const char* THREAD_LINKER;
extern const char* LINK; extern const char* LINK;
@ -13,86 +12,58 @@ extern const char* THREAD_LINK_FROM;
extern const char* THREAD_LINK_TO; extern const char* THREAD_LINK_TO;
extern const char* HEXADECIMAL; extern const char* HEXADECIMAL;
std::mutex m;
std::unordered_map<int64_t, std::unordered_multiset<int64_t>> linkedTextHandles; std::unordered_map<int64_t, std::unordered_multiset<int64_t>> linkedTextHandles;
std::shared_mutex m;
struct : QMainWindow class Window : public QMainWindow
{ {
void launch() public:
Window()
{ {
auto centralWidget = new QWidget(this); connect(&linkButton, &QPushButton::clicked, this, &Window::Link);
auto layout = new QHBoxLayout(centralWidget);
auto linkList = new QListWidget(centralWidget);
auto addLink = new QPushButton(LINK, centralWidget);
layout->addWidget(linkList);
layout->addWidget(addLink);
connect(addLink, &QPushButton::clicked, [=] layout.addWidget(&linkList);
{ layout.addWidget(&linkButton);
bool ok1, ok2, ok3, ok4;
int from = QInputDialog::getText(this, THREAD_LINK_FROM, HEXADECIMAL, QLineEdit::Normal, "", &ok1, Qt::WindowCloseButtonHint).toInt(&ok2, 16);
int to = QInputDialog::getText(this, THREAD_LINK_TO, HEXADECIMAL, QLineEdit::Normal, "", &ok3, Qt::WindowCloseButtonHint).toInt(&ok4, 16);
if (ok1 && ok2 && ok3 && ok4)
{
std::lock_guard l(m);
linkedTextHandles[from].insert(to);
linkList->addItem(QString::number(from, 16) + "->" + QString::number(to, 16));
}
});
Unlink = [=]
{
if (linkList->currentItem())
{
QStringList link = linkList->currentItem()->text().split("->");
linkList->takeItem(linkList->currentRow());
std::lock_guard l(m);
linkedTextHandles[link[0].toInt(nullptr, 16)].erase(link[1].toInt(nullptr, 16));
}
};
setCentralWidget(centralWidget); setCentralWidget(&centralWidget);
setWindowTitle(THREAD_LINKER); setWindowTitle(THREAD_LINKER);
show(); QMetaObject::invokeMethod(this, &QWidget::show, Qt::QueuedConnection);
}
private:
void Link()
{
bool ok1, ok2, ok3, ok4;
int from = QInputDialog::getText(this, THREAD_LINK_FROM, HEXADECIMAL, QLineEdit::Normal, "", &ok1, Qt::WindowCloseButtonHint).toInt(&ok2, 16);
int to = QInputDialog::getText(this, THREAD_LINK_TO, HEXADECIMAL, QLineEdit::Normal, "", &ok3, Qt::WindowCloseButtonHint).toInt(&ok4, 16);
if (ok1 && ok2 && ok3 && ok4)
{
std::lock_guard l(m);
linkedTextHandles[from].insert(to);
linkList.addItem(QString::number(from, 16) + "->" + QString::number(to, 16));
}
} }
void keyPressEvent(QKeyEvent* event) override void keyPressEvent(QKeyEvent* event) override
{ {
if (event->key() == Qt::Key_Delete) Unlink(); if (event->key() == Qt::Key_Delete && linkList.currentItem())
}
std::function<void()> Unlink;
}*window = nullptr;
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
QTimer::singleShot(0, []
{ {
QStringList link = linkList.currentItem()->text().split("->");
linkList.takeItem(linkList.currentRow());
std::lock_guard l(m); std::lock_guard l(m);
(window = new std::remove_pointer_t<decltype(window)>)->launch(); linkedTextHandles[link[0].toInt(nullptr, 16)].erase(link[1].toInt(nullptr, 16));
});
}
break;
case DLL_PROCESS_DETACH:
{
if (lpReserved == NULL) // https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683
{
std::lock_guard l(m);
delete window;
window = nullptr;
} }
} }
break;
} QWidget centralWidget{ this };
return TRUE; QHBoxLayout layout{ &centralWidget };
} QListWidget linkList{ &centralWidget };
QPushButton linkButton{ LINK, &centralWidget };
} window;
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo) bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
{ {
std::lock_guard l(m); std::shared_lock l(m);
int64_t textHandle = sentenceInfo["text number"]; int64_t textHandle = sentenceInfo["text number"];
for (auto linkedHandle : linkedTextHandles[textHandle]) for (auto linkedHandle : linkedTextHandles[textHandle])