From c5be633b829e83a308eb9537e67d3318ec86b084 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 15 Jun 2022 15:34:07 +0300 Subject: UInfoEx: - fix for custom page trees; - random crash fix; - code cleaning --- plugins/UserInfoEx/src/classPsTree.cpp | 76 ++-- plugins/UserInfoEx/src/classPsTreeItem.cpp | 145 ++++--- plugins/UserInfoEx/src/dlg_propsheet.cpp | 2 +- plugins/UserInfoEx/src/dlg_propsheet.h | 26 +- plugins/UserInfoEx/src/psp_base.cpp | 1 + plugins/UserInfoEx/src/psp_profile.cpp | 610 +++++++++++++---------------- plugins/UserInfoEx/src/version.h | 2 +- 7 files changed, 397 insertions(+), 465 deletions(-) (limited to 'plugins/UserInfoEx/src') diff --git a/plugins/UserInfoEx/src/classPsTree.cpp b/plugins/UserInfoEx/src/classPsTree.cpp index 3b486b8955..b31247fe1d 100644 --- a/plugins/UserInfoEx/src/classPsTree.cpp +++ b/plugins/UserInfoEx/src/classPsTree.cpp @@ -51,8 +51,7 @@ CPsTree::CPsTree(LPPS pPs) : **/ CPsTree::~CPsTree() { - if (_hLabelEdit) - { + if (_hLabelEdit) { DestroyWindow(_hLabelEdit); _hLabelEdit = nullptr; } @@ -105,10 +104,10 @@ uint8_t CPsTree::Create(HWND hWndTree, CPsHdr* pPsh) * return: index of the new item or -1 if failed to add **/ -int CPsTree::AddDummyItem(LPCSTR pszGroup) +CPsTreeItem* CPsTree::AddDummyItem(const char *pszGroup) { if (!mir_strcmpi(pszGroup, TREE_ROOTITEM)) - return -1; + return nullptr; CPsHdr psh; psh._hContact = _pPs->hContact; @@ -118,12 +117,13 @@ int CPsTree::AddDummyItem(LPCSTR pszGroup) USERINFOPAGE uip = {}; uip.flags = ODPF_UNICODE; uip.szTitle.w = mir_utf8decodeW(pszGroup); + uip.pPlugin = &g_plugin; auto *p = new CPsTreeItem(); p->Create(&psh, &uip); _pages.insert(p); - return _pages.indexOf(&p); + return p; } void CPsTree::Remove(HINSTANCE hInst) @@ -171,16 +171,17 @@ uint8_t CPsTree::InitTreeItems(LPWORD needWidth) SetWindowLongPtr(_hWndTree, GWL_STYLE, GetWindowLongPtr(_hWndTree, GWL_STYLE) | TVS_HASBUTTONS); // init the iParent member for all the items - for (auto &it : _pages) { - LPSTR pszGroup = it->ParentItemName(); + for (int i = 0; i < _pages.getCount(); i++) { + auto &it = _pages[i]; + char *pszGroup = it.ParentItemName(); if (pszGroup != nullptr) { - int iParent = FindItemIndexByName(pszGroup); + auto *pParent = FindItemByName(pszGroup); // need to add an empty parent item - if (iParent == -1) - iParent = AddDummyItem(pszGroup); + if (pParent == nullptr) + pParent = AddDummyItem(pszGroup); - it->Parent(iParent); + it.Parent(pParent); mir_free(pszGroup); } } @@ -192,7 +193,7 @@ uint8_t CPsTree::InitTreeItems(LPWORD needWidth) ShowWindow(_hWndTree, SW_HIDE); for (auto &it : _pages) if (it->State() != DBTVIS_INVISIBLE) - ShowItem(_pages.indexOf(&it), needWidth); + ShowItem(it, needWidth); ShowWindow(_hWndTree, SW_SHOW); return TRUE; @@ -335,52 +336,45 @@ void CPsTree::HideItem(const int iPageIndex) * needWidth - gives and takes the width, the treeview must have to show all items properly * return: TRUE if item was added successfully, FALSE otherwise **/ -HTREEITEM CPsTree::ShowItem(const int iPageIndex, LPWORD needWidth) +HTREEITEM CPsTree::ShowItem(CPsTreeItem *pti, LPWORD needWidth) { TVINSERTSTRUCT tvii; - CPsTreeItem *pti; // check parameters - if (!_hWndTree || - !IsIndexValid(iPageIndex) || - !(pti = &_pages[iPageIndex]) || - !pti->Name() || - !pti->Label()) - { + if (!_hWndTree || !pti->Name() || !pti->Label()) { MsgErr(GetParent(_hWndTree), LPGENW("Due to a parameter error, one of the treeitems can't be added!")); return nullptr; } + // item is visible at the moment - if ((tvii.itemex.hItem = pti->Hti()) == nullptr) - { - RECT rc; - const int iParent = pti->Parent(); + if ((tvii.itemex.hItem = pti->Hti()) == nullptr) { + auto *pParent = pti->Parent(); // init the rest of the treeitem - tvii.hParent = IsIndexValid(iParent) ? ShowItem(iParent, needWidth) : nullptr; - tvii.hInsertAfter = (_dwFlags & PSTVF_SORTTREE) ? TVI_SORT : TVI_LAST; - tvii.itemex.mask = TVIF_TEXT|TVIF_PARAM|TVIF_STATE; - tvii.itemex.pszText = pti->Label(); - tvii.itemex.state = pti->State() == DBTVIS_EXPANDED ? TVIS_EXPANDED : 0; - tvii.itemex.stateMask = TVIS_EXPANDED; - tvii.itemex.lParam = iPageIndex; + tvii.hParent = (pParent) ? ShowItem(pParent, needWidth) : nullptr; + tvii.hInsertAfter = (_dwFlags & PSTVF_SORTTREE) ? TVI_SORT : TVI_LAST; + tvii.itemex.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE; + tvii.itemex.pszText = pti->Label(); + tvii.itemex.state = pti->State() == DBTVIS_EXPANDED ? TVIS_EXPANDED : 0; + tvii.itemex.stateMask = TVIS_EXPANDED; + tvii.itemex.lParam = _pages.indexOf(pti); + // set images if ((tvii.itemex.iImage = tvii.itemex.iSelectedImage = pti->Image()) != -1) - { - tvii.itemex.mask |= TVIF_IMAGE|TVIF_SELECTEDIMAGE; - } + tvii.itemex.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE; + // insert item into tree if set visible - if ((tvii.itemex.hItem = TreeView_InsertItem(_hWndTree, &tvii)) == nullptr) - { + if ((tvii.itemex.hItem = TreeView_InsertItem(_hWndTree, &tvii)) == nullptr) { MsgErr(GetParent(_hWndTree), LPGENW("A fatal error occurred on adding a property sheet page!\nDialog creation aborted!")); return nullptr; } + pti->Hti(tvii.itemex.hItem); + // calculate width of treeview + RECT rc; if (needWidth && TreeView_GetItemRect(_hWndTree, pti->Hti(), &rc, TRUE) && rc.right > *needWidth) - { *needWidth = (uint16_t)rc.right; - } } return tvii.itemex.hItem; } @@ -457,7 +451,7 @@ HTREEITEM CPsTree::MoveItem(HTREEITEM hItem, HTREEITEM hInsertAfter, uint8_t bAs // update handle pointer in the page structure pItem.Hti(hNewItem); // get the index of the parent - pItem.Parent(FindItemIndexByHandle(tvis.hParent)); + pItem.Parent(FindItemByHandle(tvis.hParent)); // move children hInsertAfter = hNewItem; while (hChild = TreeView_GetChild(_hWndTree, hItem)) @@ -524,7 +518,7 @@ void CPsTree::SaveState() if (!it->Hti()) { LPSTR pszGroup; - if (!IsIndexValid(it->Parent()) || !(pszGroup = _pages[it->Parent()].Name())) + if (!it->Parent() || !(pszGroup = it->Parent()->Name())) pszGroup = TREE_ROOTITEM; numErrors += it->DBSaveItemState(pszGroup, iItem++, DBTVIS_INVISIBLE, _dwFlags); } @@ -775,7 +769,7 @@ void CPsTree::PopupMenu() DBResetState(); break; default: // show a hidden item - if ((iItem -= 100) >= 0 && ShowItem(iItem, nullptr)) + if ((iItem -= 100) >= 0 && ShowItem(&_pages[iItem], nullptr)) AddFlags(PSTVF_STATE_CHANGED | PSTVF_POS_CHANGED); break; } diff --git a/plugins/UserInfoEx/src/classPsTreeItem.cpp b/plugins/UserInfoEx/src/classPsTreeItem.cpp index 189d9fd9a1..d7971444cd 100644 --- a/plugins/UserInfoEx/src/classPsTreeItem.cpp +++ b/plugins/UserInfoEx/src/classPsTreeItem.cpp @@ -159,19 +159,16 @@ LPSTR CPsTreeItem::ParentItemName() * bIsUnicode - if TRUE the title is unicode * return: 0 on success, 1 to 4 indicating the failed operation **/ -int CPsTreeItem::Name(LPTSTR ptszTitle, const uint8_t bIsUnicode) +int CPsTreeItem::Name(const wchar_t *ptszTitle, bool bIsUnicode) { // convert title to utf8 _pszName = (bIsUnicode) ? mir_utf8encodeW((LPWSTR)ptszTitle) : mir_utf8encode((LPSTR)ptszTitle); - if (_pszName) - { + if (_pszName) { // convert disallowed characters - for (uint32_t i = 0; _pszName[i] != 0; i++) - { - switch (_pszName[i]) - { - case '{': _pszName[i] = '('; break; - case '}': _pszName[i] = ')'; break; + for (uint32_t i = 0; _pszName[i] != 0; i++) { + switch (_pszName[i]) { + case '{': _pszName[i] = '('; break; + case '}': _pszName[i] = ')'; break; } } } @@ -225,28 +222,21 @@ void CPsTreeItem::Rename(const LPTSTR pszLabel) * param: pszName - uniquely identifiing string for a propertypage encoded with utf8 (e.g.: {group\item}) * return: Label in a newly allocated piece of memory **/ -int CPsTreeItem::ItemLabel(const uint8_t bReadDBValue) +int CPsTreeItem::ItemLabel(bool bReadDBValue) { - DBVARIANT dbv; - - // clear existing - if (_ptszLabel) - mir_free(_ptszLabel); - // try to get custom label from database + DBVARIANT dbv; if (!bReadDBValue || DB::Setting::GetWString(0, MODULENAME, GlobalPropertyKey(SET_ITEM_LABEL), &dbv) || (_ptszLabel = dbv.pwszVal) == nullptr) { // extract the name - LPSTR pszName = mir_strrchr(_pszName, '\\'); + char *pszName = mir_strrchr(_pszName, '\\'); if (pszName && pszName[1]) pszName++; else pszName = _pszName; - LPTSTR ptszLabel = mir_utf8decodeW(pszName); - if (ptszLabel) { - _ptszLabel = mir_wstrdup(TranslateW(ptszLabel)); - mir_free(ptszLabel); - } + ptrW ptszLabel(mir_utf8decodeW(pszName)); + if (ptszLabel) + replaceStrW(_ptszLabel, TranslateW(ptszLabel)); } // return nonezero if label is invalid return _ptszLabel == nullptr; @@ -287,7 +277,7 @@ HICON CPsTreeItem::ProtoIcon() * hDefaultIcon - default icon to use * return: nothing **/ -int CPsTreeItem::Icon(HIMAGELIST hIml, USERINFOPAGE *uip, uint8_t bInitIconsOnly) +int CPsTreeItem::Icon(HIMAGELIST hIml, USERINFOPAGE *uip, bool bInitIconsOnly) { // check parameter if (!_pszName || !uip) @@ -366,68 +356,65 @@ int CPsTreeItem::Icon(HIMAGELIST hIml, USERINFOPAGE *uip, uint8_t bInitIconsOnly * odp - USERINFOPAGE structure with the information about the page to add * return: 0 on success, 1 on failure **/ -int CPsTreeItem::Create(CPsHdr* pPsh, USERINFOPAGE *uip) +int CPsTreeItem::Create(CPsHdr *pPsh, USERINFOPAGE *uip) { - int err; - wchar_t szTitle[ MAXSETTING ]; - // check parameter - if (pPsh && uip && PtrIsValid(uip->pPlugin)) { - // instance value - _hInst = uip->pPlugin->getInst(); - _dwFlags = uip->flags; - _initParam = uip->dwInitParam; - - // init page owning contact - _hContact = pPsh->_hContact; - _pszProto = mir_strdup(pPsh->_pszProto); - - // global settings prefix for current contact (is dialog owning contact's protocol by default) - _pszPrefix = (pPsh->_pszPrefix) ? pPsh->_pszPrefix : "Owner"; - - if (pPsh->_dwFlags & PSF_PROTOPAGESONLY) { - if (_dwFlags & ODPF_USERINFOTAB) - mir_snwprintf(szTitle, L"%s %d\\%s", uip->szTitle.w, pPsh->_nSubContact+1, uip->szGroup.w); - else - mir_snwprintf(szTitle, L"%s %d", uip->szTitle.w, pPsh->_nSubContact+1); - } - else { - if (_dwFlags & ODPF_USERINFOTAB) - mir_snwprintf(szTitle, L"%s\\%s", uip->szTitle.w, uip->szGroup.w); - else - mir_wstrcpy(szTitle, uip->szTitle.w); - } - // set the unique utf8 encoded name for the item - if (err = Name(szTitle, (_dwFlags & ODPF_UNICODE) == ODPF_UNICODE)) - MsgErr(nullptr, LPGENW("Creating unique name for a page failed with %d and error code %d"), err, GetLastError()); + if (!pPsh || !uip || !PtrIsValid(uip->pPlugin)) + return 1; - // read label from database or create it - else if (err = ItemLabel(TRUE)) - MsgErr(nullptr, LPGENW("Creating the label for a page failed with %d and error code %d"), err, GetLastError()); + // instance value + _hInst = uip->pPlugin->getInst(); + _dwFlags = uip->flags; + _initParam = uip->dwInitParam; - else { - // load icon for the item - Icon(pPsh->_hImages, uip, (pPsh->_dwFlags & PSTVF_INITICONS) == PSTVF_INITICONS); - - // the rest is not needed if only icons are loaded - if (pPsh->_dwFlags & PSTVF_INITICONS) - return 0; - - // load custom order - if (!(pPsh->_dwFlags & PSTVF_SORTTREE)) { - _iPosition = g_plugin.getByte(PropertyKey(SET_ITEM_POS), uip->position); - if ((_iPosition < 0) || (_iPosition > 0x800000A)) - _iPosition = 0; - } - // read visibility state - _bState = g_plugin.getByte(PropertyKey(SET_ITEM_STATE), DBTVIS_EXPANDED); + // init page owning contact + _hContact = pPsh->_hContact; + _pszProto = mir_strdup(pPsh->_pszProto); - // fetch dialog - _pDialog = uip->pDialog; - return 0; - } + // global settings prefix for current contact (is dialog owning contact's protocol by default) + _pszPrefix = (pPsh->_pszPrefix) ? pPsh->_pszPrefix : "Owner"; + + CMStringW wszTitle; + if (_dwFlags & ODPF_USERINFOTAB) { + wszTitle.Append(uip->szGroup.w); + wszTitle.AppendChar('\\'); + } + + wszTitle.Append(uip->szTitle.w); + if (pPsh->_dwFlags & PSF_PROTOPAGESONLY) + wszTitle.AppendFormat(L" %d", pPsh->_nSubContact + 1); + + // set the unique utf8 encoded name for the item + if (int err = Name(wszTitle, (_dwFlags & ODPF_UNICODE) == ODPF_UNICODE)) { + MsgErr(nullptr, LPGENW("Creating unique name for a page failed with %d and error code %d"), err, GetLastError()); + return 1; + } + + // read label from database or create it + if (int err = ItemLabel(TRUE)) { + MsgErr(nullptr, LPGENW("Creating the label for a page failed with %d and error code %d"), err, GetLastError()); + return 1; } - return 1; + + // load icon for the item + Icon(pPsh->_hImages, uip, (pPsh->_dwFlags & PSTVF_INITICONS) == PSTVF_INITICONS); + + // the rest is not needed if only icons are loaded + if (pPsh->_dwFlags & PSTVF_INITICONS) + return 0; + + // load custom order + if (!(pPsh->_dwFlags & PSTVF_SORTTREE)) { + _iPosition = g_plugin.getByte(PropertyKey(SET_ITEM_POS), uip->position); + if ((_iPosition < 0) || (_iPosition > 0x800000A)) + _iPosition = 0; + } + // read visibility state + _bState = g_plugin.getByte(PropertyKey(SET_ITEM_STATE), DBTVIS_EXPANDED); + + // fetch dialog + _pDialog = uip->pDialog; + return 0; } /** diff --git a/plugins/UserInfoEx/src/dlg_propsheet.cpp b/plugins/UserInfoEx/src/dlg_propsheet.cpp index e254162217..cdfcb19319 100644 --- a/plugins/UserInfoEx/src/dlg_propsheet.cpp +++ b/plugins/UserInfoEx/src/dlg_propsheet.cpp @@ -335,7 +335,7 @@ static INT_PTR AddPage(WPARAM wParam, LPARAM lParam) CPsTreeItem *pNew = new CPsTreeItem(); if (pNew) { if (pNew->Create(pPsh, uip)) { - MIR_DELETE(pNew); + delete pNew; return 1; } diff --git a/plugins/UserInfoEx/src/dlg_propsheet.h b/plugins/UserInfoEx/src/dlg_propsheet.h index 615c98102b..824fa48868 100644 --- a/plugins/UserInfoEx/src/dlg_propsheet.h +++ b/plugins/UserInfoEx/src/dlg_propsheet.h @@ -39,22 +39,22 @@ class CPsTreeItem uint32_t _dwFlags = 0; // some flags int _iPosition = 0; // initiating position if custom (used for sorting) MCONTACT _hContact = 0; // contact the page is accociated with (may be a meta subcontact if details dialog is shown for a meta contact) - LPCSTR _pszProto = 0; // protocol the page is accociated with (is the contact's protocol if _hContact is not NULL) - LPCSTR _pszPrefix = 0; // pointer to the dialog owning contact's protocol + const char* _pszProto = 0; // protocol the page is accociated with (is the contact's protocol if _hContact is not NULL) + const char* _pszPrefix = 0; // pointer to the dialog owning contact's protocol INT_PTR _initParam = 0; HTREEITEM _hItem = 0; // handle to the treeview item if visible (NULL if this item is hidden) - int _iParent = -1; // index of the owning tree item + CPsTreeItem* _pParent = 0; // owning tree item int _iImage = -1; // index of treeview item's image uint8_t _bState = 0; // initial state of this treeitem - LPSTR _pszName = 0; // original name, given by plugin (not customized) - LPTSTR _ptszLabel= 0; // string to setting in db holding information about this treeitem + char* _pszName = 0; // original name, given by plugin (not customized) + wchar_t* _ptszLabel = 0; // string to setting in db holding information about this treeitem - LPCSTR GlobalName(); + LPCSTR GlobalName(); - int Icon(HIMAGELIST hIml, USERINFOPAGE *uip, uint8_t bInitIconsOnly); - int ItemLabel(const uint8_t bReadDBValue); - int Name(LPTSTR pszTitle, const uint8_t bIsUnicode); + int Icon(HIMAGELIST hIml, USERINFOPAGE *uip, bool bInitIconsOnly); + int ItemLabel(bool bReadDBValue); + int Name(const wchar_t *pszTitle, bool bIsUnicode); HICON ProtoIcon(); public: @@ -79,8 +79,8 @@ public: __inline uint8_t State() const { return _bState; } __inline HTREEITEM Hti() const { return _hItem; } __inline void Hti(HTREEITEM hti) { _hItem = hti; } - __inline int Parent() const { return _iParent; } - __inline void Parent(const int iParent) { _iParent = iParent; } + __inline CPsTreeItem* Parent() const { return _pParent; } + __inline void Parent(CPsTreeItem *pParent) { _pParent = pParent; } __inline uint32_t Flags() const { return _dwFlags; } __inline void Flags(uint32_t dwFlags) { _dwFlags = dwFlags; } @@ -172,13 +172,13 @@ public: __inline int CurrentItemIndex() const { return _curItem; }; __inline CPsTreeItem* CurrentItem() const { return TreeItem(CurrentItemIndex()); }; - int AddDummyItem(LPCSTR pszGroup); + CPsTreeItem* AddDummyItem(const char *pszGroup); uint8_t Create(HWND hWndTree, CPsHdr *pPsh); uint8_t InitTreeItems(LPWORD needWidth); void Remove(HINSTANCE); void HideItem(const int iPageIndex); - HTREEITEM ShowItem(const int iPageIndex, LPWORD needWidth); + HTREEITEM ShowItem(CPsTreeItem *pti, LPWORD needWidth); HTREEITEM MoveItem(HTREEITEM hItem, HTREEITEM hInsertAfter, uint8_t bAsChild = FALSE); void SaveState(); diff --git a/plugins/UserInfoEx/src/psp_base.cpp b/plugins/UserInfoEx/src/psp_base.cpp index 0737807bcc..fe05560a4b 100644 --- a/plugins/UserInfoEx/src/psp_base.cpp +++ b/plugins/UserInfoEx/src/psp_base.cpp @@ -33,6 +33,7 @@ PSPBaseDlg::PSPBaseDlg(int idDialog) : CUserInfoPageDlg(g_plugin, idDialog), m_ctrlList(nullptr) { + m_bFixedSize = true; } bool PSPBaseDlg::OnInitDialog() diff --git a/plugins/UserInfoEx/src/psp_profile.cpp b/plugins/UserInfoEx/src/psp_profile.cpp index 38ee787e90..78acc56f4d 100644 --- a/plugins/UserInfoEx/src/psp_profile.cpp +++ b/plugins/UserInfoEx/src/psp_profile.cpp @@ -198,13 +198,12 @@ static void ProfileList_Clear(HWND hList) **/ static int ProfileList_EndLabelEdit(LPLISTCTRL pList, uint8_t bSave) { - HWND hEdit; - // check if labeledit is enabled - if (!PtrIsValid(pList) || !pList->hList || !pList->labelEdit.hEdit) + if (!pList->hList || !pList->labelEdit.hEdit) return 1; + // set hEdit NULL to indicate the endlabeledit call and prevent other calls - hEdit = pList->labelEdit.hEdit; + HWND hEdit = pList->labelEdit.hEdit; pList->labelEdit.hEdit = nullptr; if (bSave != FALSE && pList->labelEdit.pItem) { @@ -257,11 +256,6 @@ static int ProfileList_EndLabelEdit(LPLISTCTRL pList, uint8_t bSave) return 0; } -static int ProfileList_EndLabelEdit(HWND hList, uint8_t bSave) -{ - return ProfileList_EndLabelEdit((LPLISTCTRL)GetUserData(hList), bSave); -} - /** * name: ProfileList_BeginLabelEdit * desc: create an edit control to edit the label of the selected item @@ -272,16 +266,10 @@ static int ProfileList_EndLabelEdit(HWND hList, uint8_t bSave) **/ static HWND ProfileList_BeginLabelEdit(LPLISTCTRL pList, int iItem, int iSubItem) { - LVITEM lvi; - LPLCITEM pItem; - MCONTACT m_hContact; - RECT rcList; - - if (!PtrIsValid(pList)) - return nullptr; if (pList->labelEdit.hEdit) ProfileList_EndLabelEdit(pList, FALSE); + LVITEM lvi; lvi.mask = LVIF_PARAM | LVIF_STATE; lvi.stateMask = 0xFFFFFFFF; lvi.iItem = iItem; @@ -290,12 +278,13 @@ static HWND ProfileList_BeginLabelEdit(LPLISTCTRL pList, int iItem, int iSubItem if (!ListView_GetItem(pList->hList, &lvi)) return nullptr; - pItem = (LPLCITEM)lvi.lParam; + LPLCITEM pItem = (LPLCITEM)lvi.lParam; - PSGetContact(GetParent(pList->hList), m_hContact); + MCONTACT hContact; + PSGetContact(GetParent(pList->hList), hContact); // do not edit deviders or protocol based contact information - if (!(lvi.state & LVIS_SELECTED) || !PtrIsValid(pItem) || (m_hContact && (pItem->wFlags & CTRLF_HASPROTO))) + if (!(lvi.state & LVIS_SELECTED) || !PtrIsValid(pItem) || (hContact && (pItem->wFlags & CTRLF_HASPROTO))) return nullptr; ListView_EnsureVisible(pList->hList, iItem, FALSE); @@ -307,6 +296,8 @@ static HWND ProfileList_BeginLabelEdit(LPLISTCTRL pList, int iItem, int iSubItem ListView_GetSubItemRect(pList->hList, iItem, 1, LVIR_BOUNDS, &rc2); pList->labelEdit.rcCombo.right = rc2.left; } + + RECT rcList; GetClientRect(pList->hList, &rcList); pList->labelEdit.rcCombo.right = min(pList->labelEdit.rcCombo.right, rcList.right); pList->labelEdit.rcCombo.left = max(pList->labelEdit.rcCombo.left, rcList.left); @@ -357,19 +348,6 @@ static HWND ProfileList_BeginLabelEdit(LPLISTCTRL pList, int iItem, int iSubItem return pList->labelEdit.hEdit; } -/** - * name: ProfileList_BeginLabelEdit - * desc: create an edit control to edit the label of the selected item - * param: hList - handle to listview control - * iItem - item index - * iSubItem - subitem (column) index - * return: handle to the edit control - **/ -static HWND ProfileList_BeginLabelEdit(HWND hList, int iItem, int iSubItem) -{ - return ProfileList_BeginLabelEdit((LPLISTCTRL)GetUserData(hList), iItem, iSubItem); -} - /** * name: ProfileList_GetInsertIndex * desc: finds index to add the new item to and adds an devider if necessary @@ -411,148 +389,6 @@ static int ProfileList_GetInsertIndex(HWND hList, LPTSTR pszGroup) return iItem; } -/** - * name: ProfileList_AddNewItem - * desc: Ask's user for a type and adds new item to the list view - * param: pList - pointer to the listview's data structure - * pszList - database settings string, that identifies this category - * - * return: TRUE or FALSE - **/ -static uint8_t ProfileList_AddNewItem(HWND hDlg, LPLISTCTRL pList, const PROFILEENTRY *pEntry) -{ - LPLCITEM pItem; - LVITEM lvi; - MCONTACT m_hContact; - - if (PtrIsValid(pList) && (pItem = (LPLCITEM)mir_alloc(sizeof(LCITEM)))) { - PSGetContact(hDlg, m_hContact); - pItem->nType = CTRL_LIST_ITEM; - pItem->wFlags = m_hContact ? CTRLF_HASCUSTOM : 0; - pItem->iListItem = 0; - pItem->pszText[0] = nullptr; - pItem->pszText[1] = nullptr; - // get category list - pEntry->GetList((WPARAM)&pItem->idstrListCount, (LPARAM)&pItem->idstrList); - - lvi.mask = LVIF_PARAM | LVIF_STATE; - lvi.stateMask = 0xFFFFFFFF; - lvi.state = LVIS_FOCUSED | LVIS_SELECTED; - lvi.iItem = ProfileList_GetInsertIndex(pList->hList, pEntry->szGroup); - lvi.iSubItem = 0; - lvi.lParam = (LPARAM)pItem; - if ((lvi.iItem = ListView_InsertItem(pList->hList, &lvi)) >= 0) { - ProfileList_BeginLabelEdit(pList, lvi.iItem, 0); - return TRUE; - } - mir_free(pItem); - MsgErr(hDlg, LPGENW("Sorry, but there is a problem with adding a new item of type \"%s\""), pEntry->szGroup); - } - return FALSE; -} - -/** - * name: ProfileList_AddItemlistFromDB - * desc: reads an zero based indexed szList from the database of hContacts pszModule and fills a hList - * param: hList - HANDLE to the list to fill with two columns - * iItem - index of new listviewitem - * iImage - image to draw from a imagelist associated with the listview - * m_hContact - handle to the contact, whose information are read - * pszModule - the module the information are stored in - * szCatFormat - name of a database setting that holds the categorytext - * szValFormat - name of a database setting that holds the valuetext - * wFlags - flags to set for a new allocated item - * - * return number of added rows or -1 if listview's changed flag is set - **/ -static int ProfileList_AddItemlistFromDB( - LPLISTCTRL pList, - int &iItem, - LPIDSTRLIST idList, - UINT nList, - MCONTACT m_hContact, - LPCSTR pszModule, - LPCSTR szCatFormat, - LPCSTR szValFormat, - uint16_t wFlags) -{ - DBVARIANT dbvVal, dbvCat; - LPLCITEM pItem; - LVITEM lvi; - UINT i, j = 0; - CHAR pszSetting[MAXSETTING]; - - lvi.iSubItem = 0; - lvi.mask = LVIF_PARAM; - - for (i = 0, lvi.iItem = iItem; ; i++) { - // read the setting from db - mir_snprintf(pszSetting, szValFormat, i); - if (DB::Setting::GetWString(m_hContact, pszModule, pszSetting, &dbvVal)) - break; - if (dbvVal.type != DBVT_WCHAR) - continue; - mir_snprintf(pszSetting, szCatFormat, i); - DB::Setting::GetAString(m_hContact, pszModule, pszSetting, &dbvCat); - // create the itemobject - if (!(pItem = (LPLCITEM)mir_alloc(sizeof(LCITEM)))) { - db_free(&dbvCat); - db_free(&dbvVal); - break; - } - // fill item struct - pItem->nType = CTRL_LIST_ITEM; - pItem->idstrList = idList; - pItem->idstrListCount = nList; - pItem->iListItem = 0; - pItem->pszText[0] = nullptr; - pItem->pszText[1] = dbvVal.pwszVal; - pItem->wFlags = wFlags; - lvi.lParam = (LPARAM)pItem; - - // get id-str-list-item for the category string - if (idList != nullptr) { - for (j = 0; j < nList; j++) { - switch (dbvCat.type) { - case DBVT_BYTE: - if (dbvCat.bVal != (uint8_t)idList[j].nID) - continue; - break; - case DBVT_WORD: - if (dbvCat.wVal != (uint16_t)idList[j].nID) - continue; - break; - case DBVT_DWORD: - if (dbvCat.dVal != (uint32_t)idList[j].nID) - continue; - break; - case DBVT_ASCIIZ: - if (mir_strcmp(dbvCat.pszVal, idList[j].pszText)) - continue; - break; - } - pItem->iListItem = j; - break; - } - } - // item not found in the predefined category list? - if ((idList == nullptr || j == nList) && dbvCat.type == DBVT_ASCIIZ) { - pItem->pszText[0] = mir_a2u(dbvCat.pszVal); - db_free(&dbvCat); - } - if ((lvi.iItem = ListView_InsertItem(pList->hList, &lvi)) < 0) { - mir_free(pItem); - db_free(&dbvCat); - db_free(&dbvVal); - break; - } - lvi.iItem++; - dbvCat.type = dbvVal.type = DBVT_DELETED; - } - iItem = lvi.iItem; - return i; -} - /** * name: ProfileList_DropdownProc * desc: procedure to catch messages for a listbox control for my own combobox @@ -613,7 +449,7 @@ static LRESULT CALLBACK ProfileList_DropdownProc(HWND hwnd, UINT msg, WPARAM wPa else pList->labelEdit.dropDown.iItem = -1; - ProfileList_EndLabelEdit(pList->hList, TRUE); + ProfileList_EndLabelEdit(pList, TRUE); return 0; } case WM_KILLFOCUS: @@ -654,24 +490,20 @@ static LRESULT CALLBACK ProfileList_LabelEditProc(HWND hwnd, UINT msg, WPARAM wP SendMessage(pList->hList, WM_COMMAND, MAKEWPARAM(BTN_EDIT, BN_CLICKED), (LPARAM)pList->labelEdit.hBtn); return 0; case VK_RETURN: - { - uint8_t bEditNext; - int iItem; - - if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_WANTRETURN && !(GetKeyState(VK_CONTROL) & 0x8000)) - break; - if (PtrIsValid(pList = (LPLISTCTRL)GetUserData(hwnd))) { - bEditNext = !pList->labelEdit.iSubItem && !ProfileList_GetItemText(pList->hList, pList->labelEdit.iItem, 1, nullptr, NULL); - iItem = pList->labelEdit.iItem; - ProfileList_EndLabelEdit(pList->hList, TRUE); - if (bEditNext) ProfileList_BeginLabelEdit(pList->hList, pList->labelEdit.iItem, 1); - } - return 0; + if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_WANTRETURN && !(GetKeyState(VK_CONTROL) & 0x8000)) + break; + + if (PtrIsValid(pList = (LPLISTCTRL)GetUserData(hwnd))) { + bool bEditNext = !pList->labelEdit.iSubItem && !ProfileList_GetItemText(pList->hList, pList->labelEdit.iItem, 1, nullptr, NULL); + ProfileList_EndLabelEdit(pList, TRUE); + if (bEditNext) + ProfileList_BeginLabelEdit(pList, pList->labelEdit.iItem, 1); } + return 0; + case VK_TAB: if (PtrIsValid(pList = (LPLISTCTRL)GetUserData(hwnd))) { LVITEM lvi; - lvi.mask = LVIF_STATE; lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED; lvi.iItem = pList->labelEdit.iItem; @@ -679,11 +511,9 @@ static LRESULT CALLBACK ProfileList_LabelEditProc(HWND hwnd, UINT msg, WPARAM wP if (!pList->labelEdit.iSubItem) { lvi.iSubItem = 1; lvi.state = LVIS_FOCUSED | LVIS_SELECTED; - ProfileList_EndLabelEdit(pList->hList, TRUE); + ProfileList_EndLabelEdit(pList, TRUE); } else { - UINT iSubItem = 0; - lvi.iSubItem = 0; lvi.state = 0; @@ -694,11 +524,10 @@ static LRESULT CALLBACK ProfileList_LabelEditProc(HWND hwnd, UINT msg, WPARAM wP return 0; // search for next valid list item (skip deviders) - lvi.iSubItem = iSubItem; + lvi.iSubItem = 0; lvi.mask = LVIF_PARAM; do { lvi.iItem++; - if (lvi.iItem == -1 || !ListView_GetItem(pList->hList, &lvi)) return 0; } @@ -710,26 +539,27 @@ static LRESULT CALLBACK ProfileList_LabelEditProc(HWND hwnd, UINT msg, WPARAM wP if (!ListView_SetItem(pList->hList, &lvi)) return 0; } - ProfileList_BeginLabelEdit(pList->hList, lvi.iItem, lvi.iSubItem); + ProfileList_BeginLabelEdit(pList, lvi.iItem, lvi.iSubItem); return 0; } return 1; } break; + case WM_GETDLGCODE: return DLGC_WANTALLKEYS | mir_callNextSubclass(hwnd, ProfileList_LabelEditProc, msg, wParam, lParam); + case WM_KILLFOCUS: - { - HWND hwndFocus = GetFocus(); + HWND hwndFocus = GetFocus(); - if (PtrIsValid(pList = (LPLISTCTRL)GetUserData(hwnd)) - && hwndFocus != pList->labelEdit.dropDown.hDrop - && hwndFocus != pList->labelEdit.hEdit - && hwndFocus != pList->labelEdit.hBtn) - ProfileList_EndLabelEdit(pList, hwndFocus == pList->hList); - return 0; - } + if (PtrIsValid(pList = (LPLISTCTRL)GetUserData(hwnd)) + && hwndFocus != pList->labelEdit.dropDown.hDrop + && hwndFocus != pList->labelEdit.hEdit + && hwndFocus != pList->labelEdit.hBtn) + ProfileList_EndLabelEdit(pList, hwndFocus == pList->hList); + return 0; } + return mir_callNextSubclass(hwnd, ProfileList_LabelEditProc, msg, wParam, lParam); } @@ -744,7 +574,7 @@ static LRESULT CALLBACK ProfileList_LabelEditProc(HWND hwnd, UINT msg, WPARAM wP **/ static LRESULT CALLBACK ProfileList_SubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - LPLISTCTRL pList; + LPLISTCTRL pList = (LPLISTCTRL)GetUserData(hwnd); LVHITTESTINFO hi; switch (msg) { @@ -758,13 +588,13 @@ static LRESULT CALLBACK ProfileList_SubclassProc(HWND hwnd, UINT msg, WPARAM wPa nCurSel = ListView_GetSelectionMark(hwnd); if (nCurSel == -1) break; - ProfileList_BeginLabelEdit(hwnd, nCurSel, 0); + ProfileList_BeginLabelEdit(pList, nCurSel, 0); return 0; case VK_F3: nCurSel = ListView_GetSelectionMark(hwnd); if (nCurSel == -1) break; - ProfileList_BeginLabelEdit(hwnd, nCurSel, 1); + ProfileList_BeginLabelEdit(pList, nCurSel, 1); return 0; case VK_UP: case VK_DOWN: @@ -796,10 +626,11 @@ static LRESULT CALLBACK ProfileList_SubclassProc(HWND hwnd, UINT msg, WPARAM wPa ListView_SetSelectionMark(hwnd, lvi.iItem); return 0; } - break; } + break; + case WM_MOUSEMOVE: - if (PtrIsValid(pList = (LPLISTCTRL)GetUserData(hwnd))) { + if (PtrIsValid(pList)) { RECT rchWnd, rcItem; SIZE textSize; @@ -872,13 +703,12 @@ static LRESULT CALLBACK ProfileList_SubclassProc(HWND hwnd, UINT msg, WPARAM wPa } return 0; - // begin label edit - case WM_LBUTTONDBLCLK: + case WM_LBUTTONDBLCLK: // begin label edit { hi.pt.x = GET_X_LPARAM(lParam); hi.pt.y = GET_Y_LPARAM(lParam); if (ListView_SubItemHitTest(hwnd, &hi)) - ProfileList_BeginLabelEdit(hwnd, hi.iItem, hi.iSubItem); + ProfileList_BeginLabelEdit(pList, hi.iItem, hi.iSubItem); return TRUE; } @@ -902,75 +732,72 @@ static LRESULT CALLBACK ProfileList_SubclassProc(HWND hwnd, UINT msg, WPARAM wPa switch (LOWORD(wParam)) { // show dropdown menu for category list case BTN_EDIT: - { - int i; - wchar_t szEdit[MAX_PATH]; - - if (!PtrIsValid(pList = (LPLISTCTRL)GetUserData(hwnd))) - break; - GetWindowText(pList->labelEdit.hEdit, szEdit, _countof(szEdit)); - - // need to create the dropdown list? - if (pList->labelEdit.dropDown.hDrop == nullptr) { - const int listHeight = 120; - RECT rc, rcList; - int add; - - // dropdown rect - GetClientRect(pList->hList, &rcList); - rc.left = pList->labelEdit.rcCombo.left; - rc.right = pList->labelEdit.rcCombo.right + pList->labelEdit.rcCombo.bottom - pList->labelEdit.rcCombo.top; - - if (rcList.bottom < pList->labelEdit.rcCombo.bottom + listHeight) { - rc.bottom = pList->labelEdit.rcCombo.bottom - 7; // don't ask me why! - rc.top = rc.bottom - listHeight; - } - else { - rc.top = pList->labelEdit.rcCombo.bottom; - rc.bottom = rc.top + listHeight; - } + int i; + wchar_t szEdit[MAX_PATH]; - pList->labelEdit.dropDown.hDrop = CreateWindowEx(0, L"LISTBOX", nullptr, - WS_CHILD | WS_BORDER | WS_VSCROLL | LBS_COMBOBOX | LBS_HASSTRINGS, - rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - hwnd, nullptr, g_plugin.getInst(), nullptr); - if (!pList->labelEdit.dropDown.hDrop) - return FALSE; - SetUserData(pList->labelEdit.dropDown.hDrop, pList); - mir_subclassWindow(pList->labelEdit.dropDown.hDrop, ProfileList_DropdownProc); - SetWindowLongPtr(pList->labelEdit.dropDown.hDrop, GWLP_ID, LIST_DROPDOWN); - SendMessage(pList->labelEdit.dropDown.hDrop, WM_SETFONT, (WPARAM)SendMessage(GetParent(pList->hList), WM_GETFONT, 0, 0), 0); - - // add items - for (i = 0; i < pList->labelEdit.pItem->idstrListCount; i++) { - add = ListBox_AddString(pList->labelEdit.dropDown.hDrop, pList->labelEdit.pItem->idstrList[i].ptszTranslated); - ListBox_SetItemData(pList->labelEdit.dropDown.hDrop, add, pList->labelEdit.pItem->idstrList + i); - if (!mir_wstrcmp(szEdit, pList->labelEdit.pItem->idstrList[i].ptszTranslated)) - ListBox_SetCurSel(pList->labelEdit.dropDown.hDrop, add); - } + if (!PtrIsValid(pList = (LPLISTCTRL)GetUserData(hwnd))) + break; + GetWindowText(pList->labelEdit.hEdit, szEdit, _countof(szEdit)); + + // need to create the dropdown list? + if (pList->labelEdit.dropDown.hDrop == nullptr) { + const int listHeight = 120; + RECT rc, rcList; + int add; + + // dropdown rect + GetClientRect(pList->hList, &rcList); + rc.left = pList->labelEdit.rcCombo.left; + rc.right = pList->labelEdit.rcCombo.right + pList->labelEdit.rcCombo.bottom - pList->labelEdit.rcCombo.top; + + if (rcList.bottom < pList->labelEdit.rcCombo.bottom + listHeight) { + rc.bottom = pList->labelEdit.rcCombo.bottom - 7; // don't ask me why! + rc.top = rc.bottom - listHeight; } else { - LPIDSTRLIST lpidList; - - i = 0; - while (PtrIsValid(lpidList = (LPIDSTRLIST)ListBox_GetItemData(pList->labelEdit.dropDown.hDrop, i))) { - if (!mir_wstrcmp(szEdit, lpidList->ptszTranslated)) { - ListBox_SetCurSel(pList->labelEdit.dropDown.hDrop, i); - break; - } - i++; - } - if (i == pList->labelEdit.pItem->idstrListCount) - ListBox_SetCurSel(pList->labelEdit.dropDown.hDrop, -1); + rc.top = pList->labelEdit.rcCombo.bottom; + rc.bottom = rc.top + listHeight; } - if (IsWindowVisible(pList->labelEdit.dropDown.hDrop)) { - SetFocus(pList->labelEdit.hEdit); + + pList->labelEdit.dropDown.hDrop = CreateWindowEx(0, L"LISTBOX", nullptr, + WS_CHILD | WS_BORDER | WS_VSCROLL | LBS_COMBOBOX | LBS_HASSTRINGS, + rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, + hwnd, nullptr, g_plugin.getInst(), nullptr); + if (!pList->labelEdit.dropDown.hDrop) + return FALSE; + SetUserData(pList->labelEdit.dropDown.hDrop, pList); + mir_subclassWindow(pList->labelEdit.dropDown.hDrop, ProfileList_DropdownProc); + SetWindowLongPtr(pList->labelEdit.dropDown.hDrop, GWLP_ID, LIST_DROPDOWN); + SendMessage(pList->labelEdit.dropDown.hDrop, WM_SETFONT, (WPARAM)SendMessage(GetParent(pList->hList), WM_GETFONT, 0, 0), 0); + + // add items + for (i = 0; i < pList->labelEdit.pItem->idstrListCount; i++) { + add = ListBox_AddString(pList->labelEdit.dropDown.hDrop, pList->labelEdit.pItem->idstrList[i].ptszTranslated); + ListBox_SetItemData(pList->labelEdit.dropDown.hDrop, add, pList->labelEdit.pItem->idstrList + i); + if (!mir_wstrcmp(szEdit, pList->labelEdit.pItem->idstrList[i].ptszTranslated)) + ListBox_SetCurSel(pList->labelEdit.dropDown.hDrop, add); } - else { - ShowWindow(pList->labelEdit.dropDown.hDrop, SW_SHOW); - //SetFocus(pList->labelEdit.dropDown.hDrop); + } + else { + LPIDSTRLIST lpidList; + + i = 0; + while (PtrIsValid(lpidList = (LPIDSTRLIST)ListBox_GetItemData(pList->labelEdit.dropDown.hDrop, i))) { + if (!mir_wstrcmp(szEdit, lpidList->ptszTranslated)) { + ListBox_SetCurSel(pList->labelEdit.dropDown.hDrop, i); + break; + } + i++; } - break; + if (i == pList->labelEdit.pItem->idstrListCount) + ListBox_SetCurSel(pList->labelEdit.dropDown.hDrop, -1); + } + if (IsWindowVisible(pList->labelEdit.dropDown.hDrop)) { + SetFocus(pList->labelEdit.hEdit); + } + else { + ShowWindow(pList->labelEdit.dropDown.hDrop, SW_SHOW); + //SetFocus(pList->labelEdit.dropDown.hDrop); } } break; @@ -1017,61 +844,187 @@ static LRESULT CALLBACK ProfileList_SubclassProc(HWND hwnd, UINT msg, WPARAM wPa * return: 0 or 1 **/ -struct PSPContactProfileDlg : public PSPBaseDlg +class PSPContactProfileDlg : public PSPBaseDlg { + CCtrlListView m_list; + + /** + * name: ProfileList_AddItemlistFromDB + * desc: reads an zero based indexed szList from the database of hContacts pszModule and fills a hList + * param: iItem - index of new listviewitem + * iImage - image to draw from a imagelist associated with the listview + * hContact - handle to the contact, whose information are read + * pszModule - the module the information are stored in + * szCatFormat - name of a database setting that holds the categorytext + * szValFormat - name of a database setting that holds the valuetext + * wFlags - flags to set for a new allocated item + * + * return number of added rows or -1 if listview's changed flag is set + **/ + + int ProfileList_AddItemlistFromDB( + int &iItem, + LPIDSTRLIST idList, + int nList, + MCONTACT hContact, + LPCSTR pszModule, + LPCSTR szCatFormat, + LPCSTR szValFormat, + uint16_t wFlags) + { + DBVARIANT dbvVal, dbvCat; + CHAR pszSetting[MAXSETTING]; + + LVITEM lvi; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + lvi.iItem = iItem; + + int i; + for (i = 0; ; i++) { + // read the setting from db + mir_snprintf(pszSetting, szValFormat, i); + if (DB::Setting::GetWString(hContact, pszModule, pszSetting, &dbvVal)) + break; + if (dbvVal.type != DBVT_WCHAR) + continue; + mir_snprintf(pszSetting, szCatFormat, i); + DB::Setting::GetAString(hContact, pszModule, pszSetting, &dbvCat); + + // create the item object + LPLCITEM pItem = (LPLCITEM)mir_alloc(sizeof(LCITEM)); + pItem->nType = CTRL_LIST_ITEM; + pItem->idstrList = idList; + pItem->idstrListCount = nList; + pItem->iListItem = 0; + pItem->pszText[0] = nullptr; + pItem->pszText[1] = dbvVal.pwszVal; + pItem->wFlags = wFlags; + lvi.lParam = (LPARAM)pItem; + + // get id-str-list-item for the category string + int j = 0; + if (idList != nullptr) { + for (j = 0; j < nList; j++) { + switch (dbvCat.type) { + case DBVT_BYTE: + if (dbvCat.bVal != (uint8_t)idList[j].nID) + continue; + break; + case DBVT_WORD: + if (dbvCat.wVal != (uint16_t)idList[j].nID) + continue; + break; + case DBVT_DWORD: + if (dbvCat.dVal != (uint32_t)idList[j].nID) + continue; + break; + case DBVT_ASCIIZ: + if (mir_strcmp(dbvCat.pszVal, idList[j].pszText)) + continue; + break; + } + pItem->iListItem = j; + break; + } + } + // item not found in the predefined category list? + if ((idList == nullptr || j == nList) && dbvCat.type == DBVT_ASCIIZ) { + pItem->pszText[0] = mir_a2u(dbvCat.pszVal); + db_free(&dbvCat); + } + if ((lvi.iItem = m_list.InsertItem(&lvi)) < 0) { + mir_free(pItem); + db_free(&dbvCat); + db_free(&dbvVal); + break; + } + lvi.iItem++; + dbvCat.type = dbvVal.type = DBVT_DELETED; + } + iItem = lvi.iItem; + return i; + } + + bool ProfileList_AddNewItem(const PROFILEENTRY *pEntry) + { + LPLCITEM pItem = (LPLCITEM)mir_alloc(sizeof(LCITEM)); + pItem->nType = CTRL_LIST_ITEM; + pItem->wFlags = m_hContact ? CTRLF_HASCUSTOM : 0; + pItem->iListItem = 0; + pItem->pszText[0] = nullptr; + pItem->pszText[1] = nullptr; + // get category list + pEntry->GetList((WPARAM)&pItem->idstrListCount, (LPARAM)&pItem->idstrList); + + LVITEM lvi; + lvi.mask = LVIF_PARAM | LVIF_STATE; + lvi.stateMask = 0xFFFFFFFF; + lvi.state = LVIS_FOCUSED | LVIS_SELECTED; + lvi.iItem = ProfileList_GetInsertIndex(m_list.GetHwnd(), pEntry->szGroup); + lvi.iSubItem = 0; + lvi.lParam = (LPARAM)pItem; + if ((lvi.iItem = m_list.InsertItem(&lvi)) >= 0) { + ProfileList_BeginLabelEdit(pList, lvi.iItem, 0); + return true; + } + + mir_free(pItem); + MsgErr(m_hwnd, LPGENW("Sorry, but there is a problem with adding a new item of type \"%s\""), pEntry->szGroup); + return false; + } + +public: PSPContactProfileDlg() : - PSPBaseDlg(IDD_CONTACT_PROFILE) - {} + PSPBaseDlg(IDD_CONTACT_PROFILE), + m_list(this, LIST_PROFILE) + { + pList = (LPLISTCTRL)mir_calloc(sizeof(LISTCTRL)); + } - HWND hList; LPLISTCTRL pList; bool OnInitDialog() override { - LVCOLUMN lvc; - RECT rc; - LOGFONT lf; - HFONT hFont; - - hList = GetDlgItem(m_hwnd, LIST_PROFILE); - if (!hList || !(pList = (LPLISTCTRL)mir_calloc(sizeof(LISTCTRL)))) - return FALSE; - Ctrl_InitTextColours(); // init info structure - pList->hList = hList; + pList->hList = m_list.GetHwnd(); pList->nType = CTRL_LIST_PROFILE; memset(&pList->labelEdit, 0, sizeof(pList->labelEdit)); - SetUserData(hList, pList); + SetUserData(m_list.GetHwnd(), pList); // set new window procedure - mir_subclassWindow(hList, ProfileList_SubclassProc); + mir_subclassWindow(m_list.GetHwnd(), ProfileList_SubclassProc); // remove static edge in aero mode if (IsAeroMode()) - SetWindowLongPtr(hList, GWL_EXSTYLE, GetWindowLongPtr(hList, GWL_EXSTYLE) & ~WS_EX_STATICEDGE); + SetWindowLongPtr(m_list.GetHwnd(), GWL_EXSTYLE, GetWindowLongPtr(m_list.GetHwnd(), GWL_EXSTYLE) & ~WS_EX_STATICEDGE); // insert columns into the listboxes - ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT); + m_list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT); + HFONT hFont; PSGetBoldFont(m_hwnd, hFont); SendDlgItemMessage(m_hwnd, IDC_PAGETITLE, WM_SETFONT, (WPARAM)hFont, 0); // set listfont - pList->hFont = (HFONT)SendMessage(hList, WM_GETFONT, 0, 0); + pList->hFont = (HFONT)m_list.SendMsg(WM_GETFONT, 0, 0); pList->wFlags |= LVF_EDITLABEL; + + LOGFONT lf; GetObject(pList->hFont, sizeof(lf), &lf); lf.lfHeight -= 6; hFont = CreateFontIndirect(&lf); - SendMessage(hList, WM_SETFONT, (WPARAM)hFont, 0); + m_list.SendMsg(WM_SETFONT, (WPARAM)hFont, 0); - GetClientRect(hList, &rc); + RECT rc; + GetClientRect(m_list.GetHwnd(), &rc); rc.right -= GetSystemMetrics(SM_CXVSCROLL); // initiate the tooltips pList->hTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, nullptr, WS_POPUP | TTS_BALLOON | TTS_NOPREFIX | TTS_ALWAYSTIP, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hList, nullptr, g_plugin.getInst(), nullptr); + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, m_list.GetHwnd(), nullptr, g_plugin.getInst(), nullptr); if (pList->hTip) { SetWindowPos(pList->hTip, HWND_TOPMOST, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); @@ -1081,18 +1034,19 @@ struct PSPContactProfileDlg : public PSPBaseDlg ti.cbSize = sizeof(TOOLINFO); ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS | TTF_TRANSPARENT; ti.hinst = g_plugin.getInst(); - ti.hwnd = hList; - ti.uId = (UINT_PTR)hList; + ti.hwnd = m_list.GetHwnd(); + ti.uId = (UINT_PTR)m_list.GetHwnd(); SendMessage(pList->hTip, TTM_ADDTOOL, NULL, (LPARAM)&ti); SendMessage(pList->hTip, TTM_ACTIVATE, FALSE, (LPARAM)&ti); } // insert columns into the listboxes + LVCOLUMN lvc; lvc.mask = LVCF_WIDTH; lvc.cx = rc.right / 8 * 3; - ListView_InsertColumn(hList, 0, &lvc); + m_list.InsertColumn(0, &lvc); lvc.cx = rc.right / 8 * 5; - ListView_InsertColumn(hList, 1, &lvc); + m_list.InsertColumn(1, &lvc); return true; } @@ -1116,7 +1070,7 @@ struct PSPContactProfileDlg : public PSPBaseDlg lvi.pszText = szGroup; lvi.cchTextMax = _countof(szGroup); - for (iItem = lvi.iItem = lvi.iSubItem = 0; ListView_GetItem(hList, &lvi); lvi.iItem++) { + for (iItem = lvi.iItem = lvi.iSubItem = 0; m_list.GetItem(&lvi); lvi.iItem++) { if (!PtrIsValid(pItem = (LPLCITEM)lvi.lParam)) { // delete reluctant items if (iFmt < _countof(pFmt)) { @@ -1153,7 +1107,7 @@ struct PSPContactProfileDlg : public PSPBaseDlg // redraw the item if required if (pItem->wFlags & CTRLF_CHANGED) { pItem->wFlags &= ~CTRLF_CHANGED; - ListView_RedrawItems(hList, lvi.iItem, lvi.iItem); + m_list.RedrawItems(lvi.iItem, lvi.iItem); } iItem++; } @@ -1172,20 +1126,18 @@ struct PSPContactProfileDlg : public PSPBaseDlg bool OnRefresh() override { - LPCSTR pszProto; - uint8_t msgResult = 0; - LPIDSTRLIST idList; - UINT nList; - uint8_t i; int iItem = 0, iGrp = 0, numProtoItems, numUserItems; + LPCSTR pszProto; if (!(pList->wFlags & CTRLF_CHANGED) && PSGetBaseProto(m_hwnd, pszProto) && *pszProto != 0) { - ProfileList_Clear(hList); + ProfileList_Clear(m_list.GetHwnd()); // insert the past information - for (i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { + int nList; + LPIDSTRLIST idList; pFmt[i].GetList((WPARAM)&nList, (LPARAM)&idList); - if ((numProtoItems = ProfileList_AddItemlistFromDB(pList, iItem, idList, nList, m_hContact, pszProto, pFmt[i].szCatFmt, pFmt[i].szValFmt, CTRLF_HASPROTO)) < 0) + if ((numProtoItems = ProfileList_AddItemlistFromDB(iItem, idList, nList, m_hContact, pszProto, pFmt[i].szCatFmt, pFmt[i].szValFmt, CTRLF_HASPROTO)) < 0) return false; // scan all basic protocols for the subcontacts @@ -1195,7 +1147,7 @@ struct PSPContactProfileDlg : public PSPBaseDlg LPCSTR pszSubBaseProto; if ((hDefContact = db_mc_getSub(m_hContact, iDefault)) && (pszSubBaseProto = Proto_GetBaseAccountName(hDefContact))) { - if ((numProtoItems += ProfileList_AddItemlistFromDB(pList, iItem, idList, nList, hDefContact, pszSubBaseProto, pFmt[i].szCatFmt, pFmt[i].szValFmt, CTRLF_HASMETA | CTRLF_HASPROTO)) < 0) + if ((numProtoItems += ProfileList_AddItemlistFromDB(iItem, idList, nList, hDefContact, pszSubBaseProto, pFmt[i].szCatFmt, pFmt[i].szValFmt, CTRLF_HASMETA | CTRLF_HASPROTO)) < 0) return false; // copy the missing settings from the other subcontacts @@ -1207,17 +1159,16 @@ struct PSPContactProfileDlg : public PSPBaseDlg continue; if (!(pszSubBaseProto = Proto_GetBaseAccountName(hSubContact))) continue; - if ((numProtoItems += ProfileList_AddItemlistFromDB(pList, iItem, idList, nList, hSubContact, pszSubBaseProto, pFmt[i].szCatFmt, pFmt[i].szValFmt, CTRLF_HASMETA | CTRLF_HASPROTO)) < 0) + if ((numProtoItems += ProfileList_AddItemlistFromDB(iItem, idList, nList, hSubContact, pszSubBaseProto, pFmt[i].szCatFmt, pFmt[i].szValFmt, CTRLF_HASMETA | CTRLF_HASPROTO)) < 0) return false; } } } - if ((numUserItems = ProfileList_AddItemlistFromDB(pList, iItem, idList, nList, m_hContact, USERINFO, pFmt[i].szCatFmt, pFmt[i].szValFmt, CTRLF_HASCUSTOM)) < 0) + if ((numUserItems = ProfileList_AddItemlistFromDB(iItem, idList, nList, m_hContact, USERINFO, pFmt[i].szCatFmt, pFmt[i].szValFmt, CTRLF_HASCUSTOM)) < 0) return false; if (numUserItems || numProtoItems) { - msgResult = PSP_CHANGED; - ProfileList_AddGroup(hList, pFmt[i].szGroup, iGrp); + ProfileList_AddGroup(m_list.GetHwnd(), pFmt[i].szGroup, iGrp); iGrp = ++iItem; } } @@ -1242,7 +1193,7 @@ struct PSPContactProfileDlg : public PSPBaseDlg // some account data may have changed so reread database switch (((LPNMHDR)lParam)->code) { case PSN_KILLACTIVE: // user swiches to another propertysheetpage - ProfileList_EndLabelEdit(hList, TRUE); + ProfileList_EndLabelEdit(pList, TRUE); break; } break; @@ -1306,8 +1257,8 @@ struct PSPContactProfileDlg : public PSPBaseDlg return 0; case LVN_GETDISPINFO: - if (pList->labelEdit.iTopIndex != ListView_GetTopIndex(hList)) - ProfileList_EndLabelEdit(((LPNMHDR)lParam)->hwndFrom, FALSE); + if (pList->labelEdit.iTopIndex != m_list.GetTopIndex()) + ProfileList_EndLabelEdit(pList, FALSE); break; case NM_CUSTOMDRAW: @@ -1389,28 +1340,27 @@ struct PSPContactProfileDlg : public PSPBaseDlg case WM_COMMAND: switch (LOWORD(wParam)) { case BTN_ADD_intEREST: - return ProfileList_AddNewItem(m_hwnd, (LPLISTCTRL)GetUserData(hList), &pFmt[2]); + return ProfileList_AddNewItem(&pFmt[2]); case BTN_ADD_AFFLIATION: - return ProfileList_AddNewItem(m_hwnd, (LPLISTCTRL)GetUserData(hList), &pFmt[1]); + return ProfileList_AddNewItem(&pFmt[1]); case BTN_ADD_PAST: - return ProfileList_AddNewItem(m_hwnd, (LPLISTCTRL)GetUserData(hList), &pFmt[0]); + return ProfileList_AddNewItem(&pFmt[0]); case BTN_EDIT_CAT: - ProfileList_BeginLabelEdit(hList, ListView_GetSelectionMark(hList), 0); + ProfileList_BeginLabelEdit(pList, m_list.GetSelectionMark(), 0); break; case BTN_EDIT_VAL: - ProfileList_BeginLabelEdit(hList, ListView_GetSelectionMark(hList), 1); + ProfileList_BeginLabelEdit(pList, m_list.GetSelectionMark(), 1); break; case BTN_DEL: if (IDYES == MsgBox(m_hwnd, MB_YESNO | MB_ICON_QUESTION, LPGENW("Question"), LPGENW("Delete an entry"), LPGENW("Do you really want to delete this entry?"))) { - int iItem = ListView_GetSelectionMark(hList); - ProfileList_DeleteItem(hList, iItem); + int iItem = m_list.GetSelectionMark(); + ProfileList_DeleteItem(m_list.GetHwnd(), iItem); - if (PtrIsValid(pList)) - pList->wFlags |= CTRLF_CHANGED; + pList->wFlags |= CTRLF_CHANGED; SendMessage(GetParent(m_hwnd), PSM_CHANGED, NULL, NULL); // check if to delete any devider - if (!ProfileList_GetItemData(hList, iItem--) && !ProfileList_GetItemData(hList, iItem)) - ListView_DeleteItem(hList, iItem); + if (!ProfileList_GetItemData(m_list.GetHwnd(), iItem--) && !ProfileList_GetItemData(m_list.GetHwnd(), iItem)) + m_list.DeleteItem(iItem); } break; } diff --git a/plugins/UserInfoEx/src/version.h b/plugins/UserInfoEx/src/version.h index 798e0d7831..191d376c3e 100644 --- a/plugins/UserInfoEx/src/version.h +++ b/plugins/UserInfoEx/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 9 #define __RELEASE_NUM 0 -#define __BUILD_NUM 2 +#define __BUILD_NUM 3 #include -- cgit v1.2.3