From b16718fb5ee5e3c30c73449287be3ad4ed141082 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 23 Dec 2016 20:19:34 +0300 Subject: correct file name applied --- plugins/Scriver/src/msgwindow.cpp | 1520 ------------------------------------- plugins/Scriver/src/tabs.cpp | 1520 +++++++++++++++++++++++++++++++++++++ 2 files changed, 1520 insertions(+), 1520 deletions(-) delete mode 100644 plugins/Scriver/src/msgwindow.cpp create mode 100644 plugins/Scriver/src/tabs.cpp (limited to 'plugins/Scriver/src') diff --git a/plugins/Scriver/src/msgwindow.cpp b/plugins/Scriver/src/msgwindow.cpp deleted file mode 100644 index 9c18edc424..0000000000 --- a/plugins/Scriver/src/msgwindow.cpp +++ /dev/null @@ -1,1520 +0,0 @@ -/* -Scriver - -Copyright (c) 2000-09 Miranda ICQ/IM project, - -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#define SB_CHAR_WIDTH 40 -#define SB_SENDING_WIDTH 25 -#define SB_UNICODE_WIDTH 18 - -#define TIMEOUT_FLASHWND 900 - -static void DrawTab(ParentWindowData *dat, HWND hwnd, WPARAM wParam, LPARAM lParam); - -///////////////////////////////////////////////////////////////////////////////////////// - -static const wchar_t *titleTokenNames[] = { L"%name%", L"%status%", L"%statusmsg%", L"%account%" }; - -wchar_t* GetWindowTitle(MCONTACT hContact, const char *szProto) -{ - ptrW tmplt; - const wchar_t* tokens[4] = { 0 }; - - CMStringW tszTemplate, tszStatus, tszTitle; - if (hContact && szProto) { - tokens[0] = pcli->pfnGetContactDisplayName(hContact, 0); - tokens[1] = pcli->pfnGetStatusModeDescription(db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE), 0); - - tszStatus = ptrW(db_get_wsa(hContact, "CList", "StatusMsg")); - tszStatus.Replace(L"\r\n", L" "); - tokens[2] = tszStatus; - - char *accModule = Proto_GetBaseAccountName(hContact); - if (accModule != NULL) { - PROTOACCOUNT* proto = Proto_GetAccount(accModule); - if (proto != NULL) - tokens[3] = mir_wstrdup(proto->tszAccountName); - } - - tmplt = db_get_wsa(NULL, SRMMMOD, SRMSGSET_WINDOWTITLE); - if (tmplt != NULL) - tszTemplate = tmplt; - else { - if (g_dat.flags & SMF_STATUSICON) - tszTemplate = L"%name% - "; - else - tszTemplate = L"%name% (%status%) : "; - } - } - - for (const wchar_t *p = tszTemplate; *p; p++) { - if (*p == '%') { - int i; - for (i = 0; i < _countof(titleTokenNames); i++) { - size_t tnlen = mir_wstrlen(titleTokenNames[i]); - if (!wcsncmp(p, titleTokenNames[i], tnlen)) { - if (tokens[i] != NULL) - tszTitle.Append(tokens[i]); - - p += tnlen - 1; - break; - } - } - if (i < _countof(titleTokenNames)) - continue; - } - tszTitle.AppendChar(*p); - } - - if (tmplt == NULL) - tszTitle.Append(TranslateT("Message session")); - - return tszTitle.Detach(); -} - -static int GetChildCount(ParentWindowData *dat) -{ - return TabCtrl_GetItemCount(dat->hwndTabs); -} - -static void GetChildWindowRect(ParentWindowData *dat, RECT *rcChild) -{ - RECT rc, rcStatus, rcTabs; - GetClientRect(dat->hwnd, &rc); - GetClientRect(dat->hwndTabs, &rcTabs); - TabCtrl_AdjustRect(dat->hwndTabs, FALSE, &rcTabs); - rcStatus.top = rcStatus.bottom = 0; - if (dat->flags2 & SMF2_SHOWSTATUSBAR) - GetWindowRect(dat->hwndStatus, &rcStatus); - - rcChild->left = 0; - rcChild->right = rc.right; - if (dat->flags2 & SMF2_TABSATBOTTOM) { - rcChild->top = 2; - if ((dat->flags2 & SMF2_USETABS && !(dat->flags2 & SMF2_HIDEONETAB)) || (dat->childrenCount > 1)) - rcChild->bottom = rcTabs.bottom + 4; - else - rcChild->bottom = rc.bottom - rc.top - (rcStatus.bottom - rcStatus.top); - } - else { - if ((dat->flags2 & SMF2_USETABS && !(dat->flags2 & SMF2_HIDEONETAB)) || (dat->childrenCount > 1)) - rcChild->top = rcTabs.top; - else - rcChild->top = 2; - - rcChild->bottom = rc.bottom - rc.top - (rcStatus.bottom - rcStatus.top); - } -} - -static int GetTabFromHWND(ParentWindowData *dat, HWND child) -{ - int l = TabCtrl_GetItemCount(dat->hwndTabs); - for (int i = 0; i < l; i++) { - TCITEM tci = { 0 }; - tci.mask = TCIF_PARAM; - TabCtrl_GetItem(dat->hwndTabs, i, &tci); - MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam; - if (mwtd->hwnd == child) - return i; - } - return -1; -} - -static MessageWindowTabData* GetChildFromTab(HWND hwndTabs, int tabId) -{ - TCITEM tci = { 0 }; - tci.mask = TCIF_PARAM; - if (TabCtrl_GetItem(hwndTabs, tabId, &tci)) - return (MessageWindowTabData *)tci.lParam; - - return NULL; -} - -static MessageWindowTabData* GetChildFromHWND(ParentWindowData *dat, HWND hwnd) -{ - int l = TabCtrl_GetItemCount(dat->hwndTabs); - for (int i = 0; i < l; i++) { - TCITEM tci = { 0 }; - tci.mask = TCIF_PARAM; - TabCtrl_GetItem(dat->hwndTabs, i, &tci); - MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam; - if (mwtd->hwnd == hwnd) - return mwtd; - } - return NULL; -} - -static void GetMinimunWindowSize(ParentWindowData *dat, SIZE *size) -{ - MINMAXINFO mmi; - RECT rc, rcWindow; - int minW = 216, minH = 80; - GetWindowRect(dat->hwnd, &rcWindow); - GetChildWindowRect(dat, &rc); - for (int i = 0; i < dat->childrenCount; i++) { - MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i); - SendMessage(mwtd->hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&mmi); - if (i == 0 || mmi.ptMinTrackSize.x > minW) minW = mmi.ptMinTrackSize.x; - if (i == 0 || mmi.ptMinTrackSize.y > minH) minH = mmi.ptMinTrackSize.y; - } - if (dat->bMinimized) { - size->cx = minW; - size->cy = minH; - } - else { - size->cx = minW + (rcWindow.right - rcWindow.left) - (rc.right - rc.left); - size->cy = minH + (rcWindow.bottom - rcWindow.top) - (rc.bottom - rc.top); - } -} - -static void SetupStatusBar(ParentWindowData *dat) -{ - int statusIconNum = GetStatusIconsCount(dat->hContact); - int statwidths[4]; - RECT rc; - GetClientRect(dat->hwnd, &rc); - statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH - SB_UNICODE_WIDTH - 2 * (statusIconNum > 0) - statusIconNum * (GetSystemMetrics(SM_CXSMICON) + 2); - statwidths[1] = rc.right - rc.left - SB_UNICODE_WIDTH - 2 * (statusIconNum > 0) - statusIconNum * (GetSystemMetrics(SM_CXSMICON) + 2); - statwidths[2] = rc.right - rc.left - SB_UNICODE_WIDTH; - statwidths[3] = -1; - SendMessage(dat->hwndStatus, SB_SETPARTS, 4, (LPARAM)statwidths); - SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW) | 2, 0); - SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_NOBORDERS) | 3, 0); -} - -static int AddOrReplaceIcon(HIMAGELIST hList, int prevIndex, HICON hIcon) -{ - int usageIdx = -1; - for (int i = 0; i < g_dat.tabIconListUsageSize; i++) { - if (!g_dat.tabIconListUsage[i].used && usageIdx == -1) - usageIdx = i; - - if (g_dat.tabIconListUsage[i].index == prevIndex) { - usageIdx = i; - break; - } - } - if (usageIdx == -1) { - usageIdx = g_dat.tabIconListUsageSize; - g_dat.tabIconListUsage = (ImageListUsageEntry*)mir_realloc(g_dat.tabIconListUsage, sizeof(ImageListUsageEntry)* (g_dat.tabIconListUsageSize + 1)); - g_dat.tabIconListUsageSize++; - } - else prevIndex = g_dat.tabIconListUsage[usageIdx].index; - - g_dat.tabIconListUsage[usageIdx].used = 1; - g_dat.tabIconListUsage[usageIdx].index = (int)ImageList_ReplaceIcon(hList, prevIndex, hIcon); - return g_dat.tabIconListUsage[usageIdx].index; -} - -static void ReleaseIcon(int index) -{ - for (int i = 0; i < g_dat.tabIconListUsageSize; i++) - if (g_dat.tabIconListUsage[i].index == index) - g_dat.tabIconListUsage[i].used = 0; -} - -static void ActivateChild(ParentWindowData *dat, HWND child) -{ - RECT rcChild; - GetChildWindowRect(dat, &rcChild); - SetWindowPos(child, HWND_TOP, rcChild.left, rcChild.top, rcChild.right - rcChild.left, rcChild.bottom - rcChild.top, SWP_NOSIZE); - - int i = GetTabFromHWND(dat, child); - if (i == -1) - return; - - MessageWindowTabData *mwtd; - if ((mwtd = GetChildFromTab(dat->hwndTabs, i)) == NULL) - return; - - dat->hContact = mwtd->hContact; - if (child != dat->hwndActive) { - HWND prev = dat->hwndActive; - dat->hwndActive = child; - SetupStatusBar(dat); - SendMessage(dat->hwndActive, GC_UPDATESTATUSBAR, 0, 0); - SendMessage(dat->hwndActive, DM_UPDATETITLEBAR, 0, 0); - SendMessage(dat->hwnd, WM_SIZE, 0, 0); - ShowWindow(dat->hwndActive, SW_SHOWNOACTIVATE); - SendMessage(dat->hwndActive, DM_SCROLLLOGTOBOTTOM, 0, 0); - if (prev != NULL) - ShowWindow(prev, SW_HIDE); - } - else SendMessage(dat->hwnd, WM_SIZE, 0, 0); - - TabCtrl_SetCurSel(dat->hwndTabs, i); - SendMessage(dat->hwndActive, DM_ACTIVATE, WA_ACTIVE, 0); -} - -static void AddChild(ParentWindowData *dat, HWND hwnd, MCONTACT hContact) -{ - MessageWindowTabData *mwtd = (MessageWindowTabData *)mir_alloc(sizeof(MessageWindowTabData)); - mwtd->hwnd = hwnd; - mwtd->hContact = hContact; - mwtd->szProto = GetContactProto(hContact); - mwtd->parent = dat; - - dat->childrenCount++; - - TCITEM tci; - tci.mask = TCIF_PARAM | TCIF_IMAGE | TCIF_TEXT; - tci.lParam = (LPARAM)mwtd; - tci.iImage = -1; - tci.pszText = L""; - TabCtrl_InsertItem(dat->hwndTabs, dat->childrenCount - 1, &tci); - SetWindowPos(mwtd->hwnd, HWND_TOP, dat->childRect.left, dat->childRect.top, dat->childRect.right - dat->childRect.left, dat->childRect.bottom - dat->childRect.top, SWP_HIDEWINDOW); - SendMessage(dat->hwnd, WM_SIZE, 0, 0); - - EnableThemeDialogTexture(hwnd, ETDT_ENABLETAB); -} - -static void RemoveChild(ParentWindowData *dat, HWND child) -{ - int tab = GetTabFromHWND(dat, child); - if (tab >= 0) { - TCITEM tci; - tci.mask = TCIF_PARAM | TCIF_IMAGE; - TabCtrl_GetItem(dat->hwndTabs, tab, &tci); - TabCtrl_DeleteItem(dat->hwndTabs, tab); - mir_free((MessageWindowTabData *)tci.lParam); - dat->childrenCount--; - if (child == dat->hwndActive) { - if (tab == TabCtrl_GetItemCount(dat->hwndTabs)) tab--; - if (tab >= 0) - ActivateChild(dat, GetChildFromTab(dat->hwndTabs, tab)->hwnd); - else - dat->hwndActive = NULL; - } - ReleaseIcon(tci.iImage); - } -} - -static void CloseOtherChilden(ParentWindowData *dat, HWND child) -{ - ActivateChild(dat, child); - for (int i = dat->childrenCount - 1; i >= 0; i--) { - MessageWindowTabData *mwtd = GetChildFromTab(dat->hwndTabs, i); - if (mwtd != NULL && mwtd->hwnd != child) - SendMessage(mwtd->hwnd, WM_CLOSE, 0, 0); - } - ActivateChild(dat, child); -} - -static void ActivateNextChild(ParentWindowData *dat, HWND child) -{ - int i = GetTabFromHWND(dat, child); - int l = TabCtrl_GetItemCount(dat->hwndTabs); - i = (i + 1) % l; - ActivateChild(dat, GetChildFromTab(dat->hwndTabs, i)->hwnd); -} - -static void ActivatePrevChild(ParentWindowData *dat, HWND child) -{ - int i = GetTabFromHWND(dat, child); - int l = TabCtrl_GetItemCount(dat->hwndTabs); - i = (i + l - 1) % l; - ActivateChild(dat, GetChildFromTab(dat->hwndTabs, i)->hwnd); -} - -static void ActivateChildByIndex(ParentWindowData *dat, int index) -{ - int l = TabCtrl_GetItemCount(dat->hwndTabs); - if (index < l) { - MessageWindowTabData *mwtd = GetChildFromTab(dat->hwndTabs, index); - if (mwtd != NULL) - ActivateChild(dat, mwtd->hwnd); - } -} - -static void SetContainerWindowStyle(ParentWindowData *dat) -{ - ShowWindow(dat->hwndStatus, (dat->flags2 & SMF2_SHOWSTATUSBAR) ? SW_SHOW : SW_HIDE); - - DWORD ws = GetWindowLongPtr(dat->hwnd, GWL_STYLE) & ~(WS_CAPTION); - if (dat->flags2 & SMF2_SHOWTITLEBAR) - ws |= WS_CAPTION; - - SetWindowLongPtr(dat->hwnd, GWL_STYLE, ws); - - ws = GetWindowLongPtr(dat->hwnd, GWL_EXSTYLE)& ~WS_EX_LAYERED; - ws |= dat->flags2 & SMF2_USETRANSPARENCY ? WS_EX_LAYERED : 0; - SetWindowLongPtr(dat->hwnd, GWL_EXSTYLE, ws); - if (dat->flags2 & SMF2_USETRANSPARENCY) - SetLayeredWindowAttributes(dat->hwnd, RGB(255, 255, 255), (BYTE)(255 - g_dat.inactiveAlpha), LWA_ALPHA); - - ws = GetWindowLongPtr(dat->hwndTabs, GWL_STYLE) & ~(TCS_BOTTOM | 0x2000); - if (dat->flags2 & SMF2_TABSATBOTTOM) - ws |= TCS_BOTTOM; - - ws |= 0x2000; - if (dat->flags2 & SMF2_TABCLOSEBUTTON) - TabCtrl_SetPadding(dat->hwndTabs, GetSystemMetrics(SM_CXEDGE) + 12, GetSystemMetrics(SM_CYEDGE) + 1); - else - TabCtrl_SetPadding(dat->hwndTabs, GetSystemMetrics(SM_CXEDGE) + 4, GetSystemMetrics(SM_CYEDGE) + 1); - - SetWindowLongPtr(dat->hwndTabs, GWL_STYLE, ws); - - RECT rc; - GetWindowRect(dat->hwnd, &rc); - SetWindowPos(dat->hwnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -LRESULT CALLBACK TabCtrlProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - TabCtrlData *dat = (TabCtrlData*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - - TCHITTESTINFO thinfo; - int tabId; - - switch (msg) { - case EM_SUBCLASSED: - dat = (TabCtrlData*)mir_alloc(sizeof(TabCtrlData)); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat); - dat->bDragging = FALSE; - dat->bDragged = FALSE; - dat->srcTab = -1; - dat->destTab = -1; - return 0; - - case WM_MBUTTONDOWN: - thinfo.pt.x = LOWORD(lParam); - thinfo.pt.y = HIWORD(lParam); - tabId = TabCtrl_HitTest(hwnd, &thinfo); - if (tabId >= 0) { - TCITEM tci; - tci.mask = TCIF_PARAM; - TabCtrl_GetItem(hwnd, tabId, &tci); - MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam; - if (mwtd != NULL) { - SendMessage(mwtd->hwnd, WM_CLOSE, 0, 0); - dat->srcTab = -1; - } - } - return 0; - - case WM_LBUTTONDBLCLK: - thinfo.pt.x = LOWORD(lParam); - thinfo.pt.y = HIWORD(lParam); - tabId = TabCtrl_HitTest(hwnd, &thinfo); - if (tabId >= 0 && tabId == dat->srcTab) { - SendMessage(GetChildFromTab(hwnd, tabId)->hwnd, WM_CLOSE, 0, 0); - dat->srcTab = -1; - } - dat->destTab = -1; - break; - - case WM_LBUTTONDOWN: - if (!dat->bDragging) { - thinfo.pt.x = LOWORD(lParam); - thinfo.pt.y = HIWORD(lParam); - dat->srcTab = TabCtrl_HitTest(hwnd, &thinfo); - - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - if (dat->srcTab >= 0) { - dat->bDragging = TRUE; - dat->bDragged = FALSE; - dat->clickLParam = lParam; - dat->clickWParam = wParam; - dat->lastClickTime = ft.dwLowDateTime; - dat->mouseLBDownPos.x = thinfo.pt.x; - dat->mouseLBDownPos.y = thinfo.pt.y; - SetCapture(hwnd); - } - return 0; - } - break; - - case WM_CAPTURECHANGED: - case WM_LBUTTONUP: - if (dat->bDragging) { - thinfo.pt.x = LOWORD(lParam); - thinfo.pt.y = HIWORD(lParam); - if (dat->bDragged) { - ImageList_DragLeave(GetDesktopWindow()); - ImageList_EndDrag(); - ImageList_Destroy(dat->hDragImageList); - SetCursor(LoadCursor(NULL, IDC_ARROW)); - dat->destTab = TabCtrl_HitTest(hwnd, &thinfo); - if (thinfo.flags != TCHT_NOWHERE && dat->destTab != dat->srcTab) { - NMHDR nmh; - wchar_t sBuffer[501]; - TCITEM item; - int curSel; - curSel = TabCtrl_GetCurSel(hwnd); - item.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_TEXT; - item.pszText = sBuffer; - item.cchTextMax = _countof(sBuffer); - TabCtrl_GetItem(hwnd, dat->srcTab, &item); - sBuffer[_countof(sBuffer) - 1] = '\0'; - - if (curSel == dat->srcTab) - curSel = dat->destTab; - else if (curSel > dat->srcTab && curSel <= dat->destTab) - curSel--; - else if (curSel < dat->srcTab && curSel >= dat->destTab) - curSel++; - - TabCtrl_DeleteItem(hwnd, dat->srcTab); - TabCtrl_InsertItem(hwnd, dat->destTab, &item); - TabCtrl_SetCurSel(hwnd, curSel); - dat->destTab = -1; - nmh.hwndFrom = hwnd; - nmh.idFrom = GetDlgCtrlID(hwnd); - nmh.code = TCN_SELCHANGE; - SendMessage(GetParent(hwnd), WM_NOTIFY, nmh.idFrom, (LPARAM)&nmh); - UpdateWindow(hwnd); - } - else if (thinfo.flags == TCHT_NOWHERE) { - dat->destTab = -1; - - TCITEM tci; - tci.mask = TCIF_PARAM; - TabCtrl_GetItem(hwnd, dat->srcTab, &tci); - MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam; - if (mwtd != NULL) { - HWND hChild = mwtd->hwnd; - MCONTACT hContact = mwtd->hContact; - - POINT pt; - GetCursorPos(&pt); - HWND hParent = WindowFromPoint(pt); - while (GetParent(hParent) != NULL) - hParent = GetParent(hParent); - - hParent = WindowList_Find(g_dat.hParentWindowList, (UINT_PTR)hParent); - if ((hParent != NULL && hParent != GetParent(hwnd)) || (hParent == NULL && mwtd->parent->childrenCount > 1 && (GetKeyState(VK_CONTROL) & 0x8000))) { - if (hParent == NULL) { - hParent = GetParentWindow(hContact, FALSE); - - RECT rc; - GetWindowRect(hParent, &rc); - - rc.right = (rc.right - rc.left); - rc.bottom = (rc.bottom - rc.top); - rc.left = pt.x - rc.right / 2; - rc.top = pt.y - rc.bottom / 2; - HMONITOR hMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST); - - MONITORINFO mi; - mi.cbSize = sizeof(mi); - GetMonitorInfo(hMonitor, &mi); - - RECT rcDesktop = mi.rcWork; - if (rc.left < rcDesktop.left) - rc.left = rcDesktop.left; - if (rc.top < rcDesktop.top) - rc.top = rcDesktop.top; - MoveWindow(hParent, rc.left, rc.top, rc.right, rc.bottom, FALSE); - } - NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_CLOSING); - NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_CLOSE); - SetParent(hChild, hParent); - SendMessage(GetParent(hwnd), CM_REMOVECHILD, 0, (LPARAM)hChild); - SendMessage(hChild, DM_SETPARENT, 0, (LPARAM)hParent); - SendMessage(hParent, CM_ADDCHILD, (WPARAM)hChild, hContact); - SendMessage(hChild, DM_UPDATETABCONTROL, 0, 0); - SendMessage(hParent, CM_ACTIVATECHILD, 0, (LPARAM)hChild); - NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_OPENING); - NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_OPEN); - ShowWindow(hParent, SW_SHOWNA); - EnableWindow(hParent, TRUE); - } - } - } - else { - dat->destTab = -1; - RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); - } - } - else if (dat->srcTab >= 0 && g_dat.flags2 & SMF2_TABCLOSEBUTTON) { - IMAGEINFO info; - POINT pt; - RECT rect; - int atTop = (GetWindowLongPtr(hwnd, GWL_STYLE) & TCS_BOTTOM) == 0; - TabCtrl_GetItemRect(hwnd, dat->srcTab, &rect); - pt.x = LOWORD(lParam); - pt.y = HIWORD(lParam); - ImageList_GetImageInfo(g_dat.hButtonIconList, 0, &info); - rect.left = rect.right - (info.rcImage.right - info.rcImage.left) - 6; - if (!atTop) - rect.top = rect.bottom - (info.rcImage.bottom - info.rcImage.top); - - if (pt.x >= rect.left && pt.x < rect.left + (info.rcImage.right - info.rcImage.left) && pt.y >= rect.top && pt.y < rect.top + (info.rcImage.bottom - info.rcImage.top)) { - HBITMAP hOldBitmap, hBmp; - HDC hdc = GetDC(NULL); - HDC hdcMem = CreateCompatibleDC(hdc); - pt.x -= rect.left; - pt.y -= rect.top; - hBmp = CreateCompatibleBitmap(hdc, info.rcImage.right - info.rcImage.left + 1, info.rcImage.bottom - info.rcImage.top + 1); - hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBmp); - SetPixel(hdcMem, pt.x, pt.y, 0x000000); - ImageList_DrawEx(g_dat.hButtonIconList, 0, hdcMem, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); - COLORREF color1 = GetPixel(hdcMem, pt.x, pt.y); - SetPixel(hdcMem, pt.x, pt.y, 0xFFFFFF); - ImageList_DrawEx(g_dat.hButtonIconList, 0, hdcMem, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); - COLORREF color2 = GetPixel(hdcMem, pt.x, pt.y); - SelectObject(hdcMem, hOldBitmap); - DeleteDC(hdcMem); - DeleteObject(hBmp); - ReleaseDC(NULL, hdc); - if (color1 != 0x000000 || color2 != 0xFFFFFF) { - SendMessage(GetChildFromTab(hwnd, dat->srcTab)->hwnd, WM_CLOSE, 0, 0); - dat->srcTab = -1; - } - } - else SendMessage(hwnd, WM_LBUTTONDOWN, dat->clickWParam, dat->clickLParam); - } - else SendMessage(hwnd, WM_LBUTTONDOWN, dat->clickWParam, dat->clickLParam); - - dat->bDragged = dat->bDragging = FALSE; - dat->destTab = -1; - ReleaseCapture(); - } - break; - - case WM_MOUSEMOVE: - if (wParam & MK_LBUTTON) { - if (dat->bDragging) { - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - thinfo.pt.x = LOWORD(lParam); - thinfo.pt.y = HIWORD(lParam); - if (!dat->bDragged) { - if ((abs(thinfo.pt.x - dat->mouseLBDownPos.x) < 3 && abs(thinfo.pt.y - dat->mouseLBDownPos.y) < 3) - || (ft.dwLowDateTime - dat->lastClickTime) < 10 * 1000 * 150) - break; - } - if (!dat->bDragged) { - POINT pt; - RECT rect; - RECT rect2; - HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 254)); - GetCursorPos(&pt); - TabCtrl_GetItemRect(hwnd, dat->srcTab, &rect); - rect.right -= rect.left - 1; - rect.bottom -= rect.top - 1; - rect2.left = 0; rect2.right = rect.right; rect2.top = 0; rect2.bottom = rect.bottom; - dat->hDragImageList = ImageList_Create(rect.right, rect.bottom, ILC_COLOR | ILC_MASK, 0, 1); - HDC hDC = GetDC(hwnd); - HDC hMemDC = CreateCompatibleDC(hDC); - HBITMAP hBitmap = CreateCompatibleBitmap(hDC, rect.right, rect.bottom); - HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); - FillRect(hMemDC, &rect2, hBrush); - SetWindowOrgEx(hMemDC, rect.left, rect.top, NULL); - SendMessage(hwnd, WM_PRINTCLIENT, (WPARAM)hMemDC, PRF_CLIENT); - SelectObject(hMemDC, hOldBitmap); - ImageList_AddMasked(dat->hDragImageList, hBitmap, RGB(255, 0, 254)); - DeleteObject(hBitmap); - DeleteObject(hBrush); - ReleaseDC(hwnd, hDC); - DeleteDC(hMemDC); - ImageList_BeginDrag(dat->hDragImageList, 0, dat->mouseLBDownPos.x - rect.left, dat->mouseLBDownPos.y - rect.top); - ImageList_DragEnter(GetDesktopWindow(), pt.x, pt.y); - SetCursor(hDragCursor); - dat->mouseLBDownPos.x = thinfo.pt.x; - dat->mouseLBDownPos.y = thinfo.pt.y; - } - else { - POINT pt; - GetCursorPos(&pt); - thinfo.pt = pt; - ScreenToClient(hwnd, &thinfo.pt); - int newDest = TabCtrl_HitTest(hwnd, &thinfo); - if (thinfo.flags == TCHT_NOWHERE) - newDest = -1; - - if (newDest != dat->destTab) { - dat->destTab = newDest; - ImageList_DragLeave(GetDesktopWindow()); - RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); - ImageList_DragEnter(GetDesktopWindow(), pt.x, pt.y); - } - else ImageList_DragMove(pt.x, pt.y); - } - dat->bDragged = TRUE; - return 0; - } - } - break; - - case EM_UNSUBCLASSED: - mir_free(dat); - return 0; - } - return mir_callNextSubclass(hwnd, TabCtrlProc, msg, wParam, lParam); -} - -__forceinline void SubclassTabCtrl(HWND hwnd) -{ - mir_subclassWindow(hwnd, TabCtrlProc); - SendMessage(hwnd, EM_SUBCLASSED, 0, 0); -} - -__forceinline void UnsubclassTabCtrl(HWND hwnd) -{ - SendMessage(hwnd, EM_UNSUBCLASSED, 0, 0); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static int ScriverRestoreWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix, int flags, int showCmd) -{ - WINDOWPLACEMENT wp; - wp.length = sizeof(wp); - GetWindowPlacement(hwnd, &wp); - - char szSettingName[64]; - mir_snprintf(szSettingName, "%sx", szNamePrefix); - int x = db_get_dw(hContact, szModule, szSettingName, -1); - mir_snprintf(szSettingName, "%sy", szNamePrefix); - int y = db_get_dw(hContact, szModule, szSettingName, -1); - if (x == -1) - return 1; - - if (flags & RWPF_NOSIZE) - OffsetRect(&wp.rcNormalPosition, x - wp.rcNormalPosition.left, y - wp.rcNormalPosition.top); - else { - wp.rcNormalPosition.left = x; - wp.rcNormalPosition.top = y; - mir_snprintf(szSettingName, "%swidth", szNamePrefix); - wp.rcNormalPosition.right = wp.rcNormalPosition.left + db_get_dw(hContact, szModule, szSettingName, -1); - mir_snprintf(szSettingName, "%sheight", szNamePrefix); - wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + db_get_dw(hContact, szModule, szSettingName, -1); - } - wp.flags = 0; - wp.showCmd = showCmd; - - HMONITOR hMonitor = MonitorFromRect(&wp.rcNormalPosition, MONITOR_DEFAULTTONEAREST); - MONITORINFO mi; - mi.cbSize = sizeof(mi); - GetMonitorInfo(hMonitor, &mi); - RECT rcDesktop = mi.rcWork; - if (wp.rcNormalPosition.left > rcDesktop.right || wp.rcNormalPosition.top > rcDesktop.bottom || - wp.rcNormalPosition.right < rcDesktop.left || wp.rcNormalPosition.bottom < rcDesktop.top) return 1; - SetWindowPlacement(hwnd, &wp); - return 0; -} - -static INT_PTR CALLBACK DlgProcParentWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - ParentWindowData *dat = (ParentWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - if (!dat && msg != WM_INITDIALOG) - return FALSE; - - DWORD ws; - - switch (msg) { - case WM_INITDIALOG: - { - int savePerContact = db_get_b(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT); - NewMessageWindowLParam *newData = (NewMessageWindowLParam *)lParam; - dat = (ParentWindowData *)mir_alloc(sizeof(ParentWindowData)); - dat->hContact = newData->hContact; - dat->nFlash = 0; - dat->nFlashMax = db_get_b(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT); - dat->childrenCount = 0; - dat->hwnd = hwndDlg; - dat->mouseLBDown = 0; - dat->windowWasCascaded = 0; - dat->bMinimized = 0; - dat->bVMaximized = 0; - dat->flags2 = g_dat.flags2; - dat->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL); - dat->isChat = newData->isChat; - SendMessage(dat->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0); - //SetupStatusBar(dat); - dat->hwndTabs = GetDlgItem(hwndDlg, IDC_TABS); - dat->hwndActive = NULL; - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); - if (g_dat.hTabIconList != NULL) - TabCtrl_SetImageList(dat->hwndTabs, g_dat.hTabIconList); - - dat->next = NULL; - if (!newData->isChat) { - dat->prev = g_dat.lastParent; - g_dat.lastParent = dat; - } - else { - dat->prev = g_dat.lastChatParent; - g_dat.lastChatParent = dat; - } - if (dat->prev != NULL) - dat->prev->next = dat; - - WindowList_Add(g_dat.hParentWindowList, hwndDlg, (UINT_PTR)hwndDlg); - SubclassTabCtrl(dat->hwndTabs); - - SetContainerWindowStyle(dat); - - MCONTACT hSContact = savePerContact ? dat->hContact : NULL; - dat->bTopmost = db_get_b(hSContact, SRMMMOD, SRMSGSET_TOPMOST, SRMSGDEFSET_TOPMOST); - if (ScriverRestoreWindowPosition(hwndDlg, hSContact, SRMMMOD, (newData->isChat && !savePerContact) ? "chat" : "", 0, SW_HIDE)) - SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE | SWP_HIDEWINDOW); - - if (!savePerContact && db_get_b(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE)) - WindowList_Broadcast(g_dat.hParentWindowList, DM_CASCADENEWWINDOW, (WPARAM)hwndDlg, (LPARAM)&dat->windowWasCascaded); - - HMENU hMenu = GetSystemMenu(hwndDlg, FALSE); - InsertMenu(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); - if (dat->bTopmost) { - InsertMenu(hMenu, 0, MF_BYPOSITION | MF_ENABLED | MF_CHECKED | MF_STRING, IDM_TOPMOST, TranslateT("Always on top")); - SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - } - else InsertMenu(hMenu, 0, MF_BYPOSITION | MF_ENABLED | MF_UNCHECKED | MF_STRING, IDM_TOPMOST, TranslateT("Always on top")); - } - return TRUE; - - case WM_GETMINMAXINFO: - { - MINMAXINFO *mmi = (MINMAXINFO *)lParam; - if (dat->bVMaximized) { - MONITORINFO mi; - HMONITOR hMonitor; - WINDOWPLACEMENT wp; - RECT rcDesktop; - wp.length = sizeof(wp); - GetWindowPlacement(hwndDlg, &wp); - hMonitor = MonitorFromRect(&wp.rcNormalPosition, MONITOR_DEFAULTTONEAREST); - mi.cbSize = sizeof(mi); - GetMonitorInfo(hMonitor, &mi); - rcDesktop = mi.rcWork; - - mmi->ptMaxSize.x = wp.rcNormalPosition.right - wp.rcNormalPosition.left; - mmi->ptMaxSize.y = rcDesktop.bottom - rcDesktop.top; - mmi->ptMaxPosition.x = wp.rcNormalPosition.left; - if (IsIconic(hwndDlg)) - mmi->ptMaxPosition.y = rcDesktop.top; - else - mmi->ptMaxPosition.y = 0; - } - SIZE size; - GetMinimunWindowSize(dat, &size); - mmi->ptMinTrackSize.x = size.cx; - mmi->ptMinTrackSize.y = size.cy; - } - return FALSE; - - case WM_SIZE: - if (wParam == SIZE_MINIMIZED) - dat->bMinimized = 1; - - if (IsIconic(hwndDlg)) - MoveWindow(dat->hwndActive, dat->childRect.left, dat->childRect.top, dat->childRect.right - dat->childRect.left, dat->childRect.bottom - dat->childRect.top, TRUE); - else { - RECT rcStatus, rcChild, rcWindow, rc; - SIZE size; - dat->bMinimized = 0; - GetClientRect(hwndDlg, &rc); - GetWindowRect(hwndDlg, &rcWindow); - rcStatus.top = rcStatus.bottom = 0; - if (dat->flags2 & SMF2_SHOWSTATUSBAR) { - GetWindowRect(dat->hwndStatus, &rcStatus); - SetupStatusBar(dat); - } - MoveWindow(dat->hwndTabs, 0, 2, (rc.right - rc.left), (rc.bottom - rc.top) - (rcStatus.bottom - rcStatus.top) - 2, FALSE); - RedrawWindow(dat->hwndTabs, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE); - GetMinimunWindowSize(dat, &size); - if ((rcWindow.bottom - rcWindow.top) < size.cy || (rcWindow.right - rcWindow.left) < size.cx) { - if ((rcWindow.bottom - rcWindow.top) < size.cy) - rcWindow.bottom = rcWindow.top + size.cy; - if ((rcWindow.right - rcWindow.left) < size.cx) - rcWindow.right = rcWindow.left + size.cx; - MoveWindow(hwndDlg, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE); - } - GetChildWindowRect(dat, &rcChild); - memcpy(&dat->childRect, &rcChild, sizeof(RECT)); - MoveWindow(dat->hwndActive, rcChild.left, rcChild.top, rcChild.right - rcChild.left, rcChild.bottom - rcChild.top, TRUE); - RedrawWindow(GetDlgItem(dat->hwndActive, IDC_LOG), NULL, NULL, RDW_INVALIDATE); - if (dat->flags2 & SMF2_SHOWSTATUSBAR) { - SendMessage(dat->hwndStatus, WM_SIZE, 0, 0); - RedrawWindow(dat->hwndStatus, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); - } - } - return FALSE; - - case WM_SETFOCUS: - if (dat->hwndActive != NULL) - SetFocus(dat->hwndActive); - return TRUE; - - case WM_CLOSE: - if (g_dat.flags2 & SMF2_HIDECONTAINERS && dat->childrenCount > 0) - ShowWindow(hwndDlg, SW_HIDE); - else - DestroyWindow(hwndDlg); - return TRUE; - - case WM_MEASUREITEM: - return Menu_MeasureItem(lParam); - - case WM_DRAWITEM: - { - LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam; - if (dat && dat->hwndActive && dis->hwndItem == dat->hwndStatus) { - MessageWindowTabData *mwtd = GetChildFromHWND(dat, dat->hwndActive); - if (mwtd != NULL) - DrawStatusIcons(mwtd->hContact, dis->hDC, dis->rcItem, 2); - return TRUE; - } - if (dis->hwndItem == dat->hwndTabs) { - DrawTab(dat, dat->hwndTabs, wParam, lParam); - return TRUE; - } - } - return Menu_DrawItem(lParam); - - case WM_COMMAND: - if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, dat->hContact)) - break; - - if (LOWORD(wParam) == IDCANCEL) - return TRUE; - break; - - case WM_NOTIFY: - { - NMHDR *pNMHDR = (NMHDR*)lParam; - if (pNMHDR->hwndFrom == dat->hwndTabs) { - switch (pNMHDR->code) { - case TCN_SELCHANGE: - { - TCITEM tci = { 0 }; - int iSel = TabCtrl_GetCurSel(dat->hwndTabs); - tci.mask = TCIF_PARAM; - if (TabCtrl_GetItem(dat->hwndTabs, iSel, &tci)) { - MessageWindowTabData * mwtd = (MessageWindowTabData *)tci.lParam; - ActivateChild(dat, mwtd->hwnd); - SetFocus(dat->hwndActive); - } - } - break; - - case NM_RCLICK: - TCHITTESTINFO thinfo; - GetCursorPos(&thinfo.pt); - - int x = thinfo.pt.x; - int y = thinfo.pt.y; - ScreenToClient(dat->hwndTabs, &thinfo.pt); - int tabId = TabCtrl_HitTest(dat->hwndTabs, &thinfo); - if (tabId != -1) { - MessageWindowTabData *mwtd = GetChildFromTab(dat->hwndTabs, tabId); - HMENU hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); - HMENU hSubMenu = GetSubMenu(hMenu, 3); - TranslateMenu(hSubMenu); - HMENU hUserMenu = (HMENU)SendMessage(mwtd->hwnd, DM_GETCONTEXTMENU, 0, 0); - if (hUserMenu != NULL) { - InsertMenu(hSubMenu, 0, MF_POPUP | MF_BYPOSITION, (UINT_PTR)hUserMenu, TranslateT("User menu")); - InsertMenu(hSubMenu, 1, MF_SEPARATOR | MF_BYPOSITION, 0, 0); - } - BOOL menuResult = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, x, y, 0, hwndDlg, NULL); - switch (menuResult) { - case IDM_CLOSETAB: - SendMessage(mwtd->hwnd, WM_CLOSE, 0, 0); - break; - case IDM_CLOSEOTHERTABS: - CloseOtherChilden(dat, mwtd->hwnd); - break; - default: - Clist_MenuProcessCommand(LOWORD(menuResult), MPCF_CONTACTMENU, mwtd->hContact); - } - if (hUserMenu != NULL) - DestroyMenu(hUserMenu); - DestroyMenu(hMenu); - } - } - break; - } - else if (pNMHDR->hwndFrom == dat->hwndStatus) { - switch (pNMHDR->code) { - case NM_CLICK: - RECT rc; - NMMOUSE *nm = (NMMOUSE*)lParam; - SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 2, (LPARAM)&rc); - if (nm->pt.x >= rc.left) { - MessageWindowTabData *mwtd = GetChildFromHWND(dat, dat->hwndActive); - if (mwtd != NULL) - CheckStatusIconClick(mwtd->hContact, dat->hwndStatus, nm->pt, rc, 2, (pNMHDR->code == NM_RCLICK ? MBCF_RIGHTBUTTON : 0)); - } - return TRUE; - } - } - } - break; - - case WM_DROPFILES: - SendMessage(dat->hwndActive, WM_DROPFILES, wParam, lParam); - break; - - case WM_TIMER: - if (wParam == TIMERID_FLASHWND) { - if (dat->nFlash < 2 * dat->nFlashMax) { - FlashWindow(hwndDlg, TRUE); - dat->nFlash++; - } - else { - KillTimer(hwndDlg, TIMERID_FLASHWND); - FlashWindow(hwndDlg, FALSE); - } - } - break; - - case WM_CONTEXTMENU: - if (dat->hwndStatus && dat->hwndStatus == (HWND)wParam) { - POINT pt, pt2; - GetCursorPos(&pt); - pt2 = pt; - ScreenToClient(dat->hwndStatus, &pt); - - RECT rc; - SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 2, (LPARAM)&rc); - if (pt.x >= rc.left) { - MessageWindowTabData *mwtd = GetChildFromHWND(dat, dat->hwndActive); - if (mwtd != NULL) - CheckStatusIconClick(mwtd->hContact, dat->hwndStatus, pt, rc, 2, MBCF_RIGHTBUTTON); - break; - } - else SendMessage(dat->hwndActive, WM_CONTEXTMENU, (WPARAM)hwndDlg, 0); - } - break; - - case WM_ACTIVATE: - if (LOWORD(wParam) == WA_INACTIVE) { - ws = GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED; - ws |= dat->flags2 & SMF2_USETRANSPARENCY ? WS_EX_LAYERED : 0; - SetWindowLongPtr(hwndDlg, GWL_EXSTYLE, ws); - if (dat->flags2 & SMF2_USETRANSPARENCY) - SetLayeredWindowAttributes(hwndDlg, RGB(255, 255, 255), (BYTE)(255 - g_dat.inactiveAlpha), LWA_ALPHA); - break; - } - if (dat->hwndActive != NULL) { - ActivateChild(dat, dat->hwndActive); - g_dat.hFocusWnd = dat->hwndActive; - PostMessage(dat->hwndActive, DM_SETFOCUS, 0, msg); - } - if (KillTimer(hwndDlg, TIMERID_FLASHWND)) { - FlashWindow(hwndDlg, FALSE); - dat->nFlash = 0; - } - ws = GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED; - ws |= dat->flags2 & SMF2_USETRANSPARENCY ? WS_EX_LAYERED : 0; - SetWindowLongPtr(hwndDlg, GWL_EXSTYLE, ws); - if (dat->flags2 & SMF2_USETRANSPARENCY) - SetLayeredWindowAttributes(hwndDlg, RGB(255, 255, 255), (BYTE)(255 - g_dat.activeAlpha), LWA_ALPHA); - break; - - case WM_LBUTTONDOWN: - if (!IsZoomed(hwndDlg)) { - POINT pt; - GetCursorPos(&pt); - return SendMessage(hwndDlg, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); - } - break; - - case WM_MOVING: - if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) { - int snapPixels = 10; - RECT *pRect = (RECT *)lParam; - HMONITOR hMonitor = MonitorFromRect(pRect, MONITOR_DEFAULTTONEAREST); - SIZE szSize = { pRect->right - pRect->left, pRect->bottom - pRect->top }; - - MONITORINFO mi; - mi.cbSize = sizeof(mi); - GetMonitorInfo(hMonitor, &mi); - - POINT pt; - GetCursorPos(&pt); - - RECT rcDesktop = mi.rcWork; - pRect->left = pt.x - dat->mouseLBDownPos.x; - pRect->top = pt.y - dat->mouseLBDownPos.y; - pRect->right = pRect->left + szSize.cx; - pRect->bottom = pRect->top + szSize.cy; - if (pRect->top < rcDesktop.top + snapPixels && pRect->top > rcDesktop.top - snapPixels) { - pRect->top = rcDesktop.top; - pRect->bottom = rcDesktop.top + szSize.cy; - } - if (pRect->left < rcDesktop.left + snapPixels && pRect->left > rcDesktop.left - snapPixels) { - pRect->left = rcDesktop.left; - pRect->right = rcDesktop.left + szSize.cx; - } - if (pRect->right < rcDesktop.right + snapPixels && pRect->right > rcDesktop.right - snapPixels) { - pRect->right = rcDesktop.right; - pRect->left = rcDesktop.right - szSize.cx; - } - if (pRect->bottom < rcDesktop.bottom + snapPixels && pRect->bottom > rcDesktop.bottom - snapPixels) { - pRect->bottom = rcDesktop.bottom; - pRect->top = rcDesktop.bottom - szSize.cy; - } - } - break; - - case WM_SYSCOMMAND: - if ((wParam & 0xFFF0) == SC_MAXIMIZE) { - if (GetKeyState(VK_CONTROL) & 0x8000) - dat->bVMaximized = 1; - else - dat->bVMaximized = 0; - } - else if ((wParam & 0xFFF0) == SC_MOVE) { - RECT rc; - GetWindowRect(hwndDlg, &rc); - dat->mouseLBDownPos.x = LOWORD(lParam) - rc.left; - dat->mouseLBDownPos.y = HIWORD(lParam) - rc.top; - } - else if (wParam == IDM_TOPMOST) { - HMENU hMenu = GetSystemMenu(hwndDlg, FALSE); - if (dat->bTopmost) { - CheckMenuItem(hMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_UNCHECKED); - SetWindowPos(hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - dat->bTopmost = FALSE; - } - else { - CheckMenuItem(hMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_CHECKED); - SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - dat->bTopmost = TRUE; - } - } - break; - case WM_DESTROY: - char szSettingName[64]; - - for (int i = dat->childrenCount; i >= 0; i--) { - TCITEM tci; - tci.mask = TCIF_PARAM | TCIF_IMAGE; - if (TabCtrl_GetItem(dat->hwndTabs, i, &tci)) { - mir_free((MessageWindowTabData *)tci.lParam); - ReleaseIcon(tci.iImage); - TabCtrl_DeleteItem(dat->hwndTabs, i); - } - } - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); - WindowList_Remove(g_dat.hParentWindowList, hwndDlg); - { - int savePerContact = db_get_b(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT); - MCONTACT hContact = (savePerContact) ? dat->hContact : NULL; - - WINDOWPLACEMENT wp = { sizeof(wp) }; - GetWindowPlacement(hwndDlg, &wp); - - char *szNamePrefix = (!savePerContact && dat->isChat) ? "chat" : ""; - if (!dat->windowWasCascaded) { - mir_snprintf(szSettingName, "%sx", szNamePrefix); - db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.left); - mir_snprintf(szSettingName, "%sy", szNamePrefix); - db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.top); - } - mir_snprintf(szSettingName, "%swidth", szNamePrefix); - db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.right - wp.rcNormalPosition.left); - mir_snprintf(szSettingName, "%sheight", szNamePrefix); - db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.bottom - wp.rcNormalPosition.top); - db_set_b(hContact, SRMMMOD, SRMSGSET_TOPMOST, (BYTE)dat->bTopmost); - if (g_dat.lastParent == dat) - g_dat.lastParent = dat->prev; - - if (g_dat.lastChatParent == dat) - g_dat.lastChatParent = dat->prev; - - if (dat->prev != NULL) - dat->prev->next = dat->next; - - if (dat->next != NULL) - dat->next->prev = dat->prev; - - UnsubclassTabCtrl(dat->hwndTabs); - mir_free(dat); - } - break; - - case DM_ERRORDECIDED: - break; - - case CM_STARTFLASHING: - if ((GetActiveWindow() != hwndDlg || GetForegroundWindow() != hwndDlg)) {// && !(g_dat.flags2 & SMF2_STAYMINIMIZED)) { - dat->nFlash = 0; - SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); - } - break; - - case CM_POPUPWINDOW: - EnableWindow(hwndDlg, TRUE); - if (wParam) { /* incoming message */ - if (g_dat.flags & SMF_STAYMINIMIZED) { - if (!IsWindowVisible(hwndDlg)) - ShowWindow(hwndDlg, SW_SHOWMINNOACTIVE); - - if (dat->childrenCount == 1 || ((g_dat.flags2 & SMF2_SWITCHTOACTIVE) && (IsIconic(hwndDlg) || GetForegroundWindow() != hwndDlg))) - SendMessage(hwndDlg, CM_ACTIVATECHILD, 0, (LPARAM)lParam); - } - else { - ShowWindow(hwndDlg, IsIconic(hwndDlg) ? SW_SHOWNORMAL : SW_SHOWNA); - - if (dat->childrenCount == 1 || ((g_dat.flags2 & SMF2_SWITCHTOACTIVE) && (IsIconic(hwndDlg) || GetForegroundWindow() != hwndDlg))) - SendMessage(hwndDlg, CM_ACTIVATECHILD, 0, (LPARAM)lParam); - - SetWindowPos(hwndDlg, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); - } - } - else { /* outgoing message */ - ShowWindow(hwndDlg, IsIconic(hwndDlg) ? SW_SHOWNORMAL : SW_SHOW); - SetForegroundWindow(hwndDlg); - SetFocus((HWND)lParam); - } - break; - - case CM_REMOVECHILD: - RemoveChild(dat, (HWND)lParam); - if (dat->childrenCount != 0) - SetFocus(dat->hwndActive); - else - PostMessage(hwndDlg, WM_CLOSE, 0, 0); - return TRUE; - - case CM_ADDCHILD: - AddChild(dat, (HWND)wParam, lParam); - return TRUE; - - case CM_ACTIVATECHILD: - ActivateChild(dat, (HWND)lParam); - return TRUE; - - case CM_ACTIVATEPREV: - ActivatePrevChild(dat, (HWND)lParam); - SetFocus(dat->hwndActive); - return TRUE; - - case CM_ACTIVATENEXT: - ActivateNextChild(dat, (HWND)lParam); - SetFocus(dat->hwndActive); - return TRUE; - - case CM_ACTIVATEBYINDEX: - ActivateChildByIndex(dat, (int)lParam); - SetFocus(dat->hwndActive); - return TRUE; - - case CM_GETCHILDCOUNT: - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetChildCount(dat)); - return TRUE; - - case CM_GETACTIVECHILD: - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)dat->hwndActive); - return TRUE; - - case CM_GETTOOLBARSTATUS: - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)(dat->flags2 & SMF2_SHOWTOOLBAR) != 0); - return TRUE; - - case DM_SENDMESSAGE: - for (int i = 0; i < dat->childrenCount; i++) { - MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i); - SendMessage(mwtd->hwnd, DM_SENDMESSAGE, wParam, lParam); - } - break; - - case DM_OPTIONSAPPLIED: - dat->flags2 = g_dat.flags2; - SetContainerWindowStyle(dat); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - break; - - case CM_UPDATETITLEBAR: - { - HWND hwnd = (HWND)lParam; - TitleBarData *tbd = (TitleBarData *)wParam; - if (tbd != NULL && dat->hwndActive == hwnd) { - if (tbd->iFlags & TBDF_TEXT) { - wchar_t oldtitle[256]; - GetWindowText(hwndDlg, oldtitle, _countof(oldtitle)); - if (mir_wstrcmp(tbd->pszText, oldtitle)) - SetWindowText(hwndDlg, tbd->pszText); - } - if (tbd->iFlags & TBDF_ICON) { - SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)tbd->hIcon); - if (tbd->hIconBig != NULL) - SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)tbd->hIconBig); - if (pTaskbarInterface) - pTaskbarInterface->SetOverlayIcon(hwndDlg, tbd->hIconNot, L""); - } - } - } - break; - - case CM_UPDATESTATUSBAR: - { - HWND hwnd = (HWND)lParam; - StatusBarData *sbd = (StatusBarData *)wParam; - if (sbd != NULL) { - if ((sbd->iFlags & SBDF_TEXT) && dat->hwndActive == hwnd) - SendMessage(dat->hwndStatus, SB_SETTEXT, sbd->iItem, (LPARAM)sbd->pszText); - if ((sbd->iFlags & SBDF_ICON) && dat->hwndActive == hwnd) - SendMessage(dat->hwndStatus, SB_SETICON, sbd->iItem, (LPARAM)sbd->hIcon); - RedrawWindow(dat->hwndStatus, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); - } - } - break; - - case DM_STATUSICONCHANGE: - SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW) | 2, 0); - SetupStatusBar(dat); - RedrawWindow(dat->hwndStatus, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); - break; - - case CM_UPDATETABCONTROL: - { - TabControlData *tcd = (TabControlData*)wParam; - int tabId = GetTabFromHWND(dat, (HWND)lParam); - if (tabId >= 0 && tcd != NULL) { - wchar_t *ptszTemp = NULL; - - TCITEM tci; - tci.mask = 0; - if (tcd->iFlags & TCDF_TEXT) { - tci.mask |= TCIF_TEXT; - tci.pszText = tcd->pszText; - if (g_dat.flags2 & SMF2_LIMITNAMES) { - wchar_t *ltext = limitText(tcd->pszText, g_dat.limitNamesLength); - if (ltext != tcd->pszText) - tci.pszText = ptszTemp = ltext; - } - } - if (tcd->iFlags & TCDF_ICON) { - int iconIdx = -1; - if (tcd->hIcon != NULL) { - TCITEM tci2; - tci2.mask = TCIF_IMAGE; - TabCtrl_GetItem(dat->hwndTabs, tabId, &tci2); - iconIdx = AddOrReplaceIcon(g_dat.hTabIconList, tci2.iImage, tcd->hIcon); - } - tci.mask |= TCIF_IMAGE; - tci.iImage = iconIdx; - } - TabCtrl_SetItem(dat->hwndTabs, tabId, &tci); - mir_free(ptszTemp); - } - } - break; - - case DM_SWITCHINFOBAR: - dat->flags2 ^= SMF2_SHOWINFOBAR; - - for (int i = 0; i < dat->childrenCount; i++) { - MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i); - SendMessage(mwtd->hwnd, DM_SWITCHINFOBAR, 0, 0); - } - SendMessage(hwndDlg, WM_SIZE, 0, 0); - break; - - case DM_SWITCHSTATUSBAR: - dat->flags2 ^= SMF2_SHOWSTATUSBAR; - ShowWindow(dat->hwndStatus, (dat->flags2 & SMF2_SHOWSTATUSBAR) ? SW_SHOW : SW_HIDE); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - break; - - case DM_SWITCHTOOLBAR: - dat->flags2 ^= SMF2_SHOWTOOLBAR; - - for (int i = 0; i < dat->childrenCount; i++) { - MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i); - SendMessage(mwtd->hwnd, DM_SWITCHTOOLBAR, 0, 0); - } - - SendMessage(hwndDlg, WM_SIZE, 0, 0); - break; - - case DM_SWITCHTITLEBAR: - dat->flags2 ^= SMF2_SHOWTITLEBAR; - ws = GetWindowLongPtr(hwndDlg, GWL_STYLE) & ~(WS_CAPTION); - if (dat->flags2 & SMF2_SHOWTITLEBAR) - ws |= WS_CAPTION; - - SetWindowLongPtr(hwndDlg, GWL_STYLE, ws); - RECT rc; - GetWindowRect(hwndDlg, &rc); - SetWindowPos(hwndDlg, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING); - RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); - break; - - case DM_CASCADENEWWINDOW: - if ((HWND)wParam != hwndDlg) { - RECT rcThis, rcNew; - GetWindowRect(hwndDlg, &rcThis); - GetWindowRect((HWND)wParam, &rcNew); - if (abs(rcThis.left - rcNew.left) < 3 && abs(rcThis.top - rcNew.top) < 3) { - int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME); - SetWindowPos((HWND)wParam, 0, rcNew.left + offset, rcNew.top + offset, 0, 0, SWP_NOZORDER | SWP_NOSIZE); - *(int *)lParam = 1; - } - } - break; - } - return FALSE; -} - -static void DrawTab(ParentWindowData *dat, HWND hwnd, WPARAM, LPARAM lParam) -{ - LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam; - int iTabIndex = lpDIS->itemID; - if (iTabIndex < 0) - return; - - TabCtrlData *tcdat = (TabCtrlData*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - HANDLE hTheme = NULL; - int tstate = 0; - wchar_t szLabel[1024]; - TCITEM tci; - tci.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_STATE; - tci.pszText = szLabel; - tci.cchTextMax = _countof(szLabel); - tci.dwStateMask = TCIS_HIGHLIGHTED; - if (TabCtrl_GetItem(hwnd, iTabIndex, &tci)) { - IMAGEINFO info; - RECT rIcon = lpDIS->rcItem; - RECT rect = lpDIS->rcItem; - RECT rectTab = lpDIS->rcItem; - int bSelected = lpDIS->itemState & ODS_SELECTED; - int atTop = (GetWindowLongPtr(hwnd, GWL_STYLE) & TCS_BOTTOM) == 0; - UINT dwFormat; - if (!IsAppThemed()) - FillRect(lpDIS->hDC, &rect, GetSysColorBrush(COLOR_BTNFACE)); - else { - if (lpDIS->itemState & ODS_SELECTED) - tstate = TTIS_SELECTED; - else if (lpDIS->itemState & ODS_FOCUS) - tstate = TTIS_FOCUSED; - else if (lpDIS->itemState & ODS_HOTLIGHT) - tstate = TTIS_HOT; - else - tstate = TTIS_NORMAL; - - if (!bSelected) - InflateRect(&rectTab, 1, 1); - - hTheme = OpenThemeData(hwnd, L"TAB"); - if (IsThemeBackgroundPartiallyTransparent(hTheme, TABP_TABITEM, tstate)) - DrawThemeParentBackground(hwnd, lpDIS->hDC, &rectTab); - DrawThemeBackground(hTheme, lpDIS->hDC, TABP_TABITEM, tstate, &rectTab, NULL); - } - if (atTop) { - dwFormat = DT_SINGLELINE | DT_TOP | DT_CENTER | DT_NOPREFIX | DT_NOCLIP; - rIcon.top = rect.top + GetSystemMetrics(SM_CYEDGE); - if (tci.iImage >= 0) { - rIcon.left = rect.left + GetSystemMetrics(SM_CXEDGE) + (bSelected ? 6 : 2); - ImageList_GetImageInfo(g_dat.hTabIconList, tci.iImage, &info); - ImageList_DrawEx(g_dat.hTabIconList, tci.iImage, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); - rect.left = rIcon.left + (info.rcImage.right - info.rcImage.left); - } - if (dat->flags2 & SMF2_TABCLOSEBUTTON) { - ImageList_GetImageInfo(g_dat.hButtonIconList, 0, &info); - rIcon.left = rect.right - GetSystemMetrics(SM_CXEDGE) - (bSelected ? 6 : 2) - (info.rcImage.right - info.rcImage.left); - ImageList_DrawEx(g_dat.hButtonIconList, 0, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); - rect.right = rIcon.left - 1; - } - rect.top += GetSystemMetrics(SM_CYEDGE) + 2; - } - else { - dwFormat = DT_SINGLELINE | DT_BOTTOM | DT_CENTER | DT_NOPREFIX | DT_NOCLIP; - rIcon.left = rect.left + GetSystemMetrics(SM_CXEDGE) + (bSelected ? 6 : 2); - if (tci.iImage >= 0) { - ImageList_GetImageInfo(g_dat.hTabIconList, tci.iImage, &info); - rIcon.top = rect.bottom - (info.rcImage.bottom - info.rcImage.top) - 1; - ImageList_DrawEx(g_dat.hTabIconList, tci.iImage, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); - rect.left = rIcon.left + (info.rcImage.right - info.rcImage.left); - } - if (dat->flags2 & SMF2_TABCLOSEBUTTON) { - ImageList_GetImageInfo(g_dat.hButtonIconList, 0, &info); - rIcon.top = rect.bottom - (info.rcImage.bottom - info.rcImage.top) - 2; - rIcon.left = rect.right - GetSystemMetrics(SM_CXEDGE) - (bSelected ? 6 : 2) - (info.rcImage.right - info.rcImage.left); - ImageList_DrawEx(g_dat.hButtonIconList, 0, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); - rect.right = rIcon.left - 1; - } - rect.bottom -= GetSystemMetrics(SM_CYEDGE) + 2; - } - - if (hTheme) - DrawThemeText(hTheme, lpDIS->hDC, TABP_TABITEM, tstate, szLabel, -1, dwFormat, 0, &rect); - else - DrawText(lpDIS->hDC, szLabel, -1, &rect, dwFormat); - - if (tcdat->bDragged && iTabIndex == tcdat->destTab && iTabIndex != tcdat->srcTab) { - RECT hlRect = lpDIS->rcItem; - if (bSelected) { - hlRect.bottom -= GetSystemMetrics(SM_CYEDGE); - hlRect.top += GetSystemMetrics(SM_CYEDGE); - hlRect.left += GetSystemMetrics(SM_CXEDGE); - hlRect.right -= GetSystemMetrics(SM_CXEDGE); - } - else { - if (atTop) { - hlRect.top += GetSystemMetrics(SM_CYEDGE); - hlRect.bottom += GetSystemMetrics(SM_CYEDGE); - } - else { - hlRect.top -= GetSystemMetrics(SM_CYEDGE); - hlRect.bottom -= GetSystemMetrics(SM_CYEDGE); - } - } - FrameRect(lpDIS->hDC, &hlRect, GetSysColorBrush(COLOR_HIGHLIGHT)); - hlRect.left++; - hlRect.top++; - hlRect.right--; - hlRect.bottom--; - FrameRect(lpDIS->hDC, &hlRect, GetSysColorBrush(COLOR_HIGHLIGHT)); - } - if (hTheme) - CloseThemeData(hTheme); - } -} - -HWND GetParentWindow(MCONTACT hContact, BOOL bChat) -{ - NewMessageWindowLParam newData = { 0 }; - newData.hContact = hContact; - newData.isChat = bChat; - if (g_dat.flags2 & SMF2_USETABS) { - if (!bChat || !(g_dat.flags2 & SMF2_SEPARATECHATSCONTAINERS)) { - if (g_dat.lastParent != NULL) { - int tabsNum = (int)SendMessage(g_dat.lastParent->hwnd, CM_GETCHILDCOUNT, 0, 0); - if (!(g_dat.flags2 & SMF2_LIMITTABS) || tabsNum < g_dat.limitTabsNum) - return g_dat.lastParent->hwnd; - } - } - else { - if (g_dat.lastChatParent != NULL) { - int tabsNum = (int)SendMessage(g_dat.lastChatParent->hwnd, CM_GETCHILDCOUNT, 0, 0); - if (!(g_dat.flags2 & SMF2_LIMITCHATSTABS) || tabsNum < g_dat.limitChatsTabsNum) { - return g_dat.lastChatParent->hwnd; - } - } - } - } - if (!(g_dat.flags2 & SMF2_SEPARATECHATSCONTAINERS)) - newData.isChat = FALSE; - - return CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGWIN), NULL, DlgProcParentWindow, (LPARAM)&newData); -} diff --git a/plugins/Scriver/src/tabs.cpp b/plugins/Scriver/src/tabs.cpp new file mode 100644 index 0000000000..9c18edc424 --- /dev/null +++ b/plugins/Scriver/src/tabs.cpp @@ -0,0 +1,1520 @@ +/* +Scriver + +Copyright (c) 2000-09 Miranda ICQ/IM project, + +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#define SB_CHAR_WIDTH 40 +#define SB_SENDING_WIDTH 25 +#define SB_UNICODE_WIDTH 18 + +#define TIMEOUT_FLASHWND 900 + +static void DrawTab(ParentWindowData *dat, HWND hwnd, WPARAM wParam, LPARAM lParam); + +///////////////////////////////////////////////////////////////////////////////////////// + +static const wchar_t *titleTokenNames[] = { L"%name%", L"%status%", L"%statusmsg%", L"%account%" }; + +wchar_t* GetWindowTitle(MCONTACT hContact, const char *szProto) +{ + ptrW tmplt; + const wchar_t* tokens[4] = { 0 }; + + CMStringW tszTemplate, tszStatus, tszTitle; + if (hContact && szProto) { + tokens[0] = pcli->pfnGetContactDisplayName(hContact, 0); + tokens[1] = pcli->pfnGetStatusModeDescription(db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE), 0); + + tszStatus = ptrW(db_get_wsa(hContact, "CList", "StatusMsg")); + tszStatus.Replace(L"\r\n", L" "); + tokens[2] = tszStatus; + + char *accModule = Proto_GetBaseAccountName(hContact); + if (accModule != NULL) { + PROTOACCOUNT* proto = Proto_GetAccount(accModule); + if (proto != NULL) + tokens[3] = mir_wstrdup(proto->tszAccountName); + } + + tmplt = db_get_wsa(NULL, SRMMMOD, SRMSGSET_WINDOWTITLE); + if (tmplt != NULL) + tszTemplate = tmplt; + else { + if (g_dat.flags & SMF_STATUSICON) + tszTemplate = L"%name% - "; + else + tszTemplate = L"%name% (%status%) : "; + } + } + + for (const wchar_t *p = tszTemplate; *p; p++) { + if (*p == '%') { + int i; + for (i = 0; i < _countof(titleTokenNames); i++) { + size_t tnlen = mir_wstrlen(titleTokenNames[i]); + if (!wcsncmp(p, titleTokenNames[i], tnlen)) { + if (tokens[i] != NULL) + tszTitle.Append(tokens[i]); + + p += tnlen - 1; + break; + } + } + if (i < _countof(titleTokenNames)) + continue; + } + tszTitle.AppendChar(*p); + } + + if (tmplt == NULL) + tszTitle.Append(TranslateT("Message session")); + + return tszTitle.Detach(); +} + +static int GetChildCount(ParentWindowData *dat) +{ + return TabCtrl_GetItemCount(dat->hwndTabs); +} + +static void GetChildWindowRect(ParentWindowData *dat, RECT *rcChild) +{ + RECT rc, rcStatus, rcTabs; + GetClientRect(dat->hwnd, &rc); + GetClientRect(dat->hwndTabs, &rcTabs); + TabCtrl_AdjustRect(dat->hwndTabs, FALSE, &rcTabs); + rcStatus.top = rcStatus.bottom = 0; + if (dat->flags2 & SMF2_SHOWSTATUSBAR) + GetWindowRect(dat->hwndStatus, &rcStatus); + + rcChild->left = 0; + rcChild->right = rc.right; + if (dat->flags2 & SMF2_TABSATBOTTOM) { + rcChild->top = 2; + if ((dat->flags2 & SMF2_USETABS && !(dat->flags2 & SMF2_HIDEONETAB)) || (dat->childrenCount > 1)) + rcChild->bottom = rcTabs.bottom + 4; + else + rcChild->bottom = rc.bottom - rc.top - (rcStatus.bottom - rcStatus.top); + } + else { + if ((dat->flags2 & SMF2_USETABS && !(dat->flags2 & SMF2_HIDEONETAB)) || (dat->childrenCount > 1)) + rcChild->top = rcTabs.top; + else + rcChild->top = 2; + + rcChild->bottom = rc.bottom - rc.top - (rcStatus.bottom - rcStatus.top); + } +} + +static int GetTabFromHWND(ParentWindowData *dat, HWND child) +{ + int l = TabCtrl_GetItemCount(dat->hwndTabs); + for (int i = 0; i < l; i++) { + TCITEM tci = { 0 }; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(dat->hwndTabs, i, &tci); + MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam; + if (mwtd->hwnd == child) + return i; + } + return -1; +} + +static MessageWindowTabData* GetChildFromTab(HWND hwndTabs, int tabId) +{ + TCITEM tci = { 0 }; + tci.mask = TCIF_PARAM; + if (TabCtrl_GetItem(hwndTabs, tabId, &tci)) + return (MessageWindowTabData *)tci.lParam; + + return NULL; +} + +static MessageWindowTabData* GetChildFromHWND(ParentWindowData *dat, HWND hwnd) +{ + int l = TabCtrl_GetItemCount(dat->hwndTabs); + for (int i = 0; i < l; i++) { + TCITEM tci = { 0 }; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(dat->hwndTabs, i, &tci); + MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam; + if (mwtd->hwnd == hwnd) + return mwtd; + } + return NULL; +} + +static void GetMinimunWindowSize(ParentWindowData *dat, SIZE *size) +{ + MINMAXINFO mmi; + RECT rc, rcWindow; + int minW = 216, minH = 80; + GetWindowRect(dat->hwnd, &rcWindow); + GetChildWindowRect(dat, &rc); + for (int i = 0; i < dat->childrenCount; i++) { + MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i); + SendMessage(mwtd->hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&mmi); + if (i == 0 || mmi.ptMinTrackSize.x > minW) minW = mmi.ptMinTrackSize.x; + if (i == 0 || mmi.ptMinTrackSize.y > minH) minH = mmi.ptMinTrackSize.y; + } + if (dat->bMinimized) { + size->cx = minW; + size->cy = minH; + } + else { + size->cx = minW + (rcWindow.right - rcWindow.left) - (rc.right - rc.left); + size->cy = minH + (rcWindow.bottom - rcWindow.top) - (rc.bottom - rc.top); + } +} + +static void SetupStatusBar(ParentWindowData *dat) +{ + int statusIconNum = GetStatusIconsCount(dat->hContact); + int statwidths[4]; + RECT rc; + GetClientRect(dat->hwnd, &rc); + statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH - SB_UNICODE_WIDTH - 2 * (statusIconNum > 0) - statusIconNum * (GetSystemMetrics(SM_CXSMICON) + 2); + statwidths[1] = rc.right - rc.left - SB_UNICODE_WIDTH - 2 * (statusIconNum > 0) - statusIconNum * (GetSystemMetrics(SM_CXSMICON) + 2); + statwidths[2] = rc.right - rc.left - SB_UNICODE_WIDTH; + statwidths[3] = -1; + SendMessage(dat->hwndStatus, SB_SETPARTS, 4, (LPARAM)statwidths); + SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW) | 2, 0); + SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_NOBORDERS) | 3, 0); +} + +static int AddOrReplaceIcon(HIMAGELIST hList, int prevIndex, HICON hIcon) +{ + int usageIdx = -1; + for (int i = 0; i < g_dat.tabIconListUsageSize; i++) { + if (!g_dat.tabIconListUsage[i].used && usageIdx == -1) + usageIdx = i; + + if (g_dat.tabIconListUsage[i].index == prevIndex) { + usageIdx = i; + break; + } + } + if (usageIdx == -1) { + usageIdx = g_dat.tabIconListUsageSize; + g_dat.tabIconListUsage = (ImageListUsageEntry*)mir_realloc(g_dat.tabIconListUsage, sizeof(ImageListUsageEntry)* (g_dat.tabIconListUsageSize + 1)); + g_dat.tabIconListUsageSize++; + } + else prevIndex = g_dat.tabIconListUsage[usageIdx].index; + + g_dat.tabIconListUsage[usageIdx].used = 1; + g_dat.tabIconListUsage[usageIdx].index = (int)ImageList_ReplaceIcon(hList, prevIndex, hIcon); + return g_dat.tabIconListUsage[usageIdx].index; +} + +static void ReleaseIcon(int index) +{ + for (int i = 0; i < g_dat.tabIconListUsageSize; i++) + if (g_dat.tabIconListUsage[i].index == index) + g_dat.tabIconListUsage[i].used = 0; +} + +static void ActivateChild(ParentWindowData *dat, HWND child) +{ + RECT rcChild; + GetChildWindowRect(dat, &rcChild); + SetWindowPos(child, HWND_TOP, rcChild.left, rcChild.top, rcChild.right - rcChild.left, rcChild.bottom - rcChild.top, SWP_NOSIZE); + + int i = GetTabFromHWND(dat, child); + if (i == -1) + return; + + MessageWindowTabData *mwtd; + if ((mwtd = GetChildFromTab(dat->hwndTabs, i)) == NULL) + return; + + dat->hContact = mwtd->hContact; + if (child != dat->hwndActive) { + HWND prev = dat->hwndActive; + dat->hwndActive = child; + SetupStatusBar(dat); + SendMessage(dat->hwndActive, GC_UPDATESTATUSBAR, 0, 0); + SendMessage(dat->hwndActive, DM_UPDATETITLEBAR, 0, 0); + SendMessage(dat->hwnd, WM_SIZE, 0, 0); + ShowWindow(dat->hwndActive, SW_SHOWNOACTIVATE); + SendMessage(dat->hwndActive, DM_SCROLLLOGTOBOTTOM, 0, 0); + if (prev != NULL) + ShowWindow(prev, SW_HIDE); + } + else SendMessage(dat->hwnd, WM_SIZE, 0, 0); + + TabCtrl_SetCurSel(dat->hwndTabs, i); + SendMessage(dat->hwndActive, DM_ACTIVATE, WA_ACTIVE, 0); +} + +static void AddChild(ParentWindowData *dat, HWND hwnd, MCONTACT hContact) +{ + MessageWindowTabData *mwtd = (MessageWindowTabData *)mir_alloc(sizeof(MessageWindowTabData)); + mwtd->hwnd = hwnd; + mwtd->hContact = hContact; + mwtd->szProto = GetContactProto(hContact); + mwtd->parent = dat; + + dat->childrenCount++; + + TCITEM tci; + tci.mask = TCIF_PARAM | TCIF_IMAGE | TCIF_TEXT; + tci.lParam = (LPARAM)mwtd; + tci.iImage = -1; + tci.pszText = L""; + TabCtrl_InsertItem(dat->hwndTabs, dat->childrenCount - 1, &tci); + SetWindowPos(mwtd->hwnd, HWND_TOP, dat->childRect.left, dat->childRect.top, dat->childRect.right - dat->childRect.left, dat->childRect.bottom - dat->childRect.top, SWP_HIDEWINDOW); + SendMessage(dat->hwnd, WM_SIZE, 0, 0); + + EnableThemeDialogTexture(hwnd, ETDT_ENABLETAB); +} + +static void RemoveChild(ParentWindowData *dat, HWND child) +{ + int tab = GetTabFromHWND(dat, child); + if (tab >= 0) { + TCITEM tci; + tci.mask = TCIF_PARAM | TCIF_IMAGE; + TabCtrl_GetItem(dat->hwndTabs, tab, &tci); + TabCtrl_DeleteItem(dat->hwndTabs, tab); + mir_free((MessageWindowTabData *)tci.lParam); + dat->childrenCount--; + if (child == dat->hwndActive) { + if (tab == TabCtrl_GetItemCount(dat->hwndTabs)) tab--; + if (tab >= 0) + ActivateChild(dat, GetChildFromTab(dat->hwndTabs, tab)->hwnd); + else + dat->hwndActive = NULL; + } + ReleaseIcon(tci.iImage); + } +} + +static void CloseOtherChilden(ParentWindowData *dat, HWND child) +{ + ActivateChild(dat, child); + for (int i = dat->childrenCount - 1; i >= 0; i--) { + MessageWindowTabData *mwtd = GetChildFromTab(dat->hwndTabs, i); + if (mwtd != NULL && mwtd->hwnd != child) + SendMessage(mwtd->hwnd, WM_CLOSE, 0, 0); + } + ActivateChild(dat, child); +} + +static void ActivateNextChild(ParentWindowData *dat, HWND child) +{ + int i = GetTabFromHWND(dat, child); + int l = TabCtrl_GetItemCount(dat->hwndTabs); + i = (i + 1) % l; + ActivateChild(dat, GetChildFromTab(dat->hwndTabs, i)->hwnd); +} + +static void ActivatePrevChild(ParentWindowData *dat, HWND child) +{ + int i = GetTabFromHWND(dat, child); + int l = TabCtrl_GetItemCount(dat->hwndTabs); + i = (i + l - 1) % l; + ActivateChild(dat, GetChildFromTab(dat->hwndTabs, i)->hwnd); +} + +static void ActivateChildByIndex(ParentWindowData *dat, int index) +{ + int l = TabCtrl_GetItemCount(dat->hwndTabs); + if (index < l) { + MessageWindowTabData *mwtd = GetChildFromTab(dat->hwndTabs, index); + if (mwtd != NULL) + ActivateChild(dat, mwtd->hwnd); + } +} + +static void SetContainerWindowStyle(ParentWindowData *dat) +{ + ShowWindow(dat->hwndStatus, (dat->flags2 & SMF2_SHOWSTATUSBAR) ? SW_SHOW : SW_HIDE); + + DWORD ws = GetWindowLongPtr(dat->hwnd, GWL_STYLE) & ~(WS_CAPTION); + if (dat->flags2 & SMF2_SHOWTITLEBAR) + ws |= WS_CAPTION; + + SetWindowLongPtr(dat->hwnd, GWL_STYLE, ws); + + ws = GetWindowLongPtr(dat->hwnd, GWL_EXSTYLE)& ~WS_EX_LAYERED; + ws |= dat->flags2 & SMF2_USETRANSPARENCY ? WS_EX_LAYERED : 0; + SetWindowLongPtr(dat->hwnd, GWL_EXSTYLE, ws); + if (dat->flags2 & SMF2_USETRANSPARENCY) + SetLayeredWindowAttributes(dat->hwnd, RGB(255, 255, 255), (BYTE)(255 - g_dat.inactiveAlpha), LWA_ALPHA); + + ws = GetWindowLongPtr(dat->hwndTabs, GWL_STYLE) & ~(TCS_BOTTOM | 0x2000); + if (dat->flags2 & SMF2_TABSATBOTTOM) + ws |= TCS_BOTTOM; + + ws |= 0x2000; + if (dat->flags2 & SMF2_TABCLOSEBUTTON) + TabCtrl_SetPadding(dat->hwndTabs, GetSystemMetrics(SM_CXEDGE) + 12, GetSystemMetrics(SM_CYEDGE) + 1); + else + TabCtrl_SetPadding(dat->hwndTabs, GetSystemMetrics(SM_CXEDGE) + 4, GetSystemMetrics(SM_CYEDGE) + 1); + + SetWindowLongPtr(dat->hwndTabs, GWL_STYLE, ws); + + RECT rc; + GetWindowRect(dat->hwnd, &rc); + SetWindowPos(dat->hwnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +LRESULT CALLBACK TabCtrlProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + TabCtrlData *dat = (TabCtrlData*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + TCHITTESTINFO thinfo; + int tabId; + + switch (msg) { + case EM_SUBCLASSED: + dat = (TabCtrlData*)mir_alloc(sizeof(TabCtrlData)); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat); + dat->bDragging = FALSE; + dat->bDragged = FALSE; + dat->srcTab = -1; + dat->destTab = -1; + return 0; + + case WM_MBUTTONDOWN: + thinfo.pt.x = LOWORD(lParam); + thinfo.pt.y = HIWORD(lParam); + tabId = TabCtrl_HitTest(hwnd, &thinfo); + if (tabId >= 0) { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(hwnd, tabId, &tci); + MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam; + if (mwtd != NULL) { + SendMessage(mwtd->hwnd, WM_CLOSE, 0, 0); + dat->srcTab = -1; + } + } + return 0; + + case WM_LBUTTONDBLCLK: + thinfo.pt.x = LOWORD(lParam); + thinfo.pt.y = HIWORD(lParam); + tabId = TabCtrl_HitTest(hwnd, &thinfo); + if (tabId >= 0 && tabId == dat->srcTab) { + SendMessage(GetChildFromTab(hwnd, tabId)->hwnd, WM_CLOSE, 0, 0); + dat->srcTab = -1; + } + dat->destTab = -1; + break; + + case WM_LBUTTONDOWN: + if (!dat->bDragging) { + thinfo.pt.x = LOWORD(lParam); + thinfo.pt.y = HIWORD(lParam); + dat->srcTab = TabCtrl_HitTest(hwnd, &thinfo); + + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + if (dat->srcTab >= 0) { + dat->bDragging = TRUE; + dat->bDragged = FALSE; + dat->clickLParam = lParam; + dat->clickWParam = wParam; + dat->lastClickTime = ft.dwLowDateTime; + dat->mouseLBDownPos.x = thinfo.pt.x; + dat->mouseLBDownPos.y = thinfo.pt.y; + SetCapture(hwnd); + } + return 0; + } + break; + + case WM_CAPTURECHANGED: + case WM_LBUTTONUP: + if (dat->bDragging) { + thinfo.pt.x = LOWORD(lParam); + thinfo.pt.y = HIWORD(lParam); + if (dat->bDragged) { + ImageList_DragLeave(GetDesktopWindow()); + ImageList_EndDrag(); + ImageList_Destroy(dat->hDragImageList); + SetCursor(LoadCursor(NULL, IDC_ARROW)); + dat->destTab = TabCtrl_HitTest(hwnd, &thinfo); + if (thinfo.flags != TCHT_NOWHERE && dat->destTab != dat->srcTab) { + NMHDR nmh; + wchar_t sBuffer[501]; + TCITEM item; + int curSel; + curSel = TabCtrl_GetCurSel(hwnd); + item.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_TEXT; + item.pszText = sBuffer; + item.cchTextMax = _countof(sBuffer); + TabCtrl_GetItem(hwnd, dat->srcTab, &item); + sBuffer[_countof(sBuffer) - 1] = '\0'; + + if (curSel == dat->srcTab) + curSel = dat->destTab; + else if (curSel > dat->srcTab && curSel <= dat->destTab) + curSel--; + else if (curSel < dat->srcTab && curSel >= dat->destTab) + curSel++; + + TabCtrl_DeleteItem(hwnd, dat->srcTab); + TabCtrl_InsertItem(hwnd, dat->destTab, &item); + TabCtrl_SetCurSel(hwnd, curSel); + dat->destTab = -1; + nmh.hwndFrom = hwnd; + nmh.idFrom = GetDlgCtrlID(hwnd); + nmh.code = TCN_SELCHANGE; + SendMessage(GetParent(hwnd), WM_NOTIFY, nmh.idFrom, (LPARAM)&nmh); + UpdateWindow(hwnd); + } + else if (thinfo.flags == TCHT_NOWHERE) { + dat->destTab = -1; + + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(hwnd, dat->srcTab, &tci); + MessageWindowTabData *mwtd = (MessageWindowTabData *)tci.lParam; + if (mwtd != NULL) { + HWND hChild = mwtd->hwnd; + MCONTACT hContact = mwtd->hContact; + + POINT pt; + GetCursorPos(&pt); + HWND hParent = WindowFromPoint(pt); + while (GetParent(hParent) != NULL) + hParent = GetParent(hParent); + + hParent = WindowList_Find(g_dat.hParentWindowList, (UINT_PTR)hParent); + if ((hParent != NULL && hParent != GetParent(hwnd)) || (hParent == NULL && mwtd->parent->childrenCount > 1 && (GetKeyState(VK_CONTROL) & 0x8000))) { + if (hParent == NULL) { + hParent = GetParentWindow(hContact, FALSE); + + RECT rc; + GetWindowRect(hParent, &rc); + + rc.right = (rc.right - rc.left); + rc.bottom = (rc.bottom - rc.top); + rc.left = pt.x - rc.right / 2; + rc.top = pt.y - rc.bottom / 2; + HMONITOR hMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST); + + MONITORINFO mi; + mi.cbSize = sizeof(mi); + GetMonitorInfo(hMonitor, &mi); + + RECT rcDesktop = mi.rcWork; + if (rc.left < rcDesktop.left) + rc.left = rcDesktop.left; + if (rc.top < rcDesktop.top) + rc.top = rcDesktop.top; + MoveWindow(hParent, rc.left, rc.top, rc.right, rc.bottom, FALSE); + } + NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_CLOSING); + NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_CLOSE); + SetParent(hChild, hParent); + SendMessage(GetParent(hwnd), CM_REMOVECHILD, 0, (LPARAM)hChild); + SendMessage(hChild, DM_SETPARENT, 0, (LPARAM)hParent); + SendMessage(hParent, CM_ADDCHILD, (WPARAM)hChild, hContact); + SendMessage(hChild, DM_UPDATETABCONTROL, 0, 0); + SendMessage(hParent, CM_ACTIVATECHILD, 0, (LPARAM)hChild); + NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_OPENING); + NotifyLocalWinEvent(hContact, hChild, MSG_WINDOW_EVT_OPEN); + ShowWindow(hParent, SW_SHOWNA); + EnableWindow(hParent, TRUE); + } + } + } + else { + dat->destTab = -1; + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + } + else if (dat->srcTab >= 0 && g_dat.flags2 & SMF2_TABCLOSEBUTTON) { + IMAGEINFO info; + POINT pt; + RECT rect; + int atTop = (GetWindowLongPtr(hwnd, GWL_STYLE) & TCS_BOTTOM) == 0; + TabCtrl_GetItemRect(hwnd, dat->srcTab, &rect); + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + ImageList_GetImageInfo(g_dat.hButtonIconList, 0, &info); + rect.left = rect.right - (info.rcImage.right - info.rcImage.left) - 6; + if (!atTop) + rect.top = rect.bottom - (info.rcImage.bottom - info.rcImage.top); + + if (pt.x >= rect.left && pt.x < rect.left + (info.rcImage.right - info.rcImage.left) && pt.y >= rect.top && pt.y < rect.top + (info.rcImage.bottom - info.rcImage.top)) { + HBITMAP hOldBitmap, hBmp; + HDC hdc = GetDC(NULL); + HDC hdcMem = CreateCompatibleDC(hdc); + pt.x -= rect.left; + pt.y -= rect.top; + hBmp = CreateCompatibleBitmap(hdc, info.rcImage.right - info.rcImage.left + 1, info.rcImage.bottom - info.rcImage.top + 1); + hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBmp); + SetPixel(hdcMem, pt.x, pt.y, 0x000000); + ImageList_DrawEx(g_dat.hButtonIconList, 0, hdcMem, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); + COLORREF color1 = GetPixel(hdcMem, pt.x, pt.y); + SetPixel(hdcMem, pt.x, pt.y, 0xFFFFFF); + ImageList_DrawEx(g_dat.hButtonIconList, 0, hdcMem, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); + COLORREF color2 = GetPixel(hdcMem, pt.x, pt.y); + SelectObject(hdcMem, hOldBitmap); + DeleteDC(hdcMem); + DeleteObject(hBmp); + ReleaseDC(NULL, hdc); + if (color1 != 0x000000 || color2 != 0xFFFFFF) { + SendMessage(GetChildFromTab(hwnd, dat->srcTab)->hwnd, WM_CLOSE, 0, 0); + dat->srcTab = -1; + } + } + else SendMessage(hwnd, WM_LBUTTONDOWN, dat->clickWParam, dat->clickLParam); + } + else SendMessage(hwnd, WM_LBUTTONDOWN, dat->clickWParam, dat->clickLParam); + + dat->bDragged = dat->bDragging = FALSE; + dat->destTab = -1; + ReleaseCapture(); + } + break; + + case WM_MOUSEMOVE: + if (wParam & MK_LBUTTON) { + if (dat->bDragging) { + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + thinfo.pt.x = LOWORD(lParam); + thinfo.pt.y = HIWORD(lParam); + if (!dat->bDragged) { + if ((abs(thinfo.pt.x - dat->mouseLBDownPos.x) < 3 && abs(thinfo.pt.y - dat->mouseLBDownPos.y) < 3) + || (ft.dwLowDateTime - dat->lastClickTime) < 10 * 1000 * 150) + break; + } + if (!dat->bDragged) { + POINT pt; + RECT rect; + RECT rect2; + HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 254)); + GetCursorPos(&pt); + TabCtrl_GetItemRect(hwnd, dat->srcTab, &rect); + rect.right -= rect.left - 1; + rect.bottom -= rect.top - 1; + rect2.left = 0; rect2.right = rect.right; rect2.top = 0; rect2.bottom = rect.bottom; + dat->hDragImageList = ImageList_Create(rect.right, rect.bottom, ILC_COLOR | ILC_MASK, 0, 1); + HDC hDC = GetDC(hwnd); + HDC hMemDC = CreateCompatibleDC(hDC); + HBITMAP hBitmap = CreateCompatibleBitmap(hDC, rect.right, rect.bottom); + HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); + FillRect(hMemDC, &rect2, hBrush); + SetWindowOrgEx(hMemDC, rect.left, rect.top, NULL); + SendMessage(hwnd, WM_PRINTCLIENT, (WPARAM)hMemDC, PRF_CLIENT); + SelectObject(hMemDC, hOldBitmap); + ImageList_AddMasked(dat->hDragImageList, hBitmap, RGB(255, 0, 254)); + DeleteObject(hBitmap); + DeleteObject(hBrush); + ReleaseDC(hwnd, hDC); + DeleteDC(hMemDC); + ImageList_BeginDrag(dat->hDragImageList, 0, dat->mouseLBDownPos.x - rect.left, dat->mouseLBDownPos.y - rect.top); + ImageList_DragEnter(GetDesktopWindow(), pt.x, pt.y); + SetCursor(hDragCursor); + dat->mouseLBDownPos.x = thinfo.pt.x; + dat->mouseLBDownPos.y = thinfo.pt.y; + } + else { + POINT pt; + GetCursorPos(&pt); + thinfo.pt = pt; + ScreenToClient(hwnd, &thinfo.pt); + int newDest = TabCtrl_HitTest(hwnd, &thinfo); + if (thinfo.flags == TCHT_NOWHERE) + newDest = -1; + + if (newDest != dat->destTab) { + dat->destTab = newDest; + ImageList_DragLeave(GetDesktopWindow()); + RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); + ImageList_DragEnter(GetDesktopWindow(), pt.x, pt.y); + } + else ImageList_DragMove(pt.x, pt.y); + } + dat->bDragged = TRUE; + return 0; + } + } + break; + + case EM_UNSUBCLASSED: + mir_free(dat); + return 0; + } + return mir_callNextSubclass(hwnd, TabCtrlProc, msg, wParam, lParam); +} + +__forceinline void SubclassTabCtrl(HWND hwnd) +{ + mir_subclassWindow(hwnd, TabCtrlProc); + SendMessage(hwnd, EM_SUBCLASSED, 0, 0); +} + +__forceinline void UnsubclassTabCtrl(HWND hwnd) +{ + SendMessage(hwnd, EM_UNSUBCLASSED, 0, 0); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static int ScriverRestoreWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix, int flags, int showCmd) +{ + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + GetWindowPlacement(hwnd, &wp); + + char szSettingName[64]; + mir_snprintf(szSettingName, "%sx", szNamePrefix); + int x = db_get_dw(hContact, szModule, szSettingName, -1); + mir_snprintf(szSettingName, "%sy", szNamePrefix); + int y = db_get_dw(hContact, szModule, szSettingName, -1); + if (x == -1) + return 1; + + if (flags & RWPF_NOSIZE) + OffsetRect(&wp.rcNormalPosition, x - wp.rcNormalPosition.left, y - wp.rcNormalPosition.top); + else { + wp.rcNormalPosition.left = x; + wp.rcNormalPosition.top = y; + mir_snprintf(szSettingName, "%swidth", szNamePrefix); + wp.rcNormalPosition.right = wp.rcNormalPosition.left + db_get_dw(hContact, szModule, szSettingName, -1); + mir_snprintf(szSettingName, "%sheight", szNamePrefix); + wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + db_get_dw(hContact, szModule, szSettingName, -1); + } + wp.flags = 0; + wp.showCmd = showCmd; + + HMONITOR hMonitor = MonitorFromRect(&wp.rcNormalPosition, MONITOR_DEFAULTTONEAREST); + MONITORINFO mi; + mi.cbSize = sizeof(mi); + GetMonitorInfo(hMonitor, &mi); + RECT rcDesktop = mi.rcWork; + if (wp.rcNormalPosition.left > rcDesktop.right || wp.rcNormalPosition.top > rcDesktop.bottom || + wp.rcNormalPosition.right < rcDesktop.left || wp.rcNormalPosition.bottom < rcDesktop.top) return 1; + SetWindowPlacement(hwnd, &wp); + return 0; +} + +static INT_PTR CALLBACK DlgProcParentWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + ParentWindowData *dat = (ParentWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + if (!dat && msg != WM_INITDIALOG) + return FALSE; + + DWORD ws; + + switch (msg) { + case WM_INITDIALOG: + { + int savePerContact = db_get_b(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT); + NewMessageWindowLParam *newData = (NewMessageWindowLParam *)lParam; + dat = (ParentWindowData *)mir_alloc(sizeof(ParentWindowData)); + dat->hContact = newData->hContact; + dat->nFlash = 0; + dat->nFlashMax = db_get_b(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT); + dat->childrenCount = 0; + dat->hwnd = hwndDlg; + dat->mouseLBDown = 0; + dat->windowWasCascaded = 0; + dat->bMinimized = 0; + dat->bVMaximized = 0; + dat->flags2 = g_dat.flags2; + dat->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL); + dat->isChat = newData->isChat; + SendMessage(dat->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0); + //SetupStatusBar(dat); + dat->hwndTabs = GetDlgItem(hwndDlg, IDC_TABS); + dat->hwndActive = NULL; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + if (g_dat.hTabIconList != NULL) + TabCtrl_SetImageList(dat->hwndTabs, g_dat.hTabIconList); + + dat->next = NULL; + if (!newData->isChat) { + dat->prev = g_dat.lastParent; + g_dat.lastParent = dat; + } + else { + dat->prev = g_dat.lastChatParent; + g_dat.lastChatParent = dat; + } + if (dat->prev != NULL) + dat->prev->next = dat; + + WindowList_Add(g_dat.hParentWindowList, hwndDlg, (UINT_PTR)hwndDlg); + SubclassTabCtrl(dat->hwndTabs); + + SetContainerWindowStyle(dat); + + MCONTACT hSContact = savePerContact ? dat->hContact : NULL; + dat->bTopmost = db_get_b(hSContact, SRMMMOD, SRMSGSET_TOPMOST, SRMSGDEFSET_TOPMOST); + if (ScriverRestoreWindowPosition(hwndDlg, hSContact, SRMMMOD, (newData->isChat && !savePerContact) ? "chat" : "", 0, SW_HIDE)) + SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE | SWP_HIDEWINDOW); + + if (!savePerContact && db_get_b(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE)) + WindowList_Broadcast(g_dat.hParentWindowList, DM_CASCADENEWWINDOW, (WPARAM)hwndDlg, (LPARAM)&dat->windowWasCascaded); + + HMENU hMenu = GetSystemMenu(hwndDlg, FALSE); + InsertMenu(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + if (dat->bTopmost) { + InsertMenu(hMenu, 0, MF_BYPOSITION | MF_ENABLED | MF_CHECKED | MF_STRING, IDM_TOPMOST, TranslateT("Always on top")); + SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + } + else InsertMenu(hMenu, 0, MF_BYPOSITION | MF_ENABLED | MF_UNCHECKED | MF_STRING, IDM_TOPMOST, TranslateT("Always on top")); + } + return TRUE; + + case WM_GETMINMAXINFO: + { + MINMAXINFO *mmi = (MINMAXINFO *)lParam; + if (dat->bVMaximized) { + MONITORINFO mi; + HMONITOR hMonitor; + WINDOWPLACEMENT wp; + RECT rcDesktop; + wp.length = sizeof(wp); + GetWindowPlacement(hwndDlg, &wp); + hMonitor = MonitorFromRect(&wp.rcNormalPosition, MONITOR_DEFAULTTONEAREST); + mi.cbSize = sizeof(mi); + GetMonitorInfo(hMonitor, &mi); + rcDesktop = mi.rcWork; + + mmi->ptMaxSize.x = wp.rcNormalPosition.right - wp.rcNormalPosition.left; + mmi->ptMaxSize.y = rcDesktop.bottom - rcDesktop.top; + mmi->ptMaxPosition.x = wp.rcNormalPosition.left; + if (IsIconic(hwndDlg)) + mmi->ptMaxPosition.y = rcDesktop.top; + else + mmi->ptMaxPosition.y = 0; + } + SIZE size; + GetMinimunWindowSize(dat, &size); + mmi->ptMinTrackSize.x = size.cx; + mmi->ptMinTrackSize.y = size.cy; + } + return FALSE; + + case WM_SIZE: + if (wParam == SIZE_MINIMIZED) + dat->bMinimized = 1; + + if (IsIconic(hwndDlg)) + MoveWindow(dat->hwndActive, dat->childRect.left, dat->childRect.top, dat->childRect.right - dat->childRect.left, dat->childRect.bottom - dat->childRect.top, TRUE); + else { + RECT rcStatus, rcChild, rcWindow, rc; + SIZE size; + dat->bMinimized = 0; + GetClientRect(hwndDlg, &rc); + GetWindowRect(hwndDlg, &rcWindow); + rcStatus.top = rcStatus.bottom = 0; + if (dat->flags2 & SMF2_SHOWSTATUSBAR) { + GetWindowRect(dat->hwndStatus, &rcStatus); + SetupStatusBar(dat); + } + MoveWindow(dat->hwndTabs, 0, 2, (rc.right - rc.left), (rc.bottom - rc.top) - (rcStatus.bottom - rcStatus.top) - 2, FALSE); + RedrawWindow(dat->hwndTabs, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE); + GetMinimunWindowSize(dat, &size); + if ((rcWindow.bottom - rcWindow.top) < size.cy || (rcWindow.right - rcWindow.left) < size.cx) { + if ((rcWindow.bottom - rcWindow.top) < size.cy) + rcWindow.bottom = rcWindow.top + size.cy; + if ((rcWindow.right - rcWindow.left) < size.cx) + rcWindow.right = rcWindow.left + size.cx; + MoveWindow(hwndDlg, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE); + } + GetChildWindowRect(dat, &rcChild); + memcpy(&dat->childRect, &rcChild, sizeof(RECT)); + MoveWindow(dat->hwndActive, rcChild.left, rcChild.top, rcChild.right - rcChild.left, rcChild.bottom - rcChild.top, TRUE); + RedrawWindow(GetDlgItem(dat->hwndActive, IDC_LOG), NULL, NULL, RDW_INVALIDATE); + if (dat->flags2 & SMF2_SHOWSTATUSBAR) { + SendMessage(dat->hwndStatus, WM_SIZE, 0, 0); + RedrawWindow(dat->hwndStatus, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); + } + } + return FALSE; + + case WM_SETFOCUS: + if (dat->hwndActive != NULL) + SetFocus(dat->hwndActive); + return TRUE; + + case WM_CLOSE: + if (g_dat.flags2 & SMF2_HIDECONTAINERS && dat->childrenCount > 0) + ShowWindow(hwndDlg, SW_HIDE); + else + DestroyWindow(hwndDlg); + return TRUE; + + case WM_MEASUREITEM: + return Menu_MeasureItem(lParam); + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam; + if (dat && dat->hwndActive && dis->hwndItem == dat->hwndStatus) { + MessageWindowTabData *mwtd = GetChildFromHWND(dat, dat->hwndActive); + if (mwtd != NULL) + DrawStatusIcons(mwtd->hContact, dis->hDC, dis->rcItem, 2); + return TRUE; + } + if (dis->hwndItem == dat->hwndTabs) { + DrawTab(dat, dat->hwndTabs, wParam, lParam); + return TRUE; + } + } + return Menu_DrawItem(lParam); + + case WM_COMMAND: + if (Clist_MenuProcessCommand(LOWORD(wParam), MPCF_CONTACTMENU, dat->hContact)) + break; + + if (LOWORD(wParam) == IDCANCEL) + return TRUE; + break; + + case WM_NOTIFY: + { + NMHDR *pNMHDR = (NMHDR*)lParam; + if (pNMHDR->hwndFrom == dat->hwndTabs) { + switch (pNMHDR->code) { + case TCN_SELCHANGE: + { + TCITEM tci = { 0 }; + int iSel = TabCtrl_GetCurSel(dat->hwndTabs); + tci.mask = TCIF_PARAM; + if (TabCtrl_GetItem(dat->hwndTabs, iSel, &tci)) { + MessageWindowTabData * mwtd = (MessageWindowTabData *)tci.lParam; + ActivateChild(dat, mwtd->hwnd); + SetFocus(dat->hwndActive); + } + } + break; + + case NM_RCLICK: + TCHITTESTINFO thinfo; + GetCursorPos(&thinfo.pt); + + int x = thinfo.pt.x; + int y = thinfo.pt.y; + ScreenToClient(dat->hwndTabs, &thinfo.pt); + int tabId = TabCtrl_HitTest(dat->hwndTabs, &thinfo); + if (tabId != -1) { + MessageWindowTabData *mwtd = GetChildFromTab(dat->hwndTabs, tabId); + HMENU hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); + HMENU hSubMenu = GetSubMenu(hMenu, 3); + TranslateMenu(hSubMenu); + HMENU hUserMenu = (HMENU)SendMessage(mwtd->hwnd, DM_GETCONTEXTMENU, 0, 0); + if (hUserMenu != NULL) { + InsertMenu(hSubMenu, 0, MF_POPUP | MF_BYPOSITION, (UINT_PTR)hUserMenu, TranslateT("User menu")); + InsertMenu(hSubMenu, 1, MF_SEPARATOR | MF_BYPOSITION, 0, 0); + } + BOOL menuResult = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, x, y, 0, hwndDlg, NULL); + switch (menuResult) { + case IDM_CLOSETAB: + SendMessage(mwtd->hwnd, WM_CLOSE, 0, 0); + break; + case IDM_CLOSEOTHERTABS: + CloseOtherChilden(dat, mwtd->hwnd); + break; + default: + Clist_MenuProcessCommand(LOWORD(menuResult), MPCF_CONTACTMENU, mwtd->hContact); + } + if (hUserMenu != NULL) + DestroyMenu(hUserMenu); + DestroyMenu(hMenu); + } + } + break; + } + else if (pNMHDR->hwndFrom == dat->hwndStatus) { + switch (pNMHDR->code) { + case NM_CLICK: + RECT rc; + NMMOUSE *nm = (NMMOUSE*)lParam; + SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 2, (LPARAM)&rc); + if (nm->pt.x >= rc.left) { + MessageWindowTabData *mwtd = GetChildFromHWND(dat, dat->hwndActive); + if (mwtd != NULL) + CheckStatusIconClick(mwtd->hContact, dat->hwndStatus, nm->pt, rc, 2, (pNMHDR->code == NM_RCLICK ? MBCF_RIGHTBUTTON : 0)); + } + return TRUE; + } + } + } + break; + + case WM_DROPFILES: + SendMessage(dat->hwndActive, WM_DROPFILES, wParam, lParam); + break; + + case WM_TIMER: + if (wParam == TIMERID_FLASHWND) { + if (dat->nFlash < 2 * dat->nFlashMax) { + FlashWindow(hwndDlg, TRUE); + dat->nFlash++; + } + else { + KillTimer(hwndDlg, TIMERID_FLASHWND); + FlashWindow(hwndDlg, FALSE); + } + } + break; + + case WM_CONTEXTMENU: + if (dat->hwndStatus && dat->hwndStatus == (HWND)wParam) { + POINT pt, pt2; + GetCursorPos(&pt); + pt2 = pt; + ScreenToClient(dat->hwndStatus, &pt); + + RECT rc; + SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 2, (LPARAM)&rc); + if (pt.x >= rc.left) { + MessageWindowTabData *mwtd = GetChildFromHWND(dat, dat->hwndActive); + if (mwtd != NULL) + CheckStatusIconClick(mwtd->hContact, dat->hwndStatus, pt, rc, 2, MBCF_RIGHTBUTTON); + break; + } + else SendMessage(dat->hwndActive, WM_CONTEXTMENU, (WPARAM)hwndDlg, 0); + } + break; + + case WM_ACTIVATE: + if (LOWORD(wParam) == WA_INACTIVE) { + ws = GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED; + ws |= dat->flags2 & SMF2_USETRANSPARENCY ? WS_EX_LAYERED : 0; + SetWindowLongPtr(hwndDlg, GWL_EXSTYLE, ws); + if (dat->flags2 & SMF2_USETRANSPARENCY) + SetLayeredWindowAttributes(hwndDlg, RGB(255, 255, 255), (BYTE)(255 - g_dat.inactiveAlpha), LWA_ALPHA); + break; + } + if (dat->hwndActive != NULL) { + ActivateChild(dat, dat->hwndActive); + g_dat.hFocusWnd = dat->hwndActive; + PostMessage(dat->hwndActive, DM_SETFOCUS, 0, msg); + } + if (KillTimer(hwndDlg, TIMERID_FLASHWND)) { + FlashWindow(hwndDlg, FALSE); + dat->nFlash = 0; + } + ws = GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & ~WS_EX_LAYERED; + ws |= dat->flags2 & SMF2_USETRANSPARENCY ? WS_EX_LAYERED : 0; + SetWindowLongPtr(hwndDlg, GWL_EXSTYLE, ws); + if (dat->flags2 & SMF2_USETRANSPARENCY) + SetLayeredWindowAttributes(hwndDlg, RGB(255, 255, 255), (BYTE)(255 - g_dat.activeAlpha), LWA_ALPHA); + break; + + case WM_LBUTTONDOWN: + if (!IsZoomed(hwndDlg)) { + POINT pt; + GetCursorPos(&pt); + return SendMessage(hwndDlg, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); + } + break; + + case WM_MOVING: + if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) { + int snapPixels = 10; + RECT *pRect = (RECT *)lParam; + HMONITOR hMonitor = MonitorFromRect(pRect, MONITOR_DEFAULTTONEAREST); + SIZE szSize = { pRect->right - pRect->left, pRect->bottom - pRect->top }; + + MONITORINFO mi; + mi.cbSize = sizeof(mi); + GetMonitorInfo(hMonitor, &mi); + + POINT pt; + GetCursorPos(&pt); + + RECT rcDesktop = mi.rcWork; + pRect->left = pt.x - dat->mouseLBDownPos.x; + pRect->top = pt.y - dat->mouseLBDownPos.y; + pRect->right = pRect->left + szSize.cx; + pRect->bottom = pRect->top + szSize.cy; + if (pRect->top < rcDesktop.top + snapPixels && pRect->top > rcDesktop.top - snapPixels) { + pRect->top = rcDesktop.top; + pRect->bottom = rcDesktop.top + szSize.cy; + } + if (pRect->left < rcDesktop.left + snapPixels && pRect->left > rcDesktop.left - snapPixels) { + pRect->left = rcDesktop.left; + pRect->right = rcDesktop.left + szSize.cx; + } + if (pRect->right < rcDesktop.right + snapPixels && pRect->right > rcDesktop.right - snapPixels) { + pRect->right = rcDesktop.right; + pRect->left = rcDesktop.right - szSize.cx; + } + if (pRect->bottom < rcDesktop.bottom + snapPixels && pRect->bottom > rcDesktop.bottom - snapPixels) { + pRect->bottom = rcDesktop.bottom; + pRect->top = rcDesktop.bottom - szSize.cy; + } + } + break; + + case WM_SYSCOMMAND: + if ((wParam & 0xFFF0) == SC_MAXIMIZE) { + if (GetKeyState(VK_CONTROL) & 0x8000) + dat->bVMaximized = 1; + else + dat->bVMaximized = 0; + } + else if ((wParam & 0xFFF0) == SC_MOVE) { + RECT rc; + GetWindowRect(hwndDlg, &rc); + dat->mouseLBDownPos.x = LOWORD(lParam) - rc.left; + dat->mouseLBDownPos.y = HIWORD(lParam) - rc.top; + } + else if (wParam == IDM_TOPMOST) { + HMENU hMenu = GetSystemMenu(hwndDlg, FALSE); + if (dat->bTopmost) { + CheckMenuItem(hMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_UNCHECKED); + SetWindowPos(hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + dat->bTopmost = FALSE; + } + else { + CheckMenuItem(hMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_CHECKED); + SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + dat->bTopmost = TRUE; + } + } + break; + case WM_DESTROY: + char szSettingName[64]; + + for (int i = dat->childrenCount; i >= 0; i--) { + TCITEM tci; + tci.mask = TCIF_PARAM | TCIF_IMAGE; + if (TabCtrl_GetItem(dat->hwndTabs, i, &tci)) { + mir_free((MessageWindowTabData *)tci.lParam); + ReleaseIcon(tci.iImage); + TabCtrl_DeleteItem(dat->hwndTabs, i); + } + } + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + WindowList_Remove(g_dat.hParentWindowList, hwndDlg); + { + int savePerContact = db_get_b(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT); + MCONTACT hContact = (savePerContact) ? dat->hContact : NULL; + + WINDOWPLACEMENT wp = { sizeof(wp) }; + GetWindowPlacement(hwndDlg, &wp); + + char *szNamePrefix = (!savePerContact && dat->isChat) ? "chat" : ""; + if (!dat->windowWasCascaded) { + mir_snprintf(szSettingName, "%sx", szNamePrefix); + db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.left); + mir_snprintf(szSettingName, "%sy", szNamePrefix); + db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.top); + } + mir_snprintf(szSettingName, "%swidth", szNamePrefix); + db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.right - wp.rcNormalPosition.left); + mir_snprintf(szSettingName, "%sheight", szNamePrefix); + db_set_dw(hContact, SRMMMOD, szSettingName, wp.rcNormalPosition.bottom - wp.rcNormalPosition.top); + db_set_b(hContact, SRMMMOD, SRMSGSET_TOPMOST, (BYTE)dat->bTopmost); + if (g_dat.lastParent == dat) + g_dat.lastParent = dat->prev; + + if (g_dat.lastChatParent == dat) + g_dat.lastChatParent = dat->prev; + + if (dat->prev != NULL) + dat->prev->next = dat->next; + + if (dat->next != NULL) + dat->next->prev = dat->prev; + + UnsubclassTabCtrl(dat->hwndTabs); + mir_free(dat); + } + break; + + case DM_ERRORDECIDED: + break; + + case CM_STARTFLASHING: + if ((GetActiveWindow() != hwndDlg || GetForegroundWindow() != hwndDlg)) {// && !(g_dat.flags2 & SMF2_STAYMINIMIZED)) { + dat->nFlash = 0; + SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); + } + break; + + case CM_POPUPWINDOW: + EnableWindow(hwndDlg, TRUE); + if (wParam) { /* incoming message */ + if (g_dat.flags & SMF_STAYMINIMIZED) { + if (!IsWindowVisible(hwndDlg)) + ShowWindow(hwndDlg, SW_SHOWMINNOACTIVE); + + if (dat->childrenCount == 1 || ((g_dat.flags2 & SMF2_SWITCHTOACTIVE) && (IsIconic(hwndDlg) || GetForegroundWindow() != hwndDlg))) + SendMessage(hwndDlg, CM_ACTIVATECHILD, 0, (LPARAM)lParam); + } + else { + ShowWindow(hwndDlg, IsIconic(hwndDlg) ? SW_SHOWNORMAL : SW_SHOWNA); + + if (dat->childrenCount == 1 || ((g_dat.flags2 & SMF2_SWITCHTOACTIVE) && (IsIconic(hwndDlg) || GetForegroundWindow() != hwndDlg))) + SendMessage(hwndDlg, CM_ACTIVATECHILD, 0, (LPARAM)lParam); + + SetWindowPos(hwndDlg, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + } + } + else { /* outgoing message */ + ShowWindow(hwndDlg, IsIconic(hwndDlg) ? SW_SHOWNORMAL : SW_SHOW); + SetForegroundWindow(hwndDlg); + SetFocus((HWND)lParam); + } + break; + + case CM_REMOVECHILD: + RemoveChild(dat, (HWND)lParam); + if (dat->childrenCount != 0) + SetFocus(dat->hwndActive); + else + PostMessage(hwndDlg, WM_CLOSE, 0, 0); + return TRUE; + + case CM_ADDCHILD: + AddChild(dat, (HWND)wParam, lParam); + return TRUE; + + case CM_ACTIVATECHILD: + ActivateChild(dat, (HWND)lParam); + return TRUE; + + case CM_ACTIVATEPREV: + ActivatePrevChild(dat, (HWND)lParam); + SetFocus(dat->hwndActive); + return TRUE; + + case CM_ACTIVATENEXT: + ActivateNextChild(dat, (HWND)lParam); + SetFocus(dat->hwndActive); + return TRUE; + + case CM_ACTIVATEBYINDEX: + ActivateChildByIndex(dat, (int)lParam); + SetFocus(dat->hwndActive); + return TRUE; + + case CM_GETCHILDCOUNT: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetChildCount(dat)); + return TRUE; + + case CM_GETACTIVECHILD: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)dat->hwndActive); + return TRUE; + + case CM_GETTOOLBARSTATUS: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)(dat->flags2 & SMF2_SHOWTOOLBAR) != 0); + return TRUE; + + case DM_SENDMESSAGE: + for (int i = 0; i < dat->childrenCount; i++) { + MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i); + SendMessage(mwtd->hwnd, DM_SENDMESSAGE, wParam, lParam); + } + break; + + case DM_OPTIONSAPPLIED: + dat->flags2 = g_dat.flags2; + SetContainerWindowStyle(dat); + SendMessage(hwndDlg, WM_SIZE, 0, 0); + break; + + case CM_UPDATETITLEBAR: + { + HWND hwnd = (HWND)lParam; + TitleBarData *tbd = (TitleBarData *)wParam; + if (tbd != NULL && dat->hwndActive == hwnd) { + if (tbd->iFlags & TBDF_TEXT) { + wchar_t oldtitle[256]; + GetWindowText(hwndDlg, oldtitle, _countof(oldtitle)); + if (mir_wstrcmp(tbd->pszText, oldtitle)) + SetWindowText(hwndDlg, tbd->pszText); + } + if (tbd->iFlags & TBDF_ICON) { + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)tbd->hIcon); + if (tbd->hIconBig != NULL) + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)tbd->hIconBig); + if (pTaskbarInterface) + pTaskbarInterface->SetOverlayIcon(hwndDlg, tbd->hIconNot, L""); + } + } + } + break; + + case CM_UPDATESTATUSBAR: + { + HWND hwnd = (HWND)lParam; + StatusBarData *sbd = (StatusBarData *)wParam; + if (sbd != NULL) { + if ((sbd->iFlags & SBDF_TEXT) && dat->hwndActive == hwnd) + SendMessage(dat->hwndStatus, SB_SETTEXT, sbd->iItem, (LPARAM)sbd->pszText); + if ((sbd->iFlags & SBDF_ICON) && dat->hwndActive == hwnd) + SendMessage(dat->hwndStatus, SB_SETICON, sbd->iItem, (LPARAM)sbd->hIcon); + RedrawWindow(dat->hwndStatus, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); + } + } + break; + + case DM_STATUSICONCHANGE: + SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW) | 2, 0); + SetupStatusBar(dat); + RedrawWindow(dat->hwndStatus, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); + break; + + case CM_UPDATETABCONTROL: + { + TabControlData *tcd = (TabControlData*)wParam; + int tabId = GetTabFromHWND(dat, (HWND)lParam); + if (tabId >= 0 && tcd != NULL) { + wchar_t *ptszTemp = NULL; + + TCITEM tci; + tci.mask = 0; + if (tcd->iFlags & TCDF_TEXT) { + tci.mask |= TCIF_TEXT; + tci.pszText = tcd->pszText; + if (g_dat.flags2 & SMF2_LIMITNAMES) { + wchar_t *ltext = limitText(tcd->pszText, g_dat.limitNamesLength); + if (ltext != tcd->pszText) + tci.pszText = ptszTemp = ltext; + } + } + if (tcd->iFlags & TCDF_ICON) { + int iconIdx = -1; + if (tcd->hIcon != NULL) { + TCITEM tci2; + tci2.mask = TCIF_IMAGE; + TabCtrl_GetItem(dat->hwndTabs, tabId, &tci2); + iconIdx = AddOrReplaceIcon(g_dat.hTabIconList, tci2.iImage, tcd->hIcon); + } + tci.mask |= TCIF_IMAGE; + tci.iImage = iconIdx; + } + TabCtrl_SetItem(dat->hwndTabs, tabId, &tci); + mir_free(ptszTemp); + } + } + break; + + case DM_SWITCHINFOBAR: + dat->flags2 ^= SMF2_SHOWINFOBAR; + + for (int i = 0; i < dat->childrenCount; i++) { + MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i); + SendMessage(mwtd->hwnd, DM_SWITCHINFOBAR, 0, 0); + } + SendMessage(hwndDlg, WM_SIZE, 0, 0); + break; + + case DM_SWITCHSTATUSBAR: + dat->flags2 ^= SMF2_SHOWSTATUSBAR; + ShowWindow(dat->hwndStatus, (dat->flags2 & SMF2_SHOWSTATUSBAR) ? SW_SHOW : SW_HIDE); + SendMessage(hwndDlg, WM_SIZE, 0, 0); + break; + + case DM_SWITCHTOOLBAR: + dat->flags2 ^= SMF2_SHOWTOOLBAR; + + for (int i = 0; i < dat->childrenCount; i++) { + MessageWindowTabData * mwtd = GetChildFromTab(dat->hwndTabs, i); + SendMessage(mwtd->hwnd, DM_SWITCHTOOLBAR, 0, 0); + } + + SendMessage(hwndDlg, WM_SIZE, 0, 0); + break; + + case DM_SWITCHTITLEBAR: + dat->flags2 ^= SMF2_SHOWTITLEBAR; + ws = GetWindowLongPtr(hwndDlg, GWL_STYLE) & ~(WS_CAPTION); + if (dat->flags2 & SMF2_SHOWTITLEBAR) + ws |= WS_CAPTION; + + SetWindowLongPtr(hwndDlg, GWL_STYLE, ws); + RECT rc; + GetWindowRect(hwndDlg, &rc); + SetWindowPos(hwndDlg, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING); + RedrawWindow(hwndDlg, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); + break; + + case DM_CASCADENEWWINDOW: + if ((HWND)wParam != hwndDlg) { + RECT rcThis, rcNew; + GetWindowRect(hwndDlg, &rcThis); + GetWindowRect((HWND)wParam, &rcNew); + if (abs(rcThis.left - rcNew.left) < 3 && abs(rcThis.top - rcNew.top) < 3) { + int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME); + SetWindowPos((HWND)wParam, 0, rcNew.left + offset, rcNew.top + offset, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + *(int *)lParam = 1; + } + } + break; + } + return FALSE; +} + +static void DrawTab(ParentWindowData *dat, HWND hwnd, WPARAM, LPARAM lParam) +{ + LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam; + int iTabIndex = lpDIS->itemID; + if (iTabIndex < 0) + return; + + TabCtrlData *tcdat = (TabCtrlData*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + HANDLE hTheme = NULL; + int tstate = 0; + wchar_t szLabel[1024]; + TCITEM tci; + tci.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_STATE; + tci.pszText = szLabel; + tci.cchTextMax = _countof(szLabel); + tci.dwStateMask = TCIS_HIGHLIGHTED; + if (TabCtrl_GetItem(hwnd, iTabIndex, &tci)) { + IMAGEINFO info; + RECT rIcon = lpDIS->rcItem; + RECT rect = lpDIS->rcItem; + RECT rectTab = lpDIS->rcItem; + int bSelected = lpDIS->itemState & ODS_SELECTED; + int atTop = (GetWindowLongPtr(hwnd, GWL_STYLE) & TCS_BOTTOM) == 0; + UINT dwFormat; + if (!IsAppThemed()) + FillRect(lpDIS->hDC, &rect, GetSysColorBrush(COLOR_BTNFACE)); + else { + if (lpDIS->itemState & ODS_SELECTED) + tstate = TTIS_SELECTED; + else if (lpDIS->itemState & ODS_FOCUS) + tstate = TTIS_FOCUSED; + else if (lpDIS->itemState & ODS_HOTLIGHT) + tstate = TTIS_HOT; + else + tstate = TTIS_NORMAL; + + if (!bSelected) + InflateRect(&rectTab, 1, 1); + + hTheme = OpenThemeData(hwnd, L"TAB"); + if (IsThemeBackgroundPartiallyTransparent(hTheme, TABP_TABITEM, tstate)) + DrawThemeParentBackground(hwnd, lpDIS->hDC, &rectTab); + DrawThemeBackground(hTheme, lpDIS->hDC, TABP_TABITEM, tstate, &rectTab, NULL); + } + if (atTop) { + dwFormat = DT_SINGLELINE | DT_TOP | DT_CENTER | DT_NOPREFIX | DT_NOCLIP; + rIcon.top = rect.top + GetSystemMetrics(SM_CYEDGE); + if (tci.iImage >= 0) { + rIcon.left = rect.left + GetSystemMetrics(SM_CXEDGE) + (bSelected ? 6 : 2); + ImageList_GetImageInfo(g_dat.hTabIconList, tci.iImage, &info); + ImageList_DrawEx(g_dat.hTabIconList, tci.iImage, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); + rect.left = rIcon.left + (info.rcImage.right - info.rcImage.left); + } + if (dat->flags2 & SMF2_TABCLOSEBUTTON) { + ImageList_GetImageInfo(g_dat.hButtonIconList, 0, &info); + rIcon.left = rect.right - GetSystemMetrics(SM_CXEDGE) - (bSelected ? 6 : 2) - (info.rcImage.right - info.rcImage.left); + ImageList_DrawEx(g_dat.hButtonIconList, 0, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); + rect.right = rIcon.left - 1; + } + rect.top += GetSystemMetrics(SM_CYEDGE) + 2; + } + else { + dwFormat = DT_SINGLELINE | DT_BOTTOM | DT_CENTER | DT_NOPREFIX | DT_NOCLIP; + rIcon.left = rect.left + GetSystemMetrics(SM_CXEDGE) + (bSelected ? 6 : 2); + if (tci.iImage >= 0) { + ImageList_GetImageInfo(g_dat.hTabIconList, tci.iImage, &info); + rIcon.top = rect.bottom - (info.rcImage.bottom - info.rcImage.top) - 1; + ImageList_DrawEx(g_dat.hTabIconList, tci.iImage, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); + rect.left = rIcon.left + (info.rcImage.right - info.rcImage.left); + } + if (dat->flags2 & SMF2_TABCLOSEBUTTON) { + ImageList_GetImageInfo(g_dat.hButtonIconList, 0, &info); + rIcon.top = rect.bottom - (info.rcImage.bottom - info.rcImage.top) - 2; + rIcon.left = rect.right - GetSystemMetrics(SM_CXEDGE) - (bSelected ? 6 : 2) - (info.rcImage.right - info.rcImage.left); + ImageList_DrawEx(g_dat.hButtonIconList, 0, lpDIS->hDC, rIcon.left, rIcon.top, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); + rect.right = rIcon.left - 1; + } + rect.bottom -= GetSystemMetrics(SM_CYEDGE) + 2; + } + + if (hTheme) + DrawThemeText(hTheme, lpDIS->hDC, TABP_TABITEM, tstate, szLabel, -1, dwFormat, 0, &rect); + else + DrawText(lpDIS->hDC, szLabel, -1, &rect, dwFormat); + + if (tcdat->bDragged && iTabIndex == tcdat->destTab && iTabIndex != tcdat->srcTab) { + RECT hlRect = lpDIS->rcItem; + if (bSelected) { + hlRect.bottom -= GetSystemMetrics(SM_CYEDGE); + hlRect.top += GetSystemMetrics(SM_CYEDGE); + hlRect.left += GetSystemMetrics(SM_CXEDGE); + hlRect.right -= GetSystemMetrics(SM_CXEDGE); + } + else { + if (atTop) { + hlRect.top += GetSystemMetrics(SM_CYEDGE); + hlRect.bottom += GetSystemMetrics(SM_CYEDGE); + } + else { + hlRect.top -= GetSystemMetrics(SM_CYEDGE); + hlRect.bottom -= GetSystemMetrics(SM_CYEDGE); + } + } + FrameRect(lpDIS->hDC, &hlRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + hlRect.left++; + hlRect.top++; + hlRect.right--; + hlRect.bottom--; + FrameRect(lpDIS->hDC, &hlRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + } + if (hTheme) + CloseThemeData(hTheme); + } +} + +HWND GetParentWindow(MCONTACT hContact, BOOL bChat) +{ + NewMessageWindowLParam newData = { 0 }; + newData.hContact = hContact; + newData.isChat = bChat; + if (g_dat.flags2 & SMF2_USETABS) { + if (!bChat || !(g_dat.flags2 & SMF2_SEPARATECHATSCONTAINERS)) { + if (g_dat.lastParent != NULL) { + int tabsNum = (int)SendMessage(g_dat.lastParent->hwnd, CM_GETCHILDCOUNT, 0, 0); + if (!(g_dat.flags2 & SMF2_LIMITTABS) || tabsNum < g_dat.limitTabsNum) + return g_dat.lastParent->hwnd; + } + } + else { + if (g_dat.lastChatParent != NULL) { + int tabsNum = (int)SendMessage(g_dat.lastChatParent->hwnd, CM_GETCHILDCOUNT, 0, 0); + if (!(g_dat.flags2 & SMF2_LIMITCHATSTABS) || tabsNum < g_dat.limitChatsTabsNum) { + return g_dat.lastChatParent->hwnd; + } + } + } + } + if (!(g_dat.flags2 & SMF2_SEPARATECHATSCONTAINERS)) + newData.isChat = FALSE; + + return CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGWIN), NULL, DlgProcParentWindow, (LPARAM)&newData); +} -- cgit v1.2.3