diff --git a/deploy.ps1 b/deploy.ps1 index 515f8bb..8457ef5 100644 --- a/deploy.ps1 +++ b/deploy.ps1 @@ -15,6 +15,7 @@ foreach ($arch in @("86", "64")) { "Google Translate.dll", "Regex Filter.dll", "Remove Repetition.dll", + "Thread Linker.dll", "platforms", "styles" ) | ForEach-Object { "builds/RelWithDebInfo_x$($arch)/$($_)" }; diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index a5c1276..6f141cb 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(Extra\ Window SHARED extrawindow.cpp extensionimpl.cpp) add_library(Google\ Translate SHARED googletranslate.cpp extensionimpl.cpp) add_library(Regex\ Filter SHARED regexfilter.cpp extensionimpl.cpp) add_library(Remove\ Repetition SHARED removerepeat.cpp extensionimpl.cpp) +add_library(Thread\ Linker SHARED threadlinker.cpp extensionimpl.cpp) add_executable(Extension_Tests extensiontester.cpp) @@ -18,3 +19,4 @@ target_link_libraries(Bing\ Translate winhttp Qt5::Widgets) target_link_libraries(Extra\ Window Qt5::Widgets) target_link_libraries(Google\ Translate winhttp Qt5::Widgets) target_link_libraries(Regex\ Filter Qt5::Widgets) +target_link_libraries(Thread\ Linker Qt5::Widgets) diff --git a/extensions/threadlinker.cpp b/extensions/threadlinker.cpp new file mode 100644 index 0000000..00dc0ea --- /dev/null +++ b/extensions/threadlinker.cpp @@ -0,0 +1,100 @@ +#include "extension.h" +#include "text.h" +#include +#include +#include +#include +#include +#include +#include + +std::mutex m; +std::unordered_map> linkedTextHandles; + +struct : QMainWindow +{ + void launch() + { + auto centralWidget = new QWidget(this); + 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, [=] + { + bool ok1, ok2, ok3, ok4; + int from = QInputDialog::getText(this, THREAD_LINK_FROM, "", QLineEdit::Normal, "0x", &ok1, Qt::WindowCloseButtonHint).toInt(&ok2, 16); + int to = QInputDialog::getText(this, THREAD_LINK_TO, "", QLineEdit::Normal, "0x", &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); + setWindowTitle(THREAD_LINKER); + show(); + } + + void keyPressEvent(QKeyEvent* event) override + { + if (event->key() == Qt::Key_Delete) Unlink(); + } + + std::function 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, [] + { + std::lock_guard l(m); + (window = new std::remove_pointer_t)->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) +{ + std::lock_guard l(m); + static std::unordered_map queuedWritesByHandle; + int64_t textHandle = sentenceInfo["text handle"]; + + for (auto linkedHandle : linkedTextHandles[textHandle]) queuedWritesByHandle[linkedHandle] += L"\n" + sentence; + + if (queuedWritesByHandle[textHandle].empty()) return false; + sentence += queuedWritesByHandle[textHandle]; + queuedWritesByHandle[textHandle].clear(); + return true; +}