summaryrefslogtreecommitdiff
path: root/src/mir_core
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2023-01-02 21:10:29 +0300
committerdartraiden <wowemuh@gmail.com>2023-01-02 21:10:29 +0300
commit1979fd80424d16b2e489f9b57d01d9c7811d25a2 (patch)
tree960d42c5fe4a51f0fe2850bea91256e226bce221 /src/mir_core
parentadfbbb217d4f4a05acf198755f219a5223d31c27 (diff)
Update copyrights
Diffstat (limited to 'src/mir_core')
-rw-r--r--src/mir_core/res/version.rc114
-rw-r--r--src/mir_core/src/Linux/CCtrlBase.cpp410
-rw-r--r--src/mir_core/src/Linux/CCtrlButton.cpp110
-rw-r--r--src/mir_core/src/Linux/CCtrlCheck.cpp140
-rw-r--r--src/mir_core/src/Linux/CCtrlClc.cpp414
-rw-r--r--src/mir_core/src/Linux/CCtrlColor.cpp122
-rw-r--r--src/mir_core/src/Linux/CCtrlCombo.cpp338
-rw-r--r--src/mir_core/src/Linux/CCtrlData.cpp104
-rw-r--r--src/mir_core/src/Linux/CCtrlEdit.cpp136
-rw-r--r--src/mir_core/src/Linux/CCtrlHyperlink.cpp108
-rw-r--r--src/mir_core/src/Linux/CCtrlLabel.cpp60
-rw-r--r--src/mir_core/src/Linux/CCtrlListBox.cpp320
-rw-r--r--src/mir_core/src/Linux/CCtrlListView.cpp1102
-rw-r--r--src/mir_core/src/Linux/CCtrlMButton.cpp124
-rw-r--r--src/mir_core/src/Linux/CCtrlPages.cpp822
-rw-r--r--src/mir_core/src/Linux/CCtrlSlider.cpp140
-rw-r--r--src/mir_core/src/Linux/CCtrlSpin.cpp162
-rw-r--r--src/mir_core/src/Linux/CCtrlTreeOpts.cpp432
-rw-r--r--src/mir_core/src/Linux/CCtrlTreeView.cpp1634
-rw-r--r--src/mir_core/src/Linux/CDbLink.cpp184
-rw-r--r--src/mir_core/src/Linux/CDlgBase.cpp520
-rw-r--r--src/mir_core/src/Linux/CProgress.cpp106
-rw-r--r--src/mir_core/src/Linux/CSplitter.cpp166
-rw-r--r--src/mir_core/src/Linux/CTimer.cpp186
-rw-r--r--src/mir_core/src/Linux/cctrldate.cpp98
-rw-r--r--src/mir_core/src/Linux/fileutil.cpp178
-rw-r--r--src/mir_core/src/Linux/strutil.cpp96
-rw-r--r--src/mir_core/src/Windows/CCtrlBase.cpp448
-rw-r--r--src/mir_core/src/Windows/CCtrlButton.cpp108
-rw-r--r--src/mir_core/src/Windows/CCtrlCheck.cpp136
-rw-r--r--src/mir_core/src/Windows/CCtrlClc.cpp422
-rw-r--r--src/mir_core/src/Windows/CCtrlColor.cpp122
-rw-r--r--src/mir_core/src/Windows/CCtrlCombo.cpp370
-rw-r--r--src/mir_core/src/Windows/CCtrlData.cpp104
-rw-r--r--src/mir_core/src/Windows/CCtrlDate.cpp98
-rw-r--r--src/mir_core/src/Windows/CCtrlEdit.cpp136
-rw-r--r--src/mir_core/src/Windows/CCtrlHyperlink.cpp108
-rw-r--r--src/mir_core/src/Windows/CCtrlLabel.cpp62
-rw-r--r--src/mir_core/src/Windows/CCtrlListBox.cpp320
-rw-r--r--src/mir_core/src/Windows/CCtrlListView.cpp1102
-rw-r--r--src/mir_core/src/Windows/CCtrlMButton.cpp124
-rw-r--r--src/mir_core/src/Windows/CCtrlPages.cpp822
-rw-r--r--src/mir_core/src/Windows/CCtrlRichEdit.cpp384
-rw-r--r--src/mir_core/src/Windows/CCtrlSlider.cpp140
-rw-r--r--src/mir_core/src/Windows/CCtrlSpin.cpp162
-rw-r--r--src/mir_core/src/Windows/CCtrlTreeOpts.cpp2
-rw-r--r--src/mir_core/src/Windows/CCtrlTreeView.cpp2
-rw-r--r--src/mir_core/src/Windows/CDbLink.cpp184
-rw-r--r--src/mir_core/src/Windows/CDlgBase.cpp1044
-rw-r--r--src/mir_core/src/Windows/CProgress.cpp106
-rw-r--r--src/mir_core/src/Windows/CSplitter.cpp166
-rw-r--r--src/mir_core/src/Windows/CTimer.cpp180
-rw-r--r--src/mir_core/src/Windows/cmdline.cpp154
-rw-r--r--src/mir_core/src/Windows/colourpicker.cpp210
-rw-r--r--src/mir_core/src/Windows/diatheme.cpp340
-rw-r--r--src/mir_core/src/Windows/fileutil.cpp156
-rw-r--r--src/mir_core/src/Windows/hyperlink.cpp554
-rw-r--r--src/mir_core/src/Windows/icons.cpp148
-rw-r--r--src/mir_core/src/Windows/langpack.cpp1530
-rw-r--r--src/mir_core/src/Windows/locks.cpp92
-rw-r--r--src/mir_core/src/Windows/miranda.cpp2
-rw-r--r--src/mir_core/src/Windows/openurl.cpp152
-rw-r--r--src/mir_core/src/Windows/path.cpp492
-rw-r--r--src/mir_core/src/Windows/resizer.cpp302
-rw-r--r--src/mir_core/src/Windows/subclass.cpp402
-rw-r--r--src/mir_core/src/Windows/threads.cpp800
-rw-r--r--src/mir_core/src/Windows/timezones.cpp1186
-rw-r--r--src/mir_core/src/Windows/windowlist.cpp210
-rw-r--r--src/mir_core/src/Windows/winutil.cpp354
-rw-r--r--src/mir_core/src/Windows/winver.cpp744
-rw-r--r--src/mir_core/src/binbuffer.cpp340
-rw-r--r--src/mir_core/src/bitmaps.cpp2
-rw-r--r--src/mir_core/src/db.cpp2
-rw-r--r--src/mir_core/src/http.cpp2
-rw-r--r--src/mir_core/src/lists.cpp2
-rw-r--r--src/mir_core/src/logger.cpp406
-rw-r--r--src/mir_core/src/memory.cpp590
-rw-r--r--src/mir_core/src/miranda.h202
-rw-r--r--src/mir_core/src/modules.cpp1408
-rw-r--r--src/mir_core/src/mstring.cpp290
-rw-r--r--src/mir_core/src/stdafx.cxx2
-rw-r--r--src/mir_core/src/stdafx.h168
-rw-r--r--src/mir_core/src/utf.cpp882
-rw-r--r--src/mir_core/src/utils.cpp1140
84 files changed, 14221 insertions, 14221 deletions
diff --git a/src/mir_core/res/version.rc b/src/mir_core/res/version.rc
index 626717e99b..6d60274913 100644
--- a/src/mir_core/res/version.rc
+++ b/src/mir_core/res/version.rc
@@ -1,57 +1,57 @@
-#ifdef APSTUDIO_INVOKED
-#error this file is not editable by Microsoft Visual C++
-#endif //APSTUDIO_INVOKED
-
-#include <windows.h>
-#include <winres.h>
-
-#include "../include/m_version.h"
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1250)
-#endif //_WIN32
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION MIRANDA_VERSION_FILEVERSION
- PRODUCTVERSION MIRANDA_VERSION_FILEVERSION
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "000004b0"
- BEGIN
- VALUE "Comments", "Licensed under the terms of the GNU General Public License\0"
- VALUE "CompanyName", "Miranda NG team\0"
- VALUE "FileDescription", "Miranda NG\0"
- VALUE "FileVersion", MIRANDA_VERSION_DISPLAY
- VALUE "InternalName", "mir_core\0"
- VALUE "LegalCopyright", "Copyright © 2000-11 Miranda IM, 2012-22 Miranda NG team. This software is released under the terms of the GNU General Public License.\0"
- VALUE "LegalTrademarks", "\0"
- VALUE "OriginalFilename", "mir_core.mir\0"
- VALUE "PrivateBuild", "\0"
- VALUE "ProductName", "Miranda NG\0"
- VALUE "ProductVersion", MIRANDA_VERSION_DISPLAY
- VALUE "SpecialBuild", "\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x0, 1200
- END
-END
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
+#ifdef APSTUDIO_INVOKED
+#error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+#include <windows.h>
+#include <winres.h>
+
+#include "../include/m_version.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1250)
+#endif //_WIN32
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MIRANDA_VERSION_FILEVERSION
+ PRODUCTVERSION MIRANDA_VERSION_FILEVERSION
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "Licensed under the terms of the GNU General Public License\0"
+ VALUE "CompanyName", "Miranda NG team\0"
+ VALUE "FileDescription", "Miranda NG\0"
+ VALUE "FileVersion", MIRANDA_VERSION_DISPLAY
+ VALUE "InternalName", "mir_core\0"
+ VALUE "LegalCopyright", "Copyright © 2000-11 Miranda IM, 2012-23 Miranda NG team. This software is released under the terms of the GNU General Public License.\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "mir_core.mir\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "Miranda NG\0"
+ VALUE "ProductVersion", MIRANDA_VERSION_DISPLAY
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
diff --git a/src/mir_core/src/Linux/CCtrlBase.cpp b/src/mir_core/src/Linux/CCtrlBase.cpp
index cba8567e52..ec84f1b77c 100644
--- a/src/mir_core/src/Linux/CCtrlBase.cpp
+++ b/src/mir_core/src/Linux/CCtrlBase.cpp
@@ -1,205 +1,205 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-static mir_cs csCtrl;
-
-static int CompareControls(const CCtrlBase *p1, const CCtrlBase *p2)
-{
- return (INT_PTR)p1->GetHwnd() - (INT_PTR)p2->GetHwnd();
-}
-
-static LIST<CCtrlBase> arControls(10, CompareControls);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlBase
-
-CCtrlBase::CCtrlBase(CDlgBase *wnd, int idCtrl) :
- m_parentWnd(wnd),
- m_idCtrl(idCtrl)
-{
- if (wnd)
- wnd->AddControl(this);
-}
-
-CCtrlBase::~CCtrlBase()
-{
-}
-
-void CCtrlBase::OnInit()
-{
- m_hwnd = nullptr;
-}
-
-void CCtrlBase::OnDestroy()
-{
- void *bullshit[2]; // vfptr + hwnd
- bullshit[1] = m_hwnd;
- CCtrlBase *pCtrl = arControls.find((CCtrlBase*)&bullshit);
- if (pCtrl) {
- pCtrl->Unsubclass();
- arControls.remove(pCtrl);
- }
-
- evas_object_del(m_hwnd);
- m_hwnd = nullptr;
-}
-
-bool CCtrlBase::OnApply()
-{
- m_bChanged = false;
- return true;
-}
-
-void CCtrlBase::OnReset()
-{
-}
-
-void CCtrlBase::Show(bool bShow)
-{
- // ::ShowWindow(m_hwnd, bShow ? SW_SHOW : SW_HIDE);
-}
-
-void CCtrlBase::Enable(bool bIsEnable)
-{
- // ::EnableWindow(m_hwnd, bIsEnable);
-}
-
-bool CCtrlBase::Enabled() const
-{
- return (m_hwnd != nullptr);
-}
-
-void CCtrlBase::NotifyChange()
-{
- if (!m_parentWnd)
- return;
-
- if (m_parentWnd->IsInitialized()) {
- m_bChanged = true;
- if (!m_bSilent)
- m_parentWnd->NotifyChange();
- }
-
- OnChange(this);
-}
-
-LRESULT CCtrlBase::SendMsg(UINT Msg, WPARAM wParam, LPARAM lParam) const
-{
- // return ::SendMessage(m_hwnd, Msg, wParam, lParam);
- return 0;
-}
-
-void CCtrlBase::SetText(const wchar_t *text)
-{
- // ::SetWindowText(m_hwnd, text);
-}
-
-void CCtrlBase::SetTextA(const char *text)
-{
- // ::SetWindowTextA(m_hwnd, text);
-}
-
-void CCtrlBase::SetDraw(bool bEnable)
-{
- // ::SendMessage(m_hwnd, WM_SETREDRAW, bEnable, 0);
-}
-
-void CCtrlBase::SetInt(int value)
-{
- wchar_t buf[32] = { 0 };
- mir_snwprintf(buf, L"%d", value);
- SetText(buf);
-}
-
-wchar_t* CCtrlBase::GetText() const
-{
- return mir_wstrdup(L"");
-}
-
-char* CCtrlBase::GetTextA() const
-{
- return mir_strdup("");
-}
-
-char* CCtrlBase::GetTextU() const
-{
- return mir_utf8encodeW(ptrW(GetText()));
-}
-
-wchar_t* CCtrlBase::GetText(wchar_t *buf, size_t size) const
-{
- // GetWindowTextW(m_hwnd, buf, (int)size);
- buf[size - 1] = 0;
- return buf;
-}
-
-char* CCtrlBase::GetTextA(char *buf, size_t size) const
-{
- // GetWindowTextA(m_hwnd, buf, (int)size);
- buf[size - 1] = 0;
- return buf;
-}
-
-char* CCtrlBase::GetTextU(char *buf, size_t size) const
-{
- ptrW wszText(GetText());
- strncpy_s(buf, size, T2Utf(wszText), _TRUNCATE);
- return buf;
-}
-
-int CCtrlBase::GetInt() const
-{
- // int length = GetWindowTextLengthW(m_hwnd) + 1;
- // wchar_t *result = (wchar_t *)_alloca(length * sizeof(wchar_t));
- // GetWindowTextW(m_hwnd, result, length);
- // return _wtoi(result);
- return 0;
-}
-
-void CCtrlBase::GetCaretPos(CContextMenuPos &pos) const
-{
- pos.pCtrl = this;
- pos.iCurr = -1;
-
- // if (pos.pt.x == 0 && pos.pt.y == 0)
- // GetCursorPos(&pos.pt);
-}
-
-LRESULT CCtrlBase::CustomWndProc(UINT, WPARAM, LPARAM)
-{
- return FALSE;
-}
-
-void CCtrlBase::Subclass()
-{
- // mir_subclassWindow(m_hwnd, GlobalSubclassWndProc);
-
- mir_cslock lck(csCtrl);
- arControls.insert(this);
-}
-
-void CCtrlBase::Unsubclass()
-{
- // mir_unsubclassWindow(m_hwnd, GlobalSubclassWndProc);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+static mir_cs csCtrl;
+
+static int CompareControls(const CCtrlBase *p1, const CCtrlBase *p2)
+{
+ return (INT_PTR)p1->GetHwnd() - (INT_PTR)p2->GetHwnd();
+}
+
+static LIST<CCtrlBase> arControls(10, CompareControls);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlBase
+
+CCtrlBase::CCtrlBase(CDlgBase *wnd, int idCtrl) :
+ m_parentWnd(wnd),
+ m_idCtrl(idCtrl)
+{
+ if (wnd)
+ wnd->AddControl(this);
+}
+
+CCtrlBase::~CCtrlBase()
+{
+}
+
+void CCtrlBase::OnInit()
+{
+ m_hwnd = nullptr;
+}
+
+void CCtrlBase::OnDestroy()
+{
+ void *bullshit[2]; // vfptr + hwnd
+ bullshit[1] = m_hwnd;
+ CCtrlBase *pCtrl = arControls.find((CCtrlBase*)&bullshit);
+ if (pCtrl) {
+ pCtrl->Unsubclass();
+ arControls.remove(pCtrl);
+ }
+
+ evas_object_del(m_hwnd);
+ m_hwnd = nullptr;
+}
+
+bool CCtrlBase::OnApply()
+{
+ m_bChanged = false;
+ return true;
+}
+
+void CCtrlBase::OnReset()
+{
+}
+
+void CCtrlBase::Show(bool bShow)
+{
+ // ::ShowWindow(m_hwnd, bShow ? SW_SHOW : SW_HIDE);
+}
+
+void CCtrlBase::Enable(bool bIsEnable)
+{
+ // ::EnableWindow(m_hwnd, bIsEnable);
+}
+
+bool CCtrlBase::Enabled() const
+{
+ return (m_hwnd != nullptr);
+}
+
+void CCtrlBase::NotifyChange()
+{
+ if (!m_parentWnd)
+ return;
+
+ if (m_parentWnd->IsInitialized()) {
+ m_bChanged = true;
+ if (!m_bSilent)
+ m_parentWnd->NotifyChange();
+ }
+
+ OnChange(this);
+}
+
+LRESULT CCtrlBase::SendMsg(UINT Msg, WPARAM wParam, LPARAM lParam) const
+{
+ // return ::SendMessage(m_hwnd, Msg, wParam, lParam);
+ return 0;
+}
+
+void CCtrlBase::SetText(const wchar_t *text)
+{
+ // ::SetWindowText(m_hwnd, text);
+}
+
+void CCtrlBase::SetTextA(const char *text)
+{
+ // ::SetWindowTextA(m_hwnd, text);
+}
+
+void CCtrlBase::SetDraw(bool bEnable)
+{
+ // ::SendMessage(m_hwnd, WM_SETREDRAW, bEnable, 0);
+}
+
+void CCtrlBase::SetInt(int value)
+{
+ wchar_t buf[32] = { 0 };
+ mir_snwprintf(buf, L"%d", value);
+ SetText(buf);
+}
+
+wchar_t* CCtrlBase::GetText() const
+{
+ return mir_wstrdup(L"");
+}
+
+char* CCtrlBase::GetTextA() const
+{
+ return mir_strdup("");
+}
+
+char* CCtrlBase::GetTextU() const
+{
+ return mir_utf8encodeW(ptrW(GetText()));
+}
+
+wchar_t* CCtrlBase::GetText(wchar_t *buf, size_t size) const
+{
+ // GetWindowTextW(m_hwnd, buf, (int)size);
+ buf[size - 1] = 0;
+ return buf;
+}
+
+char* CCtrlBase::GetTextA(char *buf, size_t size) const
+{
+ // GetWindowTextA(m_hwnd, buf, (int)size);
+ buf[size - 1] = 0;
+ return buf;
+}
+
+char* CCtrlBase::GetTextU(char *buf, size_t size) const
+{
+ ptrW wszText(GetText());
+ strncpy_s(buf, size, T2Utf(wszText), _TRUNCATE);
+ return buf;
+}
+
+int CCtrlBase::GetInt() const
+{
+ // int length = GetWindowTextLengthW(m_hwnd) + 1;
+ // wchar_t *result = (wchar_t *)_alloca(length * sizeof(wchar_t));
+ // GetWindowTextW(m_hwnd, result, length);
+ // return _wtoi(result);
+ return 0;
+}
+
+void CCtrlBase::GetCaretPos(CContextMenuPos &pos) const
+{
+ pos.pCtrl = this;
+ pos.iCurr = -1;
+
+ // if (pos.pt.x == 0 && pos.pt.y == 0)
+ // GetCursorPos(&pos.pt);
+}
+
+LRESULT CCtrlBase::CustomWndProc(UINT, WPARAM, LPARAM)
+{
+ return FALSE;
+}
+
+void CCtrlBase::Subclass()
+{
+ // mir_subclassWindow(m_hwnd, GlobalSubclassWndProc);
+
+ mir_cslock lck(csCtrl);
+ arControls.insert(this);
+}
+
+void CCtrlBase::Unsubclass()
+{
+ // mir_unsubclassWindow(m_hwnd, GlobalSubclassWndProc);
+}
diff --git a/src/mir_core/src/Linux/CCtrlButton.cpp b/src/mir_core/src/Linux/CCtrlButton.cpp
index e8c107b888..da569730c2 100644
--- a/src/mir_core/src/Linux/CCtrlButton.cpp
+++ b/src/mir_core/src/Linux/CCtrlButton.cpp
@@ -1,55 +1,55 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlButton
-
-CCtrlButton::CCtrlButton(CDlgBase* wnd, int idCtrl)
- : CCtrlBase(wnd, idCtrl)
-{}
-
-BOOL CCtrlButton::OnCommand(MWindow, uint16_t, uint16_t idCode)
-{
- // if (idCode == BN_CLICKED)
- // OnClick(this);
- return FALSE;
-}
-
-void CCtrlButton::Click()
-{
- // if (Enabled())
- // ::SendMessage(m_parentWnd->GetHwnd(), WM_COMMAND, MAKELONG(m_idCtrl, BN_CLICKED), 0);
-}
-
-bool CCtrlButton::IsPushed() const
-{
- // return ::SendMessage(m_hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED;
- return false;
-}
-
-void CCtrlButton::Push(bool bPushed)
-{
- // if (Enabled())
- // ::SendMessage(m_hwnd, BM_SETCHECK, (bPushed) ? BST_CHECKED : BST_UNCHECKED, 0);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlButton
+
+CCtrlButton::CCtrlButton(CDlgBase* wnd, int idCtrl)
+ : CCtrlBase(wnd, idCtrl)
+{}
+
+BOOL CCtrlButton::OnCommand(MWindow, uint16_t, uint16_t idCode)
+{
+ // if (idCode == BN_CLICKED)
+ // OnClick(this);
+ return FALSE;
+}
+
+void CCtrlButton::Click()
+{
+ // if (Enabled())
+ // ::SendMessage(m_parentWnd->GetHwnd(), WM_COMMAND, MAKELONG(m_idCtrl, BN_CLICKED), 0);
+}
+
+bool CCtrlButton::IsPushed() const
+{
+ // return ::SendMessage(m_hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED;
+ return false;
+}
+
+void CCtrlButton::Push(bool bPushed)
+{
+ // if (Enabled())
+ // ::SendMessage(m_hwnd, BM_SETCHECK, (bPushed) ? BST_CHECKED : BST_UNCHECKED, 0);
+}
diff --git a/src/mir_core/src/Linux/CCtrlCheck.cpp b/src/mir_core/src/Linux/CCtrlCheck.cpp
index 7c821f0329..112db0b66a 100644
--- a/src/mir_core/src/Linux/CCtrlCheck.cpp
+++ b/src/mir_core/src/Linux/CCtrlCheck.cpp
@@ -1,70 +1,70 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlCheck class
-
-CCtrlCheck::CCtrlCheck(CDlgBase *dlg, int ctrlId)
- : CCtrlData(dlg, ctrlId)
-{
- m_bNotifiable = true;
-}
-
-BOOL CCtrlCheck::OnCommand(MWindow, uint16_t, uint16_t)
-{
- NotifyChange();
- return TRUE;
-}
-
-bool CCtrlCheck::OnApply()
-{
- CSuper::OnApply();
-
- if (m_dbLink != nullptr)
- SaveInt(GetState());
- return true;
-}
-
-void CCtrlCheck::OnReset()
-{
- if (m_dbLink != nullptr)
- SetState(LoadInt());
-}
-
-int CCtrlCheck::GetState() const
-{
- // return ::SendMessage(m_hwnd, BM_GETCHECK, 0, 0);
- return false;
-}
-
-void CCtrlCheck::SetState(int state)
-{
- // ::SendMessage(m_hwnd, BM_SETCHECK, state, 0);
-}
-
-bool CCtrlCheck::IsChecked()
-{
- // return GetState() == BST_CHECKED;
- return false;
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlCheck class
+
+CCtrlCheck::CCtrlCheck(CDlgBase *dlg, int ctrlId)
+ : CCtrlData(dlg, ctrlId)
+{
+ m_bNotifiable = true;
+}
+
+BOOL CCtrlCheck::OnCommand(MWindow, uint16_t, uint16_t)
+{
+ NotifyChange();
+ return TRUE;
+}
+
+bool CCtrlCheck::OnApply()
+{
+ CSuper::OnApply();
+
+ if (m_dbLink != nullptr)
+ SaveInt(GetState());
+ return true;
+}
+
+void CCtrlCheck::OnReset()
+{
+ if (m_dbLink != nullptr)
+ SetState(LoadInt());
+}
+
+int CCtrlCheck::GetState() const
+{
+ // return ::SendMessage(m_hwnd, BM_GETCHECK, 0, 0);
+ return false;
+}
+
+void CCtrlCheck::SetState(int state)
+{
+ // ::SendMessage(m_hwnd, BM_SETCHECK, state, 0);
+}
+
+bool CCtrlCheck::IsChecked()
+{
+ // return GetState() == BST_CHECKED;
+ return false;
+}
diff --git a/src/mir_core/src/Linux/CCtrlClc.cpp b/src/mir_core/src/Linux/CCtrlClc.cpp
index cf4f05cda6..57f5607ef2 100644
--- a/src/mir_core/src/Linux/CCtrlClc.cpp
+++ b/src/mir_core/src/Linux/CCtrlClc.cpp
@@ -1,207 +1,207 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlClc
-
-CCtrlClc::CCtrlClc(CDlgBase *dlg, int ctrlId)
- : CCtrlBase(dlg, ctrlId)
-{}
-
-BOOL CCtrlClc::OnNotify(int, NMHDR *pnmh)
-{
- TEventInfo evt = { this, (NMCLISTCONTROL *)pnmh };
- switch (pnmh->code) {
- case CLN_EXPANDED: OnExpanded(&evt); break;
- case CLN_LISTREBUILT: OnListRebuilt(&evt); break;
- case CLN_ITEMCHECKED: OnItemChecked(&evt); break;
- case CLN_DRAGGING: OnDragging(&evt); break;
- case CLN_DROPPED: OnDropped(&evt); break;
- case CLN_LISTSIZECHANGE: OnListSizeChange(&evt); break;
- case CLN_OPTIONSCHANGED: OnOptionsChanged(&evt); break;
- case CLN_DRAGSTOP: OnDragStop(&evt); break;
- case CLN_NEWCONTACT: OnNewContact(&evt); break;
- case CLN_CONTACTMOVED: OnContactMoved(&evt); break;
- case CLN_CHECKCHANGED: OnCheckChanged(&evt); break;
- case NM_CLICK: OnClick(&evt); break;
- }
- return FALSE;
-}
-
-void CCtrlClc::AddContact(MCONTACT hContact)
-{ SendMessage(m_hwnd, CLM_ADDCONTACT, hContact, 0);
-}
-
-void CCtrlClc::AddGroup(HANDLE hGroup)
-{ SendMessage(m_hwnd, CLM_ADDGROUP, (WPARAM)hGroup, 0);
-}
-
-void CCtrlClc::AutoRebuild()
-{ SendMessage(m_hwnd, CLM_AUTOREBUILD, 0, 0);
-}
-
-void CCtrlClc::DeleteItem(HANDLE hItem)
-{ SendMessage(m_hwnd, CLM_DELETEITEM, (WPARAM)hItem, 0);
-}
-
-void CCtrlClc::EditLabel(HANDLE hItem)
-{ SendMessage(m_hwnd, CLM_EDITLABEL, (WPARAM)hItem, 0);
-}
-
-void CCtrlClc::EndEditLabel(bool save)
-{ SendMessage(m_hwnd, CLM_ENDEDITLABELNOW, save ? 0 : 1, 0);
-}
-
-void CCtrlClc::EnsureVisible(HANDLE hItem, bool partialOk)
-{ SendMessage(m_hwnd, CLM_ENSUREVISIBLE, (WPARAM)hItem, partialOk ? TRUE : FALSE);
-}
-
-void CCtrlClc::Expand(HANDLE hItem, uint32_t flags)
-{ SendMessage(m_hwnd, CLM_EXPAND, (WPARAM)hItem, flags);
-}
-
-HANDLE CCtrlClc::FindContact(MCONTACT hContact)
-{ return (HANDLE)SendMessage(m_hwnd, CLM_FINDCONTACT, hContact, 0);
-}
-
-HANDLE CCtrlClc::FindGroup(MGROUP hGroup)
-{ return (HANDLE)SendMessage(m_hwnd, CLM_FINDGROUP, hGroup, 0);
-}
-
-COLORREF CCtrlClc::GetBkColor() const
-{ return (COLORREF)SendMessage(m_hwnd, CLM_GETBKCOLOR, 0, 0);
-}
-
-bool CCtrlClc::GetCheck(HANDLE hItem) const
-{ return SendMessage(m_hwnd, CLM_GETCHECKMARK, (WPARAM)hItem, 0) ? true : false;
-}
-
-int CCtrlClc::GetCount() const
-{ return SendMessage(m_hwnd, CLM_GETCOUNT, 0, 0);
-}
-
-HWND CCtrlClc::GetEditControl() const
-{ return (HWND)SendMessage(m_hwnd, CLM_GETEDITCONTROL, 0, 0);
-}
-
-uint32_t CCtrlClc::GetExpand(HANDLE hItem) const
-{ return SendMessage(m_hwnd, CLM_GETEXPAND, (WPARAM)hItem, 0);
-}
-
-int CCtrlClc::GetExtraColumns() const
-{ return SendMessage(m_hwnd, CLM_GETEXTRACOLUMNS, 0, 0);
-}
-
-uint8_t CCtrlClc::GetExtraImage(HANDLE hItem, int iColumn) const
-{
- return (uint8_t)(SendMessage(m_hwnd, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, 0)) & 0xFFFF);
-}
-
-HIMAGELIST CCtrlClc::GetExtraImageList() const
-{ return (HIMAGELIST)SendMessage(m_hwnd, CLM_GETEXTRAIMAGELIST, 0, 0);
-}
-
-HFONT CCtrlClc::GetFont(int iFontId) const
-{ return (HFONT)SendMessage(m_hwnd, CLM_GETFONT, (WPARAM)iFontId, 0);
-}
-
-HANDLE CCtrlClc::GetSelection() const
-{ return (HANDLE)SendMessage(m_hwnd, CLM_GETSELECTION, 0, 0);
-}
-
-HANDLE CCtrlClc::HitTest(int x, int y, uint32_t *hitTest) const
-{ return (HANDLE)SendMessage(m_hwnd, CLM_HITTEST, (WPARAM)hitTest, MAKELPARAM(x,y));
-}
-
-void CCtrlClc::SelectItem(HANDLE hItem)
-{ SendMessage(m_hwnd, CLM_SELECTITEM, (WPARAM)hItem, 0);
-}
-
-void CCtrlClc::SetBkColor(COLORREF clBack)
-{ SendMessage(m_hwnd, CLM_SETBKCOLOR, (WPARAM)clBack, 0);
-}
-
-void CCtrlClc::SetCheck(HANDLE hItem, bool check)
-{ SendMessage(m_hwnd, CLM_SETCHECKMARK, (WPARAM)hItem, check ? 1 : 0);
-}
-
-void CCtrlClc::SetExtraColumns(int iColumns)
-{ SendMessage(m_hwnd, CLM_SETEXTRACOLUMNS, (WPARAM)iColumns, 0);
-}
-
-void CCtrlClc::SetExtraImage(HANDLE hItem, int iColumn, int iImage)
-{ SendMessage(m_hwnd, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, iImage));
-}
-
-void CCtrlClc::SetExtraImageList(HIMAGELIST hImgList)
-{ SendMessage(m_hwnd, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hImgList);
-}
-
-void CCtrlClc::SetFont(int iFontId, HANDLE hFont, bool bRedraw)
-{ SendMessage(m_hwnd, CLM_SETFONT, (WPARAM)hFont, MAKELPARAM(bRedraw ? 1 : 0, iFontId));
-}
-
-void CCtrlClc::SetItemText(HANDLE hItem, char *szText)
-{ SendMessage(m_hwnd, CLM_SETITEMTEXT, (WPARAM)hItem, (LPARAM)szText);
-}
-
-void CCtrlClc::SetHideEmptyGroups(bool state)
-{ SendMessage(m_hwnd, CLM_SETHIDEEMPTYGROUPS, state ? 1 : 0, 0);
-}
-
-bool CCtrlClc::GetHideOfflineRoot() const
-{ return SendMessage(m_hwnd, CLM_GETHIDEOFFLINEROOT, 0, 0) ? true : false;
-}
-
-void CCtrlClc::SetHideOfflineRoot(bool state)
-{ SendMessage(m_hwnd, CLM_SETHIDEOFFLINEROOT, state ? 1 : 0, 9);
-}
-
-void CCtrlClc::SetUseGroups(bool state)
-{ SendMessage(m_hwnd, CLM_SETUSEGROUPS, state ? 1 : 0, 0);
-}
-
-void CCtrlClc::SetOfflineModes(uint32_t modes)
-{ SendMessage(m_hwnd, CLM_SETOFFLINEMODES, modes, 0);
-}
-
-uint32_t CCtrlClc::GetExStyle() const
-{ return SendMessage(m_hwnd, CLM_GETEXSTYLE, 0, 0);
-}
-
-void CCtrlClc::SetExStyle(uint32_t exStyle)
-{ SendMessage(m_hwnd, CLM_SETEXSTYLE, (WPARAM)exStyle, 0);
-}
-
-HANDLE CCtrlClc::AddInfoItem(CLCINFOITEM *cii)
-{ return (HANDLE)SendMessage(m_hwnd, CLM_ADDINFOITEM, 0, (LPARAM)cii);
-}
-
-int CCtrlClc::GetItemType(HANDLE hItem) const
-{ return SendMessage(m_hwnd, CLM_GETITEMTYPE, (WPARAM)hItem, 0);
-}
-
-HANDLE CCtrlClc::GetNextItem(HANDLE hItem, uint32_t flags) const
-{ return (HANDLE)SendMessage(m_hwnd, CLM_GETNEXTITEM, (WPARAM)flags, (LPARAM)hItem);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlClc
+
+CCtrlClc::CCtrlClc(CDlgBase *dlg, int ctrlId)
+ : CCtrlBase(dlg, ctrlId)
+{}
+
+BOOL CCtrlClc::OnNotify(int, NMHDR *pnmh)
+{
+ TEventInfo evt = { this, (NMCLISTCONTROL *)pnmh };
+ switch (pnmh->code) {
+ case CLN_EXPANDED: OnExpanded(&evt); break;
+ case CLN_LISTREBUILT: OnListRebuilt(&evt); break;
+ case CLN_ITEMCHECKED: OnItemChecked(&evt); break;
+ case CLN_DRAGGING: OnDragging(&evt); break;
+ case CLN_DROPPED: OnDropped(&evt); break;
+ case CLN_LISTSIZECHANGE: OnListSizeChange(&evt); break;
+ case CLN_OPTIONSCHANGED: OnOptionsChanged(&evt); break;
+ case CLN_DRAGSTOP: OnDragStop(&evt); break;
+ case CLN_NEWCONTACT: OnNewContact(&evt); break;
+ case CLN_CONTACTMOVED: OnContactMoved(&evt); break;
+ case CLN_CHECKCHANGED: OnCheckChanged(&evt); break;
+ case NM_CLICK: OnClick(&evt); break;
+ }
+ return FALSE;
+}
+
+void CCtrlClc::AddContact(MCONTACT hContact)
+{ SendMessage(m_hwnd, CLM_ADDCONTACT, hContact, 0);
+}
+
+void CCtrlClc::AddGroup(HANDLE hGroup)
+{ SendMessage(m_hwnd, CLM_ADDGROUP, (WPARAM)hGroup, 0);
+}
+
+void CCtrlClc::AutoRebuild()
+{ SendMessage(m_hwnd, CLM_AUTOREBUILD, 0, 0);
+}
+
+void CCtrlClc::DeleteItem(HANDLE hItem)
+{ SendMessage(m_hwnd, CLM_DELETEITEM, (WPARAM)hItem, 0);
+}
+
+void CCtrlClc::EditLabel(HANDLE hItem)
+{ SendMessage(m_hwnd, CLM_EDITLABEL, (WPARAM)hItem, 0);
+}
+
+void CCtrlClc::EndEditLabel(bool save)
+{ SendMessage(m_hwnd, CLM_ENDEDITLABELNOW, save ? 0 : 1, 0);
+}
+
+void CCtrlClc::EnsureVisible(HANDLE hItem, bool partialOk)
+{ SendMessage(m_hwnd, CLM_ENSUREVISIBLE, (WPARAM)hItem, partialOk ? TRUE : FALSE);
+}
+
+void CCtrlClc::Expand(HANDLE hItem, uint32_t flags)
+{ SendMessage(m_hwnd, CLM_EXPAND, (WPARAM)hItem, flags);
+}
+
+HANDLE CCtrlClc::FindContact(MCONTACT hContact)
+{ return (HANDLE)SendMessage(m_hwnd, CLM_FINDCONTACT, hContact, 0);
+}
+
+HANDLE CCtrlClc::FindGroup(MGROUP hGroup)
+{ return (HANDLE)SendMessage(m_hwnd, CLM_FINDGROUP, hGroup, 0);
+}
+
+COLORREF CCtrlClc::GetBkColor() const
+{ return (COLORREF)SendMessage(m_hwnd, CLM_GETBKCOLOR, 0, 0);
+}
+
+bool CCtrlClc::GetCheck(HANDLE hItem) const
+{ return SendMessage(m_hwnd, CLM_GETCHECKMARK, (WPARAM)hItem, 0) ? true : false;
+}
+
+int CCtrlClc::GetCount() const
+{ return SendMessage(m_hwnd, CLM_GETCOUNT, 0, 0);
+}
+
+HWND CCtrlClc::GetEditControl() const
+{ return (HWND)SendMessage(m_hwnd, CLM_GETEDITCONTROL, 0, 0);
+}
+
+uint32_t CCtrlClc::GetExpand(HANDLE hItem) const
+{ return SendMessage(m_hwnd, CLM_GETEXPAND, (WPARAM)hItem, 0);
+}
+
+int CCtrlClc::GetExtraColumns() const
+{ return SendMessage(m_hwnd, CLM_GETEXTRACOLUMNS, 0, 0);
+}
+
+uint8_t CCtrlClc::GetExtraImage(HANDLE hItem, int iColumn) const
+{
+ return (uint8_t)(SendMessage(m_hwnd, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, 0)) & 0xFFFF);
+}
+
+HIMAGELIST CCtrlClc::GetExtraImageList() const
+{ return (HIMAGELIST)SendMessage(m_hwnd, CLM_GETEXTRAIMAGELIST, 0, 0);
+}
+
+HFONT CCtrlClc::GetFont(int iFontId) const
+{ return (HFONT)SendMessage(m_hwnd, CLM_GETFONT, (WPARAM)iFontId, 0);
+}
+
+HANDLE CCtrlClc::GetSelection() const
+{ return (HANDLE)SendMessage(m_hwnd, CLM_GETSELECTION, 0, 0);
+}
+
+HANDLE CCtrlClc::HitTest(int x, int y, uint32_t *hitTest) const
+{ return (HANDLE)SendMessage(m_hwnd, CLM_HITTEST, (WPARAM)hitTest, MAKELPARAM(x,y));
+}
+
+void CCtrlClc::SelectItem(HANDLE hItem)
+{ SendMessage(m_hwnd, CLM_SELECTITEM, (WPARAM)hItem, 0);
+}
+
+void CCtrlClc::SetBkColor(COLORREF clBack)
+{ SendMessage(m_hwnd, CLM_SETBKCOLOR, (WPARAM)clBack, 0);
+}
+
+void CCtrlClc::SetCheck(HANDLE hItem, bool check)
+{ SendMessage(m_hwnd, CLM_SETCHECKMARK, (WPARAM)hItem, check ? 1 : 0);
+}
+
+void CCtrlClc::SetExtraColumns(int iColumns)
+{ SendMessage(m_hwnd, CLM_SETEXTRACOLUMNS, (WPARAM)iColumns, 0);
+}
+
+void CCtrlClc::SetExtraImage(HANDLE hItem, int iColumn, int iImage)
+{ SendMessage(m_hwnd, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, iImage));
+}
+
+void CCtrlClc::SetExtraImageList(HIMAGELIST hImgList)
+{ SendMessage(m_hwnd, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hImgList);
+}
+
+void CCtrlClc::SetFont(int iFontId, HANDLE hFont, bool bRedraw)
+{ SendMessage(m_hwnd, CLM_SETFONT, (WPARAM)hFont, MAKELPARAM(bRedraw ? 1 : 0, iFontId));
+}
+
+void CCtrlClc::SetItemText(HANDLE hItem, char *szText)
+{ SendMessage(m_hwnd, CLM_SETITEMTEXT, (WPARAM)hItem, (LPARAM)szText);
+}
+
+void CCtrlClc::SetHideEmptyGroups(bool state)
+{ SendMessage(m_hwnd, CLM_SETHIDEEMPTYGROUPS, state ? 1 : 0, 0);
+}
+
+bool CCtrlClc::GetHideOfflineRoot() const
+{ return SendMessage(m_hwnd, CLM_GETHIDEOFFLINEROOT, 0, 0) ? true : false;
+}
+
+void CCtrlClc::SetHideOfflineRoot(bool state)
+{ SendMessage(m_hwnd, CLM_SETHIDEOFFLINEROOT, state ? 1 : 0, 9);
+}
+
+void CCtrlClc::SetUseGroups(bool state)
+{ SendMessage(m_hwnd, CLM_SETUSEGROUPS, state ? 1 : 0, 0);
+}
+
+void CCtrlClc::SetOfflineModes(uint32_t modes)
+{ SendMessage(m_hwnd, CLM_SETOFFLINEMODES, modes, 0);
+}
+
+uint32_t CCtrlClc::GetExStyle() const
+{ return SendMessage(m_hwnd, CLM_GETEXSTYLE, 0, 0);
+}
+
+void CCtrlClc::SetExStyle(uint32_t exStyle)
+{ SendMessage(m_hwnd, CLM_SETEXSTYLE, (WPARAM)exStyle, 0);
+}
+
+HANDLE CCtrlClc::AddInfoItem(CLCINFOITEM *cii)
+{ return (HANDLE)SendMessage(m_hwnd, CLM_ADDINFOITEM, 0, (LPARAM)cii);
+}
+
+int CCtrlClc::GetItemType(HANDLE hItem) const
+{ return SendMessage(m_hwnd, CLM_GETITEMTYPE, (WPARAM)hItem, 0);
+}
+
+HANDLE CCtrlClc::GetNextItem(HANDLE hItem, uint32_t flags) const
+{ return (HANDLE)SendMessage(m_hwnd, CLM_GETNEXTITEM, (WPARAM)flags, (LPARAM)hItem);
+}
diff --git a/src/mir_core/src/Linux/CCtrlColor.cpp b/src/mir_core/src/Linux/CCtrlColor.cpp
index 97f5e48e02..b61fb5760a 100644
--- a/src/mir_core/src/Linux/CCtrlColor.cpp
+++ b/src/mir_core/src/Linux/CCtrlColor.cpp
@@ -1,61 +1,61 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlColor class
-
-CCtrlColor::CCtrlColor(CDlgBase *dlg, int ctrlId) :
- CCtrlData(dlg, ctrlId)
-{}
-
-BOOL CCtrlColor::OnCommand(HWND, uint16_t, uint16_t)
-{
- NotifyChange();
- return TRUE;
-}
-
-bool CCtrlColor::OnApply()
-{
- CSuper::OnApply();
-
- if (m_dbLink != nullptr)
- SaveInt(GetColor());
- return true;
-}
-
-void CCtrlColor::OnReset()
-{
- if (m_dbLink != nullptr)
- SetColor(LoadInt());
-}
-
-uint32_t CCtrlColor::GetColor()
-{
- return ::SendMessage(m_hwnd, CPM_GETCOLOUR, 0, 0);
-}
-
-void CCtrlColor::SetColor(uint32_t dwValue)
-{
- ::SendMessage(m_hwnd, CPM_SETCOLOUR, 0, dwValue);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlColor class
+
+CCtrlColor::CCtrlColor(CDlgBase *dlg, int ctrlId) :
+ CCtrlData(dlg, ctrlId)
+{}
+
+BOOL CCtrlColor::OnCommand(HWND, uint16_t, uint16_t)
+{
+ NotifyChange();
+ return TRUE;
+}
+
+bool CCtrlColor::OnApply()
+{
+ CSuper::OnApply();
+
+ if (m_dbLink != nullptr)
+ SaveInt(GetColor());
+ return true;
+}
+
+void CCtrlColor::OnReset()
+{
+ if (m_dbLink != nullptr)
+ SetColor(LoadInt());
+}
+
+uint32_t CCtrlColor::GetColor()
+{
+ return ::SendMessage(m_hwnd, CPM_GETCOLOUR, 0, 0);
+}
+
+void CCtrlColor::SetColor(uint32_t dwValue)
+{
+ ::SendMessage(m_hwnd, CPM_SETCOLOUR, 0, dwValue);
+}
diff --git a/src/mir_core/src/Linux/CCtrlCombo.cpp b/src/mir_core/src/Linux/CCtrlCombo.cpp
index 063588e39e..52a85f1115 100644
--- a/src/mir_core/src/Linux/CCtrlCombo.cpp
+++ b/src/mir_core/src/Linux/CCtrlCombo.cpp
@@ -1,169 +1,169 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlCombo class
-
-CCtrlCombo::CCtrlCombo(CDlgBase *dlg, int ctrlId)
- : CCtrlData(dlg, ctrlId)
-{}
-
-BOOL CCtrlCombo::OnCommand(MWindow, uint16_t, uint16_t idCode)
-{
- switch (idCode) {
- // case CBN_CLOSEUP: OnCloseup(this); break;
- // case CBN_DROPDOWN: OnDropdown(this); break;
- // case CBN_SELCHANGE: OnSelChanged(this); break;
- // case CBN_KILLFOCUS: OnKillFocus(this); break;
-
- // case CBN_EDITCHANGE:
- // case CBN_EDITUPDATE:
- // case CBN_SELENDOK:
- // NotifyChange();
- break;
- }
- return TRUE;
-}
-
-void CCtrlCombo::OnInit()
-{
- CSuper::OnInit();
- OnReset();
-}
-
-bool CCtrlCombo::OnApply()
-{
- CSuper::OnApply();
-
- if (GetDataType() == DBVT_WCHAR) {
- // int len = GetWindowTextLength(m_hwnd) + 1;
- // wchar_t *buf = (wchar_t *)_alloca(sizeof(wchar_t) * len);
- // GetWindowText(m_hwnd, buf, len);
- // SaveText(buf);
- }
- else if (GetDataType() != DBVT_DELETED) {
- SaveInt(GetInt());
- }
- return true;
-}
-
-void CCtrlCombo::OnReset()
-{
- if (GetDataType() == DBVT_WCHAR)
- SetText(LoadText());
- else if (GetDataType() != DBVT_DELETED)
- SetInt(LoadInt());
-}
-
-LPARAM CCtrlCombo::GetCurData() const
-{
- return GetItemData(GetCurSel());
-}
-
-// selects line with userdata passed
-int CCtrlCombo::SelectData(LPARAM data)
-{
- int ret = -1, nCount = GetCount();
-
- for (int i = 0; i < nCount; i++)
- if (GetItemData(i) == data) {
- ret = i;
- break;
- }
-
- return SetCurSel(ret);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Windows API
-
-int CCtrlCombo::AddString(const wchar_t *text, LPARAM data)
-{
- return -1;
-}
-
-int CCtrlCombo::AddStringA(const char *text, LPARAM data)
-{
- return -1;
-}
-
-void CCtrlCombo::DeleteString(int index)
-{
-}
-
-int CCtrlCombo::FindString(const wchar_t *str, int index, bool exact)
-{ return 0;
-}
-
-int CCtrlCombo::FindStringA(const char *str, int index, bool exact)
-{ return 0;
-}
-
-int CCtrlCombo::GetCount() const
-{ return 0;
-}
-
-int CCtrlCombo::GetCurSel() const
-{ return 0;
-}
-
-bool CCtrlCombo::GetDroppedState() const
-{ return 0;
-}
-
-LPARAM CCtrlCombo::GetItemData(int index) const
-{ return 0;
-}
-
-wchar_t* CCtrlCombo::GetItemText(int index) const
-{ return 0;
-}
-
-wchar_t* CCtrlCombo::GetItemText(int index, wchar_t *buf, int size) const
-{ return 0;
-}
-
-int CCtrlCombo::InsertString(const wchar_t *text, int pos, LPARAM data)
-{ return 0;
-}
-
-void CCtrlCombo::ResetContent()
-{
-}
-
-int CCtrlCombo::SelectString(const wchar_t *str)
-{ return 0;
-}
-
-int CCtrlCombo::SetCurSel(int index)
-{ return 0;
-}
-
-void CCtrlCombo::SetItemData(int index, LPARAM data)
-{
-}
-
-void CCtrlCombo::ShowDropdown(bool show)
-{
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlCombo class
+
+CCtrlCombo::CCtrlCombo(CDlgBase *dlg, int ctrlId)
+ : CCtrlData(dlg, ctrlId)
+{}
+
+BOOL CCtrlCombo::OnCommand(MWindow, uint16_t, uint16_t idCode)
+{
+ switch (idCode) {
+ // case CBN_CLOSEUP: OnCloseup(this); break;
+ // case CBN_DROPDOWN: OnDropdown(this); break;
+ // case CBN_SELCHANGE: OnSelChanged(this); break;
+ // case CBN_KILLFOCUS: OnKillFocus(this); break;
+
+ // case CBN_EDITCHANGE:
+ // case CBN_EDITUPDATE:
+ // case CBN_SELENDOK:
+ // NotifyChange();
+ break;
+ }
+ return TRUE;
+}
+
+void CCtrlCombo::OnInit()
+{
+ CSuper::OnInit();
+ OnReset();
+}
+
+bool CCtrlCombo::OnApply()
+{
+ CSuper::OnApply();
+
+ if (GetDataType() == DBVT_WCHAR) {
+ // int len = GetWindowTextLength(m_hwnd) + 1;
+ // wchar_t *buf = (wchar_t *)_alloca(sizeof(wchar_t) * len);
+ // GetWindowText(m_hwnd, buf, len);
+ // SaveText(buf);
+ }
+ else if (GetDataType() != DBVT_DELETED) {
+ SaveInt(GetInt());
+ }
+ return true;
+}
+
+void CCtrlCombo::OnReset()
+{
+ if (GetDataType() == DBVT_WCHAR)
+ SetText(LoadText());
+ else if (GetDataType() != DBVT_DELETED)
+ SetInt(LoadInt());
+}
+
+LPARAM CCtrlCombo::GetCurData() const
+{
+ return GetItemData(GetCurSel());
+}
+
+// selects line with userdata passed
+int CCtrlCombo::SelectData(LPARAM data)
+{
+ int ret = -1, nCount = GetCount();
+
+ for (int i = 0; i < nCount; i++)
+ if (GetItemData(i) == data) {
+ ret = i;
+ break;
+ }
+
+ return SetCurSel(ret);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Windows API
+
+int CCtrlCombo::AddString(const wchar_t *text, LPARAM data)
+{
+ return -1;
+}
+
+int CCtrlCombo::AddStringA(const char *text, LPARAM data)
+{
+ return -1;
+}
+
+void CCtrlCombo::DeleteString(int index)
+{
+}
+
+int CCtrlCombo::FindString(const wchar_t *str, int index, bool exact)
+{ return 0;
+}
+
+int CCtrlCombo::FindStringA(const char *str, int index, bool exact)
+{ return 0;
+}
+
+int CCtrlCombo::GetCount() const
+{ return 0;
+}
+
+int CCtrlCombo::GetCurSel() const
+{ return 0;
+}
+
+bool CCtrlCombo::GetDroppedState() const
+{ return 0;
+}
+
+LPARAM CCtrlCombo::GetItemData(int index) const
+{ return 0;
+}
+
+wchar_t* CCtrlCombo::GetItemText(int index) const
+{ return 0;
+}
+
+wchar_t* CCtrlCombo::GetItemText(int index, wchar_t *buf, int size) const
+{ return 0;
+}
+
+int CCtrlCombo::InsertString(const wchar_t *text, int pos, LPARAM data)
+{ return 0;
+}
+
+void CCtrlCombo::ResetContent()
+{
+}
+
+int CCtrlCombo::SelectString(const wchar_t *str)
+{ return 0;
+}
+
+int CCtrlCombo::SetCurSel(int index)
+{ return 0;
+}
+
+void CCtrlCombo::SetItemData(int index, LPARAM data)
+{
+}
+
+void CCtrlCombo::ShowDropdown(bool show)
+{
+}
diff --git a/src/mir_core/src/Linux/CCtrlData.cpp b/src/mir_core/src/Linux/CCtrlData.cpp
index fab5ca0409..2a60d9d31a 100644
--- a/src/mir_core/src/Linux/CCtrlData.cpp
+++ b/src/mir_core/src/Linux/CCtrlData.cpp
@@ -1,52 +1,52 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlData class
-
-CCtrlData::CCtrlData(CDlgBase *wnd, int idCtrl)
- : CCtrlBase(wnd, idCtrl),
- m_dbLink(nullptr)
-{}
-
-CCtrlData::~CCtrlData()
-{
- delete m_dbLink;
-}
-
-void CCtrlData::OnInit()
-{
- CCtrlBase::OnInit();
- OnReset();
-}
-
-void CCtrlData::CreateDbLink(const char* szModuleName, const char* szSetting, uint8_t type, uint32_t iValue)
-{
- m_dbLink = new CDbLink(szModuleName, szSetting, type, iValue);
-}
-
-void CCtrlData::CreateDbLink(const char* szModuleName, const char* szSetting, wchar_t* szValue)
-{
- m_dbLink = new CDbLink(szModuleName, szSetting, DBVT_WCHAR, szValue);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlData class
+
+CCtrlData::CCtrlData(CDlgBase *wnd, int idCtrl)
+ : CCtrlBase(wnd, idCtrl),
+ m_dbLink(nullptr)
+{}
+
+CCtrlData::~CCtrlData()
+{
+ delete m_dbLink;
+}
+
+void CCtrlData::OnInit()
+{
+ CCtrlBase::OnInit();
+ OnReset();
+}
+
+void CCtrlData::CreateDbLink(const char* szModuleName, const char* szSetting, uint8_t type, uint32_t iValue)
+{
+ m_dbLink = new CDbLink(szModuleName, szSetting, type, iValue);
+}
+
+void CCtrlData::CreateDbLink(const char* szModuleName, const char* szSetting, wchar_t* szValue)
+{
+ m_dbLink = new CDbLink(szModuleName, szSetting, DBVT_WCHAR, szValue);
+}
diff --git a/src/mir_core/src/Linux/CCtrlEdit.cpp b/src/mir_core/src/Linux/CCtrlEdit.cpp
index 7f1ac14cc2..42a9dd6327 100644
--- a/src/mir_core/src/Linux/CCtrlEdit.cpp
+++ b/src/mir_core/src/Linux/CCtrlEdit.cpp
@@ -1,68 +1,68 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlEdit class
-
-CCtrlEdit::CCtrlEdit(CDlgBase *dlg, int ctrlId)
- : CCtrlData(dlg, ctrlId)
-{}
-
-BOOL CCtrlEdit::OnCommand(MWindow, uint16_t, uint16_t idCode)
-{
- // if (idCode == EN_CHANGE)
- // NotifyChange();
- return TRUE;
-}
-
-bool CCtrlEdit::OnApply()
-{
- CSuper::OnApply();
-
- if (GetDataType() == DBVT_WCHAR) {
- // int len = GetWindowTextLength(m_hwnd) + 1;
- // wchar_t *buf = (wchar_t *)_alloca(sizeof(wchar_t) * len);
- // GetWindowText(m_hwnd, buf, len);
- // SaveText(buf);
- }
- else if (GetDataType() != DBVT_DELETED) {
- SaveInt(GetInt());
- }
- return true;
-}
-
-void CCtrlEdit::OnReset()
-{
- // m_bSilent = (GetWindowLong(m_hwnd, GWL_STYLE) & ES_READONLY) != 0;
-
- if (GetDataType() == DBVT_WCHAR)
- SetText(LoadText());
- else if (GetDataType() != DBVT_DELETED)
- SetInt(LoadInt());
-}
-
-void CCtrlEdit::SetMaxLength(unsigned int len)
-{
- // SendMsg(EM_SETLIMITTEXT, len, 0);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlEdit class
+
+CCtrlEdit::CCtrlEdit(CDlgBase *dlg, int ctrlId)
+ : CCtrlData(dlg, ctrlId)
+{}
+
+BOOL CCtrlEdit::OnCommand(MWindow, uint16_t, uint16_t idCode)
+{
+ // if (idCode == EN_CHANGE)
+ // NotifyChange();
+ return TRUE;
+}
+
+bool CCtrlEdit::OnApply()
+{
+ CSuper::OnApply();
+
+ if (GetDataType() == DBVT_WCHAR) {
+ // int len = GetWindowTextLength(m_hwnd) + 1;
+ // wchar_t *buf = (wchar_t *)_alloca(sizeof(wchar_t) * len);
+ // GetWindowText(m_hwnd, buf, len);
+ // SaveText(buf);
+ }
+ else if (GetDataType() != DBVT_DELETED) {
+ SaveInt(GetInt());
+ }
+ return true;
+}
+
+void CCtrlEdit::OnReset()
+{
+ // m_bSilent = (GetWindowLong(m_hwnd, GWL_STYLE) & ES_READONLY) != 0;
+
+ if (GetDataType() == DBVT_WCHAR)
+ SetText(LoadText());
+ else if (GetDataType() != DBVT_DELETED)
+ SetInt(LoadInt());
+}
+
+void CCtrlEdit::SetMaxLength(unsigned int len)
+{
+ // SendMsg(EM_SETLIMITTEXT, len, 0);
+}
diff --git a/src/mir_core/src/Linux/CCtrlHyperlink.cpp b/src/mir_core/src/Linux/CCtrlHyperlink.cpp
index ca92d19dbc..0e0d93a689 100644
--- a/src/mir_core/src/Linux/CCtrlHyperlink.cpp
+++ b/src/mir_core/src/Linux/CCtrlHyperlink.cpp
@@ -1,54 +1,54 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlHyperlink
-
-CCtrlHyperlink::CCtrlHyperlink(CDlgBase* wnd, int idCtrl, const char* url)
- : CCtrlBase(wnd, idCtrl),
- m_url(url)
-{
- OnClick = Callback(this, &CCtrlHyperlink::Default_OnClick);
-}
-
-BOOL CCtrlHyperlink::OnCommand(HWND, uint16_t, uint16_t)
-{
- OnClick(this);
- return FALSE;
-}
-
-void CCtrlHyperlink::Default_OnClick(CCtrlHyperlink*)
-{
- ShellExecuteA(m_hwnd, "open", m_url, "", "", SW_SHOW);
-}
-
-void CCtrlHyperlink::SetUrl(const char *url)
-{
- m_url = url;
-}
-
-const char* CCtrlHyperlink::GetUrl()
-{
- return m_url;
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlHyperlink
+
+CCtrlHyperlink::CCtrlHyperlink(CDlgBase* wnd, int idCtrl, const char* url)
+ : CCtrlBase(wnd, idCtrl),
+ m_url(url)
+{
+ OnClick = Callback(this, &CCtrlHyperlink::Default_OnClick);
+}
+
+BOOL CCtrlHyperlink::OnCommand(HWND, uint16_t, uint16_t)
+{
+ OnClick(this);
+ return FALSE;
+}
+
+void CCtrlHyperlink::Default_OnClick(CCtrlHyperlink*)
+{
+ ShellExecuteA(m_hwnd, "open", m_url, "", "", SW_SHOW);
+}
+
+void CCtrlHyperlink::SetUrl(const char *url)
+{
+ m_url = url;
+}
+
+const char* CCtrlHyperlink::GetUrl()
+{
+ return m_url;
+}
diff --git a/src/mir_core/src/Linux/CCtrlLabel.cpp b/src/mir_core/src/Linux/CCtrlLabel.cpp
index 0c097c0655..ff05f3c8cf 100644
--- a/src/mir_core/src/Linux/CCtrlLabel.cpp
+++ b/src/mir_core/src/Linux/CCtrlLabel.cpp
@@ -1,30 +1,30 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlLabel
-
-CCtrlLabel::CCtrlLabel(CDlgBase* wnd, int idCtrl)
- : CCtrlBase(wnd, idCtrl)
-{}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlLabel
+
+CCtrlLabel::CCtrlLabel(CDlgBase* wnd, int idCtrl)
+ : CCtrlBase(wnd, idCtrl)
+{}
diff --git a/src/mir_core/src/Linux/CCtrlListBox.cpp b/src/mir_core/src/Linux/CCtrlListBox.cpp
index abaa31a786..6d9f58fc23 100644
--- a/src/mir_core/src/Linux/CCtrlListBox.cpp
+++ b/src/mir_core/src/Linux/CCtrlListBox.cpp
@@ -1,160 +1,160 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlListBox class
-
-CCtrlListBox::CCtrlListBox(CDlgBase *dlg, int ctrlId)
- : CCtrlBase(dlg, ctrlId)
-{}
-
-BOOL CCtrlListBox::OnCommand(HWND, uint16_t, uint16_t idCode)
-{
- switch (idCode) {
- case LBN_DBLCLK: OnDblClick(this); break;
- case LBN_SELCANCEL: OnSelCancel(this); break;
- case LBN_SELCHANGE: OnSelChange(this); break;
- }
- return TRUE;
-}
-
-void CCtrlListBox::GetCaretPos(CContextMenuPos &pos) const
-{
- pos.pCtrl = this;
- if (pos.pt.x == 0 && pos.pt.y == 0) {
- pos.iCurr = GetCurSel();
- if (pos.iCurr != -1) {
- RECT rc;
- GetItemRect(pos.iCurr, &rc);
- pos.pt.x = rc.left + 8;
- pos.pt.y = rc.top + 8;
- ClientToScreen(m_hwnd, &pos.pt);
- return;
- }
- }
-
- CSuper::GetCaretPos(pos);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-int CCtrlListBox::AddString(const wchar_t *text, LPARAM data)
-{
- int iItem = ListBox_AddString(m_hwnd, text);
- ListBox_SetItemData(m_hwnd, iItem, data);
- return iItem;
-}
-
-void CCtrlListBox::DeleteString(int index)
-{ ListBox_DeleteString(m_hwnd, index);
-}
-
-int CCtrlListBox::FindString(const wchar_t *str, int index, bool exact)
-{ return SendMessage(m_hwnd, exact?LB_FINDSTRINGEXACT:LB_FINDSTRING, index, (LPARAM)str);
-}
-
-int CCtrlListBox::GetCount() const
-{ return ListBox_GetCount(m_hwnd);
-}
-
-int CCtrlListBox::GetCurSel() const
-{ return ListBox_GetCurSel(m_hwnd);
-}
-
-LPARAM CCtrlListBox::GetItemData(int index) const
-{ return ListBox_GetItemData(m_hwnd, index);
-}
-
-int CCtrlListBox::GetItemRect(int index, RECT *pResult) const
-{ return ListBox_GetItemRect(m_hwnd, index, pResult);
-}
-
-wchar_t* CCtrlListBox::GetItemText(int index) const
-{
- wchar_t *result = (wchar_t *)mir_alloc(sizeof(wchar_t) * (SendMessage(m_hwnd, LB_GETTEXTLEN, index, 0) + 1));
- SendMessage(m_hwnd, LB_GETTEXT, index, (LPARAM)result);
- return result;
-}
-
-wchar_t* CCtrlListBox::GetItemText(int index, wchar_t *buf, int size) const
-{
- wchar_t *result = (wchar_t *)_alloca(sizeof(wchar_t) * (SendMessage(m_hwnd, LB_GETTEXTLEN, index, 0) + 1));
- SendMessage(m_hwnd, LB_GETTEXT, index, (LPARAM)result);
- mir_wstrncpy(buf, result, size);
- return buf;
-}
-
-bool CCtrlListBox::GetSel(int index) const
-{ return ListBox_GetSel(m_hwnd, index) ? true : false;
-}
-
-int CCtrlListBox::GetSelCount() const
-{ return ListBox_GetSelCount(m_hwnd);
-}
-
-int* CCtrlListBox::GetSelItems(int *items, int count) const
-{
- ListBox_GetSelItems(m_hwnd, count, items);
- return items;
-}
-
-int* CCtrlListBox::GetSelItems() const
-{
- int count = GetSelCount() + 1;
- int *result = (int *)mir_alloc(sizeof(int) * count);
- ListBox_GetSelItems(m_hwnd, count, result);
- result[count-1] = -1;
- return result;
-}
-
-int CCtrlListBox::InsertString(const wchar_t *text, int pos, LPARAM data)
-{
- int iItem = ListBox_InsertString(m_hwnd, pos, text);
- ListBox_SetItemData(m_hwnd, iItem, data);
- return iItem;
-}
-
-void CCtrlListBox::ResetContent()
-{ ListBox_ResetContent(m_hwnd);
-}
-
-int CCtrlListBox::SelectString(const wchar_t *str)
-{ return ListBox_SelectString(m_hwnd, 0, str);
-}
-
-int CCtrlListBox::SetCurSel(int index)
-{ return ListBox_SetCurSel(m_hwnd, index);
-}
-
-void CCtrlListBox::SetItemData(int index, LPARAM data)
-{ ListBox_SetItemData(m_hwnd, index, data);
-}
-
-void CCtrlListBox::SetItemHeight(int index, int iHeight)
-{ ListBox_SetItemHeight(m_hwnd, index, iHeight);
-}
-
-void CCtrlListBox::SetSel(int index, bool sel)
-{ ListBox_SetSel(m_hwnd, sel ? TRUE : FALSE, index);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlListBox class
+
+CCtrlListBox::CCtrlListBox(CDlgBase *dlg, int ctrlId)
+ : CCtrlBase(dlg, ctrlId)
+{}
+
+BOOL CCtrlListBox::OnCommand(HWND, uint16_t, uint16_t idCode)
+{
+ switch (idCode) {
+ case LBN_DBLCLK: OnDblClick(this); break;
+ case LBN_SELCANCEL: OnSelCancel(this); break;
+ case LBN_SELCHANGE: OnSelChange(this); break;
+ }
+ return TRUE;
+}
+
+void CCtrlListBox::GetCaretPos(CContextMenuPos &pos) const
+{
+ pos.pCtrl = this;
+ if (pos.pt.x == 0 && pos.pt.y == 0) {
+ pos.iCurr = GetCurSel();
+ if (pos.iCurr != -1) {
+ RECT rc;
+ GetItemRect(pos.iCurr, &rc);
+ pos.pt.x = rc.left + 8;
+ pos.pt.y = rc.top + 8;
+ ClientToScreen(m_hwnd, &pos.pt);
+ return;
+ }
+ }
+
+ CSuper::GetCaretPos(pos);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+int CCtrlListBox::AddString(const wchar_t *text, LPARAM data)
+{
+ int iItem = ListBox_AddString(m_hwnd, text);
+ ListBox_SetItemData(m_hwnd, iItem, data);
+ return iItem;
+}
+
+void CCtrlListBox::DeleteString(int index)
+{ ListBox_DeleteString(m_hwnd, index);
+}
+
+int CCtrlListBox::FindString(const wchar_t *str, int index, bool exact)
+{ return SendMessage(m_hwnd, exact?LB_FINDSTRINGEXACT:LB_FINDSTRING, index, (LPARAM)str);
+}
+
+int CCtrlListBox::GetCount() const
+{ return ListBox_GetCount(m_hwnd);
+}
+
+int CCtrlListBox::GetCurSel() const
+{ return ListBox_GetCurSel(m_hwnd);
+}
+
+LPARAM CCtrlListBox::GetItemData(int index) const
+{ return ListBox_GetItemData(m_hwnd, index);
+}
+
+int CCtrlListBox::GetItemRect(int index, RECT *pResult) const
+{ return ListBox_GetItemRect(m_hwnd, index, pResult);
+}
+
+wchar_t* CCtrlListBox::GetItemText(int index) const
+{
+ wchar_t *result = (wchar_t *)mir_alloc(sizeof(wchar_t) * (SendMessage(m_hwnd, LB_GETTEXTLEN, index, 0) + 1));
+ SendMessage(m_hwnd, LB_GETTEXT, index, (LPARAM)result);
+ return result;
+}
+
+wchar_t* CCtrlListBox::GetItemText(int index, wchar_t *buf, int size) const
+{
+ wchar_t *result = (wchar_t *)_alloca(sizeof(wchar_t) * (SendMessage(m_hwnd, LB_GETTEXTLEN, index, 0) + 1));
+ SendMessage(m_hwnd, LB_GETTEXT, index, (LPARAM)result);
+ mir_wstrncpy(buf, result, size);
+ return buf;
+}
+
+bool CCtrlListBox::GetSel(int index) const
+{ return ListBox_GetSel(m_hwnd, index) ? true : false;
+}
+
+int CCtrlListBox::GetSelCount() const
+{ return ListBox_GetSelCount(m_hwnd);
+}
+
+int* CCtrlListBox::GetSelItems(int *items, int count) const
+{
+ ListBox_GetSelItems(m_hwnd, count, items);
+ return items;
+}
+
+int* CCtrlListBox::GetSelItems() const
+{
+ int count = GetSelCount() + 1;
+ int *result = (int *)mir_alloc(sizeof(int) * count);
+ ListBox_GetSelItems(m_hwnd, count, result);
+ result[count-1] = -1;
+ return result;
+}
+
+int CCtrlListBox::InsertString(const wchar_t *text, int pos, LPARAM data)
+{
+ int iItem = ListBox_InsertString(m_hwnd, pos, text);
+ ListBox_SetItemData(m_hwnd, iItem, data);
+ return iItem;
+}
+
+void CCtrlListBox::ResetContent()
+{ ListBox_ResetContent(m_hwnd);
+}
+
+int CCtrlListBox::SelectString(const wchar_t *str)
+{ return ListBox_SelectString(m_hwnd, 0, str);
+}
+
+int CCtrlListBox::SetCurSel(int index)
+{ return ListBox_SetCurSel(m_hwnd, index);
+}
+
+void CCtrlListBox::SetItemData(int index, LPARAM data)
+{ ListBox_SetItemData(m_hwnd, index, data);
+}
+
+void CCtrlListBox::SetItemHeight(int index, int iHeight)
+{ ListBox_SetItemHeight(m_hwnd, index, iHeight);
+}
+
+void CCtrlListBox::SetSel(int index, bool sel)
+{ ListBox_SetSel(m_hwnd, sel ? TRUE : FALSE, index);
+}
diff --git a/src/mir_core/src/Linux/CCtrlListView.cpp b/src/mir_core/src/Linux/CCtrlListView.cpp
index eb57951a3c..40bb1f481e 100644
--- a/src/mir_core/src/Linux/CCtrlListView.cpp
+++ b/src/mir_core/src/Linux/CCtrlListView.cpp
@@ -1,551 +1,551 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlListView
-
-CCtrlListView::CCtrlListView(CDlgBase *dlg, int ctrlId)
- : CCtrlBase(dlg, ctrlId)
-{}
-
-BOOL CCtrlListView::OnNotify(int, NMHDR *pnmh)
-{
- TEventInfo evt = { this, pnmh };
-
- switch (pnmh->code) {
- case NM_CLICK: OnClick(&evt); return TRUE;
- case NM_DBLCLK: OnDoubleClick(&evt); return TRUE;
- case NM_CUSTOMDRAW: OnCustomDraw(&evt); return TRUE;
- case LVN_BEGINDRAG: OnBeginDrag(&evt); return TRUE;
- case LVN_BEGINLABELEDIT: OnBeginLabelEdit(&evt); return TRUE;
- case LVN_BEGINRDRAG: OnBeginRDrag(&evt); return TRUE;
- case LVN_BEGINSCROLL: OnBeginScroll(&evt); return TRUE;
- case LVN_COLUMNCLICK: OnColumnClick(&evt); return TRUE;
- case LVN_DELETEALLITEMS: OnDeleteAllItems(&evt); return TRUE;
- case LVN_DELETEITEM: OnDeleteItem(&evt); return TRUE;
- case LVN_ENDLABELEDIT: OnEndLabelEdit(&evt); return TRUE;
- case LVN_ENDSCROLL: OnEndScroll(&evt); return TRUE;
- case LVN_GETDISPINFO: OnGetDispInfo(&evt); return TRUE;
- case LVN_GETINFOTIP: OnGetInfoTip(&evt); return TRUE;
- case LVN_HOTTRACK: OnHotTrack(&evt); return TRUE;
- case LVN_INSERTITEM: OnInsertItem(&evt); return TRUE;
- case LVN_ITEMACTIVATE: OnItemActivate(&evt); return TRUE;
- case LVN_ITEMCHANGING: OnItemChanging(&evt); return TRUE;
- case LVN_KEYDOWN: OnKeyDown(&evt); return TRUE;
- case LVN_MARQUEEBEGIN: OnMarqueeBegin(&evt); return TRUE;
- case LVN_SETDISPINFO: OnSetDispInfo(&evt); return TRUE;
-
- case LVN_ITEMCHANGED:
- if (!m_parentWnd || !m_parentWnd->IsInitialized())
- return FALSE;
-
- OnItemChanged(&evt);
-
- // item's state is calculated as 1/2 << 12, so we check it to filter out all non-state changes
- if (evt.nmlv->uChanged & LVIF_STATE)
- if ((evt.nmlv->uOldState >> 12) != 0 && (evt.nmlv->uNewState >> 12) != 0)
- NotifyChange();
- return TRUE;
-
- case LVN_ODSTATECHANGED:
- NotifyChange();
- return TRUE;
- }
-
- return FALSE;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static int CALLBACK LVMoveSortProc(LPARAM l1, LPARAM l2, LPARAM param)
-{
- int result = l1 - l2;
- int newItem = HIWORD(param);
- int oldItem = LOWORD(param);
- if (newItem > oldItem)
- return (l1 == oldItem && l2 <= newItem) ? 1 : result;
-
- return (l2 == oldItem && l1 >= newItem) ? 1 : result;
-}
-
-int CCtrlListView::MoveItem(int idx, int direction)
-{
- if ((direction > 0 && idx >= GetItemCount() - 1) || (direction < 0 && idx <= 0))
- return idx;
-
- if (idx < 0)
- idx = GetNextItem(-1, LVNI_FOCUSED);
- SortItemsEx(&LVMoveSortProc, MAKELONG(idx, idx + direction));
- return idx + direction;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CCtrlListView::SetCurSel(int idx)
-{
- SetItemState(idx, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
-}
-
-// additional api
-HIMAGELIST CCtrlListView::CreateImageList(int iImageList)
-{
- HIMAGELIST hIml = GetImageList(iImageList);
- if (hIml)
- return hIml;
-
- hIml = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1);
- SetImageList(hIml, iImageList);
- return hIml;
-}
-
-void CCtrlListView::AddColumn(int iSubItem, const wchar_t *name, int cx)
-{
- LVCOLUMN lvc;
- lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
- lvc.iImage = 0;
- lvc.pszText = (LPWSTR)name;
- lvc.cx = cx;
- lvc.iSubItem = iSubItem;
- InsertColumn(iSubItem, &lvc);
-}
-
-void CCtrlListView::AddGroup(int iGroupId, const wchar_t *name)
-{
- LVGROUP lvg = { 0 };
- lvg.cbSize = sizeof(lvg);
- lvg.mask = LVGF_HEADER | LVGF_GROUPID;
- lvg.pszHeader = (LPWSTR)name;
- lvg.cchHeader = (int)mir_wstrlen(lvg.pszHeader);
- lvg.iGroupId = iGroupId;
- InsertGroup(-1, &lvg);
-}
-
-int CCtrlListView::AddItem(const wchar_t *text, int iIcon, LPARAM lParam, int iGroupId)
-{
- LVITEM lvi = { 0 };
- lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE;
- lvi.iSubItem = 0;
- lvi.pszText = (LPWSTR)text;
- lvi.iImage = iIcon;
- lvi.lParam = lParam;
- if (iGroupId >= 0) {
- lvi.mask |= LVIF_GROUPID;
- lvi.iGroupId = iGroupId;
- }
-
- return InsertItem(&lvi);
-}
-
-void CCtrlListView::SetItem(int iItem, int iSubItem, const wchar_t *text, int iIcon)
-{
- LVITEM lvi = { 0 };
- lvi.mask = LVIF_TEXT;
- lvi.iItem = iItem;
- lvi.iSubItem = iSubItem;
- lvi.pszText = (LPWSTR)text;
- if (iIcon >= 0) {
- lvi.mask |= LVIF_IMAGE;
- lvi.iImage = iIcon;
- }
-
- SetItem(&lvi);
-}
-
-LPARAM CCtrlListView::GetItemData(int iItem) const
-{
- LVITEM lvi = { 0 };
- lvi.mask = LVIF_PARAM;
- lvi.iItem = iItem;
- return GetItem(&lvi) ? lvi.lParam : -1;
-}
-
-void CCtrlListView::GetCaretPos(CContextMenuPos &pos) const
-{
- pos.pCtrl = this;
-
- // position is empty, let's fill it using selection
- if (pos.pt.x == 0 && pos.pt.y == 0) {
- pos.iCurr = GetSelectionMark();
- if (pos.iCurr != -1) {
- RECT rc;
- GetItemRect(pos.iCurr, &rc, TRUE);
- pos.pt.x = rc.left + 8;
- pos.pt.y = rc.top + 8;
- ClientToScreen(m_hwnd, &pos.pt);
- return;
- }
- }
- // position is present, let's calculate current item
- else {
- LVHITTESTINFO hti;
- hti.pt = pos.pt;
- ScreenToClient(m_hwnd, &hti.pt);
- if (SubItemHitTest(&hti) != -1) {
- pos.iCurr = hti.iItem;
- return;
- }
- }
- CSuper::GetCaretPos(pos);
-}
-
-// classic api
-uint32_t CCtrlListView::ApproximateViewRect(int cx, int cy, int iCount)
-{ return ListView_ApproximateViewRect(m_hwnd, cx, cy, iCount);
-}
-void CCtrlListView::Arrange(UINT code)
-{ ListView_Arrange(m_hwnd, code);
-}
-void CCtrlListView::CancelEditLabel()
-{ ListView_CancelEditLabel(m_hwnd);
-}
-HIMAGELIST CCtrlListView::CreateDragImage(int iItem, LPPOINT lpptUpLeft)
-{ return ListView_CreateDragImage(m_hwnd, iItem, lpptUpLeft);
-}
-void CCtrlListView::DeleteAllItems()
-{ ListView_DeleteAllItems(m_hwnd);
-}
-void CCtrlListView::DeleteColumn(int iCol)
-{ ListView_DeleteColumn(m_hwnd, iCol);
-}
-void CCtrlListView::DeleteItem(int iItem)
-{ ListView_DeleteItem(m_hwnd, iItem);
-}
-HWND CCtrlListView::EditLabel(int iItem)
-{ return ListView_EditLabel(m_hwnd, iItem);
-}
-int CCtrlListView::EnableGroupView(BOOL fEnable)
-{ return ListView_EnableGroupView(m_hwnd, fEnable);
-}
-BOOL CCtrlListView::EnsureVisible(int i, BOOL fPartialOK)
-{ return ListView_EnsureVisible(m_hwnd, i, fPartialOK);
-}
-int CCtrlListView::FindItem(int iStart, const LVFINDINFO *plvfi)
-{ return ListView_FindItem(m_hwnd, iStart, plvfi);
-}
-COLORREF CCtrlListView::GetBkColor() const
-{ return ListView_GetBkColor(m_hwnd);
-}
-void CCtrlListView::GetBkImage(LPLVBKIMAGE plvbki) const
-{ ListView_GetBkImage(m_hwnd, plvbki);
-}
-UINT CCtrlListView::GetCallbackMask() const
-{ return ListView_GetCallbackMask(m_hwnd);
-}
-BOOL CCtrlListView::GetCheckState(UINT iIndex) const
-{ return ListView_GetCheckState(m_hwnd, iIndex);
-}
-void CCtrlListView::GetColumn(int iCol, LPLVCOLUMN pcol) const
-{ ListView_GetColumn(m_hwnd, iCol, pcol);
-}
-void CCtrlListView::GetColumnOrderArray(int iCount, int *lpiArray) const
-{ ListView_GetColumnOrderArray(m_hwnd, iCount, lpiArray);
-}
-int CCtrlListView::GetColumnWidth(int iCol) const
-{ return ListView_GetColumnWidth(m_hwnd, iCol);
-}
-int CCtrlListView::GetCountPerPage() const
-{ return ListView_GetCountPerPage(m_hwnd);
-}
-HWND CCtrlListView::GetEditControl() const
-{ return ListView_GetEditControl(m_hwnd);
-}
-uint32_t CCtrlListView::GetExtendedListViewStyle() const
-{ return ListView_GetExtendedListViewStyle(m_hwnd);
-}
-void CCtrlListView::GetGroupMetrics(LVGROUPMETRICS *pGroupMetrics) const
-{ ListView_GetGroupMetrics(m_hwnd, pGroupMetrics);
-}
-HWND CCtrlListView::GetHeader() const
-{ return ListView_GetHeader(m_hwnd);
-}
-HCURSOR CCtrlListView::GetHotCursor() const
-{ return ListView_GetHotCursor(m_hwnd);
-}
-INT CCtrlListView::GetHotItem() const
-{ return ListView_GetHotItem(m_hwnd);
-}
-uint32_t CCtrlListView::GetHoverTime() const
-{ return ListView_GetHoverTime(m_hwnd);
-}
-HIMAGELIST CCtrlListView::GetImageList(int iImageList) const
-{ return ListView_GetImageList(m_hwnd, iImageList);
-}
-BOOL CCtrlListView::GetInsertMark(LVINSERTMARK *plvim) const
-{ return ListView_GetInsertMark(m_hwnd, plvim);
-}
-COLORREF CCtrlListView::GetInsertMarkColor() const
-{ return ListView_GetInsertMarkColor(m_hwnd);
-}
-int CCtrlListView::GetInsertMarkRect(LPRECT prc) const
-{ return ListView_GetInsertMarkRect(m_hwnd, prc);
-}
-BOOL CCtrlListView::GetISearchString(LPSTR lpsz) const
-{ return ListView_GetISearchString(m_hwnd, lpsz);
-}
-bool CCtrlListView::GetItem(LPLVITEM pitem) const
-{ return ListView_GetItem(m_hwnd, pitem) == TRUE;
-}
-int CCtrlListView::GetItemCount() const
-{ return ListView_GetItemCount(m_hwnd);
-}
-void CCtrlListView::GetItemPosition(int i, POINT *ppt) const
-{ ListView_GetItemPosition(m_hwnd, i, ppt);
-}
-void CCtrlListView::GetItemRect(int i, RECT *prc, int code) const
-{ ListView_GetItemRect(m_hwnd, i, prc, code);
-}
-uint32_t CCtrlListView::GetItemSpacing(BOOL fSmall) const
-{ return ListView_GetItemSpacing(m_hwnd, fSmall);
-}
-UINT CCtrlListView::GetItemState(int i, UINT mask) const
-{ return ListView_GetItemState(m_hwnd, i, mask);
-}
-void CCtrlListView::GetItemText(int iItem, int iSubItem, LPTSTR pszText, int cchTextMax) const
-{ ListView_GetItemText(m_hwnd, iItem, iSubItem, pszText, cchTextMax);
-}
-int CCtrlListView::GetNextItem(int iStart, UINT flags) const
-{ return ListView_GetNextItem(m_hwnd, iStart, flags);
-}
-BOOL CCtrlListView::GetNumberOfWorkAreas(LPUINT lpuWorkAreas) const
-{ return ListView_GetNumberOfWorkAreas(m_hwnd, lpuWorkAreas);
-}
-BOOL CCtrlListView::GetOrigin(LPPOINT lpptOrg) const
-{ return ListView_GetOrigin(m_hwnd, lpptOrg);
-}
-COLORREF CCtrlListView::GetOutlineColor() const
-{ return ListView_GetOutlineColor(m_hwnd);
-}
-UINT CCtrlListView::GetSelectedColumn() const
-{ return ListView_GetSelectedColumn(m_hwnd);
-}
-UINT CCtrlListView::GetSelectedCount() const
-{ return ListView_GetSelectedCount(m_hwnd);
-}
-INT CCtrlListView::GetSelectionMark() const
-{ return ListView_GetSelectionMark(m_hwnd);
-}
-int CCtrlListView::GetStringWidth(LPCSTR psz) const
-{ return ListView_GetStringWidth(m_hwnd, psz);
-}
-BOOL CCtrlListView::GetSubItemRect(int iItem, int iSubItem, int code, LPRECT lpRect) const
-{ return ListView_GetSubItemRect(m_hwnd, iItem, iSubItem, code, lpRect);
-}
-COLORREF CCtrlListView::GetTextBkColor() const
-{ return ListView_GetTextBkColor(m_hwnd);
-}
-COLORREF CCtrlListView::GetTextColor() const
-{ return ListView_GetTextColor(m_hwnd);
-}
-void CCtrlListView::GetTileInfo(PLVTILEINFO plvtinfo) const
-{ ListView_GetTileInfo(m_hwnd, plvtinfo);
-}
-void CCtrlListView::GetTileViewInfo(PLVTILEVIEWINFO plvtvinfo) const
-{ ListView_GetTileViewInfo(m_hwnd, plvtvinfo);
-}
-HWND CCtrlListView::GetToolTips() const
-{ return ListView_GetToolTips(m_hwnd);
-}
-int CCtrlListView::GetTopIndex() const
-{ return ListView_GetTopIndex(m_hwnd);
-}
-BOOL CCtrlListView::GetUnicodeFormat() const
-{ return ListView_GetUnicodeFormat(m_hwnd);
-}
-uint32_t CCtrlListView::GetView() const
-{ return ListView_GetView(m_hwnd);
-}
-BOOL CCtrlListView::GetViewRect(RECT *prc) const
-{ return ListView_GetViewRect(m_hwnd, prc);
-}
-void CCtrlListView::GetWorkAreas(INT nWorkAreas, LPRECT lprc) const
-{ ListView_GetWorkAreas(m_hwnd, nWorkAreas, lprc);
-}
-BOOL CCtrlListView::HasGroup(int dwGroupId)
-{ return ListView_HasGroup(m_hwnd, dwGroupId);
-}
-int CCtrlListView::HitTest(LPLVHITTESTINFO pinfo) const
-{ return ListView_HitTest(m_hwnd, pinfo);
-}
-int CCtrlListView::InsertColumn(int iCol, const LVCOLUMN *pcol)
-{ return ListView_InsertColumn(m_hwnd, iCol, pcol);
-}
-int CCtrlListView::InsertGroup(int index, PLVGROUP pgrp)
-{ return ListView_InsertGroup(m_hwnd, index, pgrp);
-}
-void CCtrlListView::InsertGroupSorted(PLVINSERTGROUPSORTED structInsert)
-{ ListView_InsertGroupSorted(m_hwnd, structInsert);
-}
-int CCtrlListView::InsertItem(const LVITEM *pitem)
-{ return ListView_InsertItem(m_hwnd, pitem);
-}
-BOOL CCtrlListView::InsertMarkHitTest(LPPOINT point, LVINSERTMARK *plvim)
-{ return ListView_InsertMarkHitTest(m_hwnd, point, plvim);
-}
-BOOL CCtrlListView::IsGroupViewEnabled()
-{ return ListView_IsGroupViewEnabled(m_hwnd);
-}
-UINT CCtrlListView::MapIDToIndex(UINT id)
-{ return ListView_MapIDToIndex(m_hwnd, id);
-}
-UINT CCtrlListView::MapIndexToID(UINT index)
-{ return ListView_MapIndexToID(m_hwnd, index);
-}
-BOOL CCtrlListView::RedrawItems(int iFirst, int iLast)
-{ return ListView_RedrawItems(m_hwnd, iFirst, iLast);
-}
-void CCtrlListView::RemoveAllGroups()
-{ ListView_RemoveAllGroups(m_hwnd);
-}
-int CCtrlListView::RemoveGroup(int iGroupId)
-{ return ListView_RemoveGroup(m_hwnd, iGroupId);
-}
-BOOL CCtrlListView::Scroll(int dx, int dy)
-{ return ListView_Scroll(m_hwnd, dx, dy);
-}
-BOOL CCtrlListView::SetBkColor(COLORREF clrBk)
-{ return ListView_SetBkColor(m_hwnd, clrBk);
-}
-BOOL CCtrlListView::SetBkImage(LPLVBKIMAGE plvbki)
-{ return ListView_SetBkImage(m_hwnd, plvbki);
-}
-BOOL CCtrlListView::SetCallbackMask(UINT mask)
-{ return ListView_SetCallbackMask(m_hwnd, mask);
-}
-void CCtrlListView::SetCheckState(UINT iIndex, BOOL fCheck)
-{ ListView_SetCheckState(m_hwnd, iIndex, fCheck);
-}
-BOOL CCtrlListView::SetColumn(int iCol, LPLVCOLUMN pcol)
-{ return ListView_SetColumn(m_hwnd, iCol, pcol);
-}
-BOOL CCtrlListView::SetColumnOrderArray(int iCount, int *lpiArray)
-{ return ListView_SetColumnOrderArray(m_hwnd, iCount, lpiArray);
-}
-BOOL CCtrlListView::SetColumnWidth(int iCol, int cx)
-{ return ListView_SetColumnWidth(m_hwnd, iCol, cx);
-}
-void CCtrlListView::SetExtendedListViewStyle(uint32_t dwExStyle)
-{ ListView_SetExtendedListViewStyle(m_hwnd, dwExStyle);
-}
-void CCtrlListView::SetExtendedListViewStyleEx(uint32_t dwExMask, uint32_t dwExStyle)
-{ ListView_SetExtendedListViewStyleEx(m_hwnd, dwExMask, dwExStyle);
-}
-int CCtrlListView::SetGroupInfo(int iGroupId, PLVGROUP pgrp)
-{ return ListView_SetGroupInfo(m_hwnd, iGroupId, pgrp);
-}
-void CCtrlListView::SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics)
-{ ListView_SetGroupMetrics(m_hwnd, pGroupMetrics);
-}
-HCURSOR CCtrlListView::SetHotCursor(HCURSOR hCursor)
-{ return ListView_SetHotCursor(m_hwnd, hCursor);
-}
-INT CCtrlListView::SetHotItem(INT iIndex)
-{ return ListView_SetHotItem(m_hwnd, iIndex);
-}
-void CCtrlListView::SetHoverTime(uint32_t dwHoverTime)
-{ ListView_SetHoverTime(m_hwnd, dwHoverTime);
-}
-uint32_t CCtrlListView::SetIconSpacing(int cx, int cy)
-{ return ListView_SetIconSpacing(m_hwnd, cx, cy);
-}
-HIMAGELIST CCtrlListView::SetImageList(HIMAGELIST himl, int iImageList)
-{ return ListView_SetImageList(m_hwnd, himl, iImageList);
-}
-BOOL CCtrlListView::SetInfoTip(PLVSETINFOTIP plvSetInfoTip)
-{ return ListView_SetInfoTip(m_hwnd, plvSetInfoTip);
-}
-BOOL CCtrlListView::SetInsertMark(LVINSERTMARK *plvim)
-{ return ListView_SetInsertMark(m_hwnd, plvim);
-}
-COLORREF CCtrlListView::SetInsertMarkColor(COLORREF color)
-{ return ListView_SetInsertMarkColor(m_hwnd, color);
-}
-BOOL CCtrlListView::SetItem(const LVITEM *pitem)
-{ return ListView_SetItem(m_hwnd, pitem);
-}
-void CCtrlListView::SetItemCount(int cItems)
-{ ListView_SetItemCount(m_hwnd, cItems);
-}
-void CCtrlListView::SetItemCountEx(int cItems, uint32_t dwFlags)
-{ ListView_SetItemCountEx(m_hwnd, cItems, dwFlags);
-}
-BOOL CCtrlListView::SetItemPosition(int i, int x, int y)
-{ return ListView_SetItemPosition(m_hwnd, i, x, y);
-}
-void CCtrlListView::SetItemPosition32(int iItem, int x, int y)
-{ ListView_SetItemPosition32(m_hwnd, iItem, x, y);
-}
-void CCtrlListView::SetItemState(int i, UINT state, UINT mask)
-{ ListView_SetItemState(m_hwnd, i, state, mask);
-}
-void CCtrlListView::SetItemText(int i, int iSubItem, const wchar_t *pszText)
-{ ListView_SetItemText(m_hwnd, i, iSubItem, (LPWSTR)pszText);
-}
-COLORREF CCtrlListView::SetOutlineColor(COLORREF color)
-{ return ListView_SetOutlineColor(m_hwnd, color);
-}
-void CCtrlListView::SetSelectedColumn(int iCol)
-{ ListView_SetSelectedColumn(m_hwnd, iCol);
-}
-INT CCtrlListView::SetSelectionMark(INT iIndex)
-{ return ListView_SetSelectionMark(m_hwnd, iIndex);
-}
-BOOL CCtrlListView::SetTextBkColor(COLORREF clrText)
-{ return ListView_SetTextBkColor(m_hwnd, clrText);
-}
-BOOL CCtrlListView::SetTextColor(COLORREF clrText)
-{ return ListView_SetTextColor(m_hwnd, clrText);
-}
-BOOL CCtrlListView::SetTileInfo(PLVTILEINFO plvtinfo)
-{ return ListView_SetTileInfo(m_hwnd, plvtinfo);
-}
-BOOL CCtrlListView::SetTileViewInfo(PLVTILEVIEWINFO plvtvinfo)
-{ return ListView_SetTileViewInfo(m_hwnd, plvtvinfo);
-}
-HWND CCtrlListView::SetToolTips(HWND ToolTip)
-{ return ListView_SetToolTips(m_hwnd, ToolTip);
-}
-BOOL CCtrlListView::SetUnicodeFormat(BOOL fUnicode)
-{ return ListView_SetUnicodeFormat(m_hwnd, fUnicode);
-}
-int CCtrlListView::SetView(uint32_t iView)
-{ return ListView_SetView(m_hwnd, iView);
-}
-void CCtrlListView::SetWorkAreas(INT nWorkAreas, LPRECT lprc)
-{ ListView_SetWorkAreas(m_hwnd, nWorkAreas, lprc);
-}
-int CCtrlListView::SortGroups(PFNLVGROUPCOMPARE pfnGroupCompare, LPVOID plv)
-{ return ListView_SortGroups(m_hwnd, pfnGroupCompare, plv);
-}
-BOOL CCtrlListView::SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
-{ return ListView_SortItems(m_hwnd, pfnCompare, lParamSort);
-}
-BOOL CCtrlListView::SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
-{ return ListView_SortItemsEx(m_hwnd, pfnCompare, lParamSort);
-}
-INT CCtrlListView::SubItemHitTest(LPLVHITTESTINFO pInfo) const
-{ return ListView_SubItemHitTest(m_hwnd, pInfo);
-}
-BOOL CCtrlListView::Update(int iItem)
-{ return ListView_Update(m_hwnd, iItem);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlListView
+
+CCtrlListView::CCtrlListView(CDlgBase *dlg, int ctrlId)
+ : CCtrlBase(dlg, ctrlId)
+{}
+
+BOOL CCtrlListView::OnNotify(int, NMHDR *pnmh)
+{
+ TEventInfo evt = { this, pnmh };
+
+ switch (pnmh->code) {
+ case NM_CLICK: OnClick(&evt); return TRUE;
+ case NM_DBLCLK: OnDoubleClick(&evt); return TRUE;
+ case NM_CUSTOMDRAW: OnCustomDraw(&evt); return TRUE;
+ case LVN_BEGINDRAG: OnBeginDrag(&evt); return TRUE;
+ case LVN_BEGINLABELEDIT: OnBeginLabelEdit(&evt); return TRUE;
+ case LVN_BEGINRDRAG: OnBeginRDrag(&evt); return TRUE;
+ case LVN_BEGINSCROLL: OnBeginScroll(&evt); return TRUE;
+ case LVN_COLUMNCLICK: OnColumnClick(&evt); return TRUE;
+ case LVN_DELETEALLITEMS: OnDeleteAllItems(&evt); return TRUE;
+ case LVN_DELETEITEM: OnDeleteItem(&evt); return TRUE;
+ case LVN_ENDLABELEDIT: OnEndLabelEdit(&evt); return TRUE;
+ case LVN_ENDSCROLL: OnEndScroll(&evt); return TRUE;
+ case LVN_GETDISPINFO: OnGetDispInfo(&evt); return TRUE;
+ case LVN_GETINFOTIP: OnGetInfoTip(&evt); return TRUE;
+ case LVN_HOTTRACK: OnHotTrack(&evt); return TRUE;
+ case LVN_INSERTITEM: OnInsertItem(&evt); return TRUE;
+ case LVN_ITEMACTIVATE: OnItemActivate(&evt); return TRUE;
+ case LVN_ITEMCHANGING: OnItemChanging(&evt); return TRUE;
+ case LVN_KEYDOWN: OnKeyDown(&evt); return TRUE;
+ case LVN_MARQUEEBEGIN: OnMarqueeBegin(&evt); return TRUE;
+ case LVN_SETDISPINFO: OnSetDispInfo(&evt); return TRUE;
+
+ case LVN_ITEMCHANGED:
+ if (!m_parentWnd || !m_parentWnd->IsInitialized())
+ return FALSE;
+
+ OnItemChanged(&evt);
+
+ // item's state is calculated as 1/2 << 12, so we check it to filter out all non-state changes
+ if (evt.nmlv->uChanged & LVIF_STATE)
+ if ((evt.nmlv->uOldState >> 12) != 0 && (evt.nmlv->uNewState >> 12) != 0)
+ NotifyChange();
+ return TRUE;
+
+ case LVN_ODSTATECHANGED:
+ NotifyChange();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int CALLBACK LVMoveSortProc(LPARAM l1, LPARAM l2, LPARAM param)
+{
+ int result = l1 - l2;
+ int newItem = HIWORD(param);
+ int oldItem = LOWORD(param);
+ if (newItem > oldItem)
+ return (l1 == oldItem && l2 <= newItem) ? 1 : result;
+
+ return (l2 == oldItem && l1 >= newItem) ? 1 : result;
+}
+
+int CCtrlListView::MoveItem(int idx, int direction)
+{
+ if ((direction > 0 && idx >= GetItemCount() - 1) || (direction < 0 && idx <= 0))
+ return idx;
+
+ if (idx < 0)
+ idx = GetNextItem(-1, LVNI_FOCUSED);
+ SortItemsEx(&LVMoveSortProc, MAKELONG(idx, idx + direction));
+ return idx + direction;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CCtrlListView::SetCurSel(int idx)
+{
+ SetItemState(idx, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
+}
+
+// additional api
+HIMAGELIST CCtrlListView::CreateImageList(int iImageList)
+{
+ HIMAGELIST hIml = GetImageList(iImageList);
+ if (hIml)
+ return hIml;
+
+ hIml = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1);
+ SetImageList(hIml, iImageList);
+ return hIml;
+}
+
+void CCtrlListView::AddColumn(int iSubItem, const wchar_t *name, int cx)
+{
+ LVCOLUMN lvc;
+ lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
+ lvc.iImage = 0;
+ lvc.pszText = (LPWSTR)name;
+ lvc.cx = cx;
+ lvc.iSubItem = iSubItem;
+ InsertColumn(iSubItem, &lvc);
+}
+
+void CCtrlListView::AddGroup(int iGroupId, const wchar_t *name)
+{
+ LVGROUP lvg = { 0 };
+ lvg.cbSize = sizeof(lvg);
+ lvg.mask = LVGF_HEADER | LVGF_GROUPID;
+ lvg.pszHeader = (LPWSTR)name;
+ lvg.cchHeader = (int)mir_wstrlen(lvg.pszHeader);
+ lvg.iGroupId = iGroupId;
+ InsertGroup(-1, &lvg);
+}
+
+int CCtrlListView::AddItem(const wchar_t *text, int iIcon, LPARAM lParam, int iGroupId)
+{
+ LVITEM lvi = { 0 };
+ lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE;
+ lvi.iSubItem = 0;
+ lvi.pszText = (LPWSTR)text;
+ lvi.iImage = iIcon;
+ lvi.lParam = lParam;
+ if (iGroupId >= 0) {
+ lvi.mask |= LVIF_GROUPID;
+ lvi.iGroupId = iGroupId;
+ }
+
+ return InsertItem(&lvi);
+}
+
+void CCtrlListView::SetItem(int iItem, int iSubItem, const wchar_t *text, int iIcon)
+{
+ LVITEM lvi = { 0 };
+ lvi.mask = LVIF_TEXT;
+ lvi.iItem = iItem;
+ lvi.iSubItem = iSubItem;
+ lvi.pszText = (LPWSTR)text;
+ if (iIcon >= 0) {
+ lvi.mask |= LVIF_IMAGE;
+ lvi.iImage = iIcon;
+ }
+
+ SetItem(&lvi);
+}
+
+LPARAM CCtrlListView::GetItemData(int iItem) const
+{
+ LVITEM lvi = { 0 };
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = iItem;
+ return GetItem(&lvi) ? lvi.lParam : -1;
+}
+
+void CCtrlListView::GetCaretPos(CContextMenuPos &pos) const
+{
+ pos.pCtrl = this;
+
+ // position is empty, let's fill it using selection
+ if (pos.pt.x == 0 && pos.pt.y == 0) {
+ pos.iCurr = GetSelectionMark();
+ if (pos.iCurr != -1) {
+ RECT rc;
+ GetItemRect(pos.iCurr, &rc, TRUE);
+ pos.pt.x = rc.left + 8;
+ pos.pt.y = rc.top + 8;
+ ClientToScreen(m_hwnd, &pos.pt);
+ return;
+ }
+ }
+ // position is present, let's calculate current item
+ else {
+ LVHITTESTINFO hti;
+ hti.pt = pos.pt;
+ ScreenToClient(m_hwnd, &hti.pt);
+ if (SubItemHitTest(&hti) != -1) {
+ pos.iCurr = hti.iItem;
+ return;
+ }
+ }
+ CSuper::GetCaretPos(pos);
+}
+
+// classic api
+uint32_t CCtrlListView::ApproximateViewRect(int cx, int cy, int iCount)
+{ return ListView_ApproximateViewRect(m_hwnd, cx, cy, iCount);
+}
+void CCtrlListView::Arrange(UINT code)
+{ ListView_Arrange(m_hwnd, code);
+}
+void CCtrlListView::CancelEditLabel()
+{ ListView_CancelEditLabel(m_hwnd);
+}
+HIMAGELIST CCtrlListView::CreateDragImage(int iItem, LPPOINT lpptUpLeft)
+{ return ListView_CreateDragImage(m_hwnd, iItem, lpptUpLeft);
+}
+void CCtrlListView::DeleteAllItems()
+{ ListView_DeleteAllItems(m_hwnd);
+}
+void CCtrlListView::DeleteColumn(int iCol)
+{ ListView_DeleteColumn(m_hwnd, iCol);
+}
+void CCtrlListView::DeleteItem(int iItem)
+{ ListView_DeleteItem(m_hwnd, iItem);
+}
+HWND CCtrlListView::EditLabel(int iItem)
+{ return ListView_EditLabel(m_hwnd, iItem);
+}
+int CCtrlListView::EnableGroupView(BOOL fEnable)
+{ return ListView_EnableGroupView(m_hwnd, fEnable);
+}
+BOOL CCtrlListView::EnsureVisible(int i, BOOL fPartialOK)
+{ return ListView_EnsureVisible(m_hwnd, i, fPartialOK);
+}
+int CCtrlListView::FindItem(int iStart, const LVFINDINFO *plvfi)
+{ return ListView_FindItem(m_hwnd, iStart, plvfi);
+}
+COLORREF CCtrlListView::GetBkColor() const
+{ return ListView_GetBkColor(m_hwnd);
+}
+void CCtrlListView::GetBkImage(LPLVBKIMAGE plvbki) const
+{ ListView_GetBkImage(m_hwnd, plvbki);
+}
+UINT CCtrlListView::GetCallbackMask() const
+{ return ListView_GetCallbackMask(m_hwnd);
+}
+BOOL CCtrlListView::GetCheckState(UINT iIndex) const
+{ return ListView_GetCheckState(m_hwnd, iIndex);
+}
+void CCtrlListView::GetColumn(int iCol, LPLVCOLUMN pcol) const
+{ ListView_GetColumn(m_hwnd, iCol, pcol);
+}
+void CCtrlListView::GetColumnOrderArray(int iCount, int *lpiArray) const
+{ ListView_GetColumnOrderArray(m_hwnd, iCount, lpiArray);
+}
+int CCtrlListView::GetColumnWidth(int iCol) const
+{ return ListView_GetColumnWidth(m_hwnd, iCol);
+}
+int CCtrlListView::GetCountPerPage() const
+{ return ListView_GetCountPerPage(m_hwnd);
+}
+HWND CCtrlListView::GetEditControl() const
+{ return ListView_GetEditControl(m_hwnd);
+}
+uint32_t CCtrlListView::GetExtendedListViewStyle() const
+{ return ListView_GetExtendedListViewStyle(m_hwnd);
+}
+void CCtrlListView::GetGroupMetrics(LVGROUPMETRICS *pGroupMetrics) const
+{ ListView_GetGroupMetrics(m_hwnd, pGroupMetrics);
+}
+HWND CCtrlListView::GetHeader() const
+{ return ListView_GetHeader(m_hwnd);
+}
+HCURSOR CCtrlListView::GetHotCursor() const
+{ return ListView_GetHotCursor(m_hwnd);
+}
+INT CCtrlListView::GetHotItem() const
+{ return ListView_GetHotItem(m_hwnd);
+}
+uint32_t CCtrlListView::GetHoverTime() const
+{ return ListView_GetHoverTime(m_hwnd);
+}
+HIMAGELIST CCtrlListView::GetImageList(int iImageList) const
+{ return ListView_GetImageList(m_hwnd, iImageList);
+}
+BOOL CCtrlListView::GetInsertMark(LVINSERTMARK *plvim) const
+{ return ListView_GetInsertMark(m_hwnd, plvim);
+}
+COLORREF CCtrlListView::GetInsertMarkColor() const
+{ return ListView_GetInsertMarkColor(m_hwnd);
+}
+int CCtrlListView::GetInsertMarkRect(LPRECT prc) const
+{ return ListView_GetInsertMarkRect(m_hwnd, prc);
+}
+BOOL CCtrlListView::GetISearchString(LPSTR lpsz) const
+{ return ListView_GetISearchString(m_hwnd, lpsz);
+}
+bool CCtrlListView::GetItem(LPLVITEM pitem) const
+{ return ListView_GetItem(m_hwnd, pitem) == TRUE;
+}
+int CCtrlListView::GetItemCount() const
+{ return ListView_GetItemCount(m_hwnd);
+}
+void CCtrlListView::GetItemPosition(int i, POINT *ppt) const
+{ ListView_GetItemPosition(m_hwnd, i, ppt);
+}
+void CCtrlListView::GetItemRect(int i, RECT *prc, int code) const
+{ ListView_GetItemRect(m_hwnd, i, prc, code);
+}
+uint32_t CCtrlListView::GetItemSpacing(BOOL fSmall) const
+{ return ListView_GetItemSpacing(m_hwnd, fSmall);
+}
+UINT CCtrlListView::GetItemState(int i, UINT mask) const
+{ return ListView_GetItemState(m_hwnd, i, mask);
+}
+void CCtrlListView::GetItemText(int iItem, int iSubItem, LPTSTR pszText, int cchTextMax) const
+{ ListView_GetItemText(m_hwnd, iItem, iSubItem, pszText, cchTextMax);
+}
+int CCtrlListView::GetNextItem(int iStart, UINT flags) const
+{ return ListView_GetNextItem(m_hwnd, iStart, flags);
+}
+BOOL CCtrlListView::GetNumberOfWorkAreas(LPUINT lpuWorkAreas) const
+{ return ListView_GetNumberOfWorkAreas(m_hwnd, lpuWorkAreas);
+}
+BOOL CCtrlListView::GetOrigin(LPPOINT lpptOrg) const
+{ return ListView_GetOrigin(m_hwnd, lpptOrg);
+}
+COLORREF CCtrlListView::GetOutlineColor() const
+{ return ListView_GetOutlineColor(m_hwnd);
+}
+UINT CCtrlListView::GetSelectedColumn() const
+{ return ListView_GetSelectedColumn(m_hwnd);
+}
+UINT CCtrlListView::GetSelectedCount() const
+{ return ListView_GetSelectedCount(m_hwnd);
+}
+INT CCtrlListView::GetSelectionMark() const
+{ return ListView_GetSelectionMark(m_hwnd);
+}
+int CCtrlListView::GetStringWidth(LPCSTR psz) const
+{ return ListView_GetStringWidth(m_hwnd, psz);
+}
+BOOL CCtrlListView::GetSubItemRect(int iItem, int iSubItem, int code, LPRECT lpRect) const
+{ return ListView_GetSubItemRect(m_hwnd, iItem, iSubItem, code, lpRect);
+}
+COLORREF CCtrlListView::GetTextBkColor() const
+{ return ListView_GetTextBkColor(m_hwnd);
+}
+COLORREF CCtrlListView::GetTextColor() const
+{ return ListView_GetTextColor(m_hwnd);
+}
+void CCtrlListView::GetTileInfo(PLVTILEINFO plvtinfo) const
+{ ListView_GetTileInfo(m_hwnd, plvtinfo);
+}
+void CCtrlListView::GetTileViewInfo(PLVTILEVIEWINFO plvtvinfo) const
+{ ListView_GetTileViewInfo(m_hwnd, plvtvinfo);
+}
+HWND CCtrlListView::GetToolTips() const
+{ return ListView_GetToolTips(m_hwnd);
+}
+int CCtrlListView::GetTopIndex() const
+{ return ListView_GetTopIndex(m_hwnd);
+}
+BOOL CCtrlListView::GetUnicodeFormat() const
+{ return ListView_GetUnicodeFormat(m_hwnd);
+}
+uint32_t CCtrlListView::GetView() const
+{ return ListView_GetView(m_hwnd);
+}
+BOOL CCtrlListView::GetViewRect(RECT *prc) const
+{ return ListView_GetViewRect(m_hwnd, prc);
+}
+void CCtrlListView::GetWorkAreas(INT nWorkAreas, LPRECT lprc) const
+{ ListView_GetWorkAreas(m_hwnd, nWorkAreas, lprc);
+}
+BOOL CCtrlListView::HasGroup(int dwGroupId)
+{ return ListView_HasGroup(m_hwnd, dwGroupId);
+}
+int CCtrlListView::HitTest(LPLVHITTESTINFO pinfo) const
+{ return ListView_HitTest(m_hwnd, pinfo);
+}
+int CCtrlListView::InsertColumn(int iCol, const LVCOLUMN *pcol)
+{ return ListView_InsertColumn(m_hwnd, iCol, pcol);
+}
+int CCtrlListView::InsertGroup(int index, PLVGROUP pgrp)
+{ return ListView_InsertGroup(m_hwnd, index, pgrp);
+}
+void CCtrlListView::InsertGroupSorted(PLVINSERTGROUPSORTED structInsert)
+{ ListView_InsertGroupSorted(m_hwnd, structInsert);
+}
+int CCtrlListView::InsertItem(const LVITEM *pitem)
+{ return ListView_InsertItem(m_hwnd, pitem);
+}
+BOOL CCtrlListView::InsertMarkHitTest(LPPOINT point, LVINSERTMARK *plvim)
+{ return ListView_InsertMarkHitTest(m_hwnd, point, plvim);
+}
+BOOL CCtrlListView::IsGroupViewEnabled()
+{ return ListView_IsGroupViewEnabled(m_hwnd);
+}
+UINT CCtrlListView::MapIDToIndex(UINT id)
+{ return ListView_MapIDToIndex(m_hwnd, id);
+}
+UINT CCtrlListView::MapIndexToID(UINT index)
+{ return ListView_MapIndexToID(m_hwnd, index);
+}
+BOOL CCtrlListView::RedrawItems(int iFirst, int iLast)
+{ return ListView_RedrawItems(m_hwnd, iFirst, iLast);
+}
+void CCtrlListView::RemoveAllGroups()
+{ ListView_RemoveAllGroups(m_hwnd);
+}
+int CCtrlListView::RemoveGroup(int iGroupId)
+{ return ListView_RemoveGroup(m_hwnd, iGroupId);
+}
+BOOL CCtrlListView::Scroll(int dx, int dy)
+{ return ListView_Scroll(m_hwnd, dx, dy);
+}
+BOOL CCtrlListView::SetBkColor(COLORREF clrBk)
+{ return ListView_SetBkColor(m_hwnd, clrBk);
+}
+BOOL CCtrlListView::SetBkImage(LPLVBKIMAGE plvbki)
+{ return ListView_SetBkImage(m_hwnd, plvbki);
+}
+BOOL CCtrlListView::SetCallbackMask(UINT mask)
+{ return ListView_SetCallbackMask(m_hwnd, mask);
+}
+void CCtrlListView::SetCheckState(UINT iIndex, BOOL fCheck)
+{ ListView_SetCheckState(m_hwnd, iIndex, fCheck);
+}
+BOOL CCtrlListView::SetColumn(int iCol, LPLVCOLUMN pcol)
+{ return ListView_SetColumn(m_hwnd, iCol, pcol);
+}
+BOOL CCtrlListView::SetColumnOrderArray(int iCount, int *lpiArray)
+{ return ListView_SetColumnOrderArray(m_hwnd, iCount, lpiArray);
+}
+BOOL CCtrlListView::SetColumnWidth(int iCol, int cx)
+{ return ListView_SetColumnWidth(m_hwnd, iCol, cx);
+}
+void CCtrlListView::SetExtendedListViewStyle(uint32_t dwExStyle)
+{ ListView_SetExtendedListViewStyle(m_hwnd, dwExStyle);
+}
+void CCtrlListView::SetExtendedListViewStyleEx(uint32_t dwExMask, uint32_t dwExStyle)
+{ ListView_SetExtendedListViewStyleEx(m_hwnd, dwExMask, dwExStyle);
+}
+int CCtrlListView::SetGroupInfo(int iGroupId, PLVGROUP pgrp)
+{ return ListView_SetGroupInfo(m_hwnd, iGroupId, pgrp);
+}
+void CCtrlListView::SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics)
+{ ListView_SetGroupMetrics(m_hwnd, pGroupMetrics);
+}
+HCURSOR CCtrlListView::SetHotCursor(HCURSOR hCursor)
+{ return ListView_SetHotCursor(m_hwnd, hCursor);
+}
+INT CCtrlListView::SetHotItem(INT iIndex)
+{ return ListView_SetHotItem(m_hwnd, iIndex);
+}
+void CCtrlListView::SetHoverTime(uint32_t dwHoverTime)
+{ ListView_SetHoverTime(m_hwnd, dwHoverTime);
+}
+uint32_t CCtrlListView::SetIconSpacing(int cx, int cy)
+{ return ListView_SetIconSpacing(m_hwnd, cx, cy);
+}
+HIMAGELIST CCtrlListView::SetImageList(HIMAGELIST himl, int iImageList)
+{ return ListView_SetImageList(m_hwnd, himl, iImageList);
+}
+BOOL CCtrlListView::SetInfoTip(PLVSETINFOTIP plvSetInfoTip)
+{ return ListView_SetInfoTip(m_hwnd, plvSetInfoTip);
+}
+BOOL CCtrlListView::SetInsertMark(LVINSERTMARK *plvim)
+{ return ListView_SetInsertMark(m_hwnd, plvim);
+}
+COLORREF CCtrlListView::SetInsertMarkColor(COLORREF color)
+{ return ListView_SetInsertMarkColor(m_hwnd, color);
+}
+BOOL CCtrlListView::SetItem(const LVITEM *pitem)
+{ return ListView_SetItem(m_hwnd, pitem);
+}
+void CCtrlListView::SetItemCount(int cItems)
+{ ListView_SetItemCount(m_hwnd, cItems);
+}
+void CCtrlListView::SetItemCountEx(int cItems, uint32_t dwFlags)
+{ ListView_SetItemCountEx(m_hwnd, cItems, dwFlags);
+}
+BOOL CCtrlListView::SetItemPosition(int i, int x, int y)
+{ return ListView_SetItemPosition(m_hwnd, i, x, y);
+}
+void CCtrlListView::SetItemPosition32(int iItem, int x, int y)
+{ ListView_SetItemPosition32(m_hwnd, iItem, x, y);
+}
+void CCtrlListView::SetItemState(int i, UINT state, UINT mask)
+{ ListView_SetItemState(m_hwnd, i, state, mask);
+}
+void CCtrlListView::SetItemText(int i, int iSubItem, const wchar_t *pszText)
+{ ListView_SetItemText(m_hwnd, i, iSubItem, (LPWSTR)pszText);
+}
+COLORREF CCtrlListView::SetOutlineColor(COLORREF color)
+{ return ListView_SetOutlineColor(m_hwnd, color);
+}
+void CCtrlListView::SetSelectedColumn(int iCol)
+{ ListView_SetSelectedColumn(m_hwnd, iCol);
+}
+INT CCtrlListView::SetSelectionMark(INT iIndex)
+{ return ListView_SetSelectionMark(m_hwnd, iIndex);
+}
+BOOL CCtrlListView::SetTextBkColor(COLORREF clrText)
+{ return ListView_SetTextBkColor(m_hwnd, clrText);
+}
+BOOL CCtrlListView::SetTextColor(COLORREF clrText)
+{ return ListView_SetTextColor(m_hwnd, clrText);
+}
+BOOL CCtrlListView::SetTileInfo(PLVTILEINFO plvtinfo)
+{ return ListView_SetTileInfo(m_hwnd, plvtinfo);
+}
+BOOL CCtrlListView::SetTileViewInfo(PLVTILEVIEWINFO plvtvinfo)
+{ return ListView_SetTileViewInfo(m_hwnd, plvtvinfo);
+}
+HWND CCtrlListView::SetToolTips(HWND ToolTip)
+{ return ListView_SetToolTips(m_hwnd, ToolTip);
+}
+BOOL CCtrlListView::SetUnicodeFormat(BOOL fUnicode)
+{ return ListView_SetUnicodeFormat(m_hwnd, fUnicode);
+}
+int CCtrlListView::SetView(uint32_t iView)
+{ return ListView_SetView(m_hwnd, iView);
+}
+void CCtrlListView::SetWorkAreas(INT nWorkAreas, LPRECT lprc)
+{ ListView_SetWorkAreas(m_hwnd, nWorkAreas, lprc);
+}
+int CCtrlListView::SortGroups(PFNLVGROUPCOMPARE pfnGroupCompare, LPVOID plv)
+{ return ListView_SortGroups(m_hwnd, pfnGroupCompare, plv);
+}
+BOOL CCtrlListView::SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
+{ return ListView_SortItems(m_hwnd, pfnCompare, lParamSort);
+}
+BOOL CCtrlListView::SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
+{ return ListView_SortItemsEx(m_hwnd, pfnCompare, lParamSort);
+}
+INT CCtrlListView::SubItemHitTest(LPLVHITTESTINFO pInfo) const
+{ return ListView_SubItemHitTest(m_hwnd, pInfo);
+}
+BOOL CCtrlListView::Update(int iItem)
+{ return ListView_Update(m_hwnd, iItem);
+}
diff --git a/src/mir_core/src/Linux/CCtrlMButton.cpp b/src/mir_core/src/Linux/CCtrlMButton.cpp
index 8d9198e144..cc05a3a8e4 100644
--- a/src/mir_core/src/Linux/CCtrlMButton.cpp
+++ b/src/mir_core/src/Linux/CCtrlMButton.cpp
@@ -1,62 +1,62 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlMButton
-
-CCtrlMButton::CCtrlMButton(CDlgBase *dlg, int ctrlId, HICON hIcon, const char* tooltip)
- : CCtrlButton(dlg, ctrlId),
- m_hIcon(hIcon),
- m_toolTip(tooltip)
-{}
-
-CCtrlMButton::CCtrlMButton(CDlgBase *dlg, int ctrlId, int iCoreIcon, const char* tooltip)
- : CCtrlButton(dlg, ctrlId),
- m_hIcon(::Skin_LoadIcon(iCoreIcon)),
- m_toolTip(tooltip)
-{}
-
-CCtrlMButton::~CCtrlMButton()
-{
- ::IcoLib_ReleaseIcon(m_hIcon);
-}
-
-void CCtrlMButton::OnInit()
-{
- CCtrlButton::OnInit();
-
- SendMessage(m_hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)m_hIcon);
- SendMessage(m_hwnd, BUTTONADDTOOLTIP, (WPARAM)m_toolTip, 0);
- SendMessage(m_hwnd, BUTTONSETASFLATBTN, (WPARAM)m_toolTip, 0);
-}
-
-void CCtrlMButton::MakeFlat()
-{
- SendMessage(m_hwnd, BUTTONSETASFLATBTN, TRUE, 0);
-}
-
-void CCtrlMButton::MakePush()
-{
- SendMessage(m_hwnd, BUTTONSETASPUSHBTN, TRUE, 0);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlMButton
+
+CCtrlMButton::CCtrlMButton(CDlgBase *dlg, int ctrlId, HICON hIcon, const char* tooltip)
+ : CCtrlButton(dlg, ctrlId),
+ m_hIcon(hIcon),
+ m_toolTip(tooltip)
+{}
+
+CCtrlMButton::CCtrlMButton(CDlgBase *dlg, int ctrlId, int iCoreIcon, const char* tooltip)
+ : CCtrlButton(dlg, ctrlId),
+ m_hIcon(::Skin_LoadIcon(iCoreIcon)),
+ m_toolTip(tooltip)
+{}
+
+CCtrlMButton::~CCtrlMButton()
+{
+ ::IcoLib_ReleaseIcon(m_hIcon);
+}
+
+void CCtrlMButton::OnInit()
+{
+ CCtrlButton::OnInit();
+
+ SendMessage(m_hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)m_hIcon);
+ SendMessage(m_hwnd, BUTTONADDTOOLTIP, (WPARAM)m_toolTip, 0);
+ SendMessage(m_hwnd, BUTTONSETASFLATBTN, (WPARAM)m_toolTip, 0);
+}
+
+void CCtrlMButton::MakeFlat()
+{
+ SendMessage(m_hwnd, BUTTONSETASFLATBTN, TRUE, 0);
+}
+
+void CCtrlMButton::MakePush()
+{
+ SendMessage(m_hwnd, BUTTONSETASPUSHBTN, TRUE, 0);
+}
diff --git a/src/mir_core/src/Linux/CCtrlPages.cpp b/src/mir_core/src/Linux/CCtrlPages.cpp
index 512c32e142..c2a95553c5 100644
--- a/src/mir_core/src/Linux/CCtrlPages.cpp
+++ b/src/mir_core/src/Linux/CCtrlPages.cpp
@@ -1,411 +1,411 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-static volatile long g_order = 1;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlPages
-
-struct CCtrlPages::TPageInfo : public MZeroedObject
-{
- TPageInfo()
- {
- m_iOrder = InterlockedIncrement(&g_order);
- }
-
- ~TPageInfo()
- {
- if (m_hIcon)
- DestroyIcon(m_hIcon);
- }
-
- int m_iOrder;
- ptrW m_ptszHeader;
- HICON m_hIcon;
- bool m_bChanged, m_bScheduledResize;
- CDlgBase *m_pDlg;
-};
-
-CCtrlPages::CCtrlPages(CDlgBase *dlg, int ctrlId)
- : CCtrlBase(dlg, ctrlId),
- m_hIml(nullptr),
- m_pActivePage(nullptr),
- m_pages(4, NumericKeySortT)
-{}
-
-void CCtrlPages::OnInit()
-{
- CSuper::OnInit();
- Subclass();
-
- for (auto &it : m_pages)
- InsertPage(it);
- m_pages.destroy();
-
- ::SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, ::GetWindowLongPtr(m_hwnd, GWL_EXSTYLE) | WS_EX_CONTROLPARENT);
-
- TPageInfo *info = GetCurrPage();
- if (info) {
- m_pActivePage = info->m_pDlg;
- ShowPage(m_pActivePage);
-
- PSHNOTIFY pshn;
- pshn.hdr.code = PSN_INFOCHANGED;
- pshn.hdr.hwndFrom = m_pActivePage->GetHwnd();
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
- SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
- }
-}
-
-LRESULT CCtrlPages::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- int tabCount;
-
- switch (msg) {
- case WM_SIZE:
- if (TPageInfo *pCurrInfo = GetCurrPage()) {
- tabCount = GetCount();
- for (int i = 0; i < tabCount; i++) {
- TPageInfo *p = GetItemPage(i);
- if (p == nullptr)
- continue;
- if (p == pCurrInfo) {
- RECT rc;
- GetClientRect(m_hwnd, &rc);
- TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
- SetWindowPos(p->m_pDlg->GetHwnd(), nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
- }
- else p->m_bScheduledResize = true;
- }
- }
- break;
-
- case PSM_CHANGED:
- if (TPageInfo *info = GetCurrPage())
- info->m_bChanged = TRUE;
- return TRUE;
-
- case PSM_FORCECHANGED:
- tabCount = GetCount();
-
- PSHNOTIFY pshn;
- pshn.hdr.code = PSN_INFOCHANGED;
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
- for (int i = 0; i < tabCount; i++) {
- TPageInfo *p = GetItemPage(i);
- if (p) {
- pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
- if (pshn.hdr.hwndFrom != nullptr)
- SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
- }
- }
- break;
- }
-
- return CSuper::CustomWndProc(msg, wParam, lParam);
-}
-
-void CCtrlPages::AddPage(const wchar_t *ptszName, HICON hIcon, CDlgBase *pDlg)
-{
- TPageInfo *info = new TPageInfo;
- info->m_pDlg = pDlg;
- info->m_hIcon = hIcon;
- info->m_ptszHeader = mir_wstrdup(ptszName);
-
- if (m_hwnd != nullptr) {
- InsertPage(info);
-
- if (GetCount() == 1) {
- m_pActivePage = info->m_pDlg;
- ShowPage(m_pActivePage);
- }
- }
- m_pages.insert(info);
-}
-
-void CCtrlPages::ActivatePage(int iPage)
-{
- TPageInfo *info = GetItemPage(iPage);
- if (info == nullptr || info->m_pDlg == nullptr)
- return;
-
- if (m_pActivePage != nullptr)
- ShowWindow(m_pActivePage->GetHwnd(), SW_HIDE);
-
- m_pActivePage = info->m_pDlg;
- if (m_pActivePage->GetHwnd() && info->m_bScheduledResize) {
- RECT rc;
- GetClientRect(m_hwnd, &rc);
- TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
- SetWindowPos(m_pActivePage->GetHwnd(), nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
- }
-
- TabCtrl_SetCurSel(m_hwnd, iPage);
- ShowPage(m_pActivePage);
- ::SendMessage(m_pActivePage->GetHwnd(), WM_MOUSEACTIVATE, 0, 0);
-}
-
-void CCtrlPages::CheckRowCount()
-{
- int iRowCount = TabCtrl_GetRowCount(m_hwnd);
- if (m_numRows != iRowCount) {
- m_numRows = iRowCount;
- for (auto &p : m_pages)
- p->m_bScheduledResize = true;
- }
-}
-
-int CCtrlPages::GetCount()
-{
- return TabCtrl_GetItemCount(m_hwnd);
-}
-
-CDlgBase* CCtrlPages::GetNthPage(int iPage)
-{
- TPageInfo *info = GetItemPage(iPage);
- return (info == nullptr) ? nullptr : info->m_pDlg;
-}
-
-CCtrlPages::TPageInfo* CCtrlPages::GetCurrPage()
-{
- TCITEM tci = { 0 };
- tci.mask = TCIF_PARAM;
- if (!TabCtrl_GetItem(m_hwnd, TabCtrl_GetCurSel(m_hwnd), &tci))
- return nullptr;
-
- return (TPageInfo*)tci.lParam;
-}
-
-CCtrlPages::TPageInfo* CCtrlPages::GetItemPage(int iPage)
-{
- TCITEM tci = { 0 };
- tci.mask = TCIF_PARAM;
- if (!TabCtrl_GetItem(m_hwnd, iPage, &tci))
- return nullptr;
-
- return (TPageInfo*)tci.lParam;
-}
-
-int CCtrlPages::GetDlgIndex(CDlgBase *pDlg)
-{
- int tabCount = TabCtrl_GetItemCount(m_hwnd);
- for (int i = 0; i < tabCount; i++) {
- TCITEM tci;
- tci.mask = TCIF_PARAM | TCIF_IMAGE;
- TabCtrl_GetItem(m_hwnd, i, &tci);
- TPageInfo *pPage = (TPageInfo *)tci.lParam;
- if (pPage == nullptr)
- continue;
-
- if (pPage->m_pDlg == pDlg)
- return i;
- }
-
- return -1;
-}
-
-void CCtrlPages::InsertPage(TPageInfo *pPage)
-{
- TCITEM tci = { 0 };
- tci.mask = TCIF_PARAM | TCIF_TEXT;
- tci.lParam = (LPARAM)pPage;
- tci.pszText = TranslateW_LP(pPage->m_ptszHeader);
- if (pPage->m_hIcon) {
- if (!m_hIml) {
- m_hIml = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1);
- TabCtrl_SetImageList(m_hwnd, m_hIml);
- }
-
- tci.mask |= TCIF_IMAGE;
- tci.iImage = ImageList_AddIcon(m_hIml, pPage->m_hIcon);
- }
-
- TabCtrl_InsertItem(m_hwnd, TabCtrl_GetItemCount(m_hwnd), &tci);
-
- CheckRowCount();
-}
-
-void CCtrlPages::RemovePage(int iPage)
-{
- TPageInfo *p = GetItemPage(iPage);
- if (p == nullptr)
- return;
-
- TabCtrl_DeleteItem(m_hwnd, iPage);
- m_pages.remove(p);
- delete p;
-
- CheckRowCount();
-}
-
-void CCtrlPages::ShowPage(CDlgBase *pDlg)
-{
- if (pDlg->GetHwnd() == nullptr) {
- pDlg->SetParent(m_hwnd);
- pDlg->Create();
-
- RECT rc;
- GetClientRect(m_hwnd, &rc);
- TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
- SetWindowPos(pDlg->GetHwnd(), HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE);
-
- EnableThemeDialogTexture(pDlg->GetHwnd(), ETDT_ENABLETAB);
-
- PSHNOTIFY pshn;
- pshn.hdr.code = PSN_INFOCHANGED;
- pshn.hdr.hwndFrom = pDlg->GetHwnd();
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
- SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
- }
- ShowWindow(pDlg->GetHwnd(), SW_SHOW);
-}
-
-void CCtrlPages::SwapPages(int idx1, int idx2)
-{
- TPageInfo *p1 = GetItemPage(idx1), *p2 = GetItemPage(idx2);
- if (p1 == nullptr || p2 == nullptr)
- return;
-
- TabCtrl_DeleteItem(m_hwnd, idx1);
-
- TCITEM tci = { 0 };
- tci.mask = TCIF_PARAM | TCIF_TEXT;
- tci.lParam = (LPARAM)p1;
- tci.pszText = TranslateW_LP(p1->m_ptszHeader);
- TabCtrl_InsertItem(m_hwnd, idx2, &tci);
-}
-
-BOOL CCtrlPages::OnNotify(int /*idCtrl*/, NMHDR *pnmh)
-{
- TPageInfo *info;
- PSHNOTIFY pshn;
-
- switch (pnmh->code) {
- case TCN_SELCHANGING:
- if (info = GetCurrPage()) {
- pshn.hdr.code = PSN_KILLACTIVE;
- pshn.hdr.hwndFrom = info->m_pDlg->GetHwnd();
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
- if (SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn)) {
- SetWindowLongPtr(GetParent()->GetHwnd(), DWLP_MSGRESULT, TRUE);
- return TRUE;
- }
- }
- return TRUE;
-
- case TCN_SELCHANGE:
- if (m_pActivePage != nullptr)
- m_pActivePage->Hide();
-
- if (info = GetCurrPage()) {
- m_pActivePage = info->m_pDlg;
- ShowPage(m_pActivePage);
- }
- else m_pActivePage = nullptr;
- return TRUE;
- }
-
- return FALSE;
-}
-
-void CCtrlPages::OnReset()
-{
- CSuper::OnReset();
-
- PSHNOTIFY pshn;
- pshn.hdr.code = PSN_INFOCHANGED;
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
-
- int tabCount = GetCount();
- for (int i = 0; i < tabCount; i++) {
- TPageInfo *p = GetItemPage(i);
- if (p->m_pDlg->GetHwnd() == nullptr || !p->m_bChanged)
- continue;
-
- pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
- SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
- }
-}
-
-bool CCtrlPages::OnApply()
-{
- PSHNOTIFY pshn;
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
-
- if (m_pActivePage != nullptr) {
- pshn.hdr.code = PSN_KILLACTIVE;
- pshn.hdr.hwndFrom = m_pActivePage->GetHwnd();
- if (SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn))
- return false;
- }
-
- pshn.hdr.code = PSN_APPLY;
- int tabCount = GetCount();
- for (int i = 0; i < tabCount; i++) {
- TPageInfo *p = GetItemPage(i);
- if (p->m_pDlg->GetHwnd() == nullptr || !p->m_bChanged)
- continue;
-
- pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
- SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
- if (GetWindowLongPtr(pshn.hdr.hwndFrom, DWLP_MSGRESULT) == PSNRET_INVALID_NOCHANGEPAGE) {
- TabCtrl_SetCurSel(m_hwnd, i);
- if (m_pActivePage != nullptr)
- m_pActivePage->Hide();
- m_pActivePage = p->m_pDlg;
- m_pActivePage->Show();
- return false;
- }
- }
-
- CSuper::OnApply();
- return true;
-}
-
-void CCtrlPages::OnDestroy()
-{
- int tabCount = GetCount();
- for (int i = 0; i < tabCount; i++) {
- TPageInfo *p = GetItemPage(i);
- CDlgBase *pDlg = p->m_pDlg; p->m_pDlg = nullptr;
- if (pDlg->GetHwnd())
- pDlg->Close();
- delete p;
- }
-
- TabCtrl_DeleteAllItems(m_hwnd);
-
- if (m_hIml) {
- TabCtrl_SetImageList(m_hwnd, nullptr);
- ImageList_Destroy(m_hIml);
- }
-
- CSuper::OnDestroy();
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+static volatile long g_order = 1;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlPages
+
+struct CCtrlPages::TPageInfo : public MZeroedObject
+{
+ TPageInfo()
+ {
+ m_iOrder = InterlockedIncrement(&g_order);
+ }
+
+ ~TPageInfo()
+ {
+ if (m_hIcon)
+ DestroyIcon(m_hIcon);
+ }
+
+ int m_iOrder;
+ ptrW m_ptszHeader;
+ HICON m_hIcon;
+ bool m_bChanged, m_bScheduledResize;
+ CDlgBase *m_pDlg;
+};
+
+CCtrlPages::CCtrlPages(CDlgBase *dlg, int ctrlId)
+ : CCtrlBase(dlg, ctrlId),
+ m_hIml(nullptr),
+ m_pActivePage(nullptr),
+ m_pages(4, NumericKeySortT)
+{}
+
+void CCtrlPages::OnInit()
+{
+ CSuper::OnInit();
+ Subclass();
+
+ for (auto &it : m_pages)
+ InsertPage(it);
+ m_pages.destroy();
+
+ ::SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, ::GetWindowLongPtr(m_hwnd, GWL_EXSTYLE) | WS_EX_CONTROLPARENT);
+
+ TPageInfo *info = GetCurrPage();
+ if (info) {
+ m_pActivePage = info->m_pDlg;
+ ShowPage(m_pActivePage);
+
+ PSHNOTIFY pshn;
+ pshn.hdr.code = PSN_INFOCHANGED;
+ pshn.hdr.hwndFrom = m_pActivePage->GetHwnd();
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+ SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
+ }
+}
+
+LRESULT CCtrlPages::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int tabCount;
+
+ switch (msg) {
+ case WM_SIZE:
+ if (TPageInfo *pCurrInfo = GetCurrPage()) {
+ tabCount = GetCount();
+ for (int i = 0; i < tabCount; i++) {
+ TPageInfo *p = GetItemPage(i);
+ if (p == nullptr)
+ continue;
+ if (p == pCurrInfo) {
+ RECT rc;
+ GetClientRect(m_hwnd, &rc);
+ TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
+ SetWindowPos(p->m_pDlg->GetHwnd(), nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+ else p->m_bScheduledResize = true;
+ }
+ }
+ break;
+
+ case PSM_CHANGED:
+ if (TPageInfo *info = GetCurrPage())
+ info->m_bChanged = TRUE;
+ return TRUE;
+
+ case PSM_FORCECHANGED:
+ tabCount = GetCount();
+
+ PSHNOTIFY pshn;
+ pshn.hdr.code = PSN_INFOCHANGED;
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+ for (int i = 0; i < tabCount; i++) {
+ TPageInfo *p = GetItemPage(i);
+ if (p) {
+ pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
+ if (pshn.hdr.hwndFrom != nullptr)
+ SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
+ }
+ }
+ break;
+ }
+
+ return CSuper::CustomWndProc(msg, wParam, lParam);
+}
+
+void CCtrlPages::AddPage(const wchar_t *ptszName, HICON hIcon, CDlgBase *pDlg)
+{
+ TPageInfo *info = new TPageInfo;
+ info->m_pDlg = pDlg;
+ info->m_hIcon = hIcon;
+ info->m_ptszHeader = mir_wstrdup(ptszName);
+
+ if (m_hwnd != nullptr) {
+ InsertPage(info);
+
+ if (GetCount() == 1) {
+ m_pActivePage = info->m_pDlg;
+ ShowPage(m_pActivePage);
+ }
+ }
+ m_pages.insert(info);
+}
+
+void CCtrlPages::ActivatePage(int iPage)
+{
+ TPageInfo *info = GetItemPage(iPage);
+ if (info == nullptr || info->m_pDlg == nullptr)
+ return;
+
+ if (m_pActivePage != nullptr)
+ ShowWindow(m_pActivePage->GetHwnd(), SW_HIDE);
+
+ m_pActivePage = info->m_pDlg;
+ if (m_pActivePage->GetHwnd() && info->m_bScheduledResize) {
+ RECT rc;
+ GetClientRect(m_hwnd, &rc);
+ TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
+ SetWindowPos(m_pActivePage->GetHwnd(), nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+
+ TabCtrl_SetCurSel(m_hwnd, iPage);
+ ShowPage(m_pActivePage);
+ ::SendMessage(m_pActivePage->GetHwnd(), WM_MOUSEACTIVATE, 0, 0);
+}
+
+void CCtrlPages::CheckRowCount()
+{
+ int iRowCount = TabCtrl_GetRowCount(m_hwnd);
+ if (m_numRows != iRowCount) {
+ m_numRows = iRowCount;
+ for (auto &p : m_pages)
+ p->m_bScheduledResize = true;
+ }
+}
+
+int CCtrlPages::GetCount()
+{
+ return TabCtrl_GetItemCount(m_hwnd);
+}
+
+CDlgBase* CCtrlPages::GetNthPage(int iPage)
+{
+ TPageInfo *info = GetItemPage(iPage);
+ return (info == nullptr) ? nullptr : info->m_pDlg;
+}
+
+CCtrlPages::TPageInfo* CCtrlPages::GetCurrPage()
+{
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM;
+ if (!TabCtrl_GetItem(m_hwnd, TabCtrl_GetCurSel(m_hwnd), &tci))
+ return nullptr;
+
+ return (TPageInfo*)tci.lParam;
+}
+
+CCtrlPages::TPageInfo* CCtrlPages::GetItemPage(int iPage)
+{
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM;
+ if (!TabCtrl_GetItem(m_hwnd, iPage, &tci))
+ return nullptr;
+
+ return (TPageInfo*)tci.lParam;
+}
+
+int CCtrlPages::GetDlgIndex(CDlgBase *pDlg)
+{
+ int tabCount = TabCtrl_GetItemCount(m_hwnd);
+ for (int i = 0; i < tabCount; i++) {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM | TCIF_IMAGE;
+ TabCtrl_GetItem(m_hwnd, i, &tci);
+ TPageInfo *pPage = (TPageInfo *)tci.lParam;
+ if (pPage == nullptr)
+ continue;
+
+ if (pPage->m_pDlg == pDlg)
+ return i;
+ }
+
+ return -1;
+}
+
+void CCtrlPages::InsertPage(TPageInfo *pPage)
+{
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM | TCIF_TEXT;
+ tci.lParam = (LPARAM)pPage;
+ tci.pszText = TranslateW_LP(pPage->m_ptszHeader);
+ if (pPage->m_hIcon) {
+ if (!m_hIml) {
+ m_hIml = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1);
+ TabCtrl_SetImageList(m_hwnd, m_hIml);
+ }
+
+ tci.mask |= TCIF_IMAGE;
+ tci.iImage = ImageList_AddIcon(m_hIml, pPage->m_hIcon);
+ }
+
+ TabCtrl_InsertItem(m_hwnd, TabCtrl_GetItemCount(m_hwnd), &tci);
+
+ CheckRowCount();
+}
+
+void CCtrlPages::RemovePage(int iPage)
+{
+ TPageInfo *p = GetItemPage(iPage);
+ if (p == nullptr)
+ return;
+
+ TabCtrl_DeleteItem(m_hwnd, iPage);
+ m_pages.remove(p);
+ delete p;
+
+ CheckRowCount();
+}
+
+void CCtrlPages::ShowPage(CDlgBase *pDlg)
+{
+ if (pDlg->GetHwnd() == nullptr) {
+ pDlg->SetParent(m_hwnd);
+ pDlg->Create();
+
+ RECT rc;
+ GetClientRect(m_hwnd, &rc);
+ TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
+ SetWindowPos(pDlg->GetHwnd(), HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE);
+
+ EnableThemeDialogTexture(pDlg->GetHwnd(), ETDT_ENABLETAB);
+
+ PSHNOTIFY pshn;
+ pshn.hdr.code = PSN_INFOCHANGED;
+ pshn.hdr.hwndFrom = pDlg->GetHwnd();
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+ SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
+ }
+ ShowWindow(pDlg->GetHwnd(), SW_SHOW);
+}
+
+void CCtrlPages::SwapPages(int idx1, int idx2)
+{
+ TPageInfo *p1 = GetItemPage(idx1), *p2 = GetItemPage(idx2);
+ if (p1 == nullptr || p2 == nullptr)
+ return;
+
+ TabCtrl_DeleteItem(m_hwnd, idx1);
+
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM | TCIF_TEXT;
+ tci.lParam = (LPARAM)p1;
+ tci.pszText = TranslateW_LP(p1->m_ptszHeader);
+ TabCtrl_InsertItem(m_hwnd, idx2, &tci);
+}
+
+BOOL CCtrlPages::OnNotify(int /*idCtrl*/, NMHDR *pnmh)
+{
+ TPageInfo *info;
+ PSHNOTIFY pshn;
+
+ switch (pnmh->code) {
+ case TCN_SELCHANGING:
+ if (info = GetCurrPage()) {
+ pshn.hdr.code = PSN_KILLACTIVE;
+ pshn.hdr.hwndFrom = info->m_pDlg->GetHwnd();
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+ if (SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn)) {
+ SetWindowLongPtr(GetParent()->GetHwnd(), DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ }
+ return TRUE;
+
+ case TCN_SELCHANGE:
+ if (m_pActivePage != nullptr)
+ m_pActivePage->Hide();
+
+ if (info = GetCurrPage()) {
+ m_pActivePage = info->m_pDlg;
+ ShowPage(m_pActivePage);
+ }
+ else m_pActivePage = nullptr;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void CCtrlPages::OnReset()
+{
+ CSuper::OnReset();
+
+ PSHNOTIFY pshn;
+ pshn.hdr.code = PSN_INFOCHANGED;
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+
+ int tabCount = GetCount();
+ for (int i = 0; i < tabCount; i++) {
+ TPageInfo *p = GetItemPage(i);
+ if (p->m_pDlg->GetHwnd() == nullptr || !p->m_bChanged)
+ continue;
+
+ pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
+ SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
+ }
+}
+
+bool CCtrlPages::OnApply()
+{
+ PSHNOTIFY pshn;
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+
+ if (m_pActivePage != nullptr) {
+ pshn.hdr.code = PSN_KILLACTIVE;
+ pshn.hdr.hwndFrom = m_pActivePage->GetHwnd();
+ if (SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn))
+ return false;
+ }
+
+ pshn.hdr.code = PSN_APPLY;
+ int tabCount = GetCount();
+ for (int i = 0; i < tabCount; i++) {
+ TPageInfo *p = GetItemPage(i);
+ if (p->m_pDlg->GetHwnd() == nullptr || !p->m_bChanged)
+ continue;
+
+ pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
+ SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
+ if (GetWindowLongPtr(pshn.hdr.hwndFrom, DWLP_MSGRESULT) == PSNRET_INVALID_NOCHANGEPAGE) {
+ TabCtrl_SetCurSel(m_hwnd, i);
+ if (m_pActivePage != nullptr)
+ m_pActivePage->Hide();
+ m_pActivePage = p->m_pDlg;
+ m_pActivePage->Show();
+ return false;
+ }
+ }
+
+ CSuper::OnApply();
+ return true;
+}
+
+void CCtrlPages::OnDestroy()
+{
+ int tabCount = GetCount();
+ for (int i = 0; i < tabCount; i++) {
+ TPageInfo *p = GetItemPage(i);
+ CDlgBase *pDlg = p->m_pDlg; p->m_pDlg = nullptr;
+ if (pDlg->GetHwnd())
+ pDlg->Close();
+ delete p;
+ }
+
+ TabCtrl_DeleteAllItems(m_hwnd);
+
+ if (m_hIml) {
+ TabCtrl_SetImageList(m_hwnd, nullptr);
+ ImageList_Destroy(m_hIml);
+ }
+
+ CSuper::OnDestroy();
+}
diff --git a/src/mir_core/src/Linux/CCtrlSlider.cpp b/src/mir_core/src/Linux/CCtrlSlider.cpp
index 69aeb24796..9938736e42 100644
--- a/src/mir_core/src/Linux/CCtrlSlider.cpp
+++ b/src/mir_core/src/Linux/CCtrlSlider.cpp
@@ -1,70 +1,70 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlSlider class
-
-CCtrlSlider::CCtrlSlider(CDlgBase *dlg, int ctrlId, int wMax, int wMin) :
- CCtrlData(dlg, ctrlId),
- m_wMin(wMin),
- m_wMax(wMax)
-{
- m_bNotifiable = true;
-}
-
-BOOL CCtrlSlider::OnCommand(HWND, uint16_t, uint16_t idCode)
-{
- if (idCode == WM_HSCROLL) {
- NotifyChange();
- return TRUE;
- }
- return FALSE;
-}
-
-bool CCtrlSlider::OnApply()
-{
- CSuper::OnApply();
-
- if (m_dbLink != nullptr)
- SaveInt(GetPosition());
- return true;
-}
-
-void CCtrlSlider::OnReset()
-{
- SendMsg(TBM_SETRANGE, 0, MAKELONG(m_wMin, m_wMax));
-
- if (m_dbLink != nullptr)
- SetPosition(LoadInt());
-}
-
-int CCtrlSlider::GetPosition() const
-{
- return SendMsg(TBM_GETPOS, 0, 0);
-}
-
-void CCtrlSlider::SetPosition(int wPos)
-{
- SendMsg(TBM_SETPOS, TRUE, wPos);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlSlider class
+
+CCtrlSlider::CCtrlSlider(CDlgBase *dlg, int ctrlId, int wMax, int wMin) :
+ CCtrlData(dlg, ctrlId),
+ m_wMin(wMin),
+ m_wMax(wMax)
+{
+ m_bNotifiable = true;
+}
+
+BOOL CCtrlSlider::OnCommand(HWND, uint16_t, uint16_t idCode)
+{
+ if (idCode == WM_HSCROLL) {
+ NotifyChange();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool CCtrlSlider::OnApply()
+{
+ CSuper::OnApply();
+
+ if (m_dbLink != nullptr)
+ SaveInt(GetPosition());
+ return true;
+}
+
+void CCtrlSlider::OnReset()
+{
+ SendMsg(TBM_SETRANGE, 0, MAKELONG(m_wMin, m_wMax));
+
+ if (m_dbLink != nullptr)
+ SetPosition(LoadInt());
+}
+
+int CCtrlSlider::GetPosition() const
+{
+ return SendMsg(TBM_GETPOS, 0, 0);
+}
+
+void CCtrlSlider::SetPosition(int wPos)
+{
+ SendMsg(TBM_SETPOS, TRUE, wPos);
+}
diff --git a/src/mir_core/src/Linux/CCtrlSpin.cpp b/src/mir_core/src/Linux/CCtrlSpin.cpp
index 54d43e933a..54dc5ffd07 100644
--- a/src/mir_core/src/Linux/CCtrlSpin.cpp
+++ b/src/mir_core/src/Linux/CCtrlSpin.cpp
@@ -1,81 +1,81 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlSpin class
-
-CCtrlSpin::CCtrlSpin(CDlgBase *dlg, int ctrlId, int16_t wMax, int16_t wMin) :
- CCtrlData(dlg, ctrlId),
- m_wMin(wMin),
- m_wMax(wMax),
- m_wCurr(0)
-{}
-
-BOOL CCtrlSpin::OnNotify(int, NMHDR *pnmh)
-{
- if (pnmh->code == UDN_DELTAPOS) {
- auto *pEvent = (NMUPDOWN *)pnmh;
- m_wCurr = pEvent->iPos + pEvent->iDelta;
-
- NotifyChange();
- return TRUE;
- }
- return FALSE;
-}
-
-bool CCtrlSpin::OnApply()
-{
- CSuper::OnApply();
-
- m_wCurr = SendMsg(UDM_GETPOS, 0, 0);
- if (m_dbLink != nullptr)
- SaveInt(m_wCurr);
-
- HWND hwndBuddy = (HWND)SendMsg(UDM_GETBUDDY, 0, 0);
- if (hwndBuddy) {
- wchar_t buf[100];
- _itow(m_wCurr, buf, 10);
- ::SendMessage(hwndBuddy, WM_SETTEXT, 0, LPARAM(buf));
- }
-
- return true;
-}
-
-void CCtrlSpin::OnReset()
-{
- SendMsg(UDM_SETRANGE, 0, MAKELPARAM(m_wMax, m_wMin));
-
- if (m_dbLink != nullptr)
- SetPosition(LoadInt());
-}
-
-int16_t CCtrlSpin::GetPosition()
-{
- return m_wCurr;
-}
-
-void CCtrlSpin::SetPosition(int16_t wPos)
-{
- SendMsg(UDM_SETPOS, 0, m_wCurr = wPos);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlSpin class
+
+CCtrlSpin::CCtrlSpin(CDlgBase *dlg, int ctrlId, int16_t wMax, int16_t wMin) :
+ CCtrlData(dlg, ctrlId),
+ m_wMin(wMin),
+ m_wMax(wMax),
+ m_wCurr(0)
+{}
+
+BOOL CCtrlSpin::OnNotify(int, NMHDR *pnmh)
+{
+ if (pnmh->code == UDN_DELTAPOS) {
+ auto *pEvent = (NMUPDOWN *)pnmh;
+ m_wCurr = pEvent->iPos + pEvent->iDelta;
+
+ NotifyChange();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool CCtrlSpin::OnApply()
+{
+ CSuper::OnApply();
+
+ m_wCurr = SendMsg(UDM_GETPOS, 0, 0);
+ if (m_dbLink != nullptr)
+ SaveInt(m_wCurr);
+
+ HWND hwndBuddy = (HWND)SendMsg(UDM_GETBUDDY, 0, 0);
+ if (hwndBuddy) {
+ wchar_t buf[100];
+ _itow(m_wCurr, buf, 10);
+ ::SendMessage(hwndBuddy, WM_SETTEXT, 0, LPARAM(buf));
+ }
+
+ return true;
+}
+
+void CCtrlSpin::OnReset()
+{
+ SendMsg(UDM_SETRANGE, 0, MAKELPARAM(m_wMax, m_wMin));
+
+ if (m_dbLink != nullptr)
+ SetPosition(LoadInt());
+}
+
+int16_t CCtrlSpin::GetPosition()
+{
+ return m_wCurr;
+}
+
+void CCtrlSpin::SetPosition(int16_t wPos)
+{
+ SendMsg(UDM_SETPOS, 0, m_wCurr = wPos);
+}
diff --git a/src/mir_core/src/Linux/CCtrlTreeOpts.cpp b/src/mir_core/src/Linux/CCtrlTreeOpts.cpp
index 13a6b79bd3..f0b1be1fb9 100644
--- a/src/mir_core/src/Linux/CCtrlTreeOpts.cpp
+++ b/src/mir_core/src/Linux/CCtrlTreeOpts.cpp
@@ -1,216 +1,216 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_GRPOPEN, IMG_GRPCLOSED };
-
-CCtrlTreeOpts::CCtrlTreeOpts(CDlgBase* dlg, int ctrlId):
- CCtrlTreeView(dlg, ctrlId),
- m_options(5)
-{
-}
-
-CCtrlTreeOpts::~CCtrlTreeOpts()
-{
-}
-
-void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, CMOption<bool> &option)
-{
- auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::CMOPTION);
- p->m_option = &option;
- m_options.insert(p, m_options.getCount());
-}
-
-void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, bool &option)
-{
- auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::BOOL);
- p->m_pBool = &option;
- m_options.insert(p, m_options.getCount());
-}
-
-void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, uint32_t &option, uint32_t mask)
-{
- auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::MASK);
- p->m_pDword = &option;
- p->m_mask = mask;
- m_options.insert(p, m_options.getCount());
-}
-
-BOOL CCtrlTreeOpts::OnNotify(int idCtrl, NMHDR *pnmh)
-{
- switch (pnmh->code) {
- case TVN_KEYDOWN:
- {
- LPNMTVKEYDOWN lpnmtvkd = (LPNMTVKEYDOWN)pnmh;
- HTREEITEM hti;
- if ((lpnmtvkd->wVKey == VK_SPACE) && (hti = GetSelection()))
- ProcessItemClick(hti);
- }
- break;
-
- case NM_CLICK:
- TVHITTESTINFO htti;
- htti.pt.x = (short)LOWORD(GetMessagePos());
- htti.pt.y = (short)HIWORD(GetMessagePos());
- ScreenToClient(pnmh->hwndFrom, &htti.pt);
- if (HitTest(&htti))
- if (htti.flags & TVHT_ONITEMICON)
- ProcessItemClick(htti.hItem);
- break;
-
- case TVN_ITEMEXPANDED:
- LPNMTREEVIEW lpnmtv = (LPNMTREEVIEW)pnmh;
- TVITEM tvi;
- tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
- tvi.hItem = lpnmtv->itemNew.hItem;
- tvi.iImage = tvi.iSelectedImage = (lpnmtv->itemNew.state & TVIS_EXPANDED) ? IMG_GRPOPEN : IMG_GRPCLOSED;
- SendMessage(pnmh->hwndFrom, TVM_SETITEM, 0, (LPARAM)&tvi);
- break;
- }
-
- return CSuper::OnNotify(idCtrl, pnmh);
-}
-
-void CCtrlTreeOpts::OnInit()
-{
- CSuper::OnInit();
-
- SelectItem(nullptr);
- DeleteAllItems();
-
- HIMAGELIST hImgLst = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR | ILC_COLOR32 | ILC_MASK, 5, 1);
- ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_MIRANDA);
- ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_TICK);
- ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_NOTICK);
- ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_GROUPOPEN);
- ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_GROUPSHUT);
- SetImageList(hImgLst, TVSIL_NORMAL);
-
- /* build options tree. based on code from IcoLib */
- for (auto &it : m_options) {
- if (it->m_pwszSection) {
- HTREEITEM hSection = FindNamedItem(nullptr, it->m_pwszSection);
- if (!hSection) {
- TVINSERTSTRUCT tvis = {};
- tvis.hParent = hSection;
- tvis.hInsertAfter = TVI_LAST;
- tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
- tvis.item.pszText = (LPWSTR)it->m_pwszSection;
- tvis.item.state = tvis.item.stateMask = TVIS_EXPANDED | TVIS_BOLD;
- tvis.item.iImage = tvis.item.iSelectedImage = IMG_GRPOPEN;
- hSection = InsertItem(&tvis);
- }
-
- bool bValue;
- switch (it->m_type) {
- case COptionsItem::CMOPTION:
- bValue = *it->m_option;
- break;
- case COptionsItem::BOOL:
- bValue = *it->m_pBool;
- break;
- case COptionsItem::MASK:
- bValue = (*it->m_pDword & it->m_mask) != 0;
- break;
- default:
- continue;
- }
-
- TVINSERTSTRUCT tvis = {};
- tvis.hParent = hSection;
- tvis.hInsertAfter = TVI_LAST;
- tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
- tvis.item.pszText = (LPWSTR)it->m_pwszName;
- tvis.item.state = tvis.item.stateMask = TVIS_EXPANDED;
- tvis.item.lParam = m_options.indexOf(&it);
- tvis.item.iImage = tvis.item.iSelectedImage = (bValue) ? IMG_CHECK : IMG_NOCHECK;
-
- it->m_hItem = InsertItem(&tvis);
- }
- }
-
- TranslateTree();
- ShowWindow(m_hwnd, SW_SHOW);
- SelectItem(FindNamedItem(nullptr, nullptr));
-}
-
-void CCtrlTreeOpts::OnDestroy()
-{
- ImageList_Destroy(GetImageList(TVSIL_NORMAL));
-}
-
-bool CCtrlTreeOpts::OnApply()
-{
- CSuper::OnApply();
-
- for (auto &it : m_options) {
- TVITEMEX tvi;
- GetItem(it->m_hItem, &tvi);
-
- bool bValue = (tvi.iImage == IMG_CHECK);
- switch (it->m_type) {
- case COptionsItem::CMOPTION:
- *it->m_option = bValue;
- break;
- case COptionsItem::BOOL:
- *it->m_pBool = bValue;
- break;
- case COptionsItem::MASK:
- if (bValue)
- *it->m_pDword |= it->m_mask;
- else
- *it->m_pDword &= ~it->m_mask;
- break;
- }
- }
- return true;
-}
-
-void CCtrlTreeOpts::ProcessItemClick(HTREEITEM hti)
-{
- TVITEMEX tvi;
- GetItem(hti, &tvi);
- switch (tvi.iImage) {
- case IMG_GRPOPEN:
- tvi.iImage = tvi.iSelectedImage = IMG_GRPCLOSED;
- Expand(tvi.hItem, TVE_COLLAPSE);
- break;
-
- case IMG_GRPCLOSED:
- tvi.iImage = tvi.iSelectedImage = IMG_GRPOPEN;
- Expand(tvi.hItem, TVE_EXPAND);
- break;
-
- case IMG_CHECK:
- tvi.iImage = tvi.iSelectedImage = IMG_NOCHECK;
- NotifyChange();
- break;
-
- case IMG_NOCHECK:
- tvi.iImage = tvi.iSelectedImage = IMG_CHECK;
- NotifyChange();
- break;
- }
-
- SetItem(&tvi);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_GRPOPEN, IMG_GRPCLOSED };
+
+CCtrlTreeOpts::CCtrlTreeOpts(CDlgBase* dlg, int ctrlId):
+ CCtrlTreeView(dlg, ctrlId),
+ m_options(5)
+{
+}
+
+CCtrlTreeOpts::~CCtrlTreeOpts()
+{
+}
+
+void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, CMOption<bool> &option)
+{
+ auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::CMOPTION);
+ p->m_option = &option;
+ m_options.insert(p, m_options.getCount());
+}
+
+void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, bool &option)
+{
+ auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::BOOL);
+ p->m_pBool = &option;
+ m_options.insert(p, m_options.getCount());
+}
+
+void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, uint32_t &option, uint32_t mask)
+{
+ auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::MASK);
+ p->m_pDword = &option;
+ p->m_mask = mask;
+ m_options.insert(p, m_options.getCount());
+}
+
+BOOL CCtrlTreeOpts::OnNotify(int idCtrl, NMHDR *pnmh)
+{
+ switch (pnmh->code) {
+ case TVN_KEYDOWN:
+ {
+ LPNMTVKEYDOWN lpnmtvkd = (LPNMTVKEYDOWN)pnmh;
+ HTREEITEM hti;
+ if ((lpnmtvkd->wVKey == VK_SPACE) && (hti = GetSelection()))
+ ProcessItemClick(hti);
+ }
+ break;
+
+ case NM_CLICK:
+ TVHITTESTINFO htti;
+ htti.pt.x = (short)LOWORD(GetMessagePos());
+ htti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(pnmh->hwndFrom, &htti.pt);
+ if (HitTest(&htti))
+ if (htti.flags & TVHT_ONITEMICON)
+ ProcessItemClick(htti.hItem);
+ break;
+
+ case TVN_ITEMEXPANDED:
+ LPNMTREEVIEW lpnmtv = (LPNMTREEVIEW)pnmh;
+ TVITEM tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvi.hItem = lpnmtv->itemNew.hItem;
+ tvi.iImage = tvi.iSelectedImage = (lpnmtv->itemNew.state & TVIS_EXPANDED) ? IMG_GRPOPEN : IMG_GRPCLOSED;
+ SendMessage(pnmh->hwndFrom, TVM_SETITEM, 0, (LPARAM)&tvi);
+ break;
+ }
+
+ return CSuper::OnNotify(idCtrl, pnmh);
+}
+
+void CCtrlTreeOpts::OnInit()
+{
+ CSuper::OnInit();
+
+ SelectItem(nullptr);
+ DeleteAllItems();
+
+ HIMAGELIST hImgLst = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR | ILC_COLOR32 | ILC_MASK, 5, 1);
+ ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_MIRANDA);
+ ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_TICK);
+ ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_NOTICK);
+ ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_GROUPOPEN);
+ ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_GROUPSHUT);
+ SetImageList(hImgLst, TVSIL_NORMAL);
+
+ /* build options tree. based on code from IcoLib */
+ for (auto &it : m_options) {
+ if (it->m_pwszSection) {
+ HTREEITEM hSection = FindNamedItem(nullptr, it->m_pwszSection);
+ if (!hSection) {
+ TVINSERTSTRUCT tvis = {};
+ tvis.hParent = hSection;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvis.item.pszText = (LPWSTR)it->m_pwszSection;
+ tvis.item.state = tvis.item.stateMask = TVIS_EXPANDED | TVIS_BOLD;
+ tvis.item.iImage = tvis.item.iSelectedImage = IMG_GRPOPEN;
+ hSection = InsertItem(&tvis);
+ }
+
+ bool bValue;
+ switch (it->m_type) {
+ case COptionsItem::CMOPTION:
+ bValue = *it->m_option;
+ break;
+ case COptionsItem::BOOL:
+ bValue = *it->m_pBool;
+ break;
+ case COptionsItem::MASK:
+ bValue = (*it->m_pDword & it->m_mask) != 0;
+ break;
+ default:
+ continue;
+ }
+
+ TVINSERTSTRUCT tvis = {};
+ tvis.hParent = hSection;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvis.item.pszText = (LPWSTR)it->m_pwszName;
+ tvis.item.state = tvis.item.stateMask = TVIS_EXPANDED;
+ tvis.item.lParam = m_options.indexOf(&it);
+ tvis.item.iImage = tvis.item.iSelectedImage = (bValue) ? IMG_CHECK : IMG_NOCHECK;
+
+ it->m_hItem = InsertItem(&tvis);
+ }
+ }
+
+ TranslateTree();
+ ShowWindow(m_hwnd, SW_SHOW);
+ SelectItem(FindNamedItem(nullptr, nullptr));
+}
+
+void CCtrlTreeOpts::OnDestroy()
+{
+ ImageList_Destroy(GetImageList(TVSIL_NORMAL));
+}
+
+bool CCtrlTreeOpts::OnApply()
+{
+ CSuper::OnApply();
+
+ for (auto &it : m_options) {
+ TVITEMEX tvi;
+ GetItem(it->m_hItem, &tvi);
+
+ bool bValue = (tvi.iImage == IMG_CHECK);
+ switch (it->m_type) {
+ case COptionsItem::CMOPTION:
+ *it->m_option = bValue;
+ break;
+ case COptionsItem::BOOL:
+ *it->m_pBool = bValue;
+ break;
+ case COptionsItem::MASK:
+ if (bValue)
+ *it->m_pDword |= it->m_mask;
+ else
+ *it->m_pDword &= ~it->m_mask;
+ break;
+ }
+ }
+ return true;
+}
+
+void CCtrlTreeOpts::ProcessItemClick(HTREEITEM hti)
+{
+ TVITEMEX tvi;
+ GetItem(hti, &tvi);
+ switch (tvi.iImage) {
+ case IMG_GRPOPEN:
+ tvi.iImage = tvi.iSelectedImage = IMG_GRPCLOSED;
+ Expand(tvi.hItem, TVE_COLLAPSE);
+ break;
+
+ case IMG_GRPCLOSED:
+ tvi.iImage = tvi.iSelectedImage = IMG_GRPOPEN;
+ Expand(tvi.hItem, TVE_EXPAND);
+ break;
+
+ case IMG_CHECK:
+ tvi.iImage = tvi.iSelectedImage = IMG_NOCHECK;
+ NotifyChange();
+ break;
+
+ case IMG_NOCHECK:
+ tvi.iImage = tvi.iSelectedImage = IMG_CHECK;
+ NotifyChange();
+ break;
+ }
+
+ SetItem(&tvi);
+}
diff --git a/src/mir_core/src/Linux/CCtrlTreeView.cpp b/src/mir_core/src/Linux/CCtrlTreeView.cpp
index 390f1618fc..5d2174fc16 100644
--- a/src/mir_core/src/Linux/CCtrlTreeView.cpp
+++ b/src/mir_core/src/Linux/CCtrlTreeView.cpp
@@ -1,817 +1,817 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-int ImageList_AddIcon_IconLibLoaded(HIMAGELIST hIml, int iconId)
-{
- HICON hIcon = Skin_LoadIcon(iconId);
- int res = ImageList_AddIcon(hIml, hIcon);
- IcoLib_ReleaseIcon(hIcon);
- return res;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlTreeView
-
-CCtrlTreeView::CCtrlTreeView(CDlgBase *dlg, int ctrlId) :
- CCtrlBase(dlg, ctrlId),
- m_dwFlags(0),
- m_hDragItem(nullptr)
-{}
-
-void CCtrlTreeView::SetFlags(uint32_t dwFlags)
-{
- if (dwFlags & MTREE_CHECKBOX)
- m_bCheckBox = true;
-
- if (dwFlags & MTREE_MULTISELECT)
- m_bMultiSelect = true;
-
- if (dwFlags & MTREE_DND) {
- m_bDndEnabled = true;
- m_bDragging = false;
- m_hDragItem = nullptr;
- }
-}
-
-void CCtrlTreeView::OnInit()
-{
- CSuper::OnInit();
-
- Subclass();
-
- if (m_bCheckBox) {
- HIMAGELIST himlCheckBoxes = ::ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 2, 2);
- ::ImageList_AddIcon_IconLibLoaded(himlCheckBoxes, SKINICON_OTHER_NOTICK);
- ::ImageList_AddIcon_IconLibLoaded(himlCheckBoxes, SKINICON_OTHER_TICK);
- SetImageList(himlCheckBoxes, TVSIL_NORMAL);
- }
-}
-
-void CCtrlTreeView::OnDestroy()
-{
- if (m_bCheckBox)
- ::ImageList_Destroy(GetImageList(TVSIL_NORMAL));
-
- CSuper::OnDestroy();
-}
-
-HTREEITEM CCtrlTreeView::MoveItemAbove(HTREEITEM hItem, HTREEITEM hInsertAfter, HTREEITEM hParent)
-{
- if (hItem == nullptr || hInsertAfter == nullptr)
- return nullptr;
-
- if (hItem == hInsertAfter)
- return hItem;
-
- wchar_t name[128];
- TVINSERTSTRUCT tvis = {};
- tvis.itemex.mask = (UINT)-1;
- tvis.itemex.pszText = name;
- tvis.itemex.cchTextMax = _countof(name);
- tvis.itemex.hItem = hItem;
- if (!GetItem(&tvis.itemex))
- return nullptr;
-
- OBJLIST<TVINSERTSTRUCT> arChildren(1);
- for (HTREEITEM p = GetChild(hItem); p; p = GetNextSibling(p)) {
- wchar_t buf[128];
- TVINSERTSTRUCT tvis2 = {};
- tvis2.itemex.mask = (UINT)-1;
- tvis2.itemex.pszText = buf;
- tvis2.itemex.cchTextMax = _countof(buf);
- tvis2.itemex.hItem = p;
- if (GetItem(&tvis2.itemex)) {
- tvis2.itemex.pszText = mir_wstrdup(tvis2.itemex.pszText);
- arChildren.insert(new TVINSERTSTRUCT(tvis2));
-
- tvis2.itemex.lParam = 0;
- SetItem(&tvis2.itemex);
- }
- }
-
- // the pointed lParam will be freed inside TVN_DELETEITEM
- // so lets substitute it with 0
- LPARAM saveOldData = tvis.itemex.lParam;
- tvis.itemex.lParam = 0;
- SetItem(&tvis.itemex);
-
- // now current item contain lParam = 0 we can delete it. the memory will be kept.
- DeleteItem(hItem);
-
- for (auto &it : arChildren)
- DeleteItem(it->itemex.hItem);
-
- tvis.itemex.stateMask = tvis.itemex.state;
- tvis.itemex.lParam = saveOldData;
- tvis.hParent = hParent;
- tvis.hInsertAfter = hInsertAfter;
- auto hNewItem = InsertItem(&tvis);
-
- hInsertAfter = nullptr;
- for (auto &it : arChildren) {
- it->hParent = hNewItem;
- it->hInsertAfter = hInsertAfter;
- hInsertAfter = InsertItem(it);
-
- mir_free(it->itemex.pszText);
- }
-
- return hNewItem;
-}
-
-LRESULT CCtrlTreeView::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- TVHITTESTINFO hti;
-
- switch (msg) {
- case WM_MOUSEMOVE:
- if (m_bDragging) {
- hti.pt.x = (short)LOWORD(lParam);
- hti.pt.y = (short)HIWORD(lParam);
- HitTest(&hti);
- if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) {
- HTREEITEM it = hti.hItem;
- hti.pt.y -= GetItemHeight() / 2;
- HitTest(&hti);
- if (!(hti.flags & TVHT_ABOVE))
- SetInsertMark(hti.hItem, 1);
- else
- SetInsertMark(it, 0);
- }
- else {
- if (hti.flags & TVHT_ABOVE) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0);
- if (hti.flags & TVHT_BELOW) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0);
- SetInsertMark(nullptr, 0);
- }
- }
- break;
-
- case WM_LBUTTONUP:
- if (m_bDragging) {
- SetInsertMark(nullptr, 0);
- m_bDragging = false;
- ReleaseCapture();
-
- hti.pt.x = (short)LOWORD(lParam);
- hti.pt.y = (short)HIWORD(lParam) - GetItemHeight() / 2;
- HitTest(&hti);
- if (m_hDragItem == hti.hItem)
- break;
-
- if (hti.flags & TVHT_ABOVE)
- hti.hItem = TVI_FIRST;
- else if (hti.flags & TVHT_BELOW)
- hti.hItem = TVI_LAST;
-
- HTREEITEM insertAfter = hti.hItem, hParent;
- if (insertAfter != TVI_FIRST) {
- hParent = GetParent(insertAfter);
- if (GetChild(insertAfter) != nullptr) {
- hParent = insertAfter;
- insertAfter = TVI_FIRST;
- }
- }
- else hParent = nullptr;
-
- HTREEITEM FirstItem = nullptr;
- if (m_bMultiSelect) {
- LIST<_TREEITEM> arItems(10);
- GetSelected(arItems);
-
- // Proceed moving
- for (auto &it : arItems) {
- if (!insertAfter)
- break;
- if (GetParent(it) != hParent) // prevent subitems from being inserted at the same level
- continue;
-
- insertAfter = MoveItemAbove(it, insertAfter, hParent);
- if (it == arItems[0])
- FirstItem = insertAfter;
- }
- }
- else FirstItem = MoveItemAbove(m_hDragItem, insertAfter, hParent);
- if (FirstItem)
- SelectItem(FirstItem);
-
- NotifyChange();
- }
- break;
-
- case WM_LBUTTONDOWN:
- if (!m_bMultiSelect)
- break;
-
- hti.pt.x = (short)LOWORD(lParam);
- hti.pt.y = (short)HIWORD(lParam);
- if (!TreeView_HitTest(m_hwnd, &hti)) {
- UnselectAll();
- break;
- }
-
- if (!m_bDndEnabled)
- if (!(wParam & (MK_CONTROL | MK_SHIFT)) || !(hti.flags & (TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMRIGHT))) {
- UnselectAll();
- TreeView_SelectItem(m_hwnd, hti.hItem);
- break;
- }
-
- if (wParam & MK_CONTROL) {
- LIST<_TREEITEM> selected(1);
- GetSelected(selected);
-
- // Check if have to deselect it
- for (int i = 0; i < selected.getCount(); i++) {
- if (selected[i] == hti.hItem) {
- // Deselect it
- UnselectAll();
- selected.remove(i);
-
- if (i > 0)
- hti.hItem = selected[0];
- else if (i < selected.getCount())
- hti.hItem = selected[i];
- else
- hti.hItem = nullptr;
- break;
- }
- }
-
- TreeView_SelectItem(m_hwnd, hti.hItem);
- Select(selected);
- }
- else if (wParam & MK_SHIFT) {
- HTREEITEM hItem = TreeView_GetSelection(m_hwnd);
- if (hItem == nullptr)
- break;
-
- LIST<_TREEITEM> selected(1);
- GetSelected(selected);
-
- TreeView_SelectItem(m_hwnd, hti.hItem);
- Select(selected);
- SelectRange(hItem, hti.hItem);
- }
- break;
- }
-
- return CSuper::CustomWndProc(msg, wParam, lParam);
-}
-
-BOOL CCtrlTreeView::OnNotify(int, NMHDR *pnmh)
-{
- TEventInfo evt = { this, pnmh };
-
- switch (pnmh->code) {
- case NM_RCLICK: OnRightClick(&evt); return TRUE;
- case NM_CUSTOMDRAW: OnCustomDraw(&evt); return TRUE;
- case TVN_BEGINLABELEDIT: OnBeginLabelEdit(&evt); return TRUE;
- case TVN_BEGINRDRAG: OnBeginRDrag(&evt); return TRUE;
- case TVN_DELETEITEM: OnDeleteItem(&evt); return TRUE;
- case TVN_ENDLABELEDIT: OnEndLabelEdit(&evt); return TRUE;
- case TVN_GETDISPINFO: OnGetDispInfo(&evt); return TRUE;
- case TVN_GETINFOTIP: OnGetInfoTip(&evt); return TRUE;
- case TVN_ITEMEXPANDED: OnItemExpanded(&evt); return TRUE;
- case TVN_ITEMEXPANDING: OnItemExpanding(&evt); return TRUE;
- case TVN_SELCHANGED: OnSelChanged(&evt); return TRUE;
- case TVN_SELCHANGING: OnSelChanging(&evt); return TRUE;
- case TVN_SETDISPINFO: OnSetDispInfo(&evt); return TRUE;
- case TVN_SINGLEEXPAND: OnSingleExpand(&evt); return TRUE;
-
- case TVN_BEGINDRAG:
- OnBeginDrag(&evt);
-
- // user-defined can clear the event code to disable dragging
- if (m_bDndEnabled && pnmh->code) {
- ::SetCapture(m_hwnd);
- m_bDragging = true;
- m_hDragItem = evt.nmtv->itemNew.hItem;
- SelectItem(m_hDragItem);
- }
- return TRUE;
-
- case TVN_KEYDOWN:
- if (evt.nmtvkey->wVKey == VK_SPACE) {
- evt.hItem = GetSelection();
- if (m_bCheckBox)
- InvertCheck(evt.hItem);
- OnItemChanged(&evt);
- NotifyChange();
- }
-
- OnKeyDown(&evt);
- return TRUE;
- }
-
- if (pnmh->code == NM_CLICK) {
- TVHITTESTINFO hti;
- hti.pt.x = (short)LOWORD(GetMessagePos());
- hti.pt.y = (short)HIWORD(GetMessagePos());
- ScreenToClient(pnmh->hwndFrom, &hti.pt);
- if (HitTest(&hti)) {
- if (m_bCheckBox && (hti.flags & TVHT_ONITEMICON) || !m_bCheckBox && (hti.flags & TVHT_ONITEMSTATEICON)) {
- if (m_bCheckBox)
- InvertCheck(hti.hItem);
- else
- SelectItem(hti.hItem);
-
- evt.hItem = hti.hItem;
- OnItemChanged(&evt);
- NotifyChange();
- }
- }
- }
-
- return FALSE;
-}
-
-void CCtrlTreeView::InvertCheck(HTREEITEM hItem)
-{
- TVITEMEX tvi;
- tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATEEX;
- tvi.hItem = hItem;
- if (!GetItem(&tvi))
- return;
-
- if (IsWinVerVistaPlus() && (tvi.uStateEx & TVIS_EX_DISABLED))
- return;
-
- tvi.iImage = tvi.iSelectedImage = !tvi.iImage;
- SetItem(&tvi);
-
- SelectItem(hItem);
-}
-
-void CCtrlTreeView::TranslateItem(HTREEITEM hItem)
-{
- TVITEMEX tvi;
- wchar_t buf[128];
- GetItem(hItem, &tvi, buf, _countof(buf));
- tvi.pszText = TranslateW_LP(tvi.pszText);
- SetItem(&tvi);
-}
-
-void CCtrlTreeView::TranslateTree()
-{
- HTREEITEM hItem = GetRoot();
- while (hItem) {
- TranslateItem(hItem);
-
- HTREEITEM hItemTmp = nullptr;
- if (hItemTmp = GetChild(hItem))
- hItem = hItemTmp;
- else if (hItemTmp = GetNextSibling(hItem))
- hItem = hItemTmp;
- else {
- while (true) {
- if (!(hItem = GetParent(hItem)))
- break;
- if (hItemTmp = GetNextSibling(hItem)) {
- hItem = hItemTmp;
- break;
- }
- }
- }
- }
-}
-
-HTREEITEM CCtrlTreeView::FindNamedItem(HTREEITEM hItem, const wchar_t *name)
-{
- TVITEMEX tvi = { 0 };
- wchar_t str[MAX_PATH];
-
- if (hItem)
- tvi.hItem = GetChild(hItem);
- else
- tvi.hItem = GetRoot();
-
- if (!name)
- return tvi.hItem;
-
- tvi.mask = TVIF_TEXT;
- tvi.pszText = str;
- tvi.cchTextMax = _countof(str);
-
- while (tvi.hItem) {
- GetItem(&tvi);
-
- if (!mir_wstrcmp(tvi.pszText, name))
- return tvi.hItem;
-
- tvi.hItem = GetNextSibling(tvi.hItem);
- }
- return nullptr;
-}
-
-void CCtrlTreeView::GetItem(HTREEITEM hItem, TVITEMEX *tvi) const
-{
- memset(tvi, 0, sizeof(*tvi));
- tvi->mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_INTEGRAL | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE;
- tvi->hItem = hItem;
- GetItem(tvi);
-}
-
-void CCtrlTreeView::GetItem(HTREEITEM hItem, TVITEMEX *tvi, wchar_t *szText, int iTextLength) const
-{
- memset(tvi, 0, sizeof(*tvi));
- tvi->mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_INTEGRAL | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE | TVIF_TEXT;
- tvi->hItem = hItem;
- tvi->pszText = szText;
- tvi->cchTextMax = iTextLength;
- GetItem(tvi);
-}
-
-bool CCtrlTreeView::IsSelected(HTREEITEM hItem)
-{
- return (TVIS_SELECTED & TreeView_GetItemState(m_hwnd, hItem, TVIS_SELECTED)) == TVIS_SELECTED;
-}
-
-void CCtrlTreeView::Select(HTREEITEM hItem)
-{
- TreeView_SetItemState(m_hwnd, hItem, TVIS_SELECTED, TVIS_SELECTED);
-}
-
-void CCtrlTreeView::Unselect(HTREEITEM hItem)
-{
- TreeView_SetItemState(m_hwnd, hItem, 0, TVIS_SELECTED);
-}
-
-void CCtrlTreeView::DropHilite(HTREEITEM hItem)
-{
- TreeView_SetItemState(m_hwnd, hItem, TVIS_DROPHILITED, TVIS_DROPHILITED);
-}
-
-void CCtrlTreeView::DropUnhilite(HTREEITEM hItem)
-{
- TreeView_SetItemState(m_hwnd, hItem, 0, TVIS_DROPHILITED);
-}
-
-void CCtrlTreeView::SelectAll()
-{
- TreeView_SelectItem(m_hwnd, nullptr);
-
- HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
- while (hItem) {
- Select(hItem);
- hItem = TreeView_GetNextSibling(m_hwnd, hItem);
- }
-}
-
-void CCtrlTreeView::UnselectAll()
-{
- TreeView_SelectItem(m_hwnd, nullptr);
-
- HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
- while (hItem) {
- Unselect(hItem);
- hItem = TreeView_GetNextSibling(m_hwnd, hItem);
- }
-}
-
-void CCtrlTreeView::SelectRange(HTREEITEM hStart, HTREEITEM hEnd)
-{
- int start = 0, end = 0, i = 0;
- HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
- while (hItem) {
- if (hItem == hStart)
- start = i;
- if (hItem == hEnd)
- end = i;
-
- i++;
- hItem = TreeView_GetNextSibling(m_hwnd, hItem);
- }
-
- if (end < start) {
- int tmp = start;
- start = end;
- end = tmp;
- }
-
- i = 0;
- hItem = TreeView_GetRoot(m_hwnd);
- while (hItem) {
- if (i >= start)
- Select(hItem);
- if (i == end)
- break;
-
- i++;
- hItem = TreeView_GetNextSibling(m_hwnd, hItem);
- }
-}
-
-int CCtrlTreeView::GetNumSelected()
-{
- int ret = 0;
- for (HTREEITEM hItem = TreeView_GetRoot(m_hwnd); hItem; hItem = TreeView_GetNextSibling(m_hwnd, hItem))
- if (IsSelected(hItem))
- ret++;
-
- return ret;
-}
-
-void CCtrlTreeView::GetSelected(LIST<_TREEITEM> &selected)
-{
- HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
- while (hItem) {
- if (IsSelected(hItem))
- selected.insert(hItem);
- hItem = TreeView_GetNextSibling(m_hwnd, hItem);
- }
-}
-
-void CCtrlTreeView::Select(LIST<_TREEITEM> &selected)
-{
- for (auto &it : selected)
- if (it != nullptr)
- Select(it);
-}
-
-void CCtrlTreeView::GetCaretPos(CContextMenuPos &pos) const
-{
- pos.pCtrl = this;
-
- // position is empty, let's fill it using selection
- if (pos.pt.x == 0 && pos.pt.y == 0) {
- HTREEITEM hItem = GetSelection();
- if (hItem != nullptr) {
- pos.pCtrl = this;
- pos.hItem = hItem;
-
- RECT rc;
- GetItemRect(hItem, &rc, TRUE);
- pos.pt.x = rc.left + 8;
- pos.pt.y = rc.top + 8;
- ClientToScreen(m_hwnd, &pos.pt);
- return;
- }
- }
- // position is present, let's calculate current item
- else {
- TVHITTESTINFO hti;
- hti.pt = pos.pt;
- ScreenToClient(m_hwnd, &hti.pt);
- if (HitTest(&hti) && (hti.flags & TVHT_ONITEM)) {
- pos.hItem = hti.hItem;
- return;
- }
- }
-
- CSuper::GetCaretPos(pos);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-HIMAGELIST CCtrlTreeView::CreateDragImage(HTREEITEM hItem)
-{ return TreeView_CreateDragImage(m_hwnd, hItem);
-}
-
-void CCtrlTreeView::DeleteAllItems()
-{ TreeView_DeleteAllItems(m_hwnd);
-}
-
-void CCtrlTreeView::DeleteItem(HTREEITEM hItem)
-{ TreeView_DeleteItem(m_hwnd, hItem);
-}
-
-HWND CCtrlTreeView::EditLabel(HTREEITEM hItem)
-{ return TreeView_EditLabel(m_hwnd, hItem);
-}
-
-void CCtrlTreeView::EndEditLabelNow(BOOL cancel)
-{ TreeView_EndEditLabelNow(m_hwnd, cancel);
-}
-
-void CCtrlTreeView::EnsureVisible(HTREEITEM hItem)
-{ TreeView_EnsureVisible(m_hwnd, hItem);
-}
-
-void CCtrlTreeView::Expand(HTREEITEM hItem, uint32_t flag)
-{ TreeView_Expand(m_hwnd, hItem, flag);
-}
-
-COLORREF CCtrlTreeView::GetBkColor() const
-{ return TreeView_GetBkColor(m_hwnd);
-}
-
-uint32_t CCtrlTreeView::GetCheckState(HTREEITEM hItem) const
-{ return TreeView_GetCheckState(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetChild(HTREEITEM hItem) const
-{ return TreeView_GetChild(m_hwnd, hItem);
-}
-
-int CCtrlTreeView::GetCount() const
-{ return TreeView_GetCount(m_hwnd);
-}
-
-HTREEITEM CCtrlTreeView::GetDropHilight() const
-{ return TreeView_GetDropHilight(m_hwnd);
-}
-
-HWND CCtrlTreeView::GetEditControl() const
-{ return TreeView_GetEditControl(m_hwnd);
-}
-
-HTREEITEM CCtrlTreeView::GetFirstVisible() const
-{ return TreeView_GetFirstVisible(m_hwnd);
-}
-
-HIMAGELIST CCtrlTreeView::GetImageList(int iImage) const
-{ return TreeView_GetImageList(m_hwnd, iImage);
-}
-
-int CCtrlTreeView::GetIndent() const
-{ return TreeView_GetIndent(m_hwnd);
-}
-
-COLORREF CCtrlTreeView::GetInsertMarkColor() const
-{ return TreeView_GetInsertMarkColor(m_hwnd);
-}
-
-bool CCtrlTreeView::GetItem(TVITEMEX *tvi) const
-{ return TreeView_GetItem(m_hwnd, tvi) == TRUE;
-}
-
-int CCtrlTreeView::GetItemHeight() const
-{ return TreeView_GetItemHeight(m_hwnd);
-}
-
-void CCtrlTreeView::GetItemRect(HTREEITEM hItem, RECT *rcItem, BOOL fItemRect) const
-{ TreeView_GetItemRect(m_hwnd, hItem, rcItem, fItemRect);
-}
-
-uint32_t CCtrlTreeView::GetItemState(HTREEITEM hItem, uint32_t stateMask) const
-{ return TreeView_GetItemState(m_hwnd, hItem, stateMask);
-}
-
-HTREEITEM CCtrlTreeView::GetLastVisible() const
-{ return TreeView_GetLastVisible(m_hwnd);
-}
-
-COLORREF CCtrlTreeView::GetLineColor() const
-{ return TreeView_GetLineColor(m_hwnd);
-}
-
-HTREEITEM CCtrlTreeView::GetNextItem(HTREEITEM hItem, uint32_t flag) const
-{ return TreeView_GetNextItem(m_hwnd, hItem, flag);
-}
-
-HTREEITEM CCtrlTreeView::GetNextSibling(HTREEITEM hItem) const
-{ return TreeView_GetNextSibling(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetNextVisible(HTREEITEM hItem) const
-{ return TreeView_GetNextVisible(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetParent(HTREEITEM hItem) const
-{ return TreeView_GetParent(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetPrevSibling(HTREEITEM hItem) const
-{ return TreeView_GetPrevSibling(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetPrevVisible(HTREEITEM hItem) const
-{ return TreeView_GetPrevVisible(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetRoot() const
-{ return TreeView_GetRoot(m_hwnd);
-}
-
-uint32_t CCtrlTreeView::GetScrollTime() const
-{ return TreeView_GetScrollTime(m_hwnd);
-}
-
-HTREEITEM CCtrlTreeView::GetSelection() const
-{ return TreeView_GetSelection(m_hwnd);
-}
-
-COLORREF CCtrlTreeView::GetTextColor() const
-{ return TreeView_GetTextColor(m_hwnd);
-}
-
-HWND CCtrlTreeView::GetToolTips() const
-{ return TreeView_GetToolTips(m_hwnd);
-}
-
-BOOL CCtrlTreeView::GetUnicodeFormat() const
-{ return TreeView_GetUnicodeFormat(m_hwnd);
-}
-
-unsigned CCtrlTreeView::GetVisibleCount() const
-{ return TreeView_GetVisibleCount(m_hwnd);
-}
-
-HTREEITEM CCtrlTreeView::HitTest(TVHITTESTINFO *hti) const
-{ return TreeView_HitTest(m_hwnd, hti);
-}
-
-HTREEITEM CCtrlTreeView::InsertItem(TVINSERTSTRUCT *tvis)
-{ return TreeView_InsertItem(m_hwnd, tvis);
-}
-
-void CCtrlTreeView::Select(HTREEITEM hItem, uint32_t flag)
-{ TreeView_Select(m_hwnd, hItem, flag);
-}
-
-void CCtrlTreeView::SelectDropTarget(HTREEITEM hItem)
-{ TreeView_SelectDropTarget(m_hwnd, hItem);
-}
-
-void CCtrlTreeView::SelectItem(HTREEITEM hItem)
-{ TreeView_SelectItem(m_hwnd, hItem);
-}
-
-void CCtrlTreeView::SelectSetFirstVisible(HTREEITEM hItem)
-{ TreeView_SelectSetFirstVisible(m_hwnd, hItem);
-}
-
-COLORREF CCtrlTreeView::SetBkColor(COLORREF clBack)
-{ return TreeView_SetBkColor(m_hwnd, clBack);
-}
-
-void CCtrlTreeView::SetCheckState(HTREEITEM hItem, uint32_t state)
-{ TreeView_SetCheckState(m_hwnd, hItem, state);
-}
-
-void CCtrlTreeView::SetImageList(HIMAGELIST hIml, int iImage)
-{ TreeView_SetImageList(m_hwnd, hIml, iImage);
-}
-
-void CCtrlTreeView::SetIndent(int iIndent)
-{ TreeView_SetIndent(m_hwnd, iIndent);
-}
-
-void CCtrlTreeView::SetInsertMark(HTREEITEM hItem, BOOL fAfter)
-{ TreeView_SetInsertMark(m_hwnd, hItem, fAfter);
-}
-
-COLORREF CCtrlTreeView::SetInsertMarkColor(COLORREF clMark)
-{ return TreeView_SetInsertMarkColor(m_hwnd, clMark);
-}
-
-void CCtrlTreeView::SetItem(TVITEMEX *tvi)
-{ TreeView_SetItem(m_hwnd, tvi);
-}
-
-void CCtrlTreeView::SetItemHeight(short cyItem)
-{ TreeView_SetItemHeight(m_hwnd, cyItem);
-}
-
-void CCtrlTreeView::SetItemState(HTREEITEM hItem, uint32_t state, uint32_t stateMask)
-{ TreeView_SetItemState(m_hwnd, hItem, state, stateMask);
-}
-
-COLORREF CCtrlTreeView::SetLineColor(COLORREF clLine)
-{ return TreeView_SetLineColor(m_hwnd, clLine);
-}
-
-void CCtrlTreeView::SetScrollTime(UINT uMaxScrollTime)
-{ TreeView_SetScrollTime(m_hwnd, uMaxScrollTime);
-}
-
-COLORREF CCtrlTreeView::SetTextColor(COLORREF clText)
-{ return TreeView_SetTextColor(m_hwnd, clText);
-}
-
-HWND CCtrlTreeView::SetToolTips(HWND hwndToolTips)
-{ return TreeView_SetToolTips(m_hwnd, hwndToolTips);
-}
-
-BOOL CCtrlTreeView::SetUnicodeFormat(BOOL fUnicode)
-{ return TreeView_SetUnicodeFormat(m_hwnd, fUnicode);
-}
-
-void CCtrlTreeView::SortChildren(HTREEITEM hItem, BOOL fRecurse)
-{ TreeView_SortChildren(m_hwnd, hItem, fRecurse);
-}
-
-void CCtrlTreeView::SortChildrenCB(TVSORTCB *cb, BOOL fRecurse)
-{ TreeView_SortChildrenCB(m_hwnd, cb, fRecurse);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+int ImageList_AddIcon_IconLibLoaded(HIMAGELIST hIml, int iconId)
+{
+ HICON hIcon = Skin_LoadIcon(iconId);
+ int res = ImageList_AddIcon(hIml, hIcon);
+ IcoLib_ReleaseIcon(hIcon);
+ return res;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlTreeView
+
+CCtrlTreeView::CCtrlTreeView(CDlgBase *dlg, int ctrlId) :
+ CCtrlBase(dlg, ctrlId),
+ m_dwFlags(0),
+ m_hDragItem(nullptr)
+{}
+
+void CCtrlTreeView::SetFlags(uint32_t dwFlags)
+{
+ if (dwFlags & MTREE_CHECKBOX)
+ m_bCheckBox = true;
+
+ if (dwFlags & MTREE_MULTISELECT)
+ m_bMultiSelect = true;
+
+ if (dwFlags & MTREE_DND) {
+ m_bDndEnabled = true;
+ m_bDragging = false;
+ m_hDragItem = nullptr;
+ }
+}
+
+void CCtrlTreeView::OnInit()
+{
+ CSuper::OnInit();
+
+ Subclass();
+
+ if (m_bCheckBox) {
+ HIMAGELIST himlCheckBoxes = ::ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 2, 2);
+ ::ImageList_AddIcon_IconLibLoaded(himlCheckBoxes, SKINICON_OTHER_NOTICK);
+ ::ImageList_AddIcon_IconLibLoaded(himlCheckBoxes, SKINICON_OTHER_TICK);
+ SetImageList(himlCheckBoxes, TVSIL_NORMAL);
+ }
+}
+
+void CCtrlTreeView::OnDestroy()
+{
+ if (m_bCheckBox)
+ ::ImageList_Destroy(GetImageList(TVSIL_NORMAL));
+
+ CSuper::OnDestroy();
+}
+
+HTREEITEM CCtrlTreeView::MoveItemAbove(HTREEITEM hItem, HTREEITEM hInsertAfter, HTREEITEM hParent)
+{
+ if (hItem == nullptr || hInsertAfter == nullptr)
+ return nullptr;
+
+ if (hItem == hInsertAfter)
+ return hItem;
+
+ wchar_t name[128];
+ TVINSERTSTRUCT tvis = {};
+ tvis.itemex.mask = (UINT)-1;
+ tvis.itemex.pszText = name;
+ tvis.itemex.cchTextMax = _countof(name);
+ tvis.itemex.hItem = hItem;
+ if (!GetItem(&tvis.itemex))
+ return nullptr;
+
+ OBJLIST<TVINSERTSTRUCT> arChildren(1);
+ for (HTREEITEM p = GetChild(hItem); p; p = GetNextSibling(p)) {
+ wchar_t buf[128];
+ TVINSERTSTRUCT tvis2 = {};
+ tvis2.itemex.mask = (UINT)-1;
+ tvis2.itemex.pszText = buf;
+ tvis2.itemex.cchTextMax = _countof(buf);
+ tvis2.itemex.hItem = p;
+ if (GetItem(&tvis2.itemex)) {
+ tvis2.itemex.pszText = mir_wstrdup(tvis2.itemex.pszText);
+ arChildren.insert(new TVINSERTSTRUCT(tvis2));
+
+ tvis2.itemex.lParam = 0;
+ SetItem(&tvis2.itemex);
+ }
+ }
+
+ // the pointed lParam will be freed inside TVN_DELETEITEM
+ // so lets substitute it with 0
+ LPARAM saveOldData = tvis.itemex.lParam;
+ tvis.itemex.lParam = 0;
+ SetItem(&tvis.itemex);
+
+ // now current item contain lParam = 0 we can delete it. the memory will be kept.
+ DeleteItem(hItem);
+
+ for (auto &it : arChildren)
+ DeleteItem(it->itemex.hItem);
+
+ tvis.itemex.stateMask = tvis.itemex.state;
+ tvis.itemex.lParam = saveOldData;
+ tvis.hParent = hParent;
+ tvis.hInsertAfter = hInsertAfter;
+ auto hNewItem = InsertItem(&tvis);
+
+ hInsertAfter = nullptr;
+ for (auto &it : arChildren) {
+ it->hParent = hNewItem;
+ it->hInsertAfter = hInsertAfter;
+ hInsertAfter = InsertItem(it);
+
+ mir_free(it->itemex.pszText);
+ }
+
+ return hNewItem;
+}
+
+LRESULT CCtrlTreeView::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TVHITTESTINFO hti;
+
+ switch (msg) {
+ case WM_MOUSEMOVE:
+ if (m_bDragging) {
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ HitTest(&hti);
+ if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) {
+ HTREEITEM it = hti.hItem;
+ hti.pt.y -= GetItemHeight() / 2;
+ HitTest(&hti);
+ if (!(hti.flags & TVHT_ABOVE))
+ SetInsertMark(hti.hItem, 1);
+ else
+ SetInsertMark(it, 0);
+ }
+ else {
+ if (hti.flags & TVHT_ABOVE) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0);
+ if (hti.flags & TVHT_BELOW) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0);
+ SetInsertMark(nullptr, 0);
+ }
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ if (m_bDragging) {
+ SetInsertMark(nullptr, 0);
+ m_bDragging = false;
+ ReleaseCapture();
+
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam) - GetItemHeight() / 2;
+ HitTest(&hti);
+ if (m_hDragItem == hti.hItem)
+ break;
+
+ if (hti.flags & TVHT_ABOVE)
+ hti.hItem = TVI_FIRST;
+ else if (hti.flags & TVHT_BELOW)
+ hti.hItem = TVI_LAST;
+
+ HTREEITEM insertAfter = hti.hItem, hParent;
+ if (insertAfter != TVI_FIRST) {
+ hParent = GetParent(insertAfter);
+ if (GetChild(insertAfter) != nullptr) {
+ hParent = insertAfter;
+ insertAfter = TVI_FIRST;
+ }
+ }
+ else hParent = nullptr;
+
+ HTREEITEM FirstItem = nullptr;
+ if (m_bMultiSelect) {
+ LIST<_TREEITEM> arItems(10);
+ GetSelected(arItems);
+
+ // Proceed moving
+ for (auto &it : arItems) {
+ if (!insertAfter)
+ break;
+ if (GetParent(it) != hParent) // prevent subitems from being inserted at the same level
+ continue;
+
+ insertAfter = MoveItemAbove(it, insertAfter, hParent);
+ if (it == arItems[0])
+ FirstItem = insertAfter;
+ }
+ }
+ else FirstItem = MoveItemAbove(m_hDragItem, insertAfter, hParent);
+ if (FirstItem)
+ SelectItem(FirstItem);
+
+ NotifyChange();
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ if (!m_bMultiSelect)
+ break;
+
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ if (!TreeView_HitTest(m_hwnd, &hti)) {
+ UnselectAll();
+ break;
+ }
+
+ if (!m_bDndEnabled)
+ if (!(wParam & (MK_CONTROL | MK_SHIFT)) || !(hti.flags & (TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMRIGHT))) {
+ UnselectAll();
+ TreeView_SelectItem(m_hwnd, hti.hItem);
+ break;
+ }
+
+ if (wParam & MK_CONTROL) {
+ LIST<_TREEITEM> selected(1);
+ GetSelected(selected);
+
+ // Check if have to deselect it
+ for (int i = 0; i < selected.getCount(); i++) {
+ if (selected[i] == hti.hItem) {
+ // Deselect it
+ UnselectAll();
+ selected.remove(i);
+
+ if (i > 0)
+ hti.hItem = selected[0];
+ else if (i < selected.getCount())
+ hti.hItem = selected[i];
+ else
+ hti.hItem = nullptr;
+ break;
+ }
+ }
+
+ TreeView_SelectItem(m_hwnd, hti.hItem);
+ Select(selected);
+ }
+ else if (wParam & MK_SHIFT) {
+ HTREEITEM hItem = TreeView_GetSelection(m_hwnd);
+ if (hItem == nullptr)
+ break;
+
+ LIST<_TREEITEM> selected(1);
+ GetSelected(selected);
+
+ TreeView_SelectItem(m_hwnd, hti.hItem);
+ Select(selected);
+ SelectRange(hItem, hti.hItem);
+ }
+ break;
+ }
+
+ return CSuper::CustomWndProc(msg, wParam, lParam);
+}
+
+BOOL CCtrlTreeView::OnNotify(int, NMHDR *pnmh)
+{
+ TEventInfo evt = { this, pnmh };
+
+ switch (pnmh->code) {
+ case NM_RCLICK: OnRightClick(&evt); return TRUE;
+ case NM_CUSTOMDRAW: OnCustomDraw(&evt); return TRUE;
+ case TVN_BEGINLABELEDIT: OnBeginLabelEdit(&evt); return TRUE;
+ case TVN_BEGINRDRAG: OnBeginRDrag(&evt); return TRUE;
+ case TVN_DELETEITEM: OnDeleteItem(&evt); return TRUE;
+ case TVN_ENDLABELEDIT: OnEndLabelEdit(&evt); return TRUE;
+ case TVN_GETDISPINFO: OnGetDispInfo(&evt); return TRUE;
+ case TVN_GETINFOTIP: OnGetInfoTip(&evt); return TRUE;
+ case TVN_ITEMEXPANDED: OnItemExpanded(&evt); return TRUE;
+ case TVN_ITEMEXPANDING: OnItemExpanding(&evt); return TRUE;
+ case TVN_SELCHANGED: OnSelChanged(&evt); return TRUE;
+ case TVN_SELCHANGING: OnSelChanging(&evt); return TRUE;
+ case TVN_SETDISPINFO: OnSetDispInfo(&evt); return TRUE;
+ case TVN_SINGLEEXPAND: OnSingleExpand(&evt); return TRUE;
+
+ case TVN_BEGINDRAG:
+ OnBeginDrag(&evt);
+
+ // user-defined can clear the event code to disable dragging
+ if (m_bDndEnabled && pnmh->code) {
+ ::SetCapture(m_hwnd);
+ m_bDragging = true;
+ m_hDragItem = evt.nmtv->itemNew.hItem;
+ SelectItem(m_hDragItem);
+ }
+ return TRUE;
+
+ case TVN_KEYDOWN:
+ if (evt.nmtvkey->wVKey == VK_SPACE) {
+ evt.hItem = GetSelection();
+ if (m_bCheckBox)
+ InvertCheck(evt.hItem);
+ OnItemChanged(&evt);
+ NotifyChange();
+ }
+
+ OnKeyDown(&evt);
+ return TRUE;
+ }
+
+ if (pnmh->code == NM_CLICK) {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(GetMessagePos());
+ hti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(pnmh->hwndFrom, &hti.pt);
+ if (HitTest(&hti)) {
+ if (m_bCheckBox && (hti.flags & TVHT_ONITEMICON) || !m_bCheckBox && (hti.flags & TVHT_ONITEMSTATEICON)) {
+ if (m_bCheckBox)
+ InvertCheck(hti.hItem);
+ else
+ SelectItem(hti.hItem);
+
+ evt.hItem = hti.hItem;
+ OnItemChanged(&evt);
+ NotifyChange();
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void CCtrlTreeView::InvertCheck(HTREEITEM hItem)
+{
+ TVITEMEX tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATEEX;
+ tvi.hItem = hItem;
+ if (!GetItem(&tvi))
+ return;
+
+ if (IsWinVerVistaPlus() && (tvi.uStateEx & TVIS_EX_DISABLED))
+ return;
+
+ tvi.iImage = tvi.iSelectedImage = !tvi.iImage;
+ SetItem(&tvi);
+
+ SelectItem(hItem);
+}
+
+void CCtrlTreeView::TranslateItem(HTREEITEM hItem)
+{
+ TVITEMEX tvi;
+ wchar_t buf[128];
+ GetItem(hItem, &tvi, buf, _countof(buf));
+ tvi.pszText = TranslateW_LP(tvi.pszText);
+ SetItem(&tvi);
+}
+
+void CCtrlTreeView::TranslateTree()
+{
+ HTREEITEM hItem = GetRoot();
+ while (hItem) {
+ TranslateItem(hItem);
+
+ HTREEITEM hItemTmp = nullptr;
+ if (hItemTmp = GetChild(hItem))
+ hItem = hItemTmp;
+ else if (hItemTmp = GetNextSibling(hItem))
+ hItem = hItemTmp;
+ else {
+ while (true) {
+ if (!(hItem = GetParent(hItem)))
+ break;
+ if (hItemTmp = GetNextSibling(hItem)) {
+ hItem = hItemTmp;
+ break;
+ }
+ }
+ }
+ }
+}
+
+HTREEITEM CCtrlTreeView::FindNamedItem(HTREEITEM hItem, const wchar_t *name)
+{
+ TVITEMEX tvi = { 0 };
+ wchar_t str[MAX_PATH];
+
+ if (hItem)
+ tvi.hItem = GetChild(hItem);
+ else
+ tvi.hItem = GetRoot();
+
+ if (!name)
+ return tvi.hItem;
+
+ tvi.mask = TVIF_TEXT;
+ tvi.pszText = str;
+ tvi.cchTextMax = _countof(str);
+
+ while (tvi.hItem) {
+ GetItem(&tvi);
+
+ if (!mir_wstrcmp(tvi.pszText, name))
+ return tvi.hItem;
+
+ tvi.hItem = GetNextSibling(tvi.hItem);
+ }
+ return nullptr;
+}
+
+void CCtrlTreeView::GetItem(HTREEITEM hItem, TVITEMEX *tvi) const
+{
+ memset(tvi, 0, sizeof(*tvi));
+ tvi->mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_INTEGRAL | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE;
+ tvi->hItem = hItem;
+ GetItem(tvi);
+}
+
+void CCtrlTreeView::GetItem(HTREEITEM hItem, TVITEMEX *tvi, wchar_t *szText, int iTextLength) const
+{
+ memset(tvi, 0, sizeof(*tvi));
+ tvi->mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_INTEGRAL | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE | TVIF_TEXT;
+ tvi->hItem = hItem;
+ tvi->pszText = szText;
+ tvi->cchTextMax = iTextLength;
+ GetItem(tvi);
+}
+
+bool CCtrlTreeView::IsSelected(HTREEITEM hItem)
+{
+ return (TVIS_SELECTED & TreeView_GetItemState(m_hwnd, hItem, TVIS_SELECTED)) == TVIS_SELECTED;
+}
+
+void CCtrlTreeView::Select(HTREEITEM hItem)
+{
+ TreeView_SetItemState(m_hwnd, hItem, TVIS_SELECTED, TVIS_SELECTED);
+}
+
+void CCtrlTreeView::Unselect(HTREEITEM hItem)
+{
+ TreeView_SetItemState(m_hwnd, hItem, 0, TVIS_SELECTED);
+}
+
+void CCtrlTreeView::DropHilite(HTREEITEM hItem)
+{
+ TreeView_SetItemState(m_hwnd, hItem, TVIS_DROPHILITED, TVIS_DROPHILITED);
+}
+
+void CCtrlTreeView::DropUnhilite(HTREEITEM hItem)
+{
+ TreeView_SetItemState(m_hwnd, hItem, 0, TVIS_DROPHILITED);
+}
+
+void CCtrlTreeView::SelectAll()
+{
+ TreeView_SelectItem(m_hwnd, nullptr);
+
+ HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
+ while (hItem) {
+ Select(hItem);
+ hItem = TreeView_GetNextSibling(m_hwnd, hItem);
+ }
+}
+
+void CCtrlTreeView::UnselectAll()
+{
+ TreeView_SelectItem(m_hwnd, nullptr);
+
+ HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
+ while (hItem) {
+ Unselect(hItem);
+ hItem = TreeView_GetNextSibling(m_hwnd, hItem);
+ }
+}
+
+void CCtrlTreeView::SelectRange(HTREEITEM hStart, HTREEITEM hEnd)
+{
+ int start = 0, end = 0, i = 0;
+ HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
+ while (hItem) {
+ if (hItem == hStart)
+ start = i;
+ if (hItem == hEnd)
+ end = i;
+
+ i++;
+ hItem = TreeView_GetNextSibling(m_hwnd, hItem);
+ }
+
+ if (end < start) {
+ int tmp = start;
+ start = end;
+ end = tmp;
+ }
+
+ i = 0;
+ hItem = TreeView_GetRoot(m_hwnd);
+ while (hItem) {
+ if (i >= start)
+ Select(hItem);
+ if (i == end)
+ break;
+
+ i++;
+ hItem = TreeView_GetNextSibling(m_hwnd, hItem);
+ }
+}
+
+int CCtrlTreeView::GetNumSelected()
+{
+ int ret = 0;
+ for (HTREEITEM hItem = TreeView_GetRoot(m_hwnd); hItem; hItem = TreeView_GetNextSibling(m_hwnd, hItem))
+ if (IsSelected(hItem))
+ ret++;
+
+ return ret;
+}
+
+void CCtrlTreeView::GetSelected(LIST<_TREEITEM> &selected)
+{
+ HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
+ while (hItem) {
+ if (IsSelected(hItem))
+ selected.insert(hItem);
+ hItem = TreeView_GetNextSibling(m_hwnd, hItem);
+ }
+}
+
+void CCtrlTreeView::Select(LIST<_TREEITEM> &selected)
+{
+ for (auto &it : selected)
+ if (it != nullptr)
+ Select(it);
+}
+
+void CCtrlTreeView::GetCaretPos(CContextMenuPos &pos) const
+{
+ pos.pCtrl = this;
+
+ // position is empty, let's fill it using selection
+ if (pos.pt.x == 0 && pos.pt.y == 0) {
+ HTREEITEM hItem = GetSelection();
+ if (hItem != nullptr) {
+ pos.pCtrl = this;
+ pos.hItem = hItem;
+
+ RECT rc;
+ GetItemRect(hItem, &rc, TRUE);
+ pos.pt.x = rc.left + 8;
+ pos.pt.y = rc.top + 8;
+ ClientToScreen(m_hwnd, &pos.pt);
+ return;
+ }
+ }
+ // position is present, let's calculate current item
+ else {
+ TVHITTESTINFO hti;
+ hti.pt = pos.pt;
+ ScreenToClient(m_hwnd, &hti.pt);
+ if (HitTest(&hti) && (hti.flags & TVHT_ONITEM)) {
+ pos.hItem = hti.hItem;
+ return;
+ }
+ }
+
+ CSuper::GetCaretPos(pos);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+HIMAGELIST CCtrlTreeView::CreateDragImage(HTREEITEM hItem)
+{ return TreeView_CreateDragImage(m_hwnd, hItem);
+}
+
+void CCtrlTreeView::DeleteAllItems()
+{ TreeView_DeleteAllItems(m_hwnd);
+}
+
+void CCtrlTreeView::DeleteItem(HTREEITEM hItem)
+{ TreeView_DeleteItem(m_hwnd, hItem);
+}
+
+HWND CCtrlTreeView::EditLabel(HTREEITEM hItem)
+{ return TreeView_EditLabel(m_hwnd, hItem);
+}
+
+void CCtrlTreeView::EndEditLabelNow(BOOL cancel)
+{ TreeView_EndEditLabelNow(m_hwnd, cancel);
+}
+
+void CCtrlTreeView::EnsureVisible(HTREEITEM hItem)
+{ TreeView_EnsureVisible(m_hwnd, hItem);
+}
+
+void CCtrlTreeView::Expand(HTREEITEM hItem, uint32_t flag)
+{ TreeView_Expand(m_hwnd, hItem, flag);
+}
+
+COLORREF CCtrlTreeView::GetBkColor() const
+{ return TreeView_GetBkColor(m_hwnd);
+}
+
+uint32_t CCtrlTreeView::GetCheckState(HTREEITEM hItem) const
+{ return TreeView_GetCheckState(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetChild(HTREEITEM hItem) const
+{ return TreeView_GetChild(m_hwnd, hItem);
+}
+
+int CCtrlTreeView::GetCount() const
+{ return TreeView_GetCount(m_hwnd);
+}
+
+HTREEITEM CCtrlTreeView::GetDropHilight() const
+{ return TreeView_GetDropHilight(m_hwnd);
+}
+
+HWND CCtrlTreeView::GetEditControl() const
+{ return TreeView_GetEditControl(m_hwnd);
+}
+
+HTREEITEM CCtrlTreeView::GetFirstVisible() const
+{ return TreeView_GetFirstVisible(m_hwnd);
+}
+
+HIMAGELIST CCtrlTreeView::GetImageList(int iImage) const
+{ return TreeView_GetImageList(m_hwnd, iImage);
+}
+
+int CCtrlTreeView::GetIndent() const
+{ return TreeView_GetIndent(m_hwnd);
+}
+
+COLORREF CCtrlTreeView::GetInsertMarkColor() const
+{ return TreeView_GetInsertMarkColor(m_hwnd);
+}
+
+bool CCtrlTreeView::GetItem(TVITEMEX *tvi) const
+{ return TreeView_GetItem(m_hwnd, tvi) == TRUE;
+}
+
+int CCtrlTreeView::GetItemHeight() const
+{ return TreeView_GetItemHeight(m_hwnd);
+}
+
+void CCtrlTreeView::GetItemRect(HTREEITEM hItem, RECT *rcItem, BOOL fItemRect) const
+{ TreeView_GetItemRect(m_hwnd, hItem, rcItem, fItemRect);
+}
+
+uint32_t CCtrlTreeView::GetItemState(HTREEITEM hItem, uint32_t stateMask) const
+{ return TreeView_GetItemState(m_hwnd, hItem, stateMask);
+}
+
+HTREEITEM CCtrlTreeView::GetLastVisible() const
+{ return TreeView_GetLastVisible(m_hwnd);
+}
+
+COLORREF CCtrlTreeView::GetLineColor() const
+{ return TreeView_GetLineColor(m_hwnd);
+}
+
+HTREEITEM CCtrlTreeView::GetNextItem(HTREEITEM hItem, uint32_t flag) const
+{ return TreeView_GetNextItem(m_hwnd, hItem, flag);
+}
+
+HTREEITEM CCtrlTreeView::GetNextSibling(HTREEITEM hItem) const
+{ return TreeView_GetNextSibling(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetNextVisible(HTREEITEM hItem) const
+{ return TreeView_GetNextVisible(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetParent(HTREEITEM hItem) const
+{ return TreeView_GetParent(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetPrevSibling(HTREEITEM hItem) const
+{ return TreeView_GetPrevSibling(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetPrevVisible(HTREEITEM hItem) const
+{ return TreeView_GetPrevVisible(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetRoot() const
+{ return TreeView_GetRoot(m_hwnd);
+}
+
+uint32_t CCtrlTreeView::GetScrollTime() const
+{ return TreeView_GetScrollTime(m_hwnd);
+}
+
+HTREEITEM CCtrlTreeView::GetSelection() const
+{ return TreeView_GetSelection(m_hwnd);
+}
+
+COLORREF CCtrlTreeView::GetTextColor() const
+{ return TreeView_GetTextColor(m_hwnd);
+}
+
+HWND CCtrlTreeView::GetToolTips() const
+{ return TreeView_GetToolTips(m_hwnd);
+}
+
+BOOL CCtrlTreeView::GetUnicodeFormat() const
+{ return TreeView_GetUnicodeFormat(m_hwnd);
+}
+
+unsigned CCtrlTreeView::GetVisibleCount() const
+{ return TreeView_GetVisibleCount(m_hwnd);
+}
+
+HTREEITEM CCtrlTreeView::HitTest(TVHITTESTINFO *hti) const
+{ return TreeView_HitTest(m_hwnd, hti);
+}
+
+HTREEITEM CCtrlTreeView::InsertItem(TVINSERTSTRUCT *tvis)
+{ return TreeView_InsertItem(m_hwnd, tvis);
+}
+
+void CCtrlTreeView::Select(HTREEITEM hItem, uint32_t flag)
+{ TreeView_Select(m_hwnd, hItem, flag);
+}
+
+void CCtrlTreeView::SelectDropTarget(HTREEITEM hItem)
+{ TreeView_SelectDropTarget(m_hwnd, hItem);
+}
+
+void CCtrlTreeView::SelectItem(HTREEITEM hItem)
+{ TreeView_SelectItem(m_hwnd, hItem);
+}
+
+void CCtrlTreeView::SelectSetFirstVisible(HTREEITEM hItem)
+{ TreeView_SelectSetFirstVisible(m_hwnd, hItem);
+}
+
+COLORREF CCtrlTreeView::SetBkColor(COLORREF clBack)
+{ return TreeView_SetBkColor(m_hwnd, clBack);
+}
+
+void CCtrlTreeView::SetCheckState(HTREEITEM hItem, uint32_t state)
+{ TreeView_SetCheckState(m_hwnd, hItem, state);
+}
+
+void CCtrlTreeView::SetImageList(HIMAGELIST hIml, int iImage)
+{ TreeView_SetImageList(m_hwnd, hIml, iImage);
+}
+
+void CCtrlTreeView::SetIndent(int iIndent)
+{ TreeView_SetIndent(m_hwnd, iIndent);
+}
+
+void CCtrlTreeView::SetInsertMark(HTREEITEM hItem, BOOL fAfter)
+{ TreeView_SetInsertMark(m_hwnd, hItem, fAfter);
+}
+
+COLORREF CCtrlTreeView::SetInsertMarkColor(COLORREF clMark)
+{ return TreeView_SetInsertMarkColor(m_hwnd, clMark);
+}
+
+void CCtrlTreeView::SetItem(TVITEMEX *tvi)
+{ TreeView_SetItem(m_hwnd, tvi);
+}
+
+void CCtrlTreeView::SetItemHeight(short cyItem)
+{ TreeView_SetItemHeight(m_hwnd, cyItem);
+}
+
+void CCtrlTreeView::SetItemState(HTREEITEM hItem, uint32_t state, uint32_t stateMask)
+{ TreeView_SetItemState(m_hwnd, hItem, state, stateMask);
+}
+
+COLORREF CCtrlTreeView::SetLineColor(COLORREF clLine)
+{ return TreeView_SetLineColor(m_hwnd, clLine);
+}
+
+void CCtrlTreeView::SetScrollTime(UINT uMaxScrollTime)
+{ TreeView_SetScrollTime(m_hwnd, uMaxScrollTime);
+}
+
+COLORREF CCtrlTreeView::SetTextColor(COLORREF clText)
+{ return TreeView_SetTextColor(m_hwnd, clText);
+}
+
+HWND CCtrlTreeView::SetToolTips(HWND hwndToolTips)
+{ return TreeView_SetToolTips(m_hwnd, hwndToolTips);
+}
+
+BOOL CCtrlTreeView::SetUnicodeFormat(BOOL fUnicode)
+{ return TreeView_SetUnicodeFormat(m_hwnd, fUnicode);
+}
+
+void CCtrlTreeView::SortChildren(HTREEITEM hItem, BOOL fRecurse)
+{ TreeView_SortChildren(m_hwnd, hItem, fRecurse);
+}
+
+void CCtrlTreeView::SortChildrenCB(TVSORTCB *cb, BOOL fRecurse)
+{ TreeView_SortChildrenCB(m_hwnd, cb, fRecurse);
+}
diff --git a/src/mir_core/src/Linux/CDbLink.cpp b/src/mir_core/src/Linux/CDbLink.cpp
index 2a0734cd3b..05925f871b 100644
--- a/src/mir_core/src/Linux/CDbLink.cpp
+++ b/src/mir_core/src/Linux/CDbLink.cpp
@@ -1,92 +1,92 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CDbLink class
-
-CDbLink::CDbLink(const char *szModule, const char *szSetting, uint8_t type, uint32_t iValue)
- : CDataLink(type)
-{
- m_szModule = mir_strdup(szModule);
- m_szSetting = mir_strdup(szSetting);
- m_iDefault = iValue;
- m_szDefault = nullptr;
- dbv.type = DBVT_DELETED;
-}
-
-CDbLink::CDbLink(const char *szModule, const char *szSetting, uint8_t type, wchar_t *szValue)
- : CDataLink(type),
- m_iDefault(0)
-{
- m_szModule = mir_strdup(szModule);
- m_szSetting = mir_strdup(szSetting);
- m_szDefault = mir_wstrdup(szValue);
- dbv.type = DBVT_DELETED;
-}
-
-CDbLink::~CDbLink()
-{
- mir_free(m_szModule);
- mir_free(m_szSetting);
- mir_free(m_szDefault);
- if (dbv.type != DBVT_DELETED)
- db_free(&dbv);
-}
-
-uint32_t CDbLink::LoadInt()
-{
- switch (m_type) {
- case DBVT_BYTE: return db_get_b(0, m_szModule, m_szSetting, m_iDefault);
- case DBVT_WORD: return db_get_w(0, m_szModule, m_szSetting, m_iDefault);
- case DBVT_DWORD: return db_get_dw(0, m_szModule, m_szSetting, m_iDefault);
- default: return m_iDefault;
- }
-}
-
-void CDbLink::SaveInt(uint32_t value)
-{
- switch (m_type) {
- case DBVT_BYTE: db_set_b(0, m_szModule, m_szSetting, (uint8_t)value); break;
- case DBVT_WORD: db_set_w(0, m_szModule, m_szSetting, (uint16_t)value); break;
- case DBVT_DWORD: db_set_dw(0, m_szModule, m_szSetting, value); break;
- }
-}
-
-wchar_t* CDbLink::LoadText()
-{
- if (dbv.type != DBVT_DELETED) db_free(&dbv);
- if (!db_get_ws(0, m_szModule, m_szSetting, &dbv)) {
- if (dbv.type == DBVT_WCHAR)
- return dbv.pwszVal;
- return m_szDefault;
- }
-
- dbv.type = DBVT_DELETED;
- return m_szDefault;
-}
-
-void CDbLink::SaveText(wchar_t *value)
-{
- db_set_ws(0, m_szModule, m_szSetting, value);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CDbLink class
+
+CDbLink::CDbLink(const char *szModule, const char *szSetting, uint8_t type, uint32_t iValue)
+ : CDataLink(type)
+{
+ m_szModule = mir_strdup(szModule);
+ m_szSetting = mir_strdup(szSetting);
+ m_iDefault = iValue;
+ m_szDefault = nullptr;
+ dbv.type = DBVT_DELETED;
+}
+
+CDbLink::CDbLink(const char *szModule, const char *szSetting, uint8_t type, wchar_t *szValue)
+ : CDataLink(type),
+ m_iDefault(0)
+{
+ m_szModule = mir_strdup(szModule);
+ m_szSetting = mir_strdup(szSetting);
+ m_szDefault = mir_wstrdup(szValue);
+ dbv.type = DBVT_DELETED;
+}
+
+CDbLink::~CDbLink()
+{
+ mir_free(m_szModule);
+ mir_free(m_szSetting);
+ mir_free(m_szDefault);
+ if (dbv.type != DBVT_DELETED)
+ db_free(&dbv);
+}
+
+uint32_t CDbLink::LoadInt()
+{
+ switch (m_type) {
+ case DBVT_BYTE: return db_get_b(0, m_szModule, m_szSetting, m_iDefault);
+ case DBVT_WORD: return db_get_w(0, m_szModule, m_szSetting, m_iDefault);
+ case DBVT_DWORD: return db_get_dw(0, m_szModule, m_szSetting, m_iDefault);
+ default: return m_iDefault;
+ }
+}
+
+void CDbLink::SaveInt(uint32_t value)
+{
+ switch (m_type) {
+ case DBVT_BYTE: db_set_b(0, m_szModule, m_szSetting, (uint8_t)value); break;
+ case DBVT_WORD: db_set_w(0, m_szModule, m_szSetting, (uint16_t)value); break;
+ case DBVT_DWORD: db_set_dw(0, m_szModule, m_szSetting, value); break;
+ }
+}
+
+wchar_t* CDbLink::LoadText()
+{
+ if (dbv.type != DBVT_DELETED) db_free(&dbv);
+ if (!db_get_ws(0, m_szModule, m_szSetting, &dbv)) {
+ if (dbv.type == DBVT_WCHAR)
+ return dbv.pwszVal;
+ return m_szDefault;
+ }
+
+ dbv.type = DBVT_DELETED;
+ return m_szDefault;
+}
+
+void CDbLink::SaveText(wchar_t *value)
+{
+ db_set_ws(0, m_szModule, m_szSetting, value);
+}
diff --git a/src/mir_core/src/Linux/CDlgBase.cpp b/src/mir_core/src/Linux/CDlgBase.cpp
index 3504a7e74c..2ec9ceb8c8 100644
--- a/src/mir_core/src/Linux/CDlgBase.cpp
+++ b/src/mir_core/src/Linux/CDlgBase.cpp
@@ -1,260 +1,260 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-static mir_cs csDialogs;
-
-static int CompareDialogs(const CDlgBase *p1, const CDlgBase *p2)
-{
- return (INT_PTR)p1->GetHwnd() - (INT_PTR)p2->GetHwnd();
-}
-static LIST<CDlgBase> arDialogs(10, CompareDialogs);
-
-#pragma comment(lib, "uxtheme")
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CDlgBase
-
-static int CompareControlId(const CCtrlBase *c1, const CCtrlBase *c2)
-{
- return c1->GetCtrlId() - c2->GetCtrlId();
-}
-
-static int CompareTimerId(const CTimer *t1, const CTimer *t2)
-{
- return t1->GetEventId() - t2->GetEventId();
-}
-
-CDlgBase::CDlgBase(CMPluginBase &pPlug, int idDialog)
- : m_controls(1, CompareControlId),
- m_timers(1, CompareTimerId),
- m_pPlugin(pPlug)
-{
- m_idDialog = idDialog;
- m_autoClose = CLOSE_ON_OK | CLOSE_ON_CANCEL;
-}
-
-CDlgBase::~CDlgBase()
-{
- m_bInitialized = false; // prevent double call of destructor
- // if (m_hwnd)
- // DestroyWindow(m_hwnd);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// events
-
-bool CDlgBase::OnInitDialog()
-{
- return true;
-}
-
-bool CDlgBase::OnClose()
-{
- return true;
-}
-
-bool CDlgBase::OnApply()
-{
- return true;
-}
-
-void CDlgBase::OnChange()
-{}
-
-void CDlgBase::OnDestroy()
-{}
-
-void CDlgBase::OnReset()
-{}
-
-void CDlgBase::OnTimer(CTimer*)
-{}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// methods
-
-void CDlgBase::Close()
-{
- // ::SendMessage(m_hwnd, WM_CLOSE, 0, 0);
-}
-
-void CDlgBase::Create()
-{
- // CreateDialogParam(GetInst(), MAKEINTRESOURCE(m_idDialog), m_hwndParent, GlobalDlgProc, (LPARAM)this);
-}
-
-int CDlgBase::DoModal()
-{
- m_isModal = true;
- // return DialogBoxParam(GetInst(), MAKEINTRESOURCE(m_idDialog), m_hwndParent, GlobalDlgProc, (LPARAM)this);
- return 0; //!!!!!!!!
-}
-
-void CDlgBase::EndModal(INT_PTR nResult)
-{
- // ::EndDialog(m_hwnd, nResult);
-}
-
-HINSTANCE CDlgBase::GetInst() const
-{
- return m_pPlugin.getInst();
-}
-
-void CDlgBase::NotifyChange(void)
-{
- if (!m_bInitialized)
- return;
-
- OnChange();
-
- // if (m_hwndParent)
- // SendMessage(m_hwndParent, PSM_CHANGED, (WPARAM)m_hwnd, 0);
-}
-
-void CDlgBase::Resize()
-{
- // SendMessage(m_hwnd, WM_SIZE, 0, 0);
-}
-
-void CDlgBase::SetCaption(const wchar_t *ptszCaption)
-{
- // if (m_hwnd && ptszCaption)
- // SetText(ptszCaption);
-}
-
-void CDlgBase::SetDraw(bool bEnable)
-{
- // ::SendMessage(m_hwnd, WM_SETREDRAW, bEnable, 0);
-}
-
-void CDlgBase::Show(int nCmdShow)
-{
- if (m_hwnd == nullptr)
- Create();
- // ShowWindow(m_hwnd, nCmdShow);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CDlgBase::CreateLink(CCtrlData& ctrl, const char *szSetting, uint8_t type, uint32_t iValue)
-{
- ctrl.CreateDbLink(m_pPlugin.getModule(), szSetting, type, iValue);
-}
-
-void CDlgBase::CreateLink(CCtrlData& ctrl, const char *szSetting, wchar_t *szValue)
-{
- ctrl.CreateDbLink(m_pPlugin.getModule(), szSetting, szValue);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// virtual methods
-
-int CDlgBase::Resizer(UTILRESIZECONTROL*)
-{
- return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
-}
-
-BOOL CALLBACK CDlgBase::GlobalFieldEnum(MWindow hwnd, LPARAM lParam)
-{
- return TRUE;
-}
-
-INT_PTR CDlgBase::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- return FALSE;
-}
-
-int CDlgBase::GlobalDlgResizer(MWindow hwnd, LPARAM, UTILRESIZECONTROL *urc)
-{
- CDlgBase *wnd = CDlgBase::Find(hwnd);
- return (wnd == nullptr) ? 0 : wnd->Resizer(urc);
-}
-
-void CDlgBase::ThemeDialogBackground(BOOL tabbed)
-{
-}
-
-void CDlgBase::AddControl(CCtrlBase *ctrl)
-{
- m_controls.insert(ctrl);
-}
-
-void CDlgBase::RemoveControl(CCtrlBase *ctrl)
-{
- m_controls.remove(ctrl);
-}
-
-void CDlgBase::NotifyControls(void (CCtrlBase::*fn)())
-{
- for (auto &it : m_controls)
- (it->*fn)();
-}
-
-bool CDlgBase::VerifyControls(bool (CCtrlBase::*fn)())
-{
- for (auto &it : m_controls)
- if (!(it->*fn)())
- return false;
-
- return true;
-}
-
-CCtrlBase* CDlgBase::FindControl(int idCtrl)
-{
- CCtrlBase search(nullptr, idCtrl);
- return m_controls.find(&search);
-}
-
-CCtrlBase* CDlgBase::FindControl(MWindow hwnd)
-{
- for (auto &it : m_controls)
- if (it->GetHwnd() == hwnd)
- return it;
-
- return nullptr;
-}
-
-void CDlgBase::AddTimer(CTimer *timer)
-{
- m_timers.insert(timer);
-}
-
-void CDlgBase::RemoveTimer(UINT_PTR idEvent)
-{
- CTimer search(nullptr, idEvent);
- m_timers.remove(&search);
-}
-
-CTimer* CDlgBase::FindTimer(int idEvent)
-{
- CTimer search(nullptr, idEvent);
- return m_timers.find(&search);
-}
-
-CDlgBase* CDlgBase::Find(MWindow hwnd)
-{
- void *bullshit[2]; // vfptr + hwnd
- bullshit[1] = hwnd;
- return arDialogs.find((CDlgBase*)&bullshit);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+static mir_cs csDialogs;
+
+static int CompareDialogs(const CDlgBase *p1, const CDlgBase *p2)
+{
+ return (INT_PTR)p1->GetHwnd() - (INT_PTR)p2->GetHwnd();
+}
+static LIST<CDlgBase> arDialogs(10, CompareDialogs);
+
+#pragma comment(lib, "uxtheme")
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CDlgBase
+
+static int CompareControlId(const CCtrlBase *c1, const CCtrlBase *c2)
+{
+ return c1->GetCtrlId() - c2->GetCtrlId();
+}
+
+static int CompareTimerId(const CTimer *t1, const CTimer *t2)
+{
+ return t1->GetEventId() - t2->GetEventId();
+}
+
+CDlgBase::CDlgBase(CMPluginBase &pPlug, int idDialog)
+ : m_controls(1, CompareControlId),
+ m_timers(1, CompareTimerId),
+ m_pPlugin(pPlug)
+{
+ m_idDialog = idDialog;
+ m_autoClose = CLOSE_ON_OK | CLOSE_ON_CANCEL;
+}
+
+CDlgBase::~CDlgBase()
+{
+ m_bInitialized = false; // prevent double call of destructor
+ // if (m_hwnd)
+ // DestroyWindow(m_hwnd);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// events
+
+bool CDlgBase::OnInitDialog()
+{
+ return true;
+}
+
+bool CDlgBase::OnClose()
+{
+ return true;
+}
+
+bool CDlgBase::OnApply()
+{
+ return true;
+}
+
+void CDlgBase::OnChange()
+{}
+
+void CDlgBase::OnDestroy()
+{}
+
+void CDlgBase::OnReset()
+{}
+
+void CDlgBase::OnTimer(CTimer*)
+{}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// methods
+
+void CDlgBase::Close()
+{
+ // ::SendMessage(m_hwnd, WM_CLOSE, 0, 0);
+}
+
+void CDlgBase::Create()
+{
+ // CreateDialogParam(GetInst(), MAKEINTRESOURCE(m_idDialog), m_hwndParent, GlobalDlgProc, (LPARAM)this);
+}
+
+int CDlgBase::DoModal()
+{
+ m_isModal = true;
+ // return DialogBoxParam(GetInst(), MAKEINTRESOURCE(m_idDialog), m_hwndParent, GlobalDlgProc, (LPARAM)this);
+ return 0; //!!!!!!!!
+}
+
+void CDlgBase::EndModal(INT_PTR nResult)
+{
+ // ::EndDialog(m_hwnd, nResult);
+}
+
+HINSTANCE CDlgBase::GetInst() const
+{
+ return m_pPlugin.getInst();
+}
+
+void CDlgBase::NotifyChange(void)
+{
+ if (!m_bInitialized)
+ return;
+
+ OnChange();
+
+ // if (m_hwndParent)
+ // SendMessage(m_hwndParent, PSM_CHANGED, (WPARAM)m_hwnd, 0);
+}
+
+void CDlgBase::Resize()
+{
+ // SendMessage(m_hwnd, WM_SIZE, 0, 0);
+}
+
+void CDlgBase::SetCaption(const wchar_t *ptszCaption)
+{
+ // if (m_hwnd && ptszCaption)
+ // SetText(ptszCaption);
+}
+
+void CDlgBase::SetDraw(bool bEnable)
+{
+ // ::SendMessage(m_hwnd, WM_SETREDRAW, bEnable, 0);
+}
+
+void CDlgBase::Show(int nCmdShow)
+{
+ if (m_hwnd == nullptr)
+ Create();
+ // ShowWindow(m_hwnd, nCmdShow);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CDlgBase::CreateLink(CCtrlData& ctrl, const char *szSetting, uint8_t type, uint32_t iValue)
+{
+ ctrl.CreateDbLink(m_pPlugin.getModule(), szSetting, type, iValue);
+}
+
+void CDlgBase::CreateLink(CCtrlData& ctrl, const char *szSetting, wchar_t *szValue)
+{
+ ctrl.CreateDbLink(m_pPlugin.getModule(), szSetting, szValue);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// virtual methods
+
+int CDlgBase::Resizer(UTILRESIZECONTROL*)
+{
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+}
+
+BOOL CALLBACK CDlgBase::GlobalFieldEnum(MWindow hwnd, LPARAM lParam)
+{
+ return TRUE;
+}
+
+INT_PTR CDlgBase::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return FALSE;
+}
+
+int CDlgBase::GlobalDlgResizer(MWindow hwnd, LPARAM, UTILRESIZECONTROL *urc)
+{
+ CDlgBase *wnd = CDlgBase::Find(hwnd);
+ return (wnd == nullptr) ? 0 : wnd->Resizer(urc);
+}
+
+void CDlgBase::ThemeDialogBackground(BOOL tabbed)
+{
+}
+
+void CDlgBase::AddControl(CCtrlBase *ctrl)
+{
+ m_controls.insert(ctrl);
+}
+
+void CDlgBase::RemoveControl(CCtrlBase *ctrl)
+{
+ m_controls.remove(ctrl);
+}
+
+void CDlgBase::NotifyControls(void (CCtrlBase::*fn)())
+{
+ for (auto &it : m_controls)
+ (it->*fn)();
+}
+
+bool CDlgBase::VerifyControls(bool (CCtrlBase::*fn)())
+{
+ for (auto &it : m_controls)
+ if (!(it->*fn)())
+ return false;
+
+ return true;
+}
+
+CCtrlBase* CDlgBase::FindControl(int idCtrl)
+{
+ CCtrlBase search(nullptr, idCtrl);
+ return m_controls.find(&search);
+}
+
+CCtrlBase* CDlgBase::FindControl(MWindow hwnd)
+{
+ for (auto &it : m_controls)
+ if (it->GetHwnd() == hwnd)
+ return it;
+
+ return nullptr;
+}
+
+void CDlgBase::AddTimer(CTimer *timer)
+{
+ m_timers.insert(timer);
+}
+
+void CDlgBase::RemoveTimer(UINT_PTR idEvent)
+{
+ CTimer search(nullptr, idEvent);
+ m_timers.remove(&search);
+}
+
+CTimer* CDlgBase::FindTimer(int idEvent)
+{
+ CTimer search(nullptr, idEvent);
+ return m_timers.find(&search);
+}
+
+CDlgBase* CDlgBase::Find(MWindow hwnd)
+{
+ void *bullshit[2]; // vfptr + hwnd
+ bullshit[1] = hwnd;
+ return arDialogs.find((CDlgBase*)&bullshit);
+}
diff --git a/src/mir_core/src/Linux/CProgress.cpp b/src/mir_core/src/Linux/CProgress.cpp
index 991c6f239d..e2d5321f59 100644
--- a/src/mir_core/src/Linux/CProgress.cpp
+++ b/src/mir_core/src/Linux/CProgress.cpp
@@ -1,53 +1,53 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlProgress
-
-CCtrlProgress::CCtrlProgress(CDlgBase *wnd, int idCtrl)
- : CCtrlBase(wnd, idCtrl)
-{
-}
-
-void CCtrlProgress::SetRange(uint16_t max, uint16_t min)
-{
- SendMsg(PBM_SETRANGE, 0, MAKELPARAM(min, max));
-}
-
-void CCtrlProgress::SetPosition(uint16_t value)
-{
- SendMsg(PBM_SETPOS, value, 0);
-}
-
-void CCtrlProgress::SetStep(uint16_t value)
-{
- SendMsg(PBM_SETSTEP, value, 0);
-}
-
-uint16_t CCtrlProgress::Move(uint16_t delta)
-{
- return delta == 0
- ? SendMsg(PBM_STEPIT, 0, 0)
- : SendMsg(PBM_DELTAPOS, delta, 0);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlProgress
+
+CCtrlProgress::CCtrlProgress(CDlgBase *wnd, int idCtrl)
+ : CCtrlBase(wnd, idCtrl)
+{
+}
+
+void CCtrlProgress::SetRange(uint16_t max, uint16_t min)
+{
+ SendMsg(PBM_SETRANGE, 0, MAKELPARAM(min, max));
+}
+
+void CCtrlProgress::SetPosition(uint16_t value)
+{
+ SendMsg(PBM_SETPOS, value, 0);
+}
+
+void CCtrlProgress::SetStep(uint16_t value)
+{
+ SendMsg(PBM_SETSTEP, value, 0);
+}
+
+uint16_t CCtrlProgress::Move(uint16_t delta)
+{
+ return delta == 0
+ ? SendMsg(PBM_STEPIT, 0, 0)
+ : SendMsg(PBM_DELTAPOS, delta, 0);
+}
diff --git a/src/mir_core/src/Linux/CSplitter.cpp b/src/mir_core/src/Linux/CSplitter.cpp
index e2ee6b6fc8..153beaf95b 100644
--- a/src/mir_core/src/Linux/CSplitter.cpp
+++ b/src/mir_core/src/Linux/CSplitter.cpp
@@ -1,83 +1,83 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CSplitter
-
-CSplitter::CSplitter(CDlgBase *wnd, int idCtrl)
- : CCtrlBase(wnd, idCtrl),
- m_iPosition(0)
-{
-}
-
-void CSplitter::OnInit()
-{
- CSuper::OnInit();
- Subclass();
-}
-
-LRESULT CSplitter::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_NCHITTEST:
- return HTCLIENT;
-
- case WM_SETCURSOR:
- RECT rc;
- GetClientRect(m_hwnd, &rc);
- SetCursor(rc.right > rc.bottom ? g_hCursorNS : g_hCursorWE);
- return TRUE;
-
- case WM_LBUTTONDOWN:
- SetCapture(m_hwnd);
- return 0;
-
- case WM_MOUSEMOVE:
- if (GetCapture() == m_hwnd) {
- POINT pt = { 0, 0 };
- GetClientRect(m_hwnd, &rc);
- if (rc.right > rc.bottom) {
- pt.y = HIWORD(GetMessagePos()) + rc.bottom / 2;
- ScreenToClient(m_parentWnd->GetHwnd(), &pt);
- m_iPosition = pt.y;
- }
- else {
- pt.x = LOWORD(GetMessagePos()) + rc.right / 2;
- ScreenToClient(m_parentWnd->GetHwnd(), &pt);
- m_iPosition = pt.x;
- }
-
- OnChange(this);
- PostMessage(m_parentWnd->GetHwnd(), WM_SIZE, 0, 0);
- }
- return 0;
-
- case WM_LBUTTONUP:
- ReleaseCapture();
- PostMessage(m_parentWnd->GetHwnd(), WM_SIZE, 0, 0);
- return 0;
- }
-
- return CSuper::CustomWndProc(msg, wParam, lParam);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CSplitter
+
+CSplitter::CSplitter(CDlgBase *wnd, int idCtrl)
+ : CCtrlBase(wnd, idCtrl),
+ m_iPosition(0)
+{
+}
+
+void CSplitter::OnInit()
+{
+ CSuper::OnInit();
+ Subclass();
+}
+
+LRESULT CSplitter::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_NCHITTEST:
+ return HTCLIENT;
+
+ case WM_SETCURSOR:
+ RECT rc;
+ GetClientRect(m_hwnd, &rc);
+ SetCursor(rc.right > rc.bottom ? g_hCursorNS : g_hCursorWE);
+ return TRUE;
+
+ case WM_LBUTTONDOWN:
+ SetCapture(m_hwnd);
+ return 0;
+
+ case WM_MOUSEMOVE:
+ if (GetCapture() == m_hwnd) {
+ POINT pt = { 0, 0 };
+ GetClientRect(m_hwnd, &rc);
+ if (rc.right > rc.bottom) {
+ pt.y = HIWORD(GetMessagePos()) + rc.bottom / 2;
+ ScreenToClient(m_parentWnd->GetHwnd(), &pt);
+ m_iPosition = pt.y;
+ }
+ else {
+ pt.x = LOWORD(GetMessagePos()) + rc.right / 2;
+ ScreenToClient(m_parentWnd->GetHwnd(), &pt);
+ m_iPosition = pt.x;
+ }
+
+ OnChange(this);
+ PostMessage(m_parentWnd->GetHwnd(), WM_SIZE, 0, 0);
+ }
+ return 0;
+
+ case WM_LBUTTONUP:
+ ReleaseCapture();
+ PostMessage(m_parentWnd->GetHwnd(), WM_SIZE, 0, 0);
+ return 0;
+ }
+
+ return CSuper::CustomWndProc(msg, wParam, lParam);
+}
diff --git a/src/mir_core/src/Linux/CTimer.cpp b/src/mir_core/src/Linux/CTimer.cpp
index 5d3c8b01b1..07fc863c60 100644
--- a/src/mir_core/src/Linux/CTimer.cpp
+++ b/src/mir_core/src/Linux/CTimer.cpp
@@ -1,93 +1,93 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CTimer
-
-CTimer::CTimer(CDlgBase *wnd, UINT_PTR idEvent)
- : m_wnd(wnd), m_idEvent(idEvent)
-{
- if (wnd)
- wnd->AddTimer(this);
-}
-
-CTimer::~CTimer()
-{
- if (m_wnd)
- m_wnd->RemoveTimer(m_idEvent);
-}
-
-BOOL CTimer::OnTimer()
-{
- OnEvent(this);
- return FALSE;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CTimer::Start(int elapse)
-{
- // ::SetTimer(m_wnd->GetHwnd(), m_idEvent, elapse, nullptr);
-}
-
-bool CTimer::Stop()
-{
- // return 0 != ::KillTimer(m_wnd->GetHwnd(), m_idEvent);
- return false;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct TStartParam
-{
- CTimer *pTimer;
- int period;
-};
-
-static INT_PTR CALLBACK stubStart(void *param)
-{
- auto *p = (TStartParam *)param;
- // return ::SetTimer(p->pTimer->GetHwnd(), p->pTimer->GetEventId(), p->period, nullptr);
- return 0;
-}
-
-void CTimer::StartSafe(int elapse)
-{
- TStartParam param = { this, elapse };
- CallFunctionSync(stubStart, &param);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static INT_PTR CALLBACK stubStop(void *param)
-{
- auto *p = (CTimer*)param;
- // return ::KillTimer(p->GetHwnd(), p->GetEventId());
- return 0;
-}
-
-void CTimer::StopSafe()
-{
- CallFunctionSync(stubStop, this);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CTimer
+
+CTimer::CTimer(CDlgBase *wnd, UINT_PTR idEvent)
+ : m_wnd(wnd), m_idEvent(idEvent)
+{
+ if (wnd)
+ wnd->AddTimer(this);
+}
+
+CTimer::~CTimer()
+{
+ if (m_wnd)
+ m_wnd->RemoveTimer(m_idEvent);
+}
+
+BOOL CTimer::OnTimer()
+{
+ OnEvent(this);
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CTimer::Start(int elapse)
+{
+ // ::SetTimer(m_wnd->GetHwnd(), m_idEvent, elapse, nullptr);
+}
+
+bool CTimer::Stop()
+{
+ // return 0 != ::KillTimer(m_wnd->GetHwnd(), m_idEvent);
+ return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct TStartParam
+{
+ CTimer *pTimer;
+ int period;
+};
+
+static INT_PTR CALLBACK stubStart(void *param)
+{
+ auto *p = (TStartParam *)param;
+ // return ::SetTimer(p->pTimer->GetHwnd(), p->pTimer->GetEventId(), p->period, nullptr);
+ return 0;
+}
+
+void CTimer::StartSafe(int elapse)
+{
+ TStartParam param = { this, elapse };
+ CallFunctionSync(stubStart, &param);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR CALLBACK stubStop(void *param)
+{
+ auto *p = (CTimer*)param;
+ // return ::KillTimer(p->GetHwnd(), p->GetEventId());
+ return 0;
+}
+
+void CTimer::StopSafe()
+{
+ CallFunctionSync(stubStop, this);
+}
diff --git a/src/mir_core/src/Linux/cctrldate.cpp b/src/mir_core/src/Linux/cctrldate.cpp
index 1967cb5678..253b549870 100644
--- a/src/mir_core/src/Linux/cctrldate.cpp
+++ b/src/mir_core/src/Linux/cctrldate.cpp
@@ -1,49 +1,49 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlDate class
-
-CCtrlDate::CCtrlDate(CDlgBase *dlg, int ctrlId) :
- CCtrlData(dlg, ctrlId)
-{}
-
-BOOL CCtrlDate::OnNotify(int, NMHDR *pnmh)
-{
- if (pnmh->code == DTN_DATETIMECHANGE) {
- NotifyChange();
- return TRUE;
- }
- return FALSE;
-}
-
-void CCtrlDate::GetTime(SYSTEMTIME *pDate)
-{
- ::SendMessage(m_hwnd, DTM_GETSYSTEMTIME, 0, (LPARAM)pDate);
-}
-
-void CCtrlDate::SetTime(SYSTEMTIME *pDate)
-{
- ::SendMessage(m_hwnd, DTM_SETSYSTEMTIME, 0, (LPARAM)pDate);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlDate class
+
+CCtrlDate::CCtrlDate(CDlgBase *dlg, int ctrlId) :
+ CCtrlData(dlg, ctrlId)
+{}
+
+BOOL CCtrlDate::OnNotify(int, NMHDR *pnmh)
+{
+ if (pnmh->code == DTN_DATETIMECHANGE) {
+ NotifyChange();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void CCtrlDate::GetTime(SYSTEMTIME *pDate)
+{
+ ::SendMessage(m_hwnd, DTM_GETSYSTEMTIME, 0, (LPARAM)pDate);
+}
+
+void CCtrlDate::SetTime(SYSTEMTIME *pDate)
+{
+ ::SendMessage(m_hwnd, DTM_SETSYSTEMTIME, 0, (LPARAM)pDate);
+}
diff --git a/src/mir_core/src/Linux/fileutil.cpp b/src/mir_core/src/Linux/fileutil.cpp
index a5002f0a66..fadc70e430 100644
--- a/src/mir_core/src/Linux/fileutil.cpp
+++ b/src/mir_core/src/Linux/fileutil.cpp
@@ -1,89 +1,89 @@
-/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "../stdafx.h"
-#include <unistd.h>
-
-MIR_CORE_DLL(FILE*) _wfopen(const wchar_t *pwszFileName, const wchar_t *pwszMode)
-{
- return fopen(T2Utf(pwszFileName), T2Utf(pwszMode));
-}
-
-MIR_CORE_DLL(int) _wchdir(const wchar_t *pwszPath)
-{
- return chdir(T2Utf(pwszPath));
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MFilePath::MFileIterator::iterator MFilePath::MFileIterator::iterator::operator++()
-{
- // if (ptr != nullptr) {
- // if (::FindNextFileW(ptr->m_hFind, &ptr->m_data) == 0) {
- // ::FindClose(ptr->m_hFind); ptr->m_hFind = INVALID_HANDLE_VALUE;
- // ptr = nullptr;
- // }
- // }
- return *this;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MFilePath::MFileIterator::MFileIterator(const wchar_t *pwszPath)
-{
- // if (pwszPath != nullptr)
- // m_hFind = ::FindFirstFileW(pwszPath, &m_data);
-}
-
-MFilePath::MFileIterator::~MFileIterator()
-{
- // if (m_hFind != INVALID_HANDLE_VALUE)
- // ::FindClose(m_hFind);
-}
-
-MFilePath::MFileIterator::iterator MFilePath::MFileIterator::begin()
-{
- // if (m_hFind == INVALID_HANDLE_VALUE)
- // return MFilePath::MFileIterator::iterator(nullptr);
-
- return MFilePath::MFileIterator::iterator(this);
-}
-
-bool MFilePath::MFileIterator::isDir() const
-{
- //if (m_hFind == INVALID_HANDLE_VALUE)
- // return false;
-
- return (m_flags & 1) != 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-bool MFilePath::isExist() const
-{
- return ::access(T2Utf(c_str()), 0) == 0;
-}
-
-bool MFilePath::move(const wchar_t *pwszDest)
-{
- return ::rename(T2Utf(c_str()), T2Utf(pwszDest)) != 0;
-}
-
-MFilePath::MFileIterator MFilePath::search()
-{
- return MFileIterator(c_str());
-}
+/*
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "../stdafx.h"
+#include <unistd.h>
+
+MIR_CORE_DLL(FILE*) _wfopen(const wchar_t *pwszFileName, const wchar_t *pwszMode)
+{
+ return fopen(T2Utf(pwszFileName), T2Utf(pwszMode));
+}
+
+MIR_CORE_DLL(int) _wchdir(const wchar_t *pwszPath)
+{
+ return chdir(T2Utf(pwszPath));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MFilePath::MFileIterator::iterator MFilePath::MFileIterator::iterator::operator++()
+{
+ // if (ptr != nullptr) {
+ // if (::FindNextFileW(ptr->m_hFind, &ptr->m_data) == 0) {
+ // ::FindClose(ptr->m_hFind); ptr->m_hFind = INVALID_HANDLE_VALUE;
+ // ptr = nullptr;
+ // }
+ // }
+ return *this;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MFilePath::MFileIterator::MFileIterator(const wchar_t *pwszPath)
+{
+ // if (pwszPath != nullptr)
+ // m_hFind = ::FindFirstFileW(pwszPath, &m_data);
+}
+
+MFilePath::MFileIterator::~MFileIterator()
+{
+ // if (m_hFind != INVALID_HANDLE_VALUE)
+ // ::FindClose(m_hFind);
+}
+
+MFilePath::MFileIterator::iterator MFilePath::MFileIterator::begin()
+{
+ // if (m_hFind == INVALID_HANDLE_VALUE)
+ // return MFilePath::MFileIterator::iterator(nullptr);
+
+ return MFilePath::MFileIterator::iterator(this);
+}
+
+bool MFilePath::MFileIterator::isDir() const
+{
+ //if (m_hFind == INVALID_HANDLE_VALUE)
+ // return false;
+
+ return (m_flags & 1) != 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+bool MFilePath::isExist() const
+{
+ return ::access(T2Utf(c_str()), 0) == 0;
+}
+
+bool MFilePath::move(const wchar_t *pwszDest)
+{
+ return ::rename(T2Utf(c_str()), T2Utf(pwszDest)) != 0;
+}
+
+MFilePath::MFileIterator MFilePath::search()
+{
+ return MFileIterator(c_str());
+}
diff --git a/src/mir_core/src/Linux/strutil.cpp b/src/mir_core/src/Linux/strutil.cpp
index a2b854fcc8..8c44a3dd2b 100644
--- a/src/mir_core/src/Linux/strutil.cpp
+++ b/src/mir_core/src/Linux/strutil.cpp
@@ -1,48 +1,48 @@
-/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "../stdafx.h"
-
-MIR_CORE_DLL(char*) strlwr(char *str)
-{
- for (char *p = str; *p; p++)
- *p = tolower(*p);
-
- return str;
-}
-
-MIR_CORE_DLL(char*) strupr(char *str)
-{
- for (char *p = str; *p; p++)
- *p = toupper(*p);
-
- return str;
-}
-
-MIR_CORE_DLL(char*) strrev(char *str)
-{
- if (!str || !*str)
- return str;
-
- char *p1, *p2;
- for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) {
- *p1 ^= *p2;
- *p2 ^= *p1;
- *p1 ^= *p2;
- }
- return str;
-}
+/*
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "../stdafx.h"
+
+MIR_CORE_DLL(char*) strlwr(char *str)
+{
+ for (char *p = str; *p; p++)
+ *p = tolower(*p);
+
+ return str;
+}
+
+MIR_CORE_DLL(char*) strupr(char *str)
+{
+ for (char *p = str; *p; p++)
+ *p = toupper(*p);
+
+ return str;
+}
+
+MIR_CORE_DLL(char*) strrev(char *str)
+{
+ if (!str || !*str)
+ return str;
+
+ char *p1, *p2;
+ for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) {
+ *p1 ^= *p2;
+ *p2 ^= *p1;
+ *p1 ^= *p2;
+ }
+ return str;
+}
diff --git a/src/mir_core/src/Windows/CCtrlBase.cpp b/src/mir_core/src/Windows/CCtrlBase.cpp
index 58787b02db..ad80ccffe7 100644
--- a/src/mir_core/src/Windows/CCtrlBase.cpp
+++ b/src/mir_core/src/Windows/CCtrlBase.cpp
@@ -1,224 +1,224 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-static mir_cs csCtrl;
-
-static int CompareControls(const CCtrlBase *p1, const CCtrlBase *p2)
-{
- return (INT_PTR)p1->GetHwnd() - (INT_PTR)p2->GetHwnd();
-}
-static LIST<CCtrlBase> arControls(10, CompareControls);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlBase
-
-CCtrlBase::CCtrlBase(CDlgBase *wnd, int idCtrl) :
- m_parentWnd(wnd),
- m_idCtrl(idCtrl)
-{
- if (wnd)
- wnd->AddControl(this);
-}
-
-CCtrlBase::~CCtrlBase()
-{
-}
-
-void CCtrlBase::OnInit()
-{
- m_hwnd = (m_idCtrl && m_parentWnd && m_parentWnd->GetHwnd()) ? GetDlgItem(m_parentWnd->GetHwnd(), m_idCtrl) : nullptr;
-}
-
-void CCtrlBase::OnDestroy()
-{
- PVOID bullshit[2]; // vfptr + hwnd
- bullshit[1] = m_hwnd;
- CCtrlBase *pCtrl = arControls.find((CCtrlBase*)&bullshit);
- if (pCtrl) {
- pCtrl->Unsubclass();
- arControls.remove(pCtrl);
- }
-
- m_hwnd = nullptr;
-}
-
-bool CCtrlBase::OnApply()
-{
- m_bChanged = false;
- return true;
-}
-
-void CCtrlBase::OnReset()
-{}
-
-void CCtrlBase::Show(bool bShow)
-{
- ::ShowWindow(m_hwnd, bShow ? SW_SHOW : SW_HIDE);
-}
-
-void CCtrlBase::Enable(bool bIsEnable)
-{
- ::EnableWindow(m_hwnd, bIsEnable);
-}
-
-bool CCtrlBase::Enabled() const
-{
- return (m_hwnd) ? IsWindowEnabled(m_hwnd) != 0 : false;
-}
-
-void CCtrlBase::NotifyChange()
-{
- if (!m_parentWnd)
- return;
-
- if (m_parentWnd->IsInitialized()) {
- m_bChanged = true;
- if (!m_bSilent)
- m_parentWnd->NotifyChange();
- }
-
- OnChange(this);
-}
-
-LRESULT CCtrlBase::SendMsg(UINT Msg, WPARAM wParam, LPARAM lParam) const
-{
- return ::SendMessage(m_hwnd, Msg, wParam, lParam);
-}
-
-void CCtrlBase::SetText(const wchar_t *text)
-{
- ::SetWindowText(m_hwnd, text);
-}
-
-void CCtrlBase::SetTextA(const char *text)
-{
- ::SetWindowTextA(m_hwnd, text);
-}
-
-void CCtrlBase::SetDraw(bool bEnable)
-{
- ::SendMessage(m_hwnd, WM_SETREDRAW, bEnable, 0);
-}
-
-void CCtrlBase::SetInt(int value)
-{
- wchar_t buf[32] = { 0 };
- mir_snwprintf(buf, L"%d", value);
- SetWindowText(m_hwnd, buf);
-}
-
-wchar_t* CCtrlBase::GetText() const
-{
- int length = GetWindowTextLengthW(m_hwnd);
- wchar_t *result = (wchar_t *)mir_alloc((length+1) * sizeof(wchar_t));
- if (length)
- GetWindowTextW(m_hwnd, result, length+1);
- result[length] = 0;
- return result;
-}
-
-char* CCtrlBase::GetTextA() const
-{
- int length = GetWindowTextLengthA(m_hwnd);
- char *result = (char *)mir_alloc((length+1) * sizeof(char));
- if (length)
- GetWindowTextA(m_hwnd, result, length+1);
- result[length] = 0;
- return result;
-}
-
-char* CCtrlBase::GetTextU() const
-{
- return mir_utf8encodeW(ptrW(GetText()));
-}
-
-wchar_t* CCtrlBase::GetText(wchar_t *buf, size_t size) const
-{
- GetWindowTextW(m_hwnd, buf, (int)size);
- buf[size - 1] = 0;
- return buf;
-}
-
-char* CCtrlBase::GetTextA(char *buf, size_t size) const
-{
- GetWindowTextA(m_hwnd, buf, (int)size);
- buf[size - 1] = 0;
- return buf;
-}
-
-char* CCtrlBase::GetTextU(char *buf, size_t size) const
-{
- ptrW wszText(GetText());
- strncpy_s(buf, size, T2Utf(wszText), _TRUNCATE);
- return buf;
-}
-
-int CCtrlBase::GetInt() const
-{
- int length = GetWindowTextLengthW(m_hwnd) + 1;
- wchar_t *result = (wchar_t *)_alloca(length * sizeof(wchar_t));
- GetWindowTextW(m_hwnd, result, length);
- return _wtoi(result);
-}
-
-void CCtrlBase::GetCaretPos(CContextMenuPos &pos) const
-{
- pos.pCtrl = this;
- pos.iCurr = -1;
-
- if (pos.pt.x == 0 && pos.pt.y == 0)
- GetCursorPos(&pos.pt);
-}
-
-LRESULT CCtrlBase::CustomWndProc(UINT, WPARAM, LPARAM)
-{
- return FALSE;
-}
-
-LRESULT CALLBACK CCtrlBase::GlobalSubclassWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- PVOID bullshit[2]; // vfptr + hwnd
- bullshit[1] = hwnd;
- CCtrlBase *pCtrl = arControls.find((CCtrlBase*)&bullshit);
- if (pCtrl) {
- LRESULT res = pCtrl->CustomWndProc(msg, wParam, lParam);
- if (res != 0)
- return res;
- }
-
- return mir_callNextSubclass(hwnd, GlobalSubclassWndProc, msg, wParam, lParam);
-}
-
-void CCtrlBase::Subclass()
-{
- mir_subclassWindow(m_hwnd, GlobalSubclassWndProc);
-
- mir_cslock lck(csCtrl);
- arControls.insert(this);
-}
-
-void CCtrlBase::Unsubclass()
-{
- mir_unsubclassWindow(m_hwnd, GlobalSubclassWndProc);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+static mir_cs csCtrl;
+
+static int CompareControls(const CCtrlBase *p1, const CCtrlBase *p2)
+{
+ return (INT_PTR)p1->GetHwnd() - (INT_PTR)p2->GetHwnd();
+}
+static LIST<CCtrlBase> arControls(10, CompareControls);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlBase
+
+CCtrlBase::CCtrlBase(CDlgBase *wnd, int idCtrl) :
+ m_parentWnd(wnd),
+ m_idCtrl(idCtrl)
+{
+ if (wnd)
+ wnd->AddControl(this);
+}
+
+CCtrlBase::~CCtrlBase()
+{
+}
+
+void CCtrlBase::OnInit()
+{
+ m_hwnd = (m_idCtrl && m_parentWnd && m_parentWnd->GetHwnd()) ? GetDlgItem(m_parentWnd->GetHwnd(), m_idCtrl) : nullptr;
+}
+
+void CCtrlBase::OnDestroy()
+{
+ PVOID bullshit[2]; // vfptr + hwnd
+ bullshit[1] = m_hwnd;
+ CCtrlBase *pCtrl = arControls.find((CCtrlBase*)&bullshit);
+ if (pCtrl) {
+ pCtrl->Unsubclass();
+ arControls.remove(pCtrl);
+ }
+
+ m_hwnd = nullptr;
+}
+
+bool CCtrlBase::OnApply()
+{
+ m_bChanged = false;
+ return true;
+}
+
+void CCtrlBase::OnReset()
+{}
+
+void CCtrlBase::Show(bool bShow)
+{
+ ::ShowWindow(m_hwnd, bShow ? SW_SHOW : SW_HIDE);
+}
+
+void CCtrlBase::Enable(bool bIsEnable)
+{
+ ::EnableWindow(m_hwnd, bIsEnable);
+}
+
+bool CCtrlBase::Enabled() const
+{
+ return (m_hwnd) ? IsWindowEnabled(m_hwnd) != 0 : false;
+}
+
+void CCtrlBase::NotifyChange()
+{
+ if (!m_parentWnd)
+ return;
+
+ if (m_parentWnd->IsInitialized()) {
+ m_bChanged = true;
+ if (!m_bSilent)
+ m_parentWnd->NotifyChange();
+ }
+
+ OnChange(this);
+}
+
+LRESULT CCtrlBase::SendMsg(UINT Msg, WPARAM wParam, LPARAM lParam) const
+{
+ return ::SendMessage(m_hwnd, Msg, wParam, lParam);
+}
+
+void CCtrlBase::SetText(const wchar_t *text)
+{
+ ::SetWindowText(m_hwnd, text);
+}
+
+void CCtrlBase::SetTextA(const char *text)
+{
+ ::SetWindowTextA(m_hwnd, text);
+}
+
+void CCtrlBase::SetDraw(bool bEnable)
+{
+ ::SendMessage(m_hwnd, WM_SETREDRAW, bEnable, 0);
+}
+
+void CCtrlBase::SetInt(int value)
+{
+ wchar_t buf[32] = { 0 };
+ mir_snwprintf(buf, L"%d", value);
+ SetWindowText(m_hwnd, buf);
+}
+
+wchar_t* CCtrlBase::GetText() const
+{
+ int length = GetWindowTextLengthW(m_hwnd);
+ wchar_t *result = (wchar_t *)mir_alloc((length+1) * sizeof(wchar_t));
+ if (length)
+ GetWindowTextW(m_hwnd, result, length+1);
+ result[length] = 0;
+ return result;
+}
+
+char* CCtrlBase::GetTextA() const
+{
+ int length = GetWindowTextLengthA(m_hwnd);
+ char *result = (char *)mir_alloc((length+1) * sizeof(char));
+ if (length)
+ GetWindowTextA(m_hwnd, result, length+1);
+ result[length] = 0;
+ return result;
+}
+
+char* CCtrlBase::GetTextU() const
+{
+ return mir_utf8encodeW(ptrW(GetText()));
+}
+
+wchar_t* CCtrlBase::GetText(wchar_t *buf, size_t size) const
+{
+ GetWindowTextW(m_hwnd, buf, (int)size);
+ buf[size - 1] = 0;
+ return buf;
+}
+
+char* CCtrlBase::GetTextA(char *buf, size_t size) const
+{
+ GetWindowTextA(m_hwnd, buf, (int)size);
+ buf[size - 1] = 0;
+ return buf;
+}
+
+char* CCtrlBase::GetTextU(char *buf, size_t size) const
+{
+ ptrW wszText(GetText());
+ strncpy_s(buf, size, T2Utf(wszText), _TRUNCATE);
+ return buf;
+}
+
+int CCtrlBase::GetInt() const
+{
+ int length = GetWindowTextLengthW(m_hwnd) + 1;
+ wchar_t *result = (wchar_t *)_alloca(length * sizeof(wchar_t));
+ GetWindowTextW(m_hwnd, result, length);
+ return _wtoi(result);
+}
+
+void CCtrlBase::GetCaretPos(CContextMenuPos &pos) const
+{
+ pos.pCtrl = this;
+ pos.iCurr = -1;
+
+ if (pos.pt.x == 0 && pos.pt.y == 0)
+ GetCursorPos(&pos.pt);
+}
+
+LRESULT CCtrlBase::CustomWndProc(UINT, WPARAM, LPARAM)
+{
+ return FALSE;
+}
+
+LRESULT CALLBACK CCtrlBase::GlobalSubclassWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ PVOID bullshit[2]; // vfptr + hwnd
+ bullshit[1] = hwnd;
+ CCtrlBase *pCtrl = arControls.find((CCtrlBase*)&bullshit);
+ if (pCtrl) {
+ LRESULT res = pCtrl->CustomWndProc(msg, wParam, lParam);
+ if (res != 0)
+ return res;
+ }
+
+ return mir_callNextSubclass(hwnd, GlobalSubclassWndProc, msg, wParam, lParam);
+}
+
+void CCtrlBase::Subclass()
+{
+ mir_subclassWindow(m_hwnd, GlobalSubclassWndProc);
+
+ mir_cslock lck(csCtrl);
+ arControls.insert(this);
+}
+
+void CCtrlBase::Unsubclass()
+{
+ mir_unsubclassWindow(m_hwnd, GlobalSubclassWndProc);
+}
diff --git a/src/mir_core/src/Windows/CCtrlButton.cpp b/src/mir_core/src/Windows/CCtrlButton.cpp
index bf84cad74f..b39e855332 100644
--- a/src/mir_core/src/Windows/CCtrlButton.cpp
+++ b/src/mir_core/src/Windows/CCtrlButton.cpp
@@ -1,54 +1,54 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlButton
-
-CCtrlButton::CCtrlButton(CDlgBase* wnd, int idCtrl)
- : CCtrlBase(wnd, idCtrl)
-{}
-
-BOOL CCtrlButton::OnCommand(HWND, uint16_t, uint16_t idCode)
-{
- if (idCode == BN_CLICKED)
- OnClick(this);
- return FALSE;
-}
-
-void CCtrlButton::Click()
-{
- if (Enabled())
- ::SendMessage(m_parentWnd->GetHwnd(), WM_COMMAND, MAKELONG(m_idCtrl, BN_CLICKED), 0);
-}
-
-bool CCtrlButton::IsPushed() const
-{
- return ::SendMessage(m_hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED;
-}
-
-void CCtrlButton::Push(bool bPushed)
-{
- if (Enabled())
- ::SendMessage(m_hwnd, BM_SETCHECK, (bPushed) ? BST_CHECKED : BST_UNCHECKED, 0);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlButton
+
+CCtrlButton::CCtrlButton(CDlgBase* wnd, int idCtrl)
+ : CCtrlBase(wnd, idCtrl)
+{}
+
+BOOL CCtrlButton::OnCommand(HWND, uint16_t, uint16_t idCode)
+{
+ if (idCode == BN_CLICKED)
+ OnClick(this);
+ return FALSE;
+}
+
+void CCtrlButton::Click()
+{
+ if (Enabled())
+ ::SendMessage(m_parentWnd->GetHwnd(), WM_COMMAND, MAKELONG(m_idCtrl, BN_CLICKED), 0);
+}
+
+bool CCtrlButton::IsPushed() const
+{
+ return ::SendMessage(m_hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED;
+}
+
+void CCtrlButton::Push(bool bPushed)
+{
+ if (Enabled())
+ ::SendMessage(m_hwnd, BM_SETCHECK, (bPushed) ? BST_CHECKED : BST_UNCHECKED, 0);
+}
diff --git a/src/mir_core/src/Windows/CCtrlCheck.cpp b/src/mir_core/src/Windows/CCtrlCheck.cpp
index 9c1281e8b8..3258dce27f 100644
--- a/src/mir_core/src/Windows/CCtrlCheck.cpp
+++ b/src/mir_core/src/Windows/CCtrlCheck.cpp
@@ -1,68 +1,68 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlCheck class
-
-CCtrlCheck::CCtrlCheck(CDlgBase *dlg, int ctrlId)
- : CCtrlData(dlg, ctrlId)
-{
- m_bNotifiable = true;
-}
-
-BOOL CCtrlCheck::OnCommand(HWND, uint16_t, uint16_t)
-{
- NotifyChange();
- return TRUE;
-}
-
-bool CCtrlCheck::OnApply()
-{
- CSuper::OnApply();
-
- if (m_dbLink != nullptr)
- SaveInt(GetState());
- return true;
-}
-
-void CCtrlCheck::OnReset()
-{
- if (m_dbLink != nullptr)
- SetState(LoadInt());
-}
-
-int CCtrlCheck::GetState() const
-{
- return ::SendMessage(m_hwnd, BM_GETCHECK, 0, 0);
-}
-
-void CCtrlCheck::SetState(int state)
-{
- ::SendMessage(m_hwnd, BM_SETCHECK, state, 0);
-}
-
-bool CCtrlCheck::IsChecked()
-{
- return GetState() == BST_CHECKED;
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlCheck class
+
+CCtrlCheck::CCtrlCheck(CDlgBase *dlg, int ctrlId)
+ : CCtrlData(dlg, ctrlId)
+{
+ m_bNotifiable = true;
+}
+
+BOOL CCtrlCheck::OnCommand(HWND, uint16_t, uint16_t)
+{
+ NotifyChange();
+ return TRUE;
+}
+
+bool CCtrlCheck::OnApply()
+{
+ CSuper::OnApply();
+
+ if (m_dbLink != nullptr)
+ SaveInt(GetState());
+ return true;
+}
+
+void CCtrlCheck::OnReset()
+{
+ if (m_dbLink != nullptr)
+ SetState(LoadInt());
+}
+
+int CCtrlCheck::GetState() const
+{
+ return ::SendMessage(m_hwnd, BM_GETCHECK, 0, 0);
+}
+
+void CCtrlCheck::SetState(int state)
+{
+ ::SendMessage(m_hwnd, BM_SETCHECK, state, 0);
+}
+
+bool CCtrlCheck::IsChecked()
+{
+ return GetState() == BST_CHECKED;
+}
diff --git a/src/mir_core/src/Windows/CCtrlClc.cpp b/src/mir_core/src/Windows/CCtrlClc.cpp
index 3e208679d4..14e88335a0 100644
--- a/src/mir_core/src/Windows/CCtrlClc.cpp
+++ b/src/mir_core/src/Windows/CCtrlClc.cpp
@@ -1,211 +1,211 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlClc
-
-CCtrlClc::CCtrlClc(CDlgBase *dlg, int ctrlId)
- : CCtrlBase(dlg, ctrlId)
-{}
-
-BOOL CCtrlClc::OnNotify(int, NMHDR *pnmh)
-{
- TEventInfo evt = { this, (NMCLISTCONTROL *)pnmh };
- switch (pnmh->code) {
- case CLN_EXPANDED: OnExpanded(&evt); break;
- case CLN_LISTREBUILT: OnListRebuilt(&evt); break;
- case CLN_ITEMCHECKED: OnItemChecked(&evt); break;
- case CLN_DRAGGING: OnDragging(&evt); break;
- case CLN_DROPPED: OnDropped(&evt); break;
- case CLN_LISTSIZECHANGE: OnListSizeChange(&evt); break;
- case CLN_OPTIONSCHANGED: OnOptionsChanged(&evt); break;
- case CLN_DRAGSTOP: OnDragStop(&evt); break;
- case CLN_NEWCONTACT: OnNewContact(&evt); break;
- case CLN_CONTACTMOVED: OnContactMoved(&evt); break;
- case NM_CLICK: OnClick(&evt); break;
-
- case CLN_CHECKCHANGED:
- OnCheckChanged(&evt);
- NotifyChange();
- break;
- }
- return FALSE;
-}
-
-void CCtrlClc::AddContact(MCONTACT hContact)
-{ SendMessage(m_hwnd, CLM_ADDCONTACT, hContact, 0);
-}
-
-void CCtrlClc::AddGroup(HANDLE hGroup)
-{ SendMessage(m_hwnd, CLM_ADDGROUP, (WPARAM)hGroup, 0);
-}
-
-void CCtrlClc::AutoRebuild()
-{ SendMessage(m_hwnd, CLM_AUTOREBUILD, 0, 0);
-}
-
-void CCtrlClc::DeleteItem(HANDLE hItem)
-{ SendMessage(m_hwnd, CLM_DELETEITEM, (WPARAM)hItem, 0);
-}
-
-void CCtrlClc::EditLabel(HANDLE hItem)
-{ SendMessage(m_hwnd, CLM_EDITLABEL, (WPARAM)hItem, 0);
-}
-
-void CCtrlClc::EndEditLabel(bool save)
-{ SendMessage(m_hwnd, CLM_ENDEDITLABELNOW, save ? 0 : 1, 0);
-}
-
-void CCtrlClc::EnsureVisible(HANDLE hItem, bool partialOk)
-{ SendMessage(m_hwnd, CLM_ENSUREVISIBLE, (WPARAM)hItem, partialOk ? TRUE : FALSE);
-}
-
-void CCtrlClc::Expand(HANDLE hItem, uint32_t flags)
-{ SendMessage(m_hwnd, CLM_EXPAND, (WPARAM)hItem, flags);
-}
-
-HANDLE CCtrlClc::FindContact(MCONTACT hContact)
-{ return (HANDLE)SendMessage(m_hwnd, CLM_FINDCONTACT, hContact, 0);
-}
-
-HANDLE CCtrlClc::FindGroup(MGROUP hGroup)
-{ return (HANDLE)SendMessage(m_hwnd, CLM_FINDGROUP, hGroup, 0);
-}
-
-COLORREF CCtrlClc::GetBkColor() const
-{ return (COLORREF)SendMessage(m_hwnd, CLM_GETBKCOLOR, 0, 0);
-}
-
-bool CCtrlClc::GetCheck(HANDLE hItem) const
-{ return SendMessage(m_hwnd, CLM_GETCHECKMARK, (WPARAM)hItem, 0) ? true : false;
-}
-
-int CCtrlClc::GetCount() const
-{ return SendMessage(m_hwnd, CLM_GETCOUNT, 0, 0);
-}
-
-HWND CCtrlClc::GetEditControl() const
-{ return (HWND)SendMessage(m_hwnd, CLM_GETEDITCONTROL, 0, 0);
-}
-
-uint32_t CCtrlClc::GetExpand(HANDLE hItem) const
-{ return SendMessage(m_hwnd, CLM_GETEXPAND, (WPARAM)hItem, 0);
-}
-
-int CCtrlClc::GetExtraColumns() const
-{ return SendMessage(m_hwnd, CLM_GETEXTRACOLUMNS, 0, 0);
-}
-
-uint8_t CCtrlClc::GetExtraImage(HANDLE hItem, int iColumn) const
-{
- return (uint8_t)(SendMessage(m_hwnd, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, 0)) & 0xFFFF);
-}
-
-HIMAGELIST CCtrlClc::GetExtraImageList() const
-{ return (HIMAGELIST)SendMessage(m_hwnd, CLM_GETEXTRAIMAGELIST, 0, 0);
-}
-
-HFONT CCtrlClc::GetFont(int iFontId) const
-{ return (HFONT)SendMessage(m_hwnd, CLM_GETFONT, (WPARAM)iFontId, 0);
-}
-
-HANDLE CCtrlClc::GetSelection() const
-{ return (HANDLE)SendMessage(m_hwnd, CLM_GETSELECTION, 0, 0);
-}
-
-HANDLE CCtrlClc::HitTest(int x, int y, uint32_t *hitTest) const
-{ return (HANDLE)SendMessage(m_hwnd, CLM_HITTEST, (WPARAM)hitTest, MAKELPARAM(x,y));
-}
-
-void CCtrlClc::SelectItem(HANDLE hItem)
-{ SendMessage(m_hwnd, CLM_SELECTITEM, (WPARAM)hItem, 0);
-}
-
-void CCtrlClc::SetBkColor(COLORREF clBack)
-{ SendMessage(m_hwnd, CLM_SETBKCOLOR, (WPARAM)clBack, 0);
-}
-
-void CCtrlClc::SetCheck(HANDLE hItem, bool check)
-{ SendMessage(m_hwnd, CLM_SETCHECKMARK, (WPARAM)hItem, check ? 1 : 0);
-}
-
-void CCtrlClc::SetExtraColumns(int iColumns)
-{ SendMessage(m_hwnd, CLM_SETEXTRACOLUMNS, (WPARAM)iColumns, 0);
-}
-
-void CCtrlClc::SetExtraImage(HANDLE hItem, int iColumn, int iImage)
-{ SendMessage(m_hwnd, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, iImage));
-}
-
-void CCtrlClc::SetExtraImageList(HIMAGELIST hImgList)
-{ SendMessage(m_hwnd, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hImgList);
-}
-
-void CCtrlClc::SetFont(int iFontId, HANDLE hFont, bool bRedraw)
-{ SendMessage(m_hwnd, CLM_SETFONT, (WPARAM)hFont, MAKELPARAM(bRedraw ? 1 : 0, iFontId));
-}
-
-void CCtrlClc::SetItemText(HANDLE hItem, char *szText)
-{ SendMessage(m_hwnd, CLM_SETITEMTEXT, (WPARAM)hItem, (LPARAM)szText);
-}
-
-void CCtrlClc::SetHideEmptyGroups(bool state)
-{ SendMessage(m_hwnd, CLM_SETHIDEEMPTYGROUPS, state ? 1 : 0, 0);
-}
-
-bool CCtrlClc::GetHideOfflineRoot() const
-{ return SendMessage(m_hwnd, CLM_GETHIDEOFFLINEROOT, 0, 0) ? true : false;
-}
-
-void CCtrlClc::SetHideOfflineRoot(bool state)
-{ SendMessage(m_hwnd, CLM_SETHIDEOFFLINEROOT, state ? 1 : 0, 9);
-}
-
-void CCtrlClc::SetUseGroups(bool state)
-{ SendMessage(m_hwnd, CLM_SETUSEGROUPS, state ? 1 : 0, 0);
-}
-
-void CCtrlClc::SetOfflineModes(uint32_t modes)
-{ SendMessage(m_hwnd, CLM_SETOFFLINEMODES, modes, 0);
-}
-
-uint32_t CCtrlClc::GetExStyle() const
-{ return SendMessage(m_hwnd, CLM_GETEXSTYLE, 0, 0);
-}
-
-void CCtrlClc::SetExStyle(uint32_t exStyle)
-{ SendMessage(m_hwnd, CLM_SETEXSTYLE, (WPARAM)exStyle, 0);
-}
-
-HANDLE CCtrlClc::AddInfoItem(CLCINFOITEM *cii)
-{ return (HANDLE)SendMessage(m_hwnd, CLM_ADDINFOITEM, 0, (LPARAM)cii);
-}
-
-int CCtrlClc::GetItemType(HANDLE hItem) const
-{ return SendMessage(m_hwnd, CLM_GETITEMTYPE, (WPARAM)hItem, 0);
-}
-
-HANDLE CCtrlClc::GetNextItem(HANDLE hItem, uint32_t flags) const
-{ return (HANDLE)SendMessage(m_hwnd, CLM_GETNEXTITEM, (WPARAM)flags, (LPARAM)hItem);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlClc
+
+CCtrlClc::CCtrlClc(CDlgBase *dlg, int ctrlId)
+ : CCtrlBase(dlg, ctrlId)
+{}
+
+BOOL CCtrlClc::OnNotify(int, NMHDR *pnmh)
+{
+ TEventInfo evt = { this, (NMCLISTCONTROL *)pnmh };
+ switch (pnmh->code) {
+ case CLN_EXPANDED: OnExpanded(&evt); break;
+ case CLN_LISTREBUILT: OnListRebuilt(&evt); break;
+ case CLN_ITEMCHECKED: OnItemChecked(&evt); break;
+ case CLN_DRAGGING: OnDragging(&evt); break;
+ case CLN_DROPPED: OnDropped(&evt); break;
+ case CLN_LISTSIZECHANGE: OnListSizeChange(&evt); break;
+ case CLN_OPTIONSCHANGED: OnOptionsChanged(&evt); break;
+ case CLN_DRAGSTOP: OnDragStop(&evt); break;
+ case CLN_NEWCONTACT: OnNewContact(&evt); break;
+ case CLN_CONTACTMOVED: OnContactMoved(&evt); break;
+ case NM_CLICK: OnClick(&evt); break;
+
+ case CLN_CHECKCHANGED:
+ OnCheckChanged(&evt);
+ NotifyChange();
+ break;
+ }
+ return FALSE;
+}
+
+void CCtrlClc::AddContact(MCONTACT hContact)
+{ SendMessage(m_hwnd, CLM_ADDCONTACT, hContact, 0);
+}
+
+void CCtrlClc::AddGroup(HANDLE hGroup)
+{ SendMessage(m_hwnd, CLM_ADDGROUP, (WPARAM)hGroup, 0);
+}
+
+void CCtrlClc::AutoRebuild()
+{ SendMessage(m_hwnd, CLM_AUTOREBUILD, 0, 0);
+}
+
+void CCtrlClc::DeleteItem(HANDLE hItem)
+{ SendMessage(m_hwnd, CLM_DELETEITEM, (WPARAM)hItem, 0);
+}
+
+void CCtrlClc::EditLabel(HANDLE hItem)
+{ SendMessage(m_hwnd, CLM_EDITLABEL, (WPARAM)hItem, 0);
+}
+
+void CCtrlClc::EndEditLabel(bool save)
+{ SendMessage(m_hwnd, CLM_ENDEDITLABELNOW, save ? 0 : 1, 0);
+}
+
+void CCtrlClc::EnsureVisible(HANDLE hItem, bool partialOk)
+{ SendMessage(m_hwnd, CLM_ENSUREVISIBLE, (WPARAM)hItem, partialOk ? TRUE : FALSE);
+}
+
+void CCtrlClc::Expand(HANDLE hItem, uint32_t flags)
+{ SendMessage(m_hwnd, CLM_EXPAND, (WPARAM)hItem, flags);
+}
+
+HANDLE CCtrlClc::FindContact(MCONTACT hContact)
+{ return (HANDLE)SendMessage(m_hwnd, CLM_FINDCONTACT, hContact, 0);
+}
+
+HANDLE CCtrlClc::FindGroup(MGROUP hGroup)
+{ return (HANDLE)SendMessage(m_hwnd, CLM_FINDGROUP, hGroup, 0);
+}
+
+COLORREF CCtrlClc::GetBkColor() const
+{ return (COLORREF)SendMessage(m_hwnd, CLM_GETBKCOLOR, 0, 0);
+}
+
+bool CCtrlClc::GetCheck(HANDLE hItem) const
+{ return SendMessage(m_hwnd, CLM_GETCHECKMARK, (WPARAM)hItem, 0) ? true : false;
+}
+
+int CCtrlClc::GetCount() const
+{ return SendMessage(m_hwnd, CLM_GETCOUNT, 0, 0);
+}
+
+HWND CCtrlClc::GetEditControl() const
+{ return (HWND)SendMessage(m_hwnd, CLM_GETEDITCONTROL, 0, 0);
+}
+
+uint32_t CCtrlClc::GetExpand(HANDLE hItem) const
+{ return SendMessage(m_hwnd, CLM_GETEXPAND, (WPARAM)hItem, 0);
+}
+
+int CCtrlClc::GetExtraColumns() const
+{ return SendMessage(m_hwnd, CLM_GETEXTRACOLUMNS, 0, 0);
+}
+
+uint8_t CCtrlClc::GetExtraImage(HANDLE hItem, int iColumn) const
+{
+ return (uint8_t)(SendMessage(m_hwnd, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, 0)) & 0xFFFF);
+}
+
+HIMAGELIST CCtrlClc::GetExtraImageList() const
+{ return (HIMAGELIST)SendMessage(m_hwnd, CLM_GETEXTRAIMAGELIST, 0, 0);
+}
+
+HFONT CCtrlClc::GetFont(int iFontId) const
+{ return (HFONT)SendMessage(m_hwnd, CLM_GETFONT, (WPARAM)iFontId, 0);
+}
+
+HANDLE CCtrlClc::GetSelection() const
+{ return (HANDLE)SendMessage(m_hwnd, CLM_GETSELECTION, 0, 0);
+}
+
+HANDLE CCtrlClc::HitTest(int x, int y, uint32_t *hitTest) const
+{ return (HANDLE)SendMessage(m_hwnd, CLM_HITTEST, (WPARAM)hitTest, MAKELPARAM(x,y));
+}
+
+void CCtrlClc::SelectItem(HANDLE hItem)
+{ SendMessage(m_hwnd, CLM_SELECTITEM, (WPARAM)hItem, 0);
+}
+
+void CCtrlClc::SetBkColor(COLORREF clBack)
+{ SendMessage(m_hwnd, CLM_SETBKCOLOR, (WPARAM)clBack, 0);
+}
+
+void CCtrlClc::SetCheck(HANDLE hItem, bool check)
+{ SendMessage(m_hwnd, CLM_SETCHECKMARK, (WPARAM)hItem, check ? 1 : 0);
+}
+
+void CCtrlClc::SetExtraColumns(int iColumns)
+{ SendMessage(m_hwnd, CLM_SETEXTRACOLUMNS, (WPARAM)iColumns, 0);
+}
+
+void CCtrlClc::SetExtraImage(HANDLE hItem, int iColumn, int iImage)
+{ SendMessage(m_hwnd, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, iImage));
+}
+
+void CCtrlClc::SetExtraImageList(HIMAGELIST hImgList)
+{ SendMessage(m_hwnd, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hImgList);
+}
+
+void CCtrlClc::SetFont(int iFontId, HANDLE hFont, bool bRedraw)
+{ SendMessage(m_hwnd, CLM_SETFONT, (WPARAM)hFont, MAKELPARAM(bRedraw ? 1 : 0, iFontId));
+}
+
+void CCtrlClc::SetItemText(HANDLE hItem, char *szText)
+{ SendMessage(m_hwnd, CLM_SETITEMTEXT, (WPARAM)hItem, (LPARAM)szText);
+}
+
+void CCtrlClc::SetHideEmptyGroups(bool state)
+{ SendMessage(m_hwnd, CLM_SETHIDEEMPTYGROUPS, state ? 1 : 0, 0);
+}
+
+bool CCtrlClc::GetHideOfflineRoot() const
+{ return SendMessage(m_hwnd, CLM_GETHIDEOFFLINEROOT, 0, 0) ? true : false;
+}
+
+void CCtrlClc::SetHideOfflineRoot(bool state)
+{ SendMessage(m_hwnd, CLM_SETHIDEOFFLINEROOT, state ? 1 : 0, 9);
+}
+
+void CCtrlClc::SetUseGroups(bool state)
+{ SendMessage(m_hwnd, CLM_SETUSEGROUPS, state ? 1 : 0, 0);
+}
+
+void CCtrlClc::SetOfflineModes(uint32_t modes)
+{ SendMessage(m_hwnd, CLM_SETOFFLINEMODES, modes, 0);
+}
+
+uint32_t CCtrlClc::GetExStyle() const
+{ return SendMessage(m_hwnd, CLM_GETEXSTYLE, 0, 0);
+}
+
+void CCtrlClc::SetExStyle(uint32_t exStyle)
+{ SendMessage(m_hwnd, CLM_SETEXSTYLE, (WPARAM)exStyle, 0);
+}
+
+HANDLE CCtrlClc::AddInfoItem(CLCINFOITEM *cii)
+{ return (HANDLE)SendMessage(m_hwnd, CLM_ADDINFOITEM, 0, (LPARAM)cii);
+}
+
+int CCtrlClc::GetItemType(HANDLE hItem) const
+{ return SendMessage(m_hwnd, CLM_GETITEMTYPE, (WPARAM)hItem, 0);
+}
+
+HANDLE CCtrlClc::GetNextItem(HANDLE hItem, uint32_t flags) const
+{ return (HANDLE)SendMessage(m_hwnd, CLM_GETNEXTITEM, (WPARAM)flags, (LPARAM)hItem);
+}
diff --git a/src/mir_core/src/Windows/CCtrlColor.cpp b/src/mir_core/src/Windows/CCtrlColor.cpp
index 97f5e48e02..b61fb5760a 100644
--- a/src/mir_core/src/Windows/CCtrlColor.cpp
+++ b/src/mir_core/src/Windows/CCtrlColor.cpp
@@ -1,61 +1,61 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlColor class
-
-CCtrlColor::CCtrlColor(CDlgBase *dlg, int ctrlId) :
- CCtrlData(dlg, ctrlId)
-{}
-
-BOOL CCtrlColor::OnCommand(HWND, uint16_t, uint16_t)
-{
- NotifyChange();
- return TRUE;
-}
-
-bool CCtrlColor::OnApply()
-{
- CSuper::OnApply();
-
- if (m_dbLink != nullptr)
- SaveInt(GetColor());
- return true;
-}
-
-void CCtrlColor::OnReset()
-{
- if (m_dbLink != nullptr)
- SetColor(LoadInt());
-}
-
-uint32_t CCtrlColor::GetColor()
-{
- return ::SendMessage(m_hwnd, CPM_GETCOLOUR, 0, 0);
-}
-
-void CCtrlColor::SetColor(uint32_t dwValue)
-{
- ::SendMessage(m_hwnd, CPM_SETCOLOUR, 0, dwValue);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlColor class
+
+CCtrlColor::CCtrlColor(CDlgBase *dlg, int ctrlId) :
+ CCtrlData(dlg, ctrlId)
+{}
+
+BOOL CCtrlColor::OnCommand(HWND, uint16_t, uint16_t)
+{
+ NotifyChange();
+ return TRUE;
+}
+
+bool CCtrlColor::OnApply()
+{
+ CSuper::OnApply();
+
+ if (m_dbLink != nullptr)
+ SaveInt(GetColor());
+ return true;
+}
+
+void CCtrlColor::OnReset()
+{
+ if (m_dbLink != nullptr)
+ SetColor(LoadInt());
+}
+
+uint32_t CCtrlColor::GetColor()
+{
+ return ::SendMessage(m_hwnd, CPM_GETCOLOUR, 0, 0);
+}
+
+void CCtrlColor::SetColor(uint32_t dwValue)
+{
+ ::SendMessage(m_hwnd, CPM_SETCOLOUR, 0, dwValue);
+}
diff --git a/src/mir_core/src/Windows/CCtrlCombo.cpp b/src/mir_core/src/Windows/CCtrlCombo.cpp
index 83cd721494..b935129b3f 100644
--- a/src/mir_core/src/Windows/CCtrlCombo.cpp
+++ b/src/mir_core/src/Windows/CCtrlCombo.cpp
@@ -1,185 +1,185 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlCombo class
-
-CCtrlCombo::CCtrlCombo(CDlgBase *dlg, int ctrlId)
- : CCtrlData(dlg, ctrlId)
-{}
-
-BOOL CCtrlCombo::OnCommand(HWND, uint16_t, uint16_t idCode)
-{
- switch (idCode) {
- case CBN_CLOSEUP: OnCloseup(this); break;
- case CBN_DROPDOWN: OnDropdown(this); break;
- case CBN_SELCHANGE: OnSelChanged(this); break;
- case CBN_KILLFOCUS: OnKillFocus(this); break;
-
- case CBN_EDITCHANGE:
- case CBN_EDITUPDATE:
- case CBN_SELENDOK:
- NotifyChange();
- break;
- }
- return TRUE;
-}
-
-void CCtrlCombo::OnInit()
-{
- CSuper::OnInit();
- OnReset();
-}
-
-bool CCtrlCombo::OnApply()
-{
- CSuper::OnApply();
-
- if (GetDataType() == DBVT_WCHAR) {
- int len = GetWindowTextLength(m_hwnd) + 1;
- wchar_t *buf = (wchar_t *)_alloca(sizeof(wchar_t) * len);
- GetWindowText(m_hwnd, buf, len);
- SaveText(buf);
- }
- else if (GetDataType() != DBVT_DELETED) {
- SaveInt(GetInt());
- }
- return true;
-}
-
-void CCtrlCombo::OnReset()
-{
- if (GetDataType() == DBVT_WCHAR)
- SetText(LoadText());
- else if (GetDataType() != DBVT_DELETED)
- SetInt(LoadInt());
-}
-
-LPARAM CCtrlCombo::GetCurData() const
-{
- return GetItemData(GetCurSel());
-}
-
-// selects line with userdata passed
-int CCtrlCombo::SelectData(LPARAM data)
-{
- int ret = -1, nCount = GetCount();
-
- for (int i = 0; i < nCount; i++)
- if (GetItemData(i) == data) {
- ret = i;
- break;
- }
-
- return SetCurSel(ret);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Windows API
-
-int CCtrlCombo::AddString(const wchar_t *text, LPARAM data)
-{
- int iItem = SendMessage(m_hwnd, CB_ADDSTRING, 0, (LPARAM)text);
- if (data)
- SendMessage(m_hwnd, CB_SETITEMDATA, iItem, data);
- return iItem;
-}
-
-int CCtrlCombo::AddStringA(const char *text, LPARAM data)
-{
- int iItem = SendMessageA(m_hwnd, CB_ADDSTRING, 0, (LPARAM)text);
- if (data)
- SendMessage(m_hwnd, CB_SETITEMDATA, iItem, data);
- return iItem;
-}
-
-void CCtrlCombo::DeleteString(int index)
-{ SendMessage(m_hwnd, CB_DELETESTRING, index, 0);
-}
-
-int CCtrlCombo::FindString(const wchar_t *str, int index, bool exact)
-{ return SendMessage(m_hwnd, exact?CB_FINDSTRINGEXACT:CB_FINDSTRING, index, (LPARAM)str);
-}
-
-int CCtrlCombo::FindStringA(const char *str, int index, bool exact)
-{ return SendMessageA(m_hwnd, exact?CB_FINDSTRINGEXACT:CB_FINDSTRING, index, (LPARAM)str);
-}
-
-int CCtrlCombo::GetCount() const
-{ return SendMessage(m_hwnd, CB_GETCOUNT, 0, 0);
-}
-
-int CCtrlCombo::GetCurSel() const
-{ return SendMessage(m_hwnd, CB_GETCURSEL, 0, 0);
-}
-
-bool CCtrlCombo::GetDroppedState() const
-{ return SendMessage(m_hwnd, CB_GETDROPPEDSTATE, 0, 0) ? true : false;
-}
-
-LPARAM CCtrlCombo::GetItemData(int index) const
-{ return SendMessage(m_hwnd, CB_GETITEMDATA, index, 0);
-}
-
-wchar_t* CCtrlCombo::GetItemText(int index) const
-{
- wchar_t *result = (wchar_t *)mir_alloc(sizeof(wchar_t) * (SendMessage(m_hwnd, CB_GETLBTEXTLEN, index, 0) + 1));
- SendMessage(m_hwnd, CB_GETLBTEXT, index, (LPARAM)result);
- return result;
-}
-
-wchar_t* CCtrlCombo::GetItemText(int index, wchar_t *buf, int size) const
-{
- wchar_t *result = (wchar_t *)_alloca(sizeof(wchar_t) * (SendMessage(m_hwnd, CB_GETLBTEXTLEN, index, 0) + 1));
- SendMessage(m_hwnd, CB_GETLBTEXT, index, (LPARAM)result);
- mir_wstrncpy(buf, result, size);
- return buf;
-}
-
-int CCtrlCombo::InsertString(const wchar_t *text, int pos, LPARAM data)
-{
- int iItem = SendMessage(m_hwnd, CB_INSERTSTRING, pos, (LPARAM)text);
- SendMessage(m_hwnd, CB_SETITEMDATA, iItem, data);
- return iItem;
-}
-
-void CCtrlCombo::ResetContent()
-{ SendMessage(m_hwnd, CB_RESETCONTENT, 0, 0);
-}
-
-int CCtrlCombo::SelectString(const wchar_t *str)
-{ return SendMessage(m_hwnd, CB_SELECTSTRING, 0, (LPARAM)str);
-}
-
-int CCtrlCombo::SetCurSel(int index)
-{ return SendMessage(m_hwnd, CB_SETCURSEL, index, 0);
-}
-
-void CCtrlCombo::SetItemData(int index, LPARAM data)
-{ SendMessage(m_hwnd, CB_SETITEMDATA, index, data);
-}
-
-void CCtrlCombo::ShowDropdown(bool show)
-{ SendMessage(m_hwnd, CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlCombo class
+
+CCtrlCombo::CCtrlCombo(CDlgBase *dlg, int ctrlId)
+ : CCtrlData(dlg, ctrlId)
+{}
+
+BOOL CCtrlCombo::OnCommand(HWND, uint16_t, uint16_t idCode)
+{
+ switch (idCode) {
+ case CBN_CLOSEUP: OnCloseup(this); break;
+ case CBN_DROPDOWN: OnDropdown(this); break;
+ case CBN_SELCHANGE: OnSelChanged(this); break;
+ case CBN_KILLFOCUS: OnKillFocus(this); break;
+
+ case CBN_EDITCHANGE:
+ case CBN_EDITUPDATE:
+ case CBN_SELENDOK:
+ NotifyChange();
+ break;
+ }
+ return TRUE;
+}
+
+void CCtrlCombo::OnInit()
+{
+ CSuper::OnInit();
+ OnReset();
+}
+
+bool CCtrlCombo::OnApply()
+{
+ CSuper::OnApply();
+
+ if (GetDataType() == DBVT_WCHAR) {
+ int len = GetWindowTextLength(m_hwnd) + 1;
+ wchar_t *buf = (wchar_t *)_alloca(sizeof(wchar_t) * len);
+ GetWindowText(m_hwnd, buf, len);
+ SaveText(buf);
+ }
+ else if (GetDataType() != DBVT_DELETED) {
+ SaveInt(GetInt());
+ }
+ return true;
+}
+
+void CCtrlCombo::OnReset()
+{
+ if (GetDataType() == DBVT_WCHAR)
+ SetText(LoadText());
+ else if (GetDataType() != DBVT_DELETED)
+ SetInt(LoadInt());
+}
+
+LPARAM CCtrlCombo::GetCurData() const
+{
+ return GetItemData(GetCurSel());
+}
+
+// selects line with userdata passed
+int CCtrlCombo::SelectData(LPARAM data)
+{
+ int ret = -1, nCount = GetCount();
+
+ for (int i = 0; i < nCount; i++)
+ if (GetItemData(i) == data) {
+ ret = i;
+ break;
+ }
+
+ return SetCurSel(ret);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Windows API
+
+int CCtrlCombo::AddString(const wchar_t *text, LPARAM data)
+{
+ int iItem = SendMessage(m_hwnd, CB_ADDSTRING, 0, (LPARAM)text);
+ if (data)
+ SendMessage(m_hwnd, CB_SETITEMDATA, iItem, data);
+ return iItem;
+}
+
+int CCtrlCombo::AddStringA(const char *text, LPARAM data)
+{
+ int iItem = SendMessageA(m_hwnd, CB_ADDSTRING, 0, (LPARAM)text);
+ if (data)
+ SendMessage(m_hwnd, CB_SETITEMDATA, iItem, data);
+ return iItem;
+}
+
+void CCtrlCombo::DeleteString(int index)
+{ SendMessage(m_hwnd, CB_DELETESTRING, index, 0);
+}
+
+int CCtrlCombo::FindString(const wchar_t *str, int index, bool exact)
+{ return SendMessage(m_hwnd, exact?CB_FINDSTRINGEXACT:CB_FINDSTRING, index, (LPARAM)str);
+}
+
+int CCtrlCombo::FindStringA(const char *str, int index, bool exact)
+{ return SendMessageA(m_hwnd, exact?CB_FINDSTRINGEXACT:CB_FINDSTRING, index, (LPARAM)str);
+}
+
+int CCtrlCombo::GetCount() const
+{ return SendMessage(m_hwnd, CB_GETCOUNT, 0, 0);
+}
+
+int CCtrlCombo::GetCurSel() const
+{ return SendMessage(m_hwnd, CB_GETCURSEL, 0, 0);
+}
+
+bool CCtrlCombo::GetDroppedState() const
+{ return SendMessage(m_hwnd, CB_GETDROPPEDSTATE, 0, 0) ? true : false;
+}
+
+LPARAM CCtrlCombo::GetItemData(int index) const
+{ return SendMessage(m_hwnd, CB_GETITEMDATA, index, 0);
+}
+
+wchar_t* CCtrlCombo::GetItemText(int index) const
+{
+ wchar_t *result = (wchar_t *)mir_alloc(sizeof(wchar_t) * (SendMessage(m_hwnd, CB_GETLBTEXTLEN, index, 0) + 1));
+ SendMessage(m_hwnd, CB_GETLBTEXT, index, (LPARAM)result);
+ return result;
+}
+
+wchar_t* CCtrlCombo::GetItemText(int index, wchar_t *buf, int size) const
+{
+ wchar_t *result = (wchar_t *)_alloca(sizeof(wchar_t) * (SendMessage(m_hwnd, CB_GETLBTEXTLEN, index, 0) + 1));
+ SendMessage(m_hwnd, CB_GETLBTEXT, index, (LPARAM)result);
+ mir_wstrncpy(buf, result, size);
+ return buf;
+}
+
+int CCtrlCombo::InsertString(const wchar_t *text, int pos, LPARAM data)
+{
+ int iItem = SendMessage(m_hwnd, CB_INSERTSTRING, pos, (LPARAM)text);
+ SendMessage(m_hwnd, CB_SETITEMDATA, iItem, data);
+ return iItem;
+}
+
+void CCtrlCombo::ResetContent()
+{ SendMessage(m_hwnd, CB_RESETCONTENT, 0, 0);
+}
+
+int CCtrlCombo::SelectString(const wchar_t *str)
+{ return SendMessage(m_hwnd, CB_SELECTSTRING, 0, (LPARAM)str);
+}
+
+int CCtrlCombo::SetCurSel(int index)
+{ return SendMessage(m_hwnd, CB_SETCURSEL, index, 0);
+}
+
+void CCtrlCombo::SetItemData(int index, LPARAM data)
+{ SendMessage(m_hwnd, CB_SETITEMDATA, index, data);
+}
+
+void CCtrlCombo::ShowDropdown(bool show)
+{ SendMessage(m_hwnd, CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0);
+}
diff --git a/src/mir_core/src/Windows/CCtrlData.cpp b/src/mir_core/src/Windows/CCtrlData.cpp
index fab5ca0409..2a60d9d31a 100644
--- a/src/mir_core/src/Windows/CCtrlData.cpp
+++ b/src/mir_core/src/Windows/CCtrlData.cpp
@@ -1,52 +1,52 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlData class
-
-CCtrlData::CCtrlData(CDlgBase *wnd, int idCtrl)
- : CCtrlBase(wnd, idCtrl),
- m_dbLink(nullptr)
-{}
-
-CCtrlData::~CCtrlData()
-{
- delete m_dbLink;
-}
-
-void CCtrlData::OnInit()
-{
- CCtrlBase::OnInit();
- OnReset();
-}
-
-void CCtrlData::CreateDbLink(const char* szModuleName, const char* szSetting, uint8_t type, uint32_t iValue)
-{
- m_dbLink = new CDbLink(szModuleName, szSetting, type, iValue);
-}
-
-void CCtrlData::CreateDbLink(const char* szModuleName, const char* szSetting, wchar_t* szValue)
-{
- m_dbLink = new CDbLink(szModuleName, szSetting, DBVT_WCHAR, szValue);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlData class
+
+CCtrlData::CCtrlData(CDlgBase *wnd, int idCtrl)
+ : CCtrlBase(wnd, idCtrl),
+ m_dbLink(nullptr)
+{}
+
+CCtrlData::~CCtrlData()
+{
+ delete m_dbLink;
+}
+
+void CCtrlData::OnInit()
+{
+ CCtrlBase::OnInit();
+ OnReset();
+}
+
+void CCtrlData::CreateDbLink(const char* szModuleName, const char* szSetting, uint8_t type, uint32_t iValue)
+{
+ m_dbLink = new CDbLink(szModuleName, szSetting, type, iValue);
+}
+
+void CCtrlData::CreateDbLink(const char* szModuleName, const char* szSetting, wchar_t* szValue)
+{
+ m_dbLink = new CDbLink(szModuleName, szSetting, DBVT_WCHAR, szValue);
+}
diff --git a/src/mir_core/src/Windows/CCtrlDate.cpp b/src/mir_core/src/Windows/CCtrlDate.cpp
index 1967cb5678..253b549870 100644
--- a/src/mir_core/src/Windows/CCtrlDate.cpp
+++ b/src/mir_core/src/Windows/CCtrlDate.cpp
@@ -1,49 +1,49 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlDate class
-
-CCtrlDate::CCtrlDate(CDlgBase *dlg, int ctrlId) :
- CCtrlData(dlg, ctrlId)
-{}
-
-BOOL CCtrlDate::OnNotify(int, NMHDR *pnmh)
-{
- if (pnmh->code == DTN_DATETIMECHANGE) {
- NotifyChange();
- return TRUE;
- }
- return FALSE;
-}
-
-void CCtrlDate::GetTime(SYSTEMTIME *pDate)
-{
- ::SendMessage(m_hwnd, DTM_GETSYSTEMTIME, 0, (LPARAM)pDate);
-}
-
-void CCtrlDate::SetTime(SYSTEMTIME *pDate)
-{
- ::SendMessage(m_hwnd, DTM_SETSYSTEMTIME, 0, (LPARAM)pDate);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlDate class
+
+CCtrlDate::CCtrlDate(CDlgBase *dlg, int ctrlId) :
+ CCtrlData(dlg, ctrlId)
+{}
+
+BOOL CCtrlDate::OnNotify(int, NMHDR *pnmh)
+{
+ if (pnmh->code == DTN_DATETIMECHANGE) {
+ NotifyChange();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void CCtrlDate::GetTime(SYSTEMTIME *pDate)
+{
+ ::SendMessage(m_hwnd, DTM_GETSYSTEMTIME, 0, (LPARAM)pDate);
+}
+
+void CCtrlDate::SetTime(SYSTEMTIME *pDate)
+{
+ ::SendMessage(m_hwnd, DTM_SETSYSTEMTIME, 0, (LPARAM)pDate);
+}
diff --git a/src/mir_core/src/Windows/CCtrlEdit.cpp b/src/mir_core/src/Windows/CCtrlEdit.cpp
index f035b5b14a..dd5bd2927e 100644
--- a/src/mir_core/src/Windows/CCtrlEdit.cpp
+++ b/src/mir_core/src/Windows/CCtrlEdit.cpp
@@ -1,68 +1,68 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlEdit class
-
-CCtrlEdit::CCtrlEdit(CDlgBase *dlg, int ctrlId)
- : CCtrlData(dlg, ctrlId)
-{}
-
-BOOL CCtrlEdit::OnCommand(HWND, uint16_t, uint16_t idCode)
-{
- if (idCode == EN_CHANGE)
- NotifyChange();
- return TRUE;
-}
-
-bool CCtrlEdit::OnApply()
-{
- CSuper::OnApply();
-
- if (GetDataType() == DBVT_WCHAR) {
- int len = GetWindowTextLength(m_hwnd) + 1;
- wchar_t *buf = (wchar_t *)_alloca(sizeof(wchar_t) * len);
- GetWindowText(m_hwnd, buf, len);
- SaveText(buf);
- }
- else if (GetDataType() != DBVT_DELETED) {
- SaveInt(GetInt());
- }
- return true;
-}
-
-void CCtrlEdit::OnReset()
-{
- m_bSilent = (GetWindowLong(m_hwnd, GWL_STYLE) & ES_READONLY) != 0;
-
- if (GetDataType() == DBVT_WCHAR)
- SetText(LoadText());
- else if (GetDataType() != DBVT_DELETED)
- SetInt(LoadInt());
-}
-
-void CCtrlEdit::SetMaxLength(unsigned int len)
-{
- SendMsg(EM_SETLIMITTEXT, len, 0);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlEdit class
+
+CCtrlEdit::CCtrlEdit(CDlgBase *dlg, int ctrlId)
+ : CCtrlData(dlg, ctrlId)
+{}
+
+BOOL CCtrlEdit::OnCommand(HWND, uint16_t, uint16_t idCode)
+{
+ if (idCode == EN_CHANGE)
+ NotifyChange();
+ return TRUE;
+}
+
+bool CCtrlEdit::OnApply()
+{
+ CSuper::OnApply();
+
+ if (GetDataType() == DBVT_WCHAR) {
+ int len = GetWindowTextLength(m_hwnd) + 1;
+ wchar_t *buf = (wchar_t *)_alloca(sizeof(wchar_t) * len);
+ GetWindowText(m_hwnd, buf, len);
+ SaveText(buf);
+ }
+ else if (GetDataType() != DBVT_DELETED) {
+ SaveInt(GetInt());
+ }
+ return true;
+}
+
+void CCtrlEdit::OnReset()
+{
+ m_bSilent = (GetWindowLong(m_hwnd, GWL_STYLE) & ES_READONLY) != 0;
+
+ if (GetDataType() == DBVT_WCHAR)
+ SetText(LoadText());
+ else if (GetDataType() != DBVT_DELETED)
+ SetInt(LoadInt());
+}
+
+void CCtrlEdit::SetMaxLength(unsigned int len)
+{
+ SendMsg(EM_SETLIMITTEXT, len, 0);
+}
diff --git a/src/mir_core/src/Windows/CCtrlHyperlink.cpp b/src/mir_core/src/Windows/CCtrlHyperlink.cpp
index ca92d19dbc..0e0d93a689 100644
--- a/src/mir_core/src/Windows/CCtrlHyperlink.cpp
+++ b/src/mir_core/src/Windows/CCtrlHyperlink.cpp
@@ -1,54 +1,54 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlHyperlink
-
-CCtrlHyperlink::CCtrlHyperlink(CDlgBase* wnd, int idCtrl, const char* url)
- : CCtrlBase(wnd, idCtrl),
- m_url(url)
-{
- OnClick = Callback(this, &CCtrlHyperlink::Default_OnClick);
-}
-
-BOOL CCtrlHyperlink::OnCommand(HWND, uint16_t, uint16_t)
-{
- OnClick(this);
- return FALSE;
-}
-
-void CCtrlHyperlink::Default_OnClick(CCtrlHyperlink*)
-{
- ShellExecuteA(m_hwnd, "open", m_url, "", "", SW_SHOW);
-}
-
-void CCtrlHyperlink::SetUrl(const char *url)
-{
- m_url = url;
-}
-
-const char* CCtrlHyperlink::GetUrl()
-{
- return m_url;
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlHyperlink
+
+CCtrlHyperlink::CCtrlHyperlink(CDlgBase* wnd, int idCtrl, const char* url)
+ : CCtrlBase(wnd, idCtrl),
+ m_url(url)
+{
+ OnClick = Callback(this, &CCtrlHyperlink::Default_OnClick);
+}
+
+BOOL CCtrlHyperlink::OnCommand(HWND, uint16_t, uint16_t)
+{
+ OnClick(this);
+ return FALSE;
+}
+
+void CCtrlHyperlink::Default_OnClick(CCtrlHyperlink*)
+{
+ ShellExecuteA(m_hwnd, "open", m_url, "", "", SW_SHOW);
+}
+
+void CCtrlHyperlink::SetUrl(const char *url)
+{
+ m_url = url;
+}
+
+const char* CCtrlHyperlink::GetUrl()
+{
+ return m_url;
+}
diff --git a/src/mir_core/src/Windows/CCtrlLabel.cpp b/src/mir_core/src/Windows/CCtrlLabel.cpp
index fd460fdf8b..8e1de5e33f 100644
--- a/src/mir_core/src/Windows/CCtrlLabel.cpp
+++ b/src/mir_core/src/Windows/CCtrlLabel.cpp
@@ -1,31 +1,31 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlLabel
-
-CCtrlLabel::CCtrlLabel(CDlgBase* wnd, int idCtrl)
- : CCtrlBase(wnd, idCtrl)
-{}
-
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlLabel
+
+CCtrlLabel::CCtrlLabel(CDlgBase* wnd, int idCtrl)
+ : CCtrlBase(wnd, idCtrl)
+{}
+
diff --git a/src/mir_core/src/Windows/CCtrlListBox.cpp b/src/mir_core/src/Windows/CCtrlListBox.cpp
index abaa31a786..6d9f58fc23 100644
--- a/src/mir_core/src/Windows/CCtrlListBox.cpp
+++ b/src/mir_core/src/Windows/CCtrlListBox.cpp
@@ -1,160 +1,160 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlListBox class
-
-CCtrlListBox::CCtrlListBox(CDlgBase *dlg, int ctrlId)
- : CCtrlBase(dlg, ctrlId)
-{}
-
-BOOL CCtrlListBox::OnCommand(HWND, uint16_t, uint16_t idCode)
-{
- switch (idCode) {
- case LBN_DBLCLK: OnDblClick(this); break;
- case LBN_SELCANCEL: OnSelCancel(this); break;
- case LBN_SELCHANGE: OnSelChange(this); break;
- }
- return TRUE;
-}
-
-void CCtrlListBox::GetCaretPos(CContextMenuPos &pos) const
-{
- pos.pCtrl = this;
- if (pos.pt.x == 0 && pos.pt.y == 0) {
- pos.iCurr = GetCurSel();
- if (pos.iCurr != -1) {
- RECT rc;
- GetItemRect(pos.iCurr, &rc);
- pos.pt.x = rc.left + 8;
- pos.pt.y = rc.top + 8;
- ClientToScreen(m_hwnd, &pos.pt);
- return;
- }
- }
-
- CSuper::GetCaretPos(pos);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-int CCtrlListBox::AddString(const wchar_t *text, LPARAM data)
-{
- int iItem = ListBox_AddString(m_hwnd, text);
- ListBox_SetItemData(m_hwnd, iItem, data);
- return iItem;
-}
-
-void CCtrlListBox::DeleteString(int index)
-{ ListBox_DeleteString(m_hwnd, index);
-}
-
-int CCtrlListBox::FindString(const wchar_t *str, int index, bool exact)
-{ return SendMessage(m_hwnd, exact?LB_FINDSTRINGEXACT:LB_FINDSTRING, index, (LPARAM)str);
-}
-
-int CCtrlListBox::GetCount() const
-{ return ListBox_GetCount(m_hwnd);
-}
-
-int CCtrlListBox::GetCurSel() const
-{ return ListBox_GetCurSel(m_hwnd);
-}
-
-LPARAM CCtrlListBox::GetItemData(int index) const
-{ return ListBox_GetItemData(m_hwnd, index);
-}
-
-int CCtrlListBox::GetItemRect(int index, RECT *pResult) const
-{ return ListBox_GetItemRect(m_hwnd, index, pResult);
-}
-
-wchar_t* CCtrlListBox::GetItemText(int index) const
-{
- wchar_t *result = (wchar_t *)mir_alloc(sizeof(wchar_t) * (SendMessage(m_hwnd, LB_GETTEXTLEN, index, 0) + 1));
- SendMessage(m_hwnd, LB_GETTEXT, index, (LPARAM)result);
- return result;
-}
-
-wchar_t* CCtrlListBox::GetItemText(int index, wchar_t *buf, int size) const
-{
- wchar_t *result = (wchar_t *)_alloca(sizeof(wchar_t) * (SendMessage(m_hwnd, LB_GETTEXTLEN, index, 0) + 1));
- SendMessage(m_hwnd, LB_GETTEXT, index, (LPARAM)result);
- mir_wstrncpy(buf, result, size);
- return buf;
-}
-
-bool CCtrlListBox::GetSel(int index) const
-{ return ListBox_GetSel(m_hwnd, index) ? true : false;
-}
-
-int CCtrlListBox::GetSelCount() const
-{ return ListBox_GetSelCount(m_hwnd);
-}
-
-int* CCtrlListBox::GetSelItems(int *items, int count) const
-{
- ListBox_GetSelItems(m_hwnd, count, items);
- return items;
-}
-
-int* CCtrlListBox::GetSelItems() const
-{
- int count = GetSelCount() + 1;
- int *result = (int *)mir_alloc(sizeof(int) * count);
- ListBox_GetSelItems(m_hwnd, count, result);
- result[count-1] = -1;
- return result;
-}
-
-int CCtrlListBox::InsertString(const wchar_t *text, int pos, LPARAM data)
-{
- int iItem = ListBox_InsertString(m_hwnd, pos, text);
- ListBox_SetItemData(m_hwnd, iItem, data);
- return iItem;
-}
-
-void CCtrlListBox::ResetContent()
-{ ListBox_ResetContent(m_hwnd);
-}
-
-int CCtrlListBox::SelectString(const wchar_t *str)
-{ return ListBox_SelectString(m_hwnd, 0, str);
-}
-
-int CCtrlListBox::SetCurSel(int index)
-{ return ListBox_SetCurSel(m_hwnd, index);
-}
-
-void CCtrlListBox::SetItemData(int index, LPARAM data)
-{ ListBox_SetItemData(m_hwnd, index, data);
-}
-
-void CCtrlListBox::SetItemHeight(int index, int iHeight)
-{ ListBox_SetItemHeight(m_hwnd, index, iHeight);
-}
-
-void CCtrlListBox::SetSel(int index, bool sel)
-{ ListBox_SetSel(m_hwnd, sel ? TRUE : FALSE, index);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlListBox class
+
+CCtrlListBox::CCtrlListBox(CDlgBase *dlg, int ctrlId)
+ : CCtrlBase(dlg, ctrlId)
+{}
+
+BOOL CCtrlListBox::OnCommand(HWND, uint16_t, uint16_t idCode)
+{
+ switch (idCode) {
+ case LBN_DBLCLK: OnDblClick(this); break;
+ case LBN_SELCANCEL: OnSelCancel(this); break;
+ case LBN_SELCHANGE: OnSelChange(this); break;
+ }
+ return TRUE;
+}
+
+void CCtrlListBox::GetCaretPos(CContextMenuPos &pos) const
+{
+ pos.pCtrl = this;
+ if (pos.pt.x == 0 && pos.pt.y == 0) {
+ pos.iCurr = GetCurSel();
+ if (pos.iCurr != -1) {
+ RECT rc;
+ GetItemRect(pos.iCurr, &rc);
+ pos.pt.x = rc.left + 8;
+ pos.pt.y = rc.top + 8;
+ ClientToScreen(m_hwnd, &pos.pt);
+ return;
+ }
+ }
+
+ CSuper::GetCaretPos(pos);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+int CCtrlListBox::AddString(const wchar_t *text, LPARAM data)
+{
+ int iItem = ListBox_AddString(m_hwnd, text);
+ ListBox_SetItemData(m_hwnd, iItem, data);
+ return iItem;
+}
+
+void CCtrlListBox::DeleteString(int index)
+{ ListBox_DeleteString(m_hwnd, index);
+}
+
+int CCtrlListBox::FindString(const wchar_t *str, int index, bool exact)
+{ return SendMessage(m_hwnd, exact?LB_FINDSTRINGEXACT:LB_FINDSTRING, index, (LPARAM)str);
+}
+
+int CCtrlListBox::GetCount() const
+{ return ListBox_GetCount(m_hwnd);
+}
+
+int CCtrlListBox::GetCurSel() const
+{ return ListBox_GetCurSel(m_hwnd);
+}
+
+LPARAM CCtrlListBox::GetItemData(int index) const
+{ return ListBox_GetItemData(m_hwnd, index);
+}
+
+int CCtrlListBox::GetItemRect(int index, RECT *pResult) const
+{ return ListBox_GetItemRect(m_hwnd, index, pResult);
+}
+
+wchar_t* CCtrlListBox::GetItemText(int index) const
+{
+ wchar_t *result = (wchar_t *)mir_alloc(sizeof(wchar_t) * (SendMessage(m_hwnd, LB_GETTEXTLEN, index, 0) + 1));
+ SendMessage(m_hwnd, LB_GETTEXT, index, (LPARAM)result);
+ return result;
+}
+
+wchar_t* CCtrlListBox::GetItemText(int index, wchar_t *buf, int size) const
+{
+ wchar_t *result = (wchar_t *)_alloca(sizeof(wchar_t) * (SendMessage(m_hwnd, LB_GETTEXTLEN, index, 0) + 1));
+ SendMessage(m_hwnd, LB_GETTEXT, index, (LPARAM)result);
+ mir_wstrncpy(buf, result, size);
+ return buf;
+}
+
+bool CCtrlListBox::GetSel(int index) const
+{ return ListBox_GetSel(m_hwnd, index) ? true : false;
+}
+
+int CCtrlListBox::GetSelCount() const
+{ return ListBox_GetSelCount(m_hwnd);
+}
+
+int* CCtrlListBox::GetSelItems(int *items, int count) const
+{
+ ListBox_GetSelItems(m_hwnd, count, items);
+ return items;
+}
+
+int* CCtrlListBox::GetSelItems() const
+{
+ int count = GetSelCount() + 1;
+ int *result = (int *)mir_alloc(sizeof(int) * count);
+ ListBox_GetSelItems(m_hwnd, count, result);
+ result[count-1] = -1;
+ return result;
+}
+
+int CCtrlListBox::InsertString(const wchar_t *text, int pos, LPARAM data)
+{
+ int iItem = ListBox_InsertString(m_hwnd, pos, text);
+ ListBox_SetItemData(m_hwnd, iItem, data);
+ return iItem;
+}
+
+void CCtrlListBox::ResetContent()
+{ ListBox_ResetContent(m_hwnd);
+}
+
+int CCtrlListBox::SelectString(const wchar_t *str)
+{ return ListBox_SelectString(m_hwnd, 0, str);
+}
+
+int CCtrlListBox::SetCurSel(int index)
+{ return ListBox_SetCurSel(m_hwnd, index);
+}
+
+void CCtrlListBox::SetItemData(int index, LPARAM data)
+{ ListBox_SetItemData(m_hwnd, index, data);
+}
+
+void CCtrlListBox::SetItemHeight(int index, int iHeight)
+{ ListBox_SetItemHeight(m_hwnd, index, iHeight);
+}
+
+void CCtrlListBox::SetSel(int index, bool sel)
+{ ListBox_SetSel(m_hwnd, sel ? TRUE : FALSE, index);
+}
diff --git a/src/mir_core/src/Windows/CCtrlListView.cpp b/src/mir_core/src/Windows/CCtrlListView.cpp
index eb57951a3c..40bb1f481e 100644
--- a/src/mir_core/src/Windows/CCtrlListView.cpp
+++ b/src/mir_core/src/Windows/CCtrlListView.cpp
@@ -1,551 +1,551 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlListView
-
-CCtrlListView::CCtrlListView(CDlgBase *dlg, int ctrlId)
- : CCtrlBase(dlg, ctrlId)
-{}
-
-BOOL CCtrlListView::OnNotify(int, NMHDR *pnmh)
-{
- TEventInfo evt = { this, pnmh };
-
- switch (pnmh->code) {
- case NM_CLICK: OnClick(&evt); return TRUE;
- case NM_DBLCLK: OnDoubleClick(&evt); return TRUE;
- case NM_CUSTOMDRAW: OnCustomDraw(&evt); return TRUE;
- case LVN_BEGINDRAG: OnBeginDrag(&evt); return TRUE;
- case LVN_BEGINLABELEDIT: OnBeginLabelEdit(&evt); return TRUE;
- case LVN_BEGINRDRAG: OnBeginRDrag(&evt); return TRUE;
- case LVN_BEGINSCROLL: OnBeginScroll(&evt); return TRUE;
- case LVN_COLUMNCLICK: OnColumnClick(&evt); return TRUE;
- case LVN_DELETEALLITEMS: OnDeleteAllItems(&evt); return TRUE;
- case LVN_DELETEITEM: OnDeleteItem(&evt); return TRUE;
- case LVN_ENDLABELEDIT: OnEndLabelEdit(&evt); return TRUE;
- case LVN_ENDSCROLL: OnEndScroll(&evt); return TRUE;
- case LVN_GETDISPINFO: OnGetDispInfo(&evt); return TRUE;
- case LVN_GETINFOTIP: OnGetInfoTip(&evt); return TRUE;
- case LVN_HOTTRACK: OnHotTrack(&evt); return TRUE;
- case LVN_INSERTITEM: OnInsertItem(&evt); return TRUE;
- case LVN_ITEMACTIVATE: OnItemActivate(&evt); return TRUE;
- case LVN_ITEMCHANGING: OnItemChanging(&evt); return TRUE;
- case LVN_KEYDOWN: OnKeyDown(&evt); return TRUE;
- case LVN_MARQUEEBEGIN: OnMarqueeBegin(&evt); return TRUE;
- case LVN_SETDISPINFO: OnSetDispInfo(&evt); return TRUE;
-
- case LVN_ITEMCHANGED:
- if (!m_parentWnd || !m_parentWnd->IsInitialized())
- return FALSE;
-
- OnItemChanged(&evt);
-
- // item's state is calculated as 1/2 << 12, so we check it to filter out all non-state changes
- if (evt.nmlv->uChanged & LVIF_STATE)
- if ((evt.nmlv->uOldState >> 12) != 0 && (evt.nmlv->uNewState >> 12) != 0)
- NotifyChange();
- return TRUE;
-
- case LVN_ODSTATECHANGED:
- NotifyChange();
- return TRUE;
- }
-
- return FALSE;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static int CALLBACK LVMoveSortProc(LPARAM l1, LPARAM l2, LPARAM param)
-{
- int result = l1 - l2;
- int newItem = HIWORD(param);
- int oldItem = LOWORD(param);
- if (newItem > oldItem)
- return (l1 == oldItem && l2 <= newItem) ? 1 : result;
-
- return (l2 == oldItem && l1 >= newItem) ? 1 : result;
-}
-
-int CCtrlListView::MoveItem(int idx, int direction)
-{
- if ((direction > 0 && idx >= GetItemCount() - 1) || (direction < 0 && idx <= 0))
- return idx;
-
- if (idx < 0)
- idx = GetNextItem(-1, LVNI_FOCUSED);
- SortItemsEx(&LVMoveSortProc, MAKELONG(idx, idx + direction));
- return idx + direction;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CCtrlListView::SetCurSel(int idx)
-{
- SetItemState(idx, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
-}
-
-// additional api
-HIMAGELIST CCtrlListView::CreateImageList(int iImageList)
-{
- HIMAGELIST hIml = GetImageList(iImageList);
- if (hIml)
- return hIml;
-
- hIml = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1);
- SetImageList(hIml, iImageList);
- return hIml;
-}
-
-void CCtrlListView::AddColumn(int iSubItem, const wchar_t *name, int cx)
-{
- LVCOLUMN lvc;
- lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
- lvc.iImage = 0;
- lvc.pszText = (LPWSTR)name;
- lvc.cx = cx;
- lvc.iSubItem = iSubItem;
- InsertColumn(iSubItem, &lvc);
-}
-
-void CCtrlListView::AddGroup(int iGroupId, const wchar_t *name)
-{
- LVGROUP lvg = { 0 };
- lvg.cbSize = sizeof(lvg);
- lvg.mask = LVGF_HEADER | LVGF_GROUPID;
- lvg.pszHeader = (LPWSTR)name;
- lvg.cchHeader = (int)mir_wstrlen(lvg.pszHeader);
- lvg.iGroupId = iGroupId;
- InsertGroup(-1, &lvg);
-}
-
-int CCtrlListView::AddItem(const wchar_t *text, int iIcon, LPARAM lParam, int iGroupId)
-{
- LVITEM lvi = { 0 };
- lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE;
- lvi.iSubItem = 0;
- lvi.pszText = (LPWSTR)text;
- lvi.iImage = iIcon;
- lvi.lParam = lParam;
- if (iGroupId >= 0) {
- lvi.mask |= LVIF_GROUPID;
- lvi.iGroupId = iGroupId;
- }
-
- return InsertItem(&lvi);
-}
-
-void CCtrlListView::SetItem(int iItem, int iSubItem, const wchar_t *text, int iIcon)
-{
- LVITEM lvi = { 0 };
- lvi.mask = LVIF_TEXT;
- lvi.iItem = iItem;
- lvi.iSubItem = iSubItem;
- lvi.pszText = (LPWSTR)text;
- if (iIcon >= 0) {
- lvi.mask |= LVIF_IMAGE;
- lvi.iImage = iIcon;
- }
-
- SetItem(&lvi);
-}
-
-LPARAM CCtrlListView::GetItemData(int iItem) const
-{
- LVITEM lvi = { 0 };
- lvi.mask = LVIF_PARAM;
- lvi.iItem = iItem;
- return GetItem(&lvi) ? lvi.lParam : -1;
-}
-
-void CCtrlListView::GetCaretPos(CContextMenuPos &pos) const
-{
- pos.pCtrl = this;
-
- // position is empty, let's fill it using selection
- if (pos.pt.x == 0 && pos.pt.y == 0) {
- pos.iCurr = GetSelectionMark();
- if (pos.iCurr != -1) {
- RECT rc;
- GetItemRect(pos.iCurr, &rc, TRUE);
- pos.pt.x = rc.left + 8;
- pos.pt.y = rc.top + 8;
- ClientToScreen(m_hwnd, &pos.pt);
- return;
- }
- }
- // position is present, let's calculate current item
- else {
- LVHITTESTINFO hti;
- hti.pt = pos.pt;
- ScreenToClient(m_hwnd, &hti.pt);
- if (SubItemHitTest(&hti) != -1) {
- pos.iCurr = hti.iItem;
- return;
- }
- }
- CSuper::GetCaretPos(pos);
-}
-
-// classic api
-uint32_t CCtrlListView::ApproximateViewRect(int cx, int cy, int iCount)
-{ return ListView_ApproximateViewRect(m_hwnd, cx, cy, iCount);
-}
-void CCtrlListView::Arrange(UINT code)
-{ ListView_Arrange(m_hwnd, code);
-}
-void CCtrlListView::CancelEditLabel()
-{ ListView_CancelEditLabel(m_hwnd);
-}
-HIMAGELIST CCtrlListView::CreateDragImage(int iItem, LPPOINT lpptUpLeft)
-{ return ListView_CreateDragImage(m_hwnd, iItem, lpptUpLeft);
-}
-void CCtrlListView::DeleteAllItems()
-{ ListView_DeleteAllItems(m_hwnd);
-}
-void CCtrlListView::DeleteColumn(int iCol)
-{ ListView_DeleteColumn(m_hwnd, iCol);
-}
-void CCtrlListView::DeleteItem(int iItem)
-{ ListView_DeleteItem(m_hwnd, iItem);
-}
-HWND CCtrlListView::EditLabel(int iItem)
-{ return ListView_EditLabel(m_hwnd, iItem);
-}
-int CCtrlListView::EnableGroupView(BOOL fEnable)
-{ return ListView_EnableGroupView(m_hwnd, fEnable);
-}
-BOOL CCtrlListView::EnsureVisible(int i, BOOL fPartialOK)
-{ return ListView_EnsureVisible(m_hwnd, i, fPartialOK);
-}
-int CCtrlListView::FindItem(int iStart, const LVFINDINFO *plvfi)
-{ return ListView_FindItem(m_hwnd, iStart, plvfi);
-}
-COLORREF CCtrlListView::GetBkColor() const
-{ return ListView_GetBkColor(m_hwnd);
-}
-void CCtrlListView::GetBkImage(LPLVBKIMAGE plvbki) const
-{ ListView_GetBkImage(m_hwnd, plvbki);
-}
-UINT CCtrlListView::GetCallbackMask() const
-{ return ListView_GetCallbackMask(m_hwnd);
-}
-BOOL CCtrlListView::GetCheckState(UINT iIndex) const
-{ return ListView_GetCheckState(m_hwnd, iIndex);
-}
-void CCtrlListView::GetColumn(int iCol, LPLVCOLUMN pcol) const
-{ ListView_GetColumn(m_hwnd, iCol, pcol);
-}
-void CCtrlListView::GetColumnOrderArray(int iCount, int *lpiArray) const
-{ ListView_GetColumnOrderArray(m_hwnd, iCount, lpiArray);
-}
-int CCtrlListView::GetColumnWidth(int iCol) const
-{ return ListView_GetColumnWidth(m_hwnd, iCol);
-}
-int CCtrlListView::GetCountPerPage() const
-{ return ListView_GetCountPerPage(m_hwnd);
-}
-HWND CCtrlListView::GetEditControl() const
-{ return ListView_GetEditControl(m_hwnd);
-}
-uint32_t CCtrlListView::GetExtendedListViewStyle() const
-{ return ListView_GetExtendedListViewStyle(m_hwnd);
-}
-void CCtrlListView::GetGroupMetrics(LVGROUPMETRICS *pGroupMetrics) const
-{ ListView_GetGroupMetrics(m_hwnd, pGroupMetrics);
-}
-HWND CCtrlListView::GetHeader() const
-{ return ListView_GetHeader(m_hwnd);
-}
-HCURSOR CCtrlListView::GetHotCursor() const
-{ return ListView_GetHotCursor(m_hwnd);
-}
-INT CCtrlListView::GetHotItem() const
-{ return ListView_GetHotItem(m_hwnd);
-}
-uint32_t CCtrlListView::GetHoverTime() const
-{ return ListView_GetHoverTime(m_hwnd);
-}
-HIMAGELIST CCtrlListView::GetImageList(int iImageList) const
-{ return ListView_GetImageList(m_hwnd, iImageList);
-}
-BOOL CCtrlListView::GetInsertMark(LVINSERTMARK *plvim) const
-{ return ListView_GetInsertMark(m_hwnd, plvim);
-}
-COLORREF CCtrlListView::GetInsertMarkColor() const
-{ return ListView_GetInsertMarkColor(m_hwnd);
-}
-int CCtrlListView::GetInsertMarkRect(LPRECT prc) const
-{ return ListView_GetInsertMarkRect(m_hwnd, prc);
-}
-BOOL CCtrlListView::GetISearchString(LPSTR lpsz) const
-{ return ListView_GetISearchString(m_hwnd, lpsz);
-}
-bool CCtrlListView::GetItem(LPLVITEM pitem) const
-{ return ListView_GetItem(m_hwnd, pitem) == TRUE;
-}
-int CCtrlListView::GetItemCount() const
-{ return ListView_GetItemCount(m_hwnd);
-}
-void CCtrlListView::GetItemPosition(int i, POINT *ppt) const
-{ ListView_GetItemPosition(m_hwnd, i, ppt);
-}
-void CCtrlListView::GetItemRect(int i, RECT *prc, int code) const
-{ ListView_GetItemRect(m_hwnd, i, prc, code);
-}
-uint32_t CCtrlListView::GetItemSpacing(BOOL fSmall) const
-{ return ListView_GetItemSpacing(m_hwnd, fSmall);
-}
-UINT CCtrlListView::GetItemState(int i, UINT mask) const
-{ return ListView_GetItemState(m_hwnd, i, mask);
-}
-void CCtrlListView::GetItemText(int iItem, int iSubItem, LPTSTR pszText, int cchTextMax) const
-{ ListView_GetItemText(m_hwnd, iItem, iSubItem, pszText, cchTextMax);
-}
-int CCtrlListView::GetNextItem(int iStart, UINT flags) const
-{ return ListView_GetNextItem(m_hwnd, iStart, flags);
-}
-BOOL CCtrlListView::GetNumberOfWorkAreas(LPUINT lpuWorkAreas) const
-{ return ListView_GetNumberOfWorkAreas(m_hwnd, lpuWorkAreas);
-}
-BOOL CCtrlListView::GetOrigin(LPPOINT lpptOrg) const
-{ return ListView_GetOrigin(m_hwnd, lpptOrg);
-}
-COLORREF CCtrlListView::GetOutlineColor() const
-{ return ListView_GetOutlineColor(m_hwnd);
-}
-UINT CCtrlListView::GetSelectedColumn() const
-{ return ListView_GetSelectedColumn(m_hwnd);
-}
-UINT CCtrlListView::GetSelectedCount() const
-{ return ListView_GetSelectedCount(m_hwnd);
-}
-INT CCtrlListView::GetSelectionMark() const
-{ return ListView_GetSelectionMark(m_hwnd);
-}
-int CCtrlListView::GetStringWidth(LPCSTR psz) const
-{ return ListView_GetStringWidth(m_hwnd, psz);
-}
-BOOL CCtrlListView::GetSubItemRect(int iItem, int iSubItem, int code, LPRECT lpRect) const
-{ return ListView_GetSubItemRect(m_hwnd, iItem, iSubItem, code, lpRect);
-}
-COLORREF CCtrlListView::GetTextBkColor() const
-{ return ListView_GetTextBkColor(m_hwnd);
-}
-COLORREF CCtrlListView::GetTextColor() const
-{ return ListView_GetTextColor(m_hwnd);
-}
-void CCtrlListView::GetTileInfo(PLVTILEINFO plvtinfo) const
-{ ListView_GetTileInfo(m_hwnd, plvtinfo);
-}
-void CCtrlListView::GetTileViewInfo(PLVTILEVIEWINFO plvtvinfo) const
-{ ListView_GetTileViewInfo(m_hwnd, plvtvinfo);
-}
-HWND CCtrlListView::GetToolTips() const
-{ return ListView_GetToolTips(m_hwnd);
-}
-int CCtrlListView::GetTopIndex() const
-{ return ListView_GetTopIndex(m_hwnd);
-}
-BOOL CCtrlListView::GetUnicodeFormat() const
-{ return ListView_GetUnicodeFormat(m_hwnd);
-}
-uint32_t CCtrlListView::GetView() const
-{ return ListView_GetView(m_hwnd);
-}
-BOOL CCtrlListView::GetViewRect(RECT *prc) const
-{ return ListView_GetViewRect(m_hwnd, prc);
-}
-void CCtrlListView::GetWorkAreas(INT nWorkAreas, LPRECT lprc) const
-{ ListView_GetWorkAreas(m_hwnd, nWorkAreas, lprc);
-}
-BOOL CCtrlListView::HasGroup(int dwGroupId)
-{ return ListView_HasGroup(m_hwnd, dwGroupId);
-}
-int CCtrlListView::HitTest(LPLVHITTESTINFO pinfo) const
-{ return ListView_HitTest(m_hwnd, pinfo);
-}
-int CCtrlListView::InsertColumn(int iCol, const LVCOLUMN *pcol)
-{ return ListView_InsertColumn(m_hwnd, iCol, pcol);
-}
-int CCtrlListView::InsertGroup(int index, PLVGROUP pgrp)
-{ return ListView_InsertGroup(m_hwnd, index, pgrp);
-}
-void CCtrlListView::InsertGroupSorted(PLVINSERTGROUPSORTED structInsert)
-{ ListView_InsertGroupSorted(m_hwnd, structInsert);
-}
-int CCtrlListView::InsertItem(const LVITEM *pitem)
-{ return ListView_InsertItem(m_hwnd, pitem);
-}
-BOOL CCtrlListView::InsertMarkHitTest(LPPOINT point, LVINSERTMARK *plvim)
-{ return ListView_InsertMarkHitTest(m_hwnd, point, plvim);
-}
-BOOL CCtrlListView::IsGroupViewEnabled()
-{ return ListView_IsGroupViewEnabled(m_hwnd);
-}
-UINT CCtrlListView::MapIDToIndex(UINT id)
-{ return ListView_MapIDToIndex(m_hwnd, id);
-}
-UINT CCtrlListView::MapIndexToID(UINT index)
-{ return ListView_MapIndexToID(m_hwnd, index);
-}
-BOOL CCtrlListView::RedrawItems(int iFirst, int iLast)
-{ return ListView_RedrawItems(m_hwnd, iFirst, iLast);
-}
-void CCtrlListView::RemoveAllGroups()
-{ ListView_RemoveAllGroups(m_hwnd);
-}
-int CCtrlListView::RemoveGroup(int iGroupId)
-{ return ListView_RemoveGroup(m_hwnd, iGroupId);
-}
-BOOL CCtrlListView::Scroll(int dx, int dy)
-{ return ListView_Scroll(m_hwnd, dx, dy);
-}
-BOOL CCtrlListView::SetBkColor(COLORREF clrBk)
-{ return ListView_SetBkColor(m_hwnd, clrBk);
-}
-BOOL CCtrlListView::SetBkImage(LPLVBKIMAGE plvbki)
-{ return ListView_SetBkImage(m_hwnd, plvbki);
-}
-BOOL CCtrlListView::SetCallbackMask(UINT mask)
-{ return ListView_SetCallbackMask(m_hwnd, mask);
-}
-void CCtrlListView::SetCheckState(UINT iIndex, BOOL fCheck)
-{ ListView_SetCheckState(m_hwnd, iIndex, fCheck);
-}
-BOOL CCtrlListView::SetColumn(int iCol, LPLVCOLUMN pcol)
-{ return ListView_SetColumn(m_hwnd, iCol, pcol);
-}
-BOOL CCtrlListView::SetColumnOrderArray(int iCount, int *lpiArray)
-{ return ListView_SetColumnOrderArray(m_hwnd, iCount, lpiArray);
-}
-BOOL CCtrlListView::SetColumnWidth(int iCol, int cx)
-{ return ListView_SetColumnWidth(m_hwnd, iCol, cx);
-}
-void CCtrlListView::SetExtendedListViewStyle(uint32_t dwExStyle)
-{ ListView_SetExtendedListViewStyle(m_hwnd, dwExStyle);
-}
-void CCtrlListView::SetExtendedListViewStyleEx(uint32_t dwExMask, uint32_t dwExStyle)
-{ ListView_SetExtendedListViewStyleEx(m_hwnd, dwExMask, dwExStyle);
-}
-int CCtrlListView::SetGroupInfo(int iGroupId, PLVGROUP pgrp)
-{ return ListView_SetGroupInfo(m_hwnd, iGroupId, pgrp);
-}
-void CCtrlListView::SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics)
-{ ListView_SetGroupMetrics(m_hwnd, pGroupMetrics);
-}
-HCURSOR CCtrlListView::SetHotCursor(HCURSOR hCursor)
-{ return ListView_SetHotCursor(m_hwnd, hCursor);
-}
-INT CCtrlListView::SetHotItem(INT iIndex)
-{ return ListView_SetHotItem(m_hwnd, iIndex);
-}
-void CCtrlListView::SetHoverTime(uint32_t dwHoverTime)
-{ ListView_SetHoverTime(m_hwnd, dwHoverTime);
-}
-uint32_t CCtrlListView::SetIconSpacing(int cx, int cy)
-{ return ListView_SetIconSpacing(m_hwnd, cx, cy);
-}
-HIMAGELIST CCtrlListView::SetImageList(HIMAGELIST himl, int iImageList)
-{ return ListView_SetImageList(m_hwnd, himl, iImageList);
-}
-BOOL CCtrlListView::SetInfoTip(PLVSETINFOTIP plvSetInfoTip)
-{ return ListView_SetInfoTip(m_hwnd, plvSetInfoTip);
-}
-BOOL CCtrlListView::SetInsertMark(LVINSERTMARK *plvim)
-{ return ListView_SetInsertMark(m_hwnd, plvim);
-}
-COLORREF CCtrlListView::SetInsertMarkColor(COLORREF color)
-{ return ListView_SetInsertMarkColor(m_hwnd, color);
-}
-BOOL CCtrlListView::SetItem(const LVITEM *pitem)
-{ return ListView_SetItem(m_hwnd, pitem);
-}
-void CCtrlListView::SetItemCount(int cItems)
-{ ListView_SetItemCount(m_hwnd, cItems);
-}
-void CCtrlListView::SetItemCountEx(int cItems, uint32_t dwFlags)
-{ ListView_SetItemCountEx(m_hwnd, cItems, dwFlags);
-}
-BOOL CCtrlListView::SetItemPosition(int i, int x, int y)
-{ return ListView_SetItemPosition(m_hwnd, i, x, y);
-}
-void CCtrlListView::SetItemPosition32(int iItem, int x, int y)
-{ ListView_SetItemPosition32(m_hwnd, iItem, x, y);
-}
-void CCtrlListView::SetItemState(int i, UINT state, UINT mask)
-{ ListView_SetItemState(m_hwnd, i, state, mask);
-}
-void CCtrlListView::SetItemText(int i, int iSubItem, const wchar_t *pszText)
-{ ListView_SetItemText(m_hwnd, i, iSubItem, (LPWSTR)pszText);
-}
-COLORREF CCtrlListView::SetOutlineColor(COLORREF color)
-{ return ListView_SetOutlineColor(m_hwnd, color);
-}
-void CCtrlListView::SetSelectedColumn(int iCol)
-{ ListView_SetSelectedColumn(m_hwnd, iCol);
-}
-INT CCtrlListView::SetSelectionMark(INT iIndex)
-{ return ListView_SetSelectionMark(m_hwnd, iIndex);
-}
-BOOL CCtrlListView::SetTextBkColor(COLORREF clrText)
-{ return ListView_SetTextBkColor(m_hwnd, clrText);
-}
-BOOL CCtrlListView::SetTextColor(COLORREF clrText)
-{ return ListView_SetTextColor(m_hwnd, clrText);
-}
-BOOL CCtrlListView::SetTileInfo(PLVTILEINFO plvtinfo)
-{ return ListView_SetTileInfo(m_hwnd, plvtinfo);
-}
-BOOL CCtrlListView::SetTileViewInfo(PLVTILEVIEWINFO plvtvinfo)
-{ return ListView_SetTileViewInfo(m_hwnd, plvtvinfo);
-}
-HWND CCtrlListView::SetToolTips(HWND ToolTip)
-{ return ListView_SetToolTips(m_hwnd, ToolTip);
-}
-BOOL CCtrlListView::SetUnicodeFormat(BOOL fUnicode)
-{ return ListView_SetUnicodeFormat(m_hwnd, fUnicode);
-}
-int CCtrlListView::SetView(uint32_t iView)
-{ return ListView_SetView(m_hwnd, iView);
-}
-void CCtrlListView::SetWorkAreas(INT nWorkAreas, LPRECT lprc)
-{ ListView_SetWorkAreas(m_hwnd, nWorkAreas, lprc);
-}
-int CCtrlListView::SortGroups(PFNLVGROUPCOMPARE pfnGroupCompare, LPVOID plv)
-{ return ListView_SortGroups(m_hwnd, pfnGroupCompare, plv);
-}
-BOOL CCtrlListView::SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
-{ return ListView_SortItems(m_hwnd, pfnCompare, lParamSort);
-}
-BOOL CCtrlListView::SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
-{ return ListView_SortItemsEx(m_hwnd, pfnCompare, lParamSort);
-}
-INT CCtrlListView::SubItemHitTest(LPLVHITTESTINFO pInfo) const
-{ return ListView_SubItemHitTest(m_hwnd, pInfo);
-}
-BOOL CCtrlListView::Update(int iItem)
-{ return ListView_Update(m_hwnd, iItem);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlListView
+
+CCtrlListView::CCtrlListView(CDlgBase *dlg, int ctrlId)
+ : CCtrlBase(dlg, ctrlId)
+{}
+
+BOOL CCtrlListView::OnNotify(int, NMHDR *pnmh)
+{
+ TEventInfo evt = { this, pnmh };
+
+ switch (pnmh->code) {
+ case NM_CLICK: OnClick(&evt); return TRUE;
+ case NM_DBLCLK: OnDoubleClick(&evt); return TRUE;
+ case NM_CUSTOMDRAW: OnCustomDraw(&evt); return TRUE;
+ case LVN_BEGINDRAG: OnBeginDrag(&evt); return TRUE;
+ case LVN_BEGINLABELEDIT: OnBeginLabelEdit(&evt); return TRUE;
+ case LVN_BEGINRDRAG: OnBeginRDrag(&evt); return TRUE;
+ case LVN_BEGINSCROLL: OnBeginScroll(&evt); return TRUE;
+ case LVN_COLUMNCLICK: OnColumnClick(&evt); return TRUE;
+ case LVN_DELETEALLITEMS: OnDeleteAllItems(&evt); return TRUE;
+ case LVN_DELETEITEM: OnDeleteItem(&evt); return TRUE;
+ case LVN_ENDLABELEDIT: OnEndLabelEdit(&evt); return TRUE;
+ case LVN_ENDSCROLL: OnEndScroll(&evt); return TRUE;
+ case LVN_GETDISPINFO: OnGetDispInfo(&evt); return TRUE;
+ case LVN_GETINFOTIP: OnGetInfoTip(&evt); return TRUE;
+ case LVN_HOTTRACK: OnHotTrack(&evt); return TRUE;
+ case LVN_INSERTITEM: OnInsertItem(&evt); return TRUE;
+ case LVN_ITEMACTIVATE: OnItemActivate(&evt); return TRUE;
+ case LVN_ITEMCHANGING: OnItemChanging(&evt); return TRUE;
+ case LVN_KEYDOWN: OnKeyDown(&evt); return TRUE;
+ case LVN_MARQUEEBEGIN: OnMarqueeBegin(&evt); return TRUE;
+ case LVN_SETDISPINFO: OnSetDispInfo(&evt); return TRUE;
+
+ case LVN_ITEMCHANGED:
+ if (!m_parentWnd || !m_parentWnd->IsInitialized())
+ return FALSE;
+
+ OnItemChanged(&evt);
+
+ // item's state is calculated as 1/2 << 12, so we check it to filter out all non-state changes
+ if (evt.nmlv->uChanged & LVIF_STATE)
+ if ((evt.nmlv->uOldState >> 12) != 0 && (evt.nmlv->uNewState >> 12) != 0)
+ NotifyChange();
+ return TRUE;
+
+ case LVN_ODSTATECHANGED:
+ NotifyChange();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int CALLBACK LVMoveSortProc(LPARAM l1, LPARAM l2, LPARAM param)
+{
+ int result = l1 - l2;
+ int newItem = HIWORD(param);
+ int oldItem = LOWORD(param);
+ if (newItem > oldItem)
+ return (l1 == oldItem && l2 <= newItem) ? 1 : result;
+
+ return (l2 == oldItem && l1 >= newItem) ? 1 : result;
+}
+
+int CCtrlListView::MoveItem(int idx, int direction)
+{
+ if ((direction > 0 && idx >= GetItemCount() - 1) || (direction < 0 && idx <= 0))
+ return idx;
+
+ if (idx < 0)
+ idx = GetNextItem(-1, LVNI_FOCUSED);
+ SortItemsEx(&LVMoveSortProc, MAKELONG(idx, idx + direction));
+ return idx + direction;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CCtrlListView::SetCurSel(int idx)
+{
+ SetItemState(idx, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
+}
+
+// additional api
+HIMAGELIST CCtrlListView::CreateImageList(int iImageList)
+{
+ HIMAGELIST hIml = GetImageList(iImageList);
+ if (hIml)
+ return hIml;
+
+ hIml = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1);
+ SetImageList(hIml, iImageList);
+ return hIml;
+}
+
+void CCtrlListView::AddColumn(int iSubItem, const wchar_t *name, int cx)
+{
+ LVCOLUMN lvc;
+ lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
+ lvc.iImage = 0;
+ lvc.pszText = (LPWSTR)name;
+ lvc.cx = cx;
+ lvc.iSubItem = iSubItem;
+ InsertColumn(iSubItem, &lvc);
+}
+
+void CCtrlListView::AddGroup(int iGroupId, const wchar_t *name)
+{
+ LVGROUP lvg = { 0 };
+ lvg.cbSize = sizeof(lvg);
+ lvg.mask = LVGF_HEADER | LVGF_GROUPID;
+ lvg.pszHeader = (LPWSTR)name;
+ lvg.cchHeader = (int)mir_wstrlen(lvg.pszHeader);
+ lvg.iGroupId = iGroupId;
+ InsertGroup(-1, &lvg);
+}
+
+int CCtrlListView::AddItem(const wchar_t *text, int iIcon, LPARAM lParam, int iGroupId)
+{
+ LVITEM lvi = { 0 };
+ lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE;
+ lvi.iSubItem = 0;
+ lvi.pszText = (LPWSTR)text;
+ lvi.iImage = iIcon;
+ lvi.lParam = lParam;
+ if (iGroupId >= 0) {
+ lvi.mask |= LVIF_GROUPID;
+ lvi.iGroupId = iGroupId;
+ }
+
+ return InsertItem(&lvi);
+}
+
+void CCtrlListView::SetItem(int iItem, int iSubItem, const wchar_t *text, int iIcon)
+{
+ LVITEM lvi = { 0 };
+ lvi.mask = LVIF_TEXT;
+ lvi.iItem = iItem;
+ lvi.iSubItem = iSubItem;
+ lvi.pszText = (LPWSTR)text;
+ if (iIcon >= 0) {
+ lvi.mask |= LVIF_IMAGE;
+ lvi.iImage = iIcon;
+ }
+
+ SetItem(&lvi);
+}
+
+LPARAM CCtrlListView::GetItemData(int iItem) const
+{
+ LVITEM lvi = { 0 };
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = iItem;
+ return GetItem(&lvi) ? lvi.lParam : -1;
+}
+
+void CCtrlListView::GetCaretPos(CContextMenuPos &pos) const
+{
+ pos.pCtrl = this;
+
+ // position is empty, let's fill it using selection
+ if (pos.pt.x == 0 && pos.pt.y == 0) {
+ pos.iCurr = GetSelectionMark();
+ if (pos.iCurr != -1) {
+ RECT rc;
+ GetItemRect(pos.iCurr, &rc, TRUE);
+ pos.pt.x = rc.left + 8;
+ pos.pt.y = rc.top + 8;
+ ClientToScreen(m_hwnd, &pos.pt);
+ return;
+ }
+ }
+ // position is present, let's calculate current item
+ else {
+ LVHITTESTINFO hti;
+ hti.pt = pos.pt;
+ ScreenToClient(m_hwnd, &hti.pt);
+ if (SubItemHitTest(&hti) != -1) {
+ pos.iCurr = hti.iItem;
+ return;
+ }
+ }
+ CSuper::GetCaretPos(pos);
+}
+
+// classic api
+uint32_t CCtrlListView::ApproximateViewRect(int cx, int cy, int iCount)
+{ return ListView_ApproximateViewRect(m_hwnd, cx, cy, iCount);
+}
+void CCtrlListView::Arrange(UINT code)
+{ ListView_Arrange(m_hwnd, code);
+}
+void CCtrlListView::CancelEditLabel()
+{ ListView_CancelEditLabel(m_hwnd);
+}
+HIMAGELIST CCtrlListView::CreateDragImage(int iItem, LPPOINT lpptUpLeft)
+{ return ListView_CreateDragImage(m_hwnd, iItem, lpptUpLeft);
+}
+void CCtrlListView::DeleteAllItems()
+{ ListView_DeleteAllItems(m_hwnd);
+}
+void CCtrlListView::DeleteColumn(int iCol)
+{ ListView_DeleteColumn(m_hwnd, iCol);
+}
+void CCtrlListView::DeleteItem(int iItem)
+{ ListView_DeleteItem(m_hwnd, iItem);
+}
+HWND CCtrlListView::EditLabel(int iItem)
+{ return ListView_EditLabel(m_hwnd, iItem);
+}
+int CCtrlListView::EnableGroupView(BOOL fEnable)
+{ return ListView_EnableGroupView(m_hwnd, fEnable);
+}
+BOOL CCtrlListView::EnsureVisible(int i, BOOL fPartialOK)
+{ return ListView_EnsureVisible(m_hwnd, i, fPartialOK);
+}
+int CCtrlListView::FindItem(int iStart, const LVFINDINFO *plvfi)
+{ return ListView_FindItem(m_hwnd, iStart, plvfi);
+}
+COLORREF CCtrlListView::GetBkColor() const
+{ return ListView_GetBkColor(m_hwnd);
+}
+void CCtrlListView::GetBkImage(LPLVBKIMAGE plvbki) const
+{ ListView_GetBkImage(m_hwnd, plvbki);
+}
+UINT CCtrlListView::GetCallbackMask() const
+{ return ListView_GetCallbackMask(m_hwnd);
+}
+BOOL CCtrlListView::GetCheckState(UINT iIndex) const
+{ return ListView_GetCheckState(m_hwnd, iIndex);
+}
+void CCtrlListView::GetColumn(int iCol, LPLVCOLUMN pcol) const
+{ ListView_GetColumn(m_hwnd, iCol, pcol);
+}
+void CCtrlListView::GetColumnOrderArray(int iCount, int *lpiArray) const
+{ ListView_GetColumnOrderArray(m_hwnd, iCount, lpiArray);
+}
+int CCtrlListView::GetColumnWidth(int iCol) const
+{ return ListView_GetColumnWidth(m_hwnd, iCol);
+}
+int CCtrlListView::GetCountPerPage() const
+{ return ListView_GetCountPerPage(m_hwnd);
+}
+HWND CCtrlListView::GetEditControl() const
+{ return ListView_GetEditControl(m_hwnd);
+}
+uint32_t CCtrlListView::GetExtendedListViewStyle() const
+{ return ListView_GetExtendedListViewStyle(m_hwnd);
+}
+void CCtrlListView::GetGroupMetrics(LVGROUPMETRICS *pGroupMetrics) const
+{ ListView_GetGroupMetrics(m_hwnd, pGroupMetrics);
+}
+HWND CCtrlListView::GetHeader() const
+{ return ListView_GetHeader(m_hwnd);
+}
+HCURSOR CCtrlListView::GetHotCursor() const
+{ return ListView_GetHotCursor(m_hwnd);
+}
+INT CCtrlListView::GetHotItem() const
+{ return ListView_GetHotItem(m_hwnd);
+}
+uint32_t CCtrlListView::GetHoverTime() const
+{ return ListView_GetHoverTime(m_hwnd);
+}
+HIMAGELIST CCtrlListView::GetImageList(int iImageList) const
+{ return ListView_GetImageList(m_hwnd, iImageList);
+}
+BOOL CCtrlListView::GetInsertMark(LVINSERTMARK *plvim) const
+{ return ListView_GetInsertMark(m_hwnd, plvim);
+}
+COLORREF CCtrlListView::GetInsertMarkColor() const
+{ return ListView_GetInsertMarkColor(m_hwnd);
+}
+int CCtrlListView::GetInsertMarkRect(LPRECT prc) const
+{ return ListView_GetInsertMarkRect(m_hwnd, prc);
+}
+BOOL CCtrlListView::GetISearchString(LPSTR lpsz) const
+{ return ListView_GetISearchString(m_hwnd, lpsz);
+}
+bool CCtrlListView::GetItem(LPLVITEM pitem) const
+{ return ListView_GetItem(m_hwnd, pitem) == TRUE;
+}
+int CCtrlListView::GetItemCount() const
+{ return ListView_GetItemCount(m_hwnd);
+}
+void CCtrlListView::GetItemPosition(int i, POINT *ppt) const
+{ ListView_GetItemPosition(m_hwnd, i, ppt);
+}
+void CCtrlListView::GetItemRect(int i, RECT *prc, int code) const
+{ ListView_GetItemRect(m_hwnd, i, prc, code);
+}
+uint32_t CCtrlListView::GetItemSpacing(BOOL fSmall) const
+{ return ListView_GetItemSpacing(m_hwnd, fSmall);
+}
+UINT CCtrlListView::GetItemState(int i, UINT mask) const
+{ return ListView_GetItemState(m_hwnd, i, mask);
+}
+void CCtrlListView::GetItemText(int iItem, int iSubItem, LPTSTR pszText, int cchTextMax) const
+{ ListView_GetItemText(m_hwnd, iItem, iSubItem, pszText, cchTextMax);
+}
+int CCtrlListView::GetNextItem(int iStart, UINT flags) const
+{ return ListView_GetNextItem(m_hwnd, iStart, flags);
+}
+BOOL CCtrlListView::GetNumberOfWorkAreas(LPUINT lpuWorkAreas) const
+{ return ListView_GetNumberOfWorkAreas(m_hwnd, lpuWorkAreas);
+}
+BOOL CCtrlListView::GetOrigin(LPPOINT lpptOrg) const
+{ return ListView_GetOrigin(m_hwnd, lpptOrg);
+}
+COLORREF CCtrlListView::GetOutlineColor() const
+{ return ListView_GetOutlineColor(m_hwnd);
+}
+UINT CCtrlListView::GetSelectedColumn() const
+{ return ListView_GetSelectedColumn(m_hwnd);
+}
+UINT CCtrlListView::GetSelectedCount() const
+{ return ListView_GetSelectedCount(m_hwnd);
+}
+INT CCtrlListView::GetSelectionMark() const
+{ return ListView_GetSelectionMark(m_hwnd);
+}
+int CCtrlListView::GetStringWidth(LPCSTR psz) const
+{ return ListView_GetStringWidth(m_hwnd, psz);
+}
+BOOL CCtrlListView::GetSubItemRect(int iItem, int iSubItem, int code, LPRECT lpRect) const
+{ return ListView_GetSubItemRect(m_hwnd, iItem, iSubItem, code, lpRect);
+}
+COLORREF CCtrlListView::GetTextBkColor() const
+{ return ListView_GetTextBkColor(m_hwnd);
+}
+COLORREF CCtrlListView::GetTextColor() const
+{ return ListView_GetTextColor(m_hwnd);
+}
+void CCtrlListView::GetTileInfo(PLVTILEINFO plvtinfo) const
+{ ListView_GetTileInfo(m_hwnd, plvtinfo);
+}
+void CCtrlListView::GetTileViewInfo(PLVTILEVIEWINFO plvtvinfo) const
+{ ListView_GetTileViewInfo(m_hwnd, plvtvinfo);
+}
+HWND CCtrlListView::GetToolTips() const
+{ return ListView_GetToolTips(m_hwnd);
+}
+int CCtrlListView::GetTopIndex() const
+{ return ListView_GetTopIndex(m_hwnd);
+}
+BOOL CCtrlListView::GetUnicodeFormat() const
+{ return ListView_GetUnicodeFormat(m_hwnd);
+}
+uint32_t CCtrlListView::GetView() const
+{ return ListView_GetView(m_hwnd);
+}
+BOOL CCtrlListView::GetViewRect(RECT *prc) const
+{ return ListView_GetViewRect(m_hwnd, prc);
+}
+void CCtrlListView::GetWorkAreas(INT nWorkAreas, LPRECT lprc) const
+{ ListView_GetWorkAreas(m_hwnd, nWorkAreas, lprc);
+}
+BOOL CCtrlListView::HasGroup(int dwGroupId)
+{ return ListView_HasGroup(m_hwnd, dwGroupId);
+}
+int CCtrlListView::HitTest(LPLVHITTESTINFO pinfo) const
+{ return ListView_HitTest(m_hwnd, pinfo);
+}
+int CCtrlListView::InsertColumn(int iCol, const LVCOLUMN *pcol)
+{ return ListView_InsertColumn(m_hwnd, iCol, pcol);
+}
+int CCtrlListView::InsertGroup(int index, PLVGROUP pgrp)
+{ return ListView_InsertGroup(m_hwnd, index, pgrp);
+}
+void CCtrlListView::InsertGroupSorted(PLVINSERTGROUPSORTED structInsert)
+{ ListView_InsertGroupSorted(m_hwnd, structInsert);
+}
+int CCtrlListView::InsertItem(const LVITEM *pitem)
+{ return ListView_InsertItem(m_hwnd, pitem);
+}
+BOOL CCtrlListView::InsertMarkHitTest(LPPOINT point, LVINSERTMARK *plvim)
+{ return ListView_InsertMarkHitTest(m_hwnd, point, plvim);
+}
+BOOL CCtrlListView::IsGroupViewEnabled()
+{ return ListView_IsGroupViewEnabled(m_hwnd);
+}
+UINT CCtrlListView::MapIDToIndex(UINT id)
+{ return ListView_MapIDToIndex(m_hwnd, id);
+}
+UINT CCtrlListView::MapIndexToID(UINT index)
+{ return ListView_MapIndexToID(m_hwnd, index);
+}
+BOOL CCtrlListView::RedrawItems(int iFirst, int iLast)
+{ return ListView_RedrawItems(m_hwnd, iFirst, iLast);
+}
+void CCtrlListView::RemoveAllGroups()
+{ ListView_RemoveAllGroups(m_hwnd);
+}
+int CCtrlListView::RemoveGroup(int iGroupId)
+{ return ListView_RemoveGroup(m_hwnd, iGroupId);
+}
+BOOL CCtrlListView::Scroll(int dx, int dy)
+{ return ListView_Scroll(m_hwnd, dx, dy);
+}
+BOOL CCtrlListView::SetBkColor(COLORREF clrBk)
+{ return ListView_SetBkColor(m_hwnd, clrBk);
+}
+BOOL CCtrlListView::SetBkImage(LPLVBKIMAGE plvbki)
+{ return ListView_SetBkImage(m_hwnd, plvbki);
+}
+BOOL CCtrlListView::SetCallbackMask(UINT mask)
+{ return ListView_SetCallbackMask(m_hwnd, mask);
+}
+void CCtrlListView::SetCheckState(UINT iIndex, BOOL fCheck)
+{ ListView_SetCheckState(m_hwnd, iIndex, fCheck);
+}
+BOOL CCtrlListView::SetColumn(int iCol, LPLVCOLUMN pcol)
+{ return ListView_SetColumn(m_hwnd, iCol, pcol);
+}
+BOOL CCtrlListView::SetColumnOrderArray(int iCount, int *lpiArray)
+{ return ListView_SetColumnOrderArray(m_hwnd, iCount, lpiArray);
+}
+BOOL CCtrlListView::SetColumnWidth(int iCol, int cx)
+{ return ListView_SetColumnWidth(m_hwnd, iCol, cx);
+}
+void CCtrlListView::SetExtendedListViewStyle(uint32_t dwExStyle)
+{ ListView_SetExtendedListViewStyle(m_hwnd, dwExStyle);
+}
+void CCtrlListView::SetExtendedListViewStyleEx(uint32_t dwExMask, uint32_t dwExStyle)
+{ ListView_SetExtendedListViewStyleEx(m_hwnd, dwExMask, dwExStyle);
+}
+int CCtrlListView::SetGroupInfo(int iGroupId, PLVGROUP pgrp)
+{ return ListView_SetGroupInfo(m_hwnd, iGroupId, pgrp);
+}
+void CCtrlListView::SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics)
+{ ListView_SetGroupMetrics(m_hwnd, pGroupMetrics);
+}
+HCURSOR CCtrlListView::SetHotCursor(HCURSOR hCursor)
+{ return ListView_SetHotCursor(m_hwnd, hCursor);
+}
+INT CCtrlListView::SetHotItem(INT iIndex)
+{ return ListView_SetHotItem(m_hwnd, iIndex);
+}
+void CCtrlListView::SetHoverTime(uint32_t dwHoverTime)
+{ ListView_SetHoverTime(m_hwnd, dwHoverTime);
+}
+uint32_t CCtrlListView::SetIconSpacing(int cx, int cy)
+{ return ListView_SetIconSpacing(m_hwnd, cx, cy);
+}
+HIMAGELIST CCtrlListView::SetImageList(HIMAGELIST himl, int iImageList)
+{ return ListView_SetImageList(m_hwnd, himl, iImageList);
+}
+BOOL CCtrlListView::SetInfoTip(PLVSETINFOTIP plvSetInfoTip)
+{ return ListView_SetInfoTip(m_hwnd, plvSetInfoTip);
+}
+BOOL CCtrlListView::SetInsertMark(LVINSERTMARK *plvim)
+{ return ListView_SetInsertMark(m_hwnd, plvim);
+}
+COLORREF CCtrlListView::SetInsertMarkColor(COLORREF color)
+{ return ListView_SetInsertMarkColor(m_hwnd, color);
+}
+BOOL CCtrlListView::SetItem(const LVITEM *pitem)
+{ return ListView_SetItem(m_hwnd, pitem);
+}
+void CCtrlListView::SetItemCount(int cItems)
+{ ListView_SetItemCount(m_hwnd, cItems);
+}
+void CCtrlListView::SetItemCountEx(int cItems, uint32_t dwFlags)
+{ ListView_SetItemCountEx(m_hwnd, cItems, dwFlags);
+}
+BOOL CCtrlListView::SetItemPosition(int i, int x, int y)
+{ return ListView_SetItemPosition(m_hwnd, i, x, y);
+}
+void CCtrlListView::SetItemPosition32(int iItem, int x, int y)
+{ ListView_SetItemPosition32(m_hwnd, iItem, x, y);
+}
+void CCtrlListView::SetItemState(int i, UINT state, UINT mask)
+{ ListView_SetItemState(m_hwnd, i, state, mask);
+}
+void CCtrlListView::SetItemText(int i, int iSubItem, const wchar_t *pszText)
+{ ListView_SetItemText(m_hwnd, i, iSubItem, (LPWSTR)pszText);
+}
+COLORREF CCtrlListView::SetOutlineColor(COLORREF color)
+{ return ListView_SetOutlineColor(m_hwnd, color);
+}
+void CCtrlListView::SetSelectedColumn(int iCol)
+{ ListView_SetSelectedColumn(m_hwnd, iCol);
+}
+INT CCtrlListView::SetSelectionMark(INT iIndex)
+{ return ListView_SetSelectionMark(m_hwnd, iIndex);
+}
+BOOL CCtrlListView::SetTextBkColor(COLORREF clrText)
+{ return ListView_SetTextBkColor(m_hwnd, clrText);
+}
+BOOL CCtrlListView::SetTextColor(COLORREF clrText)
+{ return ListView_SetTextColor(m_hwnd, clrText);
+}
+BOOL CCtrlListView::SetTileInfo(PLVTILEINFO plvtinfo)
+{ return ListView_SetTileInfo(m_hwnd, plvtinfo);
+}
+BOOL CCtrlListView::SetTileViewInfo(PLVTILEVIEWINFO plvtvinfo)
+{ return ListView_SetTileViewInfo(m_hwnd, plvtvinfo);
+}
+HWND CCtrlListView::SetToolTips(HWND ToolTip)
+{ return ListView_SetToolTips(m_hwnd, ToolTip);
+}
+BOOL CCtrlListView::SetUnicodeFormat(BOOL fUnicode)
+{ return ListView_SetUnicodeFormat(m_hwnd, fUnicode);
+}
+int CCtrlListView::SetView(uint32_t iView)
+{ return ListView_SetView(m_hwnd, iView);
+}
+void CCtrlListView::SetWorkAreas(INT nWorkAreas, LPRECT lprc)
+{ ListView_SetWorkAreas(m_hwnd, nWorkAreas, lprc);
+}
+int CCtrlListView::SortGroups(PFNLVGROUPCOMPARE pfnGroupCompare, LPVOID plv)
+{ return ListView_SortGroups(m_hwnd, pfnGroupCompare, plv);
+}
+BOOL CCtrlListView::SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
+{ return ListView_SortItems(m_hwnd, pfnCompare, lParamSort);
+}
+BOOL CCtrlListView::SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
+{ return ListView_SortItemsEx(m_hwnd, pfnCompare, lParamSort);
+}
+INT CCtrlListView::SubItemHitTest(LPLVHITTESTINFO pInfo) const
+{ return ListView_SubItemHitTest(m_hwnd, pInfo);
+}
+BOOL CCtrlListView::Update(int iItem)
+{ return ListView_Update(m_hwnd, iItem);
+}
diff --git a/src/mir_core/src/Windows/CCtrlMButton.cpp b/src/mir_core/src/Windows/CCtrlMButton.cpp
index 8d9198e144..cc05a3a8e4 100644
--- a/src/mir_core/src/Windows/CCtrlMButton.cpp
+++ b/src/mir_core/src/Windows/CCtrlMButton.cpp
@@ -1,62 +1,62 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlMButton
-
-CCtrlMButton::CCtrlMButton(CDlgBase *dlg, int ctrlId, HICON hIcon, const char* tooltip)
- : CCtrlButton(dlg, ctrlId),
- m_hIcon(hIcon),
- m_toolTip(tooltip)
-{}
-
-CCtrlMButton::CCtrlMButton(CDlgBase *dlg, int ctrlId, int iCoreIcon, const char* tooltip)
- : CCtrlButton(dlg, ctrlId),
- m_hIcon(::Skin_LoadIcon(iCoreIcon)),
- m_toolTip(tooltip)
-{}
-
-CCtrlMButton::~CCtrlMButton()
-{
- ::IcoLib_ReleaseIcon(m_hIcon);
-}
-
-void CCtrlMButton::OnInit()
-{
- CCtrlButton::OnInit();
-
- SendMessage(m_hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)m_hIcon);
- SendMessage(m_hwnd, BUTTONADDTOOLTIP, (WPARAM)m_toolTip, 0);
- SendMessage(m_hwnd, BUTTONSETASFLATBTN, (WPARAM)m_toolTip, 0);
-}
-
-void CCtrlMButton::MakeFlat()
-{
- SendMessage(m_hwnd, BUTTONSETASFLATBTN, TRUE, 0);
-}
-
-void CCtrlMButton::MakePush()
-{
- SendMessage(m_hwnd, BUTTONSETASPUSHBTN, TRUE, 0);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlMButton
+
+CCtrlMButton::CCtrlMButton(CDlgBase *dlg, int ctrlId, HICON hIcon, const char* tooltip)
+ : CCtrlButton(dlg, ctrlId),
+ m_hIcon(hIcon),
+ m_toolTip(tooltip)
+{}
+
+CCtrlMButton::CCtrlMButton(CDlgBase *dlg, int ctrlId, int iCoreIcon, const char* tooltip)
+ : CCtrlButton(dlg, ctrlId),
+ m_hIcon(::Skin_LoadIcon(iCoreIcon)),
+ m_toolTip(tooltip)
+{}
+
+CCtrlMButton::~CCtrlMButton()
+{
+ ::IcoLib_ReleaseIcon(m_hIcon);
+}
+
+void CCtrlMButton::OnInit()
+{
+ CCtrlButton::OnInit();
+
+ SendMessage(m_hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)m_hIcon);
+ SendMessage(m_hwnd, BUTTONADDTOOLTIP, (WPARAM)m_toolTip, 0);
+ SendMessage(m_hwnd, BUTTONSETASFLATBTN, (WPARAM)m_toolTip, 0);
+}
+
+void CCtrlMButton::MakeFlat()
+{
+ SendMessage(m_hwnd, BUTTONSETASFLATBTN, TRUE, 0);
+}
+
+void CCtrlMButton::MakePush()
+{
+ SendMessage(m_hwnd, BUTTONSETASPUSHBTN, TRUE, 0);
+}
diff --git a/src/mir_core/src/Windows/CCtrlPages.cpp b/src/mir_core/src/Windows/CCtrlPages.cpp
index 512c32e142..c2a95553c5 100644
--- a/src/mir_core/src/Windows/CCtrlPages.cpp
+++ b/src/mir_core/src/Windows/CCtrlPages.cpp
@@ -1,411 +1,411 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-static volatile long g_order = 1;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlPages
-
-struct CCtrlPages::TPageInfo : public MZeroedObject
-{
- TPageInfo()
- {
- m_iOrder = InterlockedIncrement(&g_order);
- }
-
- ~TPageInfo()
- {
- if (m_hIcon)
- DestroyIcon(m_hIcon);
- }
-
- int m_iOrder;
- ptrW m_ptszHeader;
- HICON m_hIcon;
- bool m_bChanged, m_bScheduledResize;
- CDlgBase *m_pDlg;
-};
-
-CCtrlPages::CCtrlPages(CDlgBase *dlg, int ctrlId)
- : CCtrlBase(dlg, ctrlId),
- m_hIml(nullptr),
- m_pActivePage(nullptr),
- m_pages(4, NumericKeySortT)
-{}
-
-void CCtrlPages::OnInit()
-{
- CSuper::OnInit();
- Subclass();
-
- for (auto &it : m_pages)
- InsertPage(it);
- m_pages.destroy();
-
- ::SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, ::GetWindowLongPtr(m_hwnd, GWL_EXSTYLE) | WS_EX_CONTROLPARENT);
-
- TPageInfo *info = GetCurrPage();
- if (info) {
- m_pActivePage = info->m_pDlg;
- ShowPage(m_pActivePage);
-
- PSHNOTIFY pshn;
- pshn.hdr.code = PSN_INFOCHANGED;
- pshn.hdr.hwndFrom = m_pActivePage->GetHwnd();
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
- SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
- }
-}
-
-LRESULT CCtrlPages::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- int tabCount;
-
- switch (msg) {
- case WM_SIZE:
- if (TPageInfo *pCurrInfo = GetCurrPage()) {
- tabCount = GetCount();
- for (int i = 0; i < tabCount; i++) {
- TPageInfo *p = GetItemPage(i);
- if (p == nullptr)
- continue;
- if (p == pCurrInfo) {
- RECT rc;
- GetClientRect(m_hwnd, &rc);
- TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
- SetWindowPos(p->m_pDlg->GetHwnd(), nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
- }
- else p->m_bScheduledResize = true;
- }
- }
- break;
-
- case PSM_CHANGED:
- if (TPageInfo *info = GetCurrPage())
- info->m_bChanged = TRUE;
- return TRUE;
-
- case PSM_FORCECHANGED:
- tabCount = GetCount();
-
- PSHNOTIFY pshn;
- pshn.hdr.code = PSN_INFOCHANGED;
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
- for (int i = 0; i < tabCount; i++) {
- TPageInfo *p = GetItemPage(i);
- if (p) {
- pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
- if (pshn.hdr.hwndFrom != nullptr)
- SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
- }
- }
- break;
- }
-
- return CSuper::CustomWndProc(msg, wParam, lParam);
-}
-
-void CCtrlPages::AddPage(const wchar_t *ptszName, HICON hIcon, CDlgBase *pDlg)
-{
- TPageInfo *info = new TPageInfo;
- info->m_pDlg = pDlg;
- info->m_hIcon = hIcon;
- info->m_ptszHeader = mir_wstrdup(ptszName);
-
- if (m_hwnd != nullptr) {
- InsertPage(info);
-
- if (GetCount() == 1) {
- m_pActivePage = info->m_pDlg;
- ShowPage(m_pActivePage);
- }
- }
- m_pages.insert(info);
-}
-
-void CCtrlPages::ActivatePage(int iPage)
-{
- TPageInfo *info = GetItemPage(iPage);
- if (info == nullptr || info->m_pDlg == nullptr)
- return;
-
- if (m_pActivePage != nullptr)
- ShowWindow(m_pActivePage->GetHwnd(), SW_HIDE);
-
- m_pActivePage = info->m_pDlg;
- if (m_pActivePage->GetHwnd() && info->m_bScheduledResize) {
- RECT rc;
- GetClientRect(m_hwnd, &rc);
- TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
- SetWindowPos(m_pActivePage->GetHwnd(), nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
- }
-
- TabCtrl_SetCurSel(m_hwnd, iPage);
- ShowPage(m_pActivePage);
- ::SendMessage(m_pActivePage->GetHwnd(), WM_MOUSEACTIVATE, 0, 0);
-}
-
-void CCtrlPages::CheckRowCount()
-{
- int iRowCount = TabCtrl_GetRowCount(m_hwnd);
- if (m_numRows != iRowCount) {
- m_numRows = iRowCount;
- for (auto &p : m_pages)
- p->m_bScheduledResize = true;
- }
-}
-
-int CCtrlPages::GetCount()
-{
- return TabCtrl_GetItemCount(m_hwnd);
-}
-
-CDlgBase* CCtrlPages::GetNthPage(int iPage)
-{
- TPageInfo *info = GetItemPage(iPage);
- return (info == nullptr) ? nullptr : info->m_pDlg;
-}
-
-CCtrlPages::TPageInfo* CCtrlPages::GetCurrPage()
-{
- TCITEM tci = { 0 };
- tci.mask = TCIF_PARAM;
- if (!TabCtrl_GetItem(m_hwnd, TabCtrl_GetCurSel(m_hwnd), &tci))
- return nullptr;
-
- return (TPageInfo*)tci.lParam;
-}
-
-CCtrlPages::TPageInfo* CCtrlPages::GetItemPage(int iPage)
-{
- TCITEM tci = { 0 };
- tci.mask = TCIF_PARAM;
- if (!TabCtrl_GetItem(m_hwnd, iPage, &tci))
- return nullptr;
-
- return (TPageInfo*)tci.lParam;
-}
-
-int CCtrlPages::GetDlgIndex(CDlgBase *pDlg)
-{
- int tabCount = TabCtrl_GetItemCount(m_hwnd);
- for (int i = 0; i < tabCount; i++) {
- TCITEM tci;
- tci.mask = TCIF_PARAM | TCIF_IMAGE;
- TabCtrl_GetItem(m_hwnd, i, &tci);
- TPageInfo *pPage = (TPageInfo *)tci.lParam;
- if (pPage == nullptr)
- continue;
-
- if (pPage->m_pDlg == pDlg)
- return i;
- }
-
- return -1;
-}
-
-void CCtrlPages::InsertPage(TPageInfo *pPage)
-{
- TCITEM tci = { 0 };
- tci.mask = TCIF_PARAM | TCIF_TEXT;
- tci.lParam = (LPARAM)pPage;
- tci.pszText = TranslateW_LP(pPage->m_ptszHeader);
- if (pPage->m_hIcon) {
- if (!m_hIml) {
- m_hIml = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1);
- TabCtrl_SetImageList(m_hwnd, m_hIml);
- }
-
- tci.mask |= TCIF_IMAGE;
- tci.iImage = ImageList_AddIcon(m_hIml, pPage->m_hIcon);
- }
-
- TabCtrl_InsertItem(m_hwnd, TabCtrl_GetItemCount(m_hwnd), &tci);
-
- CheckRowCount();
-}
-
-void CCtrlPages::RemovePage(int iPage)
-{
- TPageInfo *p = GetItemPage(iPage);
- if (p == nullptr)
- return;
-
- TabCtrl_DeleteItem(m_hwnd, iPage);
- m_pages.remove(p);
- delete p;
-
- CheckRowCount();
-}
-
-void CCtrlPages::ShowPage(CDlgBase *pDlg)
-{
- if (pDlg->GetHwnd() == nullptr) {
- pDlg->SetParent(m_hwnd);
- pDlg->Create();
-
- RECT rc;
- GetClientRect(m_hwnd, &rc);
- TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
- SetWindowPos(pDlg->GetHwnd(), HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE);
-
- EnableThemeDialogTexture(pDlg->GetHwnd(), ETDT_ENABLETAB);
-
- PSHNOTIFY pshn;
- pshn.hdr.code = PSN_INFOCHANGED;
- pshn.hdr.hwndFrom = pDlg->GetHwnd();
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
- SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
- }
- ShowWindow(pDlg->GetHwnd(), SW_SHOW);
-}
-
-void CCtrlPages::SwapPages(int idx1, int idx2)
-{
- TPageInfo *p1 = GetItemPage(idx1), *p2 = GetItemPage(idx2);
- if (p1 == nullptr || p2 == nullptr)
- return;
-
- TabCtrl_DeleteItem(m_hwnd, idx1);
-
- TCITEM tci = { 0 };
- tci.mask = TCIF_PARAM | TCIF_TEXT;
- tci.lParam = (LPARAM)p1;
- tci.pszText = TranslateW_LP(p1->m_ptszHeader);
- TabCtrl_InsertItem(m_hwnd, idx2, &tci);
-}
-
-BOOL CCtrlPages::OnNotify(int /*idCtrl*/, NMHDR *pnmh)
-{
- TPageInfo *info;
- PSHNOTIFY pshn;
-
- switch (pnmh->code) {
- case TCN_SELCHANGING:
- if (info = GetCurrPage()) {
- pshn.hdr.code = PSN_KILLACTIVE;
- pshn.hdr.hwndFrom = info->m_pDlg->GetHwnd();
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
- if (SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn)) {
- SetWindowLongPtr(GetParent()->GetHwnd(), DWLP_MSGRESULT, TRUE);
- return TRUE;
- }
- }
- return TRUE;
-
- case TCN_SELCHANGE:
- if (m_pActivePage != nullptr)
- m_pActivePage->Hide();
-
- if (info = GetCurrPage()) {
- m_pActivePage = info->m_pDlg;
- ShowPage(m_pActivePage);
- }
- else m_pActivePage = nullptr;
- return TRUE;
- }
-
- return FALSE;
-}
-
-void CCtrlPages::OnReset()
-{
- CSuper::OnReset();
-
- PSHNOTIFY pshn;
- pshn.hdr.code = PSN_INFOCHANGED;
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
-
- int tabCount = GetCount();
- for (int i = 0; i < tabCount; i++) {
- TPageInfo *p = GetItemPage(i);
- if (p->m_pDlg->GetHwnd() == nullptr || !p->m_bChanged)
- continue;
-
- pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
- SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
- }
-}
-
-bool CCtrlPages::OnApply()
-{
- PSHNOTIFY pshn;
- pshn.hdr.idFrom = 0;
- pshn.lParam = 0;
-
- if (m_pActivePage != nullptr) {
- pshn.hdr.code = PSN_KILLACTIVE;
- pshn.hdr.hwndFrom = m_pActivePage->GetHwnd();
- if (SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn))
- return false;
- }
-
- pshn.hdr.code = PSN_APPLY;
- int tabCount = GetCount();
- for (int i = 0; i < tabCount; i++) {
- TPageInfo *p = GetItemPage(i);
- if (p->m_pDlg->GetHwnd() == nullptr || !p->m_bChanged)
- continue;
-
- pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
- SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
- if (GetWindowLongPtr(pshn.hdr.hwndFrom, DWLP_MSGRESULT) == PSNRET_INVALID_NOCHANGEPAGE) {
- TabCtrl_SetCurSel(m_hwnd, i);
- if (m_pActivePage != nullptr)
- m_pActivePage->Hide();
- m_pActivePage = p->m_pDlg;
- m_pActivePage->Show();
- return false;
- }
- }
-
- CSuper::OnApply();
- return true;
-}
-
-void CCtrlPages::OnDestroy()
-{
- int tabCount = GetCount();
- for (int i = 0; i < tabCount; i++) {
- TPageInfo *p = GetItemPage(i);
- CDlgBase *pDlg = p->m_pDlg; p->m_pDlg = nullptr;
- if (pDlg->GetHwnd())
- pDlg->Close();
- delete p;
- }
-
- TabCtrl_DeleteAllItems(m_hwnd);
-
- if (m_hIml) {
- TabCtrl_SetImageList(m_hwnd, nullptr);
- ImageList_Destroy(m_hIml);
- }
-
- CSuper::OnDestroy();
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+static volatile long g_order = 1;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlPages
+
+struct CCtrlPages::TPageInfo : public MZeroedObject
+{
+ TPageInfo()
+ {
+ m_iOrder = InterlockedIncrement(&g_order);
+ }
+
+ ~TPageInfo()
+ {
+ if (m_hIcon)
+ DestroyIcon(m_hIcon);
+ }
+
+ int m_iOrder;
+ ptrW m_ptszHeader;
+ HICON m_hIcon;
+ bool m_bChanged, m_bScheduledResize;
+ CDlgBase *m_pDlg;
+};
+
+CCtrlPages::CCtrlPages(CDlgBase *dlg, int ctrlId)
+ : CCtrlBase(dlg, ctrlId),
+ m_hIml(nullptr),
+ m_pActivePage(nullptr),
+ m_pages(4, NumericKeySortT)
+{}
+
+void CCtrlPages::OnInit()
+{
+ CSuper::OnInit();
+ Subclass();
+
+ for (auto &it : m_pages)
+ InsertPage(it);
+ m_pages.destroy();
+
+ ::SetWindowLongPtr(m_hwnd, GWL_EXSTYLE, ::GetWindowLongPtr(m_hwnd, GWL_EXSTYLE) | WS_EX_CONTROLPARENT);
+
+ TPageInfo *info = GetCurrPage();
+ if (info) {
+ m_pActivePage = info->m_pDlg;
+ ShowPage(m_pActivePage);
+
+ PSHNOTIFY pshn;
+ pshn.hdr.code = PSN_INFOCHANGED;
+ pshn.hdr.hwndFrom = m_pActivePage->GetHwnd();
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+ SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
+ }
+}
+
+LRESULT CCtrlPages::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int tabCount;
+
+ switch (msg) {
+ case WM_SIZE:
+ if (TPageInfo *pCurrInfo = GetCurrPage()) {
+ tabCount = GetCount();
+ for (int i = 0; i < tabCount; i++) {
+ TPageInfo *p = GetItemPage(i);
+ if (p == nullptr)
+ continue;
+ if (p == pCurrInfo) {
+ RECT rc;
+ GetClientRect(m_hwnd, &rc);
+ TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
+ SetWindowPos(p->m_pDlg->GetHwnd(), nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+ else p->m_bScheduledResize = true;
+ }
+ }
+ break;
+
+ case PSM_CHANGED:
+ if (TPageInfo *info = GetCurrPage())
+ info->m_bChanged = TRUE;
+ return TRUE;
+
+ case PSM_FORCECHANGED:
+ tabCount = GetCount();
+
+ PSHNOTIFY pshn;
+ pshn.hdr.code = PSN_INFOCHANGED;
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+ for (int i = 0; i < tabCount; i++) {
+ TPageInfo *p = GetItemPage(i);
+ if (p) {
+ pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
+ if (pshn.hdr.hwndFrom != nullptr)
+ SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
+ }
+ }
+ break;
+ }
+
+ return CSuper::CustomWndProc(msg, wParam, lParam);
+}
+
+void CCtrlPages::AddPage(const wchar_t *ptszName, HICON hIcon, CDlgBase *pDlg)
+{
+ TPageInfo *info = new TPageInfo;
+ info->m_pDlg = pDlg;
+ info->m_hIcon = hIcon;
+ info->m_ptszHeader = mir_wstrdup(ptszName);
+
+ if (m_hwnd != nullptr) {
+ InsertPage(info);
+
+ if (GetCount() == 1) {
+ m_pActivePage = info->m_pDlg;
+ ShowPage(m_pActivePage);
+ }
+ }
+ m_pages.insert(info);
+}
+
+void CCtrlPages::ActivatePage(int iPage)
+{
+ TPageInfo *info = GetItemPage(iPage);
+ if (info == nullptr || info->m_pDlg == nullptr)
+ return;
+
+ if (m_pActivePage != nullptr)
+ ShowWindow(m_pActivePage->GetHwnd(), SW_HIDE);
+
+ m_pActivePage = info->m_pDlg;
+ if (m_pActivePage->GetHwnd() && info->m_bScheduledResize) {
+ RECT rc;
+ GetClientRect(m_hwnd, &rc);
+ TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
+ SetWindowPos(m_pActivePage->GetHwnd(), nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+
+ TabCtrl_SetCurSel(m_hwnd, iPage);
+ ShowPage(m_pActivePage);
+ ::SendMessage(m_pActivePage->GetHwnd(), WM_MOUSEACTIVATE, 0, 0);
+}
+
+void CCtrlPages::CheckRowCount()
+{
+ int iRowCount = TabCtrl_GetRowCount(m_hwnd);
+ if (m_numRows != iRowCount) {
+ m_numRows = iRowCount;
+ for (auto &p : m_pages)
+ p->m_bScheduledResize = true;
+ }
+}
+
+int CCtrlPages::GetCount()
+{
+ return TabCtrl_GetItemCount(m_hwnd);
+}
+
+CDlgBase* CCtrlPages::GetNthPage(int iPage)
+{
+ TPageInfo *info = GetItemPage(iPage);
+ return (info == nullptr) ? nullptr : info->m_pDlg;
+}
+
+CCtrlPages::TPageInfo* CCtrlPages::GetCurrPage()
+{
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM;
+ if (!TabCtrl_GetItem(m_hwnd, TabCtrl_GetCurSel(m_hwnd), &tci))
+ return nullptr;
+
+ return (TPageInfo*)tci.lParam;
+}
+
+CCtrlPages::TPageInfo* CCtrlPages::GetItemPage(int iPage)
+{
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM;
+ if (!TabCtrl_GetItem(m_hwnd, iPage, &tci))
+ return nullptr;
+
+ return (TPageInfo*)tci.lParam;
+}
+
+int CCtrlPages::GetDlgIndex(CDlgBase *pDlg)
+{
+ int tabCount = TabCtrl_GetItemCount(m_hwnd);
+ for (int i = 0; i < tabCount; i++) {
+ TCITEM tci;
+ tci.mask = TCIF_PARAM | TCIF_IMAGE;
+ TabCtrl_GetItem(m_hwnd, i, &tci);
+ TPageInfo *pPage = (TPageInfo *)tci.lParam;
+ if (pPage == nullptr)
+ continue;
+
+ if (pPage->m_pDlg == pDlg)
+ return i;
+ }
+
+ return -1;
+}
+
+void CCtrlPages::InsertPage(TPageInfo *pPage)
+{
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM | TCIF_TEXT;
+ tci.lParam = (LPARAM)pPage;
+ tci.pszText = TranslateW_LP(pPage->m_ptszHeader);
+ if (pPage->m_hIcon) {
+ if (!m_hIml) {
+ m_hIml = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1);
+ TabCtrl_SetImageList(m_hwnd, m_hIml);
+ }
+
+ tci.mask |= TCIF_IMAGE;
+ tci.iImage = ImageList_AddIcon(m_hIml, pPage->m_hIcon);
+ }
+
+ TabCtrl_InsertItem(m_hwnd, TabCtrl_GetItemCount(m_hwnd), &tci);
+
+ CheckRowCount();
+}
+
+void CCtrlPages::RemovePage(int iPage)
+{
+ TPageInfo *p = GetItemPage(iPage);
+ if (p == nullptr)
+ return;
+
+ TabCtrl_DeleteItem(m_hwnd, iPage);
+ m_pages.remove(p);
+ delete p;
+
+ CheckRowCount();
+}
+
+void CCtrlPages::ShowPage(CDlgBase *pDlg)
+{
+ if (pDlg->GetHwnd() == nullptr) {
+ pDlg->SetParent(m_hwnd);
+ pDlg->Create();
+
+ RECT rc;
+ GetClientRect(m_hwnd, &rc);
+ TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
+ SetWindowPos(pDlg->GetHwnd(), HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE);
+
+ EnableThemeDialogTexture(pDlg->GetHwnd(), ETDT_ENABLETAB);
+
+ PSHNOTIFY pshn;
+ pshn.hdr.code = PSN_INFOCHANGED;
+ pshn.hdr.hwndFrom = pDlg->GetHwnd();
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+ SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
+ }
+ ShowWindow(pDlg->GetHwnd(), SW_SHOW);
+}
+
+void CCtrlPages::SwapPages(int idx1, int idx2)
+{
+ TPageInfo *p1 = GetItemPage(idx1), *p2 = GetItemPage(idx2);
+ if (p1 == nullptr || p2 == nullptr)
+ return;
+
+ TabCtrl_DeleteItem(m_hwnd, idx1);
+
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM | TCIF_TEXT;
+ tci.lParam = (LPARAM)p1;
+ tci.pszText = TranslateW_LP(p1->m_ptszHeader);
+ TabCtrl_InsertItem(m_hwnd, idx2, &tci);
+}
+
+BOOL CCtrlPages::OnNotify(int /*idCtrl*/, NMHDR *pnmh)
+{
+ TPageInfo *info;
+ PSHNOTIFY pshn;
+
+ switch (pnmh->code) {
+ case TCN_SELCHANGING:
+ if (info = GetCurrPage()) {
+ pshn.hdr.code = PSN_KILLACTIVE;
+ pshn.hdr.hwndFrom = info->m_pDlg->GetHwnd();
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+ if (SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn)) {
+ SetWindowLongPtr(GetParent()->GetHwnd(), DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ }
+ return TRUE;
+
+ case TCN_SELCHANGE:
+ if (m_pActivePage != nullptr)
+ m_pActivePage->Hide();
+
+ if (info = GetCurrPage()) {
+ m_pActivePage = info->m_pDlg;
+ ShowPage(m_pActivePage);
+ }
+ else m_pActivePage = nullptr;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void CCtrlPages::OnReset()
+{
+ CSuper::OnReset();
+
+ PSHNOTIFY pshn;
+ pshn.hdr.code = PSN_INFOCHANGED;
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+
+ int tabCount = GetCount();
+ for (int i = 0; i < tabCount; i++) {
+ TPageInfo *p = GetItemPage(i);
+ if (p->m_pDlg->GetHwnd() == nullptr || !p->m_bChanged)
+ continue;
+
+ pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
+ SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
+ }
+}
+
+bool CCtrlPages::OnApply()
+{
+ PSHNOTIFY pshn;
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = 0;
+
+ if (m_pActivePage != nullptr) {
+ pshn.hdr.code = PSN_KILLACTIVE;
+ pshn.hdr.hwndFrom = m_pActivePage->GetHwnd();
+ if (SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn))
+ return false;
+ }
+
+ pshn.hdr.code = PSN_APPLY;
+ int tabCount = GetCount();
+ for (int i = 0; i < tabCount; i++) {
+ TPageInfo *p = GetItemPage(i);
+ if (p->m_pDlg->GetHwnd() == nullptr || !p->m_bChanged)
+ continue;
+
+ pshn.hdr.hwndFrom = p->m_pDlg->GetHwnd();
+ SendMessage(pshn.hdr.hwndFrom, WM_NOTIFY, 0, (LPARAM)&pshn);
+ if (GetWindowLongPtr(pshn.hdr.hwndFrom, DWLP_MSGRESULT) == PSNRET_INVALID_NOCHANGEPAGE) {
+ TabCtrl_SetCurSel(m_hwnd, i);
+ if (m_pActivePage != nullptr)
+ m_pActivePage->Hide();
+ m_pActivePage = p->m_pDlg;
+ m_pActivePage->Show();
+ return false;
+ }
+ }
+
+ CSuper::OnApply();
+ return true;
+}
+
+void CCtrlPages::OnDestroy()
+{
+ int tabCount = GetCount();
+ for (int i = 0; i < tabCount; i++) {
+ TPageInfo *p = GetItemPage(i);
+ CDlgBase *pDlg = p->m_pDlg; p->m_pDlg = nullptr;
+ if (pDlg->GetHwnd())
+ pDlg->Close();
+ delete p;
+ }
+
+ TabCtrl_DeleteAllItems(m_hwnd);
+
+ if (m_hIml) {
+ TabCtrl_SetImageList(m_hwnd, nullptr);
+ ImageList_Destroy(m_hIml);
+ }
+
+ CSuper::OnDestroy();
+}
diff --git a/src/mir_core/src/Windows/CCtrlRichEdit.cpp b/src/mir_core/src/Windows/CCtrlRichEdit.cpp
index 06bca26cb5..f41cad3f98 100644
--- a/src/mir_core/src/Windows/CCtrlRichEdit.cpp
+++ b/src/mir_core/src/Windows/CCtrlRichEdit.cpp
@@ -1,192 +1,192 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-#include <RichOle.h>
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlRichEdit class
-
-CCtrlRichEdit::CCtrlRichEdit(CDlgBase *dlg, int ctrlId)
- : CCtrlEdit(dlg, ctrlId)
-{}
-
-int CCtrlRichEdit::GetRichTextLength(int iCodePage) const
-{
- GETTEXTLENGTHEX gtl;
- gtl.codepage = iCodePage;
- gtl.flags = GTL_PRECISE;
- if (iCodePage == CP_ACP)
- gtl.flags |= GTL_NUMBYTES;
- else
- gtl.flags |= GTL_NUMCHARS | GT_USECRLF;
-
- return (int)SendMessage(m_hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
-}
-
-int CCtrlRichEdit::SetRichText(const wchar_t *text)
-{
- SETTEXTEX st;
- st.flags = ST_DEFAULT;
- st.codepage = 1200;
- SendMessage(m_hwnd, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)text);
-
- return GetRichTextLength(1200);
-}
-
-int CCtrlRichEdit::SetRichTextRtf(const char *text)
-{
- SETTEXTEX st;
- st.flags = ST_DEFAULT;
- st.codepage = CP_UTF8;
- SendMessage(m_hwnd, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)text);
-
- return GetRichTextLength(1200);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static DWORD CALLBACK MessageStreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
-{
- static uint32_t dwRead;
- char **ppText = (char **)dwCookie;
-
- if (*ppText == nullptr) {
- *ppText = (char *)mir_alloc(cb + 2);
- memcpy(*ppText, pbBuff, cb);
- *pcb = cb;
- dwRead = cb;
- *(*ppText + cb) = '\0';
- }
- else {
- char *p = (char *)mir_realloc(*ppText, dwRead + cb + 2);
- memcpy(p + dwRead, pbBuff, cb);
- *ppText = p;
- *pcb = cb;
- dwRead += cb;
- *(*ppText + dwRead) = '\0';
- }
- return 0;
-}
-
-char* CCtrlRichEdit::GetRichTextRtf(bool bText, bool bSelection) const
-{
- char *pszText = nullptr;
- uint32_t dwFlags = SF_USECODEPAGE | (CP_UTF8 << 16);
- if (bText)
- dwFlags |= SF_TEXT;
- else
- dwFlags |= SF_RTFNOOBJS | SFF_PLAINRTF;
- if (bSelection)
- dwFlags |= SFF_SELECTION;
-
- EDITSTREAM stream = { 0 };
- stream.pfnCallback = MessageStreamCallback;
- stream.dwCookie = (DWORD_PTR)&pszText; // pass pointer to pointer
- SendMessage(m_hwnd, EM_STREAMOUT, dwFlags, (LPARAM)&stream);
- return pszText; // pszText contains the text
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-struct CREOleCallback : public IRichEditOleCallback
-{
- CREOleCallback() : refCount(0), nextStgId(0), pictStg(nullptr) {}
- unsigned refCount;
- IStorage *pictStg;
- int nextStgId;
-
- STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR *ppvObj)
- {
- if (IsEqualIID(riid, IID_IRichEditOleCallback)) {
- *ppvObj = this;
- AddRef();
- return S_OK;
- }
- *ppvObj = nullptr;
- return E_NOINTERFACE;
- }
-
- STDMETHOD_(ULONG, AddRef)(THIS)
- {
- if (refCount == 0)
- StgCreateDocfile(nullptr, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &pictStg);
-
- return ++refCount;
- }
-
- STDMETHOD_(ULONG, Release)(THIS)
- {
- if (--refCount == 0) {
- if (pictStg) {
- pictStg->Release();
- pictStg = nullptr;
- }
- }
- return refCount;
- }
-
- STDMETHOD(GetNewStorage)(LPSTORAGE *lplpstg)
- {
- wchar_t sztName[64];
- mir_snwprintf(sztName, L"s%u", nextStgId++);
- if (pictStg == nullptr)
- return STG_E_MEDIUMFULL;
- return pictStg->CreateStorage(sztName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, lplpstg);
- }
-
- STDMETHOD(ContextSensitiveHelp)(BOOL)
- { return S_OK; }
- STDMETHOD(GetInPlaceContext)(LPOLEINPLACEFRAME*, LPOLEINPLACEUIWINDOW*, LPOLEINPLACEFRAMEINFO)
- { return E_INVALIDARG; }
- STDMETHOD(ShowContainerUI)(BOOL)
- { return S_OK; }
- STDMETHOD(QueryInsertObject)(LPCLSID, LPSTORAGE, LONG)
- { return S_OK; }
- STDMETHOD(DeleteObject)(LPOLEOBJECT)
- { return S_OK; }
- STDMETHOD(QueryAcceptData)(LPDATAOBJECT, CLIPFORMAT*, DWORD, BOOL, HGLOBAL)
- { return S_OK; }
- STDMETHOD(GetClipboardData)(CHARRANGE*, DWORD, LPDATAOBJECT*)
- { return E_NOTIMPL; }
- STDMETHOD(GetDragDropEffect)(BOOL, DWORD, LPDWORD)
- { return S_OK; }
- STDMETHOD(GetContextMenu)(uint16_t, LPOLEOBJECT, CHARRANGE*, HMENU*)
- { return E_INVALIDARG; }
-};
-
-struct CREOleCallback2 : public CREOleCallback
-{
- STDMETHOD(QueryAcceptData)(LPDATAOBJECT, CLIPFORMAT *lpcfFormat, DWORD, BOOL, HGLOBAL)
- { *lpcfFormat = CF_UNICODETEXT;
- return S_OK;
- }
-};
-
-CREOleCallback reOleCallback;
-CREOleCallback2 reOleCallback2;
-
-void CCtrlRichEdit::SetReadOnly(bool bReadOnly)
-{
- SendMsg(EM_SETOLECALLBACK, 0, (LPARAM)(bReadOnly ? &reOleCallback : &reOleCallback2));
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+#include <RichOle.h>
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlRichEdit class
+
+CCtrlRichEdit::CCtrlRichEdit(CDlgBase *dlg, int ctrlId)
+ : CCtrlEdit(dlg, ctrlId)
+{}
+
+int CCtrlRichEdit::GetRichTextLength(int iCodePage) const
+{
+ GETTEXTLENGTHEX gtl;
+ gtl.codepage = iCodePage;
+ gtl.flags = GTL_PRECISE;
+ if (iCodePage == CP_ACP)
+ gtl.flags |= GTL_NUMBYTES;
+ else
+ gtl.flags |= GTL_NUMCHARS | GT_USECRLF;
+
+ return (int)SendMessage(m_hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
+}
+
+int CCtrlRichEdit::SetRichText(const wchar_t *text)
+{
+ SETTEXTEX st;
+ st.flags = ST_DEFAULT;
+ st.codepage = 1200;
+ SendMessage(m_hwnd, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)text);
+
+ return GetRichTextLength(1200);
+}
+
+int CCtrlRichEdit::SetRichTextRtf(const char *text)
+{
+ SETTEXTEX st;
+ st.flags = ST_DEFAULT;
+ st.codepage = CP_UTF8;
+ SendMessage(m_hwnd, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)text);
+
+ return GetRichTextLength(1200);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static DWORD CALLBACK MessageStreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
+{
+ static uint32_t dwRead;
+ char **ppText = (char **)dwCookie;
+
+ if (*ppText == nullptr) {
+ *ppText = (char *)mir_alloc(cb + 2);
+ memcpy(*ppText, pbBuff, cb);
+ *pcb = cb;
+ dwRead = cb;
+ *(*ppText + cb) = '\0';
+ }
+ else {
+ char *p = (char *)mir_realloc(*ppText, dwRead + cb + 2);
+ memcpy(p + dwRead, pbBuff, cb);
+ *ppText = p;
+ *pcb = cb;
+ dwRead += cb;
+ *(*ppText + dwRead) = '\0';
+ }
+ return 0;
+}
+
+char* CCtrlRichEdit::GetRichTextRtf(bool bText, bool bSelection) const
+{
+ char *pszText = nullptr;
+ uint32_t dwFlags = SF_USECODEPAGE | (CP_UTF8 << 16);
+ if (bText)
+ dwFlags |= SF_TEXT;
+ else
+ dwFlags |= SF_RTFNOOBJS | SFF_PLAINRTF;
+ if (bSelection)
+ dwFlags |= SFF_SELECTION;
+
+ EDITSTREAM stream = { 0 };
+ stream.pfnCallback = MessageStreamCallback;
+ stream.dwCookie = (DWORD_PTR)&pszText; // pass pointer to pointer
+ SendMessage(m_hwnd, EM_STREAMOUT, dwFlags, (LPARAM)&stream);
+ return pszText; // pszText contains the text
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+struct CREOleCallback : public IRichEditOleCallback
+{
+ CREOleCallback() : refCount(0), nextStgId(0), pictStg(nullptr) {}
+ unsigned refCount;
+ IStorage *pictStg;
+ int nextStgId;
+
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR *ppvObj)
+ {
+ if (IsEqualIID(riid, IID_IRichEditOleCallback)) {
+ *ppvObj = this;
+ AddRef();
+ return S_OK;
+ }
+ *ppvObj = nullptr;
+ return E_NOINTERFACE;
+ }
+
+ STDMETHOD_(ULONG, AddRef)(THIS)
+ {
+ if (refCount == 0)
+ StgCreateDocfile(nullptr, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &pictStg);
+
+ return ++refCount;
+ }
+
+ STDMETHOD_(ULONG, Release)(THIS)
+ {
+ if (--refCount == 0) {
+ if (pictStg) {
+ pictStg->Release();
+ pictStg = nullptr;
+ }
+ }
+ return refCount;
+ }
+
+ STDMETHOD(GetNewStorage)(LPSTORAGE *lplpstg)
+ {
+ wchar_t sztName[64];
+ mir_snwprintf(sztName, L"s%u", nextStgId++);
+ if (pictStg == nullptr)
+ return STG_E_MEDIUMFULL;
+ return pictStg->CreateStorage(sztName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, lplpstg);
+ }
+
+ STDMETHOD(ContextSensitiveHelp)(BOOL)
+ { return S_OK; }
+ STDMETHOD(GetInPlaceContext)(LPOLEINPLACEFRAME*, LPOLEINPLACEUIWINDOW*, LPOLEINPLACEFRAMEINFO)
+ { return E_INVALIDARG; }
+ STDMETHOD(ShowContainerUI)(BOOL)
+ { return S_OK; }
+ STDMETHOD(QueryInsertObject)(LPCLSID, LPSTORAGE, LONG)
+ { return S_OK; }
+ STDMETHOD(DeleteObject)(LPOLEOBJECT)
+ { return S_OK; }
+ STDMETHOD(QueryAcceptData)(LPDATAOBJECT, CLIPFORMAT*, DWORD, BOOL, HGLOBAL)
+ { return S_OK; }
+ STDMETHOD(GetClipboardData)(CHARRANGE*, DWORD, LPDATAOBJECT*)
+ { return E_NOTIMPL; }
+ STDMETHOD(GetDragDropEffect)(BOOL, DWORD, LPDWORD)
+ { return S_OK; }
+ STDMETHOD(GetContextMenu)(uint16_t, LPOLEOBJECT, CHARRANGE*, HMENU*)
+ { return E_INVALIDARG; }
+};
+
+struct CREOleCallback2 : public CREOleCallback
+{
+ STDMETHOD(QueryAcceptData)(LPDATAOBJECT, CLIPFORMAT *lpcfFormat, DWORD, BOOL, HGLOBAL)
+ { *lpcfFormat = CF_UNICODETEXT;
+ return S_OK;
+ }
+};
+
+CREOleCallback reOleCallback;
+CREOleCallback2 reOleCallback2;
+
+void CCtrlRichEdit::SetReadOnly(bool bReadOnly)
+{
+ SendMsg(EM_SETOLECALLBACK, 0, (LPARAM)(bReadOnly ? &reOleCallback : &reOleCallback2));
+}
diff --git a/src/mir_core/src/Windows/CCtrlSlider.cpp b/src/mir_core/src/Windows/CCtrlSlider.cpp
index 69aeb24796..9938736e42 100644
--- a/src/mir_core/src/Windows/CCtrlSlider.cpp
+++ b/src/mir_core/src/Windows/CCtrlSlider.cpp
@@ -1,70 +1,70 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlSlider class
-
-CCtrlSlider::CCtrlSlider(CDlgBase *dlg, int ctrlId, int wMax, int wMin) :
- CCtrlData(dlg, ctrlId),
- m_wMin(wMin),
- m_wMax(wMax)
-{
- m_bNotifiable = true;
-}
-
-BOOL CCtrlSlider::OnCommand(HWND, uint16_t, uint16_t idCode)
-{
- if (idCode == WM_HSCROLL) {
- NotifyChange();
- return TRUE;
- }
- return FALSE;
-}
-
-bool CCtrlSlider::OnApply()
-{
- CSuper::OnApply();
-
- if (m_dbLink != nullptr)
- SaveInt(GetPosition());
- return true;
-}
-
-void CCtrlSlider::OnReset()
-{
- SendMsg(TBM_SETRANGE, 0, MAKELONG(m_wMin, m_wMax));
-
- if (m_dbLink != nullptr)
- SetPosition(LoadInt());
-}
-
-int CCtrlSlider::GetPosition() const
-{
- return SendMsg(TBM_GETPOS, 0, 0);
-}
-
-void CCtrlSlider::SetPosition(int wPos)
-{
- SendMsg(TBM_SETPOS, TRUE, wPos);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlSlider class
+
+CCtrlSlider::CCtrlSlider(CDlgBase *dlg, int ctrlId, int wMax, int wMin) :
+ CCtrlData(dlg, ctrlId),
+ m_wMin(wMin),
+ m_wMax(wMax)
+{
+ m_bNotifiable = true;
+}
+
+BOOL CCtrlSlider::OnCommand(HWND, uint16_t, uint16_t idCode)
+{
+ if (idCode == WM_HSCROLL) {
+ NotifyChange();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool CCtrlSlider::OnApply()
+{
+ CSuper::OnApply();
+
+ if (m_dbLink != nullptr)
+ SaveInt(GetPosition());
+ return true;
+}
+
+void CCtrlSlider::OnReset()
+{
+ SendMsg(TBM_SETRANGE, 0, MAKELONG(m_wMin, m_wMax));
+
+ if (m_dbLink != nullptr)
+ SetPosition(LoadInt());
+}
+
+int CCtrlSlider::GetPosition() const
+{
+ return SendMsg(TBM_GETPOS, 0, 0);
+}
+
+void CCtrlSlider::SetPosition(int wPos)
+{
+ SendMsg(TBM_SETPOS, TRUE, wPos);
+}
diff --git a/src/mir_core/src/Windows/CCtrlSpin.cpp b/src/mir_core/src/Windows/CCtrlSpin.cpp
index 54d43e933a..54dc5ffd07 100644
--- a/src/mir_core/src/Windows/CCtrlSpin.cpp
+++ b/src/mir_core/src/Windows/CCtrlSpin.cpp
@@ -1,81 +1,81 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlSpin class
-
-CCtrlSpin::CCtrlSpin(CDlgBase *dlg, int ctrlId, int16_t wMax, int16_t wMin) :
- CCtrlData(dlg, ctrlId),
- m_wMin(wMin),
- m_wMax(wMax),
- m_wCurr(0)
-{}
-
-BOOL CCtrlSpin::OnNotify(int, NMHDR *pnmh)
-{
- if (pnmh->code == UDN_DELTAPOS) {
- auto *pEvent = (NMUPDOWN *)pnmh;
- m_wCurr = pEvent->iPos + pEvent->iDelta;
-
- NotifyChange();
- return TRUE;
- }
- return FALSE;
-}
-
-bool CCtrlSpin::OnApply()
-{
- CSuper::OnApply();
-
- m_wCurr = SendMsg(UDM_GETPOS, 0, 0);
- if (m_dbLink != nullptr)
- SaveInt(m_wCurr);
-
- HWND hwndBuddy = (HWND)SendMsg(UDM_GETBUDDY, 0, 0);
- if (hwndBuddy) {
- wchar_t buf[100];
- _itow(m_wCurr, buf, 10);
- ::SendMessage(hwndBuddy, WM_SETTEXT, 0, LPARAM(buf));
- }
-
- return true;
-}
-
-void CCtrlSpin::OnReset()
-{
- SendMsg(UDM_SETRANGE, 0, MAKELPARAM(m_wMax, m_wMin));
-
- if (m_dbLink != nullptr)
- SetPosition(LoadInt());
-}
-
-int16_t CCtrlSpin::GetPosition()
-{
- return m_wCurr;
-}
-
-void CCtrlSpin::SetPosition(int16_t wPos)
-{
- SendMsg(UDM_SETPOS, 0, m_wCurr = wPos);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlSpin class
+
+CCtrlSpin::CCtrlSpin(CDlgBase *dlg, int ctrlId, int16_t wMax, int16_t wMin) :
+ CCtrlData(dlg, ctrlId),
+ m_wMin(wMin),
+ m_wMax(wMax),
+ m_wCurr(0)
+{}
+
+BOOL CCtrlSpin::OnNotify(int, NMHDR *pnmh)
+{
+ if (pnmh->code == UDN_DELTAPOS) {
+ auto *pEvent = (NMUPDOWN *)pnmh;
+ m_wCurr = pEvent->iPos + pEvent->iDelta;
+
+ NotifyChange();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool CCtrlSpin::OnApply()
+{
+ CSuper::OnApply();
+
+ m_wCurr = SendMsg(UDM_GETPOS, 0, 0);
+ if (m_dbLink != nullptr)
+ SaveInt(m_wCurr);
+
+ HWND hwndBuddy = (HWND)SendMsg(UDM_GETBUDDY, 0, 0);
+ if (hwndBuddy) {
+ wchar_t buf[100];
+ _itow(m_wCurr, buf, 10);
+ ::SendMessage(hwndBuddy, WM_SETTEXT, 0, LPARAM(buf));
+ }
+
+ return true;
+}
+
+void CCtrlSpin::OnReset()
+{
+ SendMsg(UDM_SETRANGE, 0, MAKELPARAM(m_wMax, m_wMin));
+
+ if (m_dbLink != nullptr)
+ SetPosition(LoadInt());
+}
+
+int16_t CCtrlSpin::GetPosition()
+{
+ return m_wCurr;
+}
+
+void CCtrlSpin::SetPosition(int16_t wPos)
+{
+ SendMsg(UDM_SETPOS, 0, m_wCurr = wPos);
+}
diff --git a/src/mir_core/src/Windows/CCtrlTreeOpts.cpp b/src/mir_core/src/Windows/CCtrlTreeOpts.cpp
index d15f3d4b1b..7935283285 100644
--- a/src/mir_core/src/Windows/CCtrlTreeOpts.cpp
+++ b/src/mir_core/src/Windows/CCtrlTreeOpts.cpp
@@ -2,7 +2,7 @@
Object UI extensions
Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
+Copyright (C) 2012-23 Miranda NG team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
diff --git a/src/mir_core/src/Windows/CCtrlTreeView.cpp b/src/mir_core/src/Windows/CCtrlTreeView.cpp
index 6f435920f2..178b6b730e 100644
--- a/src/mir_core/src/Windows/CCtrlTreeView.cpp
+++ b/src/mir_core/src/Windows/CCtrlTreeView.cpp
@@ -2,7 +2,7 @@
Object UI extensions
Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
+Copyright (C) 2012-23 Miranda NG team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
diff --git a/src/mir_core/src/Windows/CDbLink.cpp b/src/mir_core/src/Windows/CDbLink.cpp
index 2a0734cd3b..05925f871b 100644
--- a/src/mir_core/src/Windows/CDbLink.cpp
+++ b/src/mir_core/src/Windows/CDbLink.cpp
@@ -1,92 +1,92 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CDbLink class
-
-CDbLink::CDbLink(const char *szModule, const char *szSetting, uint8_t type, uint32_t iValue)
- : CDataLink(type)
-{
- m_szModule = mir_strdup(szModule);
- m_szSetting = mir_strdup(szSetting);
- m_iDefault = iValue;
- m_szDefault = nullptr;
- dbv.type = DBVT_DELETED;
-}
-
-CDbLink::CDbLink(const char *szModule, const char *szSetting, uint8_t type, wchar_t *szValue)
- : CDataLink(type),
- m_iDefault(0)
-{
- m_szModule = mir_strdup(szModule);
- m_szSetting = mir_strdup(szSetting);
- m_szDefault = mir_wstrdup(szValue);
- dbv.type = DBVT_DELETED;
-}
-
-CDbLink::~CDbLink()
-{
- mir_free(m_szModule);
- mir_free(m_szSetting);
- mir_free(m_szDefault);
- if (dbv.type != DBVT_DELETED)
- db_free(&dbv);
-}
-
-uint32_t CDbLink::LoadInt()
-{
- switch (m_type) {
- case DBVT_BYTE: return db_get_b(0, m_szModule, m_szSetting, m_iDefault);
- case DBVT_WORD: return db_get_w(0, m_szModule, m_szSetting, m_iDefault);
- case DBVT_DWORD: return db_get_dw(0, m_szModule, m_szSetting, m_iDefault);
- default: return m_iDefault;
- }
-}
-
-void CDbLink::SaveInt(uint32_t value)
-{
- switch (m_type) {
- case DBVT_BYTE: db_set_b(0, m_szModule, m_szSetting, (uint8_t)value); break;
- case DBVT_WORD: db_set_w(0, m_szModule, m_szSetting, (uint16_t)value); break;
- case DBVT_DWORD: db_set_dw(0, m_szModule, m_szSetting, value); break;
- }
-}
-
-wchar_t* CDbLink::LoadText()
-{
- if (dbv.type != DBVT_DELETED) db_free(&dbv);
- if (!db_get_ws(0, m_szModule, m_szSetting, &dbv)) {
- if (dbv.type == DBVT_WCHAR)
- return dbv.pwszVal;
- return m_szDefault;
- }
-
- dbv.type = DBVT_DELETED;
- return m_szDefault;
-}
-
-void CDbLink::SaveText(wchar_t *value)
-{
- db_set_ws(0, m_szModule, m_szSetting, value);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CDbLink class
+
+CDbLink::CDbLink(const char *szModule, const char *szSetting, uint8_t type, uint32_t iValue)
+ : CDataLink(type)
+{
+ m_szModule = mir_strdup(szModule);
+ m_szSetting = mir_strdup(szSetting);
+ m_iDefault = iValue;
+ m_szDefault = nullptr;
+ dbv.type = DBVT_DELETED;
+}
+
+CDbLink::CDbLink(const char *szModule, const char *szSetting, uint8_t type, wchar_t *szValue)
+ : CDataLink(type),
+ m_iDefault(0)
+{
+ m_szModule = mir_strdup(szModule);
+ m_szSetting = mir_strdup(szSetting);
+ m_szDefault = mir_wstrdup(szValue);
+ dbv.type = DBVT_DELETED;
+}
+
+CDbLink::~CDbLink()
+{
+ mir_free(m_szModule);
+ mir_free(m_szSetting);
+ mir_free(m_szDefault);
+ if (dbv.type != DBVT_DELETED)
+ db_free(&dbv);
+}
+
+uint32_t CDbLink::LoadInt()
+{
+ switch (m_type) {
+ case DBVT_BYTE: return db_get_b(0, m_szModule, m_szSetting, m_iDefault);
+ case DBVT_WORD: return db_get_w(0, m_szModule, m_szSetting, m_iDefault);
+ case DBVT_DWORD: return db_get_dw(0, m_szModule, m_szSetting, m_iDefault);
+ default: return m_iDefault;
+ }
+}
+
+void CDbLink::SaveInt(uint32_t value)
+{
+ switch (m_type) {
+ case DBVT_BYTE: db_set_b(0, m_szModule, m_szSetting, (uint8_t)value); break;
+ case DBVT_WORD: db_set_w(0, m_szModule, m_szSetting, (uint16_t)value); break;
+ case DBVT_DWORD: db_set_dw(0, m_szModule, m_szSetting, value); break;
+ }
+}
+
+wchar_t* CDbLink::LoadText()
+{
+ if (dbv.type != DBVT_DELETED) db_free(&dbv);
+ if (!db_get_ws(0, m_szModule, m_szSetting, &dbv)) {
+ if (dbv.type == DBVT_WCHAR)
+ return dbv.pwszVal;
+ return m_szDefault;
+ }
+
+ dbv.type = DBVT_DELETED;
+ return m_szDefault;
+}
+
+void CDbLink::SaveText(wchar_t *value)
+{
+ db_set_ws(0, m_szModule, m_szSetting, value);
+}
diff --git a/src/mir_core/src/Windows/CDlgBase.cpp b/src/mir_core/src/Windows/CDlgBase.cpp
index 84066de414..45ae944e21 100644
--- a/src/mir_core/src/Windows/CDlgBase.cpp
+++ b/src/mir_core/src/Windows/CDlgBase.cpp
@@ -1,522 +1,522 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-#include "diatheme.h"
-
-static mir_cs csDialogs;
-
-static int CompareDialogs(const CDlgBase *p1, const CDlgBase *p2)
-{
- return (INT_PTR)p1->GetHwnd() - (INT_PTR)p2->GetHwnd();
-}
-static LIST<CDlgBase> arDialogs(10, CompareDialogs);
-
-#pragma comment(lib, "uxtheme")
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CDlgBase
-
-static int CompareControlId(const CCtrlBase *c1, const CCtrlBase *c2)
-{
- return c1->GetCtrlId() - c2->GetCtrlId();
-}
-
-static int CompareTimerId(const CTimer *t1, const CTimer *t2)
-{
- return t1->GetEventId() - t2->GetEventId();
-}
-
-CDlgBase::CDlgBase(CMPluginBase &pPlug, int idDialog) :
- m_controls(1, CompareControlId),
- m_timers(1, CompareTimerId),
- m_pPlugin(pPlug),
- m_bFixedSize(!g_bEnableDpiAware)
-{
- m_idDialog = idDialog;
- m_autoClose = CLOSE_ON_OK | CLOSE_ON_CANCEL;
-}
-
-CDlgBase::~CDlgBase()
-{
- m_bInitialized = false; // prevent double call of destructor
- if (m_hwnd)
- DestroyWindow(m_hwnd);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// events
-
-bool CDlgBase::OnInitDialog()
-{
- return true;
-}
-
-bool CDlgBase::OnClose()
-{
- return true;
-}
-
-bool CDlgBase::OnApply()
-{
- return true;
-}
-
-void CDlgBase::OnChange()
-{}
-
-void CDlgBase::OnDestroy()
-{}
-
-void CDlgBase::OnReset()
-{}
-
-void CDlgBase::OnTimer(CTimer*)
-{}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// methods
-
-void CDlgBase::Close()
-{
- ::SendMessage(m_hwnd, WM_CLOSE, 0, 0);
-}
-
-void CDlgBase::Create()
-{
- if (!m_bFixedSize) {
- mir_ptr<DLGTEMPLATE> pDlgTemplate(LoadThemedDialogTemplate(MAKEINTRESOURCE(m_idDialog), GetInst()));
- CreateDialogIndirectParam(GetInst(), pDlgTemplate, m_hwndParent, GlobalDlgProc, (LPARAM)this);
- }
- else CreateDialogParam(GetInst(), MAKEINTRESOURCE(m_idDialog), m_hwndParent, GlobalDlgProc, (LPARAM)this);
-}
-
-int CDlgBase::DoModal()
-{
- m_isModal = true;
-
- if (m_bFixedSize)
- return DialogBoxParam(GetInst(), MAKEINTRESOURCE(m_idDialog), m_hwndParent, GlobalDlgProc, (LPARAM)this);
-
- mir_ptr<DLGTEMPLATE> pDlgTemplate(LoadThemedDialogTemplate(MAKEINTRESOURCE(m_idDialog), GetInst()));
- return DialogBoxIndirectParam(GetInst(), pDlgTemplate, m_hwndParent, GlobalDlgProc, (LPARAM)this);
-}
-
-void CDlgBase::EndModal(INT_PTR nResult)
-{
- ::EndDialog(m_hwnd, nResult);
-}
-
-HINSTANCE CDlgBase::GetInst() const
-{
- return m_pPlugin.getInst();
-}
-
-void CDlgBase::NotifyChange(void)
-{
- if (!m_bInitialized)
- return;
-
- OnChange();
-
- if (m_hwndParent)
- SendMessage(m_hwndParent, PSM_CHANGED, (WPARAM)m_hwnd, 0);
-}
-
-void CDlgBase::Resize()
-{
- SendMessage(m_hwnd, WM_SIZE, 0, 0);
-}
-
-void CDlgBase::SetCaption(const wchar_t *ptszCaption)
-{
- if (m_hwnd && ptszCaption)
- SetWindowText(m_hwnd, ptszCaption);
-}
-
-void CDlgBase::SetDraw(bool bEnable)
-{
- ::SendMessage(m_hwnd, WM_SETREDRAW, bEnable, 0);
-}
-
-void CDlgBase::Show(int nCmdShow)
-{
- if (m_hwnd == nullptr)
- Create();
- ShowWindow(m_hwnd, nCmdShow);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CDlgBase::CreateLink(CCtrlData& ctrl, const char *szSetting, uint8_t type, uint32_t iValue)
-{
- ctrl.CreateDbLink(m_pPlugin.getModule(), szSetting, type, iValue);
-}
-
-void CDlgBase::CreateLink(CCtrlData& ctrl, const char *szSetting, wchar_t *szValue)
-{
- ctrl.CreateDbLink(m_pPlugin.getModule(), szSetting, szValue);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// virtual methods
-
-int CDlgBase::GlobalDlgResizer(HWND hwnd, LPARAM, UTILRESIZECONTROL *urc)
-{
- CDlgBase *wnd = CDlgBase::Find(hwnd);
- return (wnd == nullptr) ? 0 : wnd->Resizer(urc);
-}
-
-void CDlgBase::OnResize()
-{
- if (m_forceResizable || (GetWindowLongPtr(m_hwnd, GWL_STYLE) & WS_THICKFRAME))
- Utils_ResizeDialog(m_hwnd, m_pPlugin.getInst(), MAKEINTRESOURCEA(m_idDialog), GlobalDlgResizer);
-}
-
-int CDlgBase::Resizer(UTILRESIZECONTROL*)
-{
- return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
-}
-
-BOOL CALLBACK CDlgBase::GlobalFieldEnum(HWND hwnd, LPARAM lParam)
-{
- CDlgBase *pDlg = (CDlgBase*)lParam;
- int id = GetWindowLongPtrW(hwnd, GWLP_ID);
- if (id <= 0)
- return TRUE;
-
- // already declared inside the class? skipping
- CCtrlBase *ctrl = pDlg->FindControl(id);
- if (ctrl != nullptr)
- return TRUE;
-
- wchar_t wszClass[100];
- GetClassNameW(hwnd, wszClass, _countof(wszClass));
- if (!wcsicmp(wszClass, L"Static"))
- new CCtrlLabel(pDlg, id);
- if (!wcsicmp(wszClass, L"Edit"))
- new CCtrlEdit(pDlg, id);
- else if (!wcsicmp(wszClass, L"ComboBox"))
- new CCtrlCombo(pDlg, id);
- else if (!wcsicmp(wszClass, L"Button")) {
- switch (GetWindowLongW(hwnd, GWL_STYLE) & (BS_CHECKBOX | BS_RADIOBUTTON | BS_AUTOCHECKBOX | BS_AUTORADIOBUTTON)) {
- case BS_CHECKBOX:
- case BS_AUTOCHECKBOX:
- case BS_RADIOBUTTON:
- case BS_AUTORADIOBUTTON:
- new CCtrlCheck(pDlg, id);
- break;
-
- default:
- new CCtrlButton(pDlg, id);
- }
- }
- else if (!wcsicmp(wszClass, L"RichEdit50W"))
- new CCtrlRichEdit(pDlg, id);
- else if (!wcsicmp(wszClass, L"msctls_updown32"))
- new CCtrlSpin(pDlg, id);
-
- return TRUE;
-}
-
-INT_PTR CDlgBase::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_INITDIALOG:
- m_bInitialized = m_bSucceeded = false;
- TranslateDialog_LP(m_hwnd, &m_pPlugin);
-
- ::EnumChildWindows(m_hwnd, &GlobalFieldEnum, LPARAM(this));
-
- NotifyControls(&CCtrlBase::OnInit);
- if (!OnInitDialog())
- return FALSE;
-
- for (auto &it : m_controls)
- if (it->m_bNotifiable)
- it->OnChange(it);
-
- m_bInitialized = true;
- return TRUE;
-
- case WM_CTLCOLOREDIT:
- case WM_CTLCOLORSTATIC:
- if (CCtrlBase *ctrl = FindControl(HWND(lParam))) {
- if (ctrl->m_bUseSystemColors) {
- SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
- return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
- }
- }
- break;
-
- case WM_GETMINMAXINFO:
- if (m_iMinHeight != -1 && m_iMinWidth != -1) {
- MINMAXINFO *lpmmi = (MINMAXINFO*)lParam;
- lpmmi->ptMinTrackSize.y = m_iMinHeight;
- lpmmi->ptMinTrackSize.x = m_iMinWidth;
- return 0;
- }
- break;
-
- case WM_MEASUREITEM:
- if (!Menu_MeasureItem(lParam)) {
- MEASUREITEMSTRUCT *param = (MEASUREITEMSTRUCT *)lParam;
- if (param && param->CtlID)
- if (CCtrlBase *ctrl = FindControl(param->CtlID))
- return ctrl->OnMeasureItem(param);
- }
- return FALSE;
-
- case WM_DRAWITEM:
- if (!Menu_DrawItem(lParam)) {
- DRAWITEMSTRUCT *param = (DRAWITEMSTRUCT *)lParam;
- if (param && param->CtlID)
- if (CCtrlBase *ctrl = FindControl(param->CtlID))
- return ctrl->OnDrawItem(param);
- }
- return FALSE;
-
- case WM_DELETEITEM:
- {
- DELETEITEMSTRUCT *param = (DELETEITEMSTRUCT *)lParam;
- if (param && param->CtlID)
- if (CCtrlBase *ctrl = FindControl(param->CtlID))
- return ctrl->OnDeleteItem(param);
- }
- return FALSE;
-
- case WM_COMMAND:
- {
- HWND hwndCtrl = (HWND)lParam;
- uint16_t idCtrl = LOWORD(wParam);
- uint16_t idCode = HIWORD(wParam);
- if (CCtrlBase *ctrl = FindControl(idCtrl)) {
- BOOL result = ctrl->OnCommand(hwndCtrl, idCtrl, idCode);
- if (result != FALSE)
- return result;
- }
-
- if (idCode == BN_CLICKED) {
- // close dialog automatically if 'Cancel' button is pressed
- if (idCtrl == IDCANCEL && (m_autoClose & CLOSE_ON_CANCEL)) {
- m_bExiting = true;
- PostMessage(m_hwnd, WM_CLOSE, 0, 0);
- }
-
- // close dialog automatically if 'OK' button is pressed
- if (idCtrl == IDOK && (m_autoClose & CLOSE_ON_OK)) {
- // validate dialog data first
- if (VerifyControls(&CCtrlBase::OnApply)) {
- m_bExiting = true;
-
- // everything ok? good, let's close it
- if (OnApply()) {
- m_bSucceeded = true;
- PostMessage(m_hwnd, WM_CLOSE, 0, 0);
- }
- else m_bExiting = false;
- }
- }
- }
- }
- return FALSE;
-
- case WM_NOTIFY:
- {
- int idCtrl = wParam;
- NMHDR *pnmh = (NMHDR *)lParam;
- if (pnmh->idFrom == 0) {
- switch (pnmh->code) {
- case PSN_APPLY:
- if (LPPSHNOTIFY(lParam)->lParam != 3) // IDC_APPLY
- m_bExiting = true;
-
- if (!VerifyControls(&CCtrlBase::OnApply))
- m_bExiting = false;
- else if (!OnApply())
- m_bExiting = false;
- break;
-
- case PSN_RESET:
- NotifyControls(&CCtrlBase::OnReset);
- OnReset();
- break;
-
- case PSN_WIZFINISH:
- m_OnFinishWizard(this);
- break;
- }
- }
-
- if (CCtrlBase *ctrl = FindControl(pnmh->idFrom))
- return ctrl->OnNotify(idCtrl, pnmh);
- }
- return FALSE;
-
- case WM_HSCROLL:
- if (auto *pCtrl = FindControl(HWND(lParam)))
- pCtrl->OnCommand(HWND(lParam), pCtrl->m_idCtrl, WM_HSCROLL);
- break;
-
- case PSM_CHANGED:
- if (m_bInitialized)
- OnChange();
- break;
-
- case WM_CONTEXTMENU:
- if (CCtrlBase *ctrl = FindControl(HWND(wParam))) {
- CContextMenuPos pos = {};
- if (lParam != -1) {
- pos.pt.x = GET_X_LPARAM(lParam);
- pos.pt.y = GET_Y_LPARAM(lParam);
- }
- ctrl->GetCaretPos(pos);
- ctrl->OnBuildMenu(&pos);
- }
- break;
-
- case WM_SIZE:
- OnResize();
- return TRUE;
-
- case WM_TIMER:
- if (CTimer *timer = FindTimer(wParam))
- return timer->OnTimer();
- return FALSE;
-
- case WM_CLOSE:
- if (OnClose()) {
- m_bExiting = true;
- if (m_isModal)
- EndModal(m_bSucceeded ? IDOK : FALSE);
- else
- DestroyWindow(m_hwnd);
- }
- return TRUE;
-
- case WM_DESTROY:
- m_bExiting = true;
- OnDestroy();
- NotifyControls(&CCtrlBase::OnDestroy);
- {
- mir_cslock lck(csDialogs);
- int idx = arDialogs.getIndex(this);
- if (idx != -1)
- arDialogs.remove(idx);
- }
- m_hwnd = nullptr;
- if (m_bInitialized) {
- if (m_isModal)
- m_isModal = false;
- else // modeless dialogs MUST be allocated with 'new'
- delete this;
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-INT_PTR CALLBACK CDlgBase::GlobalDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CDlgBase *wnd;
- if (msg == WM_INITDIALOG) {
- wnd = (CDlgBase*)lParam;
- wnd->m_hwnd = hwnd;
-
- mir_cslock lck(csDialogs);
- arDialogs.insert(wnd);
- }
- else wnd = CDlgBase::Find(hwnd);
-
- return (wnd == nullptr) ? FALSE : wnd->DlgProc(msg, wParam, lParam);
-}
-
-void CDlgBase::ThemeDialogBackground(BOOL tabbed)
-{
- EnableThemeDialogTexture(m_hwnd, (tabbed ? ETDT_ENABLE : ETDT_DISABLE) | ETDT_USETABTEXTURE);
-}
-
-void CDlgBase::AddControl(CCtrlBase *ctrl)
-{
- m_controls.insert(ctrl);
-}
-
-void CDlgBase::RemoveControl(CCtrlBase *ctrl)
-{
- m_controls.remove(ctrl);
-}
-
-void CDlgBase::NotifyControls(void (CCtrlBase::*fn)())
-{
- for (auto &it : m_controls)
- (it->*fn)();
-}
-
-bool CDlgBase::VerifyControls(bool (CCtrlBase::*fn)())
-{
- for (auto &it : m_controls)
- if (!(it->*fn)())
- return false;
-
- return true;
-}
-
-CCtrlBase* CDlgBase::FindControl(int idCtrl)
-{
- CCtrlBase search(nullptr, idCtrl);
- return m_controls.find(&search);
-}
-
-CCtrlBase* CDlgBase::FindControl(HWND hwnd)
-{
- for (auto &it : m_controls)
- if (it->GetHwnd() == hwnd)
- return it;
-
- return nullptr;
-}
-
-void CDlgBase::AddTimer(CTimer *timer)
-{
- m_timers.insert(timer);
-}
-
-void CDlgBase::RemoveTimer(UINT_PTR idEvent)
-{
- CTimer search(nullptr, idEvent);
- m_timers.remove(&search);
-}
-
-CTimer* CDlgBase::FindTimer(int idEvent)
-{
- CTimer search(nullptr, idEvent);
- return m_timers.find(&search);
-}
-
-CDlgBase* CDlgBase::Find(HWND hwnd)
-{
- PVOID bullshit[2]; // vfptr + hwnd
- bullshit[1] = hwnd;
- return arDialogs.find((CDlgBase*)&bullshit);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+#include "diatheme.h"
+
+static mir_cs csDialogs;
+
+static int CompareDialogs(const CDlgBase *p1, const CDlgBase *p2)
+{
+ return (INT_PTR)p1->GetHwnd() - (INT_PTR)p2->GetHwnd();
+}
+static LIST<CDlgBase> arDialogs(10, CompareDialogs);
+
+#pragma comment(lib, "uxtheme")
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CDlgBase
+
+static int CompareControlId(const CCtrlBase *c1, const CCtrlBase *c2)
+{
+ return c1->GetCtrlId() - c2->GetCtrlId();
+}
+
+static int CompareTimerId(const CTimer *t1, const CTimer *t2)
+{
+ return t1->GetEventId() - t2->GetEventId();
+}
+
+CDlgBase::CDlgBase(CMPluginBase &pPlug, int idDialog) :
+ m_controls(1, CompareControlId),
+ m_timers(1, CompareTimerId),
+ m_pPlugin(pPlug),
+ m_bFixedSize(!g_bEnableDpiAware)
+{
+ m_idDialog = idDialog;
+ m_autoClose = CLOSE_ON_OK | CLOSE_ON_CANCEL;
+}
+
+CDlgBase::~CDlgBase()
+{
+ m_bInitialized = false; // prevent double call of destructor
+ if (m_hwnd)
+ DestroyWindow(m_hwnd);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// events
+
+bool CDlgBase::OnInitDialog()
+{
+ return true;
+}
+
+bool CDlgBase::OnClose()
+{
+ return true;
+}
+
+bool CDlgBase::OnApply()
+{
+ return true;
+}
+
+void CDlgBase::OnChange()
+{}
+
+void CDlgBase::OnDestroy()
+{}
+
+void CDlgBase::OnReset()
+{}
+
+void CDlgBase::OnTimer(CTimer*)
+{}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// methods
+
+void CDlgBase::Close()
+{
+ ::SendMessage(m_hwnd, WM_CLOSE, 0, 0);
+}
+
+void CDlgBase::Create()
+{
+ if (!m_bFixedSize) {
+ mir_ptr<DLGTEMPLATE> pDlgTemplate(LoadThemedDialogTemplate(MAKEINTRESOURCE(m_idDialog), GetInst()));
+ CreateDialogIndirectParam(GetInst(), pDlgTemplate, m_hwndParent, GlobalDlgProc, (LPARAM)this);
+ }
+ else CreateDialogParam(GetInst(), MAKEINTRESOURCE(m_idDialog), m_hwndParent, GlobalDlgProc, (LPARAM)this);
+}
+
+int CDlgBase::DoModal()
+{
+ m_isModal = true;
+
+ if (m_bFixedSize)
+ return DialogBoxParam(GetInst(), MAKEINTRESOURCE(m_idDialog), m_hwndParent, GlobalDlgProc, (LPARAM)this);
+
+ mir_ptr<DLGTEMPLATE> pDlgTemplate(LoadThemedDialogTemplate(MAKEINTRESOURCE(m_idDialog), GetInst()));
+ return DialogBoxIndirectParam(GetInst(), pDlgTemplate, m_hwndParent, GlobalDlgProc, (LPARAM)this);
+}
+
+void CDlgBase::EndModal(INT_PTR nResult)
+{
+ ::EndDialog(m_hwnd, nResult);
+}
+
+HINSTANCE CDlgBase::GetInst() const
+{
+ return m_pPlugin.getInst();
+}
+
+void CDlgBase::NotifyChange(void)
+{
+ if (!m_bInitialized)
+ return;
+
+ OnChange();
+
+ if (m_hwndParent)
+ SendMessage(m_hwndParent, PSM_CHANGED, (WPARAM)m_hwnd, 0);
+}
+
+void CDlgBase::Resize()
+{
+ SendMessage(m_hwnd, WM_SIZE, 0, 0);
+}
+
+void CDlgBase::SetCaption(const wchar_t *ptszCaption)
+{
+ if (m_hwnd && ptszCaption)
+ SetWindowText(m_hwnd, ptszCaption);
+}
+
+void CDlgBase::SetDraw(bool bEnable)
+{
+ ::SendMessage(m_hwnd, WM_SETREDRAW, bEnable, 0);
+}
+
+void CDlgBase::Show(int nCmdShow)
+{
+ if (m_hwnd == nullptr)
+ Create();
+ ShowWindow(m_hwnd, nCmdShow);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CDlgBase::CreateLink(CCtrlData& ctrl, const char *szSetting, uint8_t type, uint32_t iValue)
+{
+ ctrl.CreateDbLink(m_pPlugin.getModule(), szSetting, type, iValue);
+}
+
+void CDlgBase::CreateLink(CCtrlData& ctrl, const char *szSetting, wchar_t *szValue)
+{
+ ctrl.CreateDbLink(m_pPlugin.getModule(), szSetting, szValue);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// virtual methods
+
+int CDlgBase::GlobalDlgResizer(HWND hwnd, LPARAM, UTILRESIZECONTROL *urc)
+{
+ CDlgBase *wnd = CDlgBase::Find(hwnd);
+ return (wnd == nullptr) ? 0 : wnd->Resizer(urc);
+}
+
+void CDlgBase::OnResize()
+{
+ if (m_forceResizable || (GetWindowLongPtr(m_hwnd, GWL_STYLE) & WS_THICKFRAME))
+ Utils_ResizeDialog(m_hwnd, m_pPlugin.getInst(), MAKEINTRESOURCEA(m_idDialog), GlobalDlgResizer);
+}
+
+int CDlgBase::Resizer(UTILRESIZECONTROL*)
+{
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+}
+
+BOOL CALLBACK CDlgBase::GlobalFieldEnum(HWND hwnd, LPARAM lParam)
+{
+ CDlgBase *pDlg = (CDlgBase*)lParam;
+ int id = GetWindowLongPtrW(hwnd, GWLP_ID);
+ if (id <= 0)
+ return TRUE;
+
+ // already declared inside the class? skipping
+ CCtrlBase *ctrl = pDlg->FindControl(id);
+ if (ctrl != nullptr)
+ return TRUE;
+
+ wchar_t wszClass[100];
+ GetClassNameW(hwnd, wszClass, _countof(wszClass));
+ if (!wcsicmp(wszClass, L"Static"))
+ new CCtrlLabel(pDlg, id);
+ if (!wcsicmp(wszClass, L"Edit"))
+ new CCtrlEdit(pDlg, id);
+ else if (!wcsicmp(wszClass, L"ComboBox"))
+ new CCtrlCombo(pDlg, id);
+ else if (!wcsicmp(wszClass, L"Button")) {
+ switch (GetWindowLongW(hwnd, GWL_STYLE) & (BS_CHECKBOX | BS_RADIOBUTTON | BS_AUTOCHECKBOX | BS_AUTORADIOBUTTON)) {
+ case BS_CHECKBOX:
+ case BS_AUTOCHECKBOX:
+ case BS_RADIOBUTTON:
+ case BS_AUTORADIOBUTTON:
+ new CCtrlCheck(pDlg, id);
+ break;
+
+ default:
+ new CCtrlButton(pDlg, id);
+ }
+ }
+ else if (!wcsicmp(wszClass, L"RichEdit50W"))
+ new CCtrlRichEdit(pDlg, id);
+ else if (!wcsicmp(wszClass, L"msctls_updown32"))
+ new CCtrlSpin(pDlg, id);
+
+ return TRUE;
+}
+
+INT_PTR CDlgBase::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ m_bInitialized = m_bSucceeded = false;
+ TranslateDialog_LP(m_hwnd, &m_pPlugin);
+
+ ::EnumChildWindows(m_hwnd, &GlobalFieldEnum, LPARAM(this));
+
+ NotifyControls(&CCtrlBase::OnInit);
+ if (!OnInitDialog())
+ return FALSE;
+
+ for (auto &it : m_controls)
+ if (it->m_bNotifiable)
+ it->OnChange(it);
+
+ m_bInitialized = true;
+ return TRUE;
+
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ if (CCtrlBase *ctrl = FindControl(HWND(lParam))) {
+ if (ctrl->m_bUseSystemColors) {
+ SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
+ return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
+ }
+ }
+ break;
+
+ case WM_GETMINMAXINFO:
+ if (m_iMinHeight != -1 && m_iMinWidth != -1) {
+ MINMAXINFO *lpmmi = (MINMAXINFO*)lParam;
+ lpmmi->ptMinTrackSize.y = m_iMinHeight;
+ lpmmi->ptMinTrackSize.x = m_iMinWidth;
+ return 0;
+ }
+ break;
+
+ case WM_MEASUREITEM:
+ if (!Menu_MeasureItem(lParam)) {
+ MEASUREITEMSTRUCT *param = (MEASUREITEMSTRUCT *)lParam;
+ if (param && param->CtlID)
+ if (CCtrlBase *ctrl = FindControl(param->CtlID))
+ return ctrl->OnMeasureItem(param);
+ }
+ return FALSE;
+
+ case WM_DRAWITEM:
+ if (!Menu_DrawItem(lParam)) {
+ DRAWITEMSTRUCT *param = (DRAWITEMSTRUCT *)lParam;
+ if (param && param->CtlID)
+ if (CCtrlBase *ctrl = FindControl(param->CtlID))
+ return ctrl->OnDrawItem(param);
+ }
+ return FALSE;
+
+ case WM_DELETEITEM:
+ {
+ DELETEITEMSTRUCT *param = (DELETEITEMSTRUCT *)lParam;
+ if (param && param->CtlID)
+ if (CCtrlBase *ctrl = FindControl(param->CtlID))
+ return ctrl->OnDeleteItem(param);
+ }
+ return FALSE;
+
+ case WM_COMMAND:
+ {
+ HWND hwndCtrl = (HWND)lParam;
+ uint16_t idCtrl = LOWORD(wParam);
+ uint16_t idCode = HIWORD(wParam);
+ if (CCtrlBase *ctrl = FindControl(idCtrl)) {
+ BOOL result = ctrl->OnCommand(hwndCtrl, idCtrl, idCode);
+ if (result != FALSE)
+ return result;
+ }
+
+ if (idCode == BN_CLICKED) {
+ // close dialog automatically if 'Cancel' button is pressed
+ if (idCtrl == IDCANCEL && (m_autoClose & CLOSE_ON_CANCEL)) {
+ m_bExiting = true;
+ PostMessage(m_hwnd, WM_CLOSE, 0, 0);
+ }
+
+ // close dialog automatically if 'OK' button is pressed
+ if (idCtrl == IDOK && (m_autoClose & CLOSE_ON_OK)) {
+ // validate dialog data first
+ if (VerifyControls(&CCtrlBase::OnApply)) {
+ m_bExiting = true;
+
+ // everything ok? good, let's close it
+ if (OnApply()) {
+ m_bSucceeded = true;
+ PostMessage(m_hwnd, WM_CLOSE, 0, 0);
+ }
+ else m_bExiting = false;
+ }
+ }
+ }
+ }
+ return FALSE;
+
+ case WM_NOTIFY:
+ {
+ int idCtrl = wParam;
+ NMHDR *pnmh = (NMHDR *)lParam;
+ if (pnmh->idFrom == 0) {
+ switch (pnmh->code) {
+ case PSN_APPLY:
+ if (LPPSHNOTIFY(lParam)->lParam != 3) // IDC_APPLY
+ m_bExiting = true;
+
+ if (!VerifyControls(&CCtrlBase::OnApply))
+ m_bExiting = false;
+ else if (!OnApply())
+ m_bExiting = false;
+ break;
+
+ case PSN_RESET:
+ NotifyControls(&CCtrlBase::OnReset);
+ OnReset();
+ break;
+
+ case PSN_WIZFINISH:
+ m_OnFinishWizard(this);
+ break;
+ }
+ }
+
+ if (CCtrlBase *ctrl = FindControl(pnmh->idFrom))
+ return ctrl->OnNotify(idCtrl, pnmh);
+ }
+ return FALSE;
+
+ case WM_HSCROLL:
+ if (auto *pCtrl = FindControl(HWND(lParam)))
+ pCtrl->OnCommand(HWND(lParam), pCtrl->m_idCtrl, WM_HSCROLL);
+ break;
+
+ case PSM_CHANGED:
+ if (m_bInitialized)
+ OnChange();
+ break;
+
+ case WM_CONTEXTMENU:
+ if (CCtrlBase *ctrl = FindControl(HWND(wParam))) {
+ CContextMenuPos pos = {};
+ if (lParam != -1) {
+ pos.pt.x = GET_X_LPARAM(lParam);
+ pos.pt.y = GET_Y_LPARAM(lParam);
+ }
+ ctrl->GetCaretPos(pos);
+ ctrl->OnBuildMenu(&pos);
+ }
+ break;
+
+ case WM_SIZE:
+ OnResize();
+ return TRUE;
+
+ case WM_TIMER:
+ if (CTimer *timer = FindTimer(wParam))
+ return timer->OnTimer();
+ return FALSE;
+
+ case WM_CLOSE:
+ if (OnClose()) {
+ m_bExiting = true;
+ if (m_isModal)
+ EndModal(m_bSucceeded ? IDOK : FALSE);
+ else
+ DestroyWindow(m_hwnd);
+ }
+ return TRUE;
+
+ case WM_DESTROY:
+ m_bExiting = true;
+ OnDestroy();
+ NotifyControls(&CCtrlBase::OnDestroy);
+ {
+ mir_cslock lck(csDialogs);
+ int idx = arDialogs.getIndex(this);
+ if (idx != -1)
+ arDialogs.remove(idx);
+ }
+ m_hwnd = nullptr;
+ if (m_bInitialized) {
+ if (m_isModal)
+ m_isModal = false;
+ else // modeless dialogs MUST be allocated with 'new'
+ delete this;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+INT_PTR CALLBACK CDlgBase::GlobalDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CDlgBase *wnd;
+ if (msg == WM_INITDIALOG) {
+ wnd = (CDlgBase*)lParam;
+ wnd->m_hwnd = hwnd;
+
+ mir_cslock lck(csDialogs);
+ arDialogs.insert(wnd);
+ }
+ else wnd = CDlgBase::Find(hwnd);
+
+ return (wnd == nullptr) ? FALSE : wnd->DlgProc(msg, wParam, lParam);
+}
+
+void CDlgBase::ThemeDialogBackground(BOOL tabbed)
+{
+ EnableThemeDialogTexture(m_hwnd, (tabbed ? ETDT_ENABLE : ETDT_DISABLE) | ETDT_USETABTEXTURE);
+}
+
+void CDlgBase::AddControl(CCtrlBase *ctrl)
+{
+ m_controls.insert(ctrl);
+}
+
+void CDlgBase::RemoveControl(CCtrlBase *ctrl)
+{
+ m_controls.remove(ctrl);
+}
+
+void CDlgBase::NotifyControls(void (CCtrlBase::*fn)())
+{
+ for (auto &it : m_controls)
+ (it->*fn)();
+}
+
+bool CDlgBase::VerifyControls(bool (CCtrlBase::*fn)())
+{
+ for (auto &it : m_controls)
+ if (!(it->*fn)())
+ return false;
+
+ return true;
+}
+
+CCtrlBase* CDlgBase::FindControl(int idCtrl)
+{
+ CCtrlBase search(nullptr, idCtrl);
+ return m_controls.find(&search);
+}
+
+CCtrlBase* CDlgBase::FindControl(HWND hwnd)
+{
+ for (auto &it : m_controls)
+ if (it->GetHwnd() == hwnd)
+ return it;
+
+ return nullptr;
+}
+
+void CDlgBase::AddTimer(CTimer *timer)
+{
+ m_timers.insert(timer);
+}
+
+void CDlgBase::RemoveTimer(UINT_PTR idEvent)
+{
+ CTimer search(nullptr, idEvent);
+ m_timers.remove(&search);
+}
+
+CTimer* CDlgBase::FindTimer(int idEvent)
+{
+ CTimer search(nullptr, idEvent);
+ return m_timers.find(&search);
+}
+
+CDlgBase* CDlgBase::Find(HWND hwnd)
+{
+ PVOID bullshit[2]; // vfptr + hwnd
+ bullshit[1] = hwnd;
+ return arDialogs.find((CDlgBase*)&bullshit);
+}
diff --git a/src/mir_core/src/Windows/CProgress.cpp b/src/mir_core/src/Windows/CProgress.cpp
index 991c6f239d..e2d5321f59 100644
--- a/src/mir_core/src/Windows/CProgress.cpp
+++ b/src/mir_core/src/Windows/CProgress.cpp
@@ -1,53 +1,53 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlProgress
-
-CCtrlProgress::CCtrlProgress(CDlgBase *wnd, int idCtrl)
- : CCtrlBase(wnd, idCtrl)
-{
-}
-
-void CCtrlProgress::SetRange(uint16_t max, uint16_t min)
-{
- SendMsg(PBM_SETRANGE, 0, MAKELPARAM(min, max));
-}
-
-void CCtrlProgress::SetPosition(uint16_t value)
-{
- SendMsg(PBM_SETPOS, value, 0);
-}
-
-void CCtrlProgress::SetStep(uint16_t value)
-{
- SendMsg(PBM_SETSTEP, value, 0);
-}
-
-uint16_t CCtrlProgress::Move(uint16_t delta)
-{
- return delta == 0
- ? SendMsg(PBM_STEPIT, 0, 0)
- : SendMsg(PBM_DELTAPOS, delta, 0);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlProgress
+
+CCtrlProgress::CCtrlProgress(CDlgBase *wnd, int idCtrl)
+ : CCtrlBase(wnd, idCtrl)
+{
+}
+
+void CCtrlProgress::SetRange(uint16_t max, uint16_t min)
+{
+ SendMsg(PBM_SETRANGE, 0, MAKELPARAM(min, max));
+}
+
+void CCtrlProgress::SetPosition(uint16_t value)
+{
+ SendMsg(PBM_SETPOS, value, 0);
+}
+
+void CCtrlProgress::SetStep(uint16_t value)
+{
+ SendMsg(PBM_SETSTEP, value, 0);
+}
+
+uint16_t CCtrlProgress::Move(uint16_t delta)
+{
+ return delta == 0
+ ? SendMsg(PBM_STEPIT, 0, 0)
+ : SendMsg(PBM_DELTAPOS, delta, 0);
+}
diff --git a/src/mir_core/src/Windows/CSplitter.cpp b/src/mir_core/src/Windows/CSplitter.cpp
index e2ee6b6fc8..153beaf95b 100644
--- a/src/mir_core/src/Windows/CSplitter.cpp
+++ b/src/mir_core/src/Windows/CSplitter.cpp
@@ -1,83 +1,83 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CSplitter
-
-CSplitter::CSplitter(CDlgBase *wnd, int idCtrl)
- : CCtrlBase(wnd, idCtrl),
- m_iPosition(0)
-{
-}
-
-void CSplitter::OnInit()
-{
- CSuper::OnInit();
- Subclass();
-}
-
-LRESULT CSplitter::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_NCHITTEST:
- return HTCLIENT;
-
- case WM_SETCURSOR:
- RECT rc;
- GetClientRect(m_hwnd, &rc);
- SetCursor(rc.right > rc.bottom ? g_hCursorNS : g_hCursorWE);
- return TRUE;
-
- case WM_LBUTTONDOWN:
- SetCapture(m_hwnd);
- return 0;
-
- case WM_MOUSEMOVE:
- if (GetCapture() == m_hwnd) {
- POINT pt = { 0, 0 };
- GetClientRect(m_hwnd, &rc);
- if (rc.right > rc.bottom) {
- pt.y = HIWORD(GetMessagePos()) + rc.bottom / 2;
- ScreenToClient(m_parentWnd->GetHwnd(), &pt);
- m_iPosition = pt.y;
- }
- else {
- pt.x = LOWORD(GetMessagePos()) + rc.right / 2;
- ScreenToClient(m_parentWnd->GetHwnd(), &pt);
- m_iPosition = pt.x;
- }
-
- OnChange(this);
- PostMessage(m_parentWnd->GetHwnd(), WM_SIZE, 0, 0);
- }
- return 0;
-
- case WM_LBUTTONUP:
- ReleaseCapture();
- PostMessage(m_parentWnd->GetHwnd(), WM_SIZE, 0, 0);
- return 0;
- }
-
- return CSuper::CustomWndProc(msg, wParam, lParam);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CSplitter
+
+CSplitter::CSplitter(CDlgBase *wnd, int idCtrl)
+ : CCtrlBase(wnd, idCtrl),
+ m_iPosition(0)
+{
+}
+
+void CSplitter::OnInit()
+{
+ CSuper::OnInit();
+ Subclass();
+}
+
+LRESULT CSplitter::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_NCHITTEST:
+ return HTCLIENT;
+
+ case WM_SETCURSOR:
+ RECT rc;
+ GetClientRect(m_hwnd, &rc);
+ SetCursor(rc.right > rc.bottom ? g_hCursorNS : g_hCursorWE);
+ return TRUE;
+
+ case WM_LBUTTONDOWN:
+ SetCapture(m_hwnd);
+ return 0;
+
+ case WM_MOUSEMOVE:
+ if (GetCapture() == m_hwnd) {
+ POINT pt = { 0, 0 };
+ GetClientRect(m_hwnd, &rc);
+ if (rc.right > rc.bottom) {
+ pt.y = HIWORD(GetMessagePos()) + rc.bottom / 2;
+ ScreenToClient(m_parentWnd->GetHwnd(), &pt);
+ m_iPosition = pt.y;
+ }
+ else {
+ pt.x = LOWORD(GetMessagePos()) + rc.right / 2;
+ ScreenToClient(m_parentWnd->GetHwnd(), &pt);
+ m_iPosition = pt.x;
+ }
+
+ OnChange(this);
+ PostMessage(m_parentWnd->GetHwnd(), WM_SIZE, 0, 0);
+ }
+ return 0;
+
+ case WM_LBUTTONUP:
+ ReleaseCapture();
+ PostMessage(m_parentWnd->GetHwnd(), WM_SIZE, 0, 0);
+ return 0;
+ }
+
+ return CSuper::CustomWndProc(msg, wParam, lParam);
+}
diff --git a/src/mir_core/src/Windows/CTimer.cpp b/src/mir_core/src/Windows/CTimer.cpp
index b346138707..4f1141f329 100644
--- a/src/mir_core/src/Windows/CTimer.cpp
+++ b/src/mir_core/src/Windows/CTimer.cpp
@@ -1,90 +1,90 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-22 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CTimer
-
-CTimer::CTimer(CDlgBase *wnd, UINT_PTR idEvent)
- : m_wnd(wnd), m_idEvent(idEvent)
-{
- if (wnd)
- wnd->AddTimer(this);
-}
-
-CTimer::~CTimer()
-{
- if (m_wnd)
- m_wnd->RemoveTimer(m_idEvent);
-}
-
-BOOL CTimer::OnTimer()
-{
- OnEvent(this);
- return FALSE;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CTimer::Start(int elapse)
-{
- ::SetTimer(m_wnd->GetHwnd(), m_idEvent, elapse, nullptr);
-}
-
-bool CTimer::Stop()
-{
- return 0 != ::KillTimer(m_wnd->GetHwnd(), m_idEvent);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct TStartParam
-{
- CTimer *pTimer;
- int period;
-};
-
-static INT_PTR CALLBACK stubStart(void *param)
-{
- auto *p = (TStartParam *)param;
- return ::SetTimer(p->pTimer->GetHwnd(), p->pTimer->GetEventId(), p->period, nullptr);
-}
-
-void CTimer::StartSafe(int elapse)
-{
- TStartParam param = { this, elapse };
- CallFunctionSync(stubStart, &param);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static INT_PTR CALLBACK stubStop(void *param)
-{
- auto *p = (CTimer*)param;
- return ::KillTimer(p->GetHwnd(), p->GetEventId());
-}
-
-void CTimer::StopSafe()
-{
- CallFunctionSync(stubStop, this);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CTimer
+
+CTimer::CTimer(CDlgBase *wnd, UINT_PTR idEvent)
+ : m_wnd(wnd), m_idEvent(idEvent)
+{
+ if (wnd)
+ wnd->AddTimer(this);
+}
+
+CTimer::~CTimer()
+{
+ if (m_wnd)
+ m_wnd->RemoveTimer(m_idEvent);
+}
+
+BOOL CTimer::OnTimer()
+{
+ OnEvent(this);
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CTimer::Start(int elapse)
+{
+ ::SetTimer(m_wnd->GetHwnd(), m_idEvent, elapse, nullptr);
+}
+
+bool CTimer::Stop()
+{
+ return 0 != ::KillTimer(m_wnd->GetHwnd(), m_idEvent);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct TStartParam
+{
+ CTimer *pTimer;
+ int period;
+};
+
+static INT_PTR CALLBACK stubStart(void *param)
+{
+ auto *p = (TStartParam *)param;
+ return ::SetTimer(p->pTimer->GetHwnd(), p->pTimer->GetEventId(), p->period, nullptr);
+}
+
+void CTimer::StartSafe(int elapse)
+{
+ TStartParam param = { this, elapse };
+ CallFunctionSync(stubStart, &param);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR CALLBACK stubStop(void *param)
+{
+ auto *p = (CTimer*)param;
+ return ::KillTimer(p->GetHwnd(), p->GetEventId());
+}
+
+void CTimer::StopSafe()
+{
+ CallFunctionSync(stubStop, this);
+}
diff --git a/src/mir_core/src/Windows/cmdline.cpp b/src/mir_core/src/Windows/cmdline.cpp
index a4a61b2c6e..0e43610e0c 100644
--- a/src/mir_core/src/Windows/cmdline.cpp
+++ b/src/mir_core/src/Windows/cmdline.cpp
@@ -1,77 +1,77 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-
-/* command line support */
-
-struct CmdLineParam
-{
- __inline CmdLineParam(const wchar_t *_name, const wchar_t *_value) :
- name(mir_wstrdup(_name)), value(mir_wstrdup(_value))
- {}
-
- ptrW name, value;
-};
-
-static int CompareParams(const CmdLineParam *p1, const CmdLineParam *p2)
-{
- return wcscmp(p1->name, p2->name);
-}
-
-static OBJLIST<CmdLineParam> arParams(5, CompareParams);
-
-MIR_CORE_DLL(void) CmdLine_Parse(const wchar_t *ptszCmdLine)
-{
- int nArgs = 0;
- wchar_t **pArgs = CommandLineToArgvW(ptszCmdLine, &nArgs);
- if (pArgs == nullptr)
- return;
-
- for (int i=0; i < nArgs; i++) {
- wchar_t *pOptionName = pArgs[i], *p;
-
- // not an option? skip it
- if (*pOptionName != '/' && *pOptionName != '-')
- continue;
-
- pOptionName++;
- if ((p = wcspbrk(pOptionName, L"=:")) == nullptr) { // no more text in string
- arParams.insert(new CmdLineParam(pOptionName, L""));
- break;
- }
-
- // parameter with value
- *p = 0;
- arParams.insert(new CmdLineParam(pOptionName, p+1));
- }
-
- LocalFree(pArgs);
-}
-
-MIR_CORE_DLL(const wchar_t*) CmdLine_GetOption(const wchar_t* ptszParameter)
-{
- CmdLineParam tmp(ptszParameter, nullptr);
- int idx = arParams.getIndex(&tmp);
- return (idx == -1) ? nullptr : arParams[idx].value.get();
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+/* command line support */
+
+struct CmdLineParam
+{
+ __inline CmdLineParam(const wchar_t *_name, const wchar_t *_value) :
+ name(mir_wstrdup(_name)), value(mir_wstrdup(_value))
+ {}
+
+ ptrW name, value;
+};
+
+static int CompareParams(const CmdLineParam *p1, const CmdLineParam *p2)
+{
+ return wcscmp(p1->name, p2->name);
+}
+
+static OBJLIST<CmdLineParam> arParams(5, CompareParams);
+
+MIR_CORE_DLL(void) CmdLine_Parse(const wchar_t *ptszCmdLine)
+{
+ int nArgs = 0;
+ wchar_t **pArgs = CommandLineToArgvW(ptszCmdLine, &nArgs);
+ if (pArgs == nullptr)
+ return;
+
+ for (int i=0; i < nArgs; i++) {
+ wchar_t *pOptionName = pArgs[i], *p;
+
+ // not an option? skip it
+ if (*pOptionName != '/' && *pOptionName != '-')
+ continue;
+
+ pOptionName++;
+ if ((p = wcspbrk(pOptionName, L"=:")) == nullptr) { // no more text in string
+ arParams.insert(new CmdLineParam(pOptionName, L""));
+ break;
+ }
+
+ // parameter with value
+ *p = 0;
+ arParams.insert(new CmdLineParam(pOptionName, p+1));
+ }
+
+ LocalFree(pArgs);
+}
+
+MIR_CORE_DLL(const wchar_t*) CmdLine_GetOption(const wchar_t* ptszParameter)
+{
+ CmdLineParam tmp(ptszParameter, nullptr);
+ int idx = arParams.getIndex(&tmp);
+ return (idx == -1) ? nullptr : arParams[idx].value.get();
+}
diff --git a/src/mir_core/src/Windows/colourpicker.cpp b/src/mir_core/src/Windows/colourpicker.cpp
index 3272cc37ac..135f8c4096 100644
--- a/src/mir_core/src/Windows/colourpicker.cpp
+++ b/src/mir_core/src/Windows/colourpicker.cpp
@@ -1,105 +1,105 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-
-static LRESULT CALLBACK ColourPickerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- switch (message) {
- case WM_CREATE:
- SetWindowLongPtr(hwnd, 0, 0);
- SetWindowLongPtr(hwnd, sizeof(COLORREF), 0);
- break;
-
- case CPM_SETDEFAULTCOLOUR:
- SetWindowLongPtr(hwnd, sizeof(COLORREF), lParam);
- break;
-
- case CPM_GETDEFAULTCOLOUR:
- return GetWindowLongPtr(hwnd, sizeof(COLORREF));
-
- case CPM_SETCOLOUR:
- SetWindowLongPtr(hwnd, 0, lParam);
- InvalidateRect(hwnd, nullptr, FALSE);
- break;
-
- case CPM_GETCOLOUR:
- return GetWindowLongPtr(hwnd, 0);
-
- case WM_LBUTTONUP:
- {
- COLORREF custColours[16] = { 0 };
- custColours[0] = GetWindowLongPtr(hwnd, sizeof(COLORREF));
-
- CHOOSECOLOR cc = { 0 };
- cc.lStructSize = sizeof(CHOOSECOLOR);
- cc.hwndOwner = hwnd;
- cc.hInstance = (HWND)g_hInst;
- cc.rgbResult = GetWindowLongPtr(hwnd, 0);
- cc.lpCustColors = custColours;
- cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
- if (ChooseColor(&cc)) {
- SetWindowLongPtr(hwnd, 0, cc.rgbResult);
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), CPN_COLOURCHANGED), (LPARAM)hwnd);
- InvalidateRect(hwnd, nullptr, FALSE);
- }
- }
- break;
-
- case WM_ENABLE:
- InvalidateRect(hwnd, nullptr, FALSE);
- break;
-
- case WM_NCPAINT:
- case WM_PAINT:
- PAINTSTRUCT ps;
- HDC hdc1 = BeginPaint(hwnd, &ps);
-
- RECT rc;
- GetClientRect(hwnd, &rc);
- DrawEdge(hdc1, &rc, EDGE_ETCHED, BF_RECT);
- InflateRect(&rc, -2, -2);
-
- HBRUSH hBrush = (IsWindowEnabled(hwnd)) ? CreateSolidBrush(GetWindowLongPtr(hwnd, 0)) : CreateHatchBrush(HS_BDIAGONAL, GetSysColor(COLOR_GRAYTEXT));
- SetBkColor(hdc1, GetSysColor(COLOR_BTNFACE));
- FillRect(hdc1, &rc, hBrush);
- DeleteObject(hBrush);
-
- EndPaint(hwnd, &ps);
- break;
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
-}
-
-void InitColourPicker(void)
-{
- WNDCLASS wcl = { 0 };
- wcl.lpfnWndProc = ColourPickerWndProc;
- wcl.cbWndExtra = sizeof(COLORREF) * 2;
- wcl.hInstance = g_hInst;
- wcl.lpszClassName = _T(WNDCLASS_COLOURPICKER);
- wcl.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
- wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
- RegisterClass(&wcl);
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+static LRESULT CALLBACK ColourPickerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case WM_CREATE:
+ SetWindowLongPtr(hwnd, 0, 0);
+ SetWindowLongPtr(hwnd, sizeof(COLORREF), 0);
+ break;
+
+ case CPM_SETDEFAULTCOLOUR:
+ SetWindowLongPtr(hwnd, sizeof(COLORREF), lParam);
+ break;
+
+ case CPM_GETDEFAULTCOLOUR:
+ return GetWindowLongPtr(hwnd, sizeof(COLORREF));
+
+ case CPM_SETCOLOUR:
+ SetWindowLongPtr(hwnd, 0, lParam);
+ InvalidateRect(hwnd, nullptr, FALSE);
+ break;
+
+ case CPM_GETCOLOUR:
+ return GetWindowLongPtr(hwnd, 0);
+
+ case WM_LBUTTONUP:
+ {
+ COLORREF custColours[16] = { 0 };
+ custColours[0] = GetWindowLongPtr(hwnd, sizeof(COLORREF));
+
+ CHOOSECOLOR cc = { 0 };
+ cc.lStructSize = sizeof(CHOOSECOLOR);
+ cc.hwndOwner = hwnd;
+ cc.hInstance = (HWND)g_hInst;
+ cc.rgbResult = GetWindowLongPtr(hwnd, 0);
+ cc.lpCustColors = custColours;
+ cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
+ if (ChooseColor(&cc)) {
+ SetWindowLongPtr(hwnd, 0, cc.rgbResult);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), CPN_COLOURCHANGED), (LPARAM)hwnd);
+ InvalidateRect(hwnd, nullptr, FALSE);
+ }
+ }
+ break;
+
+ case WM_ENABLE:
+ InvalidateRect(hwnd, nullptr, FALSE);
+ break;
+
+ case WM_NCPAINT:
+ case WM_PAINT:
+ PAINTSTRUCT ps;
+ HDC hdc1 = BeginPaint(hwnd, &ps);
+
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ DrawEdge(hdc1, &rc, EDGE_ETCHED, BF_RECT);
+ InflateRect(&rc, -2, -2);
+
+ HBRUSH hBrush = (IsWindowEnabled(hwnd)) ? CreateSolidBrush(GetWindowLongPtr(hwnd, 0)) : CreateHatchBrush(HS_BDIAGONAL, GetSysColor(COLOR_GRAYTEXT));
+ SetBkColor(hdc1, GetSysColor(COLOR_BTNFACE));
+ FillRect(hdc1, &rc, hBrush);
+ DeleteObject(hBrush);
+
+ EndPaint(hwnd, &ps);
+ break;
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+void InitColourPicker(void)
+{
+ WNDCLASS wcl = { 0 };
+ wcl.lpfnWndProc = ColourPickerWndProc;
+ wcl.cbWndExtra = sizeof(COLORREF) * 2;
+ wcl.hInstance = g_hInst;
+ wcl.lpszClassName = _T(WNDCLASS_COLOURPICKER);
+ wcl.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+ wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
+ RegisterClass(&wcl);
+}
diff --git a/src/mir_core/src/Windows/diatheme.cpp b/src/mir_core/src/Windows/diatheme.cpp
index 2c16131643..12e37ff578 100644
--- a/src/mir_core/src/Windows/diatheme.cpp
+++ b/src/mir_core/src/Windows/diatheme.cpp
@@ -1,170 +1,170 @@
-/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "../stdafx.h"
-#include "diatheme.h"
-
-// The following code was borrowed from Notepad2 sources and adapted for Miranda NG
-
-typedef HTHEME (WINAPI *OTD)(HWND hwnd,LPCWSTR pszClassList);
-typedef HRESULT (WINAPI *GTSF)(HTHEME hTheme,int iFontId,LOGFONT *plf);
-typedef HRESULT (WINAPI *CTD)(HTHEME hTheme);
-
-BOOL GetThemedDialogFont(LPWSTR lpFaceName, WORD *wSize)
-{
- BOOL bSucceed = FALSE;
-
- HDC hDC = GetDC(nullptr);
- int iLogPixelsY = GetDeviceCaps(hDC, LOGPIXELSY);
- ReleaseDC(nullptr, hDC);
-
- if (HMODULE hModUxTheme = GetModuleHandle(L"uxtheme.dll")) {
- OTD _OpenThemeData = (OTD)GetProcAddress(hModUxTheme, "OpenThemeData");
- GTSF _GetThemeSysFont = (GTSF)GetProcAddress(hModUxTheme, "GetThemeSysFont");
- CTD _CloseThemeData = (CTD)GetProcAddress(hModUxTheme, "CloseThemeData");
-
- if (_CloseThemeData && _GetThemeSysFont && _OpenThemeData) {
- if (HTHEME hTheme = _OpenThemeData(NULL, L"WINDOWSTYLE;WINDOW")) {
- LOGFONT lf;
- if (S_OK == _GetThemeSysFont(hTheme,/*TMT_MSGBOXFONT*/805, &lf)) {
- if (lf.lfHeight < 0)
- lf.lfHeight = -lf.lfHeight;
- *wSize = (WORD)MulDiv(lf.lfHeight, 72, iLogPixelsY);
- if (*wSize == 0)
- *wSize = 8;
- wcsncpy_s(lpFaceName, LF_FACESIZE, lf.lfFaceName, _TRUNCATE);
- bSucceed = TRUE;
- }
- _CloseThemeData(hTheme);
- }
- }
- }
-
- if (!bSucceed) {
- NONCLIENTMETRICS ncm;
- ncm.cbSize = sizeof(NONCLIENTMETRICS);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
- if (ncm.lfMessageFont.lfHeight < 0)
- ncm.lfMessageFont.lfHeight = -ncm.lfMessageFont.lfHeight;
- *wSize = (WORD)MulDiv(ncm.lfMessageFont.lfHeight, 72, iLogPixelsY);
- if (*wSize == 0)
- *wSize = 8;
-
- wcsncpy_s(lpFaceName, LF_FACESIZE, ncm.lfMessageFont.lfFaceName, _TRUNCATE);
- }
-
- return TRUE;
-}
-
-BOOL DialogTemplate_IsDialogEx(const DLGTEMPLATE *pTemplate)
-{
- return ((DLGTEMPLATEEX *)pTemplate)->signature == 0xFFFF;
-}
-
-BOOL DialogTemplate_HasFont(const DLGTEMPLATE *pTemplate)
-{
- return (DS_SETFONT & (DialogTemplate_IsDialogEx(pTemplate) ? ((DLGTEMPLATEEX *)pTemplate)->style : pTemplate->style));
-}
-
-int DialogTemplate_FontAttrSize(BOOL bDialogEx)
-{
- return (int)sizeof(WORD) * (bDialogEx ? 3 : 1);
-}
-
-BYTE *DialogTemplate_GetFontSizeField(const DLGTEMPLATE *pTemplate)
-{
- BOOL bDialogEx = DialogTemplate_IsDialogEx(pTemplate);
-
- WORD *pw;
- if (bDialogEx)
- pw = (WORD *)((DLGTEMPLATEEX *)pTemplate + 1);
- else
- pw = (WORD *)(pTemplate + 1);
-
- if (*pw == (WORD)-1)
- pw += 2;
- else
- while (*pw++);
-
- if (*pw == (WORD)-1)
- pw += 2;
- else
- while (*pw++);
-
- while (*pw++);
-
- return (BYTE *)pw;
-}
-
-DLGTEMPLATE* LoadThemedDialogTemplate(LPCTSTR lpDialogTemplateID, HINSTANCE hInstance)
-{
- WCHAR wchFaceName[LF_FACESIZE];
-
- HRSRC hRsrc = FindResource(hInstance, lpDialogTemplateID, RT_DIALOG);
- if (hRsrc == nullptr)
- return nullptr;
-
- HGLOBAL hRsrcMem = LoadResource(hInstance, hRsrc);
- if (hRsrcMem == nullptr)
- return nullptr;
-
- DLGTEMPLATE *pRsrcMem = (DLGTEMPLATE *)LockResource(hRsrcMem);
- if (pRsrcMem == nullptr)
- return nullptr;
-
- size_t dwTemplateSize = (UINT)SizeofResource(hInstance, hRsrc);
- UnlockResource(hRsrcMem);
- FreeResource(hRsrcMem);
-
- if (dwTemplateSize == 0)
- return nullptr;
-
- auto *pTemplate = (DLGTEMPLATE *)mir_alloc(dwTemplateSize + LF_FACESIZE * 2);
- memcpy(pTemplate, pRsrcMem, dwTemplateSize);
- UnlockResource(hRsrcMem);
- FreeResource(hRsrcMem);
-
- WORD wFontSize;
- if (!GetThemedDialogFont(wchFaceName, &wFontSize))
- return(pTemplate);
-
- BOOL bDialogEx = DialogTemplate_IsDialogEx(pTemplate);
- BOOL bHasFont = DialogTemplate_HasFont(pTemplate);
- size_t cbFontAttr = DialogTemplate_FontAttrSize(bDialogEx);
-
- if (bDialogEx)
- ((DLGTEMPLATEEX *)pTemplate)->style |= DS_SHELLFONT;
- else
- pTemplate->style |= DS_SHELLFONT;
-
- size_t cbNew = cbFontAttr + ((mir_wstrlen(wchFaceName) + 1) * sizeof(WCHAR));
- BYTE *pbNew = (BYTE *)wchFaceName;
-
- BYTE *pb = DialogTemplate_GetFontSizeField(pTemplate);
- size_t cbOld = (int)(bHasFont ? cbFontAttr + 2 * (mir_wstrlen((WCHAR *)(pb + cbFontAttr)) + 1) : 0);
-
- BYTE *pOldControls = (BYTE *)(((DWORD_PTR)pb + cbOld + 3) & ~(DWORD_PTR)3);
- BYTE *pNewControls = (BYTE *)(((DWORD_PTR)pb + cbNew + 3) & ~(DWORD_PTR)3);
-
- WORD nCtrl = bDialogEx ? (WORD)((DLGTEMPLATEEX *)pTemplate)->cDlgItems : (WORD)pTemplate->cdit;
- if (cbNew != cbOld && nCtrl > 0)
- MoveMemory(pNewControls, pOldControls, dwTemplateSize - (pOldControls - (BYTE *)pTemplate));
-
- *(WORD *)pb = wFontSize;
- MoveMemory(pb + cbFontAttr, pbNew, cbNew - cbFontAttr);
- return pTemplate;
-}
+/*
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "../stdafx.h"
+#include "diatheme.h"
+
+// The following code was borrowed from Notepad2 sources and adapted for Miranda NG
+
+typedef HTHEME (WINAPI *OTD)(HWND hwnd,LPCWSTR pszClassList);
+typedef HRESULT (WINAPI *GTSF)(HTHEME hTheme,int iFontId,LOGFONT *plf);
+typedef HRESULT (WINAPI *CTD)(HTHEME hTheme);
+
+BOOL GetThemedDialogFont(LPWSTR lpFaceName, WORD *wSize)
+{
+ BOOL bSucceed = FALSE;
+
+ HDC hDC = GetDC(nullptr);
+ int iLogPixelsY = GetDeviceCaps(hDC, LOGPIXELSY);
+ ReleaseDC(nullptr, hDC);
+
+ if (HMODULE hModUxTheme = GetModuleHandle(L"uxtheme.dll")) {
+ OTD _OpenThemeData = (OTD)GetProcAddress(hModUxTheme, "OpenThemeData");
+ GTSF _GetThemeSysFont = (GTSF)GetProcAddress(hModUxTheme, "GetThemeSysFont");
+ CTD _CloseThemeData = (CTD)GetProcAddress(hModUxTheme, "CloseThemeData");
+
+ if (_CloseThemeData && _GetThemeSysFont && _OpenThemeData) {
+ if (HTHEME hTheme = _OpenThemeData(NULL, L"WINDOWSTYLE;WINDOW")) {
+ LOGFONT lf;
+ if (S_OK == _GetThemeSysFont(hTheme,/*TMT_MSGBOXFONT*/805, &lf)) {
+ if (lf.lfHeight < 0)
+ lf.lfHeight = -lf.lfHeight;
+ *wSize = (WORD)MulDiv(lf.lfHeight, 72, iLogPixelsY);
+ if (*wSize == 0)
+ *wSize = 8;
+ wcsncpy_s(lpFaceName, LF_FACESIZE, lf.lfFaceName, _TRUNCATE);
+ bSucceed = TRUE;
+ }
+ _CloseThemeData(hTheme);
+ }
+ }
+ }
+
+ if (!bSucceed) {
+ NONCLIENTMETRICS ncm;
+ ncm.cbSize = sizeof(NONCLIENTMETRICS);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
+ if (ncm.lfMessageFont.lfHeight < 0)
+ ncm.lfMessageFont.lfHeight = -ncm.lfMessageFont.lfHeight;
+ *wSize = (WORD)MulDiv(ncm.lfMessageFont.lfHeight, 72, iLogPixelsY);
+ if (*wSize == 0)
+ *wSize = 8;
+
+ wcsncpy_s(lpFaceName, LF_FACESIZE, ncm.lfMessageFont.lfFaceName, _TRUNCATE);
+ }
+
+ return TRUE;
+}
+
+BOOL DialogTemplate_IsDialogEx(const DLGTEMPLATE *pTemplate)
+{
+ return ((DLGTEMPLATEEX *)pTemplate)->signature == 0xFFFF;
+}
+
+BOOL DialogTemplate_HasFont(const DLGTEMPLATE *pTemplate)
+{
+ return (DS_SETFONT & (DialogTemplate_IsDialogEx(pTemplate) ? ((DLGTEMPLATEEX *)pTemplate)->style : pTemplate->style));
+}
+
+int DialogTemplate_FontAttrSize(BOOL bDialogEx)
+{
+ return (int)sizeof(WORD) * (bDialogEx ? 3 : 1);
+}
+
+BYTE *DialogTemplate_GetFontSizeField(const DLGTEMPLATE *pTemplate)
+{
+ BOOL bDialogEx = DialogTemplate_IsDialogEx(pTemplate);
+
+ WORD *pw;
+ if (bDialogEx)
+ pw = (WORD *)((DLGTEMPLATEEX *)pTemplate + 1);
+ else
+ pw = (WORD *)(pTemplate + 1);
+
+ if (*pw == (WORD)-1)
+ pw += 2;
+ else
+ while (*pw++);
+
+ if (*pw == (WORD)-1)
+ pw += 2;
+ else
+ while (*pw++);
+
+ while (*pw++);
+
+ return (BYTE *)pw;
+}
+
+DLGTEMPLATE* LoadThemedDialogTemplate(LPCTSTR lpDialogTemplateID, HINSTANCE hInstance)
+{
+ WCHAR wchFaceName[LF_FACESIZE];
+
+ HRSRC hRsrc = FindResource(hInstance, lpDialogTemplateID, RT_DIALOG);
+ if (hRsrc == nullptr)
+ return nullptr;
+
+ HGLOBAL hRsrcMem = LoadResource(hInstance, hRsrc);
+ if (hRsrcMem == nullptr)
+ return nullptr;
+
+ DLGTEMPLATE *pRsrcMem = (DLGTEMPLATE *)LockResource(hRsrcMem);
+ if (pRsrcMem == nullptr)
+ return nullptr;
+
+ size_t dwTemplateSize = (UINT)SizeofResource(hInstance, hRsrc);
+ UnlockResource(hRsrcMem);
+ FreeResource(hRsrcMem);
+
+ if (dwTemplateSize == 0)
+ return nullptr;
+
+ auto *pTemplate = (DLGTEMPLATE *)mir_alloc(dwTemplateSize + LF_FACESIZE * 2);
+ memcpy(pTemplate, pRsrcMem, dwTemplateSize);
+ UnlockResource(hRsrcMem);
+ FreeResource(hRsrcMem);
+
+ WORD wFontSize;
+ if (!GetThemedDialogFont(wchFaceName, &wFontSize))
+ return(pTemplate);
+
+ BOOL bDialogEx = DialogTemplate_IsDialogEx(pTemplate);
+ BOOL bHasFont = DialogTemplate_HasFont(pTemplate);
+ size_t cbFontAttr = DialogTemplate_FontAttrSize(bDialogEx);
+
+ if (bDialogEx)
+ ((DLGTEMPLATEEX *)pTemplate)->style |= DS_SHELLFONT;
+ else
+ pTemplate->style |= DS_SHELLFONT;
+
+ size_t cbNew = cbFontAttr + ((mir_wstrlen(wchFaceName) + 1) * sizeof(WCHAR));
+ BYTE *pbNew = (BYTE *)wchFaceName;
+
+ BYTE *pb = DialogTemplate_GetFontSizeField(pTemplate);
+ size_t cbOld = (int)(bHasFont ? cbFontAttr + 2 * (mir_wstrlen((WCHAR *)(pb + cbFontAttr)) + 1) : 0);
+
+ BYTE *pOldControls = (BYTE *)(((DWORD_PTR)pb + cbOld + 3) & ~(DWORD_PTR)3);
+ BYTE *pNewControls = (BYTE *)(((DWORD_PTR)pb + cbNew + 3) & ~(DWORD_PTR)3);
+
+ WORD nCtrl = bDialogEx ? (WORD)((DLGTEMPLATEEX *)pTemplate)->cDlgItems : (WORD)pTemplate->cdit;
+ if (cbNew != cbOld && nCtrl > 0)
+ MoveMemory(pNewControls, pOldControls, dwTemplateSize - (pOldControls - (BYTE *)pTemplate));
+
+ *(WORD *)pb = wFontSize;
+ MoveMemory(pb + cbFontAttr, pbNew, cbNew - cbFontAttr);
+ return pTemplate;
+}
diff --git a/src/mir_core/src/Windows/fileutil.cpp b/src/mir_core/src/Windows/fileutil.cpp
index 2522cc7cbe..a0dcee68f6 100644
--- a/src/mir_core/src/Windows/fileutil.cpp
+++ b/src/mir_core/src/Windows/fileutil.cpp
@@ -1,78 +1,78 @@
-/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "../stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MFilePath::MFileIterator::iterator MFilePath::MFileIterator::iterator::operator++()
-{
- if (ptr != nullptr) {
- if (::FindNextFileW(ptr->m_hFind, &ptr->m_data) == 0) {
- ::FindClose(ptr->m_hFind); ptr->m_hFind = INVALID_HANDLE_VALUE;
- ptr = nullptr;
- }
- }
- return *this;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MFilePath::MFileIterator::MFileIterator(const wchar_t *pwszPath)
-{
- if (pwszPath != nullptr)
- m_hFind = ::FindFirstFileW(pwszPath, &m_data);
-}
-
-MFilePath::MFileIterator::~MFileIterator()
-{
- if (m_hFind != INVALID_HANDLE_VALUE)
- ::FindClose(m_hFind);
-}
-
-MFilePath::MFileIterator::iterator MFilePath::MFileIterator::begin()
-{
- if (m_hFind == INVALID_HANDLE_VALUE)
- return MFilePath::MFileIterator::iterator(nullptr);
-
- return MFilePath::MFileIterator::iterator(this);
-}
-
-bool MFilePath::MFileIterator::isDir() const
-{
- if (m_hFind == INVALID_HANDLE_VALUE)
- return false;
-
- return (m_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-bool MFilePath::isExist() const
-{
- return _waccess(c_str(), 0) == 0;
-}
-
-bool MFilePath::move(const wchar_t *pwszDest)
-{
- return MoveFileW(c_str(), pwszDest) != 0;
-}
-
-MFilePath::MFileIterator MFilePath::search()
-{
- return MFileIterator(c_str());
-}
+/*
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MFilePath::MFileIterator::iterator MFilePath::MFileIterator::iterator::operator++()
+{
+ if (ptr != nullptr) {
+ if (::FindNextFileW(ptr->m_hFind, &ptr->m_data) == 0) {
+ ::FindClose(ptr->m_hFind); ptr->m_hFind = INVALID_HANDLE_VALUE;
+ ptr = nullptr;
+ }
+ }
+ return *this;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MFilePath::MFileIterator::MFileIterator(const wchar_t *pwszPath)
+{
+ if (pwszPath != nullptr)
+ m_hFind = ::FindFirstFileW(pwszPath, &m_data);
+}
+
+MFilePath::MFileIterator::~MFileIterator()
+{
+ if (m_hFind != INVALID_HANDLE_VALUE)
+ ::FindClose(m_hFind);
+}
+
+MFilePath::MFileIterator::iterator MFilePath::MFileIterator::begin()
+{
+ if (m_hFind == INVALID_HANDLE_VALUE)
+ return MFilePath::MFileIterator::iterator(nullptr);
+
+ return MFilePath::MFileIterator::iterator(this);
+}
+
+bool MFilePath::MFileIterator::isDir() const
+{
+ if (m_hFind == INVALID_HANDLE_VALUE)
+ return false;
+
+ return (m_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+bool MFilePath::isExist() const
+{
+ return _waccess(c_str(), 0) == 0;
+}
+
+bool MFilePath::move(const wchar_t *pwszDest)
+{
+ return MoveFileW(c_str(), pwszDest) != 0;
+}
+
+MFilePath::MFileIterator MFilePath::search()
+{
+ return MFileIterator(c_str());
+}
diff --git a/src/mir_core/src/Windows/hyperlink.cpp b/src/mir_core/src/Windows/hyperlink.cpp
index 2f70d23103..e83f8ff569 100644
--- a/src/mir_core/src/Windows/hyperlink.cpp
+++ b/src/mir_core/src/Windows/hyperlink.cpp
@@ -1,277 +1,277 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-
-struct HyperlinkWndData
-{
- HFONT hEnableFont, hDisableFont;
- RECT rcText;
- COLORREF enableColor, disableColor, focusColor;
- uint8_t flags; /* see HLKF_* */
-};
-
-/* flags */
-#define HLKF_HASENABLECOLOR 0x1 /* dat->enableColor is not system default */
-#define HLKF_HASDISABLECOLOR 0x2 /* dat->disableColor is not system default */
-
-/* internal messages */
-#define HLK_MEASURETEXT (WM_USER+1)
-#define HLK_INVALIDATE (WM_USER+2)
-
-static LRESULT CALLBACK HyperlinkWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- HyperlinkWndData *dat = (HyperlinkWndData*)GetWindowLongPtr(hwnd, 0);
-
- HDC hdc;
- RECT rc;
- POINT pt;
- HFONT hFont;
- LOGFONT lf;
- HCURSOR hCursor;
- COLORREF prevColor;
-
- switch (msg) {
- case WM_NCCREATE:
- dat = (struct HyperlinkWndData*)mir_calloc(sizeof(struct HyperlinkWndData));
- if (dat == nullptr)
- return FALSE; /* fail creation */
- SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat); /* always succeeds */
- /* fall thru */
-
- case WM_SYSCOLORCHANGE:
- if (!(dat->flags&HLKF_HASENABLECOLOR)) {
- if (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) dat->enableColor = RGB(0, 0, 255);
- else dat->enableColor = GetSysColor(COLOR_HOTLIGHT);
- dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
- }
- if (!(dat->flags&HLKF_HASDISABLECOLOR))
- dat->disableColor = GetSysColor(COLOR_GRAYTEXT);
- break;
-
- case WM_SETFOCUS:
- case WM_KILLFOCUS:
- RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE);
- break;
-
- case WM_MOUSEACTIVATE:
- SetFocus(hwnd);
- return MA_ACTIVATE;
-
- case WM_GETDLGCODE:
- if (lParam) {
- MSG *pMsg = (MSG *)lParam;
- if (pMsg->message == WM_KEYDOWN) {
- if (pMsg->wParam == VK_TAB)
- return 0;
- if (pMsg->wParam == VK_ESCAPE)
- return 0;
- }
- else if (pMsg->message == WM_CHAR) {
- if (pMsg->wParam == '\t')
- return 0;
- if (pMsg->wParam == 27)
- return 0;
- }
- }
- return DLGC_WANTMESSAGE;
-
- case WM_KEYDOWN:
- switch (wParam) {
- case VK_SPACE:
- case VK_RETURN:
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd);
- break;
- }
- return 0;
-
- case WM_LBUTTONDOWN:
- POINTSTOPOINT(pt, MAKEPOINTS(lParam));
- if (!PtInRect(&dat->rcText, pt)) break;
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd);
- return 0;
-
- case WM_SETFONT:
- if ((HFONT)wParam == nullptr) { /* use default system color */
- dat->hEnableFont = dat->hDisableFont = nullptr;
- return 0;
- }
- if (GetObject((HFONT)wParam, sizeof(lf), &lf)) {
- lf.lfUnderline = 1;
- hFont = CreateFontIndirect(&lf);
- if (hFont != nullptr) {
- dat->hEnableFont = hFont;
- dat->hDisableFont = (HFONT)wParam;
- if (LOWORD(lParam)) SendMessage(hwnd, HLK_INVALIDATE, 0, 0);
- SendMessage(hwnd, HLK_MEASURETEXT, 0, 0);
- }
- }
- return 0;
-
- case WM_ERASEBKGND:
- return TRUE;
-
- case WM_ENABLE:
- case HLK_INVALIDATE:
- if (GetWindowRect(hwnd, &rc)) {
- pt.x = rc.left;
- pt.y = rc.top;
-
- HWND hwndParent = GetParent(hwnd);
- if (hwndParent == nullptr)
- hwndParent = hwnd;
- if (!ScreenToClient(hwndParent, &pt))
- break;
-
- rc.right = pt.x + (rc.right - rc.left);
- rc.bottom = pt.y + (rc.bottom - rc.top);
- rc.left = pt.x;
- rc.top = pt.y;
- InvalidateRect(hwndParent, &rc, TRUE);
- }
- return 0;
-
- case WM_GETFONT:
- return (LRESULT)dat->hDisableFont;
-
- case WM_CREATE:
- case HLK_MEASURETEXT:
- wchar_t szText[256];
- if (!GetWindowText(hwnd, szText, _countof(szText))) return 0;
- lParam = (LPARAM)szText;
- /* fall thru */
-
- case WM_SETTEXT:
- hdc = GetDC(hwnd);
- if (hdc == nullptr) /* text change failed */
- return 0;
- else {
- BOOL fMeasured = FALSE;
- HFONT hPrevFont = nullptr;
- if (dat->hEnableFont != nullptr) hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont);
- if (dat->hEnableFont == nullptr || hPrevFont != nullptr) { /* select failed? */
- SIZE textSize;
- if (GetTextExtentPoint32(hdc, (wchar_t*)lParam, (int)mir_wstrlen((wchar_t*)lParam), &textSize)) {
- if (GetClientRect(hwnd, &rc)) {
- dat->rcText.top = 0;
- dat->rcText.bottom = dat->rcText.top + textSize.cy;
- LONG style = GetWindowLongPtr(hwnd, GWL_STYLE);
- if (style & SS_CENTER) dat->rcText.left = (rc.right - textSize.cx) / 2;
- else if (style & SS_RIGHT) dat->rcText.left = rc.right - textSize.cx;
- else dat->rcText.left = 0;
- dat->rcText.right = dat->rcText.left + textSize.cx;
- fMeasured = TRUE;
- }
- }
- }
- if (dat->hEnableFont != nullptr && hPrevFont != nullptr)
- SelectObject(hdc, hPrevFont);
- ReleaseDC(hwnd, hdc);
- if (!fMeasured) /* text change failed */
- return 0;
-
- SendMessage(hwnd, HLK_INVALIDATE, 0, 0);
- }
- break;
-
- case WM_SETCURSOR:
- if (!GetCursorPos(&pt)) return FALSE;
- if (!ScreenToClient(hwnd, &pt)) return FALSE;
- if (PtInRect(&dat->rcText, pt)) {
- hCursor = (HCURSOR)GetClassLongPtr(hwnd, GCLP_HCURSOR);
- if (hCursor == nullptr)
- hCursor = LoadCursor(nullptr, IDC_HAND); /* Win2000+ */
- }
- else hCursor = LoadCursor(nullptr, IDC_ARROW);
- SetCursor(hCursor);
- return TRUE;
-
- case HLK_SETENABLECOLOUR:
- prevColor = dat->enableColor;
- dat->enableColor = (COLORREF)wParam;
- dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
- dat->flags |= HLKF_HASENABLECOLOR;
- return (LRESULT)prevColor;
-
- case HLK_SETDISABLECOLOUR:
- prevColor = dat->disableColor;
- dat->disableColor = (COLORREF)wParam;
- dat->flags |= HLKF_HASDISABLECOLOR;
- return (LRESULT)prevColor;
-
- case WM_NCPAINT:
- return 0;
-
- case WM_PAINT:
- PAINTSTRUCT ps;
- hdc = BeginPaint(hwnd, &ps);
- if (hdc != nullptr) {
- HFONT hPrevFont;
- COLORREF textColor;
- if (IsWindowEnabled(hwnd)) {
- hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont);
- textColor = (GetFocus() == hwnd) ? dat->focusColor : dat->enableColor;
- }
- else {
- hPrevFont = (HFONT)SelectObject(hdc, dat->hDisableFont);
- textColor = dat->disableColor;
- }
- if (GetClientRect(hwnd, &rc) && GetWindowText(hwnd, szText, _countof(szText))) {
- BOOL fSmoothing;
- UINT fSmoothingType;
- SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fSmoothing, 0);
- SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &fSmoothingType, 0);
- if (fSmoothing && fSmoothingType == FE_FONTSMOOTHINGCLEARTYPE)
- DrawThemeParentBackground(hwnd, hdc, &rc);
- SetBkMode(hdc, TRANSPARENT);
- SetTextColor(hdc, textColor);
- UINT alignFlag = (GetWindowLongPtr(hwnd, GWL_STYLE) & (SS_CENTER | SS_RIGHT | SS_LEFT));
- DrawText(hdc, szText, -1, &rc, alignFlag | DT_NOPREFIX | DT_SINGLELINE | DT_TOP);
- }
- if (hPrevFont != nullptr) SelectObject(hdc, hPrevFont);
- EndPaint(hwnd, &ps);
- }
- return 0;
-
- case WM_NCDESTROY:
- if (dat->hEnableFont != nullptr) DeleteObject(dat->hEnableFont);
- mir_free(dat);
- break;
- }
- return DefWindowProc(hwnd, msg, wParam, lParam);
-}
-
-void InitHyperlink(void)
-{
- g_hCursorNS = LoadCursor(nullptr, IDC_SIZENS);
- g_hCursorWE = LoadCursor(nullptr, IDC_SIZEWE);
-
- WNDCLASS wcl = { 0 };
- wcl.lpfnWndProc = HyperlinkWndProc;
- wcl.cbWndExtra = sizeof(struct HyperlinkWndData*);
- wcl.hInstance = g_hInst;
- wcl.lpszClassName = WNDCLASS_HYPERLINK;
- wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS | CS_PARENTDC;
- RegisterClass(&wcl); /* automatically unregistered on exit */
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+struct HyperlinkWndData
+{
+ HFONT hEnableFont, hDisableFont;
+ RECT rcText;
+ COLORREF enableColor, disableColor, focusColor;
+ uint8_t flags; /* see HLKF_* */
+};
+
+/* flags */
+#define HLKF_HASENABLECOLOR 0x1 /* dat->enableColor is not system default */
+#define HLKF_HASDISABLECOLOR 0x2 /* dat->disableColor is not system default */
+
+/* internal messages */
+#define HLK_MEASURETEXT (WM_USER+1)
+#define HLK_INVALIDATE (WM_USER+2)
+
+static LRESULT CALLBACK HyperlinkWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HyperlinkWndData *dat = (HyperlinkWndData*)GetWindowLongPtr(hwnd, 0);
+
+ HDC hdc;
+ RECT rc;
+ POINT pt;
+ HFONT hFont;
+ LOGFONT lf;
+ HCURSOR hCursor;
+ COLORREF prevColor;
+
+ switch (msg) {
+ case WM_NCCREATE:
+ dat = (struct HyperlinkWndData*)mir_calloc(sizeof(struct HyperlinkWndData));
+ if (dat == nullptr)
+ return FALSE; /* fail creation */
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat); /* always succeeds */
+ /* fall thru */
+
+ case WM_SYSCOLORCHANGE:
+ if (!(dat->flags&HLKF_HASENABLECOLOR)) {
+ if (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) dat->enableColor = RGB(0, 0, 255);
+ else dat->enableColor = GetSysColor(COLOR_HOTLIGHT);
+ dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
+ }
+ if (!(dat->flags&HLKF_HASDISABLECOLOR))
+ dat->disableColor = GetSysColor(COLOR_GRAYTEXT);
+ break;
+
+ case WM_SETFOCUS:
+ case WM_KILLFOCUS:
+ RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE);
+ break;
+
+ case WM_MOUSEACTIVATE:
+ SetFocus(hwnd);
+ return MA_ACTIVATE;
+
+ case WM_GETDLGCODE:
+ if (lParam) {
+ MSG *pMsg = (MSG *)lParam;
+ if (pMsg->message == WM_KEYDOWN) {
+ if (pMsg->wParam == VK_TAB)
+ return 0;
+ if (pMsg->wParam == VK_ESCAPE)
+ return 0;
+ }
+ else if (pMsg->message == WM_CHAR) {
+ if (pMsg->wParam == '\t')
+ return 0;
+ if (pMsg->wParam == 27)
+ return 0;
+ }
+ }
+ return DLGC_WANTMESSAGE;
+
+ case WM_KEYDOWN:
+ switch (wParam) {
+ case VK_SPACE:
+ case VK_RETURN:
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd);
+ break;
+ }
+ return 0;
+
+ case WM_LBUTTONDOWN:
+ POINTSTOPOINT(pt, MAKEPOINTS(lParam));
+ if (!PtInRect(&dat->rcText, pt)) break;
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd);
+ return 0;
+
+ case WM_SETFONT:
+ if ((HFONT)wParam == nullptr) { /* use default system color */
+ dat->hEnableFont = dat->hDisableFont = nullptr;
+ return 0;
+ }
+ if (GetObject((HFONT)wParam, sizeof(lf), &lf)) {
+ lf.lfUnderline = 1;
+ hFont = CreateFontIndirect(&lf);
+ if (hFont != nullptr) {
+ dat->hEnableFont = hFont;
+ dat->hDisableFont = (HFONT)wParam;
+ if (LOWORD(lParam)) SendMessage(hwnd, HLK_INVALIDATE, 0, 0);
+ SendMessage(hwnd, HLK_MEASURETEXT, 0, 0);
+ }
+ }
+ return 0;
+
+ case WM_ERASEBKGND:
+ return TRUE;
+
+ case WM_ENABLE:
+ case HLK_INVALIDATE:
+ if (GetWindowRect(hwnd, &rc)) {
+ pt.x = rc.left;
+ pt.y = rc.top;
+
+ HWND hwndParent = GetParent(hwnd);
+ if (hwndParent == nullptr)
+ hwndParent = hwnd;
+ if (!ScreenToClient(hwndParent, &pt))
+ break;
+
+ rc.right = pt.x + (rc.right - rc.left);
+ rc.bottom = pt.y + (rc.bottom - rc.top);
+ rc.left = pt.x;
+ rc.top = pt.y;
+ InvalidateRect(hwndParent, &rc, TRUE);
+ }
+ return 0;
+
+ case WM_GETFONT:
+ return (LRESULT)dat->hDisableFont;
+
+ case WM_CREATE:
+ case HLK_MEASURETEXT:
+ wchar_t szText[256];
+ if (!GetWindowText(hwnd, szText, _countof(szText))) return 0;
+ lParam = (LPARAM)szText;
+ /* fall thru */
+
+ case WM_SETTEXT:
+ hdc = GetDC(hwnd);
+ if (hdc == nullptr) /* text change failed */
+ return 0;
+ else {
+ BOOL fMeasured = FALSE;
+ HFONT hPrevFont = nullptr;
+ if (dat->hEnableFont != nullptr) hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont);
+ if (dat->hEnableFont == nullptr || hPrevFont != nullptr) { /* select failed? */
+ SIZE textSize;
+ if (GetTextExtentPoint32(hdc, (wchar_t*)lParam, (int)mir_wstrlen((wchar_t*)lParam), &textSize)) {
+ if (GetClientRect(hwnd, &rc)) {
+ dat->rcText.top = 0;
+ dat->rcText.bottom = dat->rcText.top + textSize.cy;
+ LONG style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ if (style & SS_CENTER) dat->rcText.left = (rc.right - textSize.cx) / 2;
+ else if (style & SS_RIGHT) dat->rcText.left = rc.right - textSize.cx;
+ else dat->rcText.left = 0;
+ dat->rcText.right = dat->rcText.left + textSize.cx;
+ fMeasured = TRUE;
+ }
+ }
+ }
+ if (dat->hEnableFont != nullptr && hPrevFont != nullptr)
+ SelectObject(hdc, hPrevFont);
+ ReleaseDC(hwnd, hdc);
+ if (!fMeasured) /* text change failed */
+ return 0;
+
+ SendMessage(hwnd, HLK_INVALIDATE, 0, 0);
+ }
+ break;
+
+ case WM_SETCURSOR:
+ if (!GetCursorPos(&pt)) return FALSE;
+ if (!ScreenToClient(hwnd, &pt)) return FALSE;
+ if (PtInRect(&dat->rcText, pt)) {
+ hCursor = (HCURSOR)GetClassLongPtr(hwnd, GCLP_HCURSOR);
+ if (hCursor == nullptr)
+ hCursor = LoadCursor(nullptr, IDC_HAND); /* Win2000+ */
+ }
+ else hCursor = LoadCursor(nullptr, IDC_ARROW);
+ SetCursor(hCursor);
+ return TRUE;
+
+ case HLK_SETENABLECOLOUR:
+ prevColor = dat->enableColor;
+ dat->enableColor = (COLORREF)wParam;
+ dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
+ dat->flags |= HLKF_HASENABLECOLOR;
+ return (LRESULT)prevColor;
+
+ case HLK_SETDISABLECOLOUR:
+ prevColor = dat->disableColor;
+ dat->disableColor = (COLORREF)wParam;
+ dat->flags |= HLKF_HASDISABLECOLOR;
+ return (LRESULT)prevColor;
+
+ case WM_NCPAINT:
+ return 0;
+
+ case WM_PAINT:
+ PAINTSTRUCT ps;
+ hdc = BeginPaint(hwnd, &ps);
+ if (hdc != nullptr) {
+ HFONT hPrevFont;
+ COLORREF textColor;
+ if (IsWindowEnabled(hwnd)) {
+ hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont);
+ textColor = (GetFocus() == hwnd) ? dat->focusColor : dat->enableColor;
+ }
+ else {
+ hPrevFont = (HFONT)SelectObject(hdc, dat->hDisableFont);
+ textColor = dat->disableColor;
+ }
+ if (GetClientRect(hwnd, &rc) && GetWindowText(hwnd, szText, _countof(szText))) {
+ BOOL fSmoothing;
+ UINT fSmoothingType;
+ SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fSmoothing, 0);
+ SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &fSmoothingType, 0);
+ if (fSmoothing && fSmoothingType == FE_FONTSMOOTHINGCLEARTYPE)
+ DrawThemeParentBackground(hwnd, hdc, &rc);
+ SetBkMode(hdc, TRANSPARENT);
+ SetTextColor(hdc, textColor);
+ UINT alignFlag = (GetWindowLongPtr(hwnd, GWL_STYLE) & (SS_CENTER | SS_RIGHT | SS_LEFT));
+ DrawText(hdc, szText, -1, &rc, alignFlag | DT_NOPREFIX | DT_SINGLELINE | DT_TOP);
+ }
+ if (hPrevFont != nullptr) SelectObject(hdc, hPrevFont);
+ EndPaint(hwnd, &ps);
+ }
+ return 0;
+
+ case WM_NCDESTROY:
+ if (dat->hEnableFont != nullptr) DeleteObject(dat->hEnableFont);
+ mir_free(dat);
+ break;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+void InitHyperlink(void)
+{
+ g_hCursorNS = LoadCursor(nullptr, IDC_SIZENS);
+ g_hCursorWE = LoadCursor(nullptr, IDC_SIZEWE);
+
+ WNDCLASS wcl = { 0 };
+ wcl.lpfnWndProc = HyperlinkWndProc;
+ wcl.cbWndExtra = sizeof(struct HyperlinkWndData*);
+ wcl.hInstance = g_hInst;
+ wcl.lpszClassName = WNDCLASS_HYPERLINK;
+ wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS | CS_PARENTDC;
+ RegisterClass(&wcl); /* automatically unregistered on exit */
+}
diff --git a/src/mir_core/src/Windows/icons.cpp b/src/mir_core/src/Windows/icons.cpp
index a4555211de..122ecad5e5 100644
--- a/src/mir_core/src/Windows/icons.cpp
+++ b/src/mir_core/src/Windows/icons.cpp
@@ -1,74 +1,74 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-
-MIR_CORE_DLL(void) Icon_Register(HINSTANCE hInst, const char *szSection, IconItem *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin)
-{
- wchar_t szFile[MAX_PATH];
- GetModuleFileName(hInst, szFile, MAX_PATH);
-
- SKINICONDESC sid = {};
- sid.defaultFile.w = szFile;
- sid.section.a = (char*)szSection;
- sid.flags = SIDF_PATH_UNICODE;
-
- for (unsigned i = 0; i < iCount; i++) {
- char szSetting[100];
- if (prefix) {
- mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName);
- sid.pszName = szSetting;
- }
- else sid.pszName = pIcons[i].szName;
-
- sid.cx = sid.cy = pIcons[i].size;
- sid.description.a = pIcons[i].szDescr;
- sid.iDefaultIndex = -pIcons[i].defIconID;
- pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin);
- }
-}
-
-MIR_CORE_DLL(void) Icon_RegisterT(HINSTANCE hInst, const wchar_t *szSection, IconItemT *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin)
-{
- wchar_t szFile[MAX_PATH];
- GetModuleFileName(hInst, szFile, MAX_PATH);
-
- SKINICONDESC sid = {};
- sid.defaultFile.w = szFile;
- sid.section.w = (wchar_t*)szSection;
- sid.flags = SIDF_ALL_UNICODE;
-
- for (unsigned i = 0; i < iCount; i++) {
- char szSetting[100];
- if (prefix) {
- mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName);
- sid.pszName = szSetting;
- }
- else sid.pszName = pIcons[i].szName;
-
- sid.cx = sid.cy = pIcons[i].size;
- sid.description.w = pIcons[i].tszDescr;
- sid.iDefaultIndex = -pIcons[i].defIconID;
- pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin);
- }
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+MIR_CORE_DLL(void) Icon_Register(HINSTANCE hInst, const char *szSection, IconItem *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin)
+{
+ wchar_t szFile[MAX_PATH];
+ GetModuleFileName(hInst, szFile, MAX_PATH);
+
+ SKINICONDESC sid = {};
+ sid.defaultFile.w = szFile;
+ sid.section.a = (char*)szSection;
+ sid.flags = SIDF_PATH_UNICODE;
+
+ for (unsigned i = 0; i < iCount; i++) {
+ char szSetting[100];
+ if (prefix) {
+ mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName);
+ sid.pszName = szSetting;
+ }
+ else sid.pszName = pIcons[i].szName;
+
+ sid.cx = sid.cy = pIcons[i].size;
+ sid.description.a = pIcons[i].szDescr;
+ sid.iDefaultIndex = -pIcons[i].defIconID;
+ pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin);
+ }
+}
+
+MIR_CORE_DLL(void) Icon_RegisterT(HINSTANCE hInst, const wchar_t *szSection, IconItemT *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin)
+{
+ wchar_t szFile[MAX_PATH];
+ GetModuleFileName(hInst, szFile, MAX_PATH);
+
+ SKINICONDESC sid = {};
+ sid.defaultFile.w = szFile;
+ sid.section.w = (wchar_t*)szSection;
+ sid.flags = SIDF_ALL_UNICODE;
+
+ for (unsigned i = 0; i < iCount; i++) {
+ char szSetting[100];
+ if (prefix) {
+ mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName);
+ sid.pszName = szSetting;
+ }
+ else sid.pszName = pIcons[i].szName;
+
+ sid.cx = sid.cy = pIcons[i].size;
+ sid.description.w = pIcons[i].tszDescr;
+ sid.iDefaultIndex = -pIcons[i].defIconID;
+ pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin);
+ }
+}
diff --git a/src/mir_core/src/Windows/langpack.cpp b/src/mir_core/src/Windows/langpack.cpp
index 00b7d996e1..010b1311ca 100644
--- a/src/mir_core/src/Windows/langpack.cpp
+++ b/src/mir_core/src/Windows/langpack.cpp
@@ -1,765 +1,765 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-
-#include "../../../mir_app/src/langpack.h"
-
-#define LANGPACK_BUF_SIZE 4000
-
-static int CompareMuuids(const MUUID *p1, const MUUID *p2)
-{
- return memcmp(p1, p2, sizeof(MUUID));
-}
-
-static LIST<MUUID> lMuuids(10, CompareMuuids);
-static MUUID *pCurrentMuuid = nullptr;
-static HANDLE hevChanged = nullptr;
-
-static BOOL bModuleInitialized = FALSE;
-
-struct LangPackEntry
-{
- uint32_t englishHash;
- char *szLocal;
- char *utfLocal;
- wchar_t *wszLocal;
- MUUID *pMuuid;
- LangPackEntry* pNext; // for langpack items with the same hash value
-};
-
-static LANGPACK_INFO langPack;
-static wchar_t g_tszRoot[MAX_PATH];
-
-static LangPackEntry *g_pEntries;
-static int g_entryCount, g_entriesAlloced;
-
-static int IsEmpty(const char *str)
-{
- for (int i = 0; str[i]; i++)
- if (str[i] != ' ' && str[i] != '\r' && str[i] != '\n')
- return 0;
-
- return 1;
-}
-
-static int ConvertBackslashes(char *str, UINT fileCp)
-{
- int shift = 0;
- char *pstr;
- for (pstr = str; *pstr; pstr = CharNextExA(fileCp, pstr, 0)) {
- if (*pstr == '\\') {
- shift++;
- switch (pstr[1]) {
- case 'n': *pstr = '\n'; break;
- case 't': *pstr = '\t'; break;
- case 'r': *pstr = '\r'; break;
- case 's': *pstr = ' '; break;
- default: *pstr = pstr[1]; break;
- }
- memmove(pstr + 1, pstr + 2, strlen(pstr + 2) + 1);
- }
- }
- return shift;
-}
-
-#ifdef _DEBUG
-//#pragma optimize("gt", on)
-#endif
-
-// MurmurHash2
-MIR_CORE_DLL(unsigned int) mir_hash(const void * key, unsigned int len)
-{
- // 'm' and 'r' are mixing constants generated offline.
- // They're not really 'magic', they just happen to work well.
- const unsigned int m = 0x5bd1e995;
- const int r = 24;
-
- // Initialize the hash to a 'random' value
- unsigned int h = len;
-
- // Mix 4 bytes at a time into the hash
- const unsigned char *data = (const unsigned char*)key;
-
- while (len >= 4) {
- unsigned int k = *(unsigned int*)data;
-
- k *= m;
- k ^= k >> r;
- k *= m;
-
- h *= m;
- h ^= k;
-
- data += 4;
- len -= 4;
- }
-
- // Handle the last few bytes of the input array
- switch (len) {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0];
- h *= m;
- }
-
- // Do a few final mixes of the hash to ensure the last few
- // bytes are well-incorporated.
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
-}
-
-static unsigned int __fastcall hashstrW(const char *key)
-{
- if (key == nullptr) return 0;
- const unsigned int len = (unsigned int)wcslen((const wchar_t*)key);
- char *buf = (char*)alloca(len + 1);
- for (unsigned i = 0; i <= len; ++i)
- buf[i] = key[i << 1];
- return mir_hash(buf, len);
-}
-
-static const MUUID* GetMuid(HPLUGIN pPlugin)
-{
- if (!pPlugin)
- return nullptr;
-
- __try {
- return &pPlugin->getInfo().uuid;
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- return nullptr;
- }
-}
-
-static int SortLangPackHashesProc(LangPackEntry *arg1, LangPackEntry *arg2)
-{
- if (arg1->englishHash < arg2->englishHash) return -1;
- if (arg1->englishHash > arg2->englishHash) return 1;
-
- return (arg1->pMuuid < arg2->pMuuid) ? -1 : 1;
-}
-
-static void swapBytes(void *p, size_t iSize)
-{
- char *head = (char*)p; // here
- char *tail = head + iSize - 1;
-
- for (; tail > head; --tail, ++head) {
- char temp = *head;
- *head = *tail;
- *tail = temp;
- }
-}
-
-static bool EnterMuuid(const char *p, MUUID &result)
-{
- if (*p++ != '{')
- return false;
-
- uint8_t *d = (uint8_t*)&result;
-
- for (int nBytes = 0; *p && nBytes < 24; p++) {
- if (*p == '-')
- continue;
-
- if (*p == '}')
- break;
-
- if (!isxdigit(*p))
- return false;
-
- if (!isxdigit(p[1]))
- return false;
-
- int c = 0;
- if (sscanf(p, "%2x", &c) != 1)
- return false;
-
- *d++ = (uint8_t)c;
- nBytes++;
- p++;
- }
-
- if (*p != '}')
- return false;
-
- swapBytes(&result.a, sizeof(result.a));
- swapBytes(&result.b, sizeof(result.b));
- swapBytes(&result.c, sizeof(result.c));
- return true;
-}
-
-static void LoadLangPackFile(FILE *fp, char *line)
-{
- while (!feof(fp)) {
- if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr)
- break;
-
- if (IsEmpty(line) || line[0] == ';' || line[0] == 0)
- continue;
-
- rtrim(line);
-
- if (line[0] == '#') {
- strlwr(line);
-
- if (!memcmp(line + 1, "include", 7)) {
- wchar_t tszFileName[MAX_PATH];
- wchar_t *p = wcsrchr(langPack.tszFullPath, '\\');
- if (p)
- *p = 0;
- mir_snwprintf(tszFileName, L"%s\\%S", langPack.tszFullPath, ltrim(line + 9));
- if (p)
- *p = '\\';
-
- FILE *fpNew = _wfopen(tszFileName, L"r");
- if (fpNew) {
- line[0] = 0;
- fgets(line, LANGPACK_BUF_SIZE, fpNew);
-
- if (strlen(line) >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf')
- fseek(fpNew, 3, SEEK_SET);
- else
- fseek(fpNew, 0, SEEK_SET);
-
- LoadLangPackFile(fpNew, line);
- fclose(fpNew);
- }
- }
- else if (!memcmp(line + 1, "muuid", 5)) {
- MUUID t;
- if (!EnterMuuid(line + 7, t))
- continue;
-
- MUUID *pNew = (MUUID*)mir_alloc(sizeof(MUUID));
- memcpy(pNew, &t, sizeof(t));
- lMuuids.insert(pNew);
- pCurrentMuuid = pNew;
- }
-
- continue;
- }
-
- char cFirst = line[0];
-
- ConvertBackslashes(line, CP_UTF8);
-
- size_t cbLen = strlen(line) - 1;
- if (cFirst == '[' && line[cbLen] == ']') {
- if (g_entryCount && g_pEntries[g_entryCount-1].wszLocal == nullptr)
- g_entryCount--;
-
- char *pszLine = line + 1;
- line[cbLen] = '\0';
- if (++g_entryCount > g_entriesAlloced) {
- g_entriesAlloced += 128;
- g_pEntries = (LangPackEntry*)mir_realloc(g_pEntries, sizeof(LangPackEntry)*g_entriesAlloced);
- }
-
- LangPackEntry *E = &g_pEntries[g_entryCount - 1];
- E->englishHash = mir_hashstr(pszLine);
- E->szLocal = E->utfLocal = nullptr;
- E->wszLocal = nullptr;
- E->pMuuid = pCurrentMuuid;
- E->pNext = nullptr;
- continue;
- }
-
- if (!g_entryCount)
- continue;
-
- LangPackEntry *E = &g_pEntries[g_entryCount - 1];
- int iNeeded = MultiByteToWideChar(CP_UTF8, 0, line, -1, nullptr, 0), iOldLen;
- if (E->wszLocal == nullptr) {
- iOldLen = 0;
- E->wszLocal = (wchar_t *)mir_alloc((iNeeded + 1) * sizeof(wchar_t));
- MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal, iNeeded);
- }
- else {
- iOldLen = (int)wcslen(E->wszLocal);
- E->wszLocal = (wchar_t*)mir_realloc(E->wszLocal, (sizeof(wchar_t)* (iOldLen + iNeeded + 2)));
- E->wszLocal[iOldLen++] = '\n';
- }
- MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal + iOldLen, iNeeded);
- }
-}
-
-static int LoadLangDescr(LANGPACK_INFO &lpinfo, FILE *fp, char *line, int &startOfLine)
-{
- char szLanguage[64]; szLanguage[0] = 0;
- CMStringA szAuthors;
-
- lpinfo.codepage = CP_ACP;
- lpinfo.flags = 0;
- lpinfo.tszLanguage[0] = 0;
-
- fgets(line, LANGPACK_BUF_SIZE, fp);
- size_t lineLen = strlen(line);
- if (lineLen >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf')
- memmove(line, line + 3, lineLen - 2);
-
- lrtrim(line);
- if (mir_strcmp(line, "Miranda Language Pack Version 1"))
- return 2;
-
- // headers
- while (!feof(fp)) {
- startOfLine = ftell(fp);
- if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr)
- break;
-
- lrtrim(line);
- if (IsEmpty(line) || line[0] == ';' || line[0] == 0)
- continue;
-
- if (line[0] == '[' || line[0] == '#')
- break;
-
- char *pszColon = strchr(line, ':');
- if (pszColon == nullptr)
- return 3;
-
- *pszColon++ = 0;
- if (!mir_strcmp(line, "Language")) {
- strncpy_s(szLanguage, pszColon, _TRUNCATE);
- lrtrim(szLanguage);
- }
- else if (!mir_strcmp(line, "Last-Modified-Using")) {
- lpinfo.szLastModifiedUsing = pszColon;
- lpinfo.szLastModifiedUsing.Trim();
- }
- else if (!mir_strcmp(line, "Authors")) {
- if (!szAuthors.IsEmpty())
- szAuthors.AppendChar(' ');
- szAuthors.Append(lrtrim(pszColon));
- }
- else if (!mir_strcmp(line, "Locale")) {
- char szBuf[20], *stopped;
-
- lrtrim(pszColon + 1);
- USHORT langID = (USHORT)strtol(pszColon, &stopped, 16);
- lpinfo.Locale = MAKELCID(langID, 0);
- GetLocaleInfoA(lpinfo.Locale, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10);
- szBuf[5] = 0; // codepages have max. 5 digits
- lpinfo.codepage = atoi(szBuf);
- }
- }
-
- lpinfo.szAuthors = szAuthors;
-
- ptrW buf(mir_utf8decodeW(szLanguage));
- if (buf)
- wcsncpy_s(lpinfo.tszLanguage, buf, _TRUNCATE);
- else if (lpinfo.Locale != 0)
- GetLocaleInfo(lpinfo.Locale, LOCALE_SENGLANGUAGE, lpinfo.tszLanguage, _countof(lpinfo.tszLanguage));
-
- if (!lpinfo.tszLanguage[0]) {
- wchar_t *p = wcschr(lpinfo.tszFileName, '_');
- wcsncpy_s(lpinfo.tszLanguage, ((p != nullptr) ? (p + 1) : lpinfo.tszFileName), _TRUNCATE);
- p = wcsrchr(lpinfo.tszLanguage, '.');
- if (p != nullptr) *p = '\0';
- }
- return 0;
-}
-
-MIR_CORE_DLL(int) LoadLangPack(const wchar_t *ptszLangPack)
-{
- if (ptszLangPack == nullptr || !mir_wstrcmpi(ptszLangPack, L""))
- return 1;
-
- // ensure that a lang's name is a full file name
- wchar_t tszFullPath[MAX_PATH];
- if (!PathIsAbsoluteW(ptszLangPack))
- mir_snwprintf(tszFullPath, L"%s\\%s", g_tszRoot, ptszLangPack);
- else
- wcsncpy_s(tszFullPath, ptszLangPack, _TRUNCATE);
-
- // this lang is already loaded? nothing to do then
- if (!mir_wstrcmp(tszFullPath, langPack.tszFullPath))
- return 0;
-
- // ok... loading a new langpack. remove the old one if needed
- if (g_entryCount)
- UnloadLangPackModule();
-
- langPack.Locale = 0;
- langPack.codepage = CP_ACP;
- langPack.flags = 0;
-
- // exists & not a directory?
- uint32_t dwAttrib = GetFileAttributes(tszFullPath);
- if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
- return 3;
-
- // copy the full file name and extract a file name from it
- wcsncpy_s(langPack.tszFullPath, tszFullPath, _TRUNCATE);
- wchar_t *p = wcsrchr(langPack.tszFullPath, '\\');
- wcsncpy_s(langPack.tszFileName, (p == nullptr) ? tszFullPath : p + 1, _TRUNCATE);
- CharLower(langPack.tszFileName);
-
- FILE *fp = _wfopen(tszFullPath, L"rt");
- if (fp == nullptr)
- return 1;
-
- char line[LANGPACK_BUF_SIZE] = "";
- int startOfLine = 0;
- if (LoadLangDescr(langPack, fp, line, startOfLine)) {
- fclose(fp);
- return 1;
- }
-
- // body
- fseek(fp, startOfLine, SEEK_SET);
-
- LoadLangPackFile(fp, line);
- fclose(fp);
- pCurrentMuuid = nullptr;
-
- qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc);
- return 0;
-}
-
-MIR_CORE_DLL(int) LoadLangPackDescr(const wchar_t *ptszLangPack, LANGPACK_INFO *lpInfo)
-{
- if (lpInfo == nullptr)
- return 1;
-
- wcsncpy_s(lpInfo->tszFullPath, ptszLangPack, _TRUNCATE);
- wchar_t *p = wcsrchr(lpInfo->tszFullPath, '\\');
- wcsncpy_s(lpInfo->tszFileName, (p == nullptr) ? ptszLangPack : p+1, _TRUNCATE);
- CharLower(lpInfo->tszFileName);
-
- FILE *fp = _wfopen(ptszLangPack, L"rt");
- if (fp == nullptr)
- return 1;
-
- char line[LANGPACK_BUF_SIZE] = "";
- int startOfLine = 0;
- int res = LoadLangDescr(*lpInfo, fp, line, startOfLine);
- fclose(fp);
- return res;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static int SortLangPackHashesProc2(LangPackEntry *arg1, LangPackEntry *arg2)
-{
- if (arg1->englishHash < arg2->englishHash) return -1;
- if (arg1->englishHash > arg2->englishHash) return 1;
- return 0;
-}
-
-char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W)
-{
- if (g_entryCount == 0 || szEnglish == nullptr)
- return (char*)szEnglish;
-
- LangPackEntry key, *entry;
- key.englishHash = (W == 1) ? hashstrW(szEnglish) : mir_hashstr(szEnglish);
- entry = (LangPackEntry*)bsearch(&key, g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc2);
- if (entry == nullptr)
- return (char*)szEnglish;
-
- // try to find the exact match, otherwise the first entry will be returned
- if (pUuid) {
- for (LangPackEntry *p = entry->pNext; p != nullptr; p = p->pNext) {
- if (p->pMuuid && *p->pMuuid == *pUuid) {
- entry = p;
- break;
- }
- }
- }
-
- switch (W) {
- case 0:
- if (entry->szLocal == nullptr && entry->wszLocal != nullptr)
- entry->szLocal = mir_u2a_cp(entry->wszLocal, langPack.codepage);
- return entry->szLocal;
-
- case 1:
- return (char*)entry->wszLocal;
-
- case 2:
- if (entry->utfLocal == nullptr && entry->wszLocal != nullptr)
- entry->utfLocal = mir_utf8encodeW(entry->wszLocal);
- return entry->utfLocal;
- }
-
- return nullptr;
-}
-
-MIR_CORE_DLL(int) Langpack_GetDefaultCodePage()
-{
- return langPack.codepage;
-}
-
-MIR_CORE_DLL(int) Langpack_GetDefaultLocale()
-{
- return (langPack.Locale == 0) ? LOCALE_USER_DEFAULT : langPack.Locale;
-}
-
-MIR_CORE_DLL(wchar_t*) Langpack_PcharToTchar(const char *pszStr)
-{
- if (pszStr == nullptr)
- return nullptr;
-
- int len = (int)strlen(pszStr);
- wchar_t *result = (wchar_t*)alloca((len + 1)*sizeof(wchar_t));
- MultiByteToWideChar(Langpack_GetDefaultCodePage(), 0, pszStr, -1, result, len);
- result[len] = 0;
- return mir_wstrdup(TranslateW_LP(result));
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(char*) TranslateA_LP(const char *str, HPLUGIN pPlugin)
-{
- return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 0);
-}
-
-MIR_CORE_DLL(char*) TranslateU_LP(const char *str, HPLUGIN pPlugin)
-{
- return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 2);
-}
-
-MIR_CORE_DLL(wchar_t*) TranslateW_LP(const wchar_t *str, HPLUGIN pPlugin)
-{
- return (wchar_t*)LangPackTranslateString(GetMuid(pPlugin), (LPCSTR)str, 1);
-}
-
-MIR_CORE_DLL(void) TranslateMenu_LP(HMENU hMenu, HPLUGIN pPlugin)
-{
- const MUUID *uuid = &pPlugin->getInfo().uuid;
-
- MENUITEMINFO mii = { 0 };
- mii.cbSize = sizeof(mii);
-
- for (int i = GetMenuItemCount(hMenu) - 1; i >= 0; i--) {
- wchar_t str[256];
- mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
- mii.dwTypeData = (wchar_t*)str;
- mii.cch = _countof(str);
- GetMenuItemInfo(hMenu, i, TRUE, &mii);
-
- if (mii.cch && mii.dwTypeData) {
- wchar_t *result = (wchar_t*)LangPackTranslateString(uuid, (const char*)mii.dwTypeData, TRUE);
- if (result != mii.dwTypeData) {
- mii.dwTypeData = result;
- mii.fMask = MIIM_TYPE;
- SetMenuItemInfo(hMenu, i, TRUE, &mii);
- }
- }
-
- if (mii.hSubMenu != nullptr)
- TranslateMenu_LP(mii.hSubMenu, pPlugin);
- }
-}
-
-static void TranslateWindow(const MUUID *pUuid, HWND hwnd)
-{
- wchar_t title[2048];
- GetWindowText(hwnd, title, _countof(title));
-
- wchar_t *result = (wchar_t*)LangPackTranslateString(pUuid, (const char*)title, TRUE);
- if (result != title)
- SetWindowText(hwnd, result);
-}
-
-static BOOL CALLBACK TranslateDialogEnumProc(HWND hwnd, LPARAM lParam)
-{
- HPLUGIN pPlugin = (HPLUGIN)lParam;
- const MUUID *uuid = GetMuid(pPlugin);
-
- wchar_t szClass[32];
- GetClassName(hwnd, szClass, _countof(szClass));
- if (!mir_wstrcmpi(szClass, L"static") || !mir_wstrcmpi(szClass, L"hyperlink") || !mir_wstrcmpi(szClass, L"button") || !mir_wstrcmpi(szClass, L"MButtonClass") || !mir_wstrcmpi(szClass, L"MHeaderbarCtrl"))
- TranslateWindow(uuid, hwnd);
- else if (!mir_wstrcmpi(szClass, L"edit")) {
- if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY)
- TranslateWindow(uuid, hwnd);
- }
- return TRUE;
-}
-
-MIR_CORE_DLL(void) TranslateDialog_LP(HWND hDlg, HPLUGIN pPlugin)
-{
- TranslateWindow(GetMuid(pPlugin), hDlg);
- EnumChildWindows(hDlg, TranslateDialogEnumProc, (LPARAM)pPlugin);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) Langpack_SortDuplicates(void)
-{
- if (g_entryCount == 0)
- return;
-
- LangPackEntry *s = g_pEntries + 1, *d = s, *pLast = g_pEntries;
- uint32_t dwSavedHash = g_pEntries->englishHash;
- bool bSortNeeded = false;
-
- for (int i = 1; i < g_entryCount; i++, s++) {
- if (s->englishHash != dwSavedHash) {
- pLast = d;
- if (s != d)
- *d++ = *s;
- else
- d++;
- dwSavedHash = s->englishHash;
- }
- else {
- bSortNeeded = true;
- LangPackEntry *p = (LangPackEntry*)mir_alloc(sizeof(LangPackEntry));
- *p = *s;
- pLast->pNext = p; pLast = p;
- }
- }
-
- if (bSortNeeded) {
- g_entryCount = (int)(d - g_pEntries);
- qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc);
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void GetDefaultLang()
-{
- // calculate the langpacks' root
- PathToAbsoluteW(L"\\Languages", g_tszRoot);
- if (_waccess(g_tszRoot, 0) != 0) // directory Languages exists
- PathToAbsoluteW(L".", g_tszRoot);
-
- // look into mirandaboot.ini
- wchar_t tszLangName[256];
- Profile_GetSetting(L"Language/DefaultLanguage", tszLangName);
- if (tszLangName[0]) {
- if (!mir_wstrcmpi(tszLangName, L"default")) {
- db_set_ws(0, "Langpack", "Current", L"default");
- return;
- }
- if (!LoadLangPack(tszLangName)) {
- db_set_ws(0, "Langpack", "Current", tszLangName);
- return;
- }
- }
-
- // try to load langpack that matches UserDefaultUILanguage
- wchar_t tszPath[MAX_PATH];
- if (GetLocaleInfo(MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT), LOCALE_SENGLANGUAGE, tszLangName, _countof(tszLangName))) {
- mir_snwprintf(tszPath, L"langpack_%s.txt", wcslwr(tszLangName));
- if (!LoadLangPack(tszPath)) {
- db_set_ws(0, "Langpack", "Current", tszPath);
- return;
- }
- }
-
- // finally try to load first file
- mir_snwprintf(tszPath, L"%s\\langpack_*.txt", g_tszRoot);
-
- WIN32_FIND_DATA fd;
- HANDLE hFind = FindFirstFile(tszPath, &fd);
- if (hFind != INVALID_HANDLE_VALUE) {
- do {
- /* search first langpack that could be loaded */
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- continue;
-
- if (!LoadLangPack(fd.cFileName)) {
- db_set_ws(0, "Langpack", "Current", fd.cFileName);
- break;
- }
- } while (FindNextFile(hFind, &fd));
- FindClose(hFind);
- }
- else db_set_ws(0, "Langpack", "Current", L"default");
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) ReloadLangpack(wchar_t *pszStr)
-{
- if (pszStr == nullptr)
- pszStr = NEWWSTR_ALLOCA(langPack.tszFileName);
-
- UnloadLangPackModule();
- LoadLangPack(pszStr);
- Langpack_SortDuplicates();
-
- NotifyEventHooks(hevChanged, 0, 0);
-}
-
-static INT_PTR srvReloadLangpack(WPARAM, LPARAM lParam)
-{
- ReloadLangpack((wchar_t*)lParam);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) LoadLangPackModule(void)
-{
- bModuleInitialized = TRUE;
- hevChanged = CreateHookableEvent(ME_LANGPACK_CHANGED);
- CreateServiceFunction(MS_LANGPACK_RELOAD, srvReloadLangpack);
- GetDefaultLang();
- return 0;
-}
-
-void UnloadLangPackModule()
-{
- if (!bModuleInitialized) return;
-
- for (auto &it : lMuuids)
- mir_free(it);
- lMuuids.destroy();
-
- LangPackEntry *p = g_pEntries;
- for (int i = 0; i < g_entryCount; i++, p++) {
- if (p->pNext != nullptr) {
- for (LangPackEntry *p1 = p->pNext; p1 != nullptr;) {
- LangPackEntry *p2 = p1; p1 = p1->pNext;
- mir_free(p2->szLocal);
- mir_free(p2->wszLocal);
- mir_free(p2);
- }
- }
-
- mir_free(p->szLocal);
- mir_free(p->wszLocal);
- }
-
- if (g_entryCount) {
- mir_free(g_pEntries);
- g_pEntries = nullptr;
- g_entryCount = g_entriesAlloced = 0;
- }
-
- langPack.tszFileName[0] = langPack.tszFullPath[0] = 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+#include "../../../mir_app/src/langpack.h"
+
+#define LANGPACK_BUF_SIZE 4000
+
+static int CompareMuuids(const MUUID *p1, const MUUID *p2)
+{
+ return memcmp(p1, p2, sizeof(MUUID));
+}
+
+static LIST<MUUID> lMuuids(10, CompareMuuids);
+static MUUID *pCurrentMuuid = nullptr;
+static HANDLE hevChanged = nullptr;
+
+static BOOL bModuleInitialized = FALSE;
+
+struct LangPackEntry
+{
+ uint32_t englishHash;
+ char *szLocal;
+ char *utfLocal;
+ wchar_t *wszLocal;
+ MUUID *pMuuid;
+ LangPackEntry* pNext; // for langpack items with the same hash value
+};
+
+static LANGPACK_INFO langPack;
+static wchar_t g_tszRoot[MAX_PATH];
+
+static LangPackEntry *g_pEntries;
+static int g_entryCount, g_entriesAlloced;
+
+static int IsEmpty(const char *str)
+{
+ for (int i = 0; str[i]; i++)
+ if (str[i] != ' ' && str[i] != '\r' && str[i] != '\n')
+ return 0;
+
+ return 1;
+}
+
+static int ConvertBackslashes(char *str, UINT fileCp)
+{
+ int shift = 0;
+ char *pstr;
+ for (pstr = str; *pstr; pstr = CharNextExA(fileCp, pstr, 0)) {
+ if (*pstr == '\\') {
+ shift++;
+ switch (pstr[1]) {
+ case 'n': *pstr = '\n'; break;
+ case 't': *pstr = '\t'; break;
+ case 'r': *pstr = '\r'; break;
+ case 's': *pstr = ' '; break;
+ default: *pstr = pstr[1]; break;
+ }
+ memmove(pstr + 1, pstr + 2, strlen(pstr + 2) + 1);
+ }
+ }
+ return shift;
+}
+
+#ifdef _DEBUG
+//#pragma optimize("gt", on)
+#endif
+
+// MurmurHash2
+MIR_CORE_DLL(unsigned int) mir_hash(const void * key, unsigned int len)
+{
+ // 'm' and 'r' are mixing constants generated offline.
+ // They're not really 'magic', they just happen to work well.
+ const unsigned int m = 0x5bd1e995;
+ const int r = 24;
+
+ // Initialize the hash to a 'random' value
+ unsigned int h = len;
+
+ // Mix 4 bytes at a time into the hash
+ const unsigned char *data = (const unsigned char*)key;
+
+ while (len >= 4) {
+ unsigned int k = *(unsigned int*)data;
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h *= m;
+ h ^= k;
+
+ data += 4;
+ len -= 4;
+ }
+
+ // Handle the last few bytes of the input array
+ switch (len) {
+ case 3: h ^= data[2] << 16;
+ case 2: h ^= data[1] << 8;
+ case 1: h ^= data[0];
+ h *= m;
+ }
+
+ // Do a few final mixes of the hash to ensure the last few
+ // bytes are well-incorporated.
+ h ^= h >> 13;
+ h *= m;
+ h ^= h >> 15;
+
+ return h;
+}
+
+static unsigned int __fastcall hashstrW(const char *key)
+{
+ if (key == nullptr) return 0;
+ const unsigned int len = (unsigned int)wcslen((const wchar_t*)key);
+ char *buf = (char*)alloca(len + 1);
+ for (unsigned i = 0; i <= len; ++i)
+ buf[i] = key[i << 1];
+ return mir_hash(buf, len);
+}
+
+static const MUUID* GetMuid(HPLUGIN pPlugin)
+{
+ if (!pPlugin)
+ return nullptr;
+
+ __try {
+ return &pPlugin->getInfo().uuid;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ return nullptr;
+ }
+}
+
+static int SortLangPackHashesProc(LangPackEntry *arg1, LangPackEntry *arg2)
+{
+ if (arg1->englishHash < arg2->englishHash) return -1;
+ if (arg1->englishHash > arg2->englishHash) return 1;
+
+ return (arg1->pMuuid < arg2->pMuuid) ? -1 : 1;
+}
+
+static void swapBytes(void *p, size_t iSize)
+{
+ char *head = (char*)p; // here
+ char *tail = head + iSize - 1;
+
+ for (; tail > head; --tail, ++head) {
+ char temp = *head;
+ *head = *tail;
+ *tail = temp;
+ }
+}
+
+static bool EnterMuuid(const char *p, MUUID &result)
+{
+ if (*p++ != '{')
+ return false;
+
+ uint8_t *d = (uint8_t*)&result;
+
+ for (int nBytes = 0; *p && nBytes < 24; p++) {
+ if (*p == '-')
+ continue;
+
+ if (*p == '}')
+ break;
+
+ if (!isxdigit(*p))
+ return false;
+
+ if (!isxdigit(p[1]))
+ return false;
+
+ int c = 0;
+ if (sscanf(p, "%2x", &c) != 1)
+ return false;
+
+ *d++ = (uint8_t)c;
+ nBytes++;
+ p++;
+ }
+
+ if (*p != '}')
+ return false;
+
+ swapBytes(&result.a, sizeof(result.a));
+ swapBytes(&result.b, sizeof(result.b));
+ swapBytes(&result.c, sizeof(result.c));
+ return true;
+}
+
+static void LoadLangPackFile(FILE *fp, char *line)
+{
+ while (!feof(fp)) {
+ if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr)
+ break;
+
+ if (IsEmpty(line) || line[0] == ';' || line[0] == 0)
+ continue;
+
+ rtrim(line);
+
+ if (line[0] == '#') {
+ strlwr(line);
+
+ if (!memcmp(line + 1, "include", 7)) {
+ wchar_t tszFileName[MAX_PATH];
+ wchar_t *p = wcsrchr(langPack.tszFullPath, '\\');
+ if (p)
+ *p = 0;
+ mir_snwprintf(tszFileName, L"%s\\%S", langPack.tszFullPath, ltrim(line + 9));
+ if (p)
+ *p = '\\';
+
+ FILE *fpNew = _wfopen(tszFileName, L"r");
+ if (fpNew) {
+ line[0] = 0;
+ fgets(line, LANGPACK_BUF_SIZE, fpNew);
+
+ if (strlen(line) >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf')
+ fseek(fpNew, 3, SEEK_SET);
+ else
+ fseek(fpNew, 0, SEEK_SET);
+
+ LoadLangPackFile(fpNew, line);
+ fclose(fpNew);
+ }
+ }
+ else if (!memcmp(line + 1, "muuid", 5)) {
+ MUUID t;
+ if (!EnterMuuid(line + 7, t))
+ continue;
+
+ MUUID *pNew = (MUUID*)mir_alloc(sizeof(MUUID));
+ memcpy(pNew, &t, sizeof(t));
+ lMuuids.insert(pNew);
+ pCurrentMuuid = pNew;
+ }
+
+ continue;
+ }
+
+ char cFirst = line[0];
+
+ ConvertBackslashes(line, CP_UTF8);
+
+ size_t cbLen = strlen(line) - 1;
+ if (cFirst == '[' && line[cbLen] == ']') {
+ if (g_entryCount && g_pEntries[g_entryCount-1].wszLocal == nullptr)
+ g_entryCount--;
+
+ char *pszLine = line + 1;
+ line[cbLen] = '\0';
+ if (++g_entryCount > g_entriesAlloced) {
+ g_entriesAlloced += 128;
+ g_pEntries = (LangPackEntry*)mir_realloc(g_pEntries, sizeof(LangPackEntry)*g_entriesAlloced);
+ }
+
+ LangPackEntry *E = &g_pEntries[g_entryCount - 1];
+ E->englishHash = mir_hashstr(pszLine);
+ E->szLocal = E->utfLocal = nullptr;
+ E->wszLocal = nullptr;
+ E->pMuuid = pCurrentMuuid;
+ E->pNext = nullptr;
+ continue;
+ }
+
+ if (!g_entryCount)
+ continue;
+
+ LangPackEntry *E = &g_pEntries[g_entryCount - 1];
+ int iNeeded = MultiByteToWideChar(CP_UTF8, 0, line, -1, nullptr, 0), iOldLen;
+ if (E->wszLocal == nullptr) {
+ iOldLen = 0;
+ E->wszLocal = (wchar_t *)mir_alloc((iNeeded + 1) * sizeof(wchar_t));
+ MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal, iNeeded);
+ }
+ else {
+ iOldLen = (int)wcslen(E->wszLocal);
+ E->wszLocal = (wchar_t*)mir_realloc(E->wszLocal, (sizeof(wchar_t)* (iOldLen + iNeeded + 2)));
+ E->wszLocal[iOldLen++] = '\n';
+ }
+ MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal + iOldLen, iNeeded);
+ }
+}
+
+static int LoadLangDescr(LANGPACK_INFO &lpinfo, FILE *fp, char *line, int &startOfLine)
+{
+ char szLanguage[64]; szLanguage[0] = 0;
+ CMStringA szAuthors;
+
+ lpinfo.codepage = CP_ACP;
+ lpinfo.flags = 0;
+ lpinfo.tszLanguage[0] = 0;
+
+ fgets(line, LANGPACK_BUF_SIZE, fp);
+ size_t lineLen = strlen(line);
+ if (lineLen >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf')
+ memmove(line, line + 3, lineLen - 2);
+
+ lrtrim(line);
+ if (mir_strcmp(line, "Miranda Language Pack Version 1"))
+ return 2;
+
+ // headers
+ while (!feof(fp)) {
+ startOfLine = ftell(fp);
+ if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr)
+ break;
+
+ lrtrim(line);
+ if (IsEmpty(line) || line[0] == ';' || line[0] == 0)
+ continue;
+
+ if (line[0] == '[' || line[0] == '#')
+ break;
+
+ char *pszColon = strchr(line, ':');
+ if (pszColon == nullptr)
+ return 3;
+
+ *pszColon++ = 0;
+ if (!mir_strcmp(line, "Language")) {
+ strncpy_s(szLanguage, pszColon, _TRUNCATE);
+ lrtrim(szLanguage);
+ }
+ else if (!mir_strcmp(line, "Last-Modified-Using")) {
+ lpinfo.szLastModifiedUsing = pszColon;
+ lpinfo.szLastModifiedUsing.Trim();
+ }
+ else if (!mir_strcmp(line, "Authors")) {
+ if (!szAuthors.IsEmpty())
+ szAuthors.AppendChar(' ');
+ szAuthors.Append(lrtrim(pszColon));
+ }
+ else if (!mir_strcmp(line, "Locale")) {
+ char szBuf[20], *stopped;
+
+ lrtrim(pszColon + 1);
+ USHORT langID = (USHORT)strtol(pszColon, &stopped, 16);
+ lpinfo.Locale = MAKELCID(langID, 0);
+ GetLocaleInfoA(lpinfo.Locale, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10);
+ szBuf[5] = 0; // codepages have max. 5 digits
+ lpinfo.codepage = atoi(szBuf);
+ }
+ }
+
+ lpinfo.szAuthors = szAuthors;
+
+ ptrW buf(mir_utf8decodeW(szLanguage));
+ if (buf)
+ wcsncpy_s(lpinfo.tszLanguage, buf, _TRUNCATE);
+ else if (lpinfo.Locale != 0)
+ GetLocaleInfo(lpinfo.Locale, LOCALE_SENGLANGUAGE, lpinfo.tszLanguage, _countof(lpinfo.tszLanguage));
+
+ if (!lpinfo.tszLanguage[0]) {
+ wchar_t *p = wcschr(lpinfo.tszFileName, '_');
+ wcsncpy_s(lpinfo.tszLanguage, ((p != nullptr) ? (p + 1) : lpinfo.tszFileName), _TRUNCATE);
+ p = wcsrchr(lpinfo.tszLanguage, '.');
+ if (p != nullptr) *p = '\0';
+ }
+ return 0;
+}
+
+MIR_CORE_DLL(int) LoadLangPack(const wchar_t *ptszLangPack)
+{
+ if (ptszLangPack == nullptr || !mir_wstrcmpi(ptszLangPack, L""))
+ return 1;
+
+ // ensure that a lang's name is a full file name
+ wchar_t tszFullPath[MAX_PATH];
+ if (!PathIsAbsoluteW(ptszLangPack))
+ mir_snwprintf(tszFullPath, L"%s\\%s", g_tszRoot, ptszLangPack);
+ else
+ wcsncpy_s(tszFullPath, ptszLangPack, _TRUNCATE);
+
+ // this lang is already loaded? nothing to do then
+ if (!mir_wstrcmp(tszFullPath, langPack.tszFullPath))
+ return 0;
+
+ // ok... loading a new langpack. remove the old one if needed
+ if (g_entryCount)
+ UnloadLangPackModule();
+
+ langPack.Locale = 0;
+ langPack.codepage = CP_ACP;
+ langPack.flags = 0;
+
+ // exists & not a directory?
+ uint32_t dwAttrib = GetFileAttributes(tszFullPath);
+ if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
+ return 3;
+
+ // copy the full file name and extract a file name from it
+ wcsncpy_s(langPack.tszFullPath, tszFullPath, _TRUNCATE);
+ wchar_t *p = wcsrchr(langPack.tszFullPath, '\\');
+ wcsncpy_s(langPack.tszFileName, (p == nullptr) ? tszFullPath : p + 1, _TRUNCATE);
+ CharLower(langPack.tszFileName);
+
+ FILE *fp = _wfopen(tszFullPath, L"rt");
+ if (fp == nullptr)
+ return 1;
+
+ char line[LANGPACK_BUF_SIZE] = "";
+ int startOfLine = 0;
+ if (LoadLangDescr(langPack, fp, line, startOfLine)) {
+ fclose(fp);
+ return 1;
+ }
+
+ // body
+ fseek(fp, startOfLine, SEEK_SET);
+
+ LoadLangPackFile(fp, line);
+ fclose(fp);
+ pCurrentMuuid = nullptr;
+
+ qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc);
+ return 0;
+}
+
+MIR_CORE_DLL(int) LoadLangPackDescr(const wchar_t *ptszLangPack, LANGPACK_INFO *lpInfo)
+{
+ if (lpInfo == nullptr)
+ return 1;
+
+ wcsncpy_s(lpInfo->tszFullPath, ptszLangPack, _TRUNCATE);
+ wchar_t *p = wcsrchr(lpInfo->tszFullPath, '\\');
+ wcsncpy_s(lpInfo->tszFileName, (p == nullptr) ? ptszLangPack : p+1, _TRUNCATE);
+ CharLower(lpInfo->tszFileName);
+
+ FILE *fp = _wfopen(ptszLangPack, L"rt");
+ if (fp == nullptr)
+ return 1;
+
+ char line[LANGPACK_BUF_SIZE] = "";
+ int startOfLine = 0;
+ int res = LoadLangDescr(*lpInfo, fp, line, startOfLine);
+ fclose(fp);
+ return res;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int SortLangPackHashesProc2(LangPackEntry *arg1, LangPackEntry *arg2)
+{
+ if (arg1->englishHash < arg2->englishHash) return -1;
+ if (arg1->englishHash > arg2->englishHash) return 1;
+ return 0;
+}
+
+char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W)
+{
+ if (g_entryCount == 0 || szEnglish == nullptr)
+ return (char*)szEnglish;
+
+ LangPackEntry key, *entry;
+ key.englishHash = (W == 1) ? hashstrW(szEnglish) : mir_hashstr(szEnglish);
+ entry = (LangPackEntry*)bsearch(&key, g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc2);
+ if (entry == nullptr)
+ return (char*)szEnglish;
+
+ // try to find the exact match, otherwise the first entry will be returned
+ if (pUuid) {
+ for (LangPackEntry *p = entry->pNext; p != nullptr; p = p->pNext) {
+ if (p->pMuuid && *p->pMuuid == *pUuid) {
+ entry = p;
+ break;
+ }
+ }
+ }
+
+ switch (W) {
+ case 0:
+ if (entry->szLocal == nullptr && entry->wszLocal != nullptr)
+ entry->szLocal = mir_u2a_cp(entry->wszLocal, langPack.codepage);
+ return entry->szLocal;
+
+ case 1:
+ return (char*)entry->wszLocal;
+
+ case 2:
+ if (entry->utfLocal == nullptr && entry->wszLocal != nullptr)
+ entry->utfLocal = mir_utf8encodeW(entry->wszLocal);
+ return entry->utfLocal;
+ }
+
+ return nullptr;
+}
+
+MIR_CORE_DLL(int) Langpack_GetDefaultCodePage()
+{
+ return langPack.codepage;
+}
+
+MIR_CORE_DLL(int) Langpack_GetDefaultLocale()
+{
+ return (langPack.Locale == 0) ? LOCALE_USER_DEFAULT : langPack.Locale;
+}
+
+MIR_CORE_DLL(wchar_t*) Langpack_PcharToTchar(const char *pszStr)
+{
+ if (pszStr == nullptr)
+ return nullptr;
+
+ int len = (int)strlen(pszStr);
+ wchar_t *result = (wchar_t*)alloca((len + 1)*sizeof(wchar_t));
+ MultiByteToWideChar(Langpack_GetDefaultCodePage(), 0, pszStr, -1, result, len);
+ result[len] = 0;
+ return mir_wstrdup(TranslateW_LP(result));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(char*) TranslateA_LP(const char *str, HPLUGIN pPlugin)
+{
+ return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 0);
+}
+
+MIR_CORE_DLL(char*) TranslateU_LP(const char *str, HPLUGIN pPlugin)
+{
+ return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 2);
+}
+
+MIR_CORE_DLL(wchar_t*) TranslateW_LP(const wchar_t *str, HPLUGIN pPlugin)
+{
+ return (wchar_t*)LangPackTranslateString(GetMuid(pPlugin), (LPCSTR)str, 1);
+}
+
+MIR_CORE_DLL(void) TranslateMenu_LP(HMENU hMenu, HPLUGIN pPlugin)
+{
+ const MUUID *uuid = &pPlugin->getInfo().uuid;
+
+ MENUITEMINFO mii = { 0 };
+ mii.cbSize = sizeof(mii);
+
+ for (int i = GetMenuItemCount(hMenu) - 1; i >= 0; i--) {
+ wchar_t str[256];
+ mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
+ mii.dwTypeData = (wchar_t*)str;
+ mii.cch = _countof(str);
+ GetMenuItemInfo(hMenu, i, TRUE, &mii);
+
+ if (mii.cch && mii.dwTypeData) {
+ wchar_t *result = (wchar_t*)LangPackTranslateString(uuid, (const char*)mii.dwTypeData, TRUE);
+ if (result != mii.dwTypeData) {
+ mii.dwTypeData = result;
+ mii.fMask = MIIM_TYPE;
+ SetMenuItemInfo(hMenu, i, TRUE, &mii);
+ }
+ }
+
+ if (mii.hSubMenu != nullptr)
+ TranslateMenu_LP(mii.hSubMenu, pPlugin);
+ }
+}
+
+static void TranslateWindow(const MUUID *pUuid, HWND hwnd)
+{
+ wchar_t title[2048];
+ GetWindowText(hwnd, title, _countof(title));
+
+ wchar_t *result = (wchar_t*)LangPackTranslateString(pUuid, (const char*)title, TRUE);
+ if (result != title)
+ SetWindowText(hwnd, result);
+}
+
+static BOOL CALLBACK TranslateDialogEnumProc(HWND hwnd, LPARAM lParam)
+{
+ HPLUGIN pPlugin = (HPLUGIN)lParam;
+ const MUUID *uuid = GetMuid(pPlugin);
+
+ wchar_t szClass[32];
+ GetClassName(hwnd, szClass, _countof(szClass));
+ if (!mir_wstrcmpi(szClass, L"static") || !mir_wstrcmpi(szClass, L"hyperlink") || !mir_wstrcmpi(szClass, L"button") || !mir_wstrcmpi(szClass, L"MButtonClass") || !mir_wstrcmpi(szClass, L"MHeaderbarCtrl"))
+ TranslateWindow(uuid, hwnd);
+ else if (!mir_wstrcmpi(szClass, L"edit")) {
+ if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY)
+ TranslateWindow(uuid, hwnd);
+ }
+ return TRUE;
+}
+
+MIR_CORE_DLL(void) TranslateDialog_LP(HWND hDlg, HPLUGIN pPlugin)
+{
+ TranslateWindow(GetMuid(pPlugin), hDlg);
+ EnumChildWindows(hDlg, TranslateDialogEnumProc, (LPARAM)pPlugin);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(void) Langpack_SortDuplicates(void)
+{
+ if (g_entryCount == 0)
+ return;
+
+ LangPackEntry *s = g_pEntries + 1, *d = s, *pLast = g_pEntries;
+ uint32_t dwSavedHash = g_pEntries->englishHash;
+ bool bSortNeeded = false;
+
+ for (int i = 1; i < g_entryCount; i++, s++) {
+ if (s->englishHash != dwSavedHash) {
+ pLast = d;
+ if (s != d)
+ *d++ = *s;
+ else
+ d++;
+ dwSavedHash = s->englishHash;
+ }
+ else {
+ bSortNeeded = true;
+ LangPackEntry *p = (LangPackEntry*)mir_alloc(sizeof(LangPackEntry));
+ *p = *s;
+ pLast->pNext = p; pLast = p;
+ }
+ }
+
+ if (bSortNeeded) {
+ g_entryCount = (int)(d - g_pEntries);
+ qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void GetDefaultLang()
+{
+ // calculate the langpacks' root
+ PathToAbsoluteW(L"\\Languages", g_tszRoot);
+ if (_waccess(g_tszRoot, 0) != 0) // directory Languages exists
+ PathToAbsoluteW(L".", g_tszRoot);
+
+ // look into mirandaboot.ini
+ wchar_t tszLangName[256];
+ Profile_GetSetting(L"Language/DefaultLanguage", tszLangName);
+ if (tszLangName[0]) {
+ if (!mir_wstrcmpi(tszLangName, L"default")) {
+ db_set_ws(0, "Langpack", "Current", L"default");
+ return;
+ }
+ if (!LoadLangPack(tszLangName)) {
+ db_set_ws(0, "Langpack", "Current", tszLangName);
+ return;
+ }
+ }
+
+ // try to load langpack that matches UserDefaultUILanguage
+ wchar_t tszPath[MAX_PATH];
+ if (GetLocaleInfo(MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT), LOCALE_SENGLANGUAGE, tszLangName, _countof(tszLangName))) {
+ mir_snwprintf(tszPath, L"langpack_%s.txt", wcslwr(tszLangName));
+ if (!LoadLangPack(tszPath)) {
+ db_set_ws(0, "Langpack", "Current", tszPath);
+ return;
+ }
+ }
+
+ // finally try to load first file
+ mir_snwprintf(tszPath, L"%s\\langpack_*.txt", g_tszRoot);
+
+ WIN32_FIND_DATA fd;
+ HANDLE hFind = FindFirstFile(tszPath, &fd);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ /* search first langpack that could be loaded */
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ if (!LoadLangPack(fd.cFileName)) {
+ db_set_ws(0, "Langpack", "Current", fd.cFileName);
+ break;
+ }
+ } while (FindNextFile(hFind, &fd));
+ FindClose(hFind);
+ }
+ else db_set_ws(0, "Langpack", "Current", L"default");
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(void) ReloadLangpack(wchar_t *pszStr)
+{
+ if (pszStr == nullptr)
+ pszStr = NEWWSTR_ALLOCA(langPack.tszFileName);
+
+ UnloadLangPackModule();
+ LoadLangPack(pszStr);
+ Langpack_SortDuplicates();
+
+ NotifyEventHooks(hevChanged, 0, 0);
+}
+
+static INT_PTR srvReloadLangpack(WPARAM, LPARAM lParam)
+{
+ ReloadLangpack((wchar_t*)lParam);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) LoadLangPackModule(void)
+{
+ bModuleInitialized = TRUE;
+ hevChanged = CreateHookableEvent(ME_LANGPACK_CHANGED);
+ CreateServiceFunction(MS_LANGPACK_RELOAD, srvReloadLangpack);
+ GetDefaultLang();
+ return 0;
+}
+
+void UnloadLangPackModule()
+{
+ if (!bModuleInitialized) return;
+
+ for (auto &it : lMuuids)
+ mir_free(it);
+ lMuuids.destroy();
+
+ LangPackEntry *p = g_pEntries;
+ for (int i = 0; i < g_entryCount; i++, p++) {
+ if (p->pNext != nullptr) {
+ for (LangPackEntry *p1 = p->pNext; p1 != nullptr;) {
+ LangPackEntry *p2 = p1; p1 = p1->pNext;
+ mir_free(p2->szLocal);
+ mir_free(p2->wszLocal);
+ mir_free(p2);
+ }
+ }
+
+ mir_free(p->szLocal);
+ mir_free(p->wszLocal);
+ }
+
+ if (g_entryCount) {
+ mir_free(g_pEntries);
+ g_pEntries = nullptr;
+ g_entryCount = g_entriesAlloced = 0;
+ }
+
+ langPack.tszFileName[0] = langPack.tszFullPath[0] = 0;
+}
diff --git a/src/mir_core/src/Windows/locks.cpp b/src/mir_core/src/Windows/locks.cpp
index 88f4639e80..dca0e98966 100644
--- a/src/mir_core/src/Windows/locks.cpp
+++ b/src/mir_core/src/Windows/locks.cpp
@@ -1,46 +1,46 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-
-mir_cs::mir_cs()
-{
- ::InitializeCriticalSection(&m_cs);
-}
-
-mir_cs::~mir_cs()
-{
- ::DeleteCriticalSection(&m_cs);
-}
-
-void mir_cs::Lock()
-{
- while (::TryEnterCriticalSection(&m_cs) == 0)
- SleepEx(50, TRUE);
-}
-
-void mir_cs::Unlock()
-{
- ::LeaveCriticalSection(&m_cs);
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+mir_cs::mir_cs()
+{
+ ::InitializeCriticalSection(&m_cs);
+}
+
+mir_cs::~mir_cs()
+{
+ ::DeleteCriticalSection(&m_cs);
+}
+
+void mir_cs::Lock()
+{
+ while (::TryEnterCriticalSection(&m_cs) == 0)
+ SleepEx(50, TRUE);
+}
+
+void mir_cs::Unlock()
+{
+ ::LeaveCriticalSection(&m_cs);
+}
diff --git a/src/mir_core/src/Windows/miranda.cpp b/src/mir_core/src/Windows/miranda.cpp
index d13e69ff1f..ce52b20b0b 100644
--- a/src/mir_core/src/Windows/miranda.cpp
+++ b/src/mir_core/src/Windows/miranda.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/mir_core/src/Windows/openurl.cpp b/src/mir_core/src/Windows/openurl.cpp
index 3a9a3d2024..4bb8310e75 100644
--- a/src/mir_core/src/Windows/openurl.cpp
+++ b/src/mir_core/src/Windows/openurl.cpp
@@ -1,76 +1,76 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-#include <ctype.h>
-
-struct TOpenUrlInfo
-{
- TOpenUrlInfo(wchar_t *_url, int _bNew) :
- szUrl(_url),
- newWindow(_bNew)
- {}
-
- ptrW szUrl;
- int newWindow;
-};
-
-static void __cdecl OpenURLThread(TOpenUrlInfo *hUrlInfo)
-{
- // wack a protocol on it
- CMStringW tszUrl;
- if ((isalpha(hUrlInfo->szUrl[0]) && hUrlInfo->szUrl[1] == ':') || hUrlInfo->szUrl[0] == '\\')
- tszUrl.Format(L"file:///%s", hUrlInfo->szUrl.get());
- else {
- int i;
- for (i = 0; iswalpha(hUrlInfo->szUrl[i]); i++);
- if (hUrlInfo->szUrl[i] == ':')
- tszUrl = hUrlInfo->szUrl;
- else if (!wcsnicmp(hUrlInfo->szUrl, L"ftp.", 4))
- tszUrl.Format(L"ftp://%s", hUrlInfo->szUrl.get());
- else
- tszUrl.Format(L"http://%s", hUrlInfo->szUrl.get());
- }
-
- // check user defined browser for opening urls
- ptrW tszBrowser(db_get_wsa(0, "Miranda", "OpenUrlBrowser"));
- if (tszBrowser)
- ShellExecute(nullptr, L"open", tszBrowser, tszUrl, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT);
- else
- ShellExecute(nullptr, L"open", tszUrl, nullptr, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT);
-
- delete hUrlInfo;
-}
-
-MIR_CORE_DLL(void) Utils_OpenUrl(const char *pszUrl, bool bOpenInNewWindow)
-{
- if (pszUrl)
- mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_a2u(pszUrl), bOpenInNewWindow));
-}
-
-MIR_CORE_DLL(void) Utils_OpenUrlW(const wchar_t *pszUrl, bool bOpenInNewWindow)
-{
- if (pszUrl)
- mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_wstrdup(pszUrl), bOpenInNewWindow));
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+#include <ctype.h>
+
+struct TOpenUrlInfo
+{
+ TOpenUrlInfo(wchar_t *_url, int _bNew) :
+ szUrl(_url),
+ newWindow(_bNew)
+ {}
+
+ ptrW szUrl;
+ int newWindow;
+};
+
+static void __cdecl OpenURLThread(TOpenUrlInfo *hUrlInfo)
+{
+ // wack a protocol on it
+ CMStringW tszUrl;
+ if ((isalpha(hUrlInfo->szUrl[0]) && hUrlInfo->szUrl[1] == ':') || hUrlInfo->szUrl[0] == '\\')
+ tszUrl.Format(L"file:///%s", hUrlInfo->szUrl.get());
+ else {
+ int i;
+ for (i = 0; iswalpha(hUrlInfo->szUrl[i]); i++);
+ if (hUrlInfo->szUrl[i] == ':')
+ tszUrl = hUrlInfo->szUrl;
+ else if (!wcsnicmp(hUrlInfo->szUrl, L"ftp.", 4))
+ tszUrl.Format(L"ftp://%s", hUrlInfo->szUrl.get());
+ else
+ tszUrl.Format(L"http://%s", hUrlInfo->szUrl.get());
+ }
+
+ // check user defined browser for opening urls
+ ptrW tszBrowser(db_get_wsa(0, "Miranda", "OpenUrlBrowser"));
+ if (tszBrowser)
+ ShellExecute(nullptr, L"open", tszBrowser, tszUrl, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT);
+ else
+ ShellExecute(nullptr, L"open", tszUrl, nullptr, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT);
+
+ delete hUrlInfo;
+}
+
+MIR_CORE_DLL(void) Utils_OpenUrl(const char *pszUrl, bool bOpenInNewWindow)
+{
+ if (pszUrl)
+ mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_a2u(pszUrl), bOpenInNewWindow));
+}
+
+MIR_CORE_DLL(void) Utils_OpenUrlW(const wchar_t *pszUrl, bool bOpenInNewWindow)
+{
+ if (pszUrl)
+ mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_wstrdup(pszUrl), bOpenInNewWindow));
+}
diff --git a/src/mir_core/src/Windows/path.cpp b/src/mir_core/src/Windows/path.cpp
index 5623ad416f..eb14c6b0de 100644
--- a/src/mir_core/src/Windows/path.cpp
+++ b/src/mir_core/src/Windows/path.cpp
@@ -1,246 +1,246 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-
-static char szMirandaPath[MAX_PATH];
-static wchar_t szMirandaPathW[MAX_PATH];
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) PathIsAbsolute(const char *path)
-{
- if (path && strlen(path) > 2)
- if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
- return 1;
- return 0;
-}
-
-MIR_CORE_DLL(int) PathToRelative(const char *pSrc, char *pOut, const char *pBase)
-{
- if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) {
- *pOut = 0;
- return 0;
- }
-
- if (!PathIsAbsolute(pSrc))
- strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- else {
- if (pBase == nullptr)
- pBase = szMirandaPath;
-
- size_t cbBaseLen = strlen(pBase);
- if (!strnicmp(pSrc, pBase, cbBaseLen))
- strncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE);
- else
- strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- }
-
- return (int)strlen(pOut);
-}
-
-MIR_CORE_DLL(int) PathToAbsolute(const char *pSrc, char *pOut, const char *base)
-{
- if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) {
- *pOut = 0;
- return 0;
- }
-
- char buf[MAX_PATH];
- if (pSrc[0] < ' ')
- strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
-
- if (PathIsAbsolute(pSrc))
- return GetFullPathNameA(pSrc, MAX_PATH, pOut, nullptr);
-
- if (base == nullptr)
- base = szMirandaPath;
-
- if (pSrc[0] == '\\')
- pSrc++;
- mir_snprintf(buf, "%s%s", base, pSrc);
- return GetFullPathNameA(buf, _countof(buf), pOut, nullptr);
-}
-
-MIR_CORE_DLL(int) CreatePathToFile(const char *szFilePath)
-{
- if (szFilePath == nullptr)
- return ERROR_INVALID_PARAMETER;
-
- char *buf = NEWSTR_ALLOCA(szFilePath);
- char *p = strrchr(buf, '\\');
- if (p == nullptr)
- return 0;
-
- *p = '\0';
- return CreateDirectoryTree(buf);
-}
-
-MIR_CORE_DLL(int) CreateDirectoryTree(const char *szDir)
-{
- if (szDir == nullptr)
- return 1;
-
- uint32_t dwAttributes = GetFileAttributesA(szDir);
- if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
- return 0;
-
- char szTestDir[MAX_PATH];
- mir_strncpy(szTestDir, szDir, _countof(szTestDir));
- char *pszLastBackslash = strrchr(szTestDir, '\\');
- if (pszLastBackslash == nullptr)
- return 0;
-
- *pszLastBackslash = '\0';
- CreateDirectoryTree(szTestDir);
- *pszLastBackslash = '\\';
- return (CreateDirectoryA(szTestDir, nullptr) == 0) ? GetLastError() : 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) PathIsAbsoluteW(const wchar_t *path)
-{
- if (path && wcslen(path) > 2)
- if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
- return 1;
- return 0;
-}
-
-MIR_CORE_DLL(int) PathToRelativeW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *pBase)
-{
- if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH)
- return 0;
-
- if (!PathIsAbsoluteW(pSrc))
- wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- else {
- if (pBase == nullptr)
- pBase = szMirandaPathW;
-
- size_t cbBaseLen = wcslen(pBase);
- if (!wcsnicmp(pSrc, pBase, cbBaseLen))
- wcsncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE);
- else
- wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- }
- return (int)wcslen(pOut);
-}
-
-MIR_CORE_DLL(int) PathToAbsoluteW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *base)
-{
- if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH) {
- *pOut = 0;
- return 0;
- }
-
- wchar_t buf[MAX_PATH];
- if (pSrc[0] < ' ')
- return mir_snwprintf(pOut, MAX_PATH, L"%s", pSrc);
-
- if (PathIsAbsoluteW(pSrc))
- return GetFullPathName(pSrc, MAX_PATH, pOut, nullptr);
-
- if (base == nullptr)
- base = szMirandaPathW;
-
- if (pSrc[0] == '\\')
- pSrc++;
-
- mir_snwprintf(buf, MAX_PATH, L"%s%s", base, pSrc);
- return GetFullPathName(buf, MAX_PATH, pOut, nullptr);
-}
-
-MIR_CORE_DLL(int) CreatePathToFileW(const wchar_t *wszFilePath)
-{
- if (wszFilePath == nullptr)
- return ERROR_INVALID_PARAMETER;
-
- wchar_t *buf = NEWWSTR_ALLOCA(wszFilePath);
- wchar_t *p = wcsrchr(buf, '\\');
- if (p == nullptr)
- return 0;
-
- *p = '\0';
- return CreateDirectoryTreeW(buf);
-}
-
-MIR_CORE_DLL(int) CreateDirectoryTreeW(const wchar_t *szDir)
-{
- if (szDir == nullptr)
- return 1;
-
- uint32_t dwAttributes = GetFileAttributesW(szDir);
- if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
- return 0;
-
- wchar_t szTestDir[MAX_PATH];
- mir_wstrncpy(szTestDir, szDir, _countof(szTestDir));
- wchar_t *pszLastBackslash = wcsrchr(szTestDir, '\\');
- if (pszLastBackslash == nullptr)
- return 0;
-
- *pszLastBackslash = '\0';
- CreateDirectoryTreeW(szTestDir);
- *pszLastBackslash = '\\';
- return (CreateDirectoryW(szTestDir, nullptr) == 0) ? GetLastError() : 0;
-}
-
-MIR_CORE_DLL(int) DeleteDirectoryTreeW(const wchar_t *pwszDir, bool bAllowUndo)
-{
- if (pwszDir == nullptr)
- return ERROR_BAD_ARGUMENTS;
-
- CMStringW wszPath(pwszDir);
- wszPath.AppendChar(0);
-
- SHFILEOPSTRUCTW file_op = {
- nullptr,
- FO_DELETE,
- wszPath,
- L"",
- FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION,
- false,
- nullptr,
- L"" };
-
- if (bAllowUndo)
- file_op.fFlags |= FOF_ALLOWUNDO;
-
- return SHFileOperationW(&file_op);
-}
-
-int InitPathUtils(void)
-{
- GetModuleFileNameA(nullptr, szMirandaPath, _countof(szMirandaPath));
- char *p = strrchr(szMirandaPath, '\\');
- if (p)
- p[1] = 0;
-
- GetModuleFileNameW(nullptr, szMirandaPathW, _countof(szMirandaPathW));
- wchar_t *tp = wcsrchr(szMirandaPathW, '\\');
- if (tp)
- tp[1] = 0;
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+static char szMirandaPath[MAX_PATH];
+static wchar_t szMirandaPathW[MAX_PATH];
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) PathIsAbsolute(const char *path)
+{
+ if (path && strlen(path) > 2)
+ if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
+ return 1;
+ return 0;
+}
+
+MIR_CORE_DLL(int) PathToRelative(const char *pSrc, char *pOut, const char *pBase)
+{
+ if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) {
+ *pOut = 0;
+ return 0;
+ }
+
+ if (!PathIsAbsolute(pSrc))
+ strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
+ else {
+ if (pBase == nullptr)
+ pBase = szMirandaPath;
+
+ size_t cbBaseLen = strlen(pBase);
+ if (!strnicmp(pSrc, pBase, cbBaseLen))
+ strncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE);
+ else
+ strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
+ }
+
+ return (int)strlen(pOut);
+}
+
+MIR_CORE_DLL(int) PathToAbsolute(const char *pSrc, char *pOut, const char *base)
+{
+ if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) {
+ *pOut = 0;
+ return 0;
+ }
+
+ char buf[MAX_PATH];
+ if (pSrc[0] < ' ')
+ strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
+
+ if (PathIsAbsolute(pSrc))
+ return GetFullPathNameA(pSrc, MAX_PATH, pOut, nullptr);
+
+ if (base == nullptr)
+ base = szMirandaPath;
+
+ if (pSrc[0] == '\\')
+ pSrc++;
+ mir_snprintf(buf, "%s%s", base, pSrc);
+ return GetFullPathNameA(buf, _countof(buf), pOut, nullptr);
+}
+
+MIR_CORE_DLL(int) CreatePathToFile(const char *szFilePath)
+{
+ if (szFilePath == nullptr)
+ return ERROR_INVALID_PARAMETER;
+
+ char *buf = NEWSTR_ALLOCA(szFilePath);
+ char *p = strrchr(buf, '\\');
+ if (p == nullptr)
+ return 0;
+
+ *p = '\0';
+ return CreateDirectoryTree(buf);
+}
+
+MIR_CORE_DLL(int) CreateDirectoryTree(const char *szDir)
+{
+ if (szDir == nullptr)
+ return 1;
+
+ uint32_t dwAttributes = GetFileAttributesA(szDir);
+ if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ return 0;
+
+ char szTestDir[MAX_PATH];
+ mir_strncpy(szTestDir, szDir, _countof(szTestDir));
+ char *pszLastBackslash = strrchr(szTestDir, '\\');
+ if (pszLastBackslash == nullptr)
+ return 0;
+
+ *pszLastBackslash = '\0';
+ CreateDirectoryTree(szTestDir);
+ *pszLastBackslash = '\\';
+ return (CreateDirectoryA(szTestDir, nullptr) == 0) ? GetLastError() : 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) PathIsAbsoluteW(const wchar_t *path)
+{
+ if (path && wcslen(path) > 2)
+ if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
+ return 1;
+ return 0;
+}
+
+MIR_CORE_DLL(int) PathToRelativeW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *pBase)
+{
+ if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH)
+ return 0;
+
+ if (!PathIsAbsoluteW(pSrc))
+ wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
+ else {
+ if (pBase == nullptr)
+ pBase = szMirandaPathW;
+
+ size_t cbBaseLen = wcslen(pBase);
+ if (!wcsnicmp(pSrc, pBase, cbBaseLen))
+ wcsncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE);
+ else
+ wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
+ }
+ return (int)wcslen(pOut);
+}
+
+MIR_CORE_DLL(int) PathToAbsoluteW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *base)
+{
+ if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH) {
+ *pOut = 0;
+ return 0;
+ }
+
+ wchar_t buf[MAX_PATH];
+ if (pSrc[0] < ' ')
+ return mir_snwprintf(pOut, MAX_PATH, L"%s", pSrc);
+
+ if (PathIsAbsoluteW(pSrc))
+ return GetFullPathName(pSrc, MAX_PATH, pOut, nullptr);
+
+ if (base == nullptr)
+ base = szMirandaPathW;
+
+ if (pSrc[0] == '\\')
+ pSrc++;
+
+ mir_snwprintf(buf, MAX_PATH, L"%s%s", base, pSrc);
+ return GetFullPathName(buf, MAX_PATH, pOut, nullptr);
+}
+
+MIR_CORE_DLL(int) CreatePathToFileW(const wchar_t *wszFilePath)
+{
+ if (wszFilePath == nullptr)
+ return ERROR_INVALID_PARAMETER;
+
+ wchar_t *buf = NEWWSTR_ALLOCA(wszFilePath);
+ wchar_t *p = wcsrchr(buf, '\\');
+ if (p == nullptr)
+ return 0;
+
+ *p = '\0';
+ return CreateDirectoryTreeW(buf);
+}
+
+MIR_CORE_DLL(int) CreateDirectoryTreeW(const wchar_t *szDir)
+{
+ if (szDir == nullptr)
+ return 1;
+
+ uint32_t dwAttributes = GetFileAttributesW(szDir);
+ if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ return 0;
+
+ wchar_t szTestDir[MAX_PATH];
+ mir_wstrncpy(szTestDir, szDir, _countof(szTestDir));
+ wchar_t *pszLastBackslash = wcsrchr(szTestDir, '\\');
+ if (pszLastBackslash == nullptr)
+ return 0;
+
+ *pszLastBackslash = '\0';
+ CreateDirectoryTreeW(szTestDir);
+ *pszLastBackslash = '\\';
+ return (CreateDirectoryW(szTestDir, nullptr) == 0) ? GetLastError() : 0;
+}
+
+MIR_CORE_DLL(int) DeleteDirectoryTreeW(const wchar_t *pwszDir, bool bAllowUndo)
+{
+ if (pwszDir == nullptr)
+ return ERROR_BAD_ARGUMENTS;
+
+ CMStringW wszPath(pwszDir);
+ wszPath.AppendChar(0);
+
+ SHFILEOPSTRUCTW file_op = {
+ nullptr,
+ FO_DELETE,
+ wszPath,
+ L"",
+ FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION,
+ false,
+ nullptr,
+ L"" };
+
+ if (bAllowUndo)
+ file_op.fFlags |= FOF_ALLOWUNDO;
+
+ return SHFileOperationW(&file_op);
+}
+
+int InitPathUtils(void)
+{
+ GetModuleFileNameA(nullptr, szMirandaPath, _countof(szMirandaPath));
+ char *p = strrchr(szMirandaPath, '\\');
+ if (p)
+ p[1] = 0;
+
+ GetModuleFileNameW(nullptr, szMirandaPathW, _countof(szMirandaPathW));
+ wchar_t *tp = wcsrchr(szMirandaPathW, '\\');
+ if (tp)
+ tp[1] = 0;
+ return 0;
+}
diff --git a/src/mir_core/src/Windows/resizer.cpp b/src/mir_core/src/Windows/resizer.cpp
index 3b5de46fcc..519659a27f 100644
--- a/src/mir_core/src/Windows/resizer.cpp
+++ b/src/mir_core/src/Windows/resizer.cpp
@@ -1,151 +1,151 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-
-#pragma pack(2)
-
-struct START_OF_DLGITEMTEMPLATEEX
-{
- uint32_t helpID;
- uint32_t exStyle;
- uint32_t style;
- short x, y, cx, cy;
- uint32_t id;
-};
-
-struct START_OF_DLGTEMPLATEEX
-{
- uint16_t dlgVer;
- uint16_t signature;
- uint32_t helpID;
- uint32_t exStyle;
- uint32_t style;
- uint16_t cDlgItems;
- short x, y, cx, cy;
-};
-
-MIR_CORE_DLL(int) Utils_ResizeDialog(HWND hwndDlg, HINSTANCE hInstance, LPCSTR lpTemplate, DIALOGRESIZERPROC pfnResizer, LPARAM lParam)
-{
- DLGTEMPLATE *pTemplate = (DLGTEMPLATE*)LockResource(LoadResource(hInstance, FindResourceA(hInstance, lpTemplate, MAKEINTRESOURCEA(5))));
- START_OF_DLGTEMPLATEEX *pTemplateEx = (START_OF_DLGTEMPLATEEX*)pTemplate;
- int extendedDlg = pTemplateEx->signature == 0xFFFF;
- if (extendedDlg && pTemplateEx->dlgVer != 1)
- return 1;
-
- PWORD pWord = (extendedDlg) ? (PWORD)(pTemplateEx + 1) : (PWORD)(pTemplate + 1);
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class
- while (*pWord++); // skip title
- if (extendedDlg) {
- if (pTemplateEx->style & DS_SETFONT) {
- pWord += 3; // font size, weight, italic
- while (*pWord++); // font name
- }
- }
- else {
- if (pTemplate->style & DS_SETFONT) {
- pWord++; // font size
- while (*pWord++); // font name
- }
- }
-
- UTILRESIZECONTROL urc;
- urc.cbSize = sizeof(UTILRESIZECONTROL);
-
- RECT rc;
- rc.left = 0; rc.top = 0;
- if (extendedDlg) {
- rc.right = pTemplateEx->cx;
- rc.bottom = pTemplateEx->cy;
- }
- else {
- rc.right = pTemplate->cx;
- rc.bottom = pTemplate->cy;
- }
-
- MapDialogRect(hwndDlg, &rc);
- urc.dlgOriginalSize.cx = rc.right; urc.dlgOriginalSize.cy = rc.bottom;
- GetClientRect(hwndDlg, &rc);
- urc.dlgNewSize.cx = rc.right; urc.dlgNewSize.cy = rc.bottom;
-
- int itemCount = (extendedDlg) ? pTemplateEx->cDlgItems : pTemplate->cdit;
-
- HDWP hDwp = BeginDeferWindowPos(itemCount);
- for (int i = 0; i < itemCount; i++) {
- if ((UINT_PTR)pWord & 2) pWord++; //dword align
-
- if (extendedDlg) {
- START_OF_DLGITEMTEMPLATEEX *pItemEx = (START_OF_DLGITEMTEMPLATEEX*)pWord;
- pWord = (PWORD)(pItemEx + 1);
-
- urc.wId = pItemEx->id;
- urc.rcItem.left = pItemEx->x; urc.rcItem.top = pItemEx->y;
- urc.rcItem.right = urc.rcItem.left + pItemEx->cx; urc.rcItem.bottom = urc.rcItem.top + pItemEx->cy;
- }
- else {
- DLGITEMTEMPLATE *pItem = (DLGITEMTEMPLATE*)pWord;
- pWord = (PWORD)(pItem + 1);
-
- urc.wId = pItem->id;
- urc.rcItem.left = pItem->x; urc.rcItem.top = pItem->y;
- urc.rcItem.right = urc.rcItem.left + pItem->cx; urc.rcItem.bottom = urc.rcItem.top + pItem->cy;
- }
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class
- pWord += 1 + (1 + *pWord) / 2; //creation data
-
- if (urc.wId == 65535) // using this breaks the dwp, so just ignore it
- continue;
-
- MapDialogRect(hwndDlg, &urc.rcItem);
- int procResult = (pfnResizer)(hwndDlg, lParam, &urc);
- if (procResult & RD_ANCHORX_RIGHT) {
- urc.rcItem.left += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
- urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
- }
- else if (procResult & RD_ANCHORX_WIDTH)
- urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
- else if (procResult & RD_ANCHORX_CENTRE) {
- urc.rcItem.left += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2;
- urc.rcItem.right += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2;
- }
- if (procResult & RD_ANCHORY_BOTTOM) {
- urc.rcItem.top += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
- urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
- }
- else if (procResult & RD_ANCHORY_HEIGHT)
- urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
- else if (procResult & RD_ANCHORY_CENTRE) {
- urc.rcItem.top += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2;
- urc.rcItem.bottom += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2;
- }
-
- HWND hCtrl = GetDlgItem(hwndDlg, urc.wId);
- if (hCtrl != nullptr && urc.wId != UINT(-1))
- hDwp = DeferWindowPos(hDwp, hCtrl, nullptr, urc.rcItem.left, urc.rcItem.top, urc.rcItem.right - urc.rcItem.left, urc.rcItem.bottom - urc.rcItem.top, SWP_NOZORDER);
- }
- EndDeferWindowPos(hDwp);
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+#pragma pack(2)
+
+struct START_OF_DLGITEMTEMPLATEEX
+{
+ uint32_t helpID;
+ uint32_t exStyle;
+ uint32_t style;
+ short x, y, cx, cy;
+ uint32_t id;
+};
+
+struct START_OF_DLGTEMPLATEEX
+{
+ uint16_t dlgVer;
+ uint16_t signature;
+ uint32_t helpID;
+ uint32_t exStyle;
+ uint32_t style;
+ uint16_t cDlgItems;
+ short x, y, cx, cy;
+};
+
+MIR_CORE_DLL(int) Utils_ResizeDialog(HWND hwndDlg, HINSTANCE hInstance, LPCSTR lpTemplate, DIALOGRESIZERPROC pfnResizer, LPARAM lParam)
+{
+ DLGTEMPLATE *pTemplate = (DLGTEMPLATE*)LockResource(LoadResource(hInstance, FindResourceA(hInstance, lpTemplate, MAKEINTRESOURCEA(5))));
+ START_OF_DLGTEMPLATEEX *pTemplateEx = (START_OF_DLGTEMPLATEEX*)pTemplate;
+ int extendedDlg = pTemplateEx->signature == 0xFFFF;
+ if (extendedDlg && pTemplateEx->dlgVer != 1)
+ return 1;
+
+ PWORD pWord = (extendedDlg) ? (PWORD)(pTemplateEx + 1) : (PWORD)(pTemplate + 1);
+ if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu
+ if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class
+ while (*pWord++); // skip title
+ if (extendedDlg) {
+ if (pTemplateEx->style & DS_SETFONT) {
+ pWord += 3; // font size, weight, italic
+ while (*pWord++); // font name
+ }
+ }
+ else {
+ if (pTemplate->style & DS_SETFONT) {
+ pWord++; // font size
+ while (*pWord++); // font name
+ }
+ }
+
+ UTILRESIZECONTROL urc;
+ urc.cbSize = sizeof(UTILRESIZECONTROL);
+
+ RECT rc;
+ rc.left = 0; rc.top = 0;
+ if (extendedDlg) {
+ rc.right = pTemplateEx->cx;
+ rc.bottom = pTemplateEx->cy;
+ }
+ else {
+ rc.right = pTemplate->cx;
+ rc.bottom = pTemplate->cy;
+ }
+
+ MapDialogRect(hwndDlg, &rc);
+ urc.dlgOriginalSize.cx = rc.right; urc.dlgOriginalSize.cy = rc.bottom;
+ GetClientRect(hwndDlg, &rc);
+ urc.dlgNewSize.cx = rc.right; urc.dlgNewSize.cy = rc.bottom;
+
+ int itemCount = (extendedDlg) ? pTemplateEx->cDlgItems : pTemplate->cdit;
+
+ HDWP hDwp = BeginDeferWindowPos(itemCount);
+ for (int i = 0; i < itemCount; i++) {
+ if ((UINT_PTR)pWord & 2) pWord++; //dword align
+
+ if (extendedDlg) {
+ START_OF_DLGITEMTEMPLATEEX *pItemEx = (START_OF_DLGITEMTEMPLATEEX*)pWord;
+ pWord = (PWORD)(pItemEx + 1);
+
+ urc.wId = pItemEx->id;
+ urc.rcItem.left = pItemEx->x; urc.rcItem.top = pItemEx->y;
+ urc.rcItem.right = urc.rcItem.left + pItemEx->cx; urc.rcItem.bottom = urc.rcItem.top + pItemEx->cy;
+ }
+ else {
+ DLGITEMTEMPLATE *pItem = (DLGITEMTEMPLATE*)pWord;
+ pWord = (PWORD)(pItem + 1);
+
+ urc.wId = pItem->id;
+ urc.rcItem.left = pItem->x; urc.rcItem.top = pItem->y;
+ urc.rcItem.right = urc.rcItem.left + pItem->cx; urc.rcItem.bottom = urc.rcItem.top + pItem->cy;
+ }
+ if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu
+ if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class
+ pWord += 1 + (1 + *pWord) / 2; //creation data
+
+ if (urc.wId == 65535) // using this breaks the dwp, so just ignore it
+ continue;
+
+ MapDialogRect(hwndDlg, &urc.rcItem);
+ int procResult = (pfnResizer)(hwndDlg, lParam, &urc);
+ if (procResult & RD_ANCHORX_RIGHT) {
+ urc.rcItem.left += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
+ urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
+ }
+ else if (procResult & RD_ANCHORX_WIDTH)
+ urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
+ else if (procResult & RD_ANCHORX_CENTRE) {
+ urc.rcItem.left += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2;
+ urc.rcItem.right += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2;
+ }
+ if (procResult & RD_ANCHORY_BOTTOM) {
+ urc.rcItem.top += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
+ urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
+ }
+ else if (procResult & RD_ANCHORY_HEIGHT)
+ urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
+ else if (procResult & RD_ANCHORY_CENTRE) {
+ urc.rcItem.top += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2;
+ urc.rcItem.bottom += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2;
+ }
+
+ HWND hCtrl = GetDlgItem(hwndDlg, urc.wId);
+ if (hCtrl != nullptr && urc.wId != UINT(-1))
+ hDwp = DeferWindowPos(hDwp, hCtrl, nullptr, urc.rcItem.left, urc.rcItem.top, urc.rcItem.right - urc.rcItem.left, urc.rcItem.bottom - urc.rcItem.top, SWP_NOZORDER);
+ }
+ EndDeferWindowPos(hDwp);
+ return 0;
+}
diff --git a/src/mir_core/src/Windows/subclass.cpp b/src/mir_core/src/Windows/subclass.cpp
index ecc56206af..8ca02d78e3 100644
--- a/src/mir_core/src/Windows/subclass.cpp
+++ b/src/mir_core/src/Windows/subclass.cpp
@@ -1,201 +1,201 @@
-/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "../stdafx.h"
-
-struct MSubclassData
-{
- HWND m_hWnd;
-
- int m_iHooks;
- WNDPROC *m_hooks;
- WNDPROC m_origWndProc;
-
- ~MSubclassData()
- {
- free(m_hooks);
- }
-};
-
-static LIST<MSubclassData> arSubclass(10, HandleKeySortT);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static LRESULT CALLBACK MSubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hwnd);
- if (p != nullptr) {
- if (p->m_iHooks)
- return p->m_hooks[p->m_iHooks-1](hwnd, uMsg, wParam, lParam);
-
- return p->m_origWndProc(hwnd, uMsg, wParam, lParam);
- }
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// This is for wine: it return wrong WNDPROC for edit control in some cases.
-#ifdef WIN64
-#define STD_WND_PROC_ADDR_MASK 0x7FFF00000
-#else
-#define STD_WND_PROC_ADDR_MASK 0xFFFF0000
-#endif
-
-MIR_CORE_DLL(void) mir_subclassWindow(HWND hWnd, WNDPROC wndProc)
-{
- if (hWnd == nullptr)
- return;
-
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr) {
- p = new MSubclassData;
- p->m_hWnd = hWnd;
- p->m_origWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
- if (((SIZE_T)p->m_origWndProc & STD_WND_PROC_ADDR_MASK) == STD_WND_PROC_ADDR_MASK) { /* XXX: fix me. Wine fix. */
- p->m_origWndProc = (WNDPROC)GetClassLongPtr(hWnd, GCLP_WNDPROC);
- if (((SIZE_T)p->m_origWndProc & 0x7FFF0000) == 0x7FFF0000) /* Delay crash. */
- p->m_origWndProc = DefWindowProc;
- }
- p->m_iHooks = 0;
- p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC));
- arSubclass.insert(p);
- }
- else {
- for (int i=0; i < p->m_iHooks; i++)
- if (p->m_hooks[i] == wndProc)
- return;
-
- void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));
- if (tmp == nullptr)
- return;
-
- p->m_hooks = (WNDPROC *)tmp;
- }
-
- p->m_hooks[p->m_iHooks++] = wndProc;
-}
-
-MIR_CORE_DLL(void) mir_subclassWindowFull(HWND hWnd, WNDPROC wndProc, WNDPROC oldWndProc)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr) {
- p = new MSubclassData;
- p->m_hWnd = hWnd;
- p->m_origWndProc = oldWndProc;
- p->m_iHooks = 0;
- p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC));
- arSubclass.insert(p);
-
- SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
- }
- else {
- for (int i=0; i < p->m_iHooks; i++)
- if (p->m_hooks[i] == wndProc)
- return;
-
- void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));
- if (tmp == nullptr)
- return;
-
- p->m_hooks = (WNDPROC *)tmp;
- }
-
- p->m_hooks[p->m_iHooks++] = wndProc;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void removeHook(MSubclassData *p, int idx)
-{
- // untie hook from a window to prevent calling mir_callNextSubclass from saveProc
- for (int i = idx + 1; i < p->m_iHooks; i++)
- p->m_hooks[i-1] = p->m_hooks[i];
- p->m_iHooks--;
-}
-
-static WNDPROC finalizeSubclassing(HWND hWnd, MSubclassData *p)
-{
- WNDPROC saveProc = p->m_origWndProc;
- arSubclass.remove(p);
- delete p;
-
- SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)saveProc);
- return saveProc;
-}
-
-MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd, WNDPROC wndProc)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr)
- return;
-
- for (int i = 0; i < p->m_iHooks; i++) {
- if (p->m_hooks[i] == wndProc) {
- removeHook(p, i);
- i--;
- }
- }
-
- if (p->m_iHooks == 0)
- finalizeSubclassing(hWnd, p);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(LRESULT) mir_callNextSubclass(HWND hWnd, WNDPROC wndProc, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr)
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
-
- for (int i = p->m_iHooks - 1; i >= 0; i--) {
- if (p->m_hooks[i] != wndProc)
- continue;
-
- // next hook exists, call it
- if (i != 0)
- return p->m_hooks[i-1](hWnd, uMsg, wParam, lParam);
-
- // last hook called, ping the default window procedure
- if (uMsg != WM_NCDESTROY)
- return p->m_origWndProc(hWnd, uMsg, wParam, lParam);
-
- WNDPROC saveProc = finalizeSubclassing(hWnd, p);
- return saveProc(hWnd, uMsg, wParam, lParam);
- }
-
- // invalid / closed hook
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst)
-{
- for (auto &it : arSubclass.rev_iter()) {
- for (int j = 0; j < it->m_iHooks; j++) {
- if (GetInstByAddress(it->m_hooks[j]) == hInst) {
- removeHook(it, j);
- j--;
- }
- }
-
- if (it->m_iHooks == 0)
- finalizeSubclassing(it->m_hWnd, it);
- }
-}
+/*
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "../stdafx.h"
+
+struct MSubclassData
+{
+ HWND m_hWnd;
+
+ int m_iHooks;
+ WNDPROC *m_hooks;
+ WNDPROC m_origWndProc;
+
+ ~MSubclassData()
+ {
+ free(m_hooks);
+ }
+};
+
+static LIST<MSubclassData> arSubclass(10, HandleKeySortT);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static LRESULT CALLBACK MSubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ MSubclassData *p = arSubclass.find((MSubclassData*)&hwnd);
+ if (p != nullptr) {
+ if (p->m_iHooks)
+ return p->m_hooks[p->m_iHooks-1](hwnd, uMsg, wParam, lParam);
+
+ return p->m_origWndProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// This is for wine: it return wrong WNDPROC for edit control in some cases.
+#ifdef WIN64
+#define STD_WND_PROC_ADDR_MASK 0x7FFF00000
+#else
+#define STD_WND_PROC_ADDR_MASK 0xFFFF0000
+#endif
+
+MIR_CORE_DLL(void) mir_subclassWindow(HWND hWnd, WNDPROC wndProc)
+{
+ if (hWnd == nullptr)
+ return;
+
+ MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
+ if (p == nullptr) {
+ p = new MSubclassData;
+ p->m_hWnd = hWnd;
+ p->m_origWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
+ if (((SIZE_T)p->m_origWndProc & STD_WND_PROC_ADDR_MASK) == STD_WND_PROC_ADDR_MASK) { /* XXX: fix me. Wine fix. */
+ p->m_origWndProc = (WNDPROC)GetClassLongPtr(hWnd, GCLP_WNDPROC);
+ if (((SIZE_T)p->m_origWndProc & 0x7FFF0000) == 0x7FFF0000) /* Delay crash. */
+ p->m_origWndProc = DefWindowProc;
+ }
+ p->m_iHooks = 0;
+ p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC));
+ arSubclass.insert(p);
+ }
+ else {
+ for (int i=0; i < p->m_iHooks; i++)
+ if (p->m_hooks[i] == wndProc)
+ return;
+
+ void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));
+ if (tmp == nullptr)
+ return;
+
+ p->m_hooks = (WNDPROC *)tmp;
+ }
+
+ p->m_hooks[p->m_iHooks++] = wndProc;
+}
+
+MIR_CORE_DLL(void) mir_subclassWindowFull(HWND hWnd, WNDPROC wndProc, WNDPROC oldWndProc)
+{
+ MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
+ if (p == nullptr) {
+ p = new MSubclassData;
+ p->m_hWnd = hWnd;
+ p->m_origWndProc = oldWndProc;
+ p->m_iHooks = 0;
+ p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC));
+ arSubclass.insert(p);
+
+ SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
+ }
+ else {
+ for (int i=0; i < p->m_iHooks; i++)
+ if (p->m_hooks[i] == wndProc)
+ return;
+
+ void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));
+ if (tmp == nullptr)
+ return;
+
+ p->m_hooks = (WNDPROC *)tmp;
+ }
+
+ p->m_hooks[p->m_iHooks++] = wndProc;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void removeHook(MSubclassData *p, int idx)
+{
+ // untie hook from a window to prevent calling mir_callNextSubclass from saveProc
+ for (int i = idx + 1; i < p->m_iHooks; i++)
+ p->m_hooks[i-1] = p->m_hooks[i];
+ p->m_iHooks--;
+}
+
+static WNDPROC finalizeSubclassing(HWND hWnd, MSubclassData *p)
+{
+ WNDPROC saveProc = p->m_origWndProc;
+ arSubclass.remove(p);
+ delete p;
+
+ SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)saveProc);
+ return saveProc;
+}
+
+MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd, WNDPROC wndProc)
+{
+ MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
+ if (p == nullptr)
+ return;
+
+ for (int i = 0; i < p->m_iHooks; i++) {
+ if (p->m_hooks[i] == wndProc) {
+ removeHook(p, i);
+ i--;
+ }
+ }
+
+ if (p->m_iHooks == 0)
+ finalizeSubclassing(hWnd, p);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(LRESULT) mir_callNextSubclass(HWND hWnd, WNDPROC wndProc, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
+ if (p == nullptr)
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+
+ for (int i = p->m_iHooks - 1; i >= 0; i--) {
+ if (p->m_hooks[i] != wndProc)
+ continue;
+
+ // next hook exists, call it
+ if (i != 0)
+ return p->m_hooks[i-1](hWnd, uMsg, wParam, lParam);
+
+ // last hook called, ping the default window procedure
+ if (uMsg != WM_NCDESTROY)
+ return p->m_origWndProc(hWnd, uMsg, wParam, lParam);
+
+ WNDPROC saveProc = finalizeSubclassing(hWnd, p);
+ return saveProc(hWnd, uMsg, wParam, lParam);
+ }
+
+ // invalid / closed hook
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst)
+{
+ for (auto &it : arSubclass.rev_iter()) {
+ for (int j = 0; j < it->m_iHooks; j++) {
+ if (GetInstByAddress(it->m_hooks[j]) == hInst) {
+ removeHook(it, j);
+ j--;
+ }
+ }
+
+ if (it->m_iHooks == 0)
+ finalizeSubclassing(it->m_hWnd, it);
+ }
+}
diff --git a/src/mir_core/src/Windows/threads.cpp b/src/mir_core/src/Windows/threads.cpp
index 6af62d3633..c33a80faed 100644
--- a/src/mir_core/src/Windows/threads.cpp
+++ b/src/mir_core/src/Windows/threads.cpp
@@ -1,400 +1,400 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-#include <m_netlib.h>
-
-static mir_cs csThreads;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// APC and mutex functions
-
-static void __stdcall DummyAPCFunc(ULONG_PTR)
-{
- /* called in the context of thread that cleared it's APC queue */
- return;
-}
-
-static int MirandaWaitForMutex(HANDLE hEvent)
-{
- // will get WAIT_IO_COMPLETE for QueueUserAPC() which isnt a result
- for (;;) {
- uint32_t rc = MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
- if (rc == WAIT_OBJECT_0 + 1) {
- MSG msg;
- while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
- if (msg.hwnd != nullptr && IsDialogMessage(msg.hwnd, &msg)) /* Wine fix. */
- continue;
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- else if (rc == WAIT_OBJECT_0) { // got object
- return 1;
- }
- else if (rc == WAIT_ABANDONED_0 || rc == WAIT_FAILED)
- return 0;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// exception handling
-
-static uint32_t __cdecl sttDefaultFilter(uint32_t, EXCEPTION_POINTERS*)
-{
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-pfnExceptionFilter pMirandaExceptFilter = sttDefaultFilter;
-
-MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter()
-{
- return pMirandaExceptFilter;
-}
-
-MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter _mirandaExceptFilter)
-{
- pfnExceptionFilter oldOne = pMirandaExceptFilter;
- if (_mirandaExceptFilter != nullptr)
- pMirandaExceptFilter = _mirandaExceptFilter;
- return oldOne;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// thread support functions
-
-struct THREAD_WAIT_ENTRY
-{
- uint32_t dwThreadId; // valid if hThread isn't signalled
- HANDLE hThread;
- HINSTANCE hOwner;
- void *pObject, *pEntryPoint;
-};
-
-static LIST<THREAD_WAIT_ENTRY> threads(10, NumericKeySortT);
-
-struct FORK_ARG
-{
- HANDLE hEvent, hThread;
- union
- {
- pThreadFunc threadcode;
- pThreadFuncEx threadcodeex;
- };
- void *arg, *owner;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// forkthread - starts a new thread
-
-DWORD WINAPI forkthread_r(void *arg)
-{
- FORK_ARG *fa = (FORK_ARG*)arg;
- pThreadFunc callercode = fa->threadcode;
- void *cookie = fa->arg;
- HANDLE hThread = fa->hThread;
- Thread_Push((HINSTANCE)callercode);
- SetEvent(fa->hEvent);
-
- callercode(cookie);
-
- CloseHandle(hThread);
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- Thread_Pop();
- return 0;
-}
-
-MIR_CORE_DLL(HANDLE) mir_forkthread(void(__cdecl *threadcode)(void*), void *arg)
-{
- FORK_ARG fa;
- fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
- fa.threadcode = threadcode;
- fa.arg = arg;
-
- DWORD threadID;
- fa.hThread = CreateThread(nullptr, 0, forkthread_r, &fa, 0, &threadID);
- if (fa.hThread != nullptr)
- WaitForSingleObject(fa.hEvent, INFINITE);
-
- CloseHandle(fa.hEvent);
- return fa.hThread;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// forkthreadex - starts a new thread with the extended info and returns the thread id
-
-DWORD WINAPI forkthreadex_r(void *arg)
-{
- struct FORK_ARG *fa = (struct FORK_ARG *)arg;
- pThreadFuncEx threadcode = fa->threadcodeex;
- pThreadFuncOwner threadcodeex = (pThreadFuncOwner)fa->threadcodeex;
- void *cookie = fa->arg;
- void *owner = fa->owner;
- unsigned long rc = 0;
-
- Thread_Push((HINSTANCE)threadcode, fa->owner);
- SetEvent(fa->hEvent);
- if (owner)
- rc = threadcodeex(owner, cookie);
- else
- rc = threadcode(cookie);
-
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- Thread_Pop();
- return rc;
-}
-
-MIR_CORE_DLL(HANDLE) mir_forkthreadex(pThreadFuncEx aFunc, void* arg, unsigned *pThreadID)
-{
- struct FORK_ARG fa = {};
- fa.threadcodeex = aFunc;
- fa.arg = arg;
- fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
-
- DWORD threadID = 0;
- HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID);
- if (hThread != nullptr)
- WaitForSingleObject(fa.hEvent, INFINITE);
-
- if (pThreadID != nullptr)
- *pThreadID = threadID;
-
- CloseHandle(fa.hEvent);
- return hThread;
-}
-
-MIR_CORE_DLL(HANDLE) mir_forkthreadowner(pThreadFuncOwner aFunc, void *owner, void *arg, unsigned *pThreadID)
-{
- struct FORK_ARG fa = {};
- fa.threadcodeex = (pThreadFuncEx)aFunc;
- fa.arg = arg;
- fa.owner = owner;
- fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
-
- DWORD threadID = 0;
- HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID);
- if (hThread != nullptr)
- WaitForSingleObject(fa.hEvent, INFINITE);
-
- if (pThreadID != nullptr)
- *pThreadID = threadID;
-
- CloseHandle(fa.hEvent);
- return hThread;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void __cdecl KillObjectThreadsWorker(void* owner)
-{
- HANDLE *threadPool = (HANDLE*)alloca(threads.getCount() * sizeof(HANDLE));
- int threadCount = 0;
- {
- mir_cslock lck(csThreads);
-
- for (auto &it : threads)
- if (it->pObject == owner)
- threadPool[threadCount++] = it->hThread;
- }
-
- // is there anything to kill?
- if (threadCount == 0)
- return;
-
- // wait'em all
- if (WaitForMultipleObjects(threadCount, threadPool, TRUE, 5000) != WAIT_TIMEOUT)
- return;
-
- // forcibly kill all remaining threads after 5 secs
- mir_cslock lck(csThreads);
- auto T = threads.rev_iter();
- for (auto &it : T) {
- if (it->pObject == owner) {
- char szModuleName[MAX_PATH];
- GetModuleFileNameA(it->hOwner, szModuleName, sizeof(szModuleName));
- Netlib_Logf(nullptr, "Killing object thread %s:%08x", szModuleName, it->dwThreadId);
- TerminateThread(it->hThread, 9999);
- CloseHandle(it->hThread);
- mir_free(it);
- threads.removeItem(&it);
- }
- }
-}
-
-MIR_CORE_DLL(void) KillObjectThreads(void* owner)
-{
- if (owner == nullptr)
- return;
-
- uint32_t dwTicks = GetTickCount() + 6000;
- HANDLE hThread = mir_forkthread(KillObjectThreadsWorker, owner);
- while (GetTickCount() < dwTicks) {
- int res = MsgWaitForMultipleObjectsEx(1, &hThread, 50, QS_ALLPOSTMESSAGE | QS_ALLINPUT, MWMO_ALERTABLE);
- if (res == WAIT_OBJECT_0 || res == WAIT_FAILED)
- break;
-
- MSG msg;
- while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void CALLBACK KillAllThreads(HWND, UINT, UINT_PTR, DWORD)
-{
- mir_cslock lck(csThreads);
- for (auto &p : threads) {
- char szModuleName[MAX_PATH];
- GetModuleFileNameA(p->hOwner, szModuleName, sizeof(szModuleName));
- Netlib_Logf(nullptr, "Killing thread %s:%08x (%p)", szModuleName, p->dwThreadId, p->pEntryPoint);
- TerminateThread(p->hThread, 9999);
- CloseHandle(p->hThread);
- mir_free(p);
- }
-
- threads.destroy();
-
- SetEvent(hThreadQueueEmpty);
-}
-
-MIR_CORE_DLL(void) Thread_Wait(void)
-{
- // acquire the list and wake up any alertable threads
- {
- mir_cslock lck(csThreads);
- for (auto &p : threads)
- QueueUserAPC(DummyAPCFunc, p->hThread, 0);
- }
-
- // give all unclosed threads 5 seconds to close
- SetTimer(nullptr, 0, 5000, KillAllThreads);
-
- // wait til the thread list is empty
- MirandaWaitForMutex(hThreadQueueEmpty);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-typedef LONG (WINAPI *pNtQIT)(HANDLE, LONG, PVOID, ULONG, PULONG);
-#define ThreadQuerySetWin32StartAddress 9
-
-static void* GetCurrentThreadEntryPoint()
-{
- pNtQIT NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationThread");
- if (NtQueryInformationThread == nullptr)
- return nullptr;
-
- HANDLE hDupHandle, hCurrentProcess = GetCurrentProcess();
- if (!DuplicateHandle(hCurrentProcess, GetCurrentThread(), hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)) {
- SetLastError(ERROR_ACCESS_DENIED);
- return nullptr;
- }
-
- DWORD_PTR dwStartAddress;
- LONG ntStatus = NtQueryInformationThread(hDupHandle, ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD_PTR), nullptr);
- CloseHandle(hDupHandle);
-
- return (ntStatus != ERROR_SUCCESS) ? nullptr : (void*)dwStartAddress;
-}
-
-MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner)
-{
- ResetEvent(hThreadQueueEmpty); // thread list is not empty
-
- mir_cslock lck(csThreads);
-
- THREAD_WAIT_ENTRY *p = (THREAD_WAIT_ENTRY*)mir_calloc(sizeof(THREAD_WAIT_ENTRY));
- DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
- p->dwThreadId = GetCurrentThreadId();
- p->pObject = pOwner;
- p->pEntryPoint = hInst;
-
- // try to find the precise match
- CMPluginBase &pPlugin = GetPluginByInstance(hInst);
- if (pPlugin.getInst() == hInst)
- p->hOwner = hInst;
- else
- GetInstByAddress((hInst != nullptr) ? (PVOID)hInst : GetCurrentThreadEntryPoint());
-
- threads.insert(p);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(INT_PTR) Thread_Pop()
-{
- uint32_t dwThreadId = GetCurrentThreadId();
-
- mir_cslock lck(csThreads);
- THREAD_WAIT_ENTRY *p = threads.find((THREAD_WAIT_ENTRY*)&dwThreadId);
- if (p == nullptr)
- return 1;
-
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- CloseHandle(p->hThread);
- threads.remove(p);
- mir_free(p);
-
- if (!threads.getCount()) {
- threads.destroy();
- SetEvent(hThreadQueueEmpty); // thread list is empty now
- }
-
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-const uint32_t MS_VC_EXCEPTION=0x406D1388;
-
-#pragma pack(push,8)
-typedef struct tagTHREADNAME_INFO
-{
- uint32_t dwType; // Must be 0x1000.
- LPCSTR szName; // Pointer to name (in user addr space).
- uint32_t dwThreadID; // Thread ID (-1=caller thread).
- uint32_t dwFlags; // Reserved for future use, must be zero.
-} THREADNAME_INFO;
-#pragma pack(pop)
-
-MIR_CORE_DLL(void) Thread_SetName(const char *szThreadName)
-{
- THREADNAME_INFO info;
- info.dwType = 0x1000;
- info.szName = szThreadName;
- info.dwThreadID = GetCurrentThreadId();
- info.dwFlags = 0;
-
- __try {
- RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {}
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+#include <m_netlib.h>
+
+static mir_cs csThreads;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// APC and mutex functions
+
+static void __stdcall DummyAPCFunc(ULONG_PTR)
+{
+ /* called in the context of thread that cleared it's APC queue */
+ return;
+}
+
+static int MirandaWaitForMutex(HANDLE hEvent)
+{
+ // will get WAIT_IO_COMPLETE for QueueUserAPC() which isnt a result
+ for (;;) {
+ uint32_t rc = MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
+ if (rc == WAIT_OBJECT_0 + 1) {
+ MSG msg;
+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ if (msg.hwnd != nullptr && IsDialogMessage(msg.hwnd, &msg)) /* Wine fix. */
+ continue;
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ else if (rc == WAIT_OBJECT_0) { // got object
+ return 1;
+ }
+ else if (rc == WAIT_ABANDONED_0 || rc == WAIT_FAILED)
+ return 0;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// exception handling
+
+static uint32_t __cdecl sttDefaultFilter(uint32_t, EXCEPTION_POINTERS*)
+{
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+pfnExceptionFilter pMirandaExceptFilter = sttDefaultFilter;
+
+MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter()
+{
+ return pMirandaExceptFilter;
+}
+
+MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter _mirandaExceptFilter)
+{
+ pfnExceptionFilter oldOne = pMirandaExceptFilter;
+ if (_mirandaExceptFilter != nullptr)
+ pMirandaExceptFilter = _mirandaExceptFilter;
+ return oldOne;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// thread support functions
+
+struct THREAD_WAIT_ENTRY
+{
+ uint32_t dwThreadId; // valid if hThread isn't signalled
+ HANDLE hThread;
+ HINSTANCE hOwner;
+ void *pObject, *pEntryPoint;
+};
+
+static LIST<THREAD_WAIT_ENTRY> threads(10, NumericKeySortT);
+
+struct FORK_ARG
+{
+ HANDLE hEvent, hThread;
+ union
+ {
+ pThreadFunc threadcode;
+ pThreadFuncEx threadcodeex;
+ };
+ void *arg, *owner;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// forkthread - starts a new thread
+
+DWORD WINAPI forkthread_r(void *arg)
+{
+ FORK_ARG *fa = (FORK_ARG*)arg;
+ pThreadFunc callercode = fa->threadcode;
+ void *cookie = fa->arg;
+ HANDLE hThread = fa->hThread;
+ Thread_Push((HINSTANCE)callercode);
+ SetEvent(fa->hEvent);
+
+ callercode(cookie);
+
+ CloseHandle(hThread);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ Thread_Pop();
+ return 0;
+}
+
+MIR_CORE_DLL(HANDLE) mir_forkthread(void(__cdecl *threadcode)(void*), void *arg)
+{
+ FORK_ARG fa;
+ fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+ fa.threadcode = threadcode;
+ fa.arg = arg;
+
+ DWORD threadID;
+ fa.hThread = CreateThread(nullptr, 0, forkthread_r, &fa, 0, &threadID);
+ if (fa.hThread != nullptr)
+ WaitForSingleObject(fa.hEvent, INFINITE);
+
+ CloseHandle(fa.hEvent);
+ return fa.hThread;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// forkthreadex - starts a new thread with the extended info and returns the thread id
+
+DWORD WINAPI forkthreadex_r(void *arg)
+{
+ struct FORK_ARG *fa = (struct FORK_ARG *)arg;
+ pThreadFuncEx threadcode = fa->threadcodeex;
+ pThreadFuncOwner threadcodeex = (pThreadFuncOwner)fa->threadcodeex;
+ void *cookie = fa->arg;
+ void *owner = fa->owner;
+ unsigned long rc = 0;
+
+ Thread_Push((HINSTANCE)threadcode, fa->owner);
+ SetEvent(fa->hEvent);
+ if (owner)
+ rc = threadcodeex(owner, cookie);
+ else
+ rc = threadcode(cookie);
+
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ Thread_Pop();
+ return rc;
+}
+
+MIR_CORE_DLL(HANDLE) mir_forkthreadex(pThreadFuncEx aFunc, void* arg, unsigned *pThreadID)
+{
+ struct FORK_ARG fa = {};
+ fa.threadcodeex = aFunc;
+ fa.arg = arg;
+ fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+
+ DWORD threadID = 0;
+ HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID);
+ if (hThread != nullptr)
+ WaitForSingleObject(fa.hEvent, INFINITE);
+
+ if (pThreadID != nullptr)
+ *pThreadID = threadID;
+
+ CloseHandle(fa.hEvent);
+ return hThread;
+}
+
+MIR_CORE_DLL(HANDLE) mir_forkthreadowner(pThreadFuncOwner aFunc, void *owner, void *arg, unsigned *pThreadID)
+{
+ struct FORK_ARG fa = {};
+ fa.threadcodeex = (pThreadFuncEx)aFunc;
+ fa.arg = arg;
+ fa.owner = owner;
+ fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+
+ DWORD threadID = 0;
+ HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID);
+ if (hThread != nullptr)
+ WaitForSingleObject(fa.hEvent, INFINITE);
+
+ if (pThreadID != nullptr)
+ *pThreadID = threadID;
+
+ CloseHandle(fa.hEvent);
+ return hThread;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void __cdecl KillObjectThreadsWorker(void* owner)
+{
+ HANDLE *threadPool = (HANDLE*)alloca(threads.getCount() * sizeof(HANDLE));
+ int threadCount = 0;
+ {
+ mir_cslock lck(csThreads);
+
+ for (auto &it : threads)
+ if (it->pObject == owner)
+ threadPool[threadCount++] = it->hThread;
+ }
+
+ // is there anything to kill?
+ if (threadCount == 0)
+ return;
+
+ // wait'em all
+ if (WaitForMultipleObjects(threadCount, threadPool, TRUE, 5000) != WAIT_TIMEOUT)
+ return;
+
+ // forcibly kill all remaining threads after 5 secs
+ mir_cslock lck(csThreads);
+ auto T = threads.rev_iter();
+ for (auto &it : T) {
+ if (it->pObject == owner) {
+ char szModuleName[MAX_PATH];
+ GetModuleFileNameA(it->hOwner, szModuleName, sizeof(szModuleName));
+ Netlib_Logf(nullptr, "Killing object thread %s:%08x", szModuleName, it->dwThreadId);
+ TerminateThread(it->hThread, 9999);
+ CloseHandle(it->hThread);
+ mir_free(it);
+ threads.removeItem(&it);
+ }
+ }
+}
+
+MIR_CORE_DLL(void) KillObjectThreads(void* owner)
+{
+ if (owner == nullptr)
+ return;
+
+ uint32_t dwTicks = GetTickCount() + 6000;
+ HANDLE hThread = mir_forkthread(KillObjectThreadsWorker, owner);
+ while (GetTickCount() < dwTicks) {
+ int res = MsgWaitForMultipleObjectsEx(1, &hThread, 50, QS_ALLPOSTMESSAGE | QS_ALLINPUT, MWMO_ALERTABLE);
+ if (res == WAIT_OBJECT_0 || res == WAIT_FAILED)
+ break;
+
+ MSG msg;
+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void CALLBACK KillAllThreads(HWND, UINT, UINT_PTR, DWORD)
+{
+ mir_cslock lck(csThreads);
+ for (auto &p : threads) {
+ char szModuleName[MAX_PATH];
+ GetModuleFileNameA(p->hOwner, szModuleName, sizeof(szModuleName));
+ Netlib_Logf(nullptr, "Killing thread %s:%08x (%p)", szModuleName, p->dwThreadId, p->pEntryPoint);
+ TerminateThread(p->hThread, 9999);
+ CloseHandle(p->hThread);
+ mir_free(p);
+ }
+
+ threads.destroy();
+
+ SetEvent(hThreadQueueEmpty);
+}
+
+MIR_CORE_DLL(void) Thread_Wait(void)
+{
+ // acquire the list and wake up any alertable threads
+ {
+ mir_cslock lck(csThreads);
+ for (auto &p : threads)
+ QueueUserAPC(DummyAPCFunc, p->hThread, 0);
+ }
+
+ // give all unclosed threads 5 seconds to close
+ SetTimer(nullptr, 0, 5000, KillAllThreads);
+
+ // wait til the thread list is empty
+ MirandaWaitForMutex(hThreadQueueEmpty);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+typedef LONG (WINAPI *pNtQIT)(HANDLE, LONG, PVOID, ULONG, PULONG);
+#define ThreadQuerySetWin32StartAddress 9
+
+static void* GetCurrentThreadEntryPoint()
+{
+ pNtQIT NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationThread");
+ if (NtQueryInformationThread == nullptr)
+ return nullptr;
+
+ HANDLE hDupHandle, hCurrentProcess = GetCurrentProcess();
+ if (!DuplicateHandle(hCurrentProcess, GetCurrentThread(), hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return nullptr;
+ }
+
+ DWORD_PTR dwStartAddress;
+ LONG ntStatus = NtQueryInformationThread(hDupHandle, ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD_PTR), nullptr);
+ CloseHandle(hDupHandle);
+
+ return (ntStatus != ERROR_SUCCESS) ? nullptr : (void*)dwStartAddress;
+}
+
+MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner)
+{
+ ResetEvent(hThreadQueueEmpty); // thread list is not empty
+
+ mir_cslock lck(csThreads);
+
+ THREAD_WAIT_ENTRY *p = (THREAD_WAIT_ENTRY*)mir_calloc(sizeof(THREAD_WAIT_ENTRY));
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ p->dwThreadId = GetCurrentThreadId();
+ p->pObject = pOwner;
+ p->pEntryPoint = hInst;
+
+ // try to find the precise match
+ CMPluginBase &pPlugin = GetPluginByInstance(hInst);
+ if (pPlugin.getInst() == hInst)
+ p->hOwner = hInst;
+ else
+ GetInstByAddress((hInst != nullptr) ? (PVOID)hInst : GetCurrentThreadEntryPoint());
+
+ threads.insert(p);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(INT_PTR) Thread_Pop()
+{
+ uint32_t dwThreadId = GetCurrentThreadId();
+
+ mir_cslock lck(csThreads);
+ THREAD_WAIT_ENTRY *p = threads.find((THREAD_WAIT_ENTRY*)&dwThreadId);
+ if (p == nullptr)
+ return 1;
+
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ CloseHandle(p->hThread);
+ threads.remove(p);
+ mir_free(p);
+
+ if (!threads.getCount()) {
+ threads.destroy();
+ SetEvent(hThreadQueueEmpty); // thread list is empty now
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+const uint32_t MS_VC_EXCEPTION=0x406D1388;
+
+#pragma pack(push,8)
+typedef struct tagTHREADNAME_INFO
+{
+ uint32_t dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ uint32_t dwThreadID; // Thread ID (-1=caller thread).
+ uint32_t dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+MIR_CORE_DLL(void) Thread_SetName(const char *szThreadName)
+{
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = szThreadName;
+ info.dwThreadID = GetCurrentThreadId();
+ info.dwFlags = 0;
+
+ __try {
+ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {}
+}
diff --git a/src/mir_core/src/Windows/timezones.cpp b/src/mir_core/src/Windows/timezones.cpp
index 63d026a3eb..13e2fddba9 100644
--- a/src/mir_core/src/Windows/timezones.cpp
+++ b/src/mir_core/src/Windows/timezones.cpp
@@ -1,593 +1,593 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-implements services to handle location - based timezones, instead of
-simple UTC offsets.
-*/
-
-#include "../stdafx.h"
-
-typedef uint32_t (WINAPI *pfnGetDynamicTimeZoneInformation_t)(DYNAMIC_TIME_ZONE_INFORMATION *pdtzi);
-static pfnGetDynamicTimeZoneInformation_t pfnGetDynamicTimeZoneInformation;
-
-struct REG_TZI_FORMAT
-{
- LONG Bias;
- LONG StandardBias;
- LONG DaylightBias;
- SYSTEMTIME StandardDate;
- SYSTEMTIME DaylightDate;
-};
-
-#define MIM_TZ_DISPLAYLEN 128
-
-struct MIM_TIMEZONE
-{
- unsigned hash;
- int offset;
-
- wchar_t tszName[MIM_TZ_NAMELEN]; // windows name for the time zone
- wchar_t szDisplay[MIM_TZ_DISPLAYLEN]; // more descriptive display name (that's what usually appears in dialogs)
- // every hour should be sufficient.
- TIME_ZONE_INFORMATION tzi;
-
- static int compareBias(const MIM_TIMEZONE* p1, const MIM_TIMEZONE* p2)
- { return p2->tzi.Bias - p1->tzi.Bias;
- }
-};
-
-struct TZ_INT_INFO
-{
- uint32_t timestamp; // last time updated
- MIM_TIMEZONE myTZ; // set to my own timezone
-};
-
-static TZ_INT_INFO myInfo;
-
-static OBJLIST<MIM_TIMEZONE> g_timezones(55, NumericKeySortT);
-static LIST<MIM_TIMEZONE> g_timezonesBias(55, MIM_TIMEZONE::compareBias);
-
-// KB167296
-void UnixTimeToFileTime(mir_time ts, LPFILETIME pft)
-{
- unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64;
- pft->dwLowDateTime = (uint32_t)ll;
- pft->dwHighDateTime = ll >> 32;
-}
-
-mir_time FileTimeToUnixTime(LPFILETIME pft)
-{
- unsigned __int64 ll = (unsigned __int64)pft->dwHighDateTime << 32 | pft->dwLowDateTime;
- ll -= 116444736000000000i64;
- return (mir_time)(ll / 10000000);
-}
-
-void FormatTime(const SYSTEMTIME *st, const wchar_t *szFormat, wchar_t *szDest, size_t cbDest)
-{
- if (szDest == nullptr || cbDest == 0) return;
-
- CMStringW tszTemp;
-
- for (const wchar_t* pFormat = szFormat; *pFormat; ++pFormat) {
- uint32_t fmt = 0;
- bool date = false, iso = false;
- switch (*pFormat) {
- case 't':
- fmt = TIME_NOSECONDS;
- date = false;
- break;
-
- case 's':
- fmt = 0;
- date = false;
- break;
-
- case 'm':
- fmt = TIME_NOMINUTESORSECONDS;
- date = false;
- break;
-
- case 'd':
- fmt = DATE_SHORTDATE;
- date = true;
- break;
-
- case 'D':
- fmt = DATE_LONGDATE;
- date = true;
- break;
-
- case 'I':
- iso = true;
- break;
-
- default:
- tszTemp.AppendChar(*pFormat);
- continue;
- }
-
- wchar_t dateTimeStr[64];
- if (iso)
- tszTemp.AppendFormat(L"%d-%02d-%02dT%02d:%02d:%02dZ", st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond);
- else if (date) {
- GetDateFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr));
- tszTemp.Append(dateTimeStr);
- }
- else {
- GetTimeFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr));
- tszTemp.Append(dateTimeStr);
- }
- }
-
- wcsncpy_s(szDest, cbDest, tszTemp, _TRUNCATE);
-}
-
-MIR_CORE_DLL(int) TimeZone_GetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st)
-{
- if (st == nullptr) return 1;
-
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == UTC_TIME_HANDLE)
- GetSystemTime(st);
- else if (tz && tz != &myInfo.myTZ) {
- SYSTEMTIME sto;
- GetSystemTime(&sto);
- return !SystemTimeToTzSpecificLocalTime(&tz->tzi, &sto, st);
- }
- else
- GetLocalTime(st);
-
- return 0;
-}
-
-MIR_CORE_DLL(LPCTSTR) TimeZone_GetName(HANDLE hTZ)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == nullptr)
- return myInfo.myTZ.tszName;
- if (tz == UTC_TIME_HANDLE)
- return L"UTC";
-
- return tz->tszName;
-}
-
-MIR_CORE_DLL(LPCTSTR) TimeZone_GetDescription(LPCTSTR TZname)
-{
- for (auto &tz : g_timezonesBias)
- if (!mir_wstrcmp(tz->tszName, TZname))
- return tz->szDisplay;
-
- return L"";
-}
-
-static void CalcTsOffset(MIM_TIMEZONE *tz)
-{
- SYSTEMTIME st, stl;
- GetSystemTime(&st);
-
- FILETIME ft;
- SystemTimeToFileTime(&st, &ft);
- mir_time ts1 = FileTimeToUnixTime(&ft);
-
- if (!SystemTimeToTzSpecificLocalTime(&tz->tzi, &st, &stl))
- return;
-
- SystemTimeToFileTime(&stl, &ft);
- mir_time ts2 = FileTimeToUnixTime(&ft);
-
- tz->offset = ts2 - ts1;
-}
-
-static bool IsSameTime(MIM_TIMEZONE *tz)
-{
- SYSTEMTIME st, stl;
-
- if (tz == &myInfo.myTZ)
- return true;
-
- TimeZone_GetTimeZoneTime(tz, &stl);
- TimeZone_GetTimeZoneTime(nullptr, &st);
-
- return st.wHour == stl.wHour && st.wMinute == stl.wMinute;
-}
-
-MIR_CORE_DLL(HANDLE) TimeZone_CreateByName(LPCTSTR tszName, uint32_t dwFlags)
-{
- if (tszName == nullptr)
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-
- if (!(dwFlags & TZF_PLF_CB))
- if (mir_wstrcmp(myInfo.myTZ.tszName, tszName) == 0)
- return (dwFlags & TZF_DIFONLY) ? nullptr : &myInfo.myTZ;
-
- MIM_TIMEZONE tzsearch;
- tzsearch.hash = mir_hashstrT(tszName);
-
- MIM_TIMEZONE *tz = g_timezones.find(&tzsearch);
- if (tz == nullptr)
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-
- if (dwFlags & TZF_DIFONLY)
- return IsSameTime(tz) ? nullptr : tz;
-
- return tz;
-}
-
-MIR_CORE_DLL(HANDLE) TimeZone_CreateByContact(MCONTACT hContact, LPCSTR szModule, uint32_t dwFlags)
-{
- if (hContact == NULL && szModule == nullptr)
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-
- if (szModule == nullptr) szModule = "UserInfo";
-
- DBVARIANT dbv;
- if (!db_get_ws(hContact, szModule, "TzName", &dbv)) {
- HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags);
- db_free(&dbv);
- if (res) return res;
- }
-
- signed char timezone = (signed char)db_get_b(hContact, szModule, "Timezone", -1);
- if (timezone == -1) {
- char *szProto = Proto_GetBaseAccountName(hContact);
- if (!db_get_ws(hContact, szProto, "TzName", &dbv)) {
- HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags);
- db_free(&dbv);
- if (res) return res;
- }
- timezone = (signed char)db_get_b(hContact, szProto, "Timezone", -1);
- }
-
- if (timezone != -1) {
- MIM_TIMEZONE tzsearch;
- tzsearch.tzi.Bias = timezone * 30;
- if (myInfo.myTZ.tzi.Bias == tzsearch.tzi.Bias) {
- if (dwFlags & TZF_DIFONLY) return nullptr;
- return &myInfo.myTZ;
- }
-
- int i = g_timezonesBias.getIndex(&tzsearch);
- while (i >= 0 && g_timezonesBias[i]->tzi.Bias == tzsearch.tzi.Bias) --i;
-
- int delta = LONG_MAX;
- for (int j = ++i; j < g_timezonesBias.getCount() && g_timezonesBias[j]->tzi.Bias == tzsearch.tzi.Bias; ++j) {
- int delta1 = abs(g_timezonesBias[j]->tzi.DaylightDate.wMonth - myInfo.myTZ.tzi.DaylightDate.wMonth);
- if (delta1 <= delta) {
- delta = delta1;
- i = j;
- }
- }
-
- if (i >= 0) {
- MIM_TIMEZONE *tz = g_timezonesBias[i];
- return ((dwFlags & TZF_DIFONLY) && IsSameTime(tz)) ? nullptr : tz;
- }
- }
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-}
-
-MIR_CORE_DLL(void) TimeZone_StoreByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ)
-{
- if (szModule == nullptr) szModule = "UserInfo";
-
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz) {
- db_set_ws(hContact, szModule, "TzName", tz->tszName);
- db_set_b(hContact, szModule, "Timezone", (char)((tz->tzi.Bias + tz->tzi.StandardBias) / 30));
- }
- else {
- db_unset(hContact, szModule, "TzName");
- db_unset(hContact, szModule, "Timezone");
- }
-}
-
-MIR_CORE_DLL(int) TimeZone_PrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, uint32_t dwFlags)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)))
- return 1;
-
- if (tz == nullptr)
- tz = &myInfo.myTZ;
-
- SYSTEMTIME st;
- if (TimeZone_GetTimeZoneTime(tz, &st))
- return 1;
-
- FormatTime(&st, szFormat, szDest, cbDest);
- return 0;
-}
-
-MIR_CORE_DLL(int) TimeZone_GetSystemTime(HANDLE hTZ, mir_time ts, SYSTEMTIME *dest, uint32_t dwFlags)
-{
- if (dest == nullptr)
- return 2;
-
- MIM_TIMEZONE *tz = (MIM_TIMEZONE *)hTZ;
- if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) {
- memset(dest, 0, sizeof(SYSTEMTIME));
- return 1;
- }
-
- if (tz == nullptr)
- tz = &myInfo.myTZ;
-
- FILETIME ft;
- if (tz == UTC_TIME_HANDLE)
- UnixTimeToFileTime(ts, &ft);
- else {
- if (tz->offset == INT_MIN)
- CalcTsOffset(tz);
-
- UnixTimeToFileTime(ts + tz->offset, &ft);
- }
-
- FileTimeToSystemTime(&ft, dest);
- return 0;
-}
-
-MIR_CORE_DLL(int) TimeZone_PrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, uint32_t dwFlags)
-{
- SYSTEMTIME st;
- if (!TimeZone_GetSystemTime(hTZ, ts, &st, dwFlags))
- FormatTime(&st, szFormat, szDest, cbDest);
- return 0;
-}
-
-MIR_CORE_DLL(LPTIME_ZONE_INFORMATION) TimeZone_GetInfo(HANDLE hTZ)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- return tz ? &tz->tzi : &myInfo.myTZ.tzi;
-}
-
-MIR_CORE_DLL(mir_time) TimeZone_UtcToLocal(HANDLE hTZ, mir_time ts)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == nullptr)
- tz = &myInfo.myTZ;
-
- if (tz == UTC_TIME_HANDLE)
- return ts;
-
- if (tz->offset == INT_MIN)
- CalcTsOffset(tz);
-
- return ts + tz->offset;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-struct ListMessages
-{
- UINT addStr, getSel, setSel, getData, setData;
-};
-
-static const ListMessages lbMessages = { LB_ADDSTRING, LB_GETCURSEL, LB_SETCURSEL, LB_GETITEMDATA, LB_SETITEMDATA };
-static const ListMessages cbMessages = { CB_ADDSTRING, CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_SETITEMDATA };
-
-static const ListMessages* GetListMessages(HWND hWnd, uint32_t dwFlags)
-{
- if (hWnd == nullptr)
- return nullptr;
-
- if (!(dwFlags & (TZF_PLF_CB | TZF_PLF_LB))) {
- wchar_t tszClassName[128];
- GetClassName(hWnd, tszClassName, _countof(tszClassName));
- if (!mir_wstrcmpi(tszClassName, L"COMBOBOX"))
- dwFlags |= TZF_PLF_CB;
- else if (!mir_wstrcmpi(tszClassName, L"LISTBOX"))
- dwFlags |= TZF_PLF_LB;
- }
-
- if (dwFlags & TZF_PLF_CB)
- return &cbMessages;
- if (dwFlags & TZF_PLF_LB)
- return &lbMessages;
- return nullptr;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) TimeZone_SelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, uint32_t dwFlags)
-{
- const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
- if (lstMsg == nullptr)
- return -1;
-
- if (szModule == nullptr)
- szModule = "UserInfo";
-
- int iSelection = 0;
- ptrW tszName(db_get_wsa(hContact, szModule, "TzName"));
- if (tszName != NULL) {
- unsigned hash = mir_hashstrT(tszName);
- for (auto &it : g_timezonesBias) {
- if (hash == it->hash) {
- iSelection = g_timezonesBias.indexOf(&it) + 1;
- break;
- }
- }
- }
- else {
- signed char cBias = db_get_b(hContact, szModule, "Timezone", -100);
- if (cBias != -100) {
- int iBias = cBias * 30;
- for (auto &it : g_timezonesBias) {
- if (iBias == it->tzi.Bias) {
- iSelection = g_timezonesBias.indexOf(&it) + 1;
- break;
- }
- }
- }
- }
-
- SendMessage(hWnd, lstMsg->setSel, iSelection, 0);
- return iSelection;
-}
-
-MIR_CORE_DLL(int) TimeZone_PrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, uint32_t dwFlags)
-{
- const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
- if (lstMsg == nullptr)
- return 0;
-
- SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateW_LP(L"<unspecified>"));
-
- for (auto &it : g_timezonesBias) {
- SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)it->szDisplay);
- SendMessage(hWnd, lstMsg->setData, g_timezonesBias.indexOf(&it) + 1, (LPARAM)it);
- }
-
- return TimeZone_SelectListItem(hContact, szModule, hWnd, dwFlags);
-}
-
-MIR_CORE_DLL(void) TimeZone_StoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, uint32_t dwFlags)
-{
- if (szModule == nullptr) szModule = "UserInfo";
-
- const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
- if (lstMsg) {
- LRESULT offset = SendMessage(hWnd, lstMsg->getSel, 0, 0);
- if (offset > 0) {
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)SendMessage(hWnd, lstMsg->getData, offset, 0);
- if ((INT_PTR)tz != CB_ERR && tz != nullptr)
- TimeZone_StoreByContact(hContact, szModule, tz);
- }
- else TimeZone_StoreByContact(hContact, szModule, nullptr);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(uint32_t) TimeZone_ToLocal(uint32_t timeVal)
-{
- return TimeZone_UtcToLocal(nullptr, (mir_time)timeVal);
-}
-
-MIR_CORE_DLL(char*) TimeZone_ToString(mir_time timeVal, const char *szFormat, char *szDest, size_t cchDest)
-{
- wchar_t *szTemp = (wchar_t*)alloca(cchDest*sizeof(wchar_t));
- TimeZone_PrintTimeStamp(nullptr, timeVal, _A2T(szFormat), szTemp, cchDest, 0);
- WideCharToMultiByte(CP_ACP, 0, szTemp, -1, szDest, (int)cchDest, nullptr, nullptr);
- return szDest;
-}
-
-MIR_CORE_DLL(wchar_t*) TimeZone_ToStringW(mir_time timeVal, const wchar_t *wszFormat, wchar_t *wszDest, size_t cchDest)
-{
- TimeZone_PrintTimeStamp(nullptr, timeVal, wszFormat, wszDest, cchDest, 0);
- return wszDest;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GetLocalizedString(HKEY hSubKey, const wchar_t *szName, wchar_t *szBuf, uint32_t cbLen)
-{
- DWORD dwLength = cbLen * sizeof(wchar_t);
- RegQueryValueEx(hSubKey, szName, nullptr, nullptr, (unsigned char *)szBuf, &dwLength);
- szBuf[min(dwLength / sizeof(wchar_t), cbLen - 1)] = 0;
-}
-
-void RecalculateTime(void)
-{
- GetTimeZoneInformation(&myInfo.myTZ.tzi);
- myInfo.timestamp = time(0);
- myInfo.myTZ.offset = INT_MIN;
-
- bool found = false;
- DYNAMIC_TIME_ZONE_INFORMATION dtzi;
-
- if (pfnGetDynamicTimeZoneInformation && pfnGetDynamicTimeZoneInformation(&dtzi) != TIME_ZONE_ID_INVALID) {
- wcsncpy_s(myInfo.myTZ.tszName, dtzi.TimeZoneKeyName, _TRUNCATE);
- found = true;
- }
-
- for (auto &tz : g_timezones) {
- if (tz->offset != INT_MIN)
- tz->offset = INT_MIN;
-
- if (!found) {
- if (!mir_wstrcmp(tz->tzi.StandardName, myInfo.myTZ.tzi.StandardName) || !mir_wstrcmp(tz->tzi.DaylightName, myInfo.myTZ.tzi.DaylightName)) {
- wcsncpy_s(myInfo.myTZ.tszName, tz->tszName, _TRUNCATE);
- found = true;
- }
- }
- }
-}
-
-void InitTimeZones(void)
-{
- REG_TZI_FORMAT tzi;
- HKEY hKey;
-
- const wchar_t *tszKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
-
- /*
- * use GetDynamicTimeZoneInformation() on Vista+ - this will return a structure with
- * the registry key name, so finding our own time zone later will be MUCH easier for
- * localized systems or systems with a MUI pack installed
- */
- if (IsWinVerVistaPlus())
- pfnGetDynamicTimeZoneInformation = (pfnGetDynamicTimeZoneInformation_t)GetProcAddress(GetModuleHandle(L"kernel32"), "GetDynamicTimeZoneInformation");
-
- if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, tszKey, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)) {
- uint32_t dwIndex = 0;
- HKEY hSubKey;
- wchar_t tszName[MIM_TZ_NAMELEN];
-
- DWORD dwSize = _countof(tszName);
- while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, dwIndex++, tszName, &dwSize, nullptr, nullptr, nullptr, nullptr)) {
- if (ERROR_SUCCESS == RegOpenKeyEx(hKey, tszName, 0, KEY_QUERY_VALUE, &hSubKey)) {
- dwSize = sizeof(tszName);
-
- DWORD dwLength = sizeof(tzi);
- if (ERROR_SUCCESS != RegQueryValueEx(hSubKey, L"TZI", nullptr, nullptr, (unsigned char *)&tzi, &dwLength))
- continue;
-
- MIM_TIMEZONE *tz = new MIM_TIMEZONE;
-
- tz->tzi.Bias = tzi.Bias;
- tz->tzi.StandardDate = tzi.StandardDate;
- tz->tzi.StandardBias = tzi.StandardBias;
- tz->tzi.DaylightDate = tzi.DaylightDate;
- tz->tzi.DaylightBias = tzi.DaylightBias;
-
- mir_wstrcpy(tz->tszName, tszName);
- tz->hash = mir_hashstrT(tszName);
- tz->offset = INT_MIN;
-
- GetLocalizedString(hSubKey, L"Display", tz->szDisplay, _countof(tz->szDisplay));
- GetLocalizedString(hSubKey, L"Std", tz->tzi.StandardName, _countof(tz->tzi.StandardName));
- GetLocalizedString(hSubKey, L"Dlt", tz->tzi.DaylightName, _countof(tz->tzi.DaylightName));
-
- g_timezones.insert(tz);
- g_timezonesBias.insert(tz);
-
- RegCloseKey(hSubKey);
- }
- dwSize = _countof(tszName);
- }
- RegCloseKey(hKey);
- }
-
- RecalculateTime();
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+implements services to handle location - based timezones, instead of
+simple UTC offsets.
+*/
+
+#include "../stdafx.h"
+
+typedef uint32_t (WINAPI *pfnGetDynamicTimeZoneInformation_t)(DYNAMIC_TIME_ZONE_INFORMATION *pdtzi);
+static pfnGetDynamicTimeZoneInformation_t pfnGetDynamicTimeZoneInformation;
+
+struct REG_TZI_FORMAT
+{
+ LONG Bias;
+ LONG StandardBias;
+ LONG DaylightBias;
+ SYSTEMTIME StandardDate;
+ SYSTEMTIME DaylightDate;
+};
+
+#define MIM_TZ_DISPLAYLEN 128
+
+struct MIM_TIMEZONE
+{
+ unsigned hash;
+ int offset;
+
+ wchar_t tszName[MIM_TZ_NAMELEN]; // windows name for the time zone
+ wchar_t szDisplay[MIM_TZ_DISPLAYLEN]; // more descriptive display name (that's what usually appears in dialogs)
+ // every hour should be sufficient.
+ TIME_ZONE_INFORMATION tzi;
+
+ static int compareBias(const MIM_TIMEZONE* p1, const MIM_TIMEZONE* p2)
+ { return p2->tzi.Bias - p1->tzi.Bias;
+ }
+};
+
+struct TZ_INT_INFO
+{
+ uint32_t timestamp; // last time updated
+ MIM_TIMEZONE myTZ; // set to my own timezone
+};
+
+static TZ_INT_INFO myInfo;
+
+static OBJLIST<MIM_TIMEZONE> g_timezones(55, NumericKeySortT);
+static LIST<MIM_TIMEZONE> g_timezonesBias(55, MIM_TIMEZONE::compareBias);
+
+// KB167296
+void UnixTimeToFileTime(mir_time ts, LPFILETIME pft)
+{
+ unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64;
+ pft->dwLowDateTime = (uint32_t)ll;
+ pft->dwHighDateTime = ll >> 32;
+}
+
+mir_time FileTimeToUnixTime(LPFILETIME pft)
+{
+ unsigned __int64 ll = (unsigned __int64)pft->dwHighDateTime << 32 | pft->dwLowDateTime;
+ ll -= 116444736000000000i64;
+ return (mir_time)(ll / 10000000);
+}
+
+void FormatTime(const SYSTEMTIME *st, const wchar_t *szFormat, wchar_t *szDest, size_t cbDest)
+{
+ if (szDest == nullptr || cbDest == 0) return;
+
+ CMStringW tszTemp;
+
+ for (const wchar_t* pFormat = szFormat; *pFormat; ++pFormat) {
+ uint32_t fmt = 0;
+ bool date = false, iso = false;
+ switch (*pFormat) {
+ case 't':
+ fmt = TIME_NOSECONDS;
+ date = false;
+ break;
+
+ case 's':
+ fmt = 0;
+ date = false;
+ break;
+
+ case 'm':
+ fmt = TIME_NOMINUTESORSECONDS;
+ date = false;
+ break;
+
+ case 'd':
+ fmt = DATE_SHORTDATE;
+ date = true;
+ break;
+
+ case 'D':
+ fmt = DATE_LONGDATE;
+ date = true;
+ break;
+
+ case 'I':
+ iso = true;
+ break;
+
+ default:
+ tszTemp.AppendChar(*pFormat);
+ continue;
+ }
+
+ wchar_t dateTimeStr[64];
+ if (iso)
+ tszTemp.AppendFormat(L"%d-%02d-%02dT%02d:%02d:%02dZ", st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond);
+ else if (date) {
+ GetDateFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr));
+ tszTemp.Append(dateTimeStr);
+ }
+ else {
+ GetTimeFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr));
+ tszTemp.Append(dateTimeStr);
+ }
+ }
+
+ wcsncpy_s(szDest, cbDest, tszTemp, _TRUNCATE);
+}
+
+MIR_CORE_DLL(int) TimeZone_GetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st)
+{
+ if (st == nullptr) return 1;
+
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ if (tz == UTC_TIME_HANDLE)
+ GetSystemTime(st);
+ else if (tz && tz != &myInfo.myTZ) {
+ SYSTEMTIME sto;
+ GetSystemTime(&sto);
+ return !SystemTimeToTzSpecificLocalTime(&tz->tzi, &sto, st);
+ }
+ else
+ GetLocalTime(st);
+
+ return 0;
+}
+
+MIR_CORE_DLL(LPCTSTR) TimeZone_GetName(HANDLE hTZ)
+{
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ if (tz == nullptr)
+ return myInfo.myTZ.tszName;
+ if (tz == UTC_TIME_HANDLE)
+ return L"UTC";
+
+ return tz->tszName;
+}
+
+MIR_CORE_DLL(LPCTSTR) TimeZone_GetDescription(LPCTSTR TZname)
+{
+ for (auto &tz : g_timezonesBias)
+ if (!mir_wstrcmp(tz->tszName, TZname))
+ return tz->szDisplay;
+
+ return L"";
+}
+
+static void CalcTsOffset(MIM_TIMEZONE *tz)
+{
+ SYSTEMTIME st, stl;
+ GetSystemTime(&st);
+
+ FILETIME ft;
+ SystemTimeToFileTime(&st, &ft);
+ mir_time ts1 = FileTimeToUnixTime(&ft);
+
+ if (!SystemTimeToTzSpecificLocalTime(&tz->tzi, &st, &stl))
+ return;
+
+ SystemTimeToFileTime(&stl, &ft);
+ mir_time ts2 = FileTimeToUnixTime(&ft);
+
+ tz->offset = ts2 - ts1;
+}
+
+static bool IsSameTime(MIM_TIMEZONE *tz)
+{
+ SYSTEMTIME st, stl;
+
+ if (tz == &myInfo.myTZ)
+ return true;
+
+ TimeZone_GetTimeZoneTime(tz, &stl);
+ TimeZone_GetTimeZoneTime(nullptr, &st);
+
+ return st.wHour == stl.wHour && st.wMinute == stl.wMinute;
+}
+
+MIR_CORE_DLL(HANDLE) TimeZone_CreateByName(LPCTSTR tszName, uint32_t dwFlags)
+{
+ if (tszName == nullptr)
+ return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
+
+ if (!(dwFlags & TZF_PLF_CB))
+ if (mir_wstrcmp(myInfo.myTZ.tszName, tszName) == 0)
+ return (dwFlags & TZF_DIFONLY) ? nullptr : &myInfo.myTZ;
+
+ MIM_TIMEZONE tzsearch;
+ tzsearch.hash = mir_hashstrT(tszName);
+
+ MIM_TIMEZONE *tz = g_timezones.find(&tzsearch);
+ if (tz == nullptr)
+ return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
+
+ if (dwFlags & TZF_DIFONLY)
+ return IsSameTime(tz) ? nullptr : tz;
+
+ return tz;
+}
+
+MIR_CORE_DLL(HANDLE) TimeZone_CreateByContact(MCONTACT hContact, LPCSTR szModule, uint32_t dwFlags)
+{
+ if (hContact == NULL && szModule == nullptr)
+ return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
+
+ if (szModule == nullptr) szModule = "UserInfo";
+
+ DBVARIANT dbv;
+ if (!db_get_ws(hContact, szModule, "TzName", &dbv)) {
+ HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags);
+ db_free(&dbv);
+ if (res) return res;
+ }
+
+ signed char timezone = (signed char)db_get_b(hContact, szModule, "Timezone", -1);
+ if (timezone == -1) {
+ char *szProto = Proto_GetBaseAccountName(hContact);
+ if (!db_get_ws(hContact, szProto, "TzName", &dbv)) {
+ HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags);
+ db_free(&dbv);
+ if (res) return res;
+ }
+ timezone = (signed char)db_get_b(hContact, szProto, "Timezone", -1);
+ }
+
+ if (timezone != -1) {
+ MIM_TIMEZONE tzsearch;
+ tzsearch.tzi.Bias = timezone * 30;
+ if (myInfo.myTZ.tzi.Bias == tzsearch.tzi.Bias) {
+ if (dwFlags & TZF_DIFONLY) return nullptr;
+ return &myInfo.myTZ;
+ }
+
+ int i = g_timezonesBias.getIndex(&tzsearch);
+ while (i >= 0 && g_timezonesBias[i]->tzi.Bias == tzsearch.tzi.Bias) --i;
+
+ int delta = LONG_MAX;
+ for (int j = ++i; j < g_timezonesBias.getCount() && g_timezonesBias[j]->tzi.Bias == tzsearch.tzi.Bias; ++j) {
+ int delta1 = abs(g_timezonesBias[j]->tzi.DaylightDate.wMonth - myInfo.myTZ.tzi.DaylightDate.wMonth);
+ if (delta1 <= delta) {
+ delta = delta1;
+ i = j;
+ }
+ }
+
+ if (i >= 0) {
+ MIM_TIMEZONE *tz = g_timezonesBias[i];
+ return ((dwFlags & TZF_DIFONLY) && IsSameTime(tz)) ? nullptr : tz;
+ }
+ }
+ return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
+}
+
+MIR_CORE_DLL(void) TimeZone_StoreByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ)
+{
+ if (szModule == nullptr) szModule = "UserInfo";
+
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ if (tz) {
+ db_set_ws(hContact, szModule, "TzName", tz->tszName);
+ db_set_b(hContact, szModule, "Timezone", (char)((tz->tzi.Bias + tz->tzi.StandardBias) / 30));
+ }
+ else {
+ db_unset(hContact, szModule, "TzName");
+ db_unset(hContact, szModule, "Timezone");
+ }
+}
+
+MIR_CORE_DLL(int) TimeZone_PrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, uint32_t dwFlags)
+{
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)))
+ return 1;
+
+ if (tz == nullptr)
+ tz = &myInfo.myTZ;
+
+ SYSTEMTIME st;
+ if (TimeZone_GetTimeZoneTime(tz, &st))
+ return 1;
+
+ FormatTime(&st, szFormat, szDest, cbDest);
+ return 0;
+}
+
+MIR_CORE_DLL(int) TimeZone_GetSystemTime(HANDLE hTZ, mir_time ts, SYSTEMTIME *dest, uint32_t dwFlags)
+{
+ if (dest == nullptr)
+ return 2;
+
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE *)hTZ;
+ if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) {
+ memset(dest, 0, sizeof(SYSTEMTIME));
+ return 1;
+ }
+
+ if (tz == nullptr)
+ tz = &myInfo.myTZ;
+
+ FILETIME ft;
+ if (tz == UTC_TIME_HANDLE)
+ UnixTimeToFileTime(ts, &ft);
+ else {
+ if (tz->offset == INT_MIN)
+ CalcTsOffset(tz);
+
+ UnixTimeToFileTime(ts + tz->offset, &ft);
+ }
+
+ FileTimeToSystemTime(&ft, dest);
+ return 0;
+}
+
+MIR_CORE_DLL(int) TimeZone_PrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, uint32_t dwFlags)
+{
+ SYSTEMTIME st;
+ if (!TimeZone_GetSystemTime(hTZ, ts, &st, dwFlags))
+ FormatTime(&st, szFormat, szDest, cbDest);
+ return 0;
+}
+
+MIR_CORE_DLL(LPTIME_ZONE_INFORMATION) TimeZone_GetInfo(HANDLE hTZ)
+{
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ return tz ? &tz->tzi : &myInfo.myTZ.tzi;
+}
+
+MIR_CORE_DLL(mir_time) TimeZone_UtcToLocal(HANDLE hTZ, mir_time ts)
+{
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ if (tz == nullptr)
+ tz = &myInfo.myTZ;
+
+ if (tz == UTC_TIME_HANDLE)
+ return ts;
+
+ if (tz->offset == INT_MIN)
+ CalcTsOffset(tz);
+
+ return ts + tz->offset;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct ListMessages
+{
+ UINT addStr, getSel, setSel, getData, setData;
+};
+
+static const ListMessages lbMessages = { LB_ADDSTRING, LB_GETCURSEL, LB_SETCURSEL, LB_GETITEMDATA, LB_SETITEMDATA };
+static const ListMessages cbMessages = { CB_ADDSTRING, CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_SETITEMDATA };
+
+static const ListMessages* GetListMessages(HWND hWnd, uint32_t dwFlags)
+{
+ if (hWnd == nullptr)
+ return nullptr;
+
+ if (!(dwFlags & (TZF_PLF_CB | TZF_PLF_LB))) {
+ wchar_t tszClassName[128];
+ GetClassName(hWnd, tszClassName, _countof(tszClassName));
+ if (!mir_wstrcmpi(tszClassName, L"COMBOBOX"))
+ dwFlags |= TZF_PLF_CB;
+ else if (!mir_wstrcmpi(tszClassName, L"LISTBOX"))
+ dwFlags |= TZF_PLF_LB;
+ }
+
+ if (dwFlags & TZF_PLF_CB)
+ return &cbMessages;
+ if (dwFlags & TZF_PLF_LB)
+ return &lbMessages;
+ return nullptr;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) TimeZone_SelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, uint32_t dwFlags)
+{
+ const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
+ if (lstMsg == nullptr)
+ return -1;
+
+ if (szModule == nullptr)
+ szModule = "UserInfo";
+
+ int iSelection = 0;
+ ptrW tszName(db_get_wsa(hContact, szModule, "TzName"));
+ if (tszName != NULL) {
+ unsigned hash = mir_hashstrT(tszName);
+ for (auto &it : g_timezonesBias) {
+ if (hash == it->hash) {
+ iSelection = g_timezonesBias.indexOf(&it) + 1;
+ break;
+ }
+ }
+ }
+ else {
+ signed char cBias = db_get_b(hContact, szModule, "Timezone", -100);
+ if (cBias != -100) {
+ int iBias = cBias * 30;
+ for (auto &it : g_timezonesBias) {
+ if (iBias == it->tzi.Bias) {
+ iSelection = g_timezonesBias.indexOf(&it) + 1;
+ break;
+ }
+ }
+ }
+ }
+
+ SendMessage(hWnd, lstMsg->setSel, iSelection, 0);
+ return iSelection;
+}
+
+MIR_CORE_DLL(int) TimeZone_PrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, uint32_t dwFlags)
+{
+ const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
+ if (lstMsg == nullptr)
+ return 0;
+
+ SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateW_LP(L"<unspecified>"));
+
+ for (auto &it : g_timezonesBias) {
+ SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)it->szDisplay);
+ SendMessage(hWnd, lstMsg->setData, g_timezonesBias.indexOf(&it) + 1, (LPARAM)it);
+ }
+
+ return TimeZone_SelectListItem(hContact, szModule, hWnd, dwFlags);
+}
+
+MIR_CORE_DLL(void) TimeZone_StoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, uint32_t dwFlags)
+{
+ if (szModule == nullptr) szModule = "UserInfo";
+
+ const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
+ if (lstMsg) {
+ LRESULT offset = SendMessage(hWnd, lstMsg->getSel, 0, 0);
+ if (offset > 0) {
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)SendMessage(hWnd, lstMsg->getData, offset, 0);
+ if ((INT_PTR)tz != CB_ERR && tz != nullptr)
+ TimeZone_StoreByContact(hContact, szModule, tz);
+ }
+ else TimeZone_StoreByContact(hContact, szModule, nullptr);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(uint32_t) TimeZone_ToLocal(uint32_t timeVal)
+{
+ return TimeZone_UtcToLocal(nullptr, (mir_time)timeVal);
+}
+
+MIR_CORE_DLL(char*) TimeZone_ToString(mir_time timeVal, const char *szFormat, char *szDest, size_t cchDest)
+{
+ wchar_t *szTemp = (wchar_t*)alloca(cchDest*sizeof(wchar_t));
+ TimeZone_PrintTimeStamp(nullptr, timeVal, _A2T(szFormat), szTemp, cchDest, 0);
+ WideCharToMultiByte(CP_ACP, 0, szTemp, -1, szDest, (int)cchDest, nullptr, nullptr);
+ return szDest;
+}
+
+MIR_CORE_DLL(wchar_t*) TimeZone_ToStringW(mir_time timeVal, const wchar_t *wszFormat, wchar_t *wszDest, size_t cchDest)
+{
+ TimeZone_PrintTimeStamp(nullptr, timeVal, wszFormat, wszDest, cchDest, 0);
+ return wszDest;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GetLocalizedString(HKEY hSubKey, const wchar_t *szName, wchar_t *szBuf, uint32_t cbLen)
+{
+ DWORD dwLength = cbLen * sizeof(wchar_t);
+ RegQueryValueEx(hSubKey, szName, nullptr, nullptr, (unsigned char *)szBuf, &dwLength);
+ szBuf[min(dwLength / sizeof(wchar_t), cbLen - 1)] = 0;
+}
+
+void RecalculateTime(void)
+{
+ GetTimeZoneInformation(&myInfo.myTZ.tzi);
+ myInfo.timestamp = time(0);
+ myInfo.myTZ.offset = INT_MIN;
+
+ bool found = false;
+ DYNAMIC_TIME_ZONE_INFORMATION dtzi;
+
+ if (pfnGetDynamicTimeZoneInformation && pfnGetDynamicTimeZoneInformation(&dtzi) != TIME_ZONE_ID_INVALID) {
+ wcsncpy_s(myInfo.myTZ.tszName, dtzi.TimeZoneKeyName, _TRUNCATE);
+ found = true;
+ }
+
+ for (auto &tz : g_timezones) {
+ if (tz->offset != INT_MIN)
+ tz->offset = INT_MIN;
+
+ if (!found) {
+ if (!mir_wstrcmp(tz->tzi.StandardName, myInfo.myTZ.tzi.StandardName) || !mir_wstrcmp(tz->tzi.DaylightName, myInfo.myTZ.tzi.DaylightName)) {
+ wcsncpy_s(myInfo.myTZ.tszName, tz->tszName, _TRUNCATE);
+ found = true;
+ }
+ }
+ }
+}
+
+void InitTimeZones(void)
+{
+ REG_TZI_FORMAT tzi;
+ HKEY hKey;
+
+ const wchar_t *tszKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
+
+ /*
+ * use GetDynamicTimeZoneInformation() on Vista+ - this will return a structure with
+ * the registry key name, so finding our own time zone later will be MUCH easier for
+ * localized systems or systems with a MUI pack installed
+ */
+ if (IsWinVerVistaPlus())
+ pfnGetDynamicTimeZoneInformation = (pfnGetDynamicTimeZoneInformation_t)GetProcAddress(GetModuleHandle(L"kernel32"), "GetDynamicTimeZoneInformation");
+
+ if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, tszKey, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)) {
+ uint32_t dwIndex = 0;
+ HKEY hSubKey;
+ wchar_t tszName[MIM_TZ_NAMELEN];
+
+ DWORD dwSize = _countof(tszName);
+ while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, dwIndex++, tszName, &dwSize, nullptr, nullptr, nullptr, nullptr)) {
+ if (ERROR_SUCCESS == RegOpenKeyEx(hKey, tszName, 0, KEY_QUERY_VALUE, &hSubKey)) {
+ dwSize = sizeof(tszName);
+
+ DWORD dwLength = sizeof(tzi);
+ if (ERROR_SUCCESS != RegQueryValueEx(hSubKey, L"TZI", nullptr, nullptr, (unsigned char *)&tzi, &dwLength))
+ continue;
+
+ MIM_TIMEZONE *tz = new MIM_TIMEZONE;
+
+ tz->tzi.Bias = tzi.Bias;
+ tz->tzi.StandardDate = tzi.StandardDate;
+ tz->tzi.StandardBias = tzi.StandardBias;
+ tz->tzi.DaylightDate = tzi.DaylightDate;
+ tz->tzi.DaylightBias = tzi.DaylightBias;
+
+ mir_wstrcpy(tz->tszName, tszName);
+ tz->hash = mir_hashstrT(tszName);
+ tz->offset = INT_MIN;
+
+ GetLocalizedString(hSubKey, L"Display", tz->szDisplay, _countof(tz->szDisplay));
+ GetLocalizedString(hSubKey, L"Std", tz->tzi.StandardName, _countof(tz->tzi.StandardName));
+ GetLocalizedString(hSubKey, L"Dlt", tz->tzi.DaylightName, _countof(tz->tzi.DaylightName));
+
+ g_timezones.insert(tz);
+ g_timezonesBias.insert(tz);
+
+ RegCloseKey(hSubKey);
+ }
+ dwSize = _countof(tszName);
+ }
+ RegCloseKey(hKey);
+ }
+
+ RecalculateTime();
+}
diff --git a/src/mir_core/src/Windows/windowlist.cpp b/src/mir_core/src/Windows/windowlist.cpp
index 6b6e28ad66..616db3df5c 100644
--- a/src/mir_core/src/Windows/windowlist.cpp
+++ b/src/mir_core/src/Windows/windowlist.cpp
@@ -1,105 +1,105 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-
-struct TWindowListItem
-{
- TWindowListItem(UINT_PTR _param, HWND _wnd) :
- param(_param),
- hWnd(_wnd)
- {}
-
- UINT_PTR param;
- HWND hWnd;
-};
-
-struct TWindowList : public OBJLIST<TWindowListItem>
-{
- TWindowList() :
- OBJLIST<TWindowListItem>(10, NumericKeySortT)
- {}
-};
-
-MIR_CORE_DLL(MWindowList) WindowList_Create(void)
-{
- return new TWindowList();
-}
-
-MIR_CORE_DLL(void) WindowList_Destroy(MWindowList &hList)
-{
- delete hList;
- hList = nullptr;
-}
-
-MIR_CORE_DLL(int) WindowList_Add(MWindowList hList, HWND hwnd, UINT_PTR param)
-{
- if (hList == nullptr)
- return 1;
-
- hList->insert(new TWindowListItem(param, hwnd));
- return 0;
-}
-
-MIR_CORE_DLL(int) WindowList_Remove(MWindowList hList, HWND hwnd)
-{
- if (hList == nullptr) return 1;
-
- for (auto &it : *hList)
- if (it->hWnd == hwnd) {
- hList->removeItem(&it);
- return 0;
- }
-
- return 1;
-}
-
-MIR_CORE_DLL(HWND) WindowList_Find(MWindowList hList, UINT_PTR param)
-{
- if (hList == nullptr)
- return nullptr;
-
- TWindowListItem *p = hList->find((TWindowListItem*)&param);
- return (p == nullptr) ? nullptr : p->hWnd;
-}
-
-MIR_CORE_DLL(int) WindowList_Broadcast(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam)
-{
- if (hList == nullptr)
- return 0;
-
- for (auto &it : hList->rev_iter())
- SendMessage(it->hWnd, message, wParam, lParam);
- return 0;
-}
-
-MIR_CORE_DLL(int) WindowList_BroadcastAsync(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam)
-{
- if (hList == nullptr)
- return 0;
-
- for (auto &it : hList->rev_iter())
- PostMessage(it->hWnd, message, wParam, lParam);
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+struct TWindowListItem
+{
+ TWindowListItem(UINT_PTR _param, HWND _wnd) :
+ param(_param),
+ hWnd(_wnd)
+ {}
+
+ UINT_PTR param;
+ HWND hWnd;
+};
+
+struct TWindowList : public OBJLIST<TWindowListItem>
+{
+ TWindowList() :
+ OBJLIST<TWindowListItem>(10, NumericKeySortT)
+ {}
+};
+
+MIR_CORE_DLL(MWindowList) WindowList_Create(void)
+{
+ return new TWindowList();
+}
+
+MIR_CORE_DLL(void) WindowList_Destroy(MWindowList &hList)
+{
+ delete hList;
+ hList = nullptr;
+}
+
+MIR_CORE_DLL(int) WindowList_Add(MWindowList hList, HWND hwnd, UINT_PTR param)
+{
+ if (hList == nullptr)
+ return 1;
+
+ hList->insert(new TWindowListItem(param, hwnd));
+ return 0;
+}
+
+MIR_CORE_DLL(int) WindowList_Remove(MWindowList hList, HWND hwnd)
+{
+ if (hList == nullptr) return 1;
+
+ for (auto &it : *hList)
+ if (it->hWnd == hwnd) {
+ hList->removeItem(&it);
+ return 0;
+ }
+
+ return 1;
+}
+
+MIR_CORE_DLL(HWND) WindowList_Find(MWindowList hList, UINT_PTR param)
+{
+ if (hList == nullptr)
+ return nullptr;
+
+ TWindowListItem *p = hList->find((TWindowListItem*)&param);
+ return (p == nullptr) ? nullptr : p->hWnd;
+}
+
+MIR_CORE_DLL(int) WindowList_Broadcast(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (hList == nullptr)
+ return 0;
+
+ for (auto &it : hList->rev_iter())
+ SendMessage(it->hWnd, message, wParam, lParam);
+ return 0;
+}
+
+MIR_CORE_DLL(int) WindowList_BroadcastAsync(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (hList == nullptr)
+ return 0;
+
+ for (auto &it : hList->rev_iter())
+ PostMessage(it->hWnd, message, wParam, lParam);
+ return 0;
+}
diff --git a/src/mir_core/src/Windows/winutil.cpp b/src/mir_core/src/Windows/winutil.cpp
index 7a25523482..1d18041529 100644
--- a/src/mir_core/src/Windows/winutil.cpp
+++ b/src/mir_core/src/Windows/winutil.cpp
@@ -1,177 +1,177 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "../stdafx.h"
-
-MIR_CORE_DLL(int) Utils_SaveWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix)
-{
- WINDOWPLACEMENT wp;
- wp.length = sizeof(wp);
- GetWindowPlacement(hwnd, &wp);
-
- char szSettingName[64];
- mir_snprintf(szSettingName, "%sx", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.left);
-
- mir_snprintf(szSettingName, "%sy", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.top);
-
- mir_snprintf(szSettingName, "%swidth", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.right-wp.rcNormalPosition.left);
-
- mir_snprintf(szSettingName, "%sheight", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.bottom-wp.rcNormalPosition.top);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-EXTERN_C MIR_CORE_DLL(int) Utils_RestoreWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix, int flags)
-{
- WINDOWPLACEMENT wp;
- wp.length = sizeof(wp);
- GetWindowPlacement(hwnd, &wp);
-
- char szSettingName[64];
- mir_snprintf(szSettingName, "%sx", szNamePrefix);
- int x = db_get_dw(hContact, szModule, szSettingName, -1);
- if (x == -1)
- return 1;
-
- mir_snprintf(szSettingName, "%sy", szNamePrefix);
- int y = (int)db_get_dw(hContact, szModule, szSettingName, -1);
-
- if (flags & RWPF_NOSIZE)
- OffsetRect(&wp.rcNormalPosition, x-wp.rcNormalPosition.left, y-wp.rcNormalPosition.top);
- else {
- wp.rcNormalPosition.left = x;
- wp.rcNormalPosition.top = y;
-
- mir_snprintf(szSettingName, "%swidth", szNamePrefix);
- wp.rcNormalPosition.right = wp.rcNormalPosition.left+db_get_dw(hContact, szModule, szSettingName, -1);
-
- mir_snprintf(szSettingName, "%sheight", szNamePrefix);
- wp.rcNormalPosition.bottom = wp.rcNormalPosition.top+db_get_dw(hContact, szModule, szSettingName, -1);
- }
- wp.flags = 0;
- if (flags & RWPF_HIDDEN)
- wp.showCmd = SW_HIDE;
- if (flags & RWPF_NOACTIVATE)
- wp.showCmd = SW_SHOWNOACTIVATE;
-
- if (!(flags & RWPF_NOMOVE))
- Utils_AssertInsideScreen(&wp.rcNormalPosition);
-
- SetWindowPlacement(hwnd, &wp);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) Utils_AssertInsideScreen(RECT *rc)
-{
- if (rc == nullptr)
- return -1;
-
- RECT rcScreen;
- SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, FALSE);
- if (MonitorFromRect(rc, MONITOR_DEFAULTTONULL))
- return 0;
-
- MONITORINFO mi = { 0 };
- HMONITOR hMonitor = MonitorFromRect(rc, MONITOR_DEFAULTTONEAREST);
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hMonitor, &mi))
- rcScreen = mi.rcWork;
-
- if (rc->top >= rcScreen.bottom)
- OffsetRect(rc, 0, rcScreen.bottom - rc->bottom);
- else if (rc->bottom <= rcScreen.top)
- OffsetRect(rc, 0, rcScreen.top - rc->top);
- if (rc->left >= rcScreen.right)
- OffsetRect(rc, rcScreen.right - rc->right, 0);
- else if (rc->right <= rcScreen.left)
- OffsetRect(rc, rcScreen.left - rc->left, 0);
-
- return 1;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static NONCLIENTMETRICSW ncm = {};
-
-MIR_CORE_DLL(int) Utils_CorrectFontSize(int size)
-{
- if (!g_bEnableDpiAware)
- return size;
-
- if (!ncm.cbSize) {
- ncm.cbSize = sizeof(ncm);
- SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE);
- }
-
- return size * ncm.lfMessageFont.lfHeight / -12;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) Utils_ClipboardCopy(const char *pszText)
-{
- size_t cbLen = mir_strlen(pszText);
- if (!cbLen)
- return;
-
- if (!OpenClipboard(nullptr))
- return;
-
- EmptyClipboard();
-
- HGLOBAL hData = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, cbLen);
- if (hData) {
- mir_strcpy((char *)GlobalLock(hData), pszText);
- GlobalUnlock(hData);
- SetClipboardData(CF_TEXT, hData);
- }
- CloseClipboard();
-}
-
-MIR_CORE_DLL(void) Utils_ClipboardCopy(const wchar_t *pwszText)
-{
- size_t cbLen = mir_wstrlen(pwszText);
- if (!cbLen)
- return;
-
- if (!OpenClipboard(nullptr))
- return;
-
- EmptyClipboard();
-
- HGLOBAL hData = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (cbLen + 1) * sizeof(wchar_t));
- if (hData) {
- mir_wstrcpy((wchar_t *)GlobalLock(hData), pwszText);
- GlobalUnlock(hData);
- SetClipboardData(CF_UNICODETEXT, hData);
- }
- CloseClipboard();
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+MIR_CORE_DLL(int) Utils_SaveWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix)
+{
+ WINDOWPLACEMENT wp;
+ wp.length = sizeof(wp);
+ GetWindowPlacement(hwnd, &wp);
+
+ char szSettingName[64];
+ mir_snprintf(szSettingName, "%sx", szNamePrefix);
+ db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.left);
+
+ mir_snprintf(szSettingName, "%sy", szNamePrefix);
+ db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.top);
+
+ mir_snprintf(szSettingName, "%swidth", szNamePrefix);
+ db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.right-wp.rcNormalPosition.left);
+
+ mir_snprintf(szSettingName, "%sheight", szNamePrefix);
+ db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.bottom-wp.rcNormalPosition.top);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+EXTERN_C MIR_CORE_DLL(int) Utils_RestoreWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix, int flags)
+{
+ WINDOWPLACEMENT wp;
+ wp.length = sizeof(wp);
+ GetWindowPlacement(hwnd, &wp);
+
+ char szSettingName[64];
+ mir_snprintf(szSettingName, "%sx", szNamePrefix);
+ int x = db_get_dw(hContact, szModule, szSettingName, -1);
+ if (x == -1)
+ return 1;
+
+ mir_snprintf(szSettingName, "%sy", szNamePrefix);
+ int y = (int)db_get_dw(hContact, szModule, szSettingName, -1);
+
+ if (flags & RWPF_NOSIZE)
+ OffsetRect(&wp.rcNormalPosition, x-wp.rcNormalPosition.left, y-wp.rcNormalPosition.top);
+ else {
+ wp.rcNormalPosition.left = x;
+ wp.rcNormalPosition.top = y;
+
+ mir_snprintf(szSettingName, "%swidth", szNamePrefix);
+ wp.rcNormalPosition.right = wp.rcNormalPosition.left+db_get_dw(hContact, szModule, szSettingName, -1);
+
+ mir_snprintf(szSettingName, "%sheight", szNamePrefix);
+ wp.rcNormalPosition.bottom = wp.rcNormalPosition.top+db_get_dw(hContact, szModule, szSettingName, -1);
+ }
+ wp.flags = 0;
+ if (flags & RWPF_HIDDEN)
+ wp.showCmd = SW_HIDE;
+ if (flags & RWPF_NOACTIVATE)
+ wp.showCmd = SW_SHOWNOACTIVATE;
+
+ if (!(flags & RWPF_NOMOVE))
+ Utils_AssertInsideScreen(&wp.rcNormalPosition);
+
+ SetWindowPlacement(hwnd, &wp);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) Utils_AssertInsideScreen(RECT *rc)
+{
+ if (rc == nullptr)
+ return -1;
+
+ RECT rcScreen;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, FALSE);
+ if (MonitorFromRect(rc, MONITOR_DEFAULTTONULL))
+ return 0;
+
+ MONITORINFO mi = { 0 };
+ HMONITOR hMonitor = MonitorFromRect(rc, MONITOR_DEFAULTTONEAREST);
+ mi.cbSize = sizeof(mi);
+ if (GetMonitorInfo(hMonitor, &mi))
+ rcScreen = mi.rcWork;
+
+ if (rc->top >= rcScreen.bottom)
+ OffsetRect(rc, 0, rcScreen.bottom - rc->bottom);
+ else if (rc->bottom <= rcScreen.top)
+ OffsetRect(rc, 0, rcScreen.top - rc->top);
+ if (rc->left >= rcScreen.right)
+ OffsetRect(rc, rcScreen.right - rc->right, 0);
+ else if (rc->right <= rcScreen.left)
+ OffsetRect(rc, rcScreen.left - rc->left, 0);
+
+ return 1;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static NONCLIENTMETRICSW ncm = {};
+
+MIR_CORE_DLL(int) Utils_CorrectFontSize(int size)
+{
+ if (!g_bEnableDpiAware)
+ return size;
+
+ if (!ncm.cbSize) {
+ ncm.cbSize = sizeof(ncm);
+ SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE);
+ }
+
+ return size * ncm.lfMessageFont.lfHeight / -12;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(void) Utils_ClipboardCopy(const char *pszText)
+{
+ size_t cbLen = mir_strlen(pszText);
+ if (!cbLen)
+ return;
+
+ if (!OpenClipboard(nullptr))
+ return;
+
+ EmptyClipboard();
+
+ HGLOBAL hData = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, cbLen);
+ if (hData) {
+ mir_strcpy((char *)GlobalLock(hData), pszText);
+ GlobalUnlock(hData);
+ SetClipboardData(CF_TEXT, hData);
+ }
+ CloseClipboard();
+}
+
+MIR_CORE_DLL(void) Utils_ClipboardCopy(const wchar_t *pwszText)
+{
+ size_t cbLen = mir_wstrlen(pwszText);
+ if (!cbLen)
+ return;
+
+ if (!OpenClipboard(nullptr))
+ return;
+
+ EmptyClipboard();
+
+ HGLOBAL hData = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (cbLen + 1) * sizeof(wchar_t));
+ if (hData) {
+ mir_wstrcpy((wchar_t *)GlobalLock(hData), pwszText);
+ GlobalUnlock(hData);
+ SetClipboardData(CF_UNICODETEXT, hData);
+ }
+ CloseClipboard();
+}
diff --git a/src/mir_core/src/Windows/winver.cpp b/src/mir_core/src/Windows/winver.cpp
index 29a6fa7f3c..f52567ccab 100644
--- a/src/mir_core/src/Windows/winver.cpp
+++ b/src/mir_core/src/Windows/winver.cpp
@@ -1,372 +1,372 @@
-/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "../stdafx.h"
-
-#ifndef _WIN32_WINNT_WIN8
-#define _WIN32_WINNT_WIN8 0x0602 // Windows 8
-#endif
-
-#ifndef _WIN32_WINNT_WINBLUE
-#define _WIN32_WINNT_WINBLUE 0x0603 // Windows 8.1
-#endif
-
-#ifndef _WIN32_WINNT_WIN10
-#define _WIN32_WINNT_WIN10 0x0A00 // Windows 10
-#endif
-
-static int dwWinVer;
-
-void InitWinver()
-{
- uint32_t dwVer = LOWORD(GetVersion());
- dwWinVer = MAKEWORD(HIBYTE(dwVer), LOBYTE(dwVer));
-}
-
-MIR_CORE_DLL(BOOL) IsWinVerVistaPlus()
-{
- return dwWinVer >= _WIN32_WINNT_VISTA;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer7Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WIN7;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer8Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WIN8;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer81Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WINBLUE;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer10Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WIN10;
-}
-
-MIR_CORE_DLL(BOOL) IsFullScreen()
-{
- RECT rcScreen = { 0 };
-
- rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
- rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
-
- HMONITOR hMon = MonitorFromWindow(GetForegroundWindow(), MONITOR_DEFAULTTONEAREST);
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hMon, &mi))
- rcScreen = mi.rcMonitor;
-
- HWND hWndDesktop = GetDesktopWindow();
- HWND hWndShell = GetShellWindow();
-
- // check foregroundwindow
- HWND hWnd = GetForegroundWindow();
- if (hWnd && hWnd != hWndDesktop && hWnd != hWndShell) {
- wchar_t tszClassName[128] = L"";
- GetClassName(hWnd, tszClassName, _countof(tszClassName));
- if (wcscmp(tszClassName, L"WorkerW")) {
- RECT rect, rectw, recti;
- GetWindowRect(hWnd, &rectw);
-
- GetClientRect(hWnd, &rect);
- ClientToScreen(hWnd, (LPPOINT)&rect);
- ClientToScreen(hWnd, (LPPOINT)&rect.right);
-
- if (EqualRect(&rect, &rectw) && IntersectRect(&recti, &rect, &rcScreen) && EqualRect(&recti, &rcScreen))
- return true;
- }
- }
-
- return false;
-}
-
-MIR_CORE_DLL(BOOL) IsWorkstationLocked(void)
-{
- HDESK hDesk = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP);
- if (hDesk == nullptr)
- return true;
-
- wchar_t tszName[100];
- DWORD cbName;
- BOOL bLocked = (!GetUserObjectInformation(hDesk, UOI_NAME, tszName, _countof(tszName), &cbName) || mir_wstrcmpi(tszName, L"default") != 0);
- CloseDesktop(hDesk);
- return bLocked;
-}
-
-MIR_CORE_DLL(BOOL) IsTerminalDisconnected(void)
-{
- PVOID pBuffer = nullptr;
- DWORD pBytesReturned = 0;
- BOOL result = FALSE;
-
- if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState, (LPTSTR *)&pBuffer, &pBytesReturned))
- if (*(PDWORD)pBuffer == WTSDisconnected)
- result = TRUE;
-
- if (pBuffer)
- WTSFreeMemory(pBuffer);
- return result;
-}
-
-MIR_CORE_DLL(BOOL) IsScreenSaverRunning(void)
-{
- BOOL rc = FALSE;
- SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &rc, FALSE);
- return rc != 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(BOOL) OS_GetShortString(char *buf, size_t bufSize)
-{
- if (buf == nullptr || bufSize == 0)
- return false;
-
- mir_snprintf(buf, bufSize, "Windows NT %d.%d", HIBYTE(dwWinVer), LOBYTE(dwWinVer));
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifndef PRODUCT_CORE_N // Win8
-#define PRODUCT_CORE_SINGLELANGUAGE 0x00000064
-#define PRODUCT_PROFESSIONAL_WMC 0x00000067
-#endif
-
-typedef BOOL(WINAPI *PGPI)(uint32_t, uint32_t, uint32_t, uint32_t, PDWORD);
-typedef LPCSTR(WINAPI *WGV)(void);
-
-MIR_CORE_DLL(BOOL) OS_GetDisplayString(char *buf, size_t bufSize)
-{
- if (buf == nullptr || bufSize == 0)
- return 0;
-
- buf[0] = 0;
-
- OSVERSIONINFOEX osvi = { 0 };
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- BOOL bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
- if (!bOsVersionInfoEx) {
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (!GetVersionEx((OSVERSIONINFO*)&osvi))
- return false;
- }
-
- if (VER_PLATFORM_WIN32_NT != osvi.dwPlatformId || osvi.dwMajorVersion <= 4)
- return false;
-
- SYSTEM_INFO sysInfo = { 0 };
- GetNativeSystemInfo(&sysInfo);
-
- CMStringA ret("Microsoft ");
-
- // Test for the specific product.
- if (osvi.dwMajorVersion >= 6) {
- if (osvi.dwMajorVersion == 10) {
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 10 ");
- else
- ret.Append("Windows Server 10 ");
- }
- else switch (osvi.dwMinorVersion) {
- case 0:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows Vista ");
- else
- ret.Append("Windows Server 2008 ");
- break;
-
- case 1:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 7 ");
- else
- ret.Append("Windows Server 2008 R2 ");
- break;
-
- case 2:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 8 ");
- else
- ret.Append("Windows Server 2012 ");
- break;
-
- case 3:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 8.1 ");
- else
- ret.Append("Windows Server 2012 R2 ");
- break;
- }
-
- DWORD dwType = 0;
- HMODULE hKernel = GetModuleHandle(L"kernel32.dll");
- PGPI pGPI = (PGPI)GetProcAddress(hKernel, "GetProductInfo");
- if (pGPI != nullptr)
- pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
-
- switch (dwType) {
- case PRODUCT_ULTIMATE:
- ret.Append("Ultimate Edition");
- break;
- case PRODUCT_PROFESSIONAL:
- ret.Append("Professional Edition");
- break;
- case PRODUCT_PROFESSIONAL_WMC:
- ret.Append("Professional Edition with Media Center");
- break;
- case PRODUCT_HOME_PREMIUM:
- ret.Append("Home Premium Edition");
- break;
- case PRODUCT_HOME_BASIC:
- ret.Append("Home Basic Edition");
- break;
- case PRODUCT_ENTERPRISE:
- ret.Append("Enterprise Edition");
- break;
- case PRODUCT_BUSINESS:
- ret.Append("Business Edition");
- break;
- case PRODUCT_STARTER:
- ret.Append("Starter Edition");
- break;
- case PRODUCT_CLUSTER_SERVER:
- ret.Append("Cluster Server Edition");
- break;
- case PRODUCT_DATACENTER_SERVER:
- ret.Append("Datacenter Edition");
- break;
- case PRODUCT_DATACENTER_SERVER_CORE:
- ret.Append("Datacenter Edition (core installation)");
- break;
- case PRODUCT_ENTERPRISE_SERVER:
- ret.Append("Enterprise Edition");
- break;
- case PRODUCT_ENTERPRISE_SERVER_CORE:
- ret.Append("Enterprise Edition (core installation)");
- break;
- case PRODUCT_ENTERPRISE_SERVER_IA64:
- ret.Append("Enterprise Edition for Itanium-based Systems");
- break;
- case PRODUCT_SMALLBUSINESS_SERVER:
- ret.Append("Small Business Server");
- break;
- case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
- ret.Append("Small Business Server Premium Edition");
- break;
- case PRODUCT_STANDARD_SERVER:
- ret.Append("Standard Edition");
- break;
- case PRODUCT_STANDARD_SERVER_CORE:
- ret.Append("Standard Edition (core installation)");
- break;
- case PRODUCT_WEB_SERVER:
- ret.Append("Web Server Edition");
- break;
- case PRODUCT_CORE_SINGLELANGUAGE:
- ret.Append("Home Single Language");
- break;
- }
- if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
- ret.Append(", 64-bit");
- else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
- ret.Append(", 32-bit");
- }
-
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
- if (GetSystemMetrics(SM_SERVERR2))
- ret.Append("Windows Server 2003 R2, ");
- else if (osvi.wSuiteMask == VER_SUITE_STORAGE_SERVER)
- ret.Append("Windows Storage Server 2003");
- else if (osvi.wSuiteMask == VER_SUITE_WH_SERVER)
- ret.Append("Windows Home Server");
- else if (osvi.wProductType == VER_NT_WORKSTATION && sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
- ret.Append("Windows XP Professional x64 Edition");
- else
- ret.Append("Windows Server 2003, ");
-
- // Test for the server type.
- if (osvi.wProductType != VER_NT_WORKSTATION) {
- if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter Edition for Itanium-based Systems");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Enterprise Edition for Itanium-based Systems");
- }
- else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter x64 Edition");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Enterprise x64 Edition");
- else ret.Append("Standard x64 Edition");
- }
- else {
- if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
- ret.Append("Compute Cluster Edition");
- else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter Edition");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Enterprise Edition");
- else if (osvi.wSuiteMask & VER_SUITE_BLADE)
- ret.Append("Web Edition");
- else ret.Append("Standard Edition");
- }
- }
- }
-
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
- ret.Append("Windows XP ");
- if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
- ret.Append("Home Edition");
- else ret.Append("Professional");
- }
-
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
- ret.Append("Windows 2000 ");
-
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Professional");
- else {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter Server");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Advanced Server");
- else ret.Append("Server");
- }
- }
-
- // Include service pack (if any) and build number.
- if (mir_wstrlen(osvi.szCSDVersion) > 0) {
- ret.Append(" ");
- ret.Append(_T2A(osvi.szCSDVersion));
- }
-
- ret.AppendFormat(" (build %d)", osvi.dwBuildNumber);
-
- HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
- if (WGV wine_get_version = (WGV)GetProcAddress(hNtDll, "wine_get_version"))
- {
- ret.AppendFormat(" (Wine %s)", wine_get_version());
- }
-
- mir_strncpy(buf, ret, bufSize);
- return true;
-}
+/*
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "../stdafx.h"
+
+#ifndef _WIN32_WINNT_WIN8
+#define _WIN32_WINNT_WIN8 0x0602 // Windows 8
+#endif
+
+#ifndef _WIN32_WINNT_WINBLUE
+#define _WIN32_WINNT_WINBLUE 0x0603 // Windows 8.1
+#endif
+
+#ifndef _WIN32_WINNT_WIN10
+#define _WIN32_WINNT_WIN10 0x0A00 // Windows 10
+#endif
+
+static int dwWinVer;
+
+void InitWinver()
+{
+ uint32_t dwVer = LOWORD(GetVersion());
+ dwWinVer = MAKEWORD(HIBYTE(dwVer), LOBYTE(dwVer));
+}
+
+MIR_CORE_DLL(BOOL) IsWinVerVistaPlus()
+{
+ return dwWinVer >= _WIN32_WINNT_VISTA;
+}
+
+MIR_CORE_DLL(BOOL) IsWinVer7Plus()
+{
+ return dwWinVer >= _WIN32_WINNT_WIN7;
+}
+
+MIR_CORE_DLL(BOOL) IsWinVer8Plus()
+{
+ return dwWinVer >= _WIN32_WINNT_WIN8;
+}
+
+MIR_CORE_DLL(BOOL) IsWinVer81Plus()
+{
+ return dwWinVer >= _WIN32_WINNT_WINBLUE;
+}
+
+MIR_CORE_DLL(BOOL) IsWinVer10Plus()
+{
+ return dwWinVer >= _WIN32_WINNT_WIN10;
+}
+
+MIR_CORE_DLL(BOOL) IsFullScreen()
+{
+ RECT rcScreen = { 0 };
+
+ rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
+ rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
+
+ HMONITOR hMon = MonitorFromWindow(GetForegroundWindow(), MONITOR_DEFAULTTONEAREST);
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ if (GetMonitorInfo(hMon, &mi))
+ rcScreen = mi.rcMonitor;
+
+ HWND hWndDesktop = GetDesktopWindow();
+ HWND hWndShell = GetShellWindow();
+
+ // check foregroundwindow
+ HWND hWnd = GetForegroundWindow();
+ if (hWnd && hWnd != hWndDesktop && hWnd != hWndShell) {
+ wchar_t tszClassName[128] = L"";
+ GetClassName(hWnd, tszClassName, _countof(tszClassName));
+ if (wcscmp(tszClassName, L"WorkerW")) {
+ RECT rect, rectw, recti;
+ GetWindowRect(hWnd, &rectw);
+
+ GetClientRect(hWnd, &rect);
+ ClientToScreen(hWnd, (LPPOINT)&rect);
+ ClientToScreen(hWnd, (LPPOINT)&rect.right);
+
+ if (EqualRect(&rect, &rectw) && IntersectRect(&recti, &rect, &rcScreen) && EqualRect(&recti, &rcScreen))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+MIR_CORE_DLL(BOOL) IsWorkstationLocked(void)
+{
+ HDESK hDesk = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP);
+ if (hDesk == nullptr)
+ return true;
+
+ wchar_t tszName[100];
+ DWORD cbName;
+ BOOL bLocked = (!GetUserObjectInformation(hDesk, UOI_NAME, tszName, _countof(tszName), &cbName) || mir_wstrcmpi(tszName, L"default") != 0);
+ CloseDesktop(hDesk);
+ return bLocked;
+}
+
+MIR_CORE_DLL(BOOL) IsTerminalDisconnected(void)
+{
+ PVOID pBuffer = nullptr;
+ DWORD pBytesReturned = 0;
+ BOOL result = FALSE;
+
+ if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState, (LPTSTR *)&pBuffer, &pBytesReturned))
+ if (*(PDWORD)pBuffer == WTSDisconnected)
+ result = TRUE;
+
+ if (pBuffer)
+ WTSFreeMemory(pBuffer);
+ return result;
+}
+
+MIR_CORE_DLL(BOOL) IsScreenSaverRunning(void)
+{
+ BOOL rc = FALSE;
+ SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &rc, FALSE);
+ return rc != 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(BOOL) OS_GetShortString(char *buf, size_t bufSize)
+{
+ if (buf == nullptr || bufSize == 0)
+ return false;
+
+ mir_snprintf(buf, bufSize, "Windows NT %d.%d", HIBYTE(dwWinVer), LOBYTE(dwWinVer));
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifndef PRODUCT_CORE_N // Win8
+#define PRODUCT_CORE_SINGLELANGUAGE 0x00000064
+#define PRODUCT_PROFESSIONAL_WMC 0x00000067
+#endif
+
+typedef BOOL(WINAPI *PGPI)(uint32_t, uint32_t, uint32_t, uint32_t, PDWORD);
+typedef LPCSTR(WINAPI *WGV)(void);
+
+MIR_CORE_DLL(BOOL) OS_GetDisplayString(char *buf, size_t bufSize)
+{
+ if (buf == nullptr || bufSize == 0)
+ return 0;
+
+ buf[0] = 0;
+
+ OSVERSIONINFOEX osvi = { 0 };
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ BOOL bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
+ if (!bOsVersionInfoEx) {
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (!GetVersionEx((OSVERSIONINFO*)&osvi))
+ return false;
+ }
+
+ if (VER_PLATFORM_WIN32_NT != osvi.dwPlatformId || osvi.dwMajorVersion <= 4)
+ return false;
+
+ SYSTEM_INFO sysInfo = { 0 };
+ GetNativeSystemInfo(&sysInfo);
+
+ CMStringA ret("Microsoft ");
+
+ // Test for the specific product.
+ if (osvi.dwMajorVersion >= 6) {
+ if (osvi.dwMajorVersion == 10) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Windows 10 ");
+ else
+ ret.Append("Windows Server 10 ");
+ }
+ else switch (osvi.dwMinorVersion) {
+ case 0:
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Windows Vista ");
+ else
+ ret.Append("Windows Server 2008 ");
+ break;
+
+ case 1:
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Windows 7 ");
+ else
+ ret.Append("Windows Server 2008 R2 ");
+ break;
+
+ case 2:
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Windows 8 ");
+ else
+ ret.Append("Windows Server 2012 ");
+ break;
+
+ case 3:
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Windows 8.1 ");
+ else
+ ret.Append("Windows Server 2012 R2 ");
+ break;
+ }
+
+ DWORD dwType = 0;
+ HMODULE hKernel = GetModuleHandle(L"kernel32.dll");
+ PGPI pGPI = (PGPI)GetProcAddress(hKernel, "GetProductInfo");
+ if (pGPI != nullptr)
+ pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
+
+ switch (dwType) {
+ case PRODUCT_ULTIMATE:
+ ret.Append("Ultimate Edition");
+ break;
+ case PRODUCT_PROFESSIONAL:
+ ret.Append("Professional Edition");
+ break;
+ case PRODUCT_PROFESSIONAL_WMC:
+ ret.Append("Professional Edition with Media Center");
+ break;
+ case PRODUCT_HOME_PREMIUM:
+ ret.Append("Home Premium Edition");
+ break;
+ case PRODUCT_HOME_BASIC:
+ ret.Append("Home Basic Edition");
+ break;
+ case PRODUCT_ENTERPRISE:
+ ret.Append("Enterprise Edition");
+ break;
+ case PRODUCT_BUSINESS:
+ ret.Append("Business Edition");
+ break;
+ case PRODUCT_STARTER:
+ ret.Append("Starter Edition");
+ break;
+ case PRODUCT_CLUSTER_SERVER:
+ ret.Append("Cluster Server Edition");
+ break;
+ case PRODUCT_DATACENTER_SERVER:
+ ret.Append("Datacenter Edition");
+ break;
+ case PRODUCT_DATACENTER_SERVER_CORE:
+ ret.Append("Datacenter Edition (core installation)");
+ break;
+ case PRODUCT_ENTERPRISE_SERVER:
+ ret.Append("Enterprise Edition");
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_CORE:
+ ret.Append("Enterprise Edition (core installation)");
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_IA64:
+ ret.Append("Enterprise Edition for Itanium-based Systems");
+ break;
+ case PRODUCT_SMALLBUSINESS_SERVER:
+ ret.Append("Small Business Server");
+ break;
+ case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
+ ret.Append("Small Business Server Premium Edition");
+ break;
+ case PRODUCT_STANDARD_SERVER:
+ ret.Append("Standard Edition");
+ break;
+ case PRODUCT_STANDARD_SERVER_CORE:
+ ret.Append("Standard Edition (core installation)");
+ break;
+ case PRODUCT_WEB_SERVER:
+ ret.Append("Web Server Edition");
+ break;
+ case PRODUCT_CORE_SINGLELANGUAGE:
+ ret.Append("Home Single Language");
+ break;
+ }
+ if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+ ret.Append(", 64-bit");
+ else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+ ret.Append(", 32-bit");
+ }
+
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
+ if (GetSystemMetrics(SM_SERVERR2))
+ ret.Append("Windows Server 2003 R2, ");
+ else if (osvi.wSuiteMask == VER_SUITE_STORAGE_SERVER)
+ ret.Append("Windows Storage Server 2003");
+ else if (osvi.wSuiteMask == VER_SUITE_WH_SERVER)
+ ret.Append("Windows Home Server");
+ else if (osvi.wProductType == VER_NT_WORKSTATION && sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+ ret.Append("Windows XP Professional x64 Edition");
+ else
+ ret.Append("Windows Server 2003, ");
+
+ // Test for the server type.
+ if (osvi.wProductType != VER_NT_WORKSTATION) {
+ if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ ret.Append("Datacenter Edition for Itanium-based Systems");
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ ret.Append("Enterprise Edition for Itanium-based Systems");
+ }
+ else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ ret.Append("Datacenter x64 Edition");
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ ret.Append("Enterprise x64 Edition");
+ else ret.Append("Standard x64 Edition");
+ }
+ else {
+ if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
+ ret.Append("Compute Cluster Edition");
+ else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ ret.Append("Datacenter Edition");
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ ret.Append("Enterprise Edition");
+ else if (osvi.wSuiteMask & VER_SUITE_BLADE)
+ ret.Append("Web Edition");
+ else ret.Append("Standard Edition");
+ }
+ }
+ }
+
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
+ ret.Append("Windows XP ");
+ if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
+ ret.Append("Home Edition");
+ else ret.Append("Professional");
+ }
+
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
+ ret.Append("Windows 2000 ");
+
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Professional");
+ else {
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ ret.Append("Datacenter Server");
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ ret.Append("Advanced Server");
+ else ret.Append("Server");
+ }
+ }
+
+ // Include service pack (if any) and build number.
+ if (mir_wstrlen(osvi.szCSDVersion) > 0) {
+ ret.Append(" ");
+ ret.Append(_T2A(osvi.szCSDVersion));
+ }
+
+ ret.AppendFormat(" (build %d)", osvi.dwBuildNumber);
+
+ HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
+ if (WGV wine_get_version = (WGV)GetProcAddress(hNtDll, "wine_get_version"))
+ {
+ ret.AppendFormat(" (Wine %s)", wine_get_version());
+ }
+
+ mir_strncpy(buf, ret, bufSize);
+ return true;
+}
diff --git a/src/mir_core/src/binbuffer.cpp b/src/mir_core/src/binbuffer.cpp
index fbde7bfb4d..77016fbda9 100644
--- a/src/mir_core/src/binbuffer.cpp
+++ b/src/mir_core/src/binbuffer.cpp
@@ -1,170 +1,170 @@
-/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-struct BufImpl
-{
- uint32_t size, lockCount;
-
- BufImpl* alloc(size_t newSize)
- {
- bool bEmpty = (this == nullptr);
- auto *res = (BufImpl *)mir_realloc(this, newSize + sizeof(BufImpl));
- if (bEmpty) {
- res->lockCount = 1;
- res->size = 0;
- }
- return res;
- }
-
- BufImpl* realloc(size_t newSize)
- {
- bool bEmpty;
- newSize += sizeof(BufImpl);
- if (this != nullptr) {
- newSize += size;
- bEmpty = false;
- }
- else bEmpty = true;
-
- auto *res = (BufImpl *)mir_realloc(this, newSize);
- if (bEmpty) {
- res->lockCount = 1;
- res->size = 0;
- }
- return res;
- }
-
- void free()
- {
- if (this == nullptr)
- return;
-
- if (lockCount == 1)
- mir_free(this);
- else
- lockCount--;
- }
-};
-
-__forceinline BufImpl* ptr2buf(uint8_t *p)
-{
- return (p == nullptr) ? nullptr : (BufImpl*)p-1;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MBinBuffer::MBinBuffer()
-{}
-
-MBinBuffer::MBinBuffer(const MBinBuffer &orig)
-{
- ptr2buf(m_buf)->free();
-
- BufImpl *p = ptr2buf(m_buf = orig.m_buf);
- if (p)
- p->lockCount++;
-}
-
-MBinBuffer::MBinBuffer(size_t preAlloc)
-{
- BufImpl *p = (BufImpl *)mir_alloc(sizeof(BufImpl) + preAlloc);
- p->lockCount = 1;
- p->size = (unsigned)preAlloc;
- m_buf = (uint8_t *)(p + 1);
-}
-
-MBinBuffer& MBinBuffer::operator=(MBinBuffer &&from) noexcept
-{
- m_buf = from.m_buf;
- from.m_buf = nullptr;
- return *this;
-}
-
-MBinBuffer::~MBinBuffer()
-{
- ptr2buf(m_buf)->free();
-}
-
-void MBinBuffer::append(const void *pBuf, size_t bufLen)
-{
- if (pBuf == nullptr || bufLen == 0)
- return;
-
- BufImpl *p = ptr2buf(m_buf)->realloc(bufLen);
- if (p) {
- m_buf = (uint8_t *)(p + 1);
- memcpy(m_buf + p->size, pBuf, bufLen);
- p->size += (unsigned)bufLen;
- }
- else m_buf = nullptr;
-}
-
-void MBinBuffer::appendBefore(const void *pBuf, size_t bufLen)
-{
- if (pBuf == nullptr || bufLen == 0)
- return;
-
- BufImpl *p = ptr2buf(m_buf)->realloc(bufLen);
- if (p) {
- m_buf = (uint8_t *)(p + 1);
- memmove(m_buf + bufLen, m_buf, p->size);
- memcpy(m_buf, pBuf, bufLen);
- p->size += (unsigned)bufLen;
- }
- else m_buf = nullptr;
-}
-
-void MBinBuffer::assign(const void *pBuf, size_t bufLen)
-{
- if (pBuf == nullptr || bufLen == 0)
- return;
-
- BufImpl *p = ptr2buf(m_buf)->alloc(bufLen);
- if (p) {
- p->size = (unsigned)bufLen;
- m_buf = (uint8_t *)(p + 1);
- memcpy(m_buf, pBuf, bufLen);
- }
- else m_buf = nullptr;
-}
-
-size_t MBinBuffer::length() const
-{
- BufImpl *p = ptr2buf(m_buf);
- return (p) ? p->size : 0;
-}
-
-void MBinBuffer::remove(size_t sz)
-{
- BufImpl *p = ptr2buf(m_buf);
- if (!p)
- return;
-
- if (sz > p->size)
- sz = p->size;
-
- if (p->size == sz) {
- p->free();
- m_buf = nullptr;
- }
- else {
- memmove(m_buf, m_buf + sz, p->size - sz);
- p->size -= (unsigned)sz;
- }
-}
+/*
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+
+struct BufImpl
+{
+ uint32_t size, lockCount;
+
+ BufImpl* alloc(size_t newSize)
+ {
+ bool bEmpty = (this == nullptr);
+ auto *res = (BufImpl *)mir_realloc(this, newSize + sizeof(BufImpl));
+ if (bEmpty) {
+ res->lockCount = 1;
+ res->size = 0;
+ }
+ return res;
+ }
+
+ BufImpl* realloc(size_t newSize)
+ {
+ bool bEmpty;
+ newSize += sizeof(BufImpl);
+ if (this != nullptr) {
+ newSize += size;
+ bEmpty = false;
+ }
+ else bEmpty = true;
+
+ auto *res = (BufImpl *)mir_realloc(this, newSize);
+ if (bEmpty) {
+ res->lockCount = 1;
+ res->size = 0;
+ }
+ return res;
+ }
+
+ void free()
+ {
+ if (this == nullptr)
+ return;
+
+ if (lockCount == 1)
+ mir_free(this);
+ else
+ lockCount--;
+ }
+};
+
+__forceinline BufImpl* ptr2buf(uint8_t *p)
+{
+ return (p == nullptr) ? nullptr : (BufImpl*)p-1;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MBinBuffer::MBinBuffer()
+{}
+
+MBinBuffer::MBinBuffer(const MBinBuffer &orig)
+{
+ ptr2buf(m_buf)->free();
+
+ BufImpl *p = ptr2buf(m_buf = orig.m_buf);
+ if (p)
+ p->lockCount++;
+}
+
+MBinBuffer::MBinBuffer(size_t preAlloc)
+{
+ BufImpl *p = (BufImpl *)mir_alloc(sizeof(BufImpl) + preAlloc);
+ p->lockCount = 1;
+ p->size = (unsigned)preAlloc;
+ m_buf = (uint8_t *)(p + 1);
+}
+
+MBinBuffer& MBinBuffer::operator=(MBinBuffer &&from) noexcept
+{
+ m_buf = from.m_buf;
+ from.m_buf = nullptr;
+ return *this;
+}
+
+MBinBuffer::~MBinBuffer()
+{
+ ptr2buf(m_buf)->free();
+}
+
+void MBinBuffer::append(const void *pBuf, size_t bufLen)
+{
+ if (pBuf == nullptr || bufLen == 0)
+ return;
+
+ BufImpl *p = ptr2buf(m_buf)->realloc(bufLen);
+ if (p) {
+ m_buf = (uint8_t *)(p + 1);
+ memcpy(m_buf + p->size, pBuf, bufLen);
+ p->size += (unsigned)bufLen;
+ }
+ else m_buf = nullptr;
+}
+
+void MBinBuffer::appendBefore(const void *pBuf, size_t bufLen)
+{
+ if (pBuf == nullptr || bufLen == 0)
+ return;
+
+ BufImpl *p = ptr2buf(m_buf)->realloc(bufLen);
+ if (p) {
+ m_buf = (uint8_t *)(p + 1);
+ memmove(m_buf + bufLen, m_buf, p->size);
+ memcpy(m_buf, pBuf, bufLen);
+ p->size += (unsigned)bufLen;
+ }
+ else m_buf = nullptr;
+}
+
+void MBinBuffer::assign(const void *pBuf, size_t bufLen)
+{
+ if (pBuf == nullptr || bufLen == 0)
+ return;
+
+ BufImpl *p = ptr2buf(m_buf)->alloc(bufLen);
+ if (p) {
+ p->size = (unsigned)bufLen;
+ m_buf = (uint8_t *)(p + 1);
+ memcpy(m_buf, pBuf, bufLen);
+ }
+ else m_buf = nullptr;
+}
+
+size_t MBinBuffer::length() const
+{
+ BufImpl *p = ptr2buf(m_buf);
+ return (p) ? p->size : 0;
+}
+
+void MBinBuffer::remove(size_t sz)
+{
+ BufImpl *p = ptr2buf(m_buf);
+ if (!p)
+ return;
+
+ if (sz > p->size)
+ sz = p->size;
+
+ if (p->size == sz) {
+ p->free();
+ m_buf = nullptr;
+ }
+ else {
+ memmove(m_buf, m_buf + sz, p->size - sz);
+ p->size -= (unsigned)sz;
+ }
+}
diff --git a/src/mir_core/src/bitmaps.cpp b/src/mir_core/src/bitmaps.cpp
index eb1a8b02d2..5ab665df84 100644
--- a/src/mir_core/src/bitmaps.cpp
+++ b/src/mir_core/src/bitmaps.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team,
+Copyright (C) 2012-23 Miranda NG team,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/mir_core/src/db.cpp b/src/mir_core/src/db.cpp
index 8fb13fd4d3..362d359f17 100644
--- a/src/mir_core/src/db.cpp
+++ b/src/mir_core/src/db.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/mir_core/src/http.cpp b/src/mir_core/src/http.cpp
index e983676dd0..879df3b038 100644
--- a/src/mir_core/src/http.cpp
+++ b/src/mir_core/src/http.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
diff --git a/src/mir_core/src/lists.cpp b/src/mir_core/src/lists.cpp
index 21d890a148..c5b1b36825 100644
--- a/src/mir_core/src/lists.cpp
+++ b/src/mir_core/src/lists.cpp
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
Copyright (c) 2000-12 Miranda IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
diff --git a/src/mir_core/src/logger.cpp b/src/mir_core/src/logger.cpp
index 24240d691d..83218f88ed 100644
--- a/src/mir_core/src/logger.cpp
+++ b/src/mir_core/src/logger.cpp
@@ -1,203 +1,203 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-#define SECRET_SIGNATURE 0x87654321
-
-struct Logger
-{
- Logger(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFilename, unsigned options) :
- m_name(mir_strdup(pszName)),
- m_descr(mir_wstrdup(ptszDescr)),
- m_fileName(mir_wstrdup(ptszFilename)),
- m_options(options),
- m_signature(SECRET_SIGNATURE),
- m_out(nullptr),
- m_lastwrite(0)
- {
- }
-
- ~Logger()
- {
- if (m_out)
- fclose(m_out);
- }
-
- int m_signature;
- ptrA m_name;
- ptrW m_fileName, m_descr;
- FILE *m_out;
- time_t m_lastwrite;
- unsigned m_options;
- mir_cs m_cs;
-};
-
-static int CompareLoggers(const Logger *p1, const Logger *p2)
-{ return strcmp(p1->m_name, p2->m_name);
-}
-
-static OBJLIST<Logger> arLoggers(1, CompareLoggers);
-
-void InitLogs()
-{
-}
-
-void UninitLogs()
-{
- arLoggers.destroy();
-}
-
-void CheckLogs()
-{
- time_t tm = time(0);
-
- for (auto &p : arLoggers) {
- mir_cslock lck(p->m_cs);
- if (p->m_out && tm - p->m_lastwrite > 5) {
- fclose(p->m_out);
- p->m_out = nullptr;
- }
- else fflush(p->m_out);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(HANDLE) mir_createLog(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFile, unsigned options)
-{
- if (ptszFile == nullptr)
- return nullptr;
-
- Logger *result = new Logger(pszName, ptszDescr, ptszFile, options);
- if (result == nullptr)
- return nullptr;
-
- int idx = arLoggers.getIndex(result);
- if (idx != -1) {
- delete result;
- return &arLoggers[idx];
- }
-
- CreatePathToFileW(ptszFile);
- _wremove(ptszFile);
- arLoggers.insert(result);
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-static Logger* prepareLogger(HANDLE hLogger)
-{
- if (hLogger == nullptr)
- return nullptr;
-
- Logger *p = (Logger*)hLogger;
- return (p->m_signature == SECRET_SIGNATURE) ? p : nullptr;
-}
-
-MIR_CORE_DLL(void) mir_closeLog(HANDLE hLogger)
-{
- Logger *p = prepareLogger(hLogger);
- if (p != nullptr)
- arLoggers.remove(p);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_C_CORE_DLL(int) mir_writeLogA(HANDLE hLogger, const char *format, ...)
-{
- Logger *p = prepareLogger(hLogger);
- if (p == nullptr)
- return 1;
-
- mir_cslock lck(p->m_cs);
- if (p->m_out == nullptr)
- if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
- return 2;
-
- va_list args;
- va_start(args, format);
- vfprintf(p->m_out, format, args);
- va_end(args);
-
- p->m_lastwrite = time(0);
- return 0;
-}
-
-MIR_C_CORE_DLL(int) mir_writeLogW(HANDLE hLogger, const wchar_t *format, ...)
-{
- Logger *p = prepareLogger(hLogger);
- if (p == nullptr)
- return 1;
-
- mir_cslock lck(p->m_cs);
- if (p->m_out == nullptr)
- if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
- return 2;
-
- va_list args;
- va_start(args, format);
- vfwprintf(p->m_out, format, args);
- va_end(args);
-
- p->m_lastwrite = time(0);
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) mir_writeLogVA(HANDLE hLogger, const char *format, va_list args)
-{
- Logger *p = prepareLogger(hLogger);
- if (p == nullptr)
- return 1;
-
- mir_cslock lck(p->m_cs);
- if (p->m_out == nullptr)
- if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
- return 2;
-
- vfprintf(p->m_out, format, args);
-
- p->m_lastwrite = time(0);
- return 0;
-}
-
-MIR_CORE_DLL(int) mir_writeLogVW(HANDLE hLogger, const wchar_t *format, va_list args)
-{
- Logger *p = prepareLogger(hLogger);
- if (p == nullptr)
- return 1;
-
- mir_cslock lck(p->m_cs);
- if (p->m_out == nullptr)
- if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
- return 2;
-
- vfwprintf(p->m_out, format, args);
-
- p->m_lastwrite = time(0);
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+#define SECRET_SIGNATURE 0x87654321
+
+struct Logger
+{
+ Logger(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFilename, unsigned options) :
+ m_name(mir_strdup(pszName)),
+ m_descr(mir_wstrdup(ptszDescr)),
+ m_fileName(mir_wstrdup(ptszFilename)),
+ m_options(options),
+ m_signature(SECRET_SIGNATURE),
+ m_out(nullptr),
+ m_lastwrite(0)
+ {
+ }
+
+ ~Logger()
+ {
+ if (m_out)
+ fclose(m_out);
+ }
+
+ int m_signature;
+ ptrA m_name;
+ ptrW m_fileName, m_descr;
+ FILE *m_out;
+ time_t m_lastwrite;
+ unsigned m_options;
+ mir_cs m_cs;
+};
+
+static int CompareLoggers(const Logger *p1, const Logger *p2)
+{ return strcmp(p1->m_name, p2->m_name);
+}
+
+static OBJLIST<Logger> arLoggers(1, CompareLoggers);
+
+void InitLogs()
+{
+}
+
+void UninitLogs()
+{
+ arLoggers.destroy();
+}
+
+void CheckLogs()
+{
+ time_t tm = time(0);
+
+ for (auto &p : arLoggers) {
+ mir_cslock lck(p->m_cs);
+ if (p->m_out && tm - p->m_lastwrite > 5) {
+ fclose(p->m_out);
+ p->m_out = nullptr;
+ }
+ else fflush(p->m_out);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(HANDLE) mir_createLog(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFile, unsigned options)
+{
+ if (ptszFile == nullptr)
+ return nullptr;
+
+ Logger *result = new Logger(pszName, ptszDescr, ptszFile, options);
+ if (result == nullptr)
+ return nullptr;
+
+ int idx = arLoggers.getIndex(result);
+ if (idx != -1) {
+ delete result;
+ return &arLoggers[idx];
+ }
+
+ CreatePathToFileW(ptszFile);
+ _wremove(ptszFile);
+ arLoggers.insert(result);
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+static Logger* prepareLogger(HANDLE hLogger)
+{
+ if (hLogger == nullptr)
+ return nullptr;
+
+ Logger *p = (Logger*)hLogger;
+ return (p->m_signature == SECRET_SIGNATURE) ? p : nullptr;
+}
+
+MIR_CORE_DLL(void) mir_closeLog(HANDLE hLogger)
+{
+ Logger *p = prepareLogger(hLogger);
+ if (p != nullptr)
+ arLoggers.remove(p);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_C_CORE_DLL(int) mir_writeLogA(HANDLE hLogger, const char *format, ...)
+{
+ Logger *p = prepareLogger(hLogger);
+ if (p == nullptr)
+ return 1;
+
+ mir_cslock lck(p->m_cs);
+ if (p->m_out == nullptr)
+ if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
+ return 2;
+
+ va_list args;
+ va_start(args, format);
+ vfprintf(p->m_out, format, args);
+ va_end(args);
+
+ p->m_lastwrite = time(0);
+ return 0;
+}
+
+MIR_C_CORE_DLL(int) mir_writeLogW(HANDLE hLogger, const wchar_t *format, ...)
+{
+ Logger *p = prepareLogger(hLogger);
+ if (p == nullptr)
+ return 1;
+
+ mir_cslock lck(p->m_cs);
+ if (p->m_out == nullptr)
+ if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
+ return 2;
+
+ va_list args;
+ va_start(args, format);
+ vfwprintf(p->m_out, format, args);
+ va_end(args);
+
+ p->m_lastwrite = time(0);
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) mir_writeLogVA(HANDLE hLogger, const char *format, va_list args)
+{
+ Logger *p = prepareLogger(hLogger);
+ if (p == nullptr)
+ return 1;
+
+ mir_cslock lck(p->m_cs);
+ if (p->m_out == nullptr)
+ if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
+ return 2;
+
+ vfprintf(p->m_out, format, args);
+
+ p->m_lastwrite = time(0);
+ return 0;
+}
+
+MIR_CORE_DLL(int) mir_writeLogVW(HANDLE hLogger, const wchar_t *format, va_list args)
+{
+ Logger *p = prepareLogger(hLogger);
+ if (p == nullptr)
+ return 1;
+
+ mir_cslock lck(p->m_cs);
+ if (p->m_out == nullptr)
+ if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
+ return 2;
+
+ vfwprintf(p->m_out, format, args);
+
+ p->m_lastwrite = time(0);
+ return 0;
+}
diff --git a/src/mir_core/src/memory.cpp b/src/mir_core/src/memory.cpp
index 8cf95b81ab..5183310b48 100644
--- a/src/mir_core/src/memory.cpp
+++ b/src/mir_core/src/memory.cpp
@@ -1,295 +1,295 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-#define BLOCK_ALLOCED 0xABBABABA
-#define BLOCK_FREED 0xDEADBEEF
-
-static int CheckBlock(void* blk)
-{
- int result = FALSE;
- char* p = (char*)blk - sizeof(uint32_t)*2;
- uint32_t size, *b, *e;
-
- __try
- {
- size = *(uint32_t*)p;
- b = (uint32_t*)&p[ sizeof(uint32_t) ];
- e = (uint32_t*)&p[ sizeof(uint32_t)*2 + size ];
-
- if (*b != BLOCK_ALLOCED || *e != BLOCK_ALLOCED)
- {
- #ifdef _MSC_VER
- if (*b == BLOCK_FREED && *e == BLOCK_FREED)
- OutputDebugStringA("memory block is already deleted\n");
- else
- OutputDebugStringA("memory block is corrupted\n");
- #if defined(_DEBUG)
- DebugBreak();
- #endif
- #endif
- }
- else result = TRUE;
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- #ifdef _MSC_VER
- OutputDebugStringA("access violation during checking memory block\n");
- #if defined(_DEBUG)
- DebugBreak();
- #endif
- #endif
- }
-
- return result;
-}
-
-/******************************************************************************/
-
-MIR_C_CORE_DLL(void*) mir_alloc(size_t size)
-{
- if (size == 0)
- return nullptr;
-
- char *p = (char*)malloc(size + sizeof(uint32_t)* 3);
- if (p == nullptr) {
- #ifdef _MSC_VER
- OutputDebugStringA("memory overflow\n");
- #if defined(_DEBUG)
- DebugBreak();
- #endif
- #endif
- return nullptr;
- }
-
- *(uint32_t*)p = (uint32_t)size;
- *(uint32_t*)&p[sizeof(uint32_t)] = BLOCK_ALLOCED;
- *(uint32_t*)&p[size + sizeof(uint32_t)*2] = BLOCK_ALLOCED;
- return p + sizeof(uint32_t)* 2;
-}
-
-/******************************************************************************/
-
-MIR_C_CORE_DLL(void*) mir_calloc(size_t size)
-{
- void* p = mir_alloc(size);
- if (p != nullptr)
- memset(p, 0, size);
- return p;
-}
-
-/******************************************************************************/
-
-MIR_C_CORE_DLL(void*) mir_realloc(void* ptr, size_t size)
-{
- char *p;
-
- if (ptr != nullptr) {
- if (!CheckBlock(ptr))
- return nullptr;
- p = (char*)ptr - sizeof(uint32_t)*2;
- }
- else p = nullptr;
-
- p = (char*)realloc(p, size + sizeof(uint32_t)*3);
- if (p == nullptr) {
- #ifdef _MSC_VER
- OutputDebugStringA("memory overflow\n");
- #if defined(_DEBUG)
- DebugBreak();
- #endif
- #endif
- return nullptr;
- }
-
- *(uint32_t*)p = (uint32_t)size;
- *(uint32_t*)&p[sizeof(uint32_t)] = BLOCK_ALLOCED;
- *(uint32_t*)&p[size + sizeof(uint32_t)*2] = BLOCK_ALLOCED;
- return p + sizeof(uint32_t)*2;
-}
-
-/******************************************************************************/
-
-MIR_C_CORE_DLL(void) mir_free(void* ptr)
-{
- char* p;
- uint32_t size;
-
- if (ptr == nullptr)
- return;
- if (!CheckBlock(ptr))
- return;
-
- p = (char*)ptr - sizeof(uint32_t)*2;
- size = *(uint32_t*)p;
-
- *(uint32_t*)&p[sizeof(uint32_t)] = BLOCK_FREED;
- *(uint32_t*)&p[size + sizeof(uint32_t)*2] = BLOCK_FREED;
- free(p);
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(char*) mir_strdup(const char *str)
-{
- if (str == nullptr)
- return nullptr;
-
- char *p = (char*)mir_alloc(strlen(str)+1);
- if (p)
- strcpy(p, str);
- return p;
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrdup(const wchar_t *str)
-{
- if (str == nullptr)
- return nullptr;
-
- wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(wcslen(str)+1));
- if (p)
- wcscpy(p, str);
- return p;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(char*) mir_strndup(const char *str, size_t len)
-{
- if (str == nullptr || len == 0)
- return nullptr;
-
- char *p = (char*)mir_alloc(len+1);
- if (p) {
- memcpy(p, str, len);
- p[len] = 0;
- }
- return p;
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrndup(const wchar_t *str, size_t len)
-{
- if (str == nullptr || len == 0)
- return nullptr;
-
- wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(len+1));
- if (p) {
- memcpy(p, str, sizeof(wchar_t)*len);
- p[len] = 0;
- }
- return p;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(int) mir_snprintf(char *buffer, size_t count, const char* fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- int len = _vsnprintf(buffer, count-1, fmt, va);
- va_end(va);
- buffer[count-1] = 0;
- return len;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(int) mir_snwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- int len = _vsnwprintf(buffer, count-1, fmt, va);
- va_end(va);
- buffer[count-1] = 0;
- return len;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(int) mir_vsnprintf(char *buffer, size_t count, const char* fmt, va_list va)
-{
- int len = _vsnprintf(buffer, count-1, fmt, va);
- buffer[count-1] = 0;
- return len;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(int) mir_vsnwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, va_list va)
-{
- int len = _vsnwprintf(buffer, count-1, fmt, va);
- buffer[count-1] = 0;
- return len;
-}
-
-/******************************************************************************/
-
-#ifdef _MSC_VER
-MIR_CORE_DLL(wchar_t*) mir_a2u_cp(const char* src, int codepage)
-{
- if (src == nullptr)
- return nullptr;
-
- int cbLen = MultiByteToWideChar(codepage, 0, src, -1, nullptr, 0);
- wchar_t* result = (wchar_t*)mir_alloc(sizeof(wchar_t)*(cbLen+1));
- if (result == nullptr)
- return nullptr;
-
- MultiByteToWideChar(codepage, 0, src, -1, result, cbLen);
- result[cbLen] = 0;
- return result;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(wchar_t*) mir_a2u(const char* src)
-{
- return mir_a2u_cp(src, Langpack_GetDefaultCodePage());
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(char*) mir_u2a_cp(const wchar_t* src, int codepage)
-{
- if (src == nullptr)
- return nullptr;
-
- int cbLen = WideCharToMultiByte(codepage, 0, src, -1, nullptr, 0, nullptr, nullptr);
- char* result = (char*)mir_alloc(cbLen+1);
- if (result == nullptr)
- return nullptr;
-
- WideCharToMultiByte(codepage, 0, src, -1, result, cbLen, nullptr, nullptr);
- result[cbLen] = 0;
- return result;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(char*) mir_u2a(const wchar_t* src)
-{
- return mir_u2a_cp(src, Langpack_GetDefaultCodePage());
-}
-#endif
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+#define BLOCK_ALLOCED 0xABBABABA
+#define BLOCK_FREED 0xDEADBEEF
+
+static int CheckBlock(void* blk)
+{
+ int result = FALSE;
+ char* p = (char*)blk - sizeof(uint32_t)*2;
+ uint32_t size, *b, *e;
+
+ __try
+ {
+ size = *(uint32_t*)p;
+ b = (uint32_t*)&p[ sizeof(uint32_t) ];
+ e = (uint32_t*)&p[ sizeof(uint32_t)*2 + size ];
+
+ if (*b != BLOCK_ALLOCED || *e != BLOCK_ALLOCED)
+ {
+ #ifdef _MSC_VER
+ if (*b == BLOCK_FREED && *e == BLOCK_FREED)
+ OutputDebugStringA("memory block is already deleted\n");
+ else
+ OutputDebugStringA("memory block is corrupted\n");
+ #if defined(_DEBUG)
+ DebugBreak();
+ #endif
+ #endif
+ }
+ else result = TRUE;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ #ifdef _MSC_VER
+ OutputDebugStringA("access violation during checking memory block\n");
+ #if defined(_DEBUG)
+ DebugBreak();
+ #endif
+ #endif
+ }
+
+ return result;
+}
+
+/******************************************************************************/
+
+MIR_C_CORE_DLL(void*) mir_alloc(size_t size)
+{
+ if (size == 0)
+ return nullptr;
+
+ char *p = (char*)malloc(size + sizeof(uint32_t)* 3);
+ if (p == nullptr) {
+ #ifdef _MSC_VER
+ OutputDebugStringA("memory overflow\n");
+ #if defined(_DEBUG)
+ DebugBreak();
+ #endif
+ #endif
+ return nullptr;
+ }
+
+ *(uint32_t*)p = (uint32_t)size;
+ *(uint32_t*)&p[sizeof(uint32_t)] = BLOCK_ALLOCED;
+ *(uint32_t*)&p[size + sizeof(uint32_t)*2] = BLOCK_ALLOCED;
+ return p + sizeof(uint32_t)* 2;
+}
+
+/******************************************************************************/
+
+MIR_C_CORE_DLL(void*) mir_calloc(size_t size)
+{
+ void* p = mir_alloc(size);
+ if (p != nullptr)
+ memset(p, 0, size);
+ return p;
+}
+
+/******************************************************************************/
+
+MIR_C_CORE_DLL(void*) mir_realloc(void* ptr, size_t size)
+{
+ char *p;
+
+ if (ptr != nullptr) {
+ if (!CheckBlock(ptr))
+ return nullptr;
+ p = (char*)ptr - sizeof(uint32_t)*2;
+ }
+ else p = nullptr;
+
+ p = (char*)realloc(p, size + sizeof(uint32_t)*3);
+ if (p == nullptr) {
+ #ifdef _MSC_VER
+ OutputDebugStringA("memory overflow\n");
+ #if defined(_DEBUG)
+ DebugBreak();
+ #endif
+ #endif
+ return nullptr;
+ }
+
+ *(uint32_t*)p = (uint32_t)size;
+ *(uint32_t*)&p[sizeof(uint32_t)] = BLOCK_ALLOCED;
+ *(uint32_t*)&p[size + sizeof(uint32_t)*2] = BLOCK_ALLOCED;
+ return p + sizeof(uint32_t)*2;
+}
+
+/******************************************************************************/
+
+MIR_C_CORE_DLL(void) mir_free(void* ptr)
+{
+ char* p;
+ uint32_t size;
+
+ if (ptr == nullptr)
+ return;
+ if (!CheckBlock(ptr))
+ return;
+
+ p = (char*)ptr - sizeof(uint32_t)*2;
+ size = *(uint32_t*)p;
+
+ *(uint32_t*)&p[sizeof(uint32_t)] = BLOCK_FREED;
+ *(uint32_t*)&p[size + sizeof(uint32_t)*2] = BLOCK_FREED;
+ free(p);
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(char*) mir_strdup(const char *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ char *p = (char*)mir_alloc(strlen(str)+1);
+ if (p)
+ strcpy(p, str);
+ return p;
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrdup(const wchar_t *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(wcslen(str)+1));
+ if (p)
+ wcscpy(p, str);
+ return p;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(char*) mir_strndup(const char *str, size_t len)
+{
+ if (str == nullptr || len == 0)
+ return nullptr;
+
+ char *p = (char*)mir_alloc(len+1);
+ if (p) {
+ memcpy(p, str, len);
+ p[len] = 0;
+ }
+ return p;
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrndup(const wchar_t *str, size_t len)
+{
+ if (str == nullptr || len == 0)
+ return nullptr;
+
+ wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(len+1));
+ if (p) {
+ memcpy(p, str, sizeof(wchar_t)*len);
+ p[len] = 0;
+ }
+ return p;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(int) mir_snprintf(char *buffer, size_t count, const char* fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ int len = _vsnprintf(buffer, count-1, fmt, va);
+ va_end(va);
+ buffer[count-1] = 0;
+ return len;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(int) mir_snwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ int len = _vsnwprintf(buffer, count-1, fmt, va);
+ va_end(va);
+ buffer[count-1] = 0;
+ return len;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(int) mir_vsnprintf(char *buffer, size_t count, const char* fmt, va_list va)
+{
+ int len = _vsnprintf(buffer, count-1, fmt, va);
+ buffer[count-1] = 0;
+ return len;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(int) mir_vsnwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, va_list va)
+{
+ int len = _vsnwprintf(buffer, count-1, fmt, va);
+ buffer[count-1] = 0;
+ return len;
+}
+
+/******************************************************************************/
+
+#ifdef _MSC_VER
+MIR_CORE_DLL(wchar_t*) mir_a2u_cp(const char* src, int codepage)
+{
+ if (src == nullptr)
+ return nullptr;
+
+ int cbLen = MultiByteToWideChar(codepage, 0, src, -1, nullptr, 0);
+ wchar_t* result = (wchar_t*)mir_alloc(sizeof(wchar_t)*(cbLen+1));
+ if (result == nullptr)
+ return nullptr;
+
+ MultiByteToWideChar(codepage, 0, src, -1, result, cbLen);
+ result[cbLen] = 0;
+ return result;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(wchar_t*) mir_a2u(const char* src)
+{
+ return mir_a2u_cp(src, Langpack_GetDefaultCodePage());
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(char*) mir_u2a_cp(const wchar_t* src, int codepage)
+{
+ if (src == nullptr)
+ return nullptr;
+
+ int cbLen = WideCharToMultiByte(codepage, 0, src, -1, nullptr, 0, nullptr, nullptr);
+ char* result = (char*)mir_alloc(cbLen+1);
+ if (result == nullptr)
+ return nullptr;
+
+ WideCharToMultiByte(codepage, 0, src, -1, result, cbLen, nullptr, nullptr);
+ result[cbLen] = 0;
+ return result;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(char*) mir_u2a(const wchar_t* src)
+{
+ return mir_u2a_cp(src, Langpack_GetDefaultCodePage());
+}
+#endif
diff --git a/src/mir_core/src/miranda.h b/src/mir_core/src/miranda.h
index 7264f27444..2b725888f2 100644
--- a/src/mir_core/src/miranda.h
+++ b/src/mir_core/src/miranda.h
@@ -1,101 +1,101 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#pragma once
-
-void UnloadLangPackModule(void);
-
-int InitialiseModularEngine(void);
-void DestroyModularEngine(void);
-
-int InitPathUtils(void);
-
-extern HINSTANCE g_hInst;
-extern HWND hAPCWindow;
-extern HANDLE hThreadQueueEmpty;
-extern HCURSOR g_hCursorNS, g_hCursorWE;
-extern bool g_bEnableDpiAware;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// modules.cpp
-
-struct THookSubscriber
-{
- HINSTANCE hOwner;
- int type;
- union {
- struct {
- union {
- MIRANDAHOOK pfnHook;
- MIRANDAHOOKPARAM pfnHookParam;
- MIRANDAHOOKOBJ pfnHookObj;
- MIRANDAHOOKOBJPARAM pfnHookObjParam;
- };
- void* object;
- LPARAM lParam;
- };
- struct {
- HWND hwnd;
- UINT message;
- };
- };
-};
-
-#define HOOK_SECRET_SIGNATURE 0xDEADBABA
-
-struct THook : public MZeroedObject
-{
- char name[MAXMODULELABELLENGTH];
- int id;
- int subscriberCount;
- THookSubscriber* subscriber;
- MIRANDAHOOK pfnHook;
- uint32_t secretSignature = HOOK_SECRET_SIGNATURE;
- mir_cs csHook;
-};
-
-extern LIST<CMPluginBase> pluginListAddr;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// langpack.cpp
-
-char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// miranda.cpp
-
-EXTERN_C MIR_CORE_DLL(void) BeginMessageLoop(void);
-EXTERN_C MIR_CORE_DLL(void) EnterMessageLoop(void);
-EXTERN_C MIR_CORE_DLL(void) LeaveMessageLoop(void);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// threads.cpp
-
-extern uint32_t mir_tls;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// utils.cpp
-
-typedef BOOL(MIR_SYSCALL *PGENRANDOM)(void*, uint32_t);
-extern PGENRANDOM pfnRtlGenRandom;
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#pragma once
+
+void UnloadLangPackModule(void);
+
+int InitialiseModularEngine(void);
+void DestroyModularEngine(void);
+
+int InitPathUtils(void);
+
+extern HINSTANCE g_hInst;
+extern HWND hAPCWindow;
+extern HANDLE hThreadQueueEmpty;
+extern HCURSOR g_hCursorNS, g_hCursorWE;
+extern bool g_bEnableDpiAware;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// modules.cpp
+
+struct THookSubscriber
+{
+ HINSTANCE hOwner;
+ int type;
+ union {
+ struct {
+ union {
+ MIRANDAHOOK pfnHook;
+ MIRANDAHOOKPARAM pfnHookParam;
+ MIRANDAHOOKOBJ pfnHookObj;
+ MIRANDAHOOKOBJPARAM pfnHookObjParam;
+ };
+ void* object;
+ LPARAM lParam;
+ };
+ struct {
+ HWND hwnd;
+ UINT message;
+ };
+ };
+};
+
+#define HOOK_SECRET_SIGNATURE 0xDEADBABA
+
+struct THook : public MZeroedObject
+{
+ char name[MAXMODULELABELLENGTH];
+ int id;
+ int subscriberCount;
+ THookSubscriber* subscriber;
+ MIRANDAHOOK pfnHook;
+ uint32_t secretSignature = HOOK_SECRET_SIGNATURE;
+ mir_cs csHook;
+};
+
+extern LIST<CMPluginBase> pluginListAddr;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// langpack.cpp
+
+char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// miranda.cpp
+
+EXTERN_C MIR_CORE_DLL(void) BeginMessageLoop(void);
+EXTERN_C MIR_CORE_DLL(void) EnterMessageLoop(void);
+EXTERN_C MIR_CORE_DLL(void) LeaveMessageLoop(void);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// threads.cpp
+
+extern uint32_t mir_tls;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// utils.cpp
+
+typedef BOOL(MIR_SYSCALL *PGENRANDOM)(void*, uint32_t);
+extern PGENRANDOM pfnRtlGenRandom;
diff --git a/src/mir_core/src/modules.cpp b/src/mir_core/src/modules.cpp
index 1636d7449e..0d471c8c6c 100644
--- a/src/mir_core/src/modules.cpp
+++ b/src/mir_core/src/modules.cpp
@@ -1,704 +1,704 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-// list of hooks
-
-static int compareHooks(const THook* p1, const THook* p2)
-{
- return strcmp(p1->name, p2->name);
-}
-
-static LIST<THook> hooks(50, compareHooks);
-
-struct THookToMainThreadItem
-{
- THook* hook;
- HANDLE hDoneEvent;
- WPARAM wParam;
- LPARAM lParam;
- int result;
-};
-
-// list of services
-
-struct TService
-{
- uint32_t nameHash;
- HINSTANCE hOwner;
- union
- {
- MIRANDASERVICE pfnService;
- MIRANDASERVICEPARAM pfnServiceParam;
- MIRANDASERVICEOBJ pfnServiceObj;
- MIRANDASERVICEOBJPARAM pfnServiceObjParam;
- };
- int flags;
- LPARAM lParam;
- void* object;
- char name[1];
-};
-
-LIST<TService> services(100, NumericKeySortT);
-
-struct TServiceToMainThreadItem
-{
- HANDLE hDoneEvent;
- WPARAM wParam;
- LPARAM lParam;
- int result;
- const char *name;
-};
-
-// other static variables
-static BOOL bServiceMode = FALSE;
-static mir_cs csHooks, csServices;
-static uint32_t mainThreadId;
-static int sttHookId = 1;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-__forceinline HANDLE getThreadEvent()
-{
- HANDLE pData = (HANDLE)TlsGetValue(mir_tls);
- if (pData == nullptr) {
- pData = CreateEvent(nullptr, FALSE, FALSE, nullptr);
- TlsSetValue(mir_tls, pData);
- }
- return pData;
-}
-
-static int QueueMainThread(PAPCFUNC pFunc, void* pParam, HANDLE hDoneEvent)
-{
- int result = PostMessage(hAPCWindow, WM_USER + 1, (WPARAM)pFunc, (LPARAM)pParam); // let this get processed in its own time
- if (hDoneEvent)
- WaitForSingleObject(hDoneEvent, INFINITE);
-
- return result;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// HOOKS
-
-MIR_CORE_DLL(HANDLE) CreateHookableEvent(const char *name)
-{
- if (name == nullptr)
- return nullptr;
-
- mir_cslock lck(csHooks);
-
- int idx;
- if ((idx = hooks.getIndex((THook*)name)) != -1)
- return hooks[idx];
-
- THook *newItem = new THook();
- strncpy(newItem->name, name, sizeof(newItem->name)); newItem->name[MAXMODULELABELLENGTH - 1] = 0;
- newItem->id = sttHookId++;
- hooks.insert(newItem);
- return (HANDLE)newItem;
-}
-
-MIR_CORE_DLL(int) DestroyHookableEvent(HANDLE hEvent)
-{
- if (hEvent == nullptr)
- return 1;
-
- mir_cslock lck(csHooks);
-
- int idx;
- if ((idx = hooks.getIndex((THook*)hEvent)) == -1)
- return 1;
-
- THook *p = hooks[idx];
- p->secretSignature = 0;
- if (p->subscriberCount) {
- mir_free(p->subscriber);
- p->subscriber = nullptr;
- p->subscriberCount = 0;
- }
- hooks.remove(idx);
- delete p;
- return 0;
-}
-
-MIR_CORE_DLL(int) SetHookDefaultForHookableEvent(HANDLE hEvent, MIRANDAHOOK pfnHook)
-{
- THook *p = (THook*)hEvent;
-
- mir_cslock lck(csHooks);
- if (hooks.getIndex(p) != -1)
- p->pfnHook = pfnHook;
- return 0;
-}
-
-MIR_CORE_DLL(int) CallPluginEventHook(HINSTANCE hInst, const char *pszEvent, WPARAM wParam, LPARAM lParam)
-{
- int idx;
- if ((idx = hooks.getIndex((THook *)pszEvent)) == -1)
- return -1;
-
- THook *p = hooks[idx];
- if (p == nullptr || hInst == nullptr)
- return -1;
-
- mir_cslock lck(p->csHook);
- for (int i = 0; i < p->subscriberCount; i++) {
- THookSubscriber* s = &p->subscriber[i];
- if (s->hOwner != hInst)
- continue;
-
- int returnVal;
- switch (s->type) {
- case 1: returnVal = s->pfnHook(wParam, lParam); break;
- case 2: returnVal = s->pfnHookParam(wParam, lParam, s->lParam); break;
- case 3: returnVal = s->pfnHookObj(s->object, wParam, lParam); break;
- case 4: returnVal = s->pfnHookObjParam(s->object, wParam, lParam, s->lParam); break;
- case 5: returnVal = SendMessage(s->hwnd, s->message, wParam, lParam); break;
- default: continue;
- }
- if (returnVal)
- return returnVal;
- }
-
- if (p->subscriberCount == 0 && p->pfnHook != nullptr)
- return p->pfnHook(wParam, lParam);
-
- return 0;
-}
-
-MIR_CORE_DLL(int) CallObjectEventHook(void *pObject, HANDLE hEvent, WPARAM wParam, LPARAM lParam)
-{
- THook *p = (THook*)hEvent;
- if (p == nullptr || pObject == nullptr)
- return -1;
-
- mir_cslock lck(p->csHook);
- for (int i = 0; i < p->subscriberCount; i++) {
- THookSubscriber* s = &p->subscriber[i];
- if (s->object != pObject)
- continue;
-
- int returnVal;
- switch (s->type) {
- case 3: returnVal = s->pfnHookObj(s->object, wParam, lParam); break;
- case 4: returnVal = s->pfnHookObjParam(s->object, wParam, lParam, s->lParam); break;
- default: continue;
- }
- if (returnVal)
- return returnVal;
- }
-
- if (p->subscriberCount == 0 && p->pfnHook != nullptr)
- return p->pfnHook(wParam, lParam);
-
- return 0;
-}
-
-static int CallHookSubscribers(THook *p, WPARAM wParam, LPARAM lParam)
-{
- if (p == nullptr)
- return -1;
-
- mir_cslock lck(p->csHook);
-
- // NOTE: We've got the critical section while all this lot are called. That's mostly safe, though.
- for (int i = 0; i < p->subscriberCount; i++) {
- THookSubscriber* s = &p->subscriber[i];
-
- int returnVal;
- switch (s->type) {
- case 1: returnVal = s->pfnHook(wParam, lParam); break;
- case 2: returnVal = s->pfnHookParam(wParam, lParam, s->lParam); break;
- case 3: returnVal = s->pfnHookObj(s->object, wParam, lParam); break;
- case 4: returnVal = s->pfnHookObjParam(s->object, wParam, lParam, s->lParam); break;
- case 5: returnVal = SendMessage(s->hwnd, s->message, wParam, lParam); break;
- default: continue;
- }
- if (returnVal)
- return returnVal;
- }
-
- // call the default hook if any
- if (p->pfnHook != nullptr)
- return p->pfnHook(wParam, lParam);
-
- return 0;
-}
-
-enum { hookOk, hookEmpty, hookInvalid };
-
-int checkHook(THook *p)
-{
- if (p == nullptr)
- return hookInvalid;
-
- int ret;
- __try {
- if (p->secretSignature != HOOK_SECRET_SIGNATURE)
- ret = hookInvalid;
- else if (p->subscriberCount == 0 && p->pfnHook == nullptr)
- ret = hookEmpty;
- else
- ret = hookOk;
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- ret = hookInvalid;
- }
-
- return ret;
-}
-
-static void CALLBACK HookToMainAPCFunc(ULONG_PTR dwParam)
-{
- THookToMainThreadItem* item = (THookToMainThreadItem*)dwParam;
- item->result = CallHookSubscribers(item->hook, item->wParam, item->lParam);
- SetEvent(item->hDoneEvent);
-}
-
-MIR_CORE_DLL(int) NotifyEventHooks(HANDLE hEvent, WPARAM wParam, LPARAM lParam)
-{
- switch (checkHook((THook*)hEvent)) {
- case hookInvalid: return -1;
- case hookEmpty: return 0;
- }
-
- if (GetCurrentThreadId() == mainThreadId)
- return CallHookSubscribers((THook*)hEvent, wParam, lParam);
-
- THookToMainThreadItem item;
- item.hDoneEvent = getThreadEvent();
- item.hook = (THook*)hEvent;
- item.wParam = wParam;
- item.lParam = lParam;
- QueueMainThread(HookToMainAPCFunc, &item, item.hDoneEvent);
- return item.result;
-}
-
-MIR_CORE_DLL(int) NotifyFastHook(HANDLE hEvent, WPARAM wParam, LPARAM lParam)
-{
- switch (checkHook((THook*)hEvent)) {
- case hookInvalid: return -1;
- case hookEmpty: return 0;
- }
-
- return CallHookSubscribers((THook*)hEvent, wParam, lParam);
-}
-
-extern "C" MIR_CORE_DLL(int) GetSubscribersCount(THook* pHook)
-{
- switch (checkHook(pHook)) {
- case hookInvalid:
- case hookEmpty: return 0;
- }
- return pHook->subscriberCount;
-}
-
-static HANDLE HookEventInt(int type, const char *name, MIRANDAHOOK hookProc, void* object, LPARAM lParam)
-{
- mir_cslock lck(csHooks);
-
- int idx;
- if ((idx = hooks.getIndex((THook*)name)) == -1)
- return nullptr;
-
- THook *p = hooks[idx];
- p->subscriber = (THookSubscriber*)mir_realloc(p->subscriber, sizeof(THookSubscriber)*(p->subscriberCount + 1));
-
- THookSubscriber &s = p->subscriber[p->subscriberCount];
- s.type = type;
- s.pfnHook = hookProc;
- s.object = object;
- s.lParam = lParam;
- s.hOwner = GetInstByAddress(hookProc);
- p->subscriberCount++;
-
- return (HANDLE)((p->id << 16) | p->subscriberCount);
-}
-
-MIR_CORE_DLL(HANDLE) HookEvent(const char *name, MIRANDAHOOK hookProc)
-{
- return HookEventInt(1, name, hookProc, nullptr, 0);
-}
-
-MIR_CORE_DLL(HANDLE) HookEventParam(const char *name, MIRANDAHOOKPARAM hookProc, LPARAM lParam)
-{
- return HookEventInt(2, name, (MIRANDAHOOK)hookProc, nullptr, lParam);
-}
-
-MIR_CORE_DLL(HANDLE) HookEventObj(const char *name, MIRANDAHOOKOBJ hookProc, void* object)
-{
- return HookEventInt(3, name, (MIRANDAHOOK)hookProc, object, 0);
-}
-
-MIR_CORE_DLL(HANDLE) HookEventObjParam(const char *name, MIRANDAHOOKOBJPARAM hookProc, void* object, LPARAM lParam)
-{
- return HookEventInt(4, name, (MIRANDAHOOK)hookProc, object, lParam);
-}
-
-MIR_CORE_DLL(HANDLE) HookTemporaryEvent(const char *name, MIRANDAHOOK hookProc)
-{
- mir_cslockfull lck(csHooks);
-
- int idx;
- if ((idx = hooks.getIndex((THook*)name)) == -1) {
- lck.unlock();
- hookProc(0, 0);
- return nullptr;
- }
-
- THook *p = hooks[idx];
- p->subscriber = (THookSubscriber*)mir_realloc(p->subscriber, sizeof(THookSubscriber)*(p->subscriberCount + 1));
-
- THookSubscriber &s = p->subscriber[p->subscriberCount];
- memset(&s, 0, sizeof(THookSubscriber));
- s.type = 1;
- s.pfnHook = hookProc;
- s.hOwner = GetInstByAddress(hookProc);
-
- p->subscriberCount++;
- return (HANDLE)((p->id << 16) | p->subscriberCount);
-}
-
-MIR_CORE_DLL(HANDLE) HookEventMessage(const char *name, HWND hwnd, UINT message)
-{
- mir_cslock lck(csHooks);
-
- int idx;
- if ((idx = hooks.getIndex((THook*)name)) == -1)
- return nullptr;
-
- THook *p = hooks[idx];
- p->subscriber = (THookSubscriber*)mir_realloc(p->subscriber, sizeof(THookSubscriber)*(p->subscriberCount + 1));
- p->subscriber[p->subscriberCount].type = 5;
- p->subscriber[p->subscriberCount].hwnd = hwnd;
- p->subscriber[p->subscriberCount].message = message;
- p->subscriberCount++;
- return (HANDLE)((p->id << 16) | p->subscriberCount);
-}
-
-MIR_CORE_DLL(int) UnhookEvent(HANDLE hHook)
-{
- if (hHook == nullptr)
- return 0;
-
- int hookId = (INT_PTR)hHook >> 16;
- int subscriberId = ((INT_PTR)hHook & 0xFFFF) - 1;
-
- mir_cslock lck(csHooks);
-
- THook *p = nullptr;
- for (auto &it : hooks)
- if (it->id == hookId) {
- p = it;
- break;
- }
-
- if (p == nullptr)
- return 1;
-
- if (subscriberId >= p->subscriberCount || subscriberId < 0)
- return 1;
-
- p->subscriber[subscriberId].type = 0;
- p->subscriber[subscriberId].pfnHook = nullptr;
- p->subscriber[subscriberId].hOwner = nullptr;
- while (p->subscriberCount && p->subscriber[p->subscriberCount - 1].type == 0)
- p->subscriberCount--;
- if (p->subscriberCount == 0) {
- mir_free(p->subscriber);
- p->subscriber = nullptr;
- }
- return 0;
-}
-
-MIR_CORE_DLL(void) KillModuleEventHooks(HINSTANCE hInst)
-{
- mir_cslock lck(csHooks);
-
- for (auto &it : hooks.rev_iter()) {
- if (it->subscriberCount == 0)
- continue;
-
- for (int j = it->subscriberCount - 1; j >= 0; j--) {
- if (it->subscriber[j].hOwner != hInst)
- continue;
-
- char szModuleName[MAX_PATH];
- GetModuleFileNameA(it->subscriber[j].hOwner, szModuleName, sizeof(szModuleName));
- UnhookEvent((HANDLE)((it->id << 16) + j + 1));
- if (it->subscriberCount == 0)
- break;
- }
- }
-}
-
-MIR_CORE_DLL(void) KillObjectEventHooks(void* pObject)
-{
- mir_cslock lck(csHooks);
-
- for (auto &it : hooks.rev_iter()) {
- if (it->subscriberCount == 0)
- continue;
-
- for (int j = it->subscriberCount - 1; j >= 0; j--) {
- if (it->subscriber[j].object == pObject) {
- UnhookEvent((HANDLE)((it->id << 16) + j + 1));
- if (it->subscriberCount == 0)
- break;
- }
- }
- }
-}
-
-static void DestroyHooks()
-{
- mir_cslock lck(csHooks);
-
- for (auto &it : hooks) {
- if (it->subscriberCount)
- mir_free(it->subscriber);
- delete it;
- }
-}
-
-/////////////////////SERVICES
-
-static __inline TService* FindServiceByName(const char *name)
-{
- unsigned hash = mir_hashstr(name);
- return services.find((TService*)&hash);
-}
-
-static HANDLE CreateServiceInt(int type, const char *name, MIRANDASERVICE serviceProc, void* object, LPARAM lParam)
-{
- if (name == nullptr)
- return nullptr;
-
- TService tmp;
- tmp.nameHash = mir_hashstr(name);
-
- mir_cslock lck(csServices);
-
- if (services.getIndex(&tmp) != -1)
- return nullptr;
-
- TService* p = (TService*)mir_alloc(sizeof(*p) + strlen(name));
- strcpy(p->name, name);
- p->nameHash = tmp.nameHash;
- p->pfnService = serviceProc;
- p->hOwner = GetInstByAddress(serviceProc);
- p->flags = type;
- p->lParam = lParam;
- p->object = object;
- services.insert(p);
-
- return (HANDLE)tmp.nameHash;
-}
-
-MIR_CORE_DLL(HANDLE) CreateServiceFunction(const char *name, MIRANDASERVICE serviceProc)
-{
- return CreateServiceInt(0, name, serviceProc, nullptr, 0);
-}
-
-MIR_CORE_DLL(HANDLE) CreateServiceFunctionParam(const char *name, MIRANDASERVICEPARAM serviceProc, LPARAM lParam)
-{
- return CreateServiceInt(1, name, (MIRANDASERVICE)serviceProc, nullptr, lParam);
-}
-
-MIR_CORE_DLL(HANDLE) CreateServiceFunctionObj(const char *name, MIRANDASERVICEOBJ serviceProc, void* object)
-{
- return CreateServiceInt(2, name, (MIRANDASERVICE)serviceProc, object, 0);
-}
-
-MIR_CORE_DLL(HANDLE) CreateServiceFunctionObjParam(const char *name, MIRANDASERVICEOBJPARAM serviceProc, void* object, LPARAM lParam)
-{
- return CreateServiceInt(3, name, (MIRANDASERVICE)serviceProc, object, lParam);
-}
-
-MIR_CORE_DLL(HANDLE) CreateProtoServiceFunction(const char *szModule, const char *szService, MIRANDASERVICE serviceProc)
-{
- char str[MAXMODULELABELLENGTH * 2];
- strncpy_s(str, szModule, _TRUNCATE);
- strncat_s(str, szService, _TRUNCATE);
- return CreateServiceFunction(str, serviceProc);
-}
-
-MIR_CORE_DLL(int) DestroyServiceFunction(HANDLE hService)
-{
- mir_cslock lck(csServices);
-
- int idx = services.getIndex((TService*)&hService);
- if (idx != -1) {
- mir_free(services[idx]);
- services.remove(idx);
- }
-
- return 0;
-}
-
-MIR_CORE_DLL(bool) ServiceExists(const char *name)
-{
- if (name == nullptr)
- return FALSE;
-
- mir_cslock lck(csServices);
- return FindServiceByName(name) != nullptr;
-}
-
-MIR_CORE_DLL(INT_PTR) CallService(const char *name, WPARAM wParam, LPARAM lParam)
-{
- if (name == nullptr)
- return CALLSERVICE_NOTFOUND;
-
- TService *pService;
- {
- mir_cslock lck(csServices);
- if ((pService = FindServiceByName(name)) == nullptr)
- return CALLSERVICE_NOTFOUND;
- }
-
- MIRANDASERVICE pfnService = pService->pfnService;
- int flags = pService->flags;
- LPARAM fnParam = pService->lParam;
- void* object = pService->object;
- switch (flags) {
- case 1: return ((MIRANDASERVICEPARAM)pfnService)(wParam, lParam, fnParam);
- case 2: return ((MIRANDASERVICEOBJ)pfnService)(object, wParam, lParam);
- case 3: return ((MIRANDASERVICEOBJPARAM)pfnService)(object, wParam, lParam, fnParam);
- default: return pfnService(wParam, lParam);
- }
-}
-
-static void CALLBACK CallServiceToMainAPCFunc(ULONG_PTR dwParam)
-{
- TServiceToMainThreadItem *item = (TServiceToMainThreadItem*)dwParam;
- item->result = CallService(item->name, item->wParam, item->lParam);
- SetEvent(item->hDoneEvent);
-}
-
-MIR_CORE_DLL(INT_PTR) CallServiceSync(const char *name, WPARAM wParam, LPARAM lParam)
-{
- if (name == nullptr)
- return CALLSERVICE_NOTFOUND;
-
- // the service is looked up within the main thread, since the time it takes
- // for the APC queue to clear the service being called maybe removed.
- // even thou it may exists before the call, the critsec can't be locked between calls.
- if (GetCurrentThreadId() == mainThreadId)
- return CallService(name, wParam, lParam);
-
- TServiceToMainThreadItem item;
- item.wParam = wParam;
- item.lParam = lParam;
- item.name = name;
- item.hDoneEvent = getThreadEvent();
- QueueMainThread(CallServiceToMainAPCFunc, &item, item.hDoneEvent);
- return item.result;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) CallFunctionAsync(void(__stdcall *func)(void *), void *arg)
-{
- if (GetCurrentThreadId() == mainThreadId)
- func(arg);
- else
- QueueMainThread((PAPCFUNC)func, arg, nullptr);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct TSyncCallParam
-{
- INT_PTR(__stdcall *func)(void *);
- void *arg;
- HANDLE hDoneEvent;
- INT_PTR result;
-};
-
-static void CALLBACK CallFuncToMainAPCFunc(ULONG_PTR dwParam)
-{
- TSyncCallParam *item = (TSyncCallParam*)dwParam;
- item->result = (*item->func)(item->arg);
- SetEvent(item->hDoneEvent);
-}
-
-MIR_CORE_DLL(INT_PTR) CallFunctionSync(INT_PTR(__stdcall *func)(void *), void *arg)
-{
- if (GetCurrentThreadId() == mainThreadId)
- return func(arg);
-
- TSyncCallParam param = { func, arg, getThreadEvent() };
- QueueMainThread(CallFuncToMainAPCFunc, &param, param.hDoneEvent);
- return param.result;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) KillModuleServices(HINSTANCE hInst)
-{
- mir_cslock lck(csServices);
-
- for (auto &it : services.rev_iter()) {
- if (it->hOwner == hInst) {
- char szModuleName[MAX_PATH];
- GetModuleFileNameA(it->hOwner, szModuleName, sizeof(szModuleName));
- DestroyServiceFunction((HANDLE)it->nameHash);
- }
- }
-}
-
-MIR_CORE_DLL(void) KillObjectServices(void* pObject)
-{
- mir_cslock lck(csServices);
-
- for (auto &it : services.rev_iter())
- if (it->object == pObject)
- DestroyServiceFunction((HANDLE)it->nameHash);
-}
-
-static void DestroyServices()
-{
- mir_cslock lck(csServices);
-
- for (auto &it : services)
- mir_free(it);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-int InitialiseModularEngine(void)
-{
- mainThreadId = GetCurrentThreadId();
- return 0;
-}
-
-void DestroyModularEngine(void)
-{
- DestroyHooks();
- DestroyServices();
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+// list of hooks
+
+static int compareHooks(const THook* p1, const THook* p2)
+{
+ return strcmp(p1->name, p2->name);
+}
+
+static LIST<THook> hooks(50, compareHooks);
+
+struct THookToMainThreadItem
+{
+ THook* hook;
+ HANDLE hDoneEvent;
+ WPARAM wParam;
+ LPARAM lParam;
+ int result;
+};
+
+// list of services
+
+struct TService
+{
+ uint32_t nameHash;
+ HINSTANCE hOwner;
+ union
+ {
+ MIRANDASERVICE pfnService;
+ MIRANDASERVICEPARAM pfnServiceParam;
+ MIRANDASERVICEOBJ pfnServiceObj;
+ MIRANDASERVICEOBJPARAM pfnServiceObjParam;
+ };
+ int flags;
+ LPARAM lParam;
+ void* object;
+ char name[1];
+};
+
+LIST<TService> services(100, NumericKeySortT);
+
+struct TServiceToMainThreadItem
+{
+ HANDLE hDoneEvent;
+ WPARAM wParam;
+ LPARAM lParam;
+ int result;
+ const char *name;
+};
+
+// other static variables
+static BOOL bServiceMode = FALSE;
+static mir_cs csHooks, csServices;
+static uint32_t mainThreadId;
+static int sttHookId = 1;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+__forceinline HANDLE getThreadEvent()
+{
+ HANDLE pData = (HANDLE)TlsGetValue(mir_tls);
+ if (pData == nullptr) {
+ pData = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ TlsSetValue(mir_tls, pData);
+ }
+ return pData;
+}
+
+static int QueueMainThread(PAPCFUNC pFunc, void* pParam, HANDLE hDoneEvent)
+{
+ int result = PostMessage(hAPCWindow, WM_USER + 1, (WPARAM)pFunc, (LPARAM)pParam); // let this get processed in its own time
+ if (hDoneEvent)
+ WaitForSingleObject(hDoneEvent, INFINITE);
+
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// HOOKS
+
+MIR_CORE_DLL(HANDLE) CreateHookableEvent(const char *name)
+{
+ if (name == nullptr)
+ return nullptr;
+
+ mir_cslock lck(csHooks);
+
+ int idx;
+ if ((idx = hooks.getIndex((THook*)name)) != -1)
+ return hooks[idx];
+
+ THook *newItem = new THook();
+ strncpy(newItem->name, name, sizeof(newItem->name)); newItem->name[MAXMODULELABELLENGTH - 1] = 0;
+ newItem->id = sttHookId++;
+ hooks.insert(newItem);
+ return (HANDLE)newItem;
+}
+
+MIR_CORE_DLL(int) DestroyHookableEvent(HANDLE hEvent)
+{
+ if (hEvent == nullptr)
+ return 1;
+
+ mir_cslock lck(csHooks);
+
+ int idx;
+ if ((idx = hooks.getIndex((THook*)hEvent)) == -1)
+ return 1;
+
+ THook *p = hooks[idx];
+ p->secretSignature = 0;
+ if (p->subscriberCount) {
+ mir_free(p->subscriber);
+ p->subscriber = nullptr;
+ p->subscriberCount = 0;
+ }
+ hooks.remove(idx);
+ delete p;
+ return 0;
+}
+
+MIR_CORE_DLL(int) SetHookDefaultForHookableEvent(HANDLE hEvent, MIRANDAHOOK pfnHook)
+{
+ THook *p = (THook*)hEvent;
+
+ mir_cslock lck(csHooks);
+ if (hooks.getIndex(p) != -1)
+ p->pfnHook = pfnHook;
+ return 0;
+}
+
+MIR_CORE_DLL(int) CallPluginEventHook(HINSTANCE hInst, const char *pszEvent, WPARAM wParam, LPARAM lParam)
+{
+ int idx;
+ if ((idx = hooks.getIndex((THook *)pszEvent)) == -1)
+ return -1;
+
+ THook *p = hooks[idx];
+ if (p == nullptr || hInst == nullptr)
+ return -1;
+
+ mir_cslock lck(p->csHook);
+ for (int i = 0; i < p->subscriberCount; i++) {
+ THookSubscriber* s = &p->subscriber[i];
+ if (s->hOwner != hInst)
+ continue;
+
+ int returnVal;
+ switch (s->type) {
+ case 1: returnVal = s->pfnHook(wParam, lParam); break;
+ case 2: returnVal = s->pfnHookParam(wParam, lParam, s->lParam); break;
+ case 3: returnVal = s->pfnHookObj(s->object, wParam, lParam); break;
+ case 4: returnVal = s->pfnHookObjParam(s->object, wParam, lParam, s->lParam); break;
+ case 5: returnVal = SendMessage(s->hwnd, s->message, wParam, lParam); break;
+ default: continue;
+ }
+ if (returnVal)
+ return returnVal;
+ }
+
+ if (p->subscriberCount == 0 && p->pfnHook != nullptr)
+ return p->pfnHook(wParam, lParam);
+
+ return 0;
+}
+
+MIR_CORE_DLL(int) CallObjectEventHook(void *pObject, HANDLE hEvent, WPARAM wParam, LPARAM lParam)
+{
+ THook *p = (THook*)hEvent;
+ if (p == nullptr || pObject == nullptr)
+ return -1;
+
+ mir_cslock lck(p->csHook);
+ for (int i = 0; i < p->subscriberCount; i++) {
+ THookSubscriber* s = &p->subscriber[i];
+ if (s->object != pObject)
+ continue;
+
+ int returnVal;
+ switch (s->type) {
+ case 3: returnVal = s->pfnHookObj(s->object, wParam, lParam); break;
+ case 4: returnVal = s->pfnHookObjParam(s->object, wParam, lParam, s->lParam); break;
+ default: continue;
+ }
+ if (returnVal)
+ return returnVal;
+ }
+
+ if (p->subscriberCount == 0 && p->pfnHook != nullptr)
+ return p->pfnHook(wParam, lParam);
+
+ return 0;
+}
+
+static int CallHookSubscribers(THook *p, WPARAM wParam, LPARAM lParam)
+{
+ if (p == nullptr)
+ return -1;
+
+ mir_cslock lck(p->csHook);
+
+ // NOTE: We've got the critical section while all this lot are called. That's mostly safe, though.
+ for (int i = 0; i < p->subscriberCount; i++) {
+ THookSubscriber* s = &p->subscriber[i];
+
+ int returnVal;
+ switch (s->type) {
+ case 1: returnVal = s->pfnHook(wParam, lParam); break;
+ case 2: returnVal = s->pfnHookParam(wParam, lParam, s->lParam); break;
+ case 3: returnVal = s->pfnHookObj(s->object, wParam, lParam); break;
+ case 4: returnVal = s->pfnHookObjParam(s->object, wParam, lParam, s->lParam); break;
+ case 5: returnVal = SendMessage(s->hwnd, s->message, wParam, lParam); break;
+ default: continue;
+ }
+ if (returnVal)
+ return returnVal;
+ }
+
+ // call the default hook if any
+ if (p->pfnHook != nullptr)
+ return p->pfnHook(wParam, lParam);
+
+ return 0;
+}
+
+enum { hookOk, hookEmpty, hookInvalid };
+
+int checkHook(THook *p)
+{
+ if (p == nullptr)
+ return hookInvalid;
+
+ int ret;
+ __try {
+ if (p->secretSignature != HOOK_SECRET_SIGNATURE)
+ ret = hookInvalid;
+ else if (p->subscriberCount == 0 && p->pfnHook == nullptr)
+ ret = hookEmpty;
+ else
+ ret = hookOk;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ ret = hookInvalid;
+ }
+
+ return ret;
+}
+
+static void CALLBACK HookToMainAPCFunc(ULONG_PTR dwParam)
+{
+ THookToMainThreadItem* item = (THookToMainThreadItem*)dwParam;
+ item->result = CallHookSubscribers(item->hook, item->wParam, item->lParam);
+ SetEvent(item->hDoneEvent);
+}
+
+MIR_CORE_DLL(int) NotifyEventHooks(HANDLE hEvent, WPARAM wParam, LPARAM lParam)
+{
+ switch (checkHook((THook*)hEvent)) {
+ case hookInvalid: return -1;
+ case hookEmpty: return 0;
+ }
+
+ if (GetCurrentThreadId() == mainThreadId)
+ return CallHookSubscribers((THook*)hEvent, wParam, lParam);
+
+ THookToMainThreadItem item;
+ item.hDoneEvent = getThreadEvent();
+ item.hook = (THook*)hEvent;
+ item.wParam = wParam;
+ item.lParam = lParam;
+ QueueMainThread(HookToMainAPCFunc, &item, item.hDoneEvent);
+ return item.result;
+}
+
+MIR_CORE_DLL(int) NotifyFastHook(HANDLE hEvent, WPARAM wParam, LPARAM lParam)
+{
+ switch (checkHook((THook*)hEvent)) {
+ case hookInvalid: return -1;
+ case hookEmpty: return 0;
+ }
+
+ return CallHookSubscribers((THook*)hEvent, wParam, lParam);
+}
+
+extern "C" MIR_CORE_DLL(int) GetSubscribersCount(THook* pHook)
+{
+ switch (checkHook(pHook)) {
+ case hookInvalid:
+ case hookEmpty: return 0;
+ }
+ return pHook->subscriberCount;
+}
+
+static HANDLE HookEventInt(int type, const char *name, MIRANDAHOOK hookProc, void* object, LPARAM lParam)
+{
+ mir_cslock lck(csHooks);
+
+ int idx;
+ if ((idx = hooks.getIndex((THook*)name)) == -1)
+ return nullptr;
+
+ THook *p = hooks[idx];
+ p->subscriber = (THookSubscriber*)mir_realloc(p->subscriber, sizeof(THookSubscriber)*(p->subscriberCount + 1));
+
+ THookSubscriber &s = p->subscriber[p->subscriberCount];
+ s.type = type;
+ s.pfnHook = hookProc;
+ s.object = object;
+ s.lParam = lParam;
+ s.hOwner = GetInstByAddress(hookProc);
+ p->subscriberCount++;
+
+ return (HANDLE)((p->id << 16) | p->subscriberCount);
+}
+
+MIR_CORE_DLL(HANDLE) HookEvent(const char *name, MIRANDAHOOK hookProc)
+{
+ return HookEventInt(1, name, hookProc, nullptr, 0);
+}
+
+MIR_CORE_DLL(HANDLE) HookEventParam(const char *name, MIRANDAHOOKPARAM hookProc, LPARAM lParam)
+{
+ return HookEventInt(2, name, (MIRANDAHOOK)hookProc, nullptr, lParam);
+}
+
+MIR_CORE_DLL(HANDLE) HookEventObj(const char *name, MIRANDAHOOKOBJ hookProc, void* object)
+{
+ return HookEventInt(3, name, (MIRANDAHOOK)hookProc, object, 0);
+}
+
+MIR_CORE_DLL(HANDLE) HookEventObjParam(const char *name, MIRANDAHOOKOBJPARAM hookProc, void* object, LPARAM lParam)
+{
+ return HookEventInt(4, name, (MIRANDAHOOK)hookProc, object, lParam);
+}
+
+MIR_CORE_DLL(HANDLE) HookTemporaryEvent(const char *name, MIRANDAHOOK hookProc)
+{
+ mir_cslockfull lck(csHooks);
+
+ int idx;
+ if ((idx = hooks.getIndex((THook*)name)) == -1) {
+ lck.unlock();
+ hookProc(0, 0);
+ return nullptr;
+ }
+
+ THook *p = hooks[idx];
+ p->subscriber = (THookSubscriber*)mir_realloc(p->subscriber, sizeof(THookSubscriber)*(p->subscriberCount + 1));
+
+ THookSubscriber &s = p->subscriber[p->subscriberCount];
+ memset(&s, 0, sizeof(THookSubscriber));
+ s.type = 1;
+ s.pfnHook = hookProc;
+ s.hOwner = GetInstByAddress(hookProc);
+
+ p->subscriberCount++;
+ return (HANDLE)((p->id << 16) | p->subscriberCount);
+}
+
+MIR_CORE_DLL(HANDLE) HookEventMessage(const char *name, HWND hwnd, UINT message)
+{
+ mir_cslock lck(csHooks);
+
+ int idx;
+ if ((idx = hooks.getIndex((THook*)name)) == -1)
+ return nullptr;
+
+ THook *p = hooks[idx];
+ p->subscriber = (THookSubscriber*)mir_realloc(p->subscriber, sizeof(THookSubscriber)*(p->subscriberCount + 1));
+ p->subscriber[p->subscriberCount].type = 5;
+ p->subscriber[p->subscriberCount].hwnd = hwnd;
+ p->subscriber[p->subscriberCount].message = message;
+ p->subscriberCount++;
+ return (HANDLE)((p->id << 16) | p->subscriberCount);
+}
+
+MIR_CORE_DLL(int) UnhookEvent(HANDLE hHook)
+{
+ if (hHook == nullptr)
+ return 0;
+
+ int hookId = (INT_PTR)hHook >> 16;
+ int subscriberId = ((INT_PTR)hHook & 0xFFFF) - 1;
+
+ mir_cslock lck(csHooks);
+
+ THook *p = nullptr;
+ for (auto &it : hooks)
+ if (it->id == hookId) {
+ p = it;
+ break;
+ }
+
+ if (p == nullptr)
+ return 1;
+
+ if (subscriberId >= p->subscriberCount || subscriberId < 0)
+ return 1;
+
+ p->subscriber[subscriberId].type = 0;
+ p->subscriber[subscriberId].pfnHook = nullptr;
+ p->subscriber[subscriberId].hOwner = nullptr;
+ while (p->subscriberCount && p->subscriber[p->subscriberCount - 1].type == 0)
+ p->subscriberCount--;
+ if (p->subscriberCount == 0) {
+ mir_free(p->subscriber);
+ p->subscriber = nullptr;
+ }
+ return 0;
+}
+
+MIR_CORE_DLL(void) KillModuleEventHooks(HINSTANCE hInst)
+{
+ mir_cslock lck(csHooks);
+
+ for (auto &it : hooks.rev_iter()) {
+ if (it->subscriberCount == 0)
+ continue;
+
+ for (int j = it->subscriberCount - 1; j >= 0; j--) {
+ if (it->subscriber[j].hOwner != hInst)
+ continue;
+
+ char szModuleName[MAX_PATH];
+ GetModuleFileNameA(it->subscriber[j].hOwner, szModuleName, sizeof(szModuleName));
+ UnhookEvent((HANDLE)((it->id << 16) + j + 1));
+ if (it->subscriberCount == 0)
+ break;
+ }
+ }
+}
+
+MIR_CORE_DLL(void) KillObjectEventHooks(void* pObject)
+{
+ mir_cslock lck(csHooks);
+
+ for (auto &it : hooks.rev_iter()) {
+ if (it->subscriberCount == 0)
+ continue;
+
+ for (int j = it->subscriberCount - 1; j >= 0; j--) {
+ if (it->subscriber[j].object == pObject) {
+ UnhookEvent((HANDLE)((it->id << 16) + j + 1));
+ if (it->subscriberCount == 0)
+ break;
+ }
+ }
+ }
+}
+
+static void DestroyHooks()
+{
+ mir_cslock lck(csHooks);
+
+ for (auto &it : hooks) {
+ if (it->subscriberCount)
+ mir_free(it->subscriber);
+ delete it;
+ }
+}
+
+/////////////////////SERVICES
+
+static __inline TService* FindServiceByName(const char *name)
+{
+ unsigned hash = mir_hashstr(name);
+ return services.find((TService*)&hash);
+}
+
+static HANDLE CreateServiceInt(int type, const char *name, MIRANDASERVICE serviceProc, void* object, LPARAM lParam)
+{
+ if (name == nullptr)
+ return nullptr;
+
+ TService tmp;
+ tmp.nameHash = mir_hashstr(name);
+
+ mir_cslock lck(csServices);
+
+ if (services.getIndex(&tmp) != -1)
+ return nullptr;
+
+ TService* p = (TService*)mir_alloc(sizeof(*p) + strlen(name));
+ strcpy(p->name, name);
+ p->nameHash = tmp.nameHash;
+ p->pfnService = serviceProc;
+ p->hOwner = GetInstByAddress(serviceProc);
+ p->flags = type;
+ p->lParam = lParam;
+ p->object = object;
+ services.insert(p);
+
+ return (HANDLE)tmp.nameHash;
+}
+
+MIR_CORE_DLL(HANDLE) CreateServiceFunction(const char *name, MIRANDASERVICE serviceProc)
+{
+ return CreateServiceInt(0, name, serviceProc, nullptr, 0);
+}
+
+MIR_CORE_DLL(HANDLE) CreateServiceFunctionParam(const char *name, MIRANDASERVICEPARAM serviceProc, LPARAM lParam)
+{
+ return CreateServiceInt(1, name, (MIRANDASERVICE)serviceProc, nullptr, lParam);
+}
+
+MIR_CORE_DLL(HANDLE) CreateServiceFunctionObj(const char *name, MIRANDASERVICEOBJ serviceProc, void* object)
+{
+ return CreateServiceInt(2, name, (MIRANDASERVICE)serviceProc, object, 0);
+}
+
+MIR_CORE_DLL(HANDLE) CreateServiceFunctionObjParam(const char *name, MIRANDASERVICEOBJPARAM serviceProc, void* object, LPARAM lParam)
+{
+ return CreateServiceInt(3, name, (MIRANDASERVICE)serviceProc, object, lParam);
+}
+
+MIR_CORE_DLL(HANDLE) CreateProtoServiceFunction(const char *szModule, const char *szService, MIRANDASERVICE serviceProc)
+{
+ char str[MAXMODULELABELLENGTH * 2];
+ strncpy_s(str, szModule, _TRUNCATE);
+ strncat_s(str, szService, _TRUNCATE);
+ return CreateServiceFunction(str, serviceProc);
+}
+
+MIR_CORE_DLL(int) DestroyServiceFunction(HANDLE hService)
+{
+ mir_cslock lck(csServices);
+
+ int idx = services.getIndex((TService*)&hService);
+ if (idx != -1) {
+ mir_free(services[idx]);
+ services.remove(idx);
+ }
+
+ return 0;
+}
+
+MIR_CORE_DLL(bool) ServiceExists(const char *name)
+{
+ if (name == nullptr)
+ return FALSE;
+
+ mir_cslock lck(csServices);
+ return FindServiceByName(name) != nullptr;
+}
+
+MIR_CORE_DLL(INT_PTR) CallService(const char *name, WPARAM wParam, LPARAM lParam)
+{
+ if (name == nullptr)
+ return CALLSERVICE_NOTFOUND;
+
+ TService *pService;
+ {
+ mir_cslock lck(csServices);
+ if ((pService = FindServiceByName(name)) == nullptr)
+ return CALLSERVICE_NOTFOUND;
+ }
+
+ MIRANDASERVICE pfnService = pService->pfnService;
+ int flags = pService->flags;
+ LPARAM fnParam = pService->lParam;
+ void* object = pService->object;
+ switch (flags) {
+ case 1: return ((MIRANDASERVICEPARAM)pfnService)(wParam, lParam, fnParam);
+ case 2: return ((MIRANDASERVICEOBJ)pfnService)(object, wParam, lParam);
+ case 3: return ((MIRANDASERVICEOBJPARAM)pfnService)(object, wParam, lParam, fnParam);
+ default: return pfnService(wParam, lParam);
+ }
+}
+
+static void CALLBACK CallServiceToMainAPCFunc(ULONG_PTR dwParam)
+{
+ TServiceToMainThreadItem *item = (TServiceToMainThreadItem*)dwParam;
+ item->result = CallService(item->name, item->wParam, item->lParam);
+ SetEvent(item->hDoneEvent);
+}
+
+MIR_CORE_DLL(INT_PTR) CallServiceSync(const char *name, WPARAM wParam, LPARAM lParam)
+{
+ if (name == nullptr)
+ return CALLSERVICE_NOTFOUND;
+
+ // the service is looked up within the main thread, since the time it takes
+ // for the APC queue to clear the service being called maybe removed.
+ // even thou it may exists before the call, the critsec can't be locked between calls.
+ if (GetCurrentThreadId() == mainThreadId)
+ return CallService(name, wParam, lParam);
+
+ TServiceToMainThreadItem item;
+ item.wParam = wParam;
+ item.lParam = lParam;
+ item.name = name;
+ item.hDoneEvent = getThreadEvent();
+ QueueMainThread(CallServiceToMainAPCFunc, &item, item.hDoneEvent);
+ return item.result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) CallFunctionAsync(void(__stdcall *func)(void *), void *arg)
+{
+ if (GetCurrentThreadId() == mainThreadId)
+ func(arg);
+ else
+ QueueMainThread((PAPCFUNC)func, arg, nullptr);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct TSyncCallParam
+{
+ INT_PTR(__stdcall *func)(void *);
+ void *arg;
+ HANDLE hDoneEvent;
+ INT_PTR result;
+};
+
+static void CALLBACK CallFuncToMainAPCFunc(ULONG_PTR dwParam)
+{
+ TSyncCallParam *item = (TSyncCallParam*)dwParam;
+ item->result = (*item->func)(item->arg);
+ SetEvent(item->hDoneEvent);
+}
+
+MIR_CORE_DLL(INT_PTR) CallFunctionSync(INT_PTR(__stdcall *func)(void *), void *arg)
+{
+ if (GetCurrentThreadId() == mainThreadId)
+ return func(arg);
+
+ TSyncCallParam param = { func, arg, getThreadEvent() };
+ QueueMainThread(CallFuncToMainAPCFunc, &param, param.hDoneEvent);
+ return param.result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(void) KillModuleServices(HINSTANCE hInst)
+{
+ mir_cslock lck(csServices);
+
+ for (auto &it : services.rev_iter()) {
+ if (it->hOwner == hInst) {
+ char szModuleName[MAX_PATH];
+ GetModuleFileNameA(it->hOwner, szModuleName, sizeof(szModuleName));
+ DestroyServiceFunction((HANDLE)it->nameHash);
+ }
+ }
+}
+
+MIR_CORE_DLL(void) KillObjectServices(void* pObject)
+{
+ mir_cslock lck(csServices);
+
+ for (auto &it : services.rev_iter())
+ if (it->object == pObject)
+ DestroyServiceFunction((HANDLE)it->nameHash);
+}
+
+static void DestroyServices()
+{
+ mir_cslock lck(csServices);
+
+ for (auto &it : services)
+ mir_free(it);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int InitialiseModularEngine(void)
+{
+ mainThreadId = GetCurrentThreadId();
+ return 0;
+}
+
+void DestroyModularEngine(void)
+{
+ DestroyHooks();
+ DestroyServices();
+}
diff --git a/src/mir_core/src/mstring.cpp b/src/mir_core/src/mstring.cpp
index 2bff18e7f1..04a26f8a9d 100644
--- a/src/mir_core/src/mstring.cpp
+++ b/src/mir_core/src/mstring.cpp
@@ -1,145 +1,145 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CMBaseString
-
-class CNilMStringData : public CMStringData
-{
-public:
- CNilMStringData();
-
-public:
- wchar_t achNil[2];
-};
-
-CNilMStringData::CNilMStringData()
-{
- nRefs = 2; // Never gets freed
- nDataLength = 0;
- nAllocLength = 0;
- achNil[0] = 0;
- achNil[1] = 0;
-}
-
-static CNilMStringData *m_nil = nullptr;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CMBaseString
-
-MIR_CORE_DLL(CMStringData*) mirstr_allocate(int nChars, int nCharSize)
-{
- nChars++; // nil char
- size_t nDataBytes = nCharSize * nChars;
- size_t nTotalSize = nDataBytes + sizeof(CMStringData);
-
- CMStringData *pData = static_cast<CMStringData*>(malloc(nTotalSize));
- if (pData == nullptr)
- return nullptr;
-
- pData->nRefs = 1;
- pData->nAllocLength = nChars - 1;
- pData->nDataLength = 0;
- return pData;
-}
-
-MIR_CORE_DLL(void) mirstr_free(CMStringData *pData)
-{
- free(pData);
-}
-
-MIR_CORE_DLL(CMStringData*) mirstr_realloc(CMStringData* pData, int nChars, int nCharSize)
-{
- nChars++; // nil char
- uint32_t nDataBytes = nCharSize * nChars;
- uint32_t nTotalSize = nDataBytes + sizeof(CMStringData);
-
- CMStringData *pNewData = static_cast<CMStringData*>(realloc(pData, nTotalSize));
- if (pNewData == nullptr)
- return nullptr;
-
- pNewData->nAllocLength = nChars - 1;
- return pNewData;
-}
-
-MIR_CORE_DLL(CMStringData*) mirstr_getNil()
-{
- if (m_nil == nullptr)
- m_nil = new CNilMStringData();
- m_nil->AddRef();
- return m_nil;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CMStringData
-
-MIR_CORE_DLL(void) mirstr_lock(CMStringData* pThis)
-{
- pThis->nRefs--; // Locked buffers can't be shared, so no interlocked operation necessary
- if (pThis->nRefs == 0)
- pThis->nRefs = -1;
-}
-
-MIR_CORE_DLL(void) mirstr_release(CMStringData* pThis)
-{
- if (InterlockedDecrement(&pThis->nRefs) <= 0)
- mirstr_free(pThis);
-}
-
-MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis)
-{
- if (pThis->IsLocked())
- {
- pThis->nRefs++; // Locked buffers can't be shared, so no interlocked operation necessary
- if (pThis->nRefs == 0)
- pThis->nRefs = 1;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// don't remove it
-// this code just instantiates templates for CMStringW[A/W]
-
-#ifdef _MSC_VER
-template MIR_CORE_EXPORT CMStringW;
-template MIR_CORE_EXPORT CMStringA;
-#endif
-
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const CMStringW& str2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const wchar_t *psz2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const wchar_t *psz1, const CMStringW& str2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, wchar_t ch2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, char ch2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(wchar_t ch1, const CMStringW& str2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(char ch1, const CMStringW& str2);
-
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const CMStringA& str2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const char *psz2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const char *psz1, const CMStringA& str2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, wchar_t ch2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, char ch2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(wchar_t ch1, const CMStringA& str2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(char ch1, const CMStringA& str2);
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CMBaseString
+
+class CNilMStringData : public CMStringData
+{
+public:
+ CNilMStringData();
+
+public:
+ wchar_t achNil[2];
+};
+
+CNilMStringData::CNilMStringData()
+{
+ nRefs = 2; // Never gets freed
+ nDataLength = 0;
+ nAllocLength = 0;
+ achNil[0] = 0;
+ achNil[1] = 0;
+}
+
+static CNilMStringData *m_nil = nullptr;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CMBaseString
+
+MIR_CORE_DLL(CMStringData*) mirstr_allocate(int nChars, int nCharSize)
+{
+ nChars++; // nil char
+ size_t nDataBytes = nCharSize * nChars;
+ size_t nTotalSize = nDataBytes + sizeof(CMStringData);
+
+ CMStringData *pData = static_cast<CMStringData*>(malloc(nTotalSize));
+ if (pData == nullptr)
+ return nullptr;
+
+ pData->nRefs = 1;
+ pData->nAllocLength = nChars - 1;
+ pData->nDataLength = 0;
+ return pData;
+}
+
+MIR_CORE_DLL(void) mirstr_free(CMStringData *pData)
+{
+ free(pData);
+}
+
+MIR_CORE_DLL(CMStringData*) mirstr_realloc(CMStringData* pData, int nChars, int nCharSize)
+{
+ nChars++; // nil char
+ uint32_t nDataBytes = nCharSize * nChars;
+ uint32_t nTotalSize = nDataBytes + sizeof(CMStringData);
+
+ CMStringData *pNewData = static_cast<CMStringData*>(realloc(pData, nTotalSize));
+ if (pNewData == nullptr)
+ return nullptr;
+
+ pNewData->nAllocLength = nChars - 1;
+ return pNewData;
+}
+
+MIR_CORE_DLL(CMStringData*) mirstr_getNil()
+{
+ if (m_nil == nullptr)
+ m_nil = new CNilMStringData();
+ m_nil->AddRef();
+ return m_nil;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CMStringData
+
+MIR_CORE_DLL(void) mirstr_lock(CMStringData* pThis)
+{
+ pThis->nRefs--; // Locked buffers can't be shared, so no interlocked operation necessary
+ if (pThis->nRefs == 0)
+ pThis->nRefs = -1;
+}
+
+MIR_CORE_DLL(void) mirstr_release(CMStringData* pThis)
+{
+ if (InterlockedDecrement(&pThis->nRefs) <= 0)
+ mirstr_free(pThis);
+}
+
+MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis)
+{
+ if (pThis->IsLocked())
+ {
+ pThis->nRefs++; // Locked buffers can't be shared, so no interlocked operation necessary
+ if (pThis->nRefs == 0)
+ pThis->nRefs = 1;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// don't remove it
+// this code just instantiates templates for CMStringW[A/W]
+
+#ifdef _MSC_VER
+template MIR_CORE_EXPORT CMStringW;
+template MIR_CORE_EXPORT CMStringA;
+#endif
+
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const CMStringW& str2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const wchar_t *psz2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const wchar_t *psz1, const CMStringW& str2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, wchar_t ch2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, char ch2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(wchar_t ch1, const CMStringW& str2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(char ch1, const CMStringW& str2);
+
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const CMStringA& str2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const char *psz2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const char *psz1, const CMStringA& str2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, wchar_t ch2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, char ch2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(wchar_t ch1, const CMStringA& str2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(char ch1, const CMStringA& str2);
diff --git a/src/mir_core/src/stdafx.cxx b/src/mir_core/src/stdafx.cxx
index 564f422ca2..8c570f6949 100644
--- a/src/mir_core/src/stdafx.cxx
+++ b/src/mir_core/src/stdafx.cxx
@@ -1,5 +1,5 @@
/*
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org)
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
diff --git a/src/mir_core/src/stdafx.h b/src/mir_core/src/stdafx.h
index 54ec535a4c..dd6d93d679 100644
--- a/src/mir_core/src/stdafx.h
+++ b/src/mir_core/src/stdafx.h
@@ -1,84 +1,84 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#pragma once
-
-#define INCL_WINSOCK_API_TYPEDEFS 1
-
-#ifdef _MSC_VER
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #include <windows.h>
- #include <windowsx.h>
- #include <shlobj.h>
- #include <commctrl.h>
- #include <ShellAPI.h>
- #include <vssym32.h>
- #include <Uxtheme.h>
- #include <Richedit.h>
- #include <Wtsapi32.h>
-
- #include <process.h>
- #include <io.h>
- #include <direct.h>
-
- #ifdef _DEBUG
- #include <crtdbg.h>
- #endif
-#else
- #include <Elementary.h>
-#endif // _WINDOWS
-
-#include <malloc.h>
-#include <stdio.h>
-#include <time.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <limits.h>
-#include <string.h>
-#include <locale.h>
-
-#define __NO_CMPLUGIN_NEEDED
-#include <m_system.h>
-#include <m_database.h>
-#include <m_db_int.h>
-#include <newpluginapi.h>
-#include <m_langpack.h>
-#include <m_metacontacts.h>
-#include <m_skin.h>
-#include <m_icolib.h>
-#include <m_netlib.h>
-#include <m_timezones.h>
-#include <m_protocols.h>
-#include <m_button.h>
-#include <m_gui.h>
-#include <m_chat_int.h>
-
-#include "miranda.h"
-
-#include <m_xml.h>
-
-#include <m_string.inl>
-
-void GetDefaultLang();
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#pragma once
+
+#define INCL_WINSOCK_API_TYPEDEFS 1
+
+#ifdef _MSC_VER
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+ #include <windows.h>
+ #include <windowsx.h>
+ #include <shlobj.h>
+ #include <commctrl.h>
+ #include <ShellAPI.h>
+ #include <vssym32.h>
+ #include <Uxtheme.h>
+ #include <Richedit.h>
+ #include <Wtsapi32.h>
+
+ #include <process.h>
+ #include <io.h>
+ #include <direct.h>
+
+ #ifdef _DEBUG
+ #include <crtdbg.h>
+ #endif
+#else
+ #include <Elementary.h>
+#endif // _WINDOWS
+
+#include <malloc.h>
+#include <stdio.h>
+#include <time.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <limits.h>
+#include <string.h>
+#include <locale.h>
+
+#define __NO_CMPLUGIN_NEEDED
+#include <m_system.h>
+#include <m_database.h>
+#include <m_db_int.h>
+#include <newpluginapi.h>
+#include <m_langpack.h>
+#include <m_metacontacts.h>
+#include <m_skin.h>
+#include <m_icolib.h>
+#include <m_netlib.h>
+#include <m_timezones.h>
+#include <m_protocols.h>
+#include <m_button.h>
+#include <m_gui.h>
+#include <m_chat_int.h>
+
+#include "miranda.h"
+
+#include <m_xml.h>
+
+#include <m_string.inl>
+
+void GetDefaultLang();
diff --git a/src/mir_core/src/utf.cpp b/src/mir_core/src/utf.cpp
index 1e17ed60e8..eefa519727 100644
--- a/src/mir_core/src/utf.cpp
+++ b/src/mir_core/src/utf.cpp
@@ -1,441 +1,441 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
- Copyright 2000 Alexandre Julliard of Wine project
- (UTF-8 conversion routines)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-/* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
-static const char utf8_length[128] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xaf */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0-0xbf */
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xc0-0xcf */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xd0-0xdf */
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xe0-0xef */
- 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0-0xff */
-};
-
-/* first byte mask depending on UTF-8 sequence length */
-static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
-
-/* minimum Unicode value depending on UTF-8 sequence length */
-static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
-
-/* get the next char value taking surrogates into account */
-static unsigned int getSurrogateValue(const wchar_t *src, unsigned int srclen)
-{
- if (src[0] >= 0xd800 && src[0] <= 0xdfff) { /* surrogate pair */
- if (src[0] > 0xdbff || /* invalid high surrogate */
- srclen <= 1 || /* missing low surrogate */
- src[1] < 0xdc00 || src[1] > 0xdfff) /* invalid low surrogate */
- return 0;
- return 0x10000 + ((src[0] & 0x3ff) << 10) + (src[1] & 0x3ff);
- }
- return src[0];
-}
-
-/* query necessary dst length for src string */
-static int mir_utf8len(const wchar_t *src, unsigned int srclen)
-{
- int len;
- unsigned int val;
-
- for (len = 0; srclen; srclen--, src++) {
- if (*src < 0x80) { /* 0x00-0x7f: 1 byte */
- len++;
- continue;
- }
- if (*src < 0x800) { /* 0x80-0x7ff: 2 bytes */
- len += 2;
- continue;
- }
- if (!(val = getSurrogateValue(src, srclen)))
- return -2;
-
- if (val < 0x10000) /* 0x800-0xffff: 3 bytes */
- len += 3;
- else { /* 0x10000-0x10ffff: 4 bytes */
- len += 4;
- src++;
- srclen--;
- }
- }
- return len;
-}
-
-MIR_CORE_DLL(int) mir_utf8lenW(const wchar_t *src)
-{
- if (src == nullptr)
- return 0;
-
- return mir_utf8len(src, (int)wcslen(src));
-}
-
-/* wide char to UTF-8 string conversion */
-/* return -1 on dst buffer overflow, -2 on invalid input char */
-int Ucs2toUtf8(const wchar_t *src, int srclen, char *dst, int dstlen)
-{
- int len;
-
- for (len = dstlen; srclen; srclen--, src++) {
- wchar_t ch = *src;
- unsigned int val;
-
- if (ch < 0x80) { /* 0x00-0x7f: 1 byte */
- if (!len--) return -1; /* overflow */
- *dst++ = ch;
- continue;
- }
-
- if (ch < 0x800) { /* 0x80-0x7ff: 2 bytes */
- if ((len -= 2) < 0) return -1; /* overflow */
- dst[1] = 0x80 | (ch & 0x3f);
- ch >>= 6;
- dst[0] = 0xc0 | ch;
- dst += 2;
- continue;
- }
-
- if (!(val = getSurrogateValue(src, srclen)))
- return -2;
-
- if (val < 0x10000) { /* 0x800-0xffff: 3 bytes */
- if ((len -= 3) < 0) return -1; /* overflow */
- dst[2] = 0x80 | (val & 0x3f);
- val >>= 6;
- dst[1] = 0x80 | (val & 0x3f);
- val >>= 6;
- dst[0] = 0xe0 | val;
- dst += 3;
- }
- else { /* 0x10000-0x10ffff: 4 bytes */
- if ((len -= 4) < 0) return -1; /* overflow */
- dst[3] = 0x80 | (val & 0x3f);
- val >>= 6;
- dst[2] = 0x80 | (val & 0x3f);
- val >>= 6;
- dst[1] = 0x80 | (val & 0x3f);
- val >>= 6;
- dst[0] = 0xf0 | val;
- dst += 4;
- src++;
- srclen--;
- }
- }
- return dstlen - len;
-}
-
-/* helper for the various utf8 mbstowcs functions */
-static unsigned int decodeUtf8Char(unsigned char ch, const char **str, const char *strend)
-{
- unsigned int len = utf8_length[ch - 0x80];
- unsigned int res = ch & utf8_mask[len];
- const char *end = *str + len;
-
- if (end > strend) return ~0;
- switch (len) {
- case 3:
- if ((ch = end[-3] ^ 0x80) >= 0x40) break;
- res = (res << 6) | ch;
- (*str)++;
-
- case 2:
- if ((ch = end[-2] ^ 0x80) >= 0x40) break;
- res = (res << 6) | ch;
- (*str)++;
-
- case 1:
- if ((ch = end[-1] ^ 0x80) >= 0x40) break;
- res = (res << 6) | ch;
- (*str)++;
- if (res < utf8_minval[len]) break;
- return res;
- }
- return ~0;
-}
-
-/* query necessary dst length for src string */
-static int Utf8toUcs2Len(const char *src, size_t srclen)
-{
- int ret = 0;
- unsigned int res;
- const char *srcend = src + srclen;
-
- while (src < srcend) {
- unsigned char ch = *src++;
- if (ch < 0x80) { /* special fast case for 7-bit ASCII */
- ret++;
- continue;
- }
- if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0x10ffff) {
- if (res > 0xffff) ret++;
- ret++;
- }
- else return -2; /* bad char */
- /* otherwise ignore it */
- }
- return ret;
-}
-
-/* UTF-8 to wide char string conversion */
-/* return -1 on dst buffer overflow, -2 on invalid input char */
-MIR_CORE_DLL(int) Utf8toUcs2(const char *src, size_t srclen, wchar_t *dst, size_t dstlen)
-{
- unsigned int res;
- const char *srcend = src + srclen; // including trailing zero
- wchar_t *dstend = dst + dstlen;
-
- while ((dst < dstend) && (src < srcend)) {
- unsigned char ch = *src++;
- if (ch < 0x80) { /* special fast case for 7-bit ASCII */
- *dst++ = ch;
- continue;
- }
-
- if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0xffff)
- *dst++ = res;
- else if (res <= 0x10ffff) { /* we need surrogates */
- if (dst == dstend - 1)
- return -1; /* overflow */
- res -= 0x10000;
- *dst++ = 0xd800 | (res >> 10);
- *dst++ = 0xdc00 | (res & 0x3ff);
- }
- else return -2; /* bad char */
- }
-
- if (src < srcend)
- return -1; /* overflow */
-
- return (int)(dstlen - (dstend - dst));
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// mir_utf8decode - converts UTF8-encoded string to the UCS2/MBCS format
-
-#ifdef _MSC_VER
-MIR_CORE_DLL(char*) mir_utf8decodecp(char *str, int codepage, wchar_t **ucs2)
-{
- bool needs_free = false;
- wchar_t* tempBuf = nullptr;
- if (ucs2)
- *ucs2 = nullptr;
-
- if (str == nullptr)
- return nullptr;
-
- size_t len = strlen(str);
- if (len < 2) {
- if (ucs2 != nullptr) {
- *ucs2 = tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t));
- MultiByteToWideChar(codepage, 0, str, (int)len, tempBuf, (int)len);
- tempBuf[len] = 0;
- }
- return str;
- }
-
- int destlen = Utf8toUcs2Len(str, len);
- if (destlen < 0)
- return nullptr;
-
- if (ucs2 == nullptr) {
- __try {
- tempBuf = (wchar_t*)alloca((destlen + 1) * sizeof(wchar_t));
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- tempBuf = nullptr;
- needs_free = true;
- }
- }
-
- if (tempBuf == nullptr) {
- tempBuf = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t));
- if (tempBuf == nullptr)
- return nullptr;
- }
-
- Utf8toUcs2(str, len, tempBuf, destlen);
- tempBuf[destlen] = 0;
- WideCharToMultiByte(codepage, 0, tempBuf, -1, str, (int)len + 1, "?", nullptr);
-
- if (ucs2)
- *ucs2 = tempBuf;
- else if (needs_free)
- mir_free(tempBuf);
-
- return str;
-}
-
-MIR_CORE_DLL(char*) mir_utf8decode(char *str, wchar_t **ucs2)
-{
- return mir_utf8decodecp(str, Langpack_GetDefaultCodePage(), ucs2);
-}
-#endif
-
-MIR_CORE_DLL(wchar_t*) mir_utf8decodeW(const char *str)
-{
- if (str == nullptr)
- return nullptr;
-
- size_t len = strlen(str);
-
- int destlen = Utf8toUcs2Len(str, len);
- if (destlen < 0)
- return nullptr;
-
- wchar_t* ucs2 = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t));
- if (ucs2 == nullptr)
- return nullptr;
-
- if (Utf8toUcs2(str, len, ucs2, destlen) >= 0) {
- ucs2[destlen] = 0;
- return ucs2;
- }
-
- mir_free(ucs2);
-
- return nullptr;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// mir_utf8encode - converts MBCS string to the UTF8-encoded format
-
-#ifdef _MSC_VER
-MIR_CORE_DLL(char*) mir_utf8encodecp(const char* src, int codepage)
-{
- int len;
- bool needs_free = false;
- char* result = nullptr;
- wchar_t* tempBuf;
-
- if (src == nullptr)
- return nullptr;
-
- len = (int)strlen(src);
-
- __try {
- tempBuf = (wchar_t*)alloca((len + 1) * sizeof(wchar_t));
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t));
- if (tempBuf == nullptr) return nullptr;
- needs_free = true;
- }
-
- len = MultiByteToWideChar(codepage, 0, src, -1, tempBuf, len + 1);
-
- int destlen = mir_utf8len(tempBuf, len);
- if (destlen >= 0) {
- result = (char*)mir_alloc(destlen + 1);
- if (result) {
- Ucs2toUtf8(tempBuf, len, result, destlen);
- result[destlen] = 0;
- }
- }
-
- if (needs_free)
- mir_free(tempBuf);
-
- return result;
-}
-
-MIR_CORE_DLL(char*) mir_utf8encode(const char* src)
-{
- return mir_utf8encodecp(src, Langpack_GetDefaultCodePage());
-}
-#endif
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// mir_utf8encode - converts UCS2 string to the UTF8-encoded format
-
-MIR_CORE_DLL(char*) mir_utf8encodeW(const wchar_t* src)
-{
- if (src == nullptr)
- return nullptr;
-
- int len = (int)wcslen(src);
-
- int destlen = mir_utf8len(src, len);
- if (destlen < 0) return nullptr;
-
- char* result = (char*)mir_alloc(destlen + 1);
- if (result == nullptr)
- return nullptr;
-
- Ucs2toUtf8(src, len, result, destlen);
- result[destlen] = 0;
-
- return result;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Utf8CheckString - checks if a string is a valid utf8-encoded string
-
-MIR_CORE_DLL(BOOL) Utf8CheckString(const char *str)
-{
- int expect_bytes = 0, utf_found = 0;
-
- if (!str) return 0;
-
- while (*str) {
- if ((*str & 0x80) == 0) {
- /* Looks like an ASCII character */
- if (expect_bytes)
- /* byte of UTF-8 character expected */
- return 0;
- }
- else {
- /* Looks like byte of an UTF-8 character */
- if (expect_bytes) {
- /* expect_bytes already set: first byte of UTF-8 char already seen */
- if ((*str & 0xC0) != 0x80) {
- /* again first byte ?!?! */
- return 0;
- }
- }
- else {
- /* First byte of the UTF-8 character */
- /* count initial one bits and set expect_bytes to 1 less */
- char ch = *str;
- while (ch & 0x80) {
- expect_bytes++;
- ch = (ch & 0x7f) << 1;
- }
- }
- /* OK, next byte of UTF-8 character */
- /* Decrement number of expected bytes */
- if (--expect_bytes == 0)
- utf_found = 1;
- }
- str++;
- }
-
- return (utf_found && expect_bytes == 0);
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+ Copyright 2000 Alexandre Julliard of Wine project
+ (UTF-8 conversion routines)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+/* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
+static const char utf8_length[128] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xaf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0-0xbf */
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xc0-0xcf */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xd0-0xdf */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xe0-0xef */
+ 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0-0xff */
+};
+
+/* first byte mask depending on UTF-8 sequence length */
+static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
+
+/* minimum Unicode value depending on UTF-8 sequence length */
+static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
+
+/* get the next char value taking surrogates into account */
+static unsigned int getSurrogateValue(const wchar_t *src, unsigned int srclen)
+{
+ if (src[0] >= 0xd800 && src[0] <= 0xdfff) { /* surrogate pair */
+ if (src[0] > 0xdbff || /* invalid high surrogate */
+ srclen <= 1 || /* missing low surrogate */
+ src[1] < 0xdc00 || src[1] > 0xdfff) /* invalid low surrogate */
+ return 0;
+ return 0x10000 + ((src[0] & 0x3ff) << 10) + (src[1] & 0x3ff);
+ }
+ return src[0];
+}
+
+/* query necessary dst length for src string */
+static int mir_utf8len(const wchar_t *src, unsigned int srclen)
+{
+ int len;
+ unsigned int val;
+
+ for (len = 0; srclen; srclen--, src++) {
+ if (*src < 0x80) { /* 0x00-0x7f: 1 byte */
+ len++;
+ continue;
+ }
+ if (*src < 0x800) { /* 0x80-0x7ff: 2 bytes */
+ len += 2;
+ continue;
+ }
+ if (!(val = getSurrogateValue(src, srclen)))
+ return -2;
+
+ if (val < 0x10000) /* 0x800-0xffff: 3 bytes */
+ len += 3;
+ else { /* 0x10000-0x10ffff: 4 bytes */
+ len += 4;
+ src++;
+ srclen--;
+ }
+ }
+ return len;
+}
+
+MIR_CORE_DLL(int) mir_utf8lenW(const wchar_t *src)
+{
+ if (src == nullptr)
+ return 0;
+
+ return mir_utf8len(src, (int)wcslen(src));
+}
+
+/* wide char to UTF-8 string conversion */
+/* return -1 on dst buffer overflow, -2 on invalid input char */
+int Ucs2toUtf8(const wchar_t *src, int srclen, char *dst, int dstlen)
+{
+ int len;
+
+ for (len = dstlen; srclen; srclen--, src++) {
+ wchar_t ch = *src;
+ unsigned int val;
+
+ if (ch < 0x80) { /* 0x00-0x7f: 1 byte */
+ if (!len--) return -1; /* overflow */
+ *dst++ = ch;
+ continue;
+ }
+
+ if (ch < 0x800) { /* 0x80-0x7ff: 2 bytes */
+ if ((len -= 2) < 0) return -1; /* overflow */
+ dst[1] = 0x80 | (ch & 0x3f);
+ ch >>= 6;
+ dst[0] = 0xc0 | ch;
+ dst += 2;
+ continue;
+ }
+
+ if (!(val = getSurrogateValue(src, srclen)))
+ return -2;
+
+ if (val < 0x10000) { /* 0x800-0xffff: 3 bytes */
+ if ((len -= 3) < 0) return -1; /* overflow */
+ dst[2] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[1] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[0] = 0xe0 | val;
+ dst += 3;
+ }
+ else { /* 0x10000-0x10ffff: 4 bytes */
+ if ((len -= 4) < 0) return -1; /* overflow */
+ dst[3] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[2] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[1] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[0] = 0xf0 | val;
+ dst += 4;
+ src++;
+ srclen--;
+ }
+ }
+ return dstlen - len;
+}
+
+/* helper for the various utf8 mbstowcs functions */
+static unsigned int decodeUtf8Char(unsigned char ch, const char **str, const char *strend)
+{
+ unsigned int len = utf8_length[ch - 0x80];
+ unsigned int res = ch & utf8_mask[len];
+ const char *end = *str + len;
+
+ if (end > strend) return ~0;
+ switch (len) {
+ case 3:
+ if ((ch = end[-3] ^ 0x80) >= 0x40) break;
+ res = (res << 6) | ch;
+ (*str)++;
+
+ case 2:
+ if ((ch = end[-2] ^ 0x80) >= 0x40) break;
+ res = (res << 6) | ch;
+ (*str)++;
+
+ case 1:
+ if ((ch = end[-1] ^ 0x80) >= 0x40) break;
+ res = (res << 6) | ch;
+ (*str)++;
+ if (res < utf8_minval[len]) break;
+ return res;
+ }
+ return ~0;
+}
+
+/* query necessary dst length for src string */
+static int Utf8toUcs2Len(const char *src, size_t srclen)
+{
+ int ret = 0;
+ unsigned int res;
+ const char *srcend = src + srclen;
+
+ while (src < srcend) {
+ unsigned char ch = *src++;
+ if (ch < 0x80) { /* special fast case for 7-bit ASCII */
+ ret++;
+ continue;
+ }
+ if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0x10ffff) {
+ if (res > 0xffff) ret++;
+ ret++;
+ }
+ else return -2; /* bad char */
+ /* otherwise ignore it */
+ }
+ return ret;
+}
+
+/* UTF-8 to wide char string conversion */
+/* return -1 on dst buffer overflow, -2 on invalid input char */
+MIR_CORE_DLL(int) Utf8toUcs2(const char *src, size_t srclen, wchar_t *dst, size_t dstlen)
+{
+ unsigned int res;
+ const char *srcend = src + srclen; // including trailing zero
+ wchar_t *dstend = dst + dstlen;
+
+ while ((dst < dstend) && (src < srcend)) {
+ unsigned char ch = *src++;
+ if (ch < 0x80) { /* special fast case for 7-bit ASCII */
+ *dst++ = ch;
+ continue;
+ }
+
+ if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0xffff)
+ *dst++ = res;
+ else if (res <= 0x10ffff) { /* we need surrogates */
+ if (dst == dstend - 1)
+ return -1; /* overflow */
+ res -= 0x10000;
+ *dst++ = 0xd800 | (res >> 10);
+ *dst++ = 0xdc00 | (res & 0x3ff);
+ }
+ else return -2; /* bad char */
+ }
+
+ if (src < srcend)
+ return -1; /* overflow */
+
+ return (int)(dstlen - (dstend - dst));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// mir_utf8decode - converts UTF8-encoded string to the UCS2/MBCS format
+
+#ifdef _MSC_VER
+MIR_CORE_DLL(char*) mir_utf8decodecp(char *str, int codepage, wchar_t **ucs2)
+{
+ bool needs_free = false;
+ wchar_t* tempBuf = nullptr;
+ if (ucs2)
+ *ucs2 = nullptr;
+
+ if (str == nullptr)
+ return nullptr;
+
+ size_t len = strlen(str);
+ if (len < 2) {
+ if (ucs2 != nullptr) {
+ *ucs2 = tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t));
+ MultiByteToWideChar(codepage, 0, str, (int)len, tempBuf, (int)len);
+ tempBuf[len] = 0;
+ }
+ return str;
+ }
+
+ int destlen = Utf8toUcs2Len(str, len);
+ if (destlen < 0)
+ return nullptr;
+
+ if (ucs2 == nullptr) {
+ __try {
+ tempBuf = (wchar_t*)alloca((destlen + 1) * sizeof(wchar_t));
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ tempBuf = nullptr;
+ needs_free = true;
+ }
+ }
+
+ if (tempBuf == nullptr) {
+ tempBuf = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t));
+ if (tempBuf == nullptr)
+ return nullptr;
+ }
+
+ Utf8toUcs2(str, len, tempBuf, destlen);
+ tempBuf[destlen] = 0;
+ WideCharToMultiByte(codepage, 0, tempBuf, -1, str, (int)len + 1, "?", nullptr);
+
+ if (ucs2)
+ *ucs2 = tempBuf;
+ else if (needs_free)
+ mir_free(tempBuf);
+
+ return str;
+}
+
+MIR_CORE_DLL(char*) mir_utf8decode(char *str, wchar_t **ucs2)
+{
+ return mir_utf8decodecp(str, Langpack_GetDefaultCodePage(), ucs2);
+}
+#endif
+
+MIR_CORE_DLL(wchar_t*) mir_utf8decodeW(const char *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ size_t len = strlen(str);
+
+ int destlen = Utf8toUcs2Len(str, len);
+ if (destlen < 0)
+ return nullptr;
+
+ wchar_t* ucs2 = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t));
+ if (ucs2 == nullptr)
+ return nullptr;
+
+ if (Utf8toUcs2(str, len, ucs2, destlen) >= 0) {
+ ucs2[destlen] = 0;
+ return ucs2;
+ }
+
+ mir_free(ucs2);
+
+ return nullptr;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// mir_utf8encode - converts MBCS string to the UTF8-encoded format
+
+#ifdef _MSC_VER
+MIR_CORE_DLL(char*) mir_utf8encodecp(const char* src, int codepage)
+{
+ int len;
+ bool needs_free = false;
+ char* result = nullptr;
+ wchar_t* tempBuf;
+
+ if (src == nullptr)
+ return nullptr;
+
+ len = (int)strlen(src);
+
+ __try {
+ tempBuf = (wchar_t*)alloca((len + 1) * sizeof(wchar_t));
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t));
+ if (tempBuf == nullptr) return nullptr;
+ needs_free = true;
+ }
+
+ len = MultiByteToWideChar(codepage, 0, src, -1, tempBuf, len + 1);
+
+ int destlen = mir_utf8len(tempBuf, len);
+ if (destlen >= 0) {
+ result = (char*)mir_alloc(destlen + 1);
+ if (result) {
+ Ucs2toUtf8(tempBuf, len, result, destlen);
+ result[destlen] = 0;
+ }
+ }
+
+ if (needs_free)
+ mir_free(tempBuf);
+
+ return result;
+}
+
+MIR_CORE_DLL(char*) mir_utf8encode(const char* src)
+{
+ return mir_utf8encodecp(src, Langpack_GetDefaultCodePage());
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// mir_utf8encode - converts UCS2 string to the UTF8-encoded format
+
+MIR_CORE_DLL(char*) mir_utf8encodeW(const wchar_t* src)
+{
+ if (src == nullptr)
+ return nullptr;
+
+ int len = (int)wcslen(src);
+
+ int destlen = mir_utf8len(src, len);
+ if (destlen < 0) return nullptr;
+
+ char* result = (char*)mir_alloc(destlen + 1);
+ if (result == nullptr)
+ return nullptr;
+
+ Ucs2toUtf8(src, len, result, destlen);
+ result[destlen] = 0;
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Utf8CheckString - checks if a string is a valid utf8-encoded string
+
+MIR_CORE_DLL(BOOL) Utf8CheckString(const char *str)
+{
+ int expect_bytes = 0, utf_found = 0;
+
+ if (!str) return 0;
+
+ while (*str) {
+ if ((*str & 0x80) == 0) {
+ /* Looks like an ASCII character */
+ if (expect_bytes)
+ /* byte of UTF-8 character expected */
+ return 0;
+ }
+ else {
+ /* Looks like byte of an UTF-8 character */
+ if (expect_bytes) {
+ /* expect_bytes already set: first byte of UTF-8 char already seen */
+ if ((*str & 0xC0) != 0x80) {
+ /* again first byte ?!?! */
+ return 0;
+ }
+ }
+ else {
+ /* First byte of the UTF-8 character */
+ /* count initial one bits and set expect_bytes to 1 less */
+ char ch = *str;
+ while (ch & 0x80) {
+ expect_bytes++;
+ ch = (ch & 0x7f) << 1;
+ }
+ }
+ /* OK, next byte of UTF-8 character */
+ /* Decrement number of expected bytes */
+ if (--expect_bytes == 0)
+ utf_found = 1;
+ }
+ str++;
+ }
+
+ return (utf_found && expect_bytes == 0);
+}
diff --git a/src/mir_core/src/utils.cpp b/src/mir_core/src/utils.cpp
index b6953a027a..07613f6394 100644
--- a/src/mir_core/src/utils.cpp
+++ b/src/mir_core/src/utils.cpp
@@ -1,570 +1,570 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-MIR_CORE_DLL(char*) replaceStr(char* &dest, const char *src)
-{
- if (dest != nullptr)
- mir_free(dest);
-
- return dest = (src != nullptr) ? mir_strdup(src) : nullptr;
-}
-
-MIR_CORE_DLL(wchar_t*) replaceStrW(wchar_t* &dest, const wchar_t *src)
-{
- if (dest != nullptr)
- mir_free(dest);
-
- return dest = (src != nullptr) ? mir_wstrdup(src) : nullptr;
-}
-
-MIR_CORE_DLL(char*) rtrim(char *str)
-{
- if (str == nullptr)
- return nullptr;
-
- char* p = strchr(str, 0);
- while (--p >= str) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- *p = 0; break;
- default:
- return str;
- }
- }
- return str;
-}
-
-MIR_CORE_DLL(wchar_t*) rtrimw(wchar_t *str)
-{
- if (str == nullptr)
- return nullptr;
-
- wchar_t *p = wcschr(str, 0);
- while (--p >= str) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- *p = 0; break;
- default:
- return str;
- }
- }
- return str;
-}
-
-MIR_CORE_DLL(char*) ltrim(char *str)
-{
- if (str == nullptr)
- return nullptr;
-
- char* p = str;
- for (;;) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- ++p; break;
- default:
- memmove(str, p, strlen(p) + 1);
- return str;
- }
- }
-}
-
-MIR_CORE_DLL(wchar_t*) ltrimw(wchar_t *str)
-{
- if (str == nullptr)
- return nullptr;
-
- wchar_t *p = str;
- for (;;) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- ++p; break;
- default:
- memmove(str, p, sizeof(wchar_t)*(wcslen(p) + 1));
- return str;
- }
- }
-}
-
-MIR_CORE_DLL(char*) ltrimp(char *str)
-{
- if (str == nullptr)
- return nullptr;
-
- char *p = str;
- for (;;) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- ++p; break;
- default:
- return p;
- }
- }
-}
-
-MIR_CORE_DLL(wchar_t*) ltrimpw(wchar_t *str)
-{
- if (str == nullptr)
- return nullptr;
-
- wchar_t *p = str;
- for (;;) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- ++p; break;
- default:
- return p;
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(char*) strdel(char *str, size_t len)
-{
- char* p;
- for (p = str + len; *p != 0; p++)
- *(p - len) = *p;
-
- *(p - len) = '\0';
- return str;
-}
-
-MIR_CORE_DLL(wchar_t*) strdelw(wchar_t *str, size_t len)
-{
- wchar_t* p;
- for (p = str + len; *p != 0; p++)
- *(p - len) = *p;
-
- *(p - len) = '\0';
- return str;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) wildcmp(const char *name, const char *mask)
-{
- if (name == nullptr || mask == nullptr)
- return false;
-
- const char *last = nullptr;
- for (;; mask++, name++) {
- if (*mask != '?' && *mask != *name) break;
- if (*name == '\0') return ((BOOL)!*mask);
- }
- if (*mask != '*') return FALSE;
- for (;; mask++, name++) {
- while (*mask == '*') {
- last = mask++;
- if (*mask == '\0') return ((BOOL)!*mask); /* true */
- }
- if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
- if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last;
- }
-}
-
-MIR_CORE_DLL(int) wildcmpw(const wchar_t *name, const wchar_t *mask)
-{
- if (name == nullptr || mask == nullptr)
- return false;
-
- const wchar_t* last = nullptr;
- for (;; mask++, name++) {
- if (*mask != '?' && *mask != *name) break;
- if (*name == '\0') return ((BOOL)!*mask);
- }
- if (*mask != '*') return FALSE;
- for (;; mask++, name++) {
- while (*mask == '*') {
- last = mask++;
- if (*mask == '\0') return ((BOOL)!*mask); /* true */
- }
- if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
- if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last;
- }
-}
-
-#define _qtoupper(_c) (((_c) >= 'a' && (_c) <= 'z')?((_c)-'a'+'A'):(_c))
-
-MIR_CORE_DLL(int) wildcmpi(const char *name, const char *mask)
-{
- if (name == nullptr || mask == nullptr)
- return false;
-
- const char *last = nullptr;
- for (;; mask++, name++) {
- if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
- if (*name == '\0') return ((BOOL)!*mask);
- }
- if (*mask != '*') return FALSE;
- for (;; mask++, name++) {
- while (*mask == '*') {
- last = mask++;
- if (*mask == '\0') return ((BOOL)!*mask); /* true */
- }
- if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
- if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
- }
-}
-
-MIR_CORE_DLL(int) wildcmpiw(const wchar_t *name, const wchar_t *mask)
-{
- if (name == nullptr || mask == nullptr)
- return false;
-
- const wchar_t* last = nullptr;
- for (;; mask++, name++) {
- if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
- if (*name == '\0') return ((BOOL)!*mask);
- }
- if (*mask != '*') return FALSE;
- for (;; mask++, name++) {
- while (*mask == '*') {
- last = mask++;
- if (*mask == '\0') return ((BOOL)!*mask); /* true */
- }
- if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
- if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static char szHexTable[] = "0123456789abcdef";
-
-MIR_CORE_DLL(char*) bin2hex(const void *pData, size_t len, char *dest)
-{
- const uint8_t *p = (const uint8_t*)pData;
- char *d = dest;
-
- for (size_t i = 0; i < len; i++, p++) {
- *d++ = szHexTable[*p >> 4];
- *d++ = szHexTable[*p & 0x0F];
- }
- *d = 0;
-
- return dest;
-}
-
-MIR_CORE_DLL(wchar_t*) bin2hexW(const void *pData, size_t len, wchar_t *dest)
-{
- const uint8_t *p = (const uint8_t*)pData;
- wchar_t *d = dest;
-
- for (size_t i = 0; i < len; i++, p++) {
- *d++ = szHexTable[*p >> 4];
- *d++ = szHexTable[*p & 0x0F];
- }
- *d = 0;
-
- return dest;
-}
-
-static int hex2dec(int iHex)
-{
- if (iHex >= '0' && iHex <= '9')
- return iHex - '0';
- if (iHex >= 'a' && iHex <= 'f')
- return iHex - 'a' + 10;
- if (iHex >= 'A' && iHex <= 'F')
- return iHex - 'A' + 10;
- return 0;
-}
-
-MIR_CORE_DLL(bool) hex2bin(const char *pSrc, void *pData, size_t len)
-{
- if (pSrc == nullptr || pData == nullptr || len == 0)
- return false;
-
- size_t bufLen = strlen(pSrc)/2;
- if (pSrc[bufLen*2] != 0 || bufLen > len)
- return false;
-
- uint8_t *pDest = (uint8_t*)pData;
- const char *p = (const char *)pSrc;
- for (size_t i = 0; i < bufLen; i++, p += 2)
- pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]);
-
- if (bufLen < len)
- memset(pDest + bufLen, 0, len - bufLen);
- return true;
-}
-
-MIR_CORE_DLL(bool) hex2binW(const wchar_t *pSrc, void *pData, size_t len)
-{
- if (pSrc == nullptr || pData == nullptr || len == 0)
- return false;
-
- size_t bufLen = wcslen(pSrc)/2;
- if (pSrc[bufLen * 2] != 0 || bufLen > len)
- return false;
-
- uint8_t *pDest = (uint8_t*)pData;
- const wchar_t *p = (const wchar_t *)pSrc;
- for (size_t i = 0; i < bufLen; i++, p += 2)
- pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]);
-
- if (bufLen < len)
- memset(pDest+bufLen, 0, len - bufLen);
- return true;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma intrinsic(strlen, strcpy, strcat, strcmp, wcslen, wcscpy, wcscat, wcscmp)
-
-MIR_CORE_DLL(size_t) mir_strlen(const char *p)
-{
- return (p) ? strlen(p) : 0;
-}
-
-MIR_CORE_DLL(size_t) mir_wstrlen(const wchar_t *p)
-{
- return (p) ? wcslen(p) : 0;
-}
-
-MIR_CORE_DLL(char*) mir_strcpy(char *dest, const char *src)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr) {
- *dest = 0;
- return dest;
- }
-
- return strcpy(dest, src);
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrcpy(wchar_t *dest, const wchar_t *src)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr) {
- *dest = 0;
- return dest;
- }
-
- return wcscpy(dest, src);
-}
-
-MIR_CORE_DLL(char*) mir_strncpy(char *dest, const char *src, size_t len)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr)
- *dest = 0;
- else
- strncpy_s(dest, len, src, _TRUNCATE);
- return dest;
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrncpy(wchar_t *dest, const wchar_t *src, size_t len)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr)
- *dest = 0;
- else
- wcsncpy_s(dest, len, src, _TRUNCATE);
- return dest;
-}
-
-MIR_CORE_DLL(char*) mir_strcat(char *dest, const char *src)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr) {
- *dest = 0;
- return dest;
- }
-
- return strcat(dest, src);
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrcat(wchar_t *dest, const wchar_t *src)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr) {
- *dest = 0;
- return dest;
- }
-
- return wcscat(dest, src);
-}
-
-MIR_CORE_DLL(char*) mir_strncat(char *dest, const char *src, size_t len)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr)
- *dest = 0;
- else
- strncat_s(dest, len, src, _TRUNCATE);
- return dest;
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrncat(wchar_t *dest, const wchar_t *src, size_t len)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr)
- *dest = 0;
- else
- wcsncat_s(dest, len, src, _TRUNCATE);
- return dest;
-}
-
-MIR_CORE_DLL(int) mir_strcmp(const char *p1, const char *p2)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return strcmp(p1, p2);
-}
-
-MIR_CORE_DLL(int) mir_wstrcmp(const wchar_t *p1, const wchar_t *p2)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return wcscmp(p1, p2);
-}
-
-MIR_CORE_DLL(int) mir_strcmpi(const char *p1, const char *p2)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return stricmp(p1, p2);
-}
-
-MIR_CORE_DLL(int) mir_wstrcmpi(const wchar_t *p1, const wchar_t *p2)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return wcsicmp(p1, p2);
-}
-
-MIR_CORE_DLL(int) mir_strncmp(const char *p1, const char *p2, size_t n)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return strncmp(p1, p2, n);
-}
-
-MIR_CORE_DLL(int) mir_wstrncmp(const wchar_t *p1, const wchar_t *p2, size_t n)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return wcsncmp(p1, p2, n);
-}
-
-MIR_CORE_DLL(int) mir_strncmpi(const char *p1, const char *p2, size_t n)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return strnicmp(p1, p2, n);
-}
-
-MIR_CORE_DLL(int) mir_wstrncmpi(const wchar_t *p1, const wchar_t *p2, size_t n)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return wcsnicmp(p1, p2, n);
-}
-
-#ifdef _MSC_VER
-MIR_CORE_DLL(const wchar_t*) mir_wstrstri(const wchar_t *s1, const wchar_t *s2)
-{
- for (int i = 0; s1[i]; i++)
- for (int j = i, k = 0; towlower(s1[j]) == towlower(s2[k]); j++, k++)
- if (!s2[k + 1])
- return s1 + i;
-
- return nullptr;
-}
-#endif
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef _MSC_VER
- PGENRANDOM pfnRtlGenRandom;
-#endif
-
-MIR_CORE_DLL(void) Utils_GetRandom(void *pszDest, size_t cbLen)
-{
- if (pszDest == nullptr || cbLen == 0)
- return;
-
- #ifdef _MSC_VER
- if (pfnRtlGenRandom != nullptr) {
- pfnRtlGenRandom(pszDest, (uint32_t)cbLen);
- return;
- }
- #endif
-
- srand(time(0));
- uint8_t *p = (uint8_t*)pszDest;
- for (size_t i = 0; i < cbLen; i++)
- p[i] = rand() & 0xFF;
-}
-
-MIR_CORE_DLL(bool) Utils_IsRtl(const wchar_t *pszwText)
-{
- #ifdef _MSC_VER
- size_t iLen = mir_wstrlen(pszwText);
- mir_ptr<uint16_t> infoTypeC2((uint16_t*)mir_calloc(sizeof(uint16_t) * (iLen + 2)));
- GetStringTypeW(CT_CTYPE2, pszwText, (int)iLen, infoTypeC2);
-
- for (size_t i = 0; i < iLen; i++)
- if (infoTypeC2[i] == C2_RIGHTTOLEFT)
- return true;
- #endif
-
- return false;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+MIR_CORE_DLL(char*) replaceStr(char* &dest, const char *src)
+{
+ if (dest != nullptr)
+ mir_free(dest);
+
+ return dest = (src != nullptr) ? mir_strdup(src) : nullptr;
+}
+
+MIR_CORE_DLL(wchar_t*) replaceStrW(wchar_t* &dest, const wchar_t *src)
+{
+ if (dest != nullptr)
+ mir_free(dest);
+
+ return dest = (src != nullptr) ? mir_wstrdup(src) : nullptr;
+}
+
+MIR_CORE_DLL(char*) rtrim(char *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ char* p = strchr(str, 0);
+ while (--p >= str) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ *p = 0; break;
+ default:
+ return str;
+ }
+ }
+ return str;
+}
+
+MIR_CORE_DLL(wchar_t*) rtrimw(wchar_t *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ wchar_t *p = wcschr(str, 0);
+ while (--p >= str) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ *p = 0; break;
+ default:
+ return str;
+ }
+ }
+ return str;
+}
+
+MIR_CORE_DLL(char*) ltrim(char *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ char* p = str;
+ for (;;) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ ++p; break;
+ default:
+ memmove(str, p, strlen(p) + 1);
+ return str;
+ }
+ }
+}
+
+MIR_CORE_DLL(wchar_t*) ltrimw(wchar_t *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ wchar_t *p = str;
+ for (;;) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ ++p; break;
+ default:
+ memmove(str, p, sizeof(wchar_t)*(wcslen(p) + 1));
+ return str;
+ }
+ }
+}
+
+MIR_CORE_DLL(char*) ltrimp(char *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ char *p = str;
+ for (;;) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ ++p; break;
+ default:
+ return p;
+ }
+ }
+}
+
+MIR_CORE_DLL(wchar_t*) ltrimpw(wchar_t *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ wchar_t *p = str;
+ for (;;) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ ++p; break;
+ default:
+ return p;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(char*) strdel(char *str, size_t len)
+{
+ char* p;
+ for (p = str + len; *p != 0; p++)
+ *(p - len) = *p;
+
+ *(p - len) = '\0';
+ return str;
+}
+
+MIR_CORE_DLL(wchar_t*) strdelw(wchar_t *str, size_t len)
+{
+ wchar_t* p;
+ for (p = str + len; *p != 0; p++)
+ *(p - len) = *p;
+
+ *(p - len) = '\0';
+ return str;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) wildcmp(const char *name, const char *mask)
+{
+ if (name == nullptr || mask == nullptr)
+ return false;
+
+ const char *last = nullptr;
+ for (;; mask++, name++) {
+ if (*mask != '?' && *mask != *name) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++) {
+ while (*mask == '*') {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+MIR_CORE_DLL(int) wildcmpw(const wchar_t *name, const wchar_t *mask)
+{
+ if (name == nullptr || mask == nullptr)
+ return false;
+
+ const wchar_t* last = nullptr;
+ for (;; mask++, name++) {
+ if (*mask != '?' && *mask != *name) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++) {
+ while (*mask == '*') {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+#define _qtoupper(_c) (((_c) >= 'a' && (_c) <= 'z')?((_c)-'a'+'A'):(_c))
+
+MIR_CORE_DLL(int) wildcmpi(const char *name, const char *mask)
+{
+ if (name == nullptr || mask == nullptr)
+ return false;
+
+ const char *last = nullptr;
+ for (;; mask++, name++) {
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++) {
+ while (*mask == '*') {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+MIR_CORE_DLL(int) wildcmpiw(const wchar_t *name, const wchar_t *mask)
+{
+ if (name == nullptr || mask == nullptr)
+ return false;
+
+ const wchar_t* last = nullptr;
+ for (;; mask++, name++) {
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++) {
+ while (*mask == '*') {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static char szHexTable[] = "0123456789abcdef";
+
+MIR_CORE_DLL(char*) bin2hex(const void *pData, size_t len, char *dest)
+{
+ const uint8_t *p = (const uint8_t*)pData;
+ char *d = dest;
+
+ for (size_t i = 0; i < len; i++, p++) {
+ *d++ = szHexTable[*p >> 4];
+ *d++ = szHexTable[*p & 0x0F];
+ }
+ *d = 0;
+
+ return dest;
+}
+
+MIR_CORE_DLL(wchar_t*) bin2hexW(const void *pData, size_t len, wchar_t *dest)
+{
+ const uint8_t *p = (const uint8_t*)pData;
+ wchar_t *d = dest;
+
+ for (size_t i = 0; i < len; i++, p++) {
+ *d++ = szHexTable[*p >> 4];
+ *d++ = szHexTable[*p & 0x0F];
+ }
+ *d = 0;
+
+ return dest;
+}
+
+static int hex2dec(int iHex)
+{
+ if (iHex >= '0' && iHex <= '9')
+ return iHex - '0';
+ if (iHex >= 'a' && iHex <= 'f')
+ return iHex - 'a' + 10;
+ if (iHex >= 'A' && iHex <= 'F')
+ return iHex - 'A' + 10;
+ return 0;
+}
+
+MIR_CORE_DLL(bool) hex2bin(const char *pSrc, void *pData, size_t len)
+{
+ if (pSrc == nullptr || pData == nullptr || len == 0)
+ return false;
+
+ size_t bufLen = strlen(pSrc)/2;
+ if (pSrc[bufLen*2] != 0 || bufLen > len)
+ return false;
+
+ uint8_t *pDest = (uint8_t*)pData;
+ const char *p = (const char *)pSrc;
+ for (size_t i = 0; i < bufLen; i++, p += 2)
+ pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]);
+
+ if (bufLen < len)
+ memset(pDest + bufLen, 0, len - bufLen);
+ return true;
+}
+
+MIR_CORE_DLL(bool) hex2binW(const wchar_t *pSrc, void *pData, size_t len)
+{
+ if (pSrc == nullptr || pData == nullptr || len == 0)
+ return false;
+
+ size_t bufLen = wcslen(pSrc)/2;
+ if (pSrc[bufLen * 2] != 0 || bufLen > len)
+ return false;
+
+ uint8_t *pDest = (uint8_t*)pData;
+ const wchar_t *p = (const wchar_t *)pSrc;
+ for (size_t i = 0; i < bufLen; i++, p += 2)
+ pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]);
+
+ if (bufLen < len)
+ memset(pDest+bufLen, 0, len - bufLen);
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#pragma intrinsic(strlen, strcpy, strcat, strcmp, wcslen, wcscpy, wcscat, wcscmp)
+
+MIR_CORE_DLL(size_t) mir_strlen(const char *p)
+{
+ return (p) ? strlen(p) : 0;
+}
+
+MIR_CORE_DLL(size_t) mir_wstrlen(const wchar_t *p)
+{
+ return (p) ? wcslen(p) : 0;
+}
+
+MIR_CORE_DLL(char*) mir_strcpy(char *dest, const char *src)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr) {
+ *dest = 0;
+ return dest;
+ }
+
+ return strcpy(dest, src);
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrcpy(wchar_t *dest, const wchar_t *src)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr) {
+ *dest = 0;
+ return dest;
+ }
+
+ return wcscpy(dest, src);
+}
+
+MIR_CORE_DLL(char*) mir_strncpy(char *dest, const char *src, size_t len)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr)
+ *dest = 0;
+ else
+ strncpy_s(dest, len, src, _TRUNCATE);
+ return dest;
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrncpy(wchar_t *dest, const wchar_t *src, size_t len)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr)
+ *dest = 0;
+ else
+ wcsncpy_s(dest, len, src, _TRUNCATE);
+ return dest;
+}
+
+MIR_CORE_DLL(char*) mir_strcat(char *dest, const char *src)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr) {
+ *dest = 0;
+ return dest;
+ }
+
+ return strcat(dest, src);
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrcat(wchar_t *dest, const wchar_t *src)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr) {
+ *dest = 0;
+ return dest;
+ }
+
+ return wcscat(dest, src);
+}
+
+MIR_CORE_DLL(char*) mir_strncat(char *dest, const char *src, size_t len)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr)
+ *dest = 0;
+ else
+ strncat_s(dest, len, src, _TRUNCATE);
+ return dest;
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrncat(wchar_t *dest, const wchar_t *src, size_t len)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr)
+ *dest = 0;
+ else
+ wcsncat_s(dest, len, src, _TRUNCATE);
+ return dest;
+}
+
+MIR_CORE_DLL(int) mir_strcmp(const char *p1, const char *p2)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return strcmp(p1, p2);
+}
+
+MIR_CORE_DLL(int) mir_wstrcmp(const wchar_t *p1, const wchar_t *p2)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return wcscmp(p1, p2);
+}
+
+MIR_CORE_DLL(int) mir_strcmpi(const char *p1, const char *p2)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return stricmp(p1, p2);
+}
+
+MIR_CORE_DLL(int) mir_wstrcmpi(const wchar_t *p1, const wchar_t *p2)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return wcsicmp(p1, p2);
+}
+
+MIR_CORE_DLL(int) mir_strncmp(const char *p1, const char *p2, size_t n)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return strncmp(p1, p2, n);
+}
+
+MIR_CORE_DLL(int) mir_wstrncmp(const wchar_t *p1, const wchar_t *p2, size_t n)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return wcsncmp(p1, p2, n);
+}
+
+MIR_CORE_DLL(int) mir_strncmpi(const char *p1, const char *p2, size_t n)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return strnicmp(p1, p2, n);
+}
+
+MIR_CORE_DLL(int) mir_wstrncmpi(const wchar_t *p1, const wchar_t *p2, size_t n)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return wcsnicmp(p1, p2, n);
+}
+
+#ifdef _MSC_VER
+MIR_CORE_DLL(const wchar_t*) mir_wstrstri(const wchar_t *s1, const wchar_t *s2)
+{
+ for (int i = 0; s1[i]; i++)
+ for (int j = i, k = 0; towlower(s1[j]) == towlower(s2[k]); j++, k++)
+ if (!s2[k + 1])
+ return s1 + i;
+
+ return nullptr;
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef _MSC_VER
+ PGENRANDOM pfnRtlGenRandom;
+#endif
+
+MIR_CORE_DLL(void) Utils_GetRandom(void *pszDest, size_t cbLen)
+{
+ if (pszDest == nullptr || cbLen == 0)
+ return;
+
+ #ifdef _MSC_VER
+ if (pfnRtlGenRandom != nullptr) {
+ pfnRtlGenRandom(pszDest, (uint32_t)cbLen);
+ return;
+ }
+ #endif
+
+ srand(time(0));
+ uint8_t *p = (uint8_t*)pszDest;
+ for (size_t i = 0; i < cbLen; i++)
+ p[i] = rand() & 0xFF;
+}
+
+MIR_CORE_DLL(bool) Utils_IsRtl(const wchar_t *pszwText)
+{
+ #ifdef _MSC_VER
+ size_t iLen = mir_wstrlen(pszwText);
+ mir_ptr<uint16_t> infoTypeC2((uint16_t*)mir_calloc(sizeof(uint16_t) * (iLen + 2)));
+ GetStringTypeW(CT_CTYPE2, pszwText, (int)iLen, infoTypeC2);
+
+ for (size_t i = 0; i < iLen; i++)
+ if (infoTypeC2[i] == C2_RIGHTTOLEFT)
+ return true;
+ #endif
+
+ return false;
+}