aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2020-06-06 10:09:29 +1000
committerNeil <nyamatongwe@gmail.com>2020-06-06 10:09:29 +1000
commitb5b2247de50e20e7db3c64e786aab788d9f49148 (patch)
tree721bba5f0c53167e5e9c7dd2b5a15061e9d9f41c
parenteadb190f1bb1303dffcfcb1e8d5305a2c1e2ef60 (diff)
downloadscintilla-mirror-b5b2247de50e20e7db3c64e786aab788d9f49148.tar.gz
Defer most initialisation until Scintilla window is created.
Previously, more initialisation was performed inside DllMain but some actions such as loading libraries are unsafe inside DllMain. Avoid listbox UnregisterClass if no attempt to register which will occur if no Scintilla windows were created. std::call_once is used to ensure initialisation is performed at most once.
-rw-r--r--scripts/HeaderOrder.txt1
-rw-r--r--win32/PlatWin.cxx8
-rw-r--r--win32/PlatWin.h3
-rw-r--r--win32/ScintillaWin.cxx38
4 files changed, 29 insertions, 21 deletions
diff --git a/scripts/HeaderOrder.txt b/scripts/HeaderOrder.txt
index 53a1d7778..1f61d5440 100644
--- a/scripts/HeaderOrder.txt
+++ b/scripts/HeaderOrder.txt
@@ -45,6 +45,7 @@
#include <iostream>
#include <sstream>
#include <fstream>
+#include <mutex>
#include <filesystem>
// POSIX
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
index a7bc5626c..96f642824 100644
--- a/win32/PlatWin.cxx
+++ b/win32/PlatWin.cxx
@@ -3243,8 +3243,10 @@ bool ListBoxX_Register() noexcept {
return ::RegisterClassEx(&wndclassc) != 0;
}
-bool ListBoxX_Unregister() noexcept {
- return ::UnregisterClass(ListBoxX_ClassName, hinstPlatformRes) != 0;
+void ListBoxX_Unregister() noexcept {
+ if (hinstPlatformRes) {
+ ::UnregisterClass(ListBoxX_ClassName, hinstPlatformRes);
+ }
}
}
@@ -3374,7 +3376,7 @@ void Platform::Assert(const char *c, const char *file, int line) {
}
}
-void Platform_Initialise(void *hInstance) {
+void Platform_Initialise(void *hInstance) noexcept {
hinstPlatformRes = static_cast<HINSTANCE>(hInstance);
LoadDpiForWindow();
ListBoxX_Register();
diff --git a/win32/PlatWin.h b/win32/PlatWin.h
index d88ee6324..58ba5e78f 100644
--- a/win32/PlatWin.h
+++ b/win32/PlatWin.h
@@ -14,7 +14,8 @@ namespace Scintilla {
#define USER_DEFAULT_SCREEN_DPI 96
#endif
-extern void Platform_Initialise(void *hInstance);
+extern void Platform_Initialise(void *hInstance) noexcept;
+
extern void Platform_Finalise(bool fromDllMain);
constexpr RECT RectFromPRectangle(PRectangle prc) noexcept {
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index f2f6976f5..916185569 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -22,6 +22,7 @@
#include <algorithm>
#include <memory>
#include <chrono>
+#include <mutex>
// Want to use std::min and std::max so don't want Windows.h version of min and max
#if !defined(NOMINMAX)
@@ -481,6 +482,7 @@ public:
/// Implement important part of IDataObject
STDMETHODIMP GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM);
+ static void Prepare() noexcept;
static bool Register(HINSTANCE hInstance_) noexcept;
static bool Unregister() noexcept;
@@ -3305,6 +3307,22 @@ STDMETHODIMP ScintillaWin::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) {
return S_OK;
}
+void ScintillaWin::Prepare() noexcept {
+ Platform_Initialise(hInstance);
+
+ // Register the CallTip class
+ WNDCLASSEX wndclassc{};
+ wndclassc.cbSize = sizeof(wndclassc);
+ wndclassc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
+ wndclassc.cbWndExtra = sizeof(ScintillaWin *);
+ wndclassc.hInstance = hInstance;
+ wndclassc.lpfnWndProc = ScintillaWin::CTWndProc;
+ wndclassc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ wndclassc.lpszClassName = callClassName;
+
+ callClassAtom = ::RegisterClassEx(&wndclassc);
+}
+
bool ScintillaWin::Register(HINSTANCE hInstance_) noexcept {
hInstance = hInstance_;
@@ -3319,22 +3337,7 @@ bool ScintillaWin::Register(HINSTANCE hInstance_) noexcept {
wndclass.hInstance = hInstance;
wndclass.lpszClassName = L"Scintilla";
scintillaClassAtom = ::RegisterClassExW(&wndclass);
- bool result = 0 != scintillaClassAtom;
-
- if (result) {
- // Register the CallTip class
- WNDCLASSEX wndclassc {};
- wndclassc.cbSize = sizeof(wndclassc);
- wndclassc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
- wndclassc.cbWndExtra = sizeof(ScintillaWin *);
- wndclassc.hInstance = hInstance;
- wndclassc.lpfnWndProc = ScintillaWin::CTWndProc;
- wndclassc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
- wndclassc.lpszClassName = callClassName;
-
- callClassAtom = ::RegisterClassEx(&wndclassc);
- result = 0 != callClassAtom;
- }
+ const bool result = 0 != scintillaClassAtom;
return result;
}
@@ -3522,6 +3525,8 @@ LRESULT PASCAL ScintillaWin::SWndProc(
if (sci == nullptr) {
try {
if (iMessage == WM_CREATE) {
+ static std::once_flag once;
+ std::call_once(once, Prepare);
// Create C++ object associated with window
sci = new ScintillaWin(hWnd);
SetWindowPointer(hWnd, sci);
@@ -3548,7 +3553,6 @@ LRESULT PASCAL ScintillaWin::SWndProc(
// This function is externally visible so it can be called from container when building statically.
// Must be called once only.
int Scintilla_RegisterClasses(void *hInstance) {
- Platform_Initialise(hInstance);
const bool result = ScintillaWin::Register(static_cast<HINSTANCE>(hInstance));
return result;
}