summaryrefslogtreecommitdiff
path: root/src/mir_core
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2023-01-14 01:30:59 +0300
committerdartraiden <wowemuh@gmail.com>2023-01-14 01:30:59 +0300
commitde40f3be3f08487937525c2ef096dad665dda61d (patch)
treeeb1205f8dca7c30b561a2776f9527072bd92eaf1 /src/mir_core
parentdd743899a769120ba2321230afddd6e4f1271872 (diff)
Convert sources to CR+LF
Diffstat (limited to 'src/mir_core')
-rw-r--r--src/mir_core/src/Windows/CCtrlTreeOpts.cpp418
-rw-r--r--src/mir_core/src/Windows/CCtrlTreeView.cpp1600
-rw-r--r--src/mir_core/src/Windows/miranda.cpp812
-rw-r--r--src/mir_core/src/db.cpp1152
4 files changed, 1991 insertions, 1991 deletions
diff --git a/src/mir_core/src/Windows/CCtrlTreeOpts.cpp b/src/mir_core/src/Windows/CCtrlTreeOpts.cpp
index 7935283285..0366201369 100644
--- a/src/mir_core/src/Windows/CCtrlTreeOpts.cpp
+++ b/src/mir_core/src/Windows/CCtrlTreeOpts.cpp
@@ -1,209 +1,209 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-23 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-enum { IMG_SHIT, IMG_GRPOPEN, IMG_GRPCLOSED };
-
-CCtrlTreeOpts::CCtrlTreeOpts(CDlgBase* dlg, int ctrlId):
- CCtrlTreeView(dlg, ctrlId),
- m_options(5)
-{
- m_bCheckBox = true;
-}
-
-CCtrlTreeOpts::~CCtrlTreeOpts()
-{
-}
-
-void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, CMOption<bool> &option)
-{
- auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::CMOPTION);
- p->m_option = &option;
- m_options.insert(p, m_options.getCount());
-}
-
-void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, bool &option)
-{
- auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::BOOL);
- p->m_pBool = &option;
- m_options.insert(p, m_options.getCount());
-}
-
-void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, uint32_t &option, uint32_t mask)
-{
- auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::MASK);
- p->m_pDword = &option;
- p->m_mask = mask;
- m_options.insert(p, m_options.getCount());
-}
-
-BOOL CCtrlTreeOpts::OnNotify(int idCtrl, NMHDR *pnmh)
-{
- switch (pnmh->code) {
- case TVN_KEYDOWN:
- {
- LPNMTVKEYDOWN lpnmtvkd = (LPNMTVKEYDOWN)pnmh;
- HTREEITEM hti;
- if ((lpnmtvkd->wVKey == VK_SPACE) && (hti = GetSelection()))
- ProcessItemClick(hti);
- }
- break;
-
- case NM_CLICK:
- TVHITTESTINFO htti;
- htti.pt.x = (short)LOWORD(GetMessagePos());
- htti.pt.y = (short)HIWORD(GetMessagePos());
- ScreenToClient(pnmh->hwndFrom, &htti.pt);
- if (HitTest(&htti))
- if (htti.flags & TVHT_ONITEMICON)
- ProcessItemClick(htti.hItem);
- break;
-
- case TVN_ITEMEXPANDED:
- LPNMTREEVIEW lpnmtv = (LPNMTREEVIEW)pnmh;
- TVITEM tvi;
- tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
- tvi.hItem = lpnmtv->itemNew.hItem;
- tvi.iImage = tvi.iSelectedImage = (lpnmtv->itemNew.state & TVIS_EXPANDED) ? IMG_GRPOPEN : IMG_GRPCLOSED;
- SendMessage(pnmh->hwndFrom, TVM_SETITEM, 0, (LPARAM)&tvi);
- break;
- }
-
- return CSuper::OnNotify(idCtrl, pnmh);
-}
-
-void CCtrlTreeOpts::OnInit()
-{
- CSuper::OnInit();
-
- SelectItem(nullptr);
- DeleteAllItems();
-
- HIMAGELIST hImgLst = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR | ILC_COLOR32 | ILC_MASK, 5, 1);
- ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_BLANK);
- 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_EXPANDED | TVIS_BOLD | INDEXTOSTATEIMAGEMASK(3);
- tvis.item.stateMask = TVIS_EXPANDED | TVIS_BOLD | TVIS_STATEIMAGEMASK;
- tvis.item.iImage = tvis.item.iSelectedImage = IMG_GRPOPEN;
- hSection = InsertItem(&tvis);
- }
-
- bool bValue;
- switch (it->m_type) {
- case COptionsItem::CMOPTION:
- bValue = *it->m_option;
- break;
- case COptionsItem::BOOL:
- bValue = *it->m_pBool;
- break;
- case COptionsItem::MASK:
- bValue = (*it->m_pDword & it->m_mask) != 0;
- break;
- default:
- continue;
- }
-
- TVINSERTSTRUCT tvis = {};
- tvis.hParent = hSection;
- tvis.hInsertAfter = TVI_LAST;
- tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE;
- tvis.item.pszText = (LPWSTR)it->m_pwszName;
- tvis.item.lParam = m_options.indexOf(&it);
- tvis.item.iImage = -1;
- tvis.item.state = INDEXTOSTATEIMAGEMASK(bValue ? 2 : 1);
- tvis.item.stateMask = TVIS_STATEIMAGEMASK;
- 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;
- tvi.mask = TVIF_STATE;
- GetItem(it->m_hItem, &tvi);
-
- bool bValue = (tvi.state >> 12) == 2;
- switch (it->m_type) {
- case COptionsItem::CMOPTION:
- *it->m_option = bValue;
- break;
- case COptionsItem::BOOL:
- *it->m_pBool = bValue;
- break;
- case COptionsItem::MASK:
- if (bValue)
- *it->m_pDword |= it->m_mask;
- else
- *it->m_pDword &= ~it->m_mask;
- break;
- }
- }
- return true;
-}
-
-void CCtrlTreeOpts::ProcessItemClick(HTREEITEM hti)
-{
- TVITEMEX tvi;
- tvi.mask = TVIF_IMAGE;
- 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;
-
- }
-
- SetItem(&tvi);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+enum { IMG_SHIT, IMG_GRPOPEN, IMG_GRPCLOSED };
+
+CCtrlTreeOpts::CCtrlTreeOpts(CDlgBase* dlg, int ctrlId):
+ CCtrlTreeView(dlg, ctrlId),
+ m_options(5)
+{
+ m_bCheckBox = true;
+}
+
+CCtrlTreeOpts::~CCtrlTreeOpts()
+{
+}
+
+void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, CMOption<bool> &option)
+{
+ auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::CMOPTION);
+ p->m_option = &option;
+ m_options.insert(p, m_options.getCount());
+}
+
+void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, bool &option)
+{
+ auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::BOOL);
+ p->m_pBool = &option;
+ m_options.insert(p, m_options.getCount());
+}
+
+void CCtrlTreeOpts::AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, uint32_t &option, uint32_t mask)
+{
+ auto *p = new COptionsItem(pwszSection, pwszName, COptionsItem::MASK);
+ p->m_pDword = &option;
+ p->m_mask = mask;
+ m_options.insert(p, m_options.getCount());
+}
+
+BOOL CCtrlTreeOpts::OnNotify(int idCtrl, NMHDR *pnmh)
+{
+ switch (pnmh->code) {
+ case TVN_KEYDOWN:
+ {
+ LPNMTVKEYDOWN lpnmtvkd = (LPNMTVKEYDOWN)pnmh;
+ HTREEITEM hti;
+ if ((lpnmtvkd->wVKey == VK_SPACE) && (hti = GetSelection()))
+ ProcessItemClick(hti);
+ }
+ break;
+
+ case NM_CLICK:
+ TVHITTESTINFO htti;
+ htti.pt.x = (short)LOWORD(GetMessagePos());
+ htti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(pnmh->hwndFrom, &htti.pt);
+ if (HitTest(&htti))
+ if (htti.flags & TVHT_ONITEMICON)
+ ProcessItemClick(htti.hItem);
+ break;
+
+ case TVN_ITEMEXPANDED:
+ LPNMTREEVIEW lpnmtv = (LPNMTREEVIEW)pnmh;
+ TVITEM tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvi.hItem = lpnmtv->itemNew.hItem;
+ tvi.iImage = tvi.iSelectedImage = (lpnmtv->itemNew.state & TVIS_EXPANDED) ? IMG_GRPOPEN : IMG_GRPCLOSED;
+ SendMessage(pnmh->hwndFrom, TVM_SETITEM, 0, (LPARAM)&tvi);
+ break;
+ }
+
+ return CSuper::OnNotify(idCtrl, pnmh);
+}
+
+void CCtrlTreeOpts::OnInit()
+{
+ CSuper::OnInit();
+
+ SelectItem(nullptr);
+ DeleteAllItems();
+
+ HIMAGELIST hImgLst = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR | ILC_COLOR32 | ILC_MASK, 5, 1);
+ ImageList_AddSkinIcon(hImgLst, SKINICON_OTHER_BLANK);
+ 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_EXPANDED | TVIS_BOLD | INDEXTOSTATEIMAGEMASK(3);
+ tvis.item.stateMask = TVIS_EXPANDED | TVIS_BOLD | TVIS_STATEIMAGEMASK;
+ tvis.item.iImage = tvis.item.iSelectedImage = IMG_GRPOPEN;
+ hSection = InsertItem(&tvis);
+ }
+
+ bool bValue;
+ switch (it->m_type) {
+ case COptionsItem::CMOPTION:
+ bValue = *it->m_option;
+ break;
+ case COptionsItem::BOOL:
+ bValue = *it->m_pBool;
+ break;
+ case COptionsItem::MASK:
+ bValue = (*it->m_pDword & it->m_mask) != 0;
+ break;
+ default:
+ continue;
+ }
+
+ TVINSERTSTRUCT tvis = {};
+ tvis.hParent = hSection;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE;
+ tvis.item.pszText = (LPWSTR)it->m_pwszName;
+ tvis.item.lParam = m_options.indexOf(&it);
+ tvis.item.iImage = -1;
+ tvis.item.state = INDEXTOSTATEIMAGEMASK(bValue ? 2 : 1);
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ 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;
+ tvi.mask = TVIF_STATE;
+ GetItem(it->m_hItem, &tvi);
+
+ bool bValue = (tvi.state >> 12) == 2;
+ switch (it->m_type) {
+ case COptionsItem::CMOPTION:
+ *it->m_option = bValue;
+ break;
+ case COptionsItem::BOOL:
+ *it->m_pBool = bValue;
+ break;
+ case COptionsItem::MASK:
+ if (bValue)
+ *it->m_pDword |= it->m_mask;
+ else
+ *it->m_pDword &= ~it->m_mask;
+ break;
+ }
+ }
+ return true;
+}
+
+void CCtrlTreeOpts::ProcessItemClick(HTREEITEM hti)
+{
+ TVITEMEX tvi;
+ tvi.mask = TVIF_IMAGE;
+ 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;
+
+ }
+
+ SetItem(&tvi);
+}
diff --git a/src/mir_core/src/Windows/CCtrlTreeView.cpp b/src/mir_core/src/Windows/CCtrlTreeView.cpp
index 178b6b730e..92ad166f91 100644
--- a/src/mir_core/src/Windows/CCtrlTreeView.cpp
+++ b/src/mir_core/src/Windows/CCtrlTreeView.cpp
@@ -1,800 +1,800 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-23 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-int ImageList_AddIcon_IconLibLoaded(HIMAGELIST hIml, int iconId)
-{
- HICON hIcon = Skin_LoadIcon(iconId);
- int res = ImageList_AddIcon(hIml, hIcon);
- IcoLib_ReleaseIcon(hIcon);
- return res;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlTreeView
-
-CCtrlTreeView::CCtrlTreeView(CDlgBase *dlg, int ctrlId) :
- CCtrlBase(dlg, ctrlId),
- m_dwFlags(0),
- m_hDragItem(nullptr)
-{}
-
-void CCtrlTreeView::SetFlags(uint32_t dwFlags)
-{
- if (dwFlags & MTREE_CHECKBOX)
- m_bCheckBox = true;
-
- if (dwFlags & MTREE_MULTISELECT)
- m_bMultiSelect = true;
-
- if (dwFlags & MTREE_DND) {
- m_bDndEnabled = true;
- m_bDragging = false;
- m_hDragItem = nullptr;
- }
-}
-
-void CCtrlTreeView::OnInit()
-{
- CSuper::OnInit();
-
- Subclass();
-
- if (m_bCheckBox)
- SetWindowLongW(m_hwnd, GWL_STYLE, TVS_CHECKBOXES | GetWindowLongW(m_hwnd, GWL_STYLE));
-}
-
-HTREEITEM CCtrlTreeView::MoveItemAbove(HTREEITEM hItem, HTREEITEM hInsertAfter, HTREEITEM hParent)
-{
- if (hItem == nullptr || hInsertAfter == nullptr)
- return nullptr;
-
- if (hItem == hInsertAfter)
- return hItem;
-
- wchar_t name[128];
- TVINSERTSTRUCT tvis = {};
- tvis.itemex.mask = (UINT)-1;
- tvis.itemex.pszText = name;
- tvis.itemex.cchTextMax = _countof(name);
- tvis.itemex.hItem = hItem;
- if (!GetItem(&tvis.itemex))
- return nullptr;
-
- OBJLIST<TVINSERTSTRUCT> arChildren(1);
- for (HTREEITEM p = GetChild(hItem); p; p = GetNextSibling(p)) {
- wchar_t buf[128];
- TVINSERTSTRUCT tvis2 = {};
- tvis2.itemex.mask = (UINT)-1;
- tvis2.itemex.pszText = buf;
- tvis2.itemex.cchTextMax = _countof(buf);
- tvis2.itemex.hItem = p;
- if (GetItem(&tvis2.itemex)) {
- tvis2.itemex.pszText = mir_wstrdup(tvis2.itemex.pszText);
- arChildren.insert(new TVINSERTSTRUCT(tvis2));
-
- tvis2.itemex.lParam = 0;
- SetItem(&tvis2.itemex);
- }
- }
-
- // the pointed lParam will be freed inside TVN_DELETEITEM
- // so lets substitute it with 0
- LPARAM saveOldData = tvis.itemex.lParam;
- tvis.itemex.lParam = 0;
- SetItem(&tvis.itemex);
-
- // now current item contain lParam = 0 we can delete it. the memory will be kept.
- DeleteItem(hItem);
-
- for (auto &it : arChildren)
- DeleteItem(it->itemex.hItem);
-
- tvis.itemex.stateMask = tvis.itemex.state;
- tvis.itemex.lParam = saveOldData;
- tvis.hParent = hParent;
- tvis.hInsertAfter = hInsertAfter;
- auto hNewItem = InsertItem(&tvis);
-
- hInsertAfter = nullptr;
- for (auto &it : arChildren) {
- it->hParent = hNewItem;
- it->hInsertAfter = hInsertAfter;
- hInsertAfter = InsertItem(it);
-
- mir_free(it->itemex.pszText);
- }
-
- return hNewItem;
-}
-
-LRESULT CCtrlTreeView::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- TVHITTESTINFO hti;
-
- switch (msg) {
- case WM_MOUSEMOVE:
- if (m_bDragging) {
- hti.pt.x = (short)LOWORD(lParam);
- hti.pt.y = (short)HIWORD(lParam);
- HitTest(&hti);
- if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) {
- HTREEITEM it = hti.hItem;
- hti.pt.y -= GetItemHeight() / 2;
- HitTest(&hti);
- if (!(hti.flags & TVHT_ABOVE))
- SetInsertMark(hti.hItem, 1);
- else
- SetInsertMark(it, 0);
- }
- else {
- if (hti.flags & TVHT_ABOVE) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0);
- if (hti.flags & TVHT_BELOW) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0);
- SetInsertMark(nullptr, 0);
- }
- }
- break;
-
- case WM_LBUTTONUP:
- if (m_bDragging) {
- SetInsertMark(nullptr, 0);
- m_bDragging = false;
- ReleaseCapture();
-
- hti.pt.x = (short)LOWORD(lParam);
- hti.pt.y = (short)HIWORD(lParam) - GetItemHeight() / 2;
- HitTest(&hti);
- if (m_hDragItem == hti.hItem)
- break;
-
- if (hti.flags & TVHT_ABOVE)
- hti.hItem = TVI_FIRST;
- else if (hti.flags & TVHT_BELOW)
- hti.hItem = TVI_LAST;
-
- HTREEITEM insertAfter = hti.hItem, hParent;
- if (insertAfter != TVI_FIRST) {
- hParent = GetParent(insertAfter);
- if (GetChild(insertAfter) != nullptr) {
- hParent = insertAfter;
- insertAfter = TVI_FIRST;
- }
- }
- else hParent = nullptr;
-
- HTREEITEM FirstItem = nullptr;
- if (m_bMultiSelect) {
- LIST<_TREEITEM> arItems(10);
- GetSelected(arItems);
-
- // Proceed moving
- for (auto &it : arItems) {
- if (!insertAfter)
- break;
- if (GetParent(it) != hParent) // prevent subitems from being inserted at the same level
- continue;
-
- insertAfter = MoveItemAbove(it, insertAfter, hParent);
- if (it == arItems[0])
- FirstItem = insertAfter;
- }
- }
- else FirstItem = MoveItemAbove(m_hDragItem, insertAfter, hParent);
- if (FirstItem)
- SelectItem(FirstItem);
-
- NotifyChange();
- }
- break;
-
- case WM_LBUTTONDOWN:
- if (!m_bMultiSelect)
- break;
-
- hti.pt.x = (short)LOWORD(lParam);
- hti.pt.y = (short)HIWORD(lParam);
- if (!TreeView_HitTest(m_hwnd, &hti)) {
- UnselectAll();
- break;
- }
-
- if (!m_bDndEnabled)
- if (!(wParam & (MK_CONTROL | MK_SHIFT)) || !(hti.flags & (TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMRIGHT))) {
- UnselectAll();
- TreeView_SelectItem(m_hwnd, hti.hItem);
- break;
- }
-
- if (wParam & MK_CONTROL) {
- LIST<_TREEITEM> selected(1);
- GetSelected(selected);
-
- // Check if have to deselect it
- for (int i = 0; i < selected.getCount(); i++) {
- if (selected[i] == hti.hItem) {
- // Deselect it
- UnselectAll();
- selected.remove(i);
-
- if (i > 0)
- hti.hItem = selected[0];
- else if (i < selected.getCount())
- hti.hItem = selected[i];
- else
- hti.hItem = nullptr;
- break;
- }
- }
-
- TreeView_SelectItem(m_hwnd, hti.hItem);
- Select(selected);
- }
- else if (wParam & MK_SHIFT) {
- HTREEITEM hItem = TreeView_GetSelection(m_hwnd);
- if (hItem == nullptr)
- break;
-
- LIST<_TREEITEM> selected(1);
- GetSelected(selected);
-
- TreeView_SelectItem(m_hwnd, hti.hItem);
- Select(selected);
- SelectRange(hItem, hti.hItem);
- }
- break;
- }
-
- return CSuper::CustomWndProc(msg, wParam, lParam);
-}
-
-BOOL CCtrlTreeView::OnNotify(int, NMHDR *pnmh)
-{
- TEventInfo evt = { this, pnmh };
-
- switch (pnmh->code) {
- case NM_RCLICK: OnRightClick(&evt); return TRUE;
- case NM_CUSTOMDRAW: OnCustomDraw(&evt); return TRUE;
- case TVN_BEGINLABELEDIT: OnBeginLabelEdit(&evt); return TRUE;
- case TVN_BEGINRDRAG: OnBeginRDrag(&evt); return TRUE;
- case TVN_DELETEITEM: OnDeleteItem(&evt); return TRUE;
- case TVN_ENDLABELEDIT: OnEndLabelEdit(&evt); return TRUE;
- case TVN_GETDISPINFO: OnGetDispInfo(&evt); return TRUE;
- case TVN_GETINFOTIP: OnGetInfoTip(&evt); return TRUE;
- case TVN_ITEMEXPANDED: OnItemExpanded(&evt); return TRUE;
- case TVN_ITEMEXPANDING: OnItemExpanding(&evt); return TRUE;
- case TVN_SELCHANGED: OnSelChanged(&evt); return TRUE;
- case TVN_SELCHANGING: OnSelChanging(&evt); return TRUE;
- case TVN_SETDISPINFO: OnSetDispInfo(&evt); return TRUE;
- case TVN_SINGLEEXPAND: OnSingleExpand(&evt); return TRUE;
-
- case TVN_BEGINDRAG:
- OnBeginDrag(&evt);
-
- // user-defined can clear the event code to disable dragging
- if (m_bDndEnabled && pnmh->code) {
- ::SetCapture(m_hwnd);
- m_bDragging = true;
- m_hDragItem = evt.nmtv->itemNew.hItem;
- SelectItem(m_hDragItem);
- }
- return TRUE;
-
- case TVN_KEYDOWN:
- if (evt.nmtvkey->wVKey == VK_SPACE) {
- evt.hItem = GetSelection();
- 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 (hti.flags & TVHT_ONITEMSTATEICON) {
- SelectItem(hti.hItem);
-
- evt.hItem = hti.hItem;
- OnItemChanged(&evt);
- NotifyChange();
- }
- }
- }
-
- return FALSE;
-}
-
-void CCtrlTreeView::InvertCheck(HTREEITEM hItem)
-{
- TVITEMEX tvi;
- tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATEEX;
- tvi.hItem = hItem;
- if (!GetItem(&tvi))
- return;
-
- if (IsWinVerVistaPlus() && (tvi.uStateEx & TVIS_EX_DISABLED))
- return;
-
- tvi.iImage = tvi.iSelectedImage = !tvi.iImage;
- SetItem(&tvi);
-
- SelectItem(hItem);
-}
-
-void CCtrlTreeView::TranslateItem(HTREEITEM hItem)
-{
- TVITEMEX tvi;
- wchar_t buf[128];
- GetItem(hItem, &tvi, buf, _countof(buf));
- tvi.pszText = TranslateW_LP(tvi.pszText);
- SetItem(&tvi);
-}
-
-void CCtrlTreeView::TranslateTree()
-{
- HTREEITEM hItem = GetRoot();
- while (hItem) {
- TranslateItem(hItem);
-
- HTREEITEM hItemTmp = nullptr;
- if (hItemTmp = GetChild(hItem))
- hItem = hItemTmp;
- else if (hItemTmp = GetNextSibling(hItem))
- hItem = hItemTmp;
- else {
- while (true) {
- if (!(hItem = GetParent(hItem)))
- break;
- if (hItemTmp = GetNextSibling(hItem)) {
- hItem = hItemTmp;
- break;
- }
- }
- }
- }
-}
-
-HTREEITEM CCtrlTreeView::FindNamedItem(HTREEITEM hItem, const wchar_t *name)
-{
- TVITEMEX tvi = { 0 };
- wchar_t str[MAX_PATH];
-
- if (hItem)
- tvi.hItem = GetChild(hItem);
- else
- tvi.hItem = GetRoot();
-
- if (!name)
- return tvi.hItem;
-
- tvi.mask = TVIF_TEXT;
- tvi.pszText = str;
- tvi.cchTextMax = _countof(str);
-
- while (tvi.hItem) {
- GetItem(&tvi);
-
- if (!mir_wstrcmp(tvi.pszText, name))
- return tvi.hItem;
-
- tvi.hItem = GetNextSibling(tvi.hItem);
- }
- return nullptr;
-}
-
-void CCtrlTreeView::GetItem(HTREEITEM hItem, TVITEMEX *tvi) const
-{
- memset(tvi, 0, sizeof(*tvi));
- tvi->mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_INTEGRAL | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE;
- tvi->hItem = hItem;
- GetItem(tvi);
-}
-
-void CCtrlTreeView::GetItem(HTREEITEM hItem, TVITEMEX *tvi, wchar_t *szText, int iTextLength) const
-{
- memset(tvi, 0, sizeof(*tvi));
- tvi->mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_INTEGRAL | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE | TVIF_TEXT;
- tvi->hItem = hItem;
- tvi->pszText = szText;
- tvi->cchTextMax = iTextLength;
- GetItem(tvi);
-}
-
-bool CCtrlTreeView::IsSelected(HTREEITEM hItem)
-{
- return (TVIS_SELECTED & TreeView_GetItemState(m_hwnd, hItem, TVIS_SELECTED)) == TVIS_SELECTED;
-}
-
-void CCtrlTreeView::Select(HTREEITEM hItem)
-{
- TreeView_SetItemState(m_hwnd, hItem, TVIS_SELECTED, TVIS_SELECTED);
-}
-
-void CCtrlTreeView::Unselect(HTREEITEM hItem)
-{
- TreeView_SetItemState(m_hwnd, hItem, 0, TVIS_SELECTED);
-}
-
-void CCtrlTreeView::DropHilite(HTREEITEM hItem)
-{
- TreeView_SetItemState(m_hwnd, hItem, TVIS_DROPHILITED, TVIS_DROPHILITED);
-}
-
-void CCtrlTreeView::DropUnhilite(HTREEITEM hItem)
-{
- TreeView_SetItemState(m_hwnd, hItem, 0, TVIS_DROPHILITED);
-}
-
-void CCtrlTreeView::SelectAll()
-{
- TreeView_SelectItem(m_hwnd, nullptr);
-
- HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
- while (hItem) {
- Select(hItem);
- hItem = TreeView_GetNextSibling(m_hwnd, hItem);
- }
-}
-
-void CCtrlTreeView::UnselectAll()
-{
- TreeView_SelectItem(m_hwnd, nullptr);
-
- HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
- while (hItem) {
- Unselect(hItem);
- hItem = TreeView_GetNextSibling(m_hwnd, hItem);
- }
-}
-
-void CCtrlTreeView::SelectRange(HTREEITEM hStart, HTREEITEM hEnd)
-{
- int start = 0, end = 0, i = 0;
- HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
- while (hItem) {
- if (hItem == hStart)
- start = i;
- if (hItem == hEnd)
- end = i;
-
- i++;
- hItem = TreeView_GetNextSibling(m_hwnd, hItem);
- }
-
- if (end < start) {
- int tmp = start;
- start = end;
- end = tmp;
- }
-
- i = 0;
- hItem = TreeView_GetRoot(m_hwnd);
- while (hItem) {
- if (i >= start)
- Select(hItem);
- if (i == end)
- break;
-
- i++;
- hItem = TreeView_GetNextSibling(m_hwnd, hItem);
- }
-}
-
-int CCtrlTreeView::GetNumSelected()
-{
- int ret = 0;
- for (HTREEITEM hItem = TreeView_GetRoot(m_hwnd); hItem; hItem = TreeView_GetNextSibling(m_hwnd, hItem))
- if (IsSelected(hItem))
- ret++;
-
- return ret;
-}
-
-void CCtrlTreeView::GetSelected(LIST<_TREEITEM> &selected)
-{
- HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
- while (hItem) {
- if (IsSelected(hItem))
- selected.insert(hItem);
- hItem = TreeView_GetNextSibling(m_hwnd, hItem);
- }
-}
-
-void CCtrlTreeView::Select(LIST<_TREEITEM> &selected)
-{
- for (auto &it : selected)
- if (it != nullptr)
- Select(it);
-}
-
-void CCtrlTreeView::GetCaretPos(CContextMenuPos &pos) const
-{
- pos.pCtrl = this;
-
- // position is empty, let's fill it using selection
- if (pos.pt.x == 0 && pos.pt.y == 0) {
- HTREEITEM hItem = GetSelection();
- if (hItem != nullptr) {
- pos.pCtrl = this;
- pos.hItem = hItem;
-
- RECT rc;
- GetItemRect(hItem, &rc, TRUE);
- pos.pt.x = rc.left + 8;
- pos.pt.y = rc.top + 8;
- ClientToScreen(m_hwnd, &pos.pt);
- return;
- }
- }
- // position is present, let's calculate current item
- else {
- TVHITTESTINFO hti;
- hti.pt = pos.pt;
- ScreenToClient(m_hwnd, &hti.pt);
- if (HitTest(&hti) && (hti.flags & TVHT_ONITEM)) {
- pos.hItem = hti.hItem;
- return;
- }
- }
-
- CSuper::GetCaretPos(pos);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-HIMAGELIST CCtrlTreeView::CreateDragImage(HTREEITEM hItem)
-{ return TreeView_CreateDragImage(m_hwnd, hItem);
-}
-
-void CCtrlTreeView::DeleteAllItems()
-{ TreeView_DeleteAllItems(m_hwnd);
-}
-
-void CCtrlTreeView::DeleteItem(HTREEITEM hItem)
-{ TreeView_DeleteItem(m_hwnd, hItem);
-}
-
-HWND CCtrlTreeView::EditLabel(HTREEITEM hItem)
-{ return TreeView_EditLabel(m_hwnd, hItem);
-}
-
-void CCtrlTreeView::EndEditLabelNow(BOOL cancel)
-{ TreeView_EndEditLabelNow(m_hwnd, cancel);
-}
-
-void CCtrlTreeView::EnsureVisible(HTREEITEM hItem)
-{ TreeView_EnsureVisible(m_hwnd, hItem);
-}
-
-void CCtrlTreeView::Expand(HTREEITEM hItem, uint32_t flag)
-{ TreeView_Expand(m_hwnd, hItem, flag);
-}
-
-COLORREF CCtrlTreeView::GetBkColor() const
-{ return TreeView_GetBkColor(m_hwnd);
-}
-
-uint32_t CCtrlTreeView::GetCheckState(HTREEITEM hItem) const
-{ return TreeView_GetCheckState(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetChild(HTREEITEM hItem) const
-{ return TreeView_GetChild(m_hwnd, hItem);
-}
-
-int CCtrlTreeView::GetCount() const
-{ return TreeView_GetCount(m_hwnd);
-}
-
-HTREEITEM CCtrlTreeView::GetDropHilight() const
-{ return TreeView_GetDropHilight(m_hwnd);
-}
-
-HWND CCtrlTreeView::GetEditControl() const
-{ return TreeView_GetEditControl(m_hwnd);
-}
-
-HTREEITEM CCtrlTreeView::GetFirstVisible() const
-{ return TreeView_GetFirstVisible(m_hwnd);
-}
-
-HIMAGELIST CCtrlTreeView::GetImageList(int iImage) const
-{ return TreeView_GetImageList(m_hwnd, iImage);
-}
-
-int CCtrlTreeView::GetIndent() const
-{ return TreeView_GetIndent(m_hwnd);
-}
-
-COLORREF CCtrlTreeView::GetInsertMarkColor() const
-{ return TreeView_GetInsertMarkColor(m_hwnd);
-}
-
-bool CCtrlTreeView::GetItem(TVITEMEX *tvi) const
-{ return TreeView_GetItem(m_hwnd, tvi) == TRUE;
-}
-
-int CCtrlTreeView::GetItemHeight() const
-{ return TreeView_GetItemHeight(m_hwnd);
-}
-
-void CCtrlTreeView::GetItemRect(HTREEITEM hItem, RECT *rcItem, BOOL fItemRect) const
-{ TreeView_GetItemRect(m_hwnd, hItem, rcItem, fItemRect);
-}
-
-uint32_t CCtrlTreeView::GetItemState(HTREEITEM hItem, uint32_t stateMask) const
-{ return TreeView_GetItemState(m_hwnd, hItem, stateMask);
-}
-
-HTREEITEM CCtrlTreeView::GetLastVisible() const
-{ return TreeView_GetLastVisible(m_hwnd);
-}
-
-COLORREF CCtrlTreeView::GetLineColor() const
-{ return TreeView_GetLineColor(m_hwnd);
-}
-
-HTREEITEM CCtrlTreeView::GetNextItem(HTREEITEM hItem, uint32_t flag) const
-{ return TreeView_GetNextItem(m_hwnd, hItem, flag);
-}
-
-HTREEITEM CCtrlTreeView::GetNextSibling(HTREEITEM hItem) const
-{ return TreeView_GetNextSibling(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetNextVisible(HTREEITEM hItem) const
-{ return TreeView_GetNextVisible(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetParent(HTREEITEM hItem) const
-{ return TreeView_GetParent(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetPrevSibling(HTREEITEM hItem) const
-{ return TreeView_GetPrevSibling(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetPrevVisible(HTREEITEM hItem) const
-{ return TreeView_GetPrevVisible(m_hwnd, hItem);
-}
-
-HTREEITEM CCtrlTreeView::GetRoot() const
-{ return TreeView_GetRoot(m_hwnd);
-}
-
-uint32_t CCtrlTreeView::GetScrollTime() const
-{ return TreeView_GetScrollTime(m_hwnd);
-}
-
-HTREEITEM CCtrlTreeView::GetSelection() const
-{ return TreeView_GetSelection(m_hwnd);
-}
-
-COLORREF CCtrlTreeView::GetTextColor() const
-{ return TreeView_GetTextColor(m_hwnd);
-}
-
-HWND CCtrlTreeView::GetToolTips() const
-{ return TreeView_GetToolTips(m_hwnd);
-}
-
-BOOL CCtrlTreeView::GetUnicodeFormat() const
-{ return TreeView_GetUnicodeFormat(m_hwnd);
-}
-
-unsigned CCtrlTreeView::GetVisibleCount() const
-{ return TreeView_GetVisibleCount(m_hwnd);
-}
-
-HTREEITEM CCtrlTreeView::HitTest(TVHITTESTINFO *hti) const
-{ return TreeView_HitTest(m_hwnd, hti);
-}
-
-HTREEITEM CCtrlTreeView::InsertItem(TVINSERTSTRUCT *tvis)
-{ return TreeView_InsertItem(m_hwnd, tvis);
-}
-
-void CCtrlTreeView::Select(HTREEITEM hItem, uint32_t flag)
-{ TreeView_Select(m_hwnd, hItem, flag);
-}
-
-void CCtrlTreeView::SelectDropTarget(HTREEITEM hItem)
-{ TreeView_SelectDropTarget(m_hwnd, hItem);
-}
-
-void CCtrlTreeView::SelectItem(HTREEITEM hItem)
-{ TreeView_SelectItem(m_hwnd, hItem);
-}
-
-void CCtrlTreeView::SelectSetFirstVisible(HTREEITEM hItem)
-{ TreeView_SelectSetFirstVisible(m_hwnd, hItem);
-}
-
-COLORREF CCtrlTreeView::SetBkColor(COLORREF clBack)
-{ return TreeView_SetBkColor(m_hwnd, clBack);
-}
-
-void CCtrlTreeView::SetCheckState(HTREEITEM hItem, uint32_t state)
-{ TreeView_SetCheckState(m_hwnd, hItem, state);
-}
-
-HIMAGELIST CCtrlTreeView::SetImageList(HIMAGELIST hIml, int iImage)
-{ return TreeView_SetImageList(m_hwnd, hIml, iImage);
-}
-
-void CCtrlTreeView::SetIndent(int iIndent)
-{ TreeView_SetIndent(m_hwnd, iIndent);
-}
-
-void CCtrlTreeView::SetInsertMark(HTREEITEM hItem, BOOL fAfter)
-{ TreeView_SetInsertMark(m_hwnd, hItem, fAfter);
-}
-
-COLORREF CCtrlTreeView::SetInsertMarkColor(COLORREF clMark)
-{ return TreeView_SetInsertMarkColor(m_hwnd, clMark);
-}
-
-void CCtrlTreeView::SetItem(TVITEMEX *tvi)
-{ TreeView_SetItem(m_hwnd, tvi);
-}
-
-void CCtrlTreeView::SetItemHeight(short cyItem)
-{ TreeView_SetItemHeight(m_hwnd, cyItem);
-}
-
-void CCtrlTreeView::SetItemState(HTREEITEM hItem, uint32_t state, uint32_t stateMask)
-{ TreeView_SetItemState(m_hwnd, hItem, state, stateMask);
-}
-
-COLORREF CCtrlTreeView::SetLineColor(COLORREF clLine)
-{ return TreeView_SetLineColor(m_hwnd, clLine);
-}
-
-void CCtrlTreeView::SetScrollTime(UINT uMaxScrollTime)
-{ TreeView_SetScrollTime(m_hwnd, uMaxScrollTime);
-}
-
-COLORREF CCtrlTreeView::SetTextColor(COLORREF clText)
-{ return TreeView_SetTextColor(m_hwnd, clText);
-}
-
-HWND CCtrlTreeView::SetToolTips(HWND hwndToolTips)
-{ return TreeView_SetToolTips(m_hwnd, hwndToolTips);
-}
-
-BOOL CCtrlTreeView::SetUnicodeFormat(BOOL fUnicode)
-{ return TreeView_SetUnicodeFormat(m_hwnd, fUnicode);
-}
-
-void CCtrlTreeView::SortChildren(HTREEITEM hItem, BOOL fRecurse)
-{ TreeView_SortChildren(m_hwnd, hItem, fRecurse);
-}
-
-void CCtrlTreeView::SortChildrenCB(TVSORTCB *cb, BOOL fRecurse)
-{ TreeView_SortChildrenCB(m_hwnd, cb, fRecurse);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-23 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+int ImageList_AddIcon_IconLibLoaded(HIMAGELIST hIml, int iconId)
+{
+ HICON hIcon = Skin_LoadIcon(iconId);
+ int res = ImageList_AddIcon(hIml, hIcon);
+ IcoLib_ReleaseIcon(hIcon);
+ return res;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlTreeView
+
+CCtrlTreeView::CCtrlTreeView(CDlgBase *dlg, int ctrlId) :
+ CCtrlBase(dlg, ctrlId),
+ m_dwFlags(0),
+ m_hDragItem(nullptr)
+{}
+
+void CCtrlTreeView::SetFlags(uint32_t dwFlags)
+{
+ if (dwFlags & MTREE_CHECKBOX)
+ m_bCheckBox = true;
+
+ if (dwFlags & MTREE_MULTISELECT)
+ m_bMultiSelect = true;
+
+ if (dwFlags & MTREE_DND) {
+ m_bDndEnabled = true;
+ m_bDragging = false;
+ m_hDragItem = nullptr;
+ }
+}
+
+void CCtrlTreeView::OnInit()
+{
+ CSuper::OnInit();
+
+ Subclass();
+
+ if (m_bCheckBox)
+ SetWindowLongW(m_hwnd, GWL_STYLE, TVS_CHECKBOXES | GetWindowLongW(m_hwnd, GWL_STYLE));
+}
+
+HTREEITEM CCtrlTreeView::MoveItemAbove(HTREEITEM hItem, HTREEITEM hInsertAfter, HTREEITEM hParent)
+{
+ if (hItem == nullptr || hInsertAfter == nullptr)
+ return nullptr;
+
+ if (hItem == hInsertAfter)
+ return hItem;
+
+ wchar_t name[128];
+ TVINSERTSTRUCT tvis = {};
+ tvis.itemex.mask = (UINT)-1;
+ tvis.itemex.pszText = name;
+ tvis.itemex.cchTextMax = _countof(name);
+ tvis.itemex.hItem = hItem;
+ if (!GetItem(&tvis.itemex))
+ return nullptr;
+
+ OBJLIST<TVINSERTSTRUCT> arChildren(1);
+ for (HTREEITEM p = GetChild(hItem); p; p = GetNextSibling(p)) {
+ wchar_t buf[128];
+ TVINSERTSTRUCT tvis2 = {};
+ tvis2.itemex.mask = (UINT)-1;
+ tvis2.itemex.pszText = buf;
+ tvis2.itemex.cchTextMax = _countof(buf);
+ tvis2.itemex.hItem = p;
+ if (GetItem(&tvis2.itemex)) {
+ tvis2.itemex.pszText = mir_wstrdup(tvis2.itemex.pszText);
+ arChildren.insert(new TVINSERTSTRUCT(tvis2));
+
+ tvis2.itemex.lParam = 0;
+ SetItem(&tvis2.itemex);
+ }
+ }
+
+ // the pointed lParam will be freed inside TVN_DELETEITEM
+ // so lets substitute it with 0
+ LPARAM saveOldData = tvis.itemex.lParam;
+ tvis.itemex.lParam = 0;
+ SetItem(&tvis.itemex);
+
+ // now current item contain lParam = 0 we can delete it. the memory will be kept.
+ DeleteItem(hItem);
+
+ for (auto &it : arChildren)
+ DeleteItem(it->itemex.hItem);
+
+ tvis.itemex.stateMask = tvis.itemex.state;
+ tvis.itemex.lParam = saveOldData;
+ tvis.hParent = hParent;
+ tvis.hInsertAfter = hInsertAfter;
+ auto hNewItem = InsertItem(&tvis);
+
+ hInsertAfter = nullptr;
+ for (auto &it : arChildren) {
+ it->hParent = hNewItem;
+ it->hInsertAfter = hInsertAfter;
+ hInsertAfter = InsertItem(it);
+
+ mir_free(it->itemex.pszText);
+ }
+
+ return hNewItem;
+}
+
+LRESULT CCtrlTreeView::CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TVHITTESTINFO hti;
+
+ switch (msg) {
+ case WM_MOUSEMOVE:
+ if (m_bDragging) {
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ HitTest(&hti);
+ if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) {
+ HTREEITEM it = hti.hItem;
+ hti.pt.y -= GetItemHeight() / 2;
+ HitTest(&hti);
+ if (!(hti.flags & TVHT_ABOVE))
+ SetInsertMark(hti.hItem, 1);
+ else
+ SetInsertMark(it, 0);
+ }
+ else {
+ if (hti.flags & TVHT_ABOVE) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0);
+ if (hti.flags & TVHT_BELOW) SendMsg(WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0);
+ SetInsertMark(nullptr, 0);
+ }
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ if (m_bDragging) {
+ SetInsertMark(nullptr, 0);
+ m_bDragging = false;
+ ReleaseCapture();
+
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam) - GetItemHeight() / 2;
+ HitTest(&hti);
+ if (m_hDragItem == hti.hItem)
+ break;
+
+ if (hti.flags & TVHT_ABOVE)
+ hti.hItem = TVI_FIRST;
+ else if (hti.flags & TVHT_BELOW)
+ hti.hItem = TVI_LAST;
+
+ HTREEITEM insertAfter = hti.hItem, hParent;
+ if (insertAfter != TVI_FIRST) {
+ hParent = GetParent(insertAfter);
+ if (GetChild(insertAfter) != nullptr) {
+ hParent = insertAfter;
+ insertAfter = TVI_FIRST;
+ }
+ }
+ else hParent = nullptr;
+
+ HTREEITEM FirstItem = nullptr;
+ if (m_bMultiSelect) {
+ LIST<_TREEITEM> arItems(10);
+ GetSelected(arItems);
+
+ // Proceed moving
+ for (auto &it : arItems) {
+ if (!insertAfter)
+ break;
+ if (GetParent(it) != hParent) // prevent subitems from being inserted at the same level
+ continue;
+
+ insertAfter = MoveItemAbove(it, insertAfter, hParent);
+ if (it == arItems[0])
+ FirstItem = insertAfter;
+ }
+ }
+ else FirstItem = MoveItemAbove(m_hDragItem, insertAfter, hParent);
+ if (FirstItem)
+ SelectItem(FirstItem);
+
+ NotifyChange();
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ if (!m_bMultiSelect)
+ break;
+
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ if (!TreeView_HitTest(m_hwnd, &hti)) {
+ UnselectAll();
+ break;
+ }
+
+ if (!m_bDndEnabled)
+ if (!(wParam & (MK_CONTROL | MK_SHIFT)) || !(hti.flags & (TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMRIGHT))) {
+ UnselectAll();
+ TreeView_SelectItem(m_hwnd, hti.hItem);
+ break;
+ }
+
+ if (wParam & MK_CONTROL) {
+ LIST<_TREEITEM> selected(1);
+ GetSelected(selected);
+
+ // Check if have to deselect it
+ for (int i = 0; i < selected.getCount(); i++) {
+ if (selected[i] == hti.hItem) {
+ // Deselect it
+ UnselectAll();
+ selected.remove(i);
+
+ if (i > 0)
+ hti.hItem = selected[0];
+ else if (i < selected.getCount())
+ hti.hItem = selected[i];
+ else
+ hti.hItem = nullptr;
+ break;
+ }
+ }
+
+ TreeView_SelectItem(m_hwnd, hti.hItem);
+ Select(selected);
+ }
+ else if (wParam & MK_SHIFT) {
+ HTREEITEM hItem = TreeView_GetSelection(m_hwnd);
+ if (hItem == nullptr)
+ break;
+
+ LIST<_TREEITEM> selected(1);
+ GetSelected(selected);
+
+ TreeView_SelectItem(m_hwnd, hti.hItem);
+ Select(selected);
+ SelectRange(hItem, hti.hItem);
+ }
+ break;
+ }
+
+ return CSuper::CustomWndProc(msg, wParam, lParam);
+}
+
+BOOL CCtrlTreeView::OnNotify(int, NMHDR *pnmh)
+{
+ TEventInfo evt = { this, pnmh };
+
+ switch (pnmh->code) {
+ case NM_RCLICK: OnRightClick(&evt); return TRUE;
+ case NM_CUSTOMDRAW: OnCustomDraw(&evt); return TRUE;
+ case TVN_BEGINLABELEDIT: OnBeginLabelEdit(&evt); return TRUE;
+ case TVN_BEGINRDRAG: OnBeginRDrag(&evt); return TRUE;
+ case TVN_DELETEITEM: OnDeleteItem(&evt); return TRUE;
+ case TVN_ENDLABELEDIT: OnEndLabelEdit(&evt); return TRUE;
+ case TVN_GETDISPINFO: OnGetDispInfo(&evt); return TRUE;
+ case TVN_GETINFOTIP: OnGetInfoTip(&evt); return TRUE;
+ case TVN_ITEMEXPANDED: OnItemExpanded(&evt); return TRUE;
+ case TVN_ITEMEXPANDING: OnItemExpanding(&evt); return TRUE;
+ case TVN_SELCHANGED: OnSelChanged(&evt); return TRUE;
+ case TVN_SELCHANGING: OnSelChanging(&evt); return TRUE;
+ case TVN_SETDISPINFO: OnSetDispInfo(&evt); return TRUE;
+ case TVN_SINGLEEXPAND: OnSingleExpand(&evt); return TRUE;
+
+ case TVN_BEGINDRAG:
+ OnBeginDrag(&evt);
+
+ // user-defined can clear the event code to disable dragging
+ if (m_bDndEnabled && pnmh->code) {
+ ::SetCapture(m_hwnd);
+ m_bDragging = true;
+ m_hDragItem = evt.nmtv->itemNew.hItem;
+ SelectItem(m_hDragItem);
+ }
+ return TRUE;
+
+ case TVN_KEYDOWN:
+ if (evt.nmtvkey->wVKey == VK_SPACE) {
+ evt.hItem = GetSelection();
+ 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 (hti.flags & TVHT_ONITEMSTATEICON) {
+ SelectItem(hti.hItem);
+
+ evt.hItem = hti.hItem;
+ OnItemChanged(&evt);
+ NotifyChange();
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void CCtrlTreeView::InvertCheck(HTREEITEM hItem)
+{
+ TVITEMEX tvi;
+ tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATEEX;
+ tvi.hItem = hItem;
+ if (!GetItem(&tvi))
+ return;
+
+ if (IsWinVerVistaPlus() && (tvi.uStateEx & TVIS_EX_DISABLED))
+ return;
+
+ tvi.iImage = tvi.iSelectedImage = !tvi.iImage;
+ SetItem(&tvi);
+
+ SelectItem(hItem);
+}
+
+void CCtrlTreeView::TranslateItem(HTREEITEM hItem)
+{
+ TVITEMEX tvi;
+ wchar_t buf[128];
+ GetItem(hItem, &tvi, buf, _countof(buf));
+ tvi.pszText = TranslateW_LP(tvi.pszText);
+ SetItem(&tvi);
+}
+
+void CCtrlTreeView::TranslateTree()
+{
+ HTREEITEM hItem = GetRoot();
+ while (hItem) {
+ TranslateItem(hItem);
+
+ HTREEITEM hItemTmp = nullptr;
+ if (hItemTmp = GetChild(hItem))
+ hItem = hItemTmp;
+ else if (hItemTmp = GetNextSibling(hItem))
+ hItem = hItemTmp;
+ else {
+ while (true) {
+ if (!(hItem = GetParent(hItem)))
+ break;
+ if (hItemTmp = GetNextSibling(hItem)) {
+ hItem = hItemTmp;
+ break;
+ }
+ }
+ }
+ }
+}
+
+HTREEITEM CCtrlTreeView::FindNamedItem(HTREEITEM hItem, const wchar_t *name)
+{
+ TVITEMEX tvi = { 0 };
+ wchar_t str[MAX_PATH];
+
+ if (hItem)
+ tvi.hItem = GetChild(hItem);
+ else
+ tvi.hItem = GetRoot();
+
+ if (!name)
+ return tvi.hItem;
+
+ tvi.mask = TVIF_TEXT;
+ tvi.pszText = str;
+ tvi.cchTextMax = _countof(str);
+
+ while (tvi.hItem) {
+ GetItem(&tvi);
+
+ if (!mir_wstrcmp(tvi.pszText, name))
+ return tvi.hItem;
+
+ tvi.hItem = GetNextSibling(tvi.hItem);
+ }
+ return nullptr;
+}
+
+void CCtrlTreeView::GetItem(HTREEITEM hItem, TVITEMEX *tvi) const
+{
+ memset(tvi, 0, sizeof(*tvi));
+ tvi->mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_INTEGRAL | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE;
+ tvi->hItem = hItem;
+ GetItem(tvi);
+}
+
+void CCtrlTreeView::GetItem(HTREEITEM hItem, TVITEMEX *tvi, wchar_t *szText, int iTextLength) const
+{
+ memset(tvi, 0, sizeof(*tvi));
+ tvi->mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_INTEGRAL | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE | TVIF_TEXT;
+ tvi->hItem = hItem;
+ tvi->pszText = szText;
+ tvi->cchTextMax = iTextLength;
+ GetItem(tvi);
+}
+
+bool CCtrlTreeView::IsSelected(HTREEITEM hItem)
+{
+ return (TVIS_SELECTED & TreeView_GetItemState(m_hwnd, hItem, TVIS_SELECTED)) == TVIS_SELECTED;
+}
+
+void CCtrlTreeView::Select(HTREEITEM hItem)
+{
+ TreeView_SetItemState(m_hwnd, hItem, TVIS_SELECTED, TVIS_SELECTED);
+}
+
+void CCtrlTreeView::Unselect(HTREEITEM hItem)
+{
+ TreeView_SetItemState(m_hwnd, hItem, 0, TVIS_SELECTED);
+}
+
+void CCtrlTreeView::DropHilite(HTREEITEM hItem)
+{
+ TreeView_SetItemState(m_hwnd, hItem, TVIS_DROPHILITED, TVIS_DROPHILITED);
+}
+
+void CCtrlTreeView::DropUnhilite(HTREEITEM hItem)
+{
+ TreeView_SetItemState(m_hwnd, hItem, 0, TVIS_DROPHILITED);
+}
+
+void CCtrlTreeView::SelectAll()
+{
+ TreeView_SelectItem(m_hwnd, nullptr);
+
+ HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
+ while (hItem) {
+ Select(hItem);
+ hItem = TreeView_GetNextSibling(m_hwnd, hItem);
+ }
+}
+
+void CCtrlTreeView::UnselectAll()
+{
+ TreeView_SelectItem(m_hwnd, nullptr);
+
+ HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
+ while (hItem) {
+ Unselect(hItem);
+ hItem = TreeView_GetNextSibling(m_hwnd, hItem);
+ }
+}
+
+void CCtrlTreeView::SelectRange(HTREEITEM hStart, HTREEITEM hEnd)
+{
+ int start = 0, end = 0, i = 0;
+ HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
+ while (hItem) {
+ if (hItem == hStart)
+ start = i;
+ if (hItem == hEnd)
+ end = i;
+
+ i++;
+ hItem = TreeView_GetNextSibling(m_hwnd, hItem);
+ }
+
+ if (end < start) {
+ int tmp = start;
+ start = end;
+ end = tmp;
+ }
+
+ i = 0;
+ hItem = TreeView_GetRoot(m_hwnd);
+ while (hItem) {
+ if (i >= start)
+ Select(hItem);
+ if (i == end)
+ break;
+
+ i++;
+ hItem = TreeView_GetNextSibling(m_hwnd, hItem);
+ }
+}
+
+int CCtrlTreeView::GetNumSelected()
+{
+ int ret = 0;
+ for (HTREEITEM hItem = TreeView_GetRoot(m_hwnd); hItem; hItem = TreeView_GetNextSibling(m_hwnd, hItem))
+ if (IsSelected(hItem))
+ ret++;
+
+ return ret;
+}
+
+void CCtrlTreeView::GetSelected(LIST<_TREEITEM> &selected)
+{
+ HTREEITEM hItem = TreeView_GetRoot(m_hwnd);
+ while (hItem) {
+ if (IsSelected(hItem))
+ selected.insert(hItem);
+ hItem = TreeView_GetNextSibling(m_hwnd, hItem);
+ }
+}
+
+void CCtrlTreeView::Select(LIST<_TREEITEM> &selected)
+{
+ for (auto &it : selected)
+ if (it != nullptr)
+ Select(it);
+}
+
+void CCtrlTreeView::GetCaretPos(CContextMenuPos &pos) const
+{
+ pos.pCtrl = this;
+
+ // position is empty, let's fill it using selection
+ if (pos.pt.x == 0 && pos.pt.y == 0) {
+ HTREEITEM hItem = GetSelection();
+ if (hItem != nullptr) {
+ pos.pCtrl = this;
+ pos.hItem = hItem;
+
+ RECT rc;
+ GetItemRect(hItem, &rc, TRUE);
+ pos.pt.x = rc.left + 8;
+ pos.pt.y = rc.top + 8;
+ ClientToScreen(m_hwnd, &pos.pt);
+ return;
+ }
+ }
+ // position is present, let's calculate current item
+ else {
+ TVHITTESTINFO hti;
+ hti.pt = pos.pt;
+ ScreenToClient(m_hwnd, &hti.pt);
+ if (HitTest(&hti) && (hti.flags & TVHT_ONITEM)) {
+ pos.hItem = hti.hItem;
+ return;
+ }
+ }
+
+ CSuper::GetCaretPos(pos);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+HIMAGELIST CCtrlTreeView::CreateDragImage(HTREEITEM hItem)
+{ return TreeView_CreateDragImage(m_hwnd, hItem);
+}
+
+void CCtrlTreeView::DeleteAllItems()
+{ TreeView_DeleteAllItems(m_hwnd);
+}
+
+void CCtrlTreeView::DeleteItem(HTREEITEM hItem)
+{ TreeView_DeleteItem(m_hwnd, hItem);
+}
+
+HWND CCtrlTreeView::EditLabel(HTREEITEM hItem)
+{ return TreeView_EditLabel(m_hwnd, hItem);
+}
+
+void CCtrlTreeView::EndEditLabelNow(BOOL cancel)
+{ TreeView_EndEditLabelNow(m_hwnd, cancel);
+}
+
+void CCtrlTreeView::EnsureVisible(HTREEITEM hItem)
+{ TreeView_EnsureVisible(m_hwnd, hItem);
+}
+
+void CCtrlTreeView::Expand(HTREEITEM hItem, uint32_t flag)
+{ TreeView_Expand(m_hwnd, hItem, flag);
+}
+
+COLORREF CCtrlTreeView::GetBkColor() const
+{ return TreeView_GetBkColor(m_hwnd);
+}
+
+uint32_t CCtrlTreeView::GetCheckState(HTREEITEM hItem) const
+{ return TreeView_GetCheckState(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetChild(HTREEITEM hItem) const
+{ return TreeView_GetChild(m_hwnd, hItem);
+}
+
+int CCtrlTreeView::GetCount() const
+{ return TreeView_GetCount(m_hwnd);
+}
+
+HTREEITEM CCtrlTreeView::GetDropHilight() const
+{ return TreeView_GetDropHilight(m_hwnd);
+}
+
+HWND CCtrlTreeView::GetEditControl() const
+{ return TreeView_GetEditControl(m_hwnd);
+}
+
+HTREEITEM CCtrlTreeView::GetFirstVisible() const
+{ return TreeView_GetFirstVisible(m_hwnd);
+}
+
+HIMAGELIST CCtrlTreeView::GetImageList(int iImage) const
+{ return TreeView_GetImageList(m_hwnd, iImage);
+}
+
+int CCtrlTreeView::GetIndent() const
+{ return TreeView_GetIndent(m_hwnd);
+}
+
+COLORREF CCtrlTreeView::GetInsertMarkColor() const
+{ return TreeView_GetInsertMarkColor(m_hwnd);
+}
+
+bool CCtrlTreeView::GetItem(TVITEMEX *tvi) const
+{ return TreeView_GetItem(m_hwnd, tvi) == TRUE;
+}
+
+int CCtrlTreeView::GetItemHeight() const
+{ return TreeView_GetItemHeight(m_hwnd);
+}
+
+void CCtrlTreeView::GetItemRect(HTREEITEM hItem, RECT *rcItem, BOOL fItemRect) const
+{ TreeView_GetItemRect(m_hwnd, hItem, rcItem, fItemRect);
+}
+
+uint32_t CCtrlTreeView::GetItemState(HTREEITEM hItem, uint32_t stateMask) const
+{ return TreeView_GetItemState(m_hwnd, hItem, stateMask);
+}
+
+HTREEITEM CCtrlTreeView::GetLastVisible() const
+{ return TreeView_GetLastVisible(m_hwnd);
+}
+
+COLORREF CCtrlTreeView::GetLineColor() const
+{ return TreeView_GetLineColor(m_hwnd);
+}
+
+HTREEITEM CCtrlTreeView::GetNextItem(HTREEITEM hItem, uint32_t flag) const
+{ return TreeView_GetNextItem(m_hwnd, hItem, flag);
+}
+
+HTREEITEM CCtrlTreeView::GetNextSibling(HTREEITEM hItem) const
+{ return TreeView_GetNextSibling(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetNextVisible(HTREEITEM hItem) const
+{ return TreeView_GetNextVisible(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetParent(HTREEITEM hItem) const
+{ return TreeView_GetParent(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetPrevSibling(HTREEITEM hItem) const
+{ return TreeView_GetPrevSibling(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetPrevVisible(HTREEITEM hItem) const
+{ return TreeView_GetPrevVisible(m_hwnd, hItem);
+}
+
+HTREEITEM CCtrlTreeView::GetRoot() const
+{ return TreeView_GetRoot(m_hwnd);
+}
+
+uint32_t CCtrlTreeView::GetScrollTime() const
+{ return TreeView_GetScrollTime(m_hwnd);
+}
+
+HTREEITEM CCtrlTreeView::GetSelection() const
+{ return TreeView_GetSelection(m_hwnd);
+}
+
+COLORREF CCtrlTreeView::GetTextColor() const
+{ return TreeView_GetTextColor(m_hwnd);
+}
+
+HWND CCtrlTreeView::GetToolTips() const
+{ return TreeView_GetToolTips(m_hwnd);
+}
+
+BOOL CCtrlTreeView::GetUnicodeFormat() const
+{ return TreeView_GetUnicodeFormat(m_hwnd);
+}
+
+unsigned CCtrlTreeView::GetVisibleCount() const
+{ return TreeView_GetVisibleCount(m_hwnd);
+}
+
+HTREEITEM CCtrlTreeView::HitTest(TVHITTESTINFO *hti) const
+{ return TreeView_HitTest(m_hwnd, hti);
+}
+
+HTREEITEM CCtrlTreeView::InsertItem(TVINSERTSTRUCT *tvis)
+{ return TreeView_InsertItem(m_hwnd, tvis);
+}
+
+void CCtrlTreeView::Select(HTREEITEM hItem, uint32_t flag)
+{ TreeView_Select(m_hwnd, hItem, flag);
+}
+
+void CCtrlTreeView::SelectDropTarget(HTREEITEM hItem)
+{ TreeView_SelectDropTarget(m_hwnd, hItem);
+}
+
+void CCtrlTreeView::SelectItem(HTREEITEM hItem)
+{ TreeView_SelectItem(m_hwnd, hItem);
+}
+
+void CCtrlTreeView::SelectSetFirstVisible(HTREEITEM hItem)
+{ TreeView_SelectSetFirstVisible(m_hwnd, hItem);
+}
+
+COLORREF CCtrlTreeView::SetBkColor(COLORREF clBack)
+{ return TreeView_SetBkColor(m_hwnd, clBack);
+}
+
+void CCtrlTreeView::SetCheckState(HTREEITEM hItem, uint32_t state)
+{ TreeView_SetCheckState(m_hwnd, hItem, state);
+}
+
+HIMAGELIST CCtrlTreeView::SetImageList(HIMAGELIST hIml, int iImage)
+{ return TreeView_SetImageList(m_hwnd, hIml, iImage);
+}
+
+void CCtrlTreeView::SetIndent(int iIndent)
+{ TreeView_SetIndent(m_hwnd, iIndent);
+}
+
+void CCtrlTreeView::SetInsertMark(HTREEITEM hItem, BOOL fAfter)
+{ TreeView_SetInsertMark(m_hwnd, hItem, fAfter);
+}
+
+COLORREF CCtrlTreeView::SetInsertMarkColor(COLORREF clMark)
+{ return TreeView_SetInsertMarkColor(m_hwnd, clMark);
+}
+
+void CCtrlTreeView::SetItem(TVITEMEX *tvi)
+{ TreeView_SetItem(m_hwnd, tvi);
+}
+
+void CCtrlTreeView::SetItemHeight(short cyItem)
+{ TreeView_SetItemHeight(m_hwnd, cyItem);
+}
+
+void CCtrlTreeView::SetItemState(HTREEITEM hItem, uint32_t state, uint32_t stateMask)
+{ TreeView_SetItemState(m_hwnd, hItem, state, stateMask);
+}
+
+COLORREF CCtrlTreeView::SetLineColor(COLORREF clLine)
+{ return TreeView_SetLineColor(m_hwnd, clLine);
+}
+
+void CCtrlTreeView::SetScrollTime(UINT uMaxScrollTime)
+{ TreeView_SetScrollTime(m_hwnd, uMaxScrollTime);
+}
+
+COLORREF CCtrlTreeView::SetTextColor(COLORREF clText)
+{ return TreeView_SetTextColor(m_hwnd, clText);
+}
+
+HWND CCtrlTreeView::SetToolTips(HWND hwndToolTips)
+{ return TreeView_SetToolTips(m_hwnd, hwndToolTips);
+}
+
+BOOL CCtrlTreeView::SetUnicodeFormat(BOOL fUnicode)
+{ return TreeView_SetUnicodeFormat(m_hwnd, fUnicode);
+}
+
+void CCtrlTreeView::SortChildren(HTREEITEM hItem, BOOL fRecurse)
+{ TreeView_SortChildren(m_hwnd, hItem, fRecurse);
+}
+
+void CCtrlTreeView::SortChildrenCB(TVSORTCB *cb, BOOL fRecurse)
+{ TreeView_SortChildrenCB(m_hwnd, cb, fRecurse);
+}
diff --git a/src/mir_core/src/Windows/miranda.cpp b/src/mir_core/src/Windows/miranda.cpp
index ce52b20b0b..5649a69e4c 100644
--- a/src/mir_core/src/Windows/miranda.cpp
+++ b/src/mir_core/src/Windows/miranda.cpp
@@ -1,406 +1,406 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "../stdafx.h"
-
-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;
-HANDLE hShutdownEvent, hPreShutdownEvent;
-uint32_t mir_tls = 0;
-
-static bool g_bMirandaTerminated = false;
-bool g_bEnableDpiAware = false;
-
-MIR_CORE_DLL(bool) Miranda_IsTerminated()
-{
- return g_bMirandaTerminated;
-}
-
-MIR_CORE_DLL(void) Miranda_SetTerminated(void)
-{
- g_bMirandaTerminated = true;
-
- NotifyEventHooks(hPreShutdownEvent, 0, 0);
- NotifyEventHooks(hShutdownEvent, 0, 0);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct MWaitableObject
-{
- MWaitableObject(MWaitableStub pFunc, HANDLE hEvent) :
- m_bOwnsEvent(false),
- m_hEvent(hEvent),
- m_pFunc(pFunc),
- m_pInfo(INVALID_HANDLE_VALUE)
- {
- if (hEvent == nullptr) {
- m_hEvent = CreateEvent(nullptr, TRUE, TRUE, nullptr);
- m_bOwnsEvent = true;
- }
- }
-
- MWaitableObject(MWaitableStubEx pFunc, void *pInfo) :
- m_bOwnsEvent(true),
- m_hEvent(CreateEvent(nullptr, TRUE, TRUE, nullptr)),
- m_pFuncEx(pFunc),
- m_pInfo(pInfo)
- {}
-
- ~MWaitableObject()
- {
- if (m_bOwnsEvent)
- ::CloseHandle(m_hEvent);
- }
-
- HANDLE m_hEvent;
- union
- {
- MWaitableStub m_pFunc;
- MWaitableStubEx m_pFuncEx;
- };
- void *m_pInfo;
-
- bool m_bOwnsEvent;
-};
-
-static OBJLIST<MWaitableObject> arWaitableObjects(1, HandleKeySortT);
-
-MIR_CORE_DLL(void) Miranda_WaitOnHandle(MWaitableStub pFunc, HANDLE hEvent)
-{
- arWaitableObjects.insert(new MWaitableObject(pFunc, hEvent));
-}
-
-MIR_CORE_DLL(void) Miranda_WaitOnHandleEx(MWaitableStubEx pFunc, void *pInfo)
-{
- arWaitableObjects.insert(new MWaitableObject(pFunc, pInfo));
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-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();
-
- wchar_t wszIniPath[MAX_PATH];
- PathToAbsoluteW(L"mirandaboot.ini", wszIniPath);
- if (GetPrivateProfileIntW(L"Interface", L"DpiAware", 0, wszIniPath) == 1)
- g_bEnableDpiAware = true;
-
- CreateServiceFunction(MS_SYSTEM_RESTART, RestartMiranda);
-
- hShutdownEvent = CreateHookableEvent(ME_SYSTEM_SHUTDOWN);
- hPreShutdownEvent = CreateHookableEvent(ME_SYSTEM_PRESHUTDOWN);
-
- pfnRtlGenRandom = (PGENRANDOM)GetProcAddress(GetModuleHandleA("advapi32"), "SystemFunction036");
-}
-
-MIR_CORE_DLL(void) UnloadCoreModule(void)
-{
- DestroyWindow(hAPCWindow);
- CloseHandle(hThreadQueueEmpty);
- TlsFree(mir_tls);
-
- DestroyModularEngine();
- UninitLogs();
- UnloadLangPackModule();
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Message loop
-
-static HMODULE hThemeAPI;
-
-typedef HRESULT(STDAPICALLTYPE *pfnBufferedPaintInit)(void);
-pfnBufferedPaintInit bufferedPaintInit;
-
-typedef HRESULT(STDAPICALLTYPE *pfnBufferedPaintUninit)(void);
-pfnBufferedPaintUninit bufferedPaintUninit;
-
-static void crtErrorHandler(const wchar_t *, const wchar_t *, const wchar_t *, unsigned, uintptr_t)
-{}
-
-static void __cdecl compactHeapsThread(void*)
-{
- Thread_SetName("compactHeapsThread");
-
- while (!Miranda_IsTerminated()) {
- SleepEx((1000 * 60) * 5, TRUE); // every 5 minutes
-
- HANDLE hHeaps[256];
- uint32_t hc = GetProcessHeaps(255, (PHANDLE)&hHeaps);
- if (hc != 0 && hc < 256) {
- __try {
- for (uint32_t j = 0; j < hc; j++)
- HeapCompact(hHeaps[j], 0);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {}
- }
- }
-}
-
-static void EnableDpiAware()
-{
- if (HMODULE hInst = GetModuleHandleW(L"user32")) {
- typedef void (WINAPI *pfnSetProcessDpiAwarenessContext)(HANDLE);
- if (auto *pFunc = (pfnSetProcessDpiAwarenessContext)GetProcAddress(hInst, "SetProcessDpiAwarenessContext")) {
- pFunc(HANDLE(-4));
- return;
- }
-
- typedef void (WINAPI *pfnSetProcessDpiAwareness)(DWORD);
- if (auto *pFunc = (pfnSetProcessDpiAwareness)GetProcAddress(hInst, "SetProcessDpiAwareness")) {
- pFunc(2);
- return;
- }
-
- typedef void (WINAPI *pfnSetProcessDPIAware_t)(void);
- if (auto *pFunc = (pfnSetProcessDPIAware_t)GetProcAddress(hInst, "SetProcessDPIAware"))
- pFunc();
- }
-}
-
-MIR_CORE_DLL(void) BeginMessageLoop()
-{
- _set_invalid_parameter_handler(&crtErrorHandler);
-
- #ifdef _DEBUG
- _CrtSetReportMode(_CRT_ASSERT, 0);
- #endif
-
- #ifdef _DEBUG
- if (CmdLine_GetOption(L"memdebug"))
- _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
- #endif
-
- hThemeAPI = LoadLibrary(L"uxtheme.dll");
- if (hThemeAPI) {
- bufferedPaintInit = (pfnBufferedPaintInit)GetProcAddress(hThemeAPI, "BufferedPaintInit");
- bufferedPaintUninit = (pfnBufferedPaintUninit)GetProcAddress(hThemeAPI, "BufferedPaintUninit");
- }
-
- if (g_bEnableDpiAware)
- EnableDpiAware();
-
- if (bufferedPaintInit)
- bufferedPaintInit();
-
- OleInitialize(nullptr);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static uint32_t dwEventTime = 0;
-
-void checkIdle(MSG *msg)
-{
- switch (msg->message) {
- case WM_MOUSEACTIVATE:
- case WM_MOUSEMOVE:
- case WM_CHAR:
- dwEventTime = GetTickCount();
- }
-}
-
-MIR_CORE_DLL(uint32_t) Miranda_GetIdle()
-{
- return dwEventTime;
-}
-
-static uint32_t myWait()
-{
- HANDLE *hWaitObjects = (HANDLE *)_alloca(arWaitableObjects.getCount() * sizeof(HANDLE));
- for (int i = 0; i < arWaitableObjects.getCount(); i++)
- hWaitObjects[i] = arWaitableObjects[i].m_hEvent;
-
- return MsgWaitForMultipleObjectsEx(arWaitableObjects.getCount(), hWaitObjects, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
-}
-
-MIR_CORE_DLL(void) EnterMessageLoop()
-{
- mir_forkthread(compactHeapsThread);
- dwEventTime = GetTickCount();
- uint32_t myPid = GetCurrentProcessId();
-
- bool messageloop = true;
- while (messageloop) {
- MSG msg;
- BOOL dying = FALSE;
- uint32_t rc = myWait();
- if (rc < WAIT_OBJECT_0 + arWaitableObjects.getCount()) {
- auto &pWait = arWaitableObjects[rc - WAIT_OBJECT_0];
- if (pWait.m_pInfo == INVALID_HANDLE_VALUE)
- (*pWait.m_pFunc)();
- else
- (*pWait.m_pFuncEx)(pWait.m_pInfo);
-
- if (pWait.m_bOwnsEvent)
- arWaitableObjects.remove(&pWait);
- }
-
- while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
- if (msg.message != WM_QUIT) {
- HWND h = GetForegroundWindow();
- DWORD pid = 0;
- checkIdle(&msg);
- if (h != nullptr && GetWindowThreadProcessId(h, &pid) && pid == myPid && GetClassLongPtr(h, GCW_ATOM) == 32770)
- if (h != nullptr && IsDialogMessage(h, &msg)) /* Wine fix. */
- continue;
-
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- else if (!dying) {
- dying++;
- g_bMirandaTerminated = true;
- NotifyEventHooks(hPreShutdownEvent, 0, 0);
-
- // this spins and processes the msg loop, objects and APC.
- Thread_Wait();
- NotifyEventHooks(hShutdownEvent, 0, 0);
- // if the hooks generated any messages, it'll get processed before the second WM_QUIT
- PostQuitMessage(0);
- }
- else if (dying)
- messageloop = false;
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) LeaveMessageLoop()
-{
- // Dragons live there...
- __try {
- OleUninitialize();
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- }
-
- if (bufferedPaintUninit) {
- bufferedPaintUninit();
- FreeLibrary(hThemeAPI);
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// entry point
-
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, uint32_t 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;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+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;
+HANDLE hShutdownEvent, hPreShutdownEvent;
+uint32_t mir_tls = 0;
+
+static bool g_bMirandaTerminated = false;
+bool g_bEnableDpiAware = false;
+
+MIR_CORE_DLL(bool) Miranda_IsTerminated()
+{
+ return g_bMirandaTerminated;
+}
+
+MIR_CORE_DLL(void) Miranda_SetTerminated(void)
+{
+ g_bMirandaTerminated = true;
+
+ NotifyEventHooks(hPreShutdownEvent, 0, 0);
+ NotifyEventHooks(hShutdownEvent, 0, 0);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct MWaitableObject
+{
+ MWaitableObject(MWaitableStub pFunc, HANDLE hEvent) :
+ m_bOwnsEvent(false),
+ m_hEvent(hEvent),
+ m_pFunc(pFunc),
+ m_pInfo(INVALID_HANDLE_VALUE)
+ {
+ if (hEvent == nullptr) {
+ m_hEvent = CreateEvent(nullptr, TRUE, TRUE, nullptr);
+ m_bOwnsEvent = true;
+ }
+ }
+
+ MWaitableObject(MWaitableStubEx pFunc, void *pInfo) :
+ m_bOwnsEvent(true),
+ m_hEvent(CreateEvent(nullptr, TRUE, TRUE, nullptr)),
+ m_pFuncEx(pFunc),
+ m_pInfo(pInfo)
+ {}
+
+ ~MWaitableObject()
+ {
+ if (m_bOwnsEvent)
+ ::CloseHandle(m_hEvent);
+ }
+
+ HANDLE m_hEvent;
+ union
+ {
+ MWaitableStub m_pFunc;
+ MWaitableStubEx m_pFuncEx;
+ };
+ void *m_pInfo;
+
+ bool m_bOwnsEvent;
+};
+
+static OBJLIST<MWaitableObject> arWaitableObjects(1, HandleKeySortT);
+
+MIR_CORE_DLL(void) Miranda_WaitOnHandle(MWaitableStub pFunc, HANDLE hEvent)
+{
+ arWaitableObjects.insert(new MWaitableObject(pFunc, hEvent));
+}
+
+MIR_CORE_DLL(void) Miranda_WaitOnHandleEx(MWaitableStubEx pFunc, void *pInfo)
+{
+ arWaitableObjects.insert(new MWaitableObject(pFunc, pInfo));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+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();
+
+ wchar_t wszIniPath[MAX_PATH];
+ PathToAbsoluteW(L"mirandaboot.ini", wszIniPath);
+ if (GetPrivateProfileIntW(L"Interface", L"DpiAware", 0, wszIniPath) == 1)
+ g_bEnableDpiAware = true;
+
+ CreateServiceFunction(MS_SYSTEM_RESTART, RestartMiranda);
+
+ hShutdownEvent = CreateHookableEvent(ME_SYSTEM_SHUTDOWN);
+ hPreShutdownEvent = CreateHookableEvent(ME_SYSTEM_PRESHUTDOWN);
+
+ pfnRtlGenRandom = (PGENRANDOM)GetProcAddress(GetModuleHandleA("advapi32"), "SystemFunction036");
+}
+
+MIR_CORE_DLL(void) UnloadCoreModule(void)
+{
+ DestroyWindow(hAPCWindow);
+ CloseHandle(hThreadQueueEmpty);
+ TlsFree(mir_tls);
+
+ DestroyModularEngine();
+ UninitLogs();
+ UnloadLangPackModule();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Message loop
+
+static HMODULE hThemeAPI;
+
+typedef HRESULT(STDAPICALLTYPE *pfnBufferedPaintInit)(void);
+pfnBufferedPaintInit bufferedPaintInit;
+
+typedef HRESULT(STDAPICALLTYPE *pfnBufferedPaintUninit)(void);
+pfnBufferedPaintUninit bufferedPaintUninit;
+
+static void crtErrorHandler(const wchar_t *, const wchar_t *, const wchar_t *, unsigned, uintptr_t)
+{}
+
+static void __cdecl compactHeapsThread(void*)
+{
+ Thread_SetName("compactHeapsThread");
+
+ while (!Miranda_IsTerminated()) {
+ SleepEx((1000 * 60) * 5, TRUE); // every 5 minutes
+
+ HANDLE hHeaps[256];
+ uint32_t hc = GetProcessHeaps(255, (PHANDLE)&hHeaps);
+ if (hc != 0 && hc < 256) {
+ __try {
+ for (uint32_t j = 0; j < hc; j++)
+ HeapCompact(hHeaps[j], 0);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {}
+ }
+ }
+}
+
+static void EnableDpiAware()
+{
+ if (HMODULE hInst = GetModuleHandleW(L"user32")) {
+ typedef void (WINAPI *pfnSetProcessDpiAwarenessContext)(HANDLE);
+ if (auto *pFunc = (pfnSetProcessDpiAwarenessContext)GetProcAddress(hInst, "SetProcessDpiAwarenessContext")) {
+ pFunc(HANDLE(-4));
+ return;
+ }
+
+ typedef void (WINAPI *pfnSetProcessDpiAwareness)(DWORD);
+ if (auto *pFunc = (pfnSetProcessDpiAwareness)GetProcAddress(hInst, "SetProcessDpiAwareness")) {
+ pFunc(2);
+ return;
+ }
+
+ typedef void (WINAPI *pfnSetProcessDPIAware_t)(void);
+ if (auto *pFunc = (pfnSetProcessDPIAware_t)GetProcAddress(hInst, "SetProcessDPIAware"))
+ pFunc();
+ }
+}
+
+MIR_CORE_DLL(void) BeginMessageLoop()
+{
+ _set_invalid_parameter_handler(&crtErrorHandler);
+
+ #ifdef _DEBUG
+ _CrtSetReportMode(_CRT_ASSERT, 0);
+ #endif
+
+ #ifdef _DEBUG
+ if (CmdLine_GetOption(L"memdebug"))
+ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+ #endif
+
+ hThemeAPI = LoadLibrary(L"uxtheme.dll");
+ if (hThemeAPI) {
+ bufferedPaintInit = (pfnBufferedPaintInit)GetProcAddress(hThemeAPI, "BufferedPaintInit");
+ bufferedPaintUninit = (pfnBufferedPaintUninit)GetProcAddress(hThemeAPI, "BufferedPaintUninit");
+ }
+
+ if (g_bEnableDpiAware)
+ EnableDpiAware();
+
+ if (bufferedPaintInit)
+ bufferedPaintInit();
+
+ OleInitialize(nullptr);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static uint32_t dwEventTime = 0;
+
+void checkIdle(MSG *msg)
+{
+ switch (msg->message) {
+ case WM_MOUSEACTIVATE:
+ case WM_MOUSEMOVE:
+ case WM_CHAR:
+ dwEventTime = GetTickCount();
+ }
+}
+
+MIR_CORE_DLL(uint32_t) Miranda_GetIdle()
+{
+ return dwEventTime;
+}
+
+static uint32_t myWait()
+{
+ HANDLE *hWaitObjects = (HANDLE *)_alloca(arWaitableObjects.getCount() * sizeof(HANDLE));
+ for (int i = 0; i < arWaitableObjects.getCount(); i++)
+ hWaitObjects[i] = arWaitableObjects[i].m_hEvent;
+
+ return MsgWaitForMultipleObjectsEx(arWaitableObjects.getCount(), hWaitObjects, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
+}
+
+MIR_CORE_DLL(void) EnterMessageLoop()
+{
+ mir_forkthread(compactHeapsThread);
+ dwEventTime = GetTickCount();
+ uint32_t myPid = GetCurrentProcessId();
+
+ bool messageloop = true;
+ while (messageloop) {
+ MSG msg;
+ BOOL dying = FALSE;
+ uint32_t rc = myWait();
+ if (rc < WAIT_OBJECT_0 + arWaitableObjects.getCount()) {
+ auto &pWait = arWaitableObjects[rc - WAIT_OBJECT_0];
+ if (pWait.m_pInfo == INVALID_HANDLE_VALUE)
+ (*pWait.m_pFunc)();
+ else
+ (*pWait.m_pFuncEx)(pWait.m_pInfo);
+
+ if (pWait.m_bOwnsEvent)
+ arWaitableObjects.remove(&pWait);
+ }
+
+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ if (msg.message != WM_QUIT) {
+ HWND h = GetForegroundWindow();
+ DWORD pid = 0;
+ checkIdle(&msg);
+ if (h != nullptr && GetWindowThreadProcessId(h, &pid) && pid == myPid && GetClassLongPtr(h, GCW_ATOM) == 32770)
+ if (h != nullptr && IsDialogMessage(h, &msg)) /* Wine fix. */
+ continue;
+
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ else if (!dying) {
+ dying++;
+ g_bMirandaTerminated = true;
+ NotifyEventHooks(hPreShutdownEvent, 0, 0);
+
+ // this spins and processes the msg loop, objects and APC.
+ Thread_Wait();
+ NotifyEventHooks(hShutdownEvent, 0, 0);
+ // if the hooks generated any messages, it'll get processed before the second WM_QUIT
+ PostQuitMessage(0);
+ }
+ else if (dying)
+ messageloop = false;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(void) LeaveMessageLoop()
+{
+ // Dragons live there...
+ __try {
+ OleUninitialize();
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+
+ if (bufferedPaintUninit) {
+ bufferedPaintUninit();
+ FreeLibrary(hThemeAPI);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// entry point
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, uint32_t 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/db.cpp b/src/mir_core/src/db.cpp
index 63899787c7..5b2048c2bb 100644
--- a/src/mir_core/src/db.cpp
+++ b/src/mir_core/src/db.cpp
@@ -1,576 +1,576 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-MIR_CORE_EXPORT MDatabaseCommon* g_pCurrDb = nullptr;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// database functions
-
-MIR_CORE_DLL(void) db_set_safety_mode(BOOL bNewMode)
-{
- if (g_pCurrDb)
- g_pCurrDb->SetCacheSafetyMode(bNewMode != 0);
-}
-
-MIR_CORE_DLL(int) db_get_contact_count(void)
-{
- return (g_pCurrDb) ? g_pCurrDb->GetContactCount() : 0;
-}
-
-MIR_CORE_DLL(MDatabaseCommon*) db_get_current()
-{
- return g_pCurrDb;
-}
-
-MIR_CORE_DLL(int) db_delete_module(MCONTACT hContact, const char *szModuleName)
-{
- return (g_pCurrDb) ? g_pCurrDb->DeleteModule(hContact, szModuleName) : 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static int CheckIfModuleIsEmptyProc(const char *, void *)
-{
- return 1;
-}
-
-MIR_CORE_DLL(bool) db_is_module_empty(MCONTACT hContact, const char *szModule)
-{
- return (g_pCurrDb) ? g_pCurrDb->EnumContactSettings(hContact, CheckIfModuleIsEmptyProc, szModule, 0) < 0 : true;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct EnumProcParam
-{
- MCONTACT hContact;
- LPCSTR szModule, szNewModule;
-};
-
-static int EnumProc(const char *szSetting, void *lParam)
-{
- EnumProcParam *param = (EnumProcParam *)lParam;
-
- DBVARIANT dbv;
- if (!db_get(param->hContact, param->szModule, szSetting, &dbv)) {
- db_set(param->hContact, param->szNewModule, szSetting, &dbv);
- db_free(&dbv);
- }
- return 0;
-}
-
-MIR_CORE_DLL(int) db_copy_module(const char *szModule, const char *szNewModule, MCONTACT hContact)
-{
- EnumProcParam param = { hContact, szModule, szNewModule };
- return db_enum_settings(hContact, EnumProc, szModule, &param);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// contact functions
-
-MIR_CORE_DLL(MCONTACT) db_add_contact(void)
-{
- MCONTACT hNew = (g_pCurrDb) ? g_pCurrDb->AddContact() : 0;
- Netlib_Logf(nullptr, "New contact created: %d", hNew);
- return hNew;
-}
-
-MIR_CORE_DLL(int) db_delete_contact(MCONTACT hContact)
-{
- ptrW wszPhoto(db_get_wsa(hContact, "ContactPhoto", "File"));
- if (wszPhoto != nullptr) {
- #ifdef _MSC_VER
- DeleteFileW(wszPhoto);
- #else
- remove(T2Utf(wszPhoto));
- #endif
- }
-
- Netlib_Logf(nullptr, "Contact deleted: %d", hContact);
- return (g_pCurrDb) ? g_pCurrDb->DeleteContact(hContact) : 0;
-}
-
-MIR_CORE_DLL(int) db_is_contact(MCONTACT hContact)
-{
- return (g_pCurrDb) ? g_pCurrDb->IsDbContact(hContact) : 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// enumerators
-
-MIR_CORE_DLL(int) db_enum_modules(DBMODULEENUMPROC pFunc, void *param)
-{
- return (g_pCurrDb) ? g_pCurrDb->EnumModuleNames(pFunc, param) : 0;
-}
-
-MIR_CORE_DLL(int) db_enum_residents(DBMODULEENUMPROC pFunc, void *param)
-{
- return (g_pCurrDb) ? g_pCurrDb->EnumResidentSettings(pFunc, param) : 0;
-}
-
-MIR_CORE_DLL(int) db_enum_settings(MCONTACT hContact, DBSETTINGENUMPROC pFunc, const char *szModule, void *param)
-{
- return (g_pCurrDb) ? g_pCurrDb->EnumContactSettings(hContact, pFunc, szModule, param) : 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// getting data
-
-MIR_CORE_DLL(int) db_get_b(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue)
-{
- if (g_pCurrDb != nullptr) {
- DBVARIANT dbv;
- if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv))
- {
- switch(dbv.type) {
- case DBVT_BYTE: return dbv.bVal;
- case DBVT_WORD: return uint8_t(dbv.wVal);
- case DBVT_DWORD: return uint8_t(dbv.dVal);
- }
- g_pCurrDb->FreeVariant(&dbv);
- }
- }
- return errorValue;
-}
-
-MIR_CORE_DLL(int) db_get_w(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue)
-{
- if (g_pCurrDb != nullptr) {
- DBVARIANT dbv;
- if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) {
- switch(dbv.type) {
- case DBVT_BYTE: return dbv.bVal;
- case DBVT_WORD: return dbv.wVal;
- case DBVT_DWORD: return uint16_t(dbv.dVal);
- }
- g_pCurrDb->FreeVariant(&dbv);
- }
- }
- return errorValue;
-}
-
-MIR_CORE_DLL(uint32_t) db_get_dw(MCONTACT hContact, const char *szModule, const char *szSetting, uint32_t errorValue)
-{
- if (g_pCurrDb != nullptr) {
- DBVARIANT dbv;
- if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) {
- switch(dbv.type) {
- case DBVT_BYTE: return dbv.bVal;
- case DBVT_WORD: return dbv.wVal;
- case DBVT_DWORD: return dbv.dVal;
- }
- g_pCurrDb->FreeVariant(&dbv);
- }
- }
-
- return errorValue;
-}
-
-MIR_CORE_DLL(INT_PTR) db_get(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- return g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_get_s(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv, const int nType)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- dbv->type = (uint8_t)nType;
- return g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, dbv);
-}
-
-MIR_CORE_DLL(char*) db_get_sa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue)
-{
- if (g_pCurrDb) {
- DBVARIANT dbv = { DBVT_ASCIIZ };
- if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
- return dbv.pszVal;
- }
-
- return (szValue == nullptr) ? nullptr : mir_strdup(szValue);
-}
-
-MIR_CORE_DLL(char*) db_get_utfa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue)
-{
- if (g_pCurrDb) {
- DBVARIANT dbv = { DBVT_UTF8 };
- if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
- return dbv.pszVal;
- }
-
- return (szValue == nullptr) ? nullptr : mir_strdup(szValue);
-}
-
-MIR_CORE_DLL(wchar_t*) db_get_wsa(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *szValue)
-{
- if (g_pCurrDb) {
- DBVARIANT dbv = { DBVT_WCHAR };
- if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
- return dbv.pwszVal;
- }
-
- return (szValue == nullptr) ? nullptr : mir_wstrdup(szValue);
-}
-
-MIR_CORE_DLL(CMStringA) db_get_sm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const char *szValue)
-{
- if (g_pCurrDb == nullptr)
- return (szValue == nullptr) ? CMStringA() : CMStringA(szValue);
-
- DBVARIANT dbv = { DBVT_ASCIIZ };
- if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
- return (szValue == nullptr) ? CMStringA() : CMStringA(szValue);
-
- return CMStringA(ptrA(dbv.pszVal).get());
-}
-
-MIR_CORE_DLL(CMStringW) db_get_wsm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const wchar_t *szValue)
-{
- if (g_pCurrDb == nullptr)
- return (szValue == nullptr) ? CMStringW() : CMStringW(szValue);
-
- DBVARIANT dbv = { DBVT_WCHAR };
- if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
- return (szValue == nullptr) ? CMStringW() : CMStringW(szValue);
-
- return CMStringW(ptrW(dbv.pwszVal).get());
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// getting static data
-
-MIR_CORE_DLL(int) db_get_static(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_ASCIIZ;
- dbv.pszVal = pDest;
- dbv.cchVal = cbDest;
- return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
-}
-
-MIR_CORE_DLL(int) db_get_static_utf(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_UTF8;
- dbv.pszVal = pDest;
- dbv.cchVal = cbDest;
- return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
-}
-
-MIR_CORE_DLL(int) db_get_wstatic(MCONTACT hContact, const char *szModule, const char *szSetting, wchar_t *pDest, int cbDest)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_WCHAR;
- dbv.pwszVal = pDest;
- dbv.cchVal = cbDest;
- return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// setting data
-
-MIR_CORE_DLL(INT_PTR) db_set(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_b(MCONTACT hContact, const char *szModule, const char *szSetting, uint8_t val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_BYTE;
- dbv.bVal = val;
- return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_w(MCONTACT hContact, const char *szModule, const char *szSetting, uint16_t val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_WORD;
- dbv.wVal = val;
- return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_dw(MCONTACT hContact, const char *szModule, const char *szSetting, uint32_t val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_DWORD;
- dbv.dVal = val;
- return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_s(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_ASCIIZ;
- dbv.pszVal = (char*)(val == nullptr ? "" : val);
- return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_ws(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_WCHAR;
- dbv.pwszVal = (wchar_t*)(val == nullptr ? L"" : val);
- return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_utf(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_UTF8;
- dbv.pszVal = (char*)(val == nullptr ? "" : val);
- return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_blob(MCONTACT hContact, const char *szModule, const char *szSetting, const void *val, unsigned len)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_BLOB;
- dbv.cpbVal = (uint16_t)len;
- dbv.pbVal = (unsigned char*)val;
- return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// events
-
-MIR_CORE_DLL(MEVENT) db_event_add(MCONTACT hContact, const DBEVENTINFO *dbei)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->AddEvent(hContact, dbei);
-}
-
-MIR_CORE_DLL(int) db_event_count(MCONTACT hContact)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventCount(hContact);
-}
-
-MIR_CORE_DLL(int) db_event_delete(MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->DeleteEvent(hDbEvent);
-}
-
-MIR_CORE_DLL(int) db_event_edit(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO *dbei)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EditEvent(hContact, hDbEvent, dbei);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_first(MCONTACT hContact)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstEvent(hContact);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_firstUnread(MCONTACT hContact)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstUnreadEvent(hContact);
-}
-
-MIR_CORE_DLL(int) db_event_get(MEVENT hDbEvent, DBEVENTINFO *dbei)
-{
- return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->GetEvent(hDbEvent, dbei);
-}
-
-MIR_CORE_DLL(int) db_event_getBlobSize(MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetBlobSize(hDbEvent);
-}
-
-MIR_CORE_DLL(MCONTACT) db_event_getContact(MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventContact(hDbEvent);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_last(MCONTACT hContact)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindLastEvent(hContact);
-}
-
-MIR_CORE_DLL(int) db_event_markRead(MCONTACT hContact, MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->MarkEventRead(hContact, hDbEvent);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_next(MCONTACT hContact, MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindNextEvent(hContact, hDbEvent);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_prev(MCONTACT hContact, MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindPrevEvent(hContact, hDbEvent);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_replace(MCONTACT hContact, const DBEVENTINFO *dbei)
-{
- MEVENT ret = 0;
- if (dbei->szId)
- ret = db_event_getById(dbei->szModule, dbei->szId);
- if (!ret)
- ret = db_event_add(hContact, dbei);
- // do not uncomment
- // else
- // db_event_edit(hContact, ret, dbei);
- return ret;
-}
-
-MIR_CORE_DLL(MEVENT) db_event_getById(const char *szModule, const char *szId)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventById(szModule, szId);
-}
-
-MIR_CORE_DLL(int) db_event_updateId(MEVENT hDbEvent, const char *szId)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->UpdateEventId(hDbEvent, szId);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// event cursors
-
-DB::EventCursor::~EventCursor()
-{
-}
-
-MIR_CORE_DLL(DB::EventCursor*) DB::Events(MCONTACT hContact, MEVENT iStartEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursor(hContact, iStartEvent);
-}
-
-MIR_CORE_DLL(DB::EventCursor*) DB::EventsRev(MCONTACT hContact, MEVENT iStartEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursorRev(hContact, iStartEvent);
-}
-
-DB::ECPTR::ECPTR(EventCursor *_pCursor) :
- m_cursor(_pCursor),
- m_prevFetched(-1),
- m_currEvent(0)
-{
-}
-
-DB::ECPTR::~ECPTR()
-{
- delete m_cursor;
-}
-
-void DB::ECPTR::DeleteEvent()
-{
- m_prevFetched = m_cursor->FetchNext();
- db_event_delete(m_currEvent);
-}
-
-MEVENT DB::ECPTR::FetchNext()
-{
- if (m_prevFetched != -1) {
- m_currEvent = m_prevFetched;
- m_prevFetched = -1;
- }
- else m_currEvent = m_cursor->FetchNext();
-
- return m_currEvent;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// misc functions
-
-MIR_CORE_DLL(INT_PTR) db_free(DBVARIANT *dbv)
-{
- return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->FreeVariant(dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_unset(MCONTACT hContact, const char *szModule, const char *szSetting)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- return g_pCurrDb->DeleteContactSetting(hContact, szModule, szSetting);
-}
-
-MIR_CORE_DLL(DBCachedContact*) db_get_contact(MCONTACT hContact)
-{
- return (g_pCurrDb == nullptr) ? nullptr : g_pCurrDb->getCache()->GetCachedContact(hContact);
-}
-
-MIR_CORE_DLL(MCONTACT) db_find_first(const char *szProto)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstContact(szProto);
-}
-
-MIR_CORE_DLL(MCONTACT) db_find_next(MCONTACT hContact, const char *szProto)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindNextContact(hContact, szProto);
-}
-
-MIR_CORE_DLL(void) db_setCurrent(MDatabaseCommon *_db)
-{
- g_pCurrDb = _db;
- if (g_pCurrDb == nullptr)
- return;
-
- // try to get the langpack's name from a profile
- ptrW langpack(db_get_wsa(0, "Langpack", "Current"));
- if (langpack && langpack[0] != '\0')
- LoadLangPack(langpack);
- else
- GetDefaultLang();
-}
-
-MIR_CORE_DLL(BOOL) db_set_resident(const char *szModule, const char *szService, BOOL bEnable)
-{
- if (g_pCurrDb == nullptr || szModule == nullptr || szService == nullptr)
- return FALSE;
-
- char str[MAXMODULELABELLENGTH * 2];
- mir_snprintf(str, "%s/%s", szModule, szService);
- return g_pCurrDb->SetSettingResident(bEnable, str);
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+MIR_CORE_EXPORT MDatabaseCommon* g_pCurrDb = nullptr;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// database functions
+
+MIR_CORE_DLL(void) db_set_safety_mode(BOOL bNewMode)
+{
+ if (g_pCurrDb)
+ g_pCurrDb->SetCacheSafetyMode(bNewMode != 0);
+}
+
+MIR_CORE_DLL(int) db_get_contact_count(void)
+{
+ return (g_pCurrDb) ? g_pCurrDb->GetContactCount() : 0;
+}
+
+MIR_CORE_DLL(MDatabaseCommon*) db_get_current()
+{
+ return g_pCurrDb;
+}
+
+MIR_CORE_DLL(int) db_delete_module(MCONTACT hContact, const char *szModuleName)
+{
+ return (g_pCurrDb) ? g_pCurrDb->DeleteModule(hContact, szModuleName) : 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int CheckIfModuleIsEmptyProc(const char *, void *)
+{
+ return 1;
+}
+
+MIR_CORE_DLL(bool) db_is_module_empty(MCONTACT hContact, const char *szModule)
+{
+ return (g_pCurrDb) ? g_pCurrDb->EnumContactSettings(hContact, CheckIfModuleIsEmptyProc, szModule, 0) < 0 : true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct EnumProcParam
+{
+ MCONTACT hContact;
+ LPCSTR szModule, szNewModule;
+};
+
+static int EnumProc(const char *szSetting, void *lParam)
+{
+ EnumProcParam *param = (EnumProcParam *)lParam;
+
+ DBVARIANT dbv;
+ if (!db_get(param->hContact, param->szModule, szSetting, &dbv)) {
+ db_set(param->hContact, param->szNewModule, szSetting, &dbv);
+ db_free(&dbv);
+ }
+ return 0;
+}
+
+MIR_CORE_DLL(int) db_copy_module(const char *szModule, const char *szNewModule, MCONTACT hContact)
+{
+ EnumProcParam param = { hContact, szModule, szNewModule };
+ return db_enum_settings(hContact, EnumProc, szModule, &param);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// contact functions
+
+MIR_CORE_DLL(MCONTACT) db_add_contact(void)
+{
+ MCONTACT hNew = (g_pCurrDb) ? g_pCurrDb->AddContact() : 0;
+ Netlib_Logf(nullptr, "New contact created: %d", hNew);
+ return hNew;
+}
+
+MIR_CORE_DLL(int) db_delete_contact(MCONTACT hContact)
+{
+ ptrW wszPhoto(db_get_wsa(hContact, "ContactPhoto", "File"));
+ if (wszPhoto != nullptr) {
+ #ifdef _MSC_VER
+ DeleteFileW(wszPhoto);
+ #else
+ remove(T2Utf(wszPhoto));
+ #endif
+ }
+
+ Netlib_Logf(nullptr, "Contact deleted: %d", hContact);
+ return (g_pCurrDb) ? g_pCurrDb->DeleteContact(hContact) : 0;
+}
+
+MIR_CORE_DLL(int) db_is_contact(MCONTACT hContact)
+{
+ return (g_pCurrDb) ? g_pCurrDb->IsDbContact(hContact) : 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// enumerators
+
+MIR_CORE_DLL(int) db_enum_modules(DBMODULEENUMPROC pFunc, void *param)
+{
+ return (g_pCurrDb) ? g_pCurrDb->EnumModuleNames(pFunc, param) : 0;
+}
+
+MIR_CORE_DLL(int) db_enum_residents(DBMODULEENUMPROC pFunc, void *param)
+{
+ return (g_pCurrDb) ? g_pCurrDb->EnumResidentSettings(pFunc, param) : 0;
+}
+
+MIR_CORE_DLL(int) db_enum_settings(MCONTACT hContact, DBSETTINGENUMPROC pFunc, const char *szModule, void *param)
+{
+ return (g_pCurrDb) ? g_pCurrDb->EnumContactSettings(hContact, pFunc, szModule, param) : 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// getting data
+
+MIR_CORE_DLL(int) db_get_b(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue)
+{
+ if (g_pCurrDb != nullptr) {
+ DBVARIANT dbv;
+ if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv))
+ {
+ switch(dbv.type) {
+ case DBVT_BYTE: return dbv.bVal;
+ case DBVT_WORD: return uint8_t(dbv.wVal);
+ case DBVT_DWORD: return uint8_t(dbv.dVal);
+ }
+ g_pCurrDb->FreeVariant(&dbv);
+ }
+ }
+ return errorValue;
+}
+
+MIR_CORE_DLL(int) db_get_w(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue)
+{
+ if (g_pCurrDb != nullptr) {
+ DBVARIANT dbv;
+ if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) {
+ switch(dbv.type) {
+ case DBVT_BYTE: return dbv.bVal;
+ case DBVT_WORD: return dbv.wVal;
+ case DBVT_DWORD: return uint16_t(dbv.dVal);
+ }
+ g_pCurrDb->FreeVariant(&dbv);
+ }
+ }
+ return errorValue;
+}
+
+MIR_CORE_DLL(uint32_t) db_get_dw(MCONTACT hContact, const char *szModule, const char *szSetting, uint32_t errorValue)
+{
+ if (g_pCurrDb != nullptr) {
+ DBVARIANT dbv;
+ if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) {
+ switch(dbv.type) {
+ case DBVT_BYTE: return dbv.bVal;
+ case DBVT_WORD: return dbv.wVal;
+ case DBVT_DWORD: return dbv.dVal;
+ }
+ g_pCurrDb->FreeVariant(&dbv);
+ }
+ }
+
+ return errorValue;
+}
+
+MIR_CORE_DLL(INT_PTR) db_get(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ return g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_get_s(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv, const int nType)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ dbv->type = (uint8_t)nType;
+ return g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, dbv);
+}
+
+MIR_CORE_DLL(char*) db_get_sa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue)
+{
+ if (g_pCurrDb) {
+ DBVARIANT dbv = { DBVT_ASCIIZ };
+ if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
+ return dbv.pszVal;
+ }
+
+ return (szValue == nullptr) ? nullptr : mir_strdup(szValue);
+}
+
+MIR_CORE_DLL(char*) db_get_utfa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue)
+{
+ if (g_pCurrDb) {
+ DBVARIANT dbv = { DBVT_UTF8 };
+ if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
+ return dbv.pszVal;
+ }
+
+ return (szValue == nullptr) ? nullptr : mir_strdup(szValue);
+}
+
+MIR_CORE_DLL(wchar_t*) db_get_wsa(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *szValue)
+{
+ if (g_pCurrDb) {
+ DBVARIANT dbv = { DBVT_WCHAR };
+ if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
+ return dbv.pwszVal;
+ }
+
+ return (szValue == nullptr) ? nullptr : mir_wstrdup(szValue);
+}
+
+MIR_CORE_DLL(CMStringA) db_get_sm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const char *szValue)
+{
+ if (g_pCurrDb == nullptr)
+ return (szValue == nullptr) ? CMStringA() : CMStringA(szValue);
+
+ DBVARIANT dbv = { DBVT_ASCIIZ };
+ if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
+ return (szValue == nullptr) ? CMStringA() : CMStringA(szValue);
+
+ return CMStringA(ptrA(dbv.pszVal).get());
+}
+
+MIR_CORE_DLL(CMStringW) db_get_wsm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const wchar_t *szValue)
+{
+ if (g_pCurrDb == nullptr)
+ return (szValue == nullptr) ? CMStringW() : CMStringW(szValue);
+
+ DBVARIANT dbv = { DBVT_WCHAR };
+ if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
+ return (szValue == nullptr) ? CMStringW() : CMStringW(szValue);
+
+ return CMStringW(ptrW(dbv.pwszVal).get());
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// getting static data
+
+MIR_CORE_DLL(int) db_get_static(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_ASCIIZ;
+ dbv.pszVal = pDest;
+ dbv.cchVal = cbDest;
+ return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
+}
+
+MIR_CORE_DLL(int) db_get_static_utf(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_UTF8;
+ dbv.pszVal = pDest;
+ dbv.cchVal = cbDest;
+ return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
+}
+
+MIR_CORE_DLL(int) db_get_wstatic(MCONTACT hContact, const char *szModule, const char *szSetting, wchar_t *pDest, int cbDest)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_WCHAR;
+ dbv.pwszVal = pDest;
+ dbv.cchVal = cbDest;
+ return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// setting data
+
+MIR_CORE_DLL(INT_PTR) db_set(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_b(MCONTACT hContact, const char *szModule, const char *szSetting, uint8_t val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_BYTE;
+ dbv.bVal = val;
+ return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_w(MCONTACT hContact, const char *szModule, const char *szSetting, uint16_t val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_WORD;
+ dbv.wVal = val;
+ return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_dw(MCONTACT hContact, const char *szModule, const char *szSetting, uint32_t val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_DWORD;
+ dbv.dVal = val;
+ return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_s(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_ASCIIZ;
+ dbv.pszVal = (char*)(val == nullptr ? "" : val);
+ return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_ws(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_WCHAR;
+ dbv.pwszVal = (wchar_t*)(val == nullptr ? L"" : val);
+ return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_utf(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_UTF8;
+ dbv.pszVal = (char*)(val == nullptr ? "" : val);
+ return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_blob(MCONTACT hContact, const char *szModule, const char *szSetting, const void *val, unsigned len)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_BLOB;
+ dbv.cpbVal = (uint16_t)len;
+ dbv.pbVal = (unsigned char*)val;
+ return g_pCurrDb->WriteContactSetting(hContact, szModule, szSetting, &dbv);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// events
+
+MIR_CORE_DLL(MEVENT) db_event_add(MCONTACT hContact, const DBEVENTINFO *dbei)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->AddEvent(hContact, dbei);
+}
+
+MIR_CORE_DLL(int) db_event_count(MCONTACT hContact)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventCount(hContact);
+}
+
+MIR_CORE_DLL(int) db_event_delete(MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->DeleteEvent(hDbEvent);
+}
+
+MIR_CORE_DLL(int) db_event_edit(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO *dbei)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EditEvent(hContact, hDbEvent, dbei);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_first(MCONTACT hContact)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstEvent(hContact);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_firstUnread(MCONTACT hContact)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstUnreadEvent(hContact);
+}
+
+MIR_CORE_DLL(int) db_event_get(MEVENT hDbEvent, DBEVENTINFO *dbei)
+{
+ return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->GetEvent(hDbEvent, dbei);
+}
+
+MIR_CORE_DLL(int) db_event_getBlobSize(MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetBlobSize(hDbEvent);
+}
+
+MIR_CORE_DLL(MCONTACT) db_event_getContact(MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventContact(hDbEvent);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_last(MCONTACT hContact)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindLastEvent(hContact);
+}
+
+MIR_CORE_DLL(int) db_event_markRead(MCONTACT hContact, MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->MarkEventRead(hContact, hDbEvent);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_next(MCONTACT hContact, MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindNextEvent(hContact, hDbEvent);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_prev(MCONTACT hContact, MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindPrevEvent(hContact, hDbEvent);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_replace(MCONTACT hContact, const DBEVENTINFO *dbei)
+{
+ MEVENT ret = 0;
+ if (dbei->szId)
+ ret = db_event_getById(dbei->szModule, dbei->szId);
+ if (!ret)
+ ret = db_event_add(hContact, dbei);
+ // do not uncomment
+ // else
+ // db_event_edit(hContact, ret, dbei);
+ return ret;
+}
+
+MIR_CORE_DLL(MEVENT) db_event_getById(const char *szModule, const char *szId)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventById(szModule, szId);
+}
+
+MIR_CORE_DLL(int) db_event_updateId(MEVENT hDbEvent, const char *szId)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->UpdateEventId(hDbEvent, szId);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// event cursors
+
+DB::EventCursor::~EventCursor()
+{
+}
+
+MIR_CORE_DLL(DB::EventCursor*) DB::Events(MCONTACT hContact, MEVENT iStartEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursor(hContact, iStartEvent);
+}
+
+MIR_CORE_DLL(DB::EventCursor*) DB::EventsRev(MCONTACT hContact, MEVENT iStartEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursorRev(hContact, iStartEvent);
+}
+
+DB::ECPTR::ECPTR(EventCursor *_pCursor) :
+ m_cursor(_pCursor),
+ m_prevFetched(-1),
+ m_currEvent(0)
+{
+}
+
+DB::ECPTR::~ECPTR()
+{
+ delete m_cursor;
+}
+
+void DB::ECPTR::DeleteEvent()
+{
+ m_prevFetched = m_cursor->FetchNext();
+ db_event_delete(m_currEvent);
+}
+
+MEVENT DB::ECPTR::FetchNext()
+{
+ if (m_prevFetched != -1) {
+ m_currEvent = m_prevFetched;
+ m_prevFetched = -1;
+ }
+ else m_currEvent = m_cursor->FetchNext();
+
+ return m_currEvent;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// misc functions
+
+MIR_CORE_DLL(INT_PTR) db_free(DBVARIANT *dbv)
+{
+ return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->FreeVariant(dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_unset(MCONTACT hContact, const char *szModule, const char *szSetting)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ return g_pCurrDb->DeleteContactSetting(hContact, szModule, szSetting);
+}
+
+MIR_CORE_DLL(DBCachedContact*) db_get_contact(MCONTACT hContact)
+{
+ return (g_pCurrDb == nullptr) ? nullptr : g_pCurrDb->getCache()->GetCachedContact(hContact);
+}
+
+MIR_CORE_DLL(MCONTACT) db_find_first(const char *szProto)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstContact(szProto);
+}
+
+MIR_CORE_DLL(MCONTACT) db_find_next(MCONTACT hContact, const char *szProto)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindNextContact(hContact, szProto);
+}
+
+MIR_CORE_DLL(void) db_setCurrent(MDatabaseCommon *_db)
+{
+ g_pCurrDb = _db;
+ if (g_pCurrDb == nullptr)
+ return;
+
+ // try to get the langpack's name from a profile
+ ptrW langpack(db_get_wsa(0, "Langpack", "Current"));
+ if (langpack && langpack[0] != '\0')
+ LoadLangPack(langpack);
+ else
+ GetDefaultLang();
+}
+
+MIR_CORE_DLL(BOOL) db_set_resident(const char *szModule, const char *szService, BOOL bEnable)
+{
+ if (g_pCurrDb == nullptr || szModule == nullptr || szService == nullptr)
+ return FALSE;
+
+ char str[MAXMODULELABELLENGTH * 2];
+ mir_snprintf(str, "%s/%s", szModule, szService);
+ return g_pCurrDb->SetSettingResident(bEnable, str);
+}