From 27dab93c710a72ed363b5e0a543827b210ea71af Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 7 Nov 2021 12:05:31 +0300 Subject: let's separate modules for Windows from common ones --- src/mir_core/mir_core.vcxproj | 165 ++++-- src/mir_core/mir_core.vcxproj.filters | 202 +++---- src/mir_core/src/CCtrlBase.cpp | 224 -------- src/mir_core/src/CCtrlButton.cpp | 54 -- src/mir_core/src/CCtrlCheck.cpp | 68 --- src/mir_core/src/CCtrlClc.cpp | 207 ------- src/mir_core/src/CCtrlColor.cpp | 61 --- src/mir_core/src/CCtrlCombo.cpp | 185 ------- src/mir_core/src/CCtrlData.cpp | 52 -- src/mir_core/src/CCtrlEdit.cpp | 68 --- src/mir_core/src/CCtrlHyperlink.cpp | 54 -- src/mir_core/src/CCtrlLabel.cpp | 31 -- src/mir_core/src/CCtrlListBox.cpp | 160 ------ src/mir_core/src/CCtrlListView.cpp | 551 ------------------- src/mir_core/src/CCtrlMButton.cpp | 62 --- src/mir_core/src/CCtrlPages.cpp | 411 -------------- src/mir_core/src/CCtrlRichEdit.cpp | 192 ------- src/mir_core/src/CCtrlSlider.cpp | 70 --- src/mir_core/src/CCtrlSpin.cpp | 81 --- src/mir_core/src/CCtrlTreeOpts.cpp | 169 ------ src/mir_core/src/CCtrlTreeView.cpp | 817 ---------------------------- src/mir_core/src/CDbLink.cpp | 92 ---- src/mir_core/src/CDlgBase.cpp | 501 ----------------- src/mir_core/src/CProgress.cpp | 53 -- src/mir_core/src/CSplitter.cpp | 83 --- src/mir_core/src/CTimer.cpp | 90 --- src/mir_core/src/Windows/CCtrlBase.cpp | 224 ++++++++ src/mir_core/src/Windows/CCtrlButton.cpp | 54 ++ src/mir_core/src/Windows/CCtrlCheck.cpp | 68 +++ src/mir_core/src/Windows/CCtrlClc.cpp | 207 +++++++ src/mir_core/src/Windows/CCtrlColor.cpp | 61 +++ src/mir_core/src/Windows/CCtrlCombo.cpp | 185 +++++++ src/mir_core/src/Windows/CCtrlData.cpp | 52 ++ src/mir_core/src/Windows/CCtrlEdit.cpp | 68 +++ src/mir_core/src/Windows/CCtrlHyperlink.cpp | 54 ++ src/mir_core/src/Windows/CCtrlLabel.cpp | 31 ++ src/mir_core/src/Windows/CCtrlListBox.cpp | 160 ++++++ src/mir_core/src/Windows/CCtrlListView.cpp | 551 +++++++++++++++++++ src/mir_core/src/Windows/CCtrlMButton.cpp | 62 +++ src/mir_core/src/Windows/CCtrlPages.cpp | 411 ++++++++++++++ src/mir_core/src/Windows/CCtrlRichEdit.cpp | 192 +++++++ src/mir_core/src/Windows/CCtrlSlider.cpp | 70 +++ src/mir_core/src/Windows/CCtrlSpin.cpp | 81 +++ src/mir_core/src/Windows/CCtrlTreeOpts.cpp | 169 ++++++ src/mir_core/src/Windows/CCtrlTreeView.cpp | 817 ++++++++++++++++++++++++++++ src/mir_core/src/Windows/CDbLink.cpp | 92 ++++ src/mir_core/src/Windows/CDlgBase.cpp | 501 +++++++++++++++++ src/mir_core/src/Windows/CProgress.cpp | 53 ++ src/mir_core/src/Windows/CSplitter.cpp | 83 +++ src/mir_core/src/Windows/CTimer.cpp | 90 +++ src/mir_core/src/Windows/cctrldate.cpp | 49 ++ src/mir_core/src/Windows/cmdline.cpp | 77 +++ src/mir_core/src/Windows/colourpicker.cpp | 105 ++++ src/mir_core/src/Windows/hyperlink.cpp | 277 ++++++++++ src/mir_core/src/Windows/icons.cpp | 74 +++ src/mir_core/src/Windows/langpack.cpp | 765 ++++++++++++++++++++++++++ src/mir_core/src/Windows/locks.cpp | 45 ++ src/mir_core/src/Windows/miranda.cpp | 149 +++++ src/mir_core/src/Windows/openurl.cpp | 76 +++ src/mir_core/src/Windows/path.cpp | 246 +++++++++ src/mir_core/src/Windows/resizer.cpp | 151 +++++ src/mir_core/src/Windows/subclass.cpp | 201 +++++++ src/mir_core/src/Windows/threads.cpp | 400 ++++++++++++++ src/mir_core/src/Windows/timezones.cpp | 592 ++++++++++++++++++++ src/mir_core/src/Windows/windowlist.cpp | 105 ++++ src/mir_core/src/Windows/winutil.cpp | 118 ++++ src/mir_core/src/Windows/winver.cpp | 372 +++++++++++++ src/mir_core/src/cctrldate.cpp | 49 -- src/mir_core/src/cmdline.cpp | 77 --- src/mir_core/src/colourpicker.cpp | 105 ---- src/mir_core/src/hyperlink.cpp | 277 ---------- src/mir_core/src/icons.cpp | 74 --- src/mir_core/src/langpack.cpp | 765 -------------------------- src/mir_core/src/locks.cpp | 45 -- src/mir_core/src/miranda.cpp | 149 ----- src/mir_core/src/openurl.cpp | 76 --- src/mir_core/src/path.cpp | 246 --------- src/mir_core/src/resizer.cpp | 151 ----- src/mir_core/src/subclass.cpp | 201 ------- src/mir_core/src/threads.cpp | 400 -------------- src/mir_core/src/timezones.cpp | 592 -------------------- src/mir_core/src/windowlist.cpp | 105 ---- src/mir_core/src/winutil.cpp | 118 ---- src/mir_core/src/winver.cpp | 372 ------------- 84 files changed, 8367 insertions(+), 8276 deletions(-) delete mode 100644 src/mir_core/src/CCtrlBase.cpp delete mode 100644 src/mir_core/src/CCtrlButton.cpp delete mode 100644 src/mir_core/src/CCtrlCheck.cpp delete mode 100644 src/mir_core/src/CCtrlClc.cpp delete mode 100644 src/mir_core/src/CCtrlColor.cpp delete mode 100644 src/mir_core/src/CCtrlCombo.cpp delete mode 100644 src/mir_core/src/CCtrlData.cpp delete mode 100644 src/mir_core/src/CCtrlEdit.cpp delete mode 100644 src/mir_core/src/CCtrlHyperlink.cpp delete mode 100644 src/mir_core/src/CCtrlLabel.cpp delete mode 100644 src/mir_core/src/CCtrlListBox.cpp delete mode 100644 src/mir_core/src/CCtrlListView.cpp delete mode 100644 src/mir_core/src/CCtrlMButton.cpp delete mode 100644 src/mir_core/src/CCtrlPages.cpp delete mode 100644 src/mir_core/src/CCtrlRichEdit.cpp delete mode 100644 src/mir_core/src/CCtrlSlider.cpp delete mode 100644 src/mir_core/src/CCtrlSpin.cpp delete mode 100644 src/mir_core/src/CCtrlTreeOpts.cpp delete mode 100644 src/mir_core/src/CCtrlTreeView.cpp delete mode 100644 src/mir_core/src/CDbLink.cpp delete mode 100644 src/mir_core/src/CDlgBase.cpp delete mode 100644 src/mir_core/src/CProgress.cpp delete mode 100644 src/mir_core/src/CSplitter.cpp delete mode 100644 src/mir_core/src/CTimer.cpp create mode 100644 src/mir_core/src/Windows/CCtrlBase.cpp create mode 100644 src/mir_core/src/Windows/CCtrlButton.cpp create mode 100644 src/mir_core/src/Windows/CCtrlCheck.cpp create mode 100644 src/mir_core/src/Windows/CCtrlClc.cpp create mode 100644 src/mir_core/src/Windows/CCtrlColor.cpp create mode 100644 src/mir_core/src/Windows/CCtrlCombo.cpp create mode 100644 src/mir_core/src/Windows/CCtrlData.cpp create mode 100644 src/mir_core/src/Windows/CCtrlEdit.cpp create mode 100644 src/mir_core/src/Windows/CCtrlHyperlink.cpp create mode 100644 src/mir_core/src/Windows/CCtrlLabel.cpp create mode 100644 src/mir_core/src/Windows/CCtrlListBox.cpp create mode 100644 src/mir_core/src/Windows/CCtrlListView.cpp create mode 100644 src/mir_core/src/Windows/CCtrlMButton.cpp create mode 100644 src/mir_core/src/Windows/CCtrlPages.cpp create mode 100644 src/mir_core/src/Windows/CCtrlRichEdit.cpp create mode 100644 src/mir_core/src/Windows/CCtrlSlider.cpp create mode 100644 src/mir_core/src/Windows/CCtrlSpin.cpp create mode 100644 src/mir_core/src/Windows/CCtrlTreeOpts.cpp create mode 100644 src/mir_core/src/Windows/CCtrlTreeView.cpp create mode 100644 src/mir_core/src/Windows/CDbLink.cpp create mode 100644 src/mir_core/src/Windows/CDlgBase.cpp create mode 100644 src/mir_core/src/Windows/CProgress.cpp create mode 100644 src/mir_core/src/Windows/CSplitter.cpp create mode 100644 src/mir_core/src/Windows/CTimer.cpp create mode 100644 src/mir_core/src/Windows/cctrldate.cpp create mode 100644 src/mir_core/src/Windows/cmdline.cpp create mode 100644 src/mir_core/src/Windows/colourpicker.cpp create mode 100644 src/mir_core/src/Windows/hyperlink.cpp create mode 100644 src/mir_core/src/Windows/icons.cpp create mode 100644 src/mir_core/src/Windows/langpack.cpp create mode 100644 src/mir_core/src/Windows/locks.cpp create mode 100644 src/mir_core/src/Windows/miranda.cpp create mode 100644 src/mir_core/src/Windows/openurl.cpp create mode 100644 src/mir_core/src/Windows/path.cpp create mode 100644 src/mir_core/src/Windows/resizer.cpp create mode 100644 src/mir_core/src/Windows/subclass.cpp create mode 100644 src/mir_core/src/Windows/threads.cpp create mode 100644 src/mir_core/src/Windows/timezones.cpp create mode 100644 src/mir_core/src/Windows/windowlist.cpp create mode 100644 src/mir_core/src/Windows/winutil.cpp create mode 100644 src/mir_core/src/Windows/winver.cpp delete mode 100644 src/mir_core/src/cctrldate.cpp delete mode 100644 src/mir_core/src/cmdline.cpp delete mode 100644 src/mir_core/src/colourpicker.cpp delete mode 100644 src/mir_core/src/hyperlink.cpp delete mode 100644 src/mir_core/src/icons.cpp delete mode 100644 src/mir_core/src/langpack.cpp delete mode 100644 src/mir_core/src/locks.cpp delete mode 100644 src/mir_core/src/miranda.cpp delete mode 100644 src/mir_core/src/openurl.cpp delete mode 100644 src/mir_core/src/path.cpp delete mode 100644 src/mir_core/src/resizer.cpp delete mode 100644 src/mir_core/src/subclass.cpp delete mode 100644 src/mir_core/src/threads.cpp delete mode 100644 src/mir_core/src/timezones.cpp delete mode 100644 src/mir_core/src/windowlist.cpp delete mode 100644 src/mir_core/src/winutil.cpp delete mode 100644 src/mir_core/src/winver.cpp diff --git a/src/mir_core/mir_core.vcxproj b/src/mir_core/mir_core.vcxproj index 23e75824de..f0466fabab 100644 --- a/src/mir_core/mir_core.vcxproj +++ b/src/mir_core/mir_core.vcxproj @@ -42,67 +42,150 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - - - - - - + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + + ../stdafx.h + + diff --git a/src/mir_core/mir_core.vcxproj.filters b/src/mir_core/mir_core.vcxproj.filters index 2eba1c3237..92df544754 100644 --- a/src/mir_core/mir_core.vcxproj.filters +++ b/src/mir_core/mir_core.vcxproj.filters @@ -8,173 +8,173 @@ Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows - - Source Files + + Source Files\Windows @@ -187,6 +187,9 @@ Header Files + + Source Files + @@ -197,4 +200,9 @@ + + + {af52c09e-568e-4948-95c9-120c030fd932} + + \ No newline at end of file diff --git a/src/mir_core/src/CCtrlBase.cpp b/src/mir_core/src/CCtrlBase.cpp deleted file mode 100644 index aa684707e0..0000000000 --- a/src/mir_core/src/CCtrlBase.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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 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/CCtrlButton.cpp b/src/mir_core/src/CCtrlButton.cpp deleted file mode 100644 index 75b25e477c..0000000000 --- a/src/mir_core/src/CCtrlButton.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, WORD, WORD 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/CCtrlCheck.cpp b/src/mir_core/src/CCtrlCheck.cpp deleted file mode 100644 index ce765274b4..0000000000 --- a/src/mir_core/src/CCtrlCheck.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, WORD, WORD) -{ - 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/CCtrlClc.cpp b/src/mir_core/src/CCtrlClc.cpp deleted file mode 100644 index b5b439cdb7..0000000000 --- a/src/mir_core/src/CCtrlClc.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, DWORD 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); -} - -DWORD 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); -} - -BYTE CCtrlClc::GetExtraImage(HANDLE hItem, int iColumn) const -{ - return (BYTE)(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, DWORD *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(DWORD modes) -{ SendMessage(m_hwnd, CLM_SETOFFLINEMODES, modes, 0); -} - -DWORD CCtrlClc::GetExStyle() const -{ return SendMessage(m_hwnd, CLM_GETEXSTYLE, 0, 0); -} - -void CCtrlClc::SetExStyle(DWORD 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, DWORD flags) const -{ return (HANDLE)SendMessage(m_hwnd, CLM_GETNEXTITEM, (WPARAM)flags, (LPARAM)hItem); -} diff --git a/src/mir_core/src/CCtrlColor.cpp b/src/mir_core/src/CCtrlColor.cpp deleted file mode 100644 index 71e913b5b9..0000000000 --- a/src/mir_core/src/CCtrlColor.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, WORD, WORD) -{ - 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()); -} - -DWORD CCtrlColor::GetColor() -{ - return ::SendMessage(m_hwnd, CPM_GETCOLOUR, 0, 0); -} - -void CCtrlColor::SetColor(DWORD dwValue) -{ - ::SendMessage(m_hwnd, CPM_SETCOLOUR, 0, dwValue); -} diff --git a/src/mir_core/src/CCtrlCombo.cpp b/src/mir_core/src/CCtrlCombo.cpp deleted file mode 100644 index 4a67f14720..0000000000 --- a/src/mir_core/src/CCtrlCombo.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, WORD, WORD 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/CCtrlData.cpp b/src/mir_core/src/CCtrlData.cpp deleted file mode 100644 index 92c25a4c4d..0000000000 --- a/src/mir_core/src/CCtrlData.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, BYTE type, DWORD 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/CCtrlEdit.cpp b/src/mir_core/src/CCtrlEdit.cpp deleted file mode 100644 index 3f60855843..0000000000 --- a/src/mir_core/src/CCtrlEdit.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, WORD, WORD 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/CCtrlHyperlink.cpp b/src/mir_core/src/CCtrlHyperlink.cpp deleted file mode 100644 index 7a4bf2ab28..0000000000 --- a/src/mir_core/src/CCtrlHyperlink.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, WORD, WORD) -{ - 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/CCtrlLabel.cpp b/src/mir_core/src/CCtrlLabel.cpp deleted file mode 100644 index 2f95578aba..0000000000 --- a/src/mir_core/src/CCtrlLabel.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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/CCtrlListBox.cpp b/src/mir_core/src/CCtrlListBox.cpp deleted file mode 100644 index da75fefe19..0000000000 --- a/src/mir_core/src/CCtrlListBox.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, WORD, WORD 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/CCtrlListView.cpp b/src/mir_core/src/CCtrlListView.cpp deleted file mode 100644 index 5ac8f4d32e..0000000000 --- a/src/mir_core/src/CCtrlListView.cpp +++ /dev/null @@ -1,551 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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 -DWORD 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); -} -DWORD 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); -} -DWORD 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); -} -DWORD 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); -} -DWORD 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 LPLVCOLUMN 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 LPLVITEM 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(DWORD dwExStyle) -{ ListView_SetExtendedListViewStyle(m_hwnd, dwExStyle); -} -void CCtrlListView::SetExtendedListViewStyleEx(DWORD dwExMask, DWORD 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(DWORD dwHoverTime) -{ ListView_SetHoverTime(m_hwnd, dwHoverTime); -} -DWORD 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 LPLVITEM pitem) -{ return ListView_SetItem(m_hwnd, pitem); -} -void CCtrlListView::SetItemCount(int cItems) -{ ListView_SetItemCount(m_hwnd, cItems); -} -void CCtrlListView::SetItemCountEx(int cItems, DWORD 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(DWORD 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/CCtrlMButton.cpp b/src/mir_core/src/CCtrlMButton.cpp deleted file mode 100644 index 42f5fd3303..0000000000 --- a/src/mir_core/src/CCtrlMButton.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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/CCtrlPages.cpp b/src/mir_core/src/CCtrlPages.cpp deleted file mode 100644 index 4ca7f1b16d..0000000000 --- a/src/mir_core/src/CCtrlPages.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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/CCtrlRichEdit.cpp b/src/mir_core/src/CCtrlRichEdit.cpp deleted file mode 100644 index eec1a467c2..0000000000 --- a/src/mir_core/src/CCtrlRichEdit.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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 - -///////////////////////////////////////////////////////////////////////////////////////// -// 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)>l, 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 DWORD 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; - DWORD 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)(WORD, 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/CCtrlSlider.cpp b/src/mir_core/src/CCtrlSlider.cpp deleted file mode 100644 index df42737d0b..0000000000 --- a/src/mir_core/src/CCtrlSlider.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, WORD, WORD 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/CCtrlSpin.cpp b/src/mir_core/src/CCtrlSpin.cpp deleted file mode 100644 index 9f452d6d6f..0000000000 --- a/src/mir_core/src/CCtrlSpin.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, WORD wMax, WORD 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()); -} - -WORD CCtrlSpin::GetPosition() -{ - return m_wCurr; -} - -void CCtrlSpin::SetPosition(WORD wPos) -{ - SendMsg(UDM_SETPOS, 0, m_wCurr = wPos); -} diff --git a/src/mir_core/src/CCtrlTreeOpts.cpp b/src/mir_core/src/CCtrlTreeOpts.cpp deleted file mode 100644 index 4c63a0042f..0000000000 --- a/src/mir_core/src/CCtrlTreeOpts.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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 &option) -{ - m_options.insert(new COptionsItem(pwszSection, pwszName, option), 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); - } - - 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 = (*it->m_option) ? 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); - *it->m_option = (tvi.iImage == IMG_CHECK) ? 1 : 0; - } - 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/CCtrlTreeView.cpp b/src/mir_core/src/CCtrlTreeView.cpp deleted file mode 100644 index 0522bfee03..0000000000 --- a/src/mir_core/src/CCtrlTreeView.cpp +++ /dev/null @@ -1,817 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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 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, DWORD flag) -{ TreeView_Expand(m_hwnd, hItem, flag); -} - -COLORREF CCtrlTreeView::GetBkColor() const -{ return TreeView_GetBkColor(m_hwnd); -} - -DWORD 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); -} - -DWORD CCtrlTreeView::GetItemState(HTREEITEM hItem, DWORD 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, DWORD 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); -} - -DWORD 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, DWORD 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, DWORD 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, DWORD state, DWORD 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/CDbLink.cpp b/src/mir_core/src/CDbLink.cpp deleted file mode 100644 index e81c5e181a..0000000000 --- a/src/mir_core/src/CDbLink.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, BYTE type, DWORD 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, BYTE 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); -} - -DWORD 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(DWORD value) -{ - switch (m_type) { - case DBVT_BYTE: db_set_b(0, m_szModule, m_szSetting, (BYTE)value); break; - case DBVT_WORD: db_set_w(0, m_szModule, m_szSetting, (WORD)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/CDlgBase.cpp b/src/mir_core/src/CDlgBase.cpp deleted file mode 100644 index f9f5f47a06..0000000000 --- a/src/mir_core/src/CDlgBase.cpp +++ /dev/null @@ -1,501 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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 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); -} - -void CDlgBase::EndModal(INT_PTR nResult) -{ - ::EndDialog(m_hwnd, nResult); -} - -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, BYTE type, DWORD 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(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; - WORD idCtrl = LOWORD(wParam); - WORD 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: - if (m_forceResizable || (GetWindowLongPtr(m_hwnd, GWL_STYLE) & WS_THICKFRAME)) - Utils_ResizeDialog(m_hwnd, m_pPlugin.getInst(), MAKEINTRESOURCEA(m_idDialog), GlobalDlgResizer); - 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); -} - -int CDlgBase::GlobalDlgResizer(HWND hwnd, LPARAM, UTILRESIZECONTROL *urc) -{ - CDlgBase *wnd = CDlgBase::Find(hwnd); - return (wnd == nullptr) ? 0 : wnd->Resizer(urc); -} - -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/CProgress.cpp b/src/mir_core/src/CProgress.cpp deleted file mode 100644 index 3b745b10cd..0000000000 --- a/src/mir_core/src/CProgress.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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(WORD max, WORD min) -{ - SendMsg(PBM_SETRANGE, 0, MAKELPARAM(min, max)); -} - -void CCtrlProgress::SetPosition(WORD value) -{ - SendMsg(PBM_SETPOS, value, 0); -} - -void CCtrlProgress::SetStep(WORD value) -{ - SendMsg(PBM_SETSTEP, value, 0); -} - -WORD CCtrlProgress::Move(WORD delta) -{ - return delta == 0 - ? SendMsg(PBM_STEPIT, 0, 0) - : SendMsg(PBM_DELTAPOS, delta, 0); -} diff --git a/src/mir_core/src/CSplitter.cpp b/src/mir_core/src/CSplitter.cpp deleted file mode 100644 index 7ea0b538c9..0000000000 --- a/src/mir_core/src/CSplitter.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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/CTimer.cpp b/src/mir_core/src/CTimer.cpp deleted file mode 100644 index dfaa83be0a..0000000000 --- a/src/mir_core/src/CTimer.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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, ¶m); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -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/CCtrlBase.cpp b/src/mir_core/src/Windows/CCtrlBase.cpp new file mode 100644 index 0000000000..83afe7fea6 --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlBase.cpp @@ -0,0 +1,224 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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 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 new file mode 100644 index 0000000000..d86ba2e0ad --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlButton.cpp @@ -0,0 +1,54 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, WORD, WORD 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 new file mode 100644 index 0000000000..0315e1601b --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlCheck.cpp @@ -0,0 +1,68 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, WORD, WORD) +{ + 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 new file mode 100644 index 0000000000..9239d3d61a --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlClc.cpp @@ -0,0 +1,207 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, DWORD 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); +} + +DWORD 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); +} + +BYTE CCtrlClc::GetExtraImage(HANDLE hItem, int iColumn) const +{ + return (BYTE)(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, DWORD *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(DWORD modes) +{ SendMessage(m_hwnd, CLM_SETOFFLINEMODES, modes, 0); +} + +DWORD CCtrlClc::GetExStyle() const +{ return SendMessage(m_hwnd, CLM_GETEXSTYLE, 0, 0); +} + +void CCtrlClc::SetExStyle(DWORD 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, DWORD 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 new file mode 100644 index 0000000000..dcd841b213 --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlColor.cpp @@ -0,0 +1,61 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, WORD, WORD) +{ + 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()); +} + +DWORD CCtrlColor::GetColor() +{ + return ::SendMessage(m_hwnd, CPM_GETCOLOUR, 0, 0); +} + +void CCtrlColor::SetColor(DWORD 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 new file mode 100644 index 0000000000..f481b1554d --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlCombo.cpp @@ -0,0 +1,185 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, WORD, WORD 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 new file mode 100644 index 0000000000..7f228b159e --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlData.cpp @@ -0,0 +1,52 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, BYTE type, DWORD 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/CCtrlEdit.cpp b/src/mir_core/src/Windows/CCtrlEdit.cpp new file mode 100644 index 0000000000..4395af9419 --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlEdit.cpp @@ -0,0 +1,68 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, WORD, WORD 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 new file mode 100644 index 0000000000..f63e87ed8e --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlHyperlink.cpp @@ -0,0 +1,54 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, WORD, WORD) +{ + 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 new file mode 100644 index 0000000000..f4848592d5 --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlLabel.cpp @@ -0,0 +1,31 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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 new file mode 100644 index 0000000000..71519a96ca --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlListBox.cpp @@ -0,0 +1,160 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, WORD, WORD 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 new file mode 100644 index 0000000000..23f780f170 --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlListView.cpp @@ -0,0 +1,551 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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 +DWORD 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); +} +DWORD 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); +} +DWORD 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); +} +DWORD 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); +} +DWORD 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 LPLVCOLUMN 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 LPLVITEM 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(DWORD dwExStyle) +{ ListView_SetExtendedListViewStyle(m_hwnd, dwExStyle); +} +void CCtrlListView::SetExtendedListViewStyleEx(DWORD dwExMask, DWORD 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(DWORD dwHoverTime) +{ ListView_SetHoverTime(m_hwnd, dwHoverTime); +} +DWORD 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 LPLVITEM pitem) +{ return ListView_SetItem(m_hwnd, pitem); +} +void CCtrlListView::SetItemCount(int cItems) +{ ListView_SetItemCount(m_hwnd, cItems); +} +void CCtrlListView::SetItemCountEx(int cItems, DWORD 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(DWORD 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 new file mode 100644 index 0000000000..6ab2cb0efd --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlMButton.cpp @@ -0,0 +1,62 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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 new file mode 100644 index 0000000000..81ffdd008a --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlPages.cpp @@ -0,0 +1,411 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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 new file mode 100644 index 0000000000..44d965a682 --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlRichEdit.cpp @@ -0,0 +1,192 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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 + +///////////////////////////////////////////////////////////////////////////////////////// +// 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)>l, 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 DWORD 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; + DWORD 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)(WORD, 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 new file mode 100644 index 0000000000..4adbd45506 --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlSlider.cpp @@ -0,0 +1,70 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, WORD, WORD 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 new file mode 100644 index 0000000000..bf75a67c91 --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlSpin.cpp @@ -0,0 +1,81 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, WORD wMax, WORD 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()); +} + +WORD CCtrlSpin::GetPosition() +{ + return m_wCurr; +} + +void CCtrlSpin::SetPosition(WORD 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 new file mode 100644 index 0000000000..0867347106 --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlTreeOpts.cpp @@ -0,0 +1,169 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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 &option) +{ + m_options.insert(new COptionsItem(pwszSection, pwszName, option), 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); + } + + 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 = (*it->m_option) ? 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); + *it->m_option = (tvi.iImage == IMG_CHECK) ? 1 : 0; + } + 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/Windows/CCtrlTreeView.cpp b/src/mir_core/src/Windows/CCtrlTreeView.cpp new file mode 100644 index 0000000000..08b4d57d7b --- /dev/null +++ b/src/mir_core/src/Windows/CCtrlTreeView.cpp @@ -0,0 +1,817 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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 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, DWORD flag) +{ TreeView_Expand(m_hwnd, hItem, flag); +} + +COLORREF CCtrlTreeView::GetBkColor() const +{ return TreeView_GetBkColor(m_hwnd); +} + +DWORD 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); +} + +DWORD CCtrlTreeView::GetItemState(HTREEITEM hItem, DWORD 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, DWORD 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); +} + +DWORD 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, DWORD 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, DWORD 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, DWORD state, DWORD 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/Windows/CDbLink.cpp b/src/mir_core/src/Windows/CDbLink.cpp new file mode 100644 index 0000000000..4515e032f2 --- /dev/null +++ b/src/mir_core/src/Windows/CDbLink.cpp @@ -0,0 +1,92 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, BYTE type, DWORD 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, BYTE 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); +} + +DWORD 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(DWORD value) +{ + switch (m_type) { + case DBVT_BYTE: db_set_b(0, m_szModule, m_szSetting, (BYTE)value); break; + case DBVT_WORD: db_set_w(0, m_szModule, m_szSetting, (WORD)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 new file mode 100644 index 0000000000..5949057fda --- /dev/null +++ b/src/mir_core/src/Windows/CDlgBase.cpp @@ -0,0 +1,501 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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 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); +} + +void CDlgBase::EndModal(INT_PTR nResult) +{ + ::EndDialog(m_hwnd, nResult); +} + +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, BYTE type, DWORD 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(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; + WORD idCtrl = LOWORD(wParam); + WORD 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: + if (m_forceResizable || (GetWindowLongPtr(m_hwnd, GWL_STYLE) & WS_THICKFRAME)) + Utils_ResizeDialog(m_hwnd, m_pPlugin.getInst(), MAKEINTRESOURCEA(m_idDialog), GlobalDlgResizer); + 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); +} + +int CDlgBase::GlobalDlgResizer(HWND hwnd, LPARAM, UTILRESIZECONTROL *urc) +{ + CDlgBase *wnd = CDlgBase::Find(hwnd); + return (wnd == nullptr) ? 0 : wnd->Resizer(urc); +} + +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 new file mode 100644 index 0000000000..acc4773aff --- /dev/null +++ b/src/mir_core/src/Windows/CProgress.cpp @@ -0,0 +1,53 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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(WORD max, WORD min) +{ + SendMsg(PBM_SETRANGE, 0, MAKELPARAM(min, max)); +} + +void CCtrlProgress::SetPosition(WORD value) +{ + SendMsg(PBM_SETPOS, value, 0); +} + +void CCtrlProgress::SetStep(WORD value) +{ + SendMsg(PBM_SETSTEP, value, 0); +} + +WORD CCtrlProgress::Move(WORD 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 new file mode 100644 index 0000000000..24e406f999 --- /dev/null +++ b/src/mir_core/src/Windows/CSplitter.cpp @@ -0,0 +1,83 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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 new file mode 100644 index 0000000000..367c65249f --- /dev/null +++ b/src/mir_core/src/Windows/CTimer.cpp @@ -0,0 +1,90 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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, ¶m); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +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/cctrldate.cpp b/src/mir_core/src/Windows/cctrldate.cpp new file mode 100644 index 0000000000..809679aad3 --- /dev/null +++ b/src/mir_core/src/Windows/cctrldate.cpp @@ -0,0 +1,49 @@ +/* + +Object UI extensions +Copyright (c) 2008 Victor Pavlychko, George Hazan +Copyright (C) 2012-21 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/cmdline.cpp b/src/mir_core/src/Windows/cmdline.cpp new file mode 100644 index 0000000000..6aee0efe60 --- /dev/null +++ b/src/mir_core/src/Windows/cmdline.cpp @@ -0,0 +1,77 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 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 new file mode 100644 index 0000000000..464c29abc5 --- /dev/null +++ b/src/mir_core/src/Windows/colourpicker.cpp @@ -0,0 +1,105 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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/hyperlink.cpp b/src/mir_core/src/Windows/hyperlink.cpp new file mode 100644 index 0000000000..65ce93c54a --- /dev/null +++ b/src/mir_core/src/Windows/hyperlink.cpp @@ -0,0 +1,277 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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; + BYTE 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 new file mode 100644 index 0000000000..b187f7ba0c --- /dev/null +++ b/src/mir_core/src/Windows/icons.cpp @@ -0,0 +1,74 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 new file mode 100644 index 0000000000..f877a7ca5f --- /dev/null +++ b/src/mir_core/src/Windows/langpack.cpp @@ -0,0 +1,765 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 lMuuids(10, CompareMuuids); +static MUUID *pCurrentMuuid = nullptr; +static HANDLE hevChanged = nullptr; + +static BOOL bModuleInitialized = FALSE; + +struct LangPackEntry +{ + DWORD 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; + + BYTE *d = (BYTE*)&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++ = (BYTE)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? + DWORD 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 == *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; + DWORD 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 new file mode 100644 index 0000000000..809926f2b9 --- /dev/null +++ b/src/mir_core/src/Windows/locks.cpp @@ -0,0 +1,45 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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() +{ + ::EnterCriticalSection(&m_cs); +} + +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 new file mode 100644 index 0000000000..ba7ac7bf96 --- /dev/null +++ b/src/mir_core/src/Windows/miranda.cpp @@ -0,0 +1,149 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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" + +HWND hAPCWindow = nullptr; + +int InitPathUtils(void); +void RecalculateTime(void); + +void CheckLogs(); +void InitLogs(); +void UninitLogs(); + +void InitColourPicker(); +void InitHyperlink(); +void InitTimeZones(); +void InitWinver(); + +HINSTANCE g_hInst = nullptr; + +HCURSOR g_hCursorNS, g_hCursorWE; +HANDLE hThreadQueueEmpty; +DWORD mir_tls = 0; + +///////////////////////////////////////////////////////////////////////////////////////// + +static INT_PTR RestartMiranda(WPARAM wParam, LPARAM lParam) +{ + wchar_t mirandaPath[MAX_PATH], cmdLine[MAX_PATH]; + if (lParam) + wcsncpy_s(mirandaPath, (const wchar_t*)lParam, _TRUNCATE); + else + GetModuleFileName(nullptr, mirandaPath, _countof(mirandaPath)); + + if (wParam) { + VARSW profilename(L"%miranda_profilename%"); + mir_snwprintf(cmdLine, L"\"%s\" /restart:%d /profile=%s", mirandaPath, GetCurrentProcessId(), (wchar_t*)profilename); + } + else mir_snwprintf(cmdLine, L"\"%s\" /restart:%d", mirandaPath, GetCurrentProcessId()); + + CallService("CloseAction", 0, 0); + + PROCESS_INFORMATION pi; + STARTUPINFO startupInfo = { 0 }; + startupInfo.cb = sizeof(startupInfo); + CreateProcess(mirandaPath, cmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startupInfo, &pi); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// module init + +static LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_USER+1) { + PAPCFUNC pFunc = (PAPCFUNC)wParam; + pFunc((ULONG_PTR)lParam); + return 0; + } + + if (msg == WM_TIMER) + CheckLogs(); + + if (msg == WM_TIMECHANGE) + RecalculateTime(); + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +static void LoadCoreModule(void) +{ + INITCOMMONCONTROLSEX icce = {0}; + icce.dwSize = sizeof(icce); + icce.dwICC = ICC_WIN95_CLASSES | ICC_USEREX_CLASSES; + InitCommonControlsEx(&icce); + + hAPCWindow = CreateWindowEx(0, L"ComboLBox", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); + SetClassLongPtr(hAPCWindow, GCL_STYLE, GetClassLongPtr(hAPCWindow, GCL_STYLE) | CS_DROPSHADOW); + DestroyWindow(hAPCWindow); + + hAPCWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); + SetWindowLongPtr(hAPCWindow, GWLP_WNDPROC, (LONG_PTR)APCWndProc); + SetTimer(hAPCWindow, 1, 1000, nullptr); + hThreadQueueEmpty = CreateEvent(nullptr, TRUE, TRUE, nullptr); + + InitWinver(); + InitPathUtils(); + InitLogs(); + InitColourPicker(); + InitHyperlink(); + InitTimeZones(); + InitialiseModularEngine(); + + CreateServiceFunction(MS_SYSTEM_RESTART, RestartMiranda); + + pfnRtlGenRandom = (PGENRANDOM)GetProcAddress(GetModuleHandleA("advapi32"), "SystemFunction036"); +} + +MIR_CORE_DLL(void) UnloadCoreModule(void) +{ + DestroyWindow(hAPCWindow); + CloseHandle(hThreadQueueEmpty); + TlsFree(mir_tls); + + DestroyModularEngine(); + UninitLogs(); + UnloadLangPackModule(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// entry point + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID) +{ + if (fdwReason == DLL_PROCESS_ATTACH) { + g_hInst = hinstDLL; + mir_tls = TlsAlloc(); + LoadCoreModule(); + } + else if (fdwReason == DLL_THREAD_DETACH) { + HANDLE hEvent = TlsGetValue(mir_tls); + if (hEvent) + CloseHandle(hEvent); + } + return TRUE; +} diff --git a/src/mir_core/src/Windows/openurl.cpp b/src/mir_core/src/Windows/openurl.cpp new file mode 100644 index 0000000000..40dc3ca54a --- /dev/null +++ b/src/mir_core/src/Windows/openurl.cpp @@ -0,0 +1,76 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 + +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(OpenURLThread, new TOpenUrlInfo(mir_a2u(pszUrl), bOpenInNewWindow)); +} + +MIR_CORE_DLL(void) Utils_OpenUrlW(const wchar_t *pszUrl, bool bOpenInNewWindow) +{ + if (pszUrl) + mir_forkThread(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 new file mode 100644 index 0000000000..a09c44a1cb --- /dev/null +++ b/src/mir_core/src/Windows/path.cpp @@ -0,0 +1,246 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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; + + DWORD 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; + + DWORD 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 new file mode 100644 index 0000000000..a8a6be41e4 --- /dev/null +++ b/src/mir_core/src/Windows/resizer.cpp @@ -0,0 +1,151 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 +{ + DWORD helpID; + DWORD exStyle; + DWORD style; + short x, y, cx, cy; + DWORD id; +}; + +struct START_OF_DLGTEMPLATEEX +{ + WORD dlgVer; + WORD signature; + DWORD helpID; + DWORD exStyle; + DWORD style; + WORD 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) + 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 new file mode 100644 index 0000000000..99d5d355b2 --- /dev/null +++ b/src/mir_core/src/Windows/subclass.cpp @@ -0,0 +1,201 @@ +/* +Copyright (C) 2012-21 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 . +*/ + +#include "../stdafx.h" + +struct MSubclassData +{ + HWND m_hWnd; + + int m_iHooks; + WNDPROC *m_hooks; + WNDPROC m_origWndProc; + + ~MSubclassData() + { + free(m_hooks); + } +}; + +static LIST 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 new file mode 100644 index 0000000000..fdd9f5e85f --- /dev/null +++ b/src/mir_core/src/Windows/threads.cpp @@ -0,0 +1,400 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 + +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 (;;) { + DWORD 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 DWORD __cdecl sttDefaultFilter(DWORD, 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 +{ + DWORD dwThreadId; // valid if hThread isn't signalled + HANDLE hThread; + HINSTANCE hOwner; + void *pObject, *pEntryPoint; +}; + +static LIST 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; + + DWORD 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() +{ + DWORD 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 DWORD MS_VC_EXCEPTION=0x406D1388; + +#pragma pack(push,8) +typedef struct tagTHREADNAME_INFO +{ + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD 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 new file mode 100644 index 0000000000..8de5704d30 --- /dev/null +++ b/src/mir_core/src/Windows/timezones.cpp @@ -0,0 +1,592 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 DWORD (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 +{ + DWORD timestamp; // last time updated + MIM_TIMEZONE myTZ; // set to my own timezone +}; + +static TZ_INT_INFO myInfo; + +static OBJLIST g_timezones(55, NumericKeySortT); +static LIST g_timezonesBias(55, MIM_TIMEZONE::compareBias); + +// KB167296 +void UnixTimeToFileTime(mir_time ts, LPFILETIME pft) +{ + unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64; + pft->dwLowDateTime = (DWORD)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) { + DWORD 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, DWORD dwFlags) +{ + if (tszName == nullptr) + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ; + + 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, DWORD 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, DWORD 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, DWORD 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, DWORD 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, DWORD 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, DWORD 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, DWORD dwFlags) +{ + const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); + if (lstMsg == nullptr) + return 0; + + SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateW_LP(L"")); + + 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, DWORD 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(DWORD) TimeZone_ToLocal(DWORD 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, DWORD 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)) { + DWORD 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 new file mode 100644 index 0000000000..6549b28812 --- /dev/null +++ b/src/mir_core/src/Windows/windowlist.cpp @@ -0,0 +1,105 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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 +{ + TWindowList() : + OBJLIST(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*)¶m); + 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 new file mode 100644 index 0000000000..dbd729c896 --- /dev/null +++ b/src/mir_core/src/Windows/winutil.cpp @@ -0,0 +1,118 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 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; +} diff --git a/src/mir_core/src/Windows/winver.cpp b/src/mir_core/src/Windows/winver.cpp new file mode 100644 index 0000000000..d519d10478 --- /dev/null +++ b/src/mir_core/src/Windows/winver.cpp @@ -0,0 +1,372 @@ +/* +Copyright (C) 2012-21 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 . +*/ + +#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() +{ + DWORD 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)(DWORD, DWORD, DWORD, DWORD, 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/cctrldate.cpp b/src/mir_core/src/cctrldate.cpp deleted file mode 100644 index 415c1571b2..0000000000 --- a/src/mir_core/src/cctrldate.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - -Object UI extensions -Copyright (c) 2008 Victor Pavlychko, George Hazan -Copyright (C) 2012-21 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/cmdline.cpp b/src/mir_core/src/cmdline.cpp deleted file mode 100644 index 4dc74695c4..0000000000 --- a/src/mir_core/src/cmdline.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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 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/colourpicker.cpp b/src/mir_core/src/colourpicker.cpp deleted file mode 100644 index 181eadd894..0000000000 --- a/src/mir_core/src/colourpicker.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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/hyperlink.cpp b/src/mir_core/src/hyperlink.cpp deleted file mode 100644 index 12aa157522..0000000000 --- a/src/mir_core/src/hyperlink.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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; - BYTE 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/icons.cpp b/src/mir_core/src/icons.cpp deleted file mode 100644 index 12ff1f5caf..0000000000 --- a/src/mir_core/src/icons.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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/langpack.cpp b/src/mir_core/src/langpack.cpp deleted file mode 100644 index c16ebc878f..0000000000 --- a/src/mir_core/src/langpack.cpp +++ /dev/null @@ -1,765 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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 lMuuids(10, CompareMuuids); -static MUUID *pCurrentMuuid = nullptr; -static HANDLE hevChanged = nullptr; - -static BOOL bModuleInitialized = FALSE; - -struct LangPackEntry -{ - DWORD 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; - - BYTE *d = (BYTE*)&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++ = (BYTE)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? - DWORD 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 == *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; - DWORD 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/locks.cpp b/src/mir_core/src/locks.cpp deleted file mode 100644 index 2855974dea..0000000000 --- a/src/mir_core/src/locks.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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() -{ - ::EnterCriticalSection(&m_cs); -} - -void mir_cs::Unlock() -{ - ::LeaveCriticalSection(&m_cs); -} diff --git a/src/mir_core/src/miranda.cpp b/src/mir_core/src/miranda.cpp deleted file mode 100644 index 9a0915e53c..0000000000 --- a/src/mir_core/src/miranda.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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" - -HWND hAPCWindow = nullptr; - -int InitPathUtils(void); -void RecalculateTime(void); - -void CheckLogs(); -void InitLogs(); -void UninitLogs(); - -void InitColourPicker(); -void InitHyperlink(); -void InitTimeZones(); -void InitWinver(); - -HINSTANCE g_hInst = nullptr; - -HCURSOR g_hCursorNS, g_hCursorWE; -HANDLE hThreadQueueEmpty; -DWORD mir_tls = 0; - -///////////////////////////////////////////////////////////////////////////////////////// - -static INT_PTR RestartMiranda(WPARAM wParam, LPARAM lParam) -{ - wchar_t mirandaPath[MAX_PATH], cmdLine[MAX_PATH]; - if (lParam) - wcsncpy_s(mirandaPath, (const wchar_t*)lParam, _TRUNCATE); - else - GetModuleFileName(nullptr, mirandaPath, _countof(mirandaPath)); - - if (wParam) { - VARSW profilename(L"%miranda_profilename%"); - mir_snwprintf(cmdLine, L"\"%s\" /restart:%d /profile=%s", mirandaPath, GetCurrentProcessId(), (wchar_t*)profilename); - } - else mir_snwprintf(cmdLine, L"\"%s\" /restart:%d", mirandaPath, GetCurrentProcessId()); - - CallService("CloseAction", 0, 0); - - PROCESS_INFORMATION pi; - STARTUPINFO startupInfo = { 0 }; - startupInfo.cb = sizeof(startupInfo); - CreateProcess(mirandaPath, cmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startupInfo, &pi); - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// module init - -static LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (msg == WM_USER+1) { - PAPCFUNC pFunc = (PAPCFUNC)wParam; - pFunc((ULONG_PTR)lParam); - return 0; - } - - if (msg == WM_TIMER) - CheckLogs(); - - if (msg == WM_TIMECHANGE) - RecalculateTime(); - - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -static void LoadCoreModule(void) -{ - INITCOMMONCONTROLSEX icce = {0}; - icce.dwSize = sizeof(icce); - icce.dwICC = ICC_WIN95_CLASSES | ICC_USEREX_CLASSES; - InitCommonControlsEx(&icce); - - hAPCWindow = CreateWindowEx(0, L"ComboLBox", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); - SetClassLongPtr(hAPCWindow, GCL_STYLE, GetClassLongPtr(hAPCWindow, GCL_STYLE) | CS_DROPSHADOW); - DestroyWindow(hAPCWindow); - - hAPCWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); - SetWindowLongPtr(hAPCWindow, GWLP_WNDPROC, (LONG_PTR)APCWndProc); - SetTimer(hAPCWindow, 1, 1000, nullptr); - hThreadQueueEmpty = CreateEvent(nullptr, TRUE, TRUE, nullptr); - - InitWinver(); - InitPathUtils(); - InitLogs(); - InitColourPicker(); - InitHyperlink(); - InitTimeZones(); - InitialiseModularEngine(); - - CreateServiceFunction(MS_SYSTEM_RESTART, RestartMiranda); - - pfnRtlGenRandom = (PGENRANDOM)GetProcAddress(GetModuleHandleA("advapi32"), "SystemFunction036"); -} - -MIR_CORE_DLL(void) UnloadCoreModule(void) -{ - DestroyWindow(hAPCWindow); - CloseHandle(hThreadQueueEmpty); - TlsFree(mir_tls); - - DestroyModularEngine(); - UninitLogs(); - UnloadLangPackModule(); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// entry point - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID) -{ - if (fdwReason == DLL_PROCESS_ATTACH) { - g_hInst = hinstDLL; - mir_tls = TlsAlloc(); - LoadCoreModule(); - } - else if (fdwReason == DLL_THREAD_DETACH) { - HANDLE hEvent = TlsGetValue(mir_tls); - if (hEvent) - CloseHandle(hEvent); - } - return TRUE; -} diff --git a/src/mir_core/src/openurl.cpp b/src/mir_core/src/openurl.cpp deleted file mode 100644 index abc66f920b..0000000000 --- a/src/mir_core/src/openurl.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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 - -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(OpenURLThread, new TOpenUrlInfo(mir_a2u(pszUrl), bOpenInNewWindow)); -} - -MIR_CORE_DLL(void) Utils_OpenUrlW(const wchar_t *pszUrl, bool bOpenInNewWindow) -{ - if (pszUrl) - mir_forkThread(OpenURLThread, new TOpenUrlInfo(mir_wstrdup(pszUrl), bOpenInNewWindow)); -} diff --git a/src/mir_core/src/path.cpp b/src/mir_core/src/path.cpp deleted file mode 100644 index c26e712d06..0000000000 --- a/src/mir_core/src/path.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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; - - DWORD 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; - - DWORD 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/resizer.cpp b/src/mir_core/src/resizer.cpp deleted file mode 100644 index 01d65a7916..0000000000 --- a/src/mir_core/src/resizer.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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 -{ - DWORD helpID; - DWORD exStyle; - DWORD style; - short x, y, cx, cy; - DWORD id; -}; - -struct START_OF_DLGTEMPLATEEX -{ - WORD dlgVer; - WORD signature; - DWORD helpID; - DWORD exStyle; - DWORD style; - WORD 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) - 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/subclass.cpp b/src/mir_core/src/subclass.cpp deleted file mode 100644 index ecf53b470f..0000000000 --- a/src/mir_core/src/subclass.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* -Copyright (C) 2012-21 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 . -*/ - -#include "stdafx.h" - -struct MSubclassData -{ - HWND m_hWnd; - - int m_iHooks; - WNDPROC *m_hooks; - WNDPROC m_origWndProc; - - ~MSubclassData() - { - free(m_hooks); - } -}; - -static LIST 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/threads.cpp b/src/mir_core/src/threads.cpp deleted file mode 100644 index 917ecc5bb5..0000000000 --- a/src/mir_core/src/threads.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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 - -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 (;;) { - DWORD 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 DWORD __cdecl sttDefaultFilter(DWORD, 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 -{ - DWORD dwThreadId; // valid if hThread isn't signalled - HANDLE hThread; - HINSTANCE hOwner; - void *pObject, *pEntryPoint; -}; - -static LIST 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; - - DWORD 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() -{ - DWORD 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 DWORD MS_VC_EXCEPTION=0x406D1388; - -#pragma pack(push,8) -typedef struct tagTHREADNAME_INFO -{ - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD 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/timezones.cpp b/src/mir_core/src/timezones.cpp deleted file mode 100644 index 10d2ad6225..0000000000 --- a/src/mir_core/src/timezones.cpp +++ /dev/null @@ -1,592 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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 DWORD (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 -{ - DWORD timestamp; // last time updated - MIM_TIMEZONE myTZ; // set to my own timezone -}; - -static TZ_INT_INFO myInfo; - -static OBJLIST g_timezones(55, NumericKeySortT); -static LIST g_timezonesBias(55, MIM_TIMEZONE::compareBias); - -// KB167296 -void UnixTimeToFileTime(mir_time ts, LPFILETIME pft) -{ - unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64; - pft->dwLowDateTime = (DWORD)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) { - DWORD 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, DWORD dwFlags) -{ - if (tszName == nullptr) - return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ; - - 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, DWORD 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, DWORD 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, DWORD 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, DWORD 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, DWORD 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, DWORD 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, DWORD dwFlags) -{ - const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); - if (lstMsg == nullptr) - return 0; - - SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateW_LP(L"")); - - 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, DWORD 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(DWORD) TimeZone_ToLocal(DWORD 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, DWORD 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)) { - DWORD 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/windowlist.cpp b/src/mir_core/src/windowlist.cpp deleted file mode 100644 index 99631cb9a5..0000000000 --- a/src/mir_core/src/windowlist.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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 -{ - TWindowList() : - OBJLIST(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*)¶m); - 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/winutil.cpp b/src/mir_core/src/winutil.cpp deleted file mode 100644 index a09fa90016..0000000000 --- a/src/mir_core/src/winutil.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-21 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; -} diff --git a/src/mir_core/src/winver.cpp b/src/mir_core/src/winver.cpp deleted file mode 100644 index 28ced22337..0000000000 --- a/src/mir_core/src/winver.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* -Copyright (C) 2012-21 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 . -*/ - -#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() -{ - DWORD 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)(DWORD, DWORD, DWORD, DWORD, 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; -} -- cgit v1.2.3